Re:Re: Question about "Make sched entity usage tracking scale-invariant"

2015-05-26 Thread Chao Xie

At 2015-05-26 19:05:36, "Morten Rasmussen"  wrote:
>Hi,
>
>[Adding maintainers and others to cc]
>
>On Mon, May 25, 2015 at 02:19:43AM +0100, Chao Xie wrote:
>> hi
>> I saw the patch “sched: Make sched entity usage tracking
>> scale-invariant” that will make the usage to be freq scaled.
>> So if delta period that the calculation of usage based on cross a
>> frequency change, so how can you make sure the usage calculation is
>> correct?
>> The delta period may last hundreds of microseconds, and frequency
>> change window may be 10-20 microseconds, so many frequency change can
>> happen during the delta period.
>> It seems the patch does not consider about it, and it just pick up the
>> current one.
>> So how can you resolve this issue?
>
>Right. We don't know how many times the frequency may have changed since
>last time we updated the entity usage tracking for the particular
>entity. All we do is to call arch_scale_freq_capacity() and use that
>scaling factor to compensate for whatever changes might have taken
>place.
>
>The easiest implementation of arch_scale_freq_capacity() for most
>architectures is to just return a scaling factor computed based on the
>current frequency and ignoring when exactly the change happened and
>ignoring if multiple changes happened. Depending on how often the
>frequency might change this might be an acceptable approximation. While
>the task is running the sched tick will update the entity usage tracking
>(every 10ms by default on most ARM systems), hence we shouldn't be more
>than a tick off in term of when the frequency change is accounted for.
>Under normal circumstances the delta period should therefore be <10ms
>and generally shorter than that if you have more than one task runnable
>on the cpu or the task(s) are not always-running. It is not perfect but
>it is a lot better than the utilization tracking currently used by
>cpufreq governors and better than the scheduler being completely unaware
>of frequency scaling.
>
>For systems with very frequent frequency changes, i.e. fast hardware and
>an aggressive governor leading to multiple changes in less than 10ms,
>the solution above might not be sufficient. In that case, I think a
>better solution might be to track the average frequency using hardware
>counters or whatever tracking metrics the system might have to let
>arch_scale_freq_capacity() return the average performance delivered over
>the most recent period of time. AFAIK, x86 already has performance
>counters (APERF/MPERF) that could be used for this purpose. The delta
>period for each entity tracking update isn't fixed, but it might
>sufficient to just average over some fixed period of time. Accurate
>tracking would require some time-stamp information to be stored in each
>sched_entity for the true average to be computed for the delta period.
>That quickly becomes rather messy but not impossible. I did look at it
>briefly a while back, but decided not to go down that route until we
>know that using current frequency or some fixed period average isn't
>going to be sufficient. Usage or utilization is and average of something
>that might be constantly changing anyways, so it never going to be very
>accurate anyway. If it does turn out that we can't get the overall
>picture right, we will need to improve it.
>
>Updating the entity tracking for each frequency change adds to much
>overhead I think and seems unnecessary if we do with an average scaling
>factor.
>
>I hope that answers your question. Have you observed any problems with
>the usage tracking?
>

Thanks for the explanation.

I agree that the "delta" is less than 10ms at most situation, but i think at 
least one period
need to be considered.
If the frequency change happens just a little, for example, 10us before the 
task start to
calculate its utilization which may have a delta of 10ms. The almost whole 
delta will be calculated
based on new frequency, not the old one. The frequency change can be from the 
lowest to highest,
so for this time the delta calculation has big deviation, and this situation is 
not rare.

>Thanks,
>Morten


Question about "Make sched entity usage tracking scale-invariant"

2015-05-24 Thread Chao Xie
hi
I saw the patch “sched: Make sched entity usage tracking scale-invariant” that 
will make the usage to be freq scaled.
So if delta period that the calculation of usage based on cross a frequency 
change, so how can you make sure the usage calculation is correct?
The delta period may last hundreds of microseconds, and frequency change window 
may be 10-20 microseconds, so many frequency change can happen during the delta 
period.
It seems the patch does not consider about it, and it just pick up the current 
one.
So how can you resolve this issue?

Thanks.N嫥叉靣笡y氊b瞂千v豝�)藓{.n�+壏{睉赙zXФ洝塄}财爖�&j:+v墾�珣赙zZ+€�+zf"穐殘啳嗃iz�畐ア�?櫒璀�&�)撷f旟^j谦y呩@A玜囤
0鹅h�鍜i

[PATCH RESEND 3/3] clk: mmp: add timer clock for pxa168/mmp2/pxa910

2015-04-29 Thread Chao Xie
From: Chao Xie 

Timer has external fast clock, and it is a mux clock.
Add the timer clock type for timer driver.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-of-mmp2.c  |  6 ++
 drivers/clk/mmp/clk-of-pxa168.c|  7 +++
 drivers/clk/mmp/clk-of-pxa910.c| 11 +++
 include/dt-bindings/clock/marvell,mmp2.h   |  1 +
 include/dt-bindings/clock/marvell,pxa168.h |  2 ++
 include/dt-bindings/clock/marvell,pxa910.h |  3 +++
 6 files changed, 30 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index b7e0b89..251533d 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -30,6 +30,7 @@
 #define APBC_TWSI4 0x7c
 #define APBC_TWSI5 0x80
 #define APBC_KPC   0x18
+#define APBC_TIMER 0x24
 #define APBC_UART0 0x2c
 #define APBC_UART1 0x30
 #define APBC_UART2 0x34
@@ -132,6 +133,9 @@ static DEFINE_SPINLOCK(ssp2_lock);
 static DEFINE_SPINLOCK(ssp3_lock);
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", 
"pll1_16"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", 
"vctcxo"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -143,6 +147,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
+   {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), 
CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -168,6 +173,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 
0x7, 0x3, 0x0, 0, &ssp1_lock},
{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 
0x7, 0x3, 0x0, 0, &ssp2_lock},
{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 
0x7, 0x3, 0x0, 0, &ssp3_lock},
+   {MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, 
APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 01a650e..64eaf41 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -32,6 +32,7 @@
 #define APBC_PWM1  0x10
 #define APBC_PWM2  0x14
 #define APBC_PWM3  0x18
+#define APBC_TIMER 0x34
 #define APBC_SSP0  0x81c
 #define APBC_SSP1  0x820
 #define APBC_SSP2  0x84c
@@ -71,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] 
= {
{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -120,6 +122,9 @@ static DEFINE_SPINLOCK(ssp3_lock);
 static DEFINE_SPINLOCK(ssp4_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", 
"pll1_12"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", 
"pll1_192"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -131,6 +136,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
+   {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), 
CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 

[PATCH RESEND 1/3] clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168

2015-04-29 Thread Chao Xie
From: Chao Xie 

USB will drive clock from USB_PLL.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-of-pxa168.c| 1 +
 drivers/clk/mmp/clk-of-pxa910.c| 1 +
 include/dt-bindings/clock/marvell,pxa168.h | 1 +
 include/dt-bindings/clock/marvell,pxa910.h | 1 +
 4 files changed, 4 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 5b1810d..01a650e 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -58,6 +58,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+   {PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 5e3c80d..cca98ef 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -57,6 +57,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+   {PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/include/dt-bindings/clock/marvell,pxa168.h 
b/include/dt-bindings/clock/marvell,pxa168.h
index 79630b9..84ce5de 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -19,6 +19,7 @@
 #define PXA168_CLK_PLL1_2_1_5  19
 #define PXA168_CLK_PLL1_3_16   20
 #define PXA168_CLK_UART_PLL27
+#define PXA168_CLK_USB_PLL 28
 
 /* apb periphrals */
 #define PXA168_CLK_TWSI0   60
diff --git a/include/dt-bindings/clock/marvell,pxa910.h 
b/include/dt-bindings/clock/marvell,pxa910.h
index 719cffb..bea08b6 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -19,6 +19,7 @@
 #define PXA910_CLK_PLL1_2_1_5  19
 #define PXA910_CLK_PLL1_3_16   20
 #define PXA910_CLK_UART_PLL27
+#define PXA910_CLK_USB_PLL 28
 
 /* apb periphrals */
 #define PXA910_CLK_TWSI0   60
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND 2/3] clk: mmp: Fix the wrong factor table for uart PLL

2015-04-29 Thread Chao Xie
From: Chao Xie 

The suggested value in the mmp2 manual is wrong.
There are only 13 bits for numerator, but some suggested
value has 14 bits.
Fix the factor tabled and remove the unused items.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-mmp2.c| 4 +---
 drivers/clk/mmp/clk-of-mmp2.c | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 5c90a42..09d2832 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -63,10 +63,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-   {.num = 14634, .den = 2165},/*14.745MHZ */
+   {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
-   {.num = 9679, .den = 5728}, /*58.9824MHZ */
-   {.num = 15850, .den = 9451},/*59.429MHZ */
 };
 
 static const char *uart_parent[] = {"uart_pll", "vctcxo"};
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 2cbc2b4..b7e0b89 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -98,10 +98,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-   {.num = 14634, .den = 2165},/*14.745MHZ */
+   {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
-   {.num = 9679, .den = 5728}, /*58.9824MHZ */
-   {.num = 15850, .den = 9451},/*59.429MHZ */
 };
 
 static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH RESEND 0/3] clk: mmp: fix and add new clock

2015-04-29 Thread Chao Xie
From: Chao Xie 

There are three patches
First two are fix patches.
The last one will add the timer clock for pxa168/mmp2/pxa910.

The timer driver will make use of the timer clock.

Chao Xie (3):
  clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168
  clk: mmp: Fix the wrong factor table for uart PLL
  clk: mmp: add timer clock for pxa168/mmp2/pxa910

 drivers/clk/mmp/clk-mmp2.c |  4 +---
 drivers/clk/mmp/clk-of-mmp2.c  | 10 +++---
 drivers/clk/mmp/clk-of-pxa168.c|  8 
 drivers/clk/mmp/clk-of-pxa910.c| 12 
 include/dt-bindings/clock/marvell,mmp2.h   |  1 +
 include/dt-bindings/clock/marvell,pxa168.h |  3 +++
 include/dt-bindings/clock/marvell,pxa910.h |  4 
 7 files changed, 36 insertions(+), 6 deletions(-)

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re:[PATCH 0/3] clk: mmp: fix and add new clock

2015-04-22 Thread Chao Xie

hi, Mike


These patches are bug fix and enhancement patches for mmp clock. 


If it does not have any problem, can you help to merge it?


Thanks.



At 2015-04-07 14:17:01, "Chao Xie"  wrote:
>From: Chao Xie 
>
>There are three patches
>First two are fix patches.
>The last one will add the timer clock for pxa168/mmp2/pxa910.
>
>The timer driver will make use of the timer clock.
>
>Chao Xie (3):
>  clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168
>  clk: mmp: Fix the wrong factor table for uart PLL
>  clk: mmp: add timer clock for pxa168/mmp2/pxa910
>
> drivers/clk/mmp/clk-mmp2.c |  4 +---
> drivers/clk/mmp/clk-of-mmp2.c  | 10 +++---
> drivers/clk/mmp/clk-of-pxa168.c|  8 
> drivers/clk/mmp/clk-of-pxa910.c| 12 
> include/dt-bindings/clock/marvell,mmp2.h   |  1 +
> include/dt-bindings/clock/marvell,pxa168.h |  3 +++
> include/dt-bindings/clock/marvell,pxa910.h |  4 
> 7 files changed, 36 insertions(+), 6 deletions(-)
>
>-- 
>1.8.3.2
>
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�&j:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a���
0��h���i

[PATCH 1/3] clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168

2015-04-06 Thread Chao Xie
From: Chao Xie 

USB will drive clock from USB_PLL.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-of-pxa168.c| 1 +
 drivers/clk/mmp/clk-of-pxa910.c| 1 +
 include/dt-bindings/clock/marvell,pxa168.h | 1 +
 include/dt-bindings/clock/marvell,pxa910.h | 1 +
 4 files changed, 4 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 5b1810d..01a650e 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -58,6 +58,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
{PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+   {PXA168_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
index 5e3c80d..cca98ef 100644
--- a/drivers/clk/mmp/clk-of-pxa910.c
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -57,6 +57,7 @@ static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
{PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+   {PXA910_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
 };
 
 static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
diff --git a/include/dt-bindings/clock/marvell,pxa168.h 
b/include/dt-bindings/clock/marvell,pxa168.h
index 79630b9..84ce5de 100644
--- a/include/dt-bindings/clock/marvell,pxa168.h
+++ b/include/dt-bindings/clock/marvell,pxa168.h
@@ -19,6 +19,7 @@
 #define PXA168_CLK_PLL1_2_1_5  19
 #define PXA168_CLK_PLL1_3_16   20
 #define PXA168_CLK_UART_PLL27
+#define PXA168_CLK_USB_PLL 28
 
 /* apb periphrals */
 #define PXA168_CLK_TWSI0   60
diff --git a/include/dt-bindings/clock/marvell,pxa910.h 
b/include/dt-bindings/clock/marvell,pxa910.h
index 719cffb..bea08b6 100644
--- a/include/dt-bindings/clock/marvell,pxa910.h
+++ b/include/dt-bindings/clock/marvell,pxa910.h
@@ -19,6 +19,7 @@
 #define PXA910_CLK_PLL1_2_1_5  19
 #define PXA910_CLK_PLL1_3_16   20
 #define PXA910_CLK_UART_PLL27
+#define PXA910_CLK_USB_PLL 28
 
 /* apb periphrals */
 #define PXA910_CLK_TWSI0   60
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] clk: mmp: add timer clock for pxa168/mmp2/pxa910

2015-04-06 Thread Chao Xie
From: Chao Xie 

Timer has external fast clock, and it is a mux clock.
Add the timer clock type for timer driver.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-of-mmp2.c  |  6 ++
 drivers/clk/mmp/clk-of-pxa168.c|  7 +++
 drivers/clk/mmp/clk-of-pxa910.c| 11 +++
 include/dt-bindings/clock/marvell,mmp2.h   |  1 +
 include/dt-bindings/clock/marvell,pxa168.h |  2 ++
 include/dt-bindings/clock/marvell,pxa910.h |  3 +++
 6 files changed, 30 insertions(+)

diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index b7e0b89..251533d 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -30,6 +30,7 @@
 #define APBC_TWSI4 0x7c
 #define APBC_TWSI5 0x80
 #define APBC_KPC   0x18
+#define APBC_TIMER 0x24
 #define APBC_UART0 0x2c
 #define APBC_UART1 0x30
 #define APBC_UART2 0x34
@@ -132,6 +133,9 @@ static DEFINE_SPINLOCK(ssp2_lock);
 static DEFINE_SPINLOCK(ssp3_lock);
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", 
"pll1_16"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", 
"vctcxo"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -143,6 +147,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp1_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP1, 4, 3, 0, &ssp1_lock},
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
+   {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), 
CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 
 static struct mmp_param_gate_clk apbc_gate_clks[] = {
@@ -168,6 +173,7 @@ static struct mmp_param_gate_clk apbc_gate_clks[] = {
{MMP2_CLK_SSP1, "ssp1_clk", "ssp1_mux", CLK_SET_RATE_PARENT, APBC_SSP1, 
0x7, 0x3, 0x0, 0, &ssp1_lock},
{MMP2_CLK_SSP2, "ssp2_clk", "ssp2_mux", CLK_SET_RATE_PARENT, APBC_SSP2, 
0x7, 0x3, 0x0, 0, &ssp2_lock},
{MMP2_CLK_SSP3, "ssp3_clk", "ssp3_mux", CLK_SET_RATE_PARENT, APBC_SSP3, 
0x7, 0x3, 0x0, 0, &ssp3_lock},
+   {MMP2_CLK_TIMER, "timer_clk", "timer_mux", CLK_SET_RATE_PARENT, 
APBC_TIMER, 0x7, 0x3, 0x0, 0, &timer_lock},
 };
 
 static void mmp2_apb_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
index 01a650e..64eaf41 100644
--- a/drivers/clk/mmp/clk-of-pxa168.c
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -32,6 +32,7 @@
 #define APBC_PWM1  0x10
 #define APBC_PWM2  0x14
 #define APBC_PWM3  0x18
+#define APBC_TIMER 0x34
 #define APBC_SSP0  0x81c
 #define APBC_SSP1  0x820
 #define APBC_SSP2  0x84c
@@ -71,6 +72,7 @@ static struct mmp_param_fixed_factor_clk fixed_factor_clks[] 
= {
{PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
{PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
{PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA168_CLK_PLL1_192, "pll1_192", "pll1_96", 1, 2, 0},
{PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
{PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
{PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
@@ -120,6 +122,9 @@ static DEFINE_SPINLOCK(ssp3_lock);
 static DEFINE_SPINLOCK(ssp4_lock);
 static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", 
"pll1_12"};
 
+static DEFINE_SPINLOCK(timer_lock);
+static const char *timer_parent_names[] = {"pll1_48", "clk32", "pll1_96", 
"pll1_192"};
+
 static DEFINE_SPINLOCK(reset_lock);
 
 static struct mmp_param_mux_clk apbc_mux_clks[] = {
@@ -131,6 +136,7 @@ static struct mmp_param_mux_clk apbc_mux_clks[] = {
{0, "ssp2_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP2, 4, 3, 0, &ssp2_lock},
{0, "ssp3_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP3, 4, 3, 0, &ssp3_lock},
{0, "ssp4_mux", ssp_parent_names, ARRAY_SIZE(ssp_parent_names), 
CLK_SET_RATE_PARENT, APBC_SSP4, 4, 3, 0, &ssp4_lock},
+   {0, "timer_mux", timer_parent_names, ARRAY_SIZE(timer_parent_names), 
CLK_SET_RATE_PARENT, APBC_TIMER, 4, 3, 0, &timer_lock},
 };
 

[PATCH 2/3] clk: mmp: Fix the wrong factor table for uart PLL

2015-04-06 Thread Chao Xie
From: Chao Xie 

The suggested value in the mmp2 manual is wrong.
There are only 13 bits for numerator, but some suggested
value has 14 bits.
Fix the factor tabled and remove the unused items.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-mmp2.c| 4 +---
 drivers/clk/mmp/clk-of-mmp2.c | 4 +---
 2 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 5c90a42..09d2832 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -63,10 +63,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-   {.num = 14634, .den = 2165},/*14.745MHZ */
+   {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
-   {.num = 9679, .den = 5728}, /*58.9824MHZ */
-   {.num = 15850, .den = 9451},/*59.429MHZ */
 };
 
 static const char *uart_parent[] = {"uart_pll", "vctcxo"};
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
index 2cbc2b4..b7e0b89 100644
--- a/drivers/clk/mmp/clk-of-mmp2.c
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -98,10 +98,8 @@ static struct mmp_clk_factor_masks uart_factor_masks = {
 };
 
 static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
-   {.num = 14634, .den = 2165},/*14.745MHZ */
+   {.num = 8125, .den = 1536}, /*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
-   {.num = 9679, .den = 5728}, /*58.9824MHZ */
-   {.num = 15850, .den = 9451},/*59.429MHZ */
 };
 
 static void mmp2_pll_init(struct mmp2_clk_unit *pxa_unit)
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/3] clk: mmp: fix and add new clock

2015-04-06 Thread Chao Xie
From: Chao Xie 

There are three patches
First two are fix patches.
The last one will add the timer clock for pxa168/mmp2/pxa910.

The timer driver will make use of the timer clock.

Chao Xie (3):
  clk: mmp: add fixed clock UBS_PLL for pxa910/pxa168
  clk: mmp: Fix the wrong factor table for uart PLL
  clk: mmp: add timer clock for pxa168/mmp2/pxa910

 drivers/clk/mmp/clk-mmp2.c |  4 +---
 drivers/clk/mmp/clk-of-mmp2.c  | 10 +++---
 drivers/clk/mmp/clk-of-pxa168.c|  8 
 drivers/clk/mmp/clk-of-pxa910.c| 12 
 include/dt-bindings/clock/marvell,mmp2.h   |  1 +
 include/dt-bindings/clock/marvell,pxa168.h |  3 +++
 include/dt-bindings/clock/marvell,pxa910.h |  4 
 7 files changed, 36 insertions(+), 6 deletions(-)

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re:Re: [PATCH V2] gpio: mmp: add GPIO driver for Marvell MMP series

2015-03-17 Thread Chao Xie


At 2015-03-17 18:25:24, "Linus Walleij"  wrote:
>On Fri, Mar 6, 2015 at 3:04 AM, Chao Xie  wrote:
>
>> Signed-off-by: Chao Xie 
>
>First can some of the MMP people comment on this driver please?
>(Eric/Haojian)
>
>So this driver duplicates drivers/gpio/gpio-pxa.c in some sense but
>is nicer and cleaner and thus an incentive for me to merge it.
>At the same time I don't want two drivers for essentially the same
>hardware and in that way I would prefer to clean up the PXA driver.
>
>But I don't know how close the PXA and MMP drivers really are.
>
>Will it also cover MMP2 that is currently using by the PXA driver?
>
>Is it really complicated to migrate gpio-pxa to GPIOLIB_IRQCHIP?
>
>I guess you should also delete the compatible string and
>compatibility code in drivers/gpio/gpio-pxa.c (as a separate patch
>in this series) and merge this along with some defconfig
>changes that activates this by default for the MMP machines?

>


I will ask Haojian to comment at it when send out V3 patch.
pxa and mmp are two different series.
First pxa is Intel's product, and after Intel sell its xscale to marvell, the 
SOC series become mmp.
The SOC design has many differences.
now mmp gpio has some registers kept in order to use the old pxa driver, but 
silicon designer
warned us that it is better to use the new register interfaces.
The major differences are:
For all the edge detecting setting/clearing, level setting/clearing, direction 
setting/clearing, mmp has
separated registers

>> +config GPIO_MMP
>> +   bool "MMP GPIO support"
>> +   depends on ARCH_MMP
>> +   select GPIOLIB_IRQCHIP
>
>NICE!
>
>> +struct mmp_gpio_bank {
>> +   void __iomem *reg_bank;
>> +   u32 irq_mask;
>> +   u32 irq_rising_edge;
>> +   u32 irq_falling_edge;
>
>I can't see why you're keeping all these settings of the edges and mask
>in these variables. Why can't you just keep the state in the hardware
>registers?

>
When other driver request gpio, it will set whether it is rising edge detect or
falling edge detect or both.
We need record it.
So when user mask/unmask the interrupt, we know whether we need clear/set
rising edge detect/falling edge detect or both.

>> +};
>> +
>> +struct mmp_gpio_chip {
>> +   struct gpio_chip chip;
>> +   void __iomem *reg_base;
>> +   int irq;
>
>Do you need to keep irq around if you use devm_* to request the
>IRQ?

>


Yes, it is right. I will remove it.

>> +   unsigned int ngpio;
>
>This is already stored in struct gpio_chip, why
>store it a second time in this struct?
>
>> +   unsigned int nbank;
>> +   struct mmp_gpio_bank *banks;
>
>To repeat an eternal story: why do you have to register several
>banks under the same gpio_chip? I guess it's because they share
>a single IRQ line, but wanna make sure

>
Yes. they share same interrupt line.

There are the following reasons
1. There is only one IRQ for the whole GPIO, even there are 3 or more banks.
2. The registers are not formatted into group. They are interleaved.
 For example, there are three banks, So for the registers order are
 LEVEL_STATUS_BANK0, LEVEL_STASTUS_BANK1, LEVEL_STATUS_BANK2
 DIRECTION_STATUS_BANK0, DIRECTION_STATUS_BANK1, DIRECTION_STATUS_BANK2
>> +};>> +
>> +static int mmp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
>> +{
>> +   struct mmp_gpio_chip *mmp_chip =
>> +   container_of(chip, struct mmp_gpio_chip, chip);
>> +   struct mmp_gpio_bank *bank =
>> +   &mmp_chip->banks[mmp_gpio_to_bank_idx(offset)];
>
>Rewrite this:
>
>> +   u32 bit = (1 << mmp_gpio_to_bank_offset(offset));
>> +
>> +   writel(bit, bank->reg_bank + GCDR);
>
>Like this:
>
>#include 
>
>writel(BIT(mmp_gpio_to_bank_offset(offset)), bank->reg_bank + GCDR);

>
I will do it.>
>> +static int mmp_gpio_direction_output(struct gpio_chip *chip,
>> +unsigned offset, int value)
>> +{
>
>Use the same pattern with BIT() as described above.

>
I will do it.>> +static int mmp_gpio_get(struct gpio_chip *chip, unsigned 
offset)
>> +{
>> +
>> +   return !!(gplr & bit);
>
>Use the same pattern with BIT() as described above.

>


I will do it.
I will use BIT() for all below comments you suggested. Thanks.>> +static struct 
irq_chip mmp_muxed_gpio_chip = {
>> +   .name   = "mmp-gpio-irqchip",
>> +   .irq_mask   = mmp_mask_muxed_gpio,
>> +   .irq_unmask = mmp_unmask_

[PATCH V2] gpio: mmp: add GPIO driver for Marvell MMP series

2015-03-05 Thread Chao Xie
From: Chao Xie 

For some old PXA series, they used PXA GPIO driver.
The IP of GPIO changes since PXA988 which is Marvell MMP
series.
It will use new way to control the GPIO level, direction
and edge status.

Signed-off-by: Chao Xie 
---
 drivers/gpio/Kconfig|  10 ++
 drivers/gpio/Makefile   |   1 +
 drivers/gpio/gpio-mmp.c | 364 
 3 files changed, 375 insertions(+)
 create mode 100644 drivers/gpio/gpio-mmp.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 633ec21..6dce470 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -197,6 +197,16 @@ config GPIO_F7188X
  To compile this driver as a module, choose M here: the module will
  be called f7188x-gpio.
 
+config GPIO_MMP
+   bool "MMP GPIO support"
+   depends on ARCH_MMP
+   select GPIOLIB_IRQCHIP
+   help
+ Say yes here to support the MMP GPIO device at
+ PXA1088/PXA1908/PXA1928. Comparing with PXA GPIO device, the IP of
+ MMP GPIO changes a lot. It will use new way to control the GPIO
+ level, direction and edge status.
+
 config GPIO_MOXART
bool "MOXART GPIO support"
depends on ARCH_MOXART
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 81755f1..60a7cf5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)  += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)   += gpio-mm-lantiq.o
+obj-$(CONFIG_GPIO_MMP) += gpio-mmp.o
 obj-$(CONFIG_GPIO_MOXART)  += gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
diff --git a/drivers/gpio/gpio-mmp.c b/drivers/gpio/gpio-mmp.c
new file mode 100644
index 000..4202654
--- /dev/null
+++ b/drivers/gpio/gpio-mmp.c
@@ -0,0 +1,364 @@
+/*
+ *  Copyright (C) 2015 Marvell International Ltd.
+ *
+ *  Generic MMP GPIO handling
+ *
+ * Chao Xie 
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define GPLR   0x0
+#define GPDR   0xc
+#define GPSR   0x18
+#define GPCR   0x24
+#define GRER   0x30
+#define GFER   0x3c
+#define GEDR   0x48
+#define GSDR   0x54
+#define GCDR   0x60
+#define GSRER  0x6c
+#define GCRER  0x78
+#define GSFER  0x84
+#define GCFER  0x90
+#define GAPMASK0x9c
+#define GCPMASK0xa8
+
+/* Bank will have 2^n GPIOes, and for mmp-gpio n = 5 */
+#define BANK_GPIO_ORDER5
+#define BANK_GPIO_NUMBER   (1 << BANK_GPIO_ORDER)
+#define BANK_GPIO_MASK (BANK_GPIO_NUMBER - 1)
+
+#define mmp_gpio_to_bank_idx(gpio) ((gpio) >> BANK_GPIO_ORDER)
+#define mmp_gpio_to_bank_offset(gpio)  ((gpio) & BANK_GPIO_MASK)
+#define mmp_bank_to_gpio(idx, offset)  (((idx) << BANK_GPIO_ORDER) \
+   | ((offset) & BANK_GPIO_MASK))
+
+struct mmp_gpio_bank {
+   void __iomem *reg_bank;
+   u32 irq_mask;
+   u32 irq_rising_edge;
+   u32 irq_falling_edge;
+};
+
+struct mmp_gpio_chip {
+   struct gpio_chip chip;
+   void __iomem *reg_base;
+   int irq;
+   unsigned int ngpio;
+   unsigned int nbank;
+   struct mmp_gpio_bank *banks;
+};
+
+static int mmp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+   struct mmp_gpio_bank *bank =
+   &mmp_chip->banks[mmp_gpio_to_bank_idx(offset)];
+   u32 bit = (1 << mmp_gpio_to_bank_offset(offset));
+
+   writel(bit, bank->reg_bank + GCDR);
+
+   return 0;
+}
+
+static int mmp_gpio_direction_output(struct gpio_chip *chip,
+unsigned offset, int value)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+   struct mmp_gpio_bank *bank =
+   &mmp_chip->banks[mmp_gpio_to_bank_idx(offset)];
+   u32 bit = (1 << mmp_gpio_to_bank_offset(offset));
+
+   /* Set value first. */
+   writel(bit, bank->reg_bank + (value ? GPSR : GPCR));
+
+   writel(bit, bank->reg_bank + GSDR);
+
+   return 0;
+}
+
+static int mmp_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+   struct mmp_gpio_bank *bank =
+   &mmp_chip->banks[mmp_gpio_to_

Re:Re: [PATCH] gpio: mmp: add GPIO driver for Marvell MMP series

2015-02-03 Thread Chao Xie

At 2015-02-03 21:21:43, "Linus Walleij"  wrote:
>On Wed, Jan 28, 2015 at 3:30 AM, Chao Xie  wrote:
>
>> From: Chao Xie 
>>
>> For some old PXA series, they used PXA GPIO driver.
>> The IP of GPIO changes since PXA988 which is Marvell MMP
>> series.
>> It will use new way to control the GPIO level, direction
>> and edge status.
>>
>> Signed-off-by: Chao Xie 
>
>(...)
>
>> +config GPIO_MMP
>> +   bool "MMP GPIO support"
>> +   depends on ARCH_MMP
>
>All new simple drivers with IRQ should
>
>select GPIOLIB_IRQCHIP
>

Thanks for review.

I will check GPIOLIB_IRQCHIP and make use of it.

>Since this looks like a basic MMIO driver I think
>you should also use:
>
>select GPIO_GENERIC
>

I think the gpio-mmp is not same as gpio-generic.
gpio-mmp need control the level/direction/rising edge detect enable/falling 
edge detect enable.
For each of them, there are three registers: status register,  setting register 
and clear register.
For example, for direction, if you configure it as output.
You need SET the bit in setting register.
If you want to configure it as input
You need SET the bit in clear register.
The bits will be cleared by hardware if the operation is completed by hardware.

It is same for level/rising edege detect enable/falling edge detect enable.

If you want to read the status of the pin. For example, the current level of 
the pin.
You CAN NOT read the setting/clear register. You need read the level status 
register.

>And set up simple getter/setter functions with a
>
>
>> +   help
>> + Say yes here to support the MMP GPIO device at 
>> PXA1088/PXA1908/PXA1928.
>> + Comparing with PXA GPIO device, the IP of MMP GPIO changes a lot.
>> +
>
>(...)
>
>> +++ b/drivers/gpio/gpio-mmp.c
>
>> +#include 
>> +#include 
>> +#include 
>
>You don't need this include with GPIOLIB_IRQCHIP
>

I will fix it.

>> +#include 
>> +#include 
>> +#include 
>
>#include 
>
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>
>get rid of these two includes in favor of using GPIOLIB_IRQCHIP
>

I will fix it.

>> +#include 
>
>Add:
>#include 
>
>And implement generic GPIO using bgpio_init()
>
>(...)

The reasons are listed above

>> +#define GPLR   0x0
>> +#define GPDR   0xc
>> +#define GPSR   0x18
>> +#define GPCR   0x24
>> +#define GRER   0x30
>> +#define GFER   0x3c
>> +#define GEDR   0x48
>> +#define GSDR   0x54
>> +#define GCDR   0x60
>> +#define GSRER  0x6c
>> +#define GCRER  0x78
>> +#define GSFER  0x84
>> +#define GCFER  0x90
>> +#define GAPMASK0x9c
>> +#define GCPMASK0xa8
>> +
>> +/* Bank will have 2^n GPIOes, and for mmp-gpio n = 5 */
>> +#define BANK_GPIO_ORDER5
>> +#define BANK_GPIO_NUMBER   (1 << BANK_GPIO_ORDER)
>> +#define BANK_GPIO_MASK (BANK_GPIO_NUMBER - 1)
>> +
>> +#define mmp_gpio_to_bank_idx(gpio) ((gpio) >> BANK_GPIO_ORDER)
>> +#define mmp_gpio_to_bank_offset(gpio)  ((gpio) & BANK_GPIO_MASK)
>> +#define mmp_bank_to_gpio(idx, offset)  (((idx) << BANK_GPIO_ORDER) \
>> +   | ((offset) & 
>> BANK_GPIO_MASK))
>> +
>
>This looks convoluted. Why not just register each bank as a separate
>device instead of trying to figure out bank index like this?
>

There are the following reasons
1. There is only one IRQ for the whole GPIO, even there are 3 or more banks.
2. The registers are not formatted into group. They are interleaved.
For example, there are three banks, So for the registers order are
LEVEL_STATUS_BANK0, LEVEL_STASTUS_BANK1, LEVEL_STATUS_BANK2
DIRECTION_STATUS_BANK0, DIRECTION_STATUS_BANK1, DIRECTION_STATUS_BANK2
3. each bank has 32 bits. Formatting them into one driver will make other 
driver easier.
For example, the MMC driver has GPIO detection for card. So it knows the 
GPIO is GPIO56.
In the device tree of MMC driver, you can simple add as
cd-gpios = <&gpio 56 X>
if you format them into different devices, the mmc driver owner need to 
know how much bits a bank is, and calculate out correct GPIOx and offset
cd-gpios = <&gpio1 24 X>

>> +struct mmp_gpio_bank {
>> +   void __iomem *reg_bank;
>> +   u32 irq_mask;
>> +   u32 irq_rising_edge;
>> +   u32 irq_falling_edge;
>> +};
>> +
>> +struct mmp_gpio_

Re: [PATCH 1/4] clocksource: mmp: add mmp timer driver

2015-02-02 Thread Chao Xie



>From: Mark Rutland [mailto:mark.rutl...@arm.com] 
>Sent: 2015年2月2日 18:35
>To: Chao Xie
>Cc: daniel.lezc...@linaro.org; t...@linutronix.de; haojian.zhu...@linaro.org; 
>linux-kernel@vger.kernel.org; devicet...@vger.kernel.org
>Subject: Re: [PATCH 1/4] clocksource: mmp: add mmp timer driver
>
>On Mon, Feb 02, 2015 at 08:31:36AM +, Chao Xie wrote:
>> From: Chao Xie 
>> 
>> MMP timer is attached to APB bus, It has the following limitation.
>> 1. When get count of timer counter, it need some delay
>>to get a stable count.
>> 2. When set match register, it need disable the counter
>>first, and enable it after set the match register.
>>The disabling need wait for 2 clock cycle to take
>>effect.
>> 
>> To improve above #1, shadow register for count is added.
>> To improve above #2, CRSR register is added for quick updating.
>> 
>> So there are three types of timer.
>> timer1: old timer.
>> timer2: old timer with shadow register.
>> timer3: old timer with shadow and CRSR register.
>> 
>> This timer driver will be used for many SOCes.
>> 1. pxa168, pxa910, pxa988 pxa1088 have only timer1.
>> 2. pxa1L88, pxa1U88 have timer1 and timer3.
>> 3. pxa1928 has timer 2.
>> 
>> The driver supports DT and non-DT initialization.
>> The driver supports UP/SMP SOCes and 64 bit core.
>> 
>> Signed-off-by: Chao Xie 
>> ---
>>  .../devicetree/bindings/arm/mrvl/timer.txt |  61 +-
>>  drivers/clocksource/Makefile   |   1 +
>>  drivers/clocksource/timer-mmp.c| 837 
>> +
>>  include/linux/mmp_timer.h  |  40 +
>>  4 files changed, 933 insertions(+), 6 deletions(-)  create mode 
>> 100644 drivers/clocksource/timer-mmp.c  create mode 100644 
>> include/linux/mmp_timer.h
>> 
>> diff --git a/Documentation/devicetree/bindings/arm/mrvl/timer.txt 
>> b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
>> index 9a6e251..b49cb3e 100644
>> --- a/Documentation/devicetree/bindings/arm/mrvl/timer.txt
>> +++ b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
>> @@ -1,13 +1,62 @@
>>  * Marvell MMP Timer controller
>> 
>> +Each timer have multiple counters, so the timer DT need include 
>> +counter's description.
>> +
>> +1. Timer
>> +
>>  Required properties:
>> -- compatible : Should be "mrvl,mmp-timer".
>> +- compatible : Should be "marvell,mmp-timer".
>>  - reg : Address and length of the register set of timer controller.
>> -- interrupts : Should be the interrupt number.
>> +- clocks : The first clock is the fequency of the apb bus that the 
>> +timer
>> +  attached to. The second clock is the fast clock frequency of the timer.
>> +  This frequency and fast clock are used to calculated delay
>> +  loops for clock operations.
>
>It might be a good idea to use clock-names for "apb" and "fast" and use them 
>in the driver.

>


Yes. I will fix it.

>> +
>> +Optional properties:
>> +- marvell,timer-has-crsr : This timer has CRSR register.
>> +- marvell,timer-has-shadow : This timer has shadow register.
>> +
>> +2. Counter
>
>The coutner nodes appear to be sub-nodes of the timer. That should be stated 
>explicitly.

>


I will fix it.


>> +>> +Required properties:
>> +- compatible : It can be
>> +  "marvell,timer-counter-clkevt" : The counter is used for clock event
>> +   device.
>> +  "marvell,timer-counter-clksrc" : The counter is used for clock source.
>> +  "marvell,timer-counter-delay" : The counter is used for delay timer.
>
>These are all Linux-internal details. I don't see why we should need separate 
>strings; Linux should be able to allocate these as appropriate (and a single 
>timer should be able to be both a clocksource and a delay timer).
>
>Is there any reason you envisage for having separate strings here? It douesn't 
>make sense to me to do so.
>
>> +- marvell,timer-counter-id : The counter index in this timer.
>
>It sounds like you could use reg for this, unless you have other sub-nodes 
>you'll need to instantiate?
>
>> 
>> -Example:
>> -   timer0: timer@d4014000 {
>> -   compatible = "mrvl,mmp-timer";
>> -   reg = <0xd4014000 0x100>;
>> +Optional properties:
>> +- marvell,fast-clock : whether the counter use the fast-clock for counting.
>
>It looks below like this 

[PATCH 1/4] clocksource: mmp: add mmp timer driver

2015-02-02 Thread Chao Xie
From: Chao Xie 

MMP timer is attached to APB bus, It has the following
limitation.
1. When get count of timer counter, it need some delay
   to get a stable count.
2. When set match register, it need disable the counter
   first, and enable it after set the match register.
   The disabling need wait for 2 clock cycle to take
   effect.

To improve above #1, shadow register for count is added.
To improve above #2, CRSR register is added for quick updating.

So there are three types of timer.
timer1: old timer.
timer2: old timer with shadow register.
timer3: old timer with shadow and CRSR register.

This timer driver will be used for many SOCes.
1. pxa168, pxa910, pxa988 pxa1088 have only timer1.
2. pxa1L88, pxa1U88 have timer1 and timer3.
3. pxa1928 has timer 2.

The driver supports DT and non-DT initialization.
The driver supports UP/SMP SOCes and 64 bit core.

Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/arm/mrvl/timer.txt |  61 +-
 drivers/clocksource/Makefile   |   1 +
 drivers/clocksource/timer-mmp.c| 837 +
 include/linux/mmp_timer.h  |  40 +
 4 files changed, 933 insertions(+), 6 deletions(-)
 create mode 100644 drivers/clocksource/timer-mmp.c
 create mode 100644 include/linux/mmp_timer.h

diff --git a/Documentation/devicetree/bindings/arm/mrvl/timer.txt 
b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
index 9a6e251..b49cb3e 100644
--- a/Documentation/devicetree/bindings/arm/mrvl/timer.txt
+++ b/Documentation/devicetree/bindings/arm/mrvl/timer.txt
@@ -1,13 +1,62 @@
 * Marvell MMP Timer controller
 
+Each timer have multiple counters, so the timer DT need include counter's
+description.
+
+1. Timer
+
 Required properties:
-- compatible : Should be "mrvl,mmp-timer".
+- compatible : Should be "marvell,mmp-timer".
 - reg : Address and length of the register set of timer controller.
-- interrupts : Should be the interrupt number.
+- clocks : The first clock is the fequency of the apb bus that the timer
+  attached to. The second clock is the fast clock frequency of the timer.
+  This frequency and fast clock are used to calculated delay
+  loops for clock operations.
+
+Optional properties:
+- marvell,timer-has-crsr : This timer has CRSR register.
+- marvell,timer-has-shadow : This timer has shadow register.
+
+2. Counter
+
+Required properties:
+- compatible : It can be
+  "marvell,timer-counter-clkevt" : The counter is used for clock event
+   device.
+  "marvell,timer-counter-clksrc" : The counter is used for clock source.
+  "marvell,timer-counter-delay" : The counter is used for delay timer.
+- marvell,timer-counter-id : The counter index in this timer.
 
-Example:
-   timer0: timer@d4014000 {
-   compatible = "mrvl,mmp-timer";
-   reg = <0xd4014000 0x100>;
+Optional properties:
+- marvell,fast-clock : whether the counter use the fast-clock for counting.
+- interrupts : The interrupt for clock event device.
+  Only valid for "marvell,timer-counter-clkevt".
+- marvell,timer-counter-cpu : which CPU the counter is bound. Only valid for
+  "marvell,timer-counter-clkevt".
+- marvell,timer-counter-broadcast : When this counter acts as clock event
+  device. It is broadcast clock event device.
+  Only valid for "marvell,timer-counter-clkevt".
+- marvell,timer-counter-nodynirq : When this counter acts as broadcast clock
+  event device, it cannot switch the IRQ of broadcast clock event to any CPU.
+  Only valid for "marvell,timer-counter-clkevt".
+
+3. Examples
+
+timer0: timer@d4014000 {
+   compatible = "marvell,mmp-timer";
+   reg = <0xd4014000 0xc8>;
+   clocks = <&soc_clocks MMP2_PLL1_24>, <&soc_closk MMP2_CLK_TIMER>;
+   status = "okay";
+
+   counter0 {
+   compatible = "marvell,timer-counter-clkevt";
interrupts = <13>;
+   marvell,timer-counter-id = <0>;
+   marvell,timer-counter-cpu = <0>;
+   };
+
+   counter1 {
+   compatible = "marvell,timer-counter-clksrc";
+   marvell,timer-counter-id = <1>;
};
+};
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 94d90b2..6a66d4d 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_ORION_TIMER) += time-orion.o
 obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o
 obj-$(CONFIG_ARCH_CLPS711X)+= clps711x-timer.o
 obj-$(CONFIG_ARCH_MARCO)   += timer-marco.o
+obj-$(CONFIG_ARCH_MMP) += timer-mmp.o
 obj-$(CONFIG_ARCH_MOXART)  += moxart_timer.o
 obj-$(CONFIG_ARCH_MXS) += mxs_timer.o
 obj-$(CONFIG_ARCH_PXA) += pxa_timer.o
diff --git a/drivers/clocksour

[PATCH 4/4] arm: mmp: remove the old timer driver

2015-02-02 Thread Chao Xie
From: Chao Xie 

The new timer driver has been created under
drivers/clocksource/.

After change all SOCes to use the new driver,
remove the old one.

Signed-off-by: Chao Xie 
---
 arch/arm/mach-mmp/Makefile |   2 +-
 arch/arm/mach-mmp/time.c   | 247 -
 2 files changed, 1 insertion(+), 248 deletions(-)
 delete mode 100644 arch/arm/mach-mmp/time.c

diff --git a/arch/arm/mach-mmp/Makefile b/arch/arm/mach-mmp/Makefile
index 98f0f63..18ba814 100644
--- a/arch/arm/mach-mmp/Makefile
+++ b/arch/arm/mach-mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for Marvell's PXA168 processors line
 #
 
-obj-y  += common.o devices.o time.o
+obj-y  += common.o devices.o
 
 # SoC support
 obj-$(CONFIG_CPU_PXA168)   += pxa168.o
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
deleted file mode 100644
index 2756351..000
--- a/arch/arm/mach-mmp/time.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * linux/arch/arm/mach-mmp/time.c
- *
- *   Support for clocksource and clockevents
- *
- * Copyright (C) 2008 Marvell International Ltd.
- * All rights reserved.
- *
- *   2008-04-11: Jason Chagas 
- *   2008-10-08: Bin Yang 
- *
- * The timers module actually includes three timers, each timer with up to
- * three match comparators. Timer #0 is used here in free-running mode as
- * the clock source, and match comparator #1 used as clock event device.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include "clock.h"
-
-#ifdef CONFIG_CPU_MMP2
-#define MMP_CLOCK_FREQ 650
-#else
-#define MMP_CLOCK_FREQ 325
-#endif
-
-#define TIMERS_VIRT_BASE   TIMERS1_VIRT_BASE
-
-#define MAX_DELTA  (0xfffe)
-#define MIN_DELTA  (16)
-
-static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
-
-/*
- * FIXME: the timer needs some delay to stablize the counter capture
- */
-static inline uint32_t timer_read(void)
-{
-   int delay = 100;
-
-   __raw_writel(1, mmp_timer_base + TMR_CVWR(1));
-
-   while (delay--)
-   cpu_relax();
-
-   return __raw_readl(mmp_timer_base + TMR_CVWR(1));
-}
-
-static u64 notrace mmp_read_sched_clock(void)
-{
-   return timer_read();
-}
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-   struct clock_event_device *c = dev_id;
-
-   /*
-* Clear pending interrupt status.
-*/
-   __raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
-
-   /*
-* Disable timer 0.
-*/
-   __raw_writel(0x02, mmp_timer_base + TMR_CER);
-
-   c->event_handler(c);
-
-   return IRQ_HANDLED;
-}
-
-static int timer_set_next_event(unsigned long delta,
-   struct clock_event_device *dev)
-{
-   unsigned long flags;
-
-   local_irq_save(flags);
-
-   /*
-* Disable timer 0.
-*/
-   __raw_writel(0x02, mmp_timer_base + TMR_CER);
-
-   /*
-* Clear and enable timer match 0 interrupt.
-*/
-   __raw_writel(0x01, mmp_timer_base + TMR_ICR(0));
-   __raw_writel(0x01, mmp_timer_base + TMR_IER(0));
-
-   /*
-* Setup new clockevent timer value.
-*/
-   __raw_writel(delta - 1, mmp_timer_base + TMR_TN_MM(0, 0));
-
-   /*
-* Enable timer 0.
-*/
-   __raw_writel(0x03, mmp_timer_base + TMR_CER);
-
-   local_irq_restore(flags);
-
-   return 0;
-}
-
-static void timer_set_mode(enum clock_event_mode mode,
-  struct clock_event_device *dev)
-{
-   unsigned long flags;
-
-   local_irq_save(flags);
-   switch (mode) {
-   case CLOCK_EVT_MODE_ONESHOT:
-   case CLOCK_EVT_MODE_UNUSED:
-   case CLOCK_EVT_MODE_SHUTDOWN:
-   /* disable the matching interrupt */
-   __raw_writel(0x00, mmp_timer_base + TMR_IER(0));
-   break;
-   case CLOCK_EVT_MODE_RESUME:
-   case CLOCK_EVT_MODE_PERIODIC:
-   break;
-   }
-   local_irq_restore(flags);
-}
-
-static struct clock_event_device ckevt = {
-   .name   = "clockevent",
-   .features   = CLOCK_EVT_FEAT_ONESHOT,
-   .rating = 200,
-   .set_next_event = timer_set_next_event,
-   .set_mode   = timer_set_mode,
-};
-
-static cycle_t clksrc_read(struct clocksource *cs)
-{
-   return timer_read();
-}
-
-static struct clocksource cksrc = {
-   .name   = "clocksource",
-   .rating = 200,
-   .read   = clksrc_read,
-   .mask   = CLOCKSOURCE_MASK(32),
-   .flags  = CLOCK_SOURCE_IS

[PATCH 0/4] drivers: clocksource: add mmp timer driver

2015-02-02 Thread Chao Xie
From: Chao Xie 

These patch will create a new timer driver in drivers/clocksource/
The timer driver will support all SOCes in mach-mmp

There are two patches #2 and #3 changing the arch/mach-mmp to make
DT and no-DT supported SOCes to make use of new timer driver

The final patch will remove the old timer driver.

The patches are tested at pxa910 and mmp2(DT and no-DT support).
Because pxa168 is too old, and it is hard to find the board.
So only pass the compiling.

Chao Xie (4):
  clocksource: mmp: add mmp timer driver
  arm: mmp: make SOCes without DT use new timer driver
  arm: mmp: make SOCes with DT use new timer driver
  arm: mmp: remove the old timer driver

 .../devicetree/bindings/arm/mrvl/timer.txt |  61 +-
 arch/arm/boot/dts/mmp2.dtsi|  19 +-
 arch/arm/boot/dts/pxa168.dtsi  |  20 +-
 arch/arm/boot/dts/pxa910.dtsi  |  26 +-
 arch/arm/mach-mmp/Kconfig  |   2 +
 arch/arm/mach-mmp/Makefile |   2 +-
 arch/arm/mach-mmp/common.h |   2 -
 arch/arm/mach-mmp/mmp-dt.c |   4 +-
 arch/arm/mach-mmp/mmp2-dt.c|   4 +-
 arch/arm/mach-mmp/mmp2.c   |  23 +-
 arch/arm/mach-mmp/pxa168.c |  23 +-
 arch/arm/mach-mmp/pxa910.c |  24 +-
 arch/arm/mach-mmp/time.c   | 247 --
 drivers/clocksource/Makefile   |   1 +
 drivers/clocksource/timer-mmp.c| 837 +
 include/linux/mmp_timer.h  |  40 +
 16 files changed, 1058 insertions(+), 277 deletions(-)
 delete mode 100644 arch/arm/mach-mmp/time.c
 create mode 100644 drivers/clocksource/timer-mmp.c
 create mode 100644 include/linux/mmp_timer.h

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/4] arm: mmp: make SOCes without DT use new timer driver

2015-02-02 Thread Chao Xie
From: Chao Xie 

For no DT support, directly call new timer's APIs to initialize
timer.
It need to initialize the timer first, then initialize the clock
event device or clock source which are based on counter.

Signed-off-by: Chao Xie 
---
 arch/arm/mach-mmp/common.h |  2 --
 arch/arm/mach-mmp/mmp2.c   | 23 ++-
 arch/arm/mach-mmp/pxa168.c | 23 ++-
 arch/arm/mach-mmp/pxa910.c | 24 +++-
 4 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index cf445ba..015b209 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -1,8 +1,6 @@
 #include 
 #define ARRAY_AND_SIZE(x)  (x), ARRAY_SIZE(x)
 
-extern void timer_init(int irq);
-
 extern void __init mmp_map_io(void);
 extern void mmp_restart(enum reboot_mode, const char *);
 extern void __init pxa168_clk_init(void);
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index a70b553..12ba28a 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -16,12 +16,14 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -133,7 +135,26 @@ void __init mmp2_timer_init(void)
clk_rst = APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(1);
__raw_writel(clk_rst, APBC_TIMERS);
 
-   timer_init(IRQ_MMP2_TIMER1);
+   /*
+* Make use of timer 1 which id is 0.
+* It has no shadow and crsr regsiters.
+* The fast lock is 6.5M.
+* apb bus is 26M.
+*/
+   mmp_timer_init(0, TIMERS1_VIRT_BASE, 0, 650, 2600);
+
+   /*
+* Enable counter 1 to be clock source.
+* The frequency is 32K.
+*/
+   mmp_counter_clocksource_init(0, 1, 32768);
+
+   /*
+* Enable counter 0 to be clock event device.
+* The frequency is 32K.
+* Only one cpu and there is no broadcast timer.
+*/
+   mmp_counter_clockevent_init(0, 0, IRQ_MMP2_TIMER1, 32768, 0, 0);
 }
 
 /* on-chip devices */
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index 144e997..bb65d8f 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -22,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -78,7 +80,26 @@ void __init pxa168_timer_init(void)
/* 3.25MHz, bus/functional clock enabled, release reset */
__raw_writel(TIMER_CLK_RST, APBC_TIMERS);
 
-   timer_init(IRQ_PXA168_TIMER1);
+   /*
+* Make use of timer 1 which id is 0.
+* It has no shadow and crsr regsiters.
+* The fast lock is 3.25M.
+* apb bus is 26M.
+*/
+   mmp_timer_init(0, TIMERS1_VIRT_BASE, 0, 325, 2600);
+
+   /*
+* Enable counter 1 to be clock source.
+* The frequency is 32K.
+*/
+   mmp_counter_clocksource_init(0, 1, 32768);
+
+   /*
+* Enable counter 0 to be clock event device.
+* The frequency is 32K.
+* Only one cpu and there is no broadcast timer.
+*/
+   mmp_counter_clockevent_init(0, 0, IRQ_PXA168_TIMER1, 32768, 0, 0);
 }
 
 void pxa168_clear_keypad_wakeup(void)
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index eb57ee1..e8ae5b1 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -15,11 +15,13 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -114,7 +116,27 @@ void __init pxa910_timer_init(void)
__raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
__raw_writel(TIMER_CLK_RST, APBC_TIMERS);
 
-   timer_init(IRQ_PXA910_AP1_TIMER1);
+   /*
+* Make use of timer 1 which id is 0.
+* It has no shadow and crsr regsiters.
+* The fast lock is 3.25M.
+* apb bus is 26M.
+*/
+   mmp_timer_init(0, TIMERS1_VIRT_BASE, 0, 325, 2600);
+
+   /*
+* Enable counter 1 to be clock source.
+* The frequency is 32K.
+*/
+   mmp_counter_clocksource_init(0, 1, 32768);
+
+   /*
+* Enable counter 0 to be clock event device.
+* The frequency is 32K.
+* Only one cpu and there is no broadcast timer.
+*/
+   mmp_counter_clockevent_init(0, 0, IRQ_PXA910_AP1_TIMER1,
+   32768, 0, 0);
 }
 
 /* on-chip devices */
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/4] arm: mmp: make SOCes with DT use new timer driver

2015-02-02 Thread Chao Xie
From: Chao Xie 

Change the dtsi and DT support for mmp SOCes to make them
use the new timer driver.

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/mmp2.dtsi   | 19 ---
 arch/arm/boot/dts/pxa168.dtsi | 20 +---
 arch/arm/boot/dts/pxa910.dtsi | 26 --
 arch/arm/mach-mmp/Kconfig |  2 ++
 arch/arm/mach-mmp/mmp-dt.c|  4 +++-
 arch/arm/mach-mmp/mmp2-dt.c   |  4 +++-
 6 files changed, 57 insertions(+), 18 deletions(-)

diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 766bbb8..e63e3a3 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -127,9 +127,22 @@
ranges;
 
timer0: timer@d4014000 {
-   compatible = "mrvl,mmp-timer";
-   reg = <0xd4014000 0x100>;
-   interrupts = <13>;
+   compatible = "marvell,mmp-timer";
+   reg = <0xd4014000 0xc8>;
+   clocks = <&soc_clocks MMP2_CLK_VCTCXO>, 
<&soc_clocks MMP2_CLK_TIMER>;
+   status = "okay";
+
+   counter0 {
+   compatible = 
"marvell,timer-counter-clkevt";
+   interrupts = <13>;
+   marvell,timer-counter-id = <0>;
+   marvell,timer-counter-cpu = <0>;
+};
+
+counter1 {
+   compatible = 
"marvell,timer-counter-clksrc";
+   marvell,timer-counter-id = <1>;
+};
};
 
uart1: uart@d403 {
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index b899e25..5a2f385 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -51,9 +51,23 @@
ranges;
 
timer0: timer@d4014000 {
-   compatible = "mrvl,mmp-timer";
-   reg = <0xd4014000 0x100>;
-   interrupts = <13>;
+   compatible = "marvell,mmp-timer";
+   reg = <0xd4014000 0xc8>;
+   clocks = <&soc_clocks PXA168_CLK_PLL1_24>, 
<&soc_clocks PXA168_CLK_TIMER>;
+   status = "okay";
+
+   counter0 {
+   compatible = 
"marvell,timer-counter-clkevt";
+   interrupts = <13>;
+   marvell,timer-counter-id = <0>;
+   marvell,timer-counter-cpu = <0>;
+};
+
+counter1 {
+   compatible = 
"marvell,timer-counter-clksrc";
+   marvell,timer-counter-id = <1>;
+};
+
};
 
uart1: uart@d4017000 {
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
index 0868f67..beb25fc 100644
--- a/arch/arm/boot/dts/pxa910.dtsi
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -56,16 +56,22 @@
ranges;
 
timer0: timer@d4014000 {
-   compatible = "mrvl,mmp-timer";
-   reg = <0xd4014000 0x100>;
-   interrupts = <13>;
-   };
-
-   timer1: timer@d4016000 {
-   compatible = "mrvl,mmp-timer";
-   reg = <0xd4016000 0x100>;
-   interrupts = <29>;
-   status = "disabled";
+   compatible = "marvell,mmp-timer";
+   reg = <0xd4014000 0xc8>;
+   clocks = <&soc_clocks PXA910_CLK_PLL1_24>, 
<&soc_clocks PXA910_CLK_TIMER0>;
+   status = "okay";
+
+   counter0 {
+   compatible = 
"marvell,timer-counter-clkevt";
+   interrupts = <13>;
+   ma

[PATCH] gpio: mmp: add GPIO driver for Marvell MMP series

2015-01-27 Thread Chao Xie
From: Chao Xie 

For some old PXA series, they used PXA GPIO driver.
The IP of GPIO changes since PXA988 which is Marvell MMP
series.
It will use new way to control the GPIO level, direction
and edge status.

Signed-off-by: Chao Xie 
---
 drivers/gpio/Kconfig|   7 +
 drivers/gpio/Makefile   |   1 +
 drivers/gpio/gpio-mmp.c | 444 
 3 files changed, 452 insertions(+)
 create mode 100644 drivers/gpio/gpio-mmp.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 633ec21..c1e4e27 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -197,6 +197,13 @@ config GPIO_F7188X
  To compile this driver as a module, choose M here: the module will
  be called f7188x-gpio.
 
+config GPIO_MMP
+   bool "MMP GPIO support"
+   depends on ARCH_MMP
+   help
+ Say yes here to support the MMP GPIO device at 
PXA1088/PXA1908/PXA1928.
+ Comparing with PXA GPIO device, the IP of MMP GPIO changes a lot.
+
 config GPIO_MOXART
bool "MOXART GPIO support"
depends on ARCH_MOXART
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 81755f1..60a7cf5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -53,6 +53,7 @@ obj-$(CONFIG_GPIO_MC9S08DZ60) += gpio-mc9s08dz60.o
 obj-$(CONFIG_GPIO_MCP23S08)+= gpio-mcp23s08.o
 obj-$(CONFIG_GPIO_ML_IOH)  += gpio-ml-ioh.o
 obj-$(CONFIG_GPIO_MM_LANTIQ)   += gpio-mm-lantiq.o
+obj-$(CONFIG_GPIO_MMP) += gpio-mmp.o
 obj-$(CONFIG_GPIO_MOXART)  += gpio-moxart.o
 obj-$(CONFIG_GPIO_MPC5200) += gpio-mpc5200.o
 obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o
diff --git a/drivers/gpio/gpio-mmp.c b/drivers/gpio/gpio-mmp.c
new file mode 100644
index 000..63e0766
--- /dev/null
+++ b/drivers/gpio/gpio-mmp.c
@@ -0,0 +1,444 @@
+/*
+ *  Copyright (C) 2014 Marvell International Ltd.
+ *
+ *  Generic MMP GPIO handling
+ *
+ * Chao Xie 
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define GPLR   0x0
+#define GPDR   0xc
+#define GPSR   0x18
+#define GPCR   0x24
+#define GRER   0x30
+#define GFER   0x3c
+#define GEDR   0x48
+#define GSDR   0x54
+#define GCDR   0x60
+#define GSRER  0x6c
+#define GCRER  0x78
+#define GSFER  0x84
+#define GCFER  0x90
+#define GAPMASK0x9c
+#define GCPMASK0xa8
+
+/* Bank will have 2^n GPIOes, and for mmp-gpio n = 5 */
+#define BANK_GPIO_ORDER5
+#define BANK_GPIO_NUMBER   (1 << BANK_GPIO_ORDER)
+#define BANK_GPIO_MASK (BANK_GPIO_NUMBER - 1)
+
+#define mmp_gpio_to_bank_idx(gpio) ((gpio) >> BANK_GPIO_ORDER)
+#define mmp_gpio_to_bank_offset(gpio)  ((gpio) & BANK_GPIO_MASK)
+#define mmp_bank_to_gpio(idx, offset)  (((idx) << BANK_GPIO_ORDER) \
+   | ((offset) & BANK_GPIO_MASK))
+
+struct mmp_gpio_bank {
+   void __iomem *reg_bank;
+   u32 irq_mask;
+   u32 irq_rising_edge;
+   u32 irq_falling_edge;
+};
+
+struct mmp_gpio_chip {
+   struct gpio_chip chip;
+   void __iomem *reg_base;
+   int irq;
+   struct irq_domain *domain;
+   unsigned int ngpio;
+   unsigned int nbank;
+   struct mmp_gpio_bank *banks;
+};
+
+static int mmp_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+
+   return irq_create_mapping(mmp_chip->domain, offset);
+}
+
+static int mmp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+   struct mmp_gpio_bank *bank =
+   &mmp_chip->banks[mmp_gpio_to_bank_idx(offset)];
+   u32 bit = (1 << mmp_gpio_to_bank_offset(offset));
+
+   writel(bit, bank->reg_bank + GCDR);
+
+   return 0;
+}
+
+static int mmp_gpio_direction_output(struct gpio_chip *chip,
+unsigned offset, int value)
+{
+   struct mmp_gpio_chip *mmp_chip =
+   container_of(chip, struct mmp_gpio_chip, chip);
+   struct mmp_gpio_bank *bank =
+   &mmp_chip->banks[mmp_gpio_to_bank_idx(offset)];
+   u32 bit = (1 << mmp_gpio_to_bank_offset(offset));
+
+   /* Set value first. */
+   writel(bit, bank->reg_bank + (value ? GPSR : GPCR));
+
+   writel(bit, bank->reg_bank + GSDR);
+
+   return 0;
+}
+
+static int mmp_gpio_ge

[PATCH V2 00/13] clk: mmp: clock device tree support

2014-10-30 Thread Chao Xie
From: Chao Xie 

The patch set focuses at support device tree for clock.

The first part of the patches
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h It enhances the clk-frac.

The second part of the patches
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock

The third part of the patches
  clk: mmp: add basic support functions for DT support
  clk: mmp: add reset support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
It add the device tree support for pxa168, pxa910 and mmp2.

V1 -> V2:
  Add reset support for the clocks that have reset bit.

Chao Xie (13):
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add basic support functions for DT support
  clk: mmp: add reset support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
  arm: mmp: Make all the dts file to be compiled by Makefile
  arm: mmp: Make use of the DT supported clock

 .../devicetree/bindings/clock/marvell,mmp2.txt |  21 +
 .../devicetree/bindings/clock/marvell,pxa168.txt   |  21 +
 .../devicetree/bindings/clock/marvell,pxa910.txt   |  21 +
 arch/arm/boot/dts/Makefile |   3 +
 arch/arm/boot/dts/mmp2-brownstone.dts  |   2 +-
 arch/arm/boot/dts/mmp2.dtsi|  29 +-
 arch/arm/boot/dts/pxa168-aspenite.dts  |   2 +-
 arch/arm/boot/dts/pxa168.dtsi  |  27 +-
 arch/arm/boot/dts/pxa910-dkb.dts   |   2 +-
 arch/arm/boot/dts/pxa910.dtsi  |  28 +-
 arch/arm/mach-mmp/Kconfig  |  12 +-
 arch/arm/mach-mmp/mmp-dt.c |  57 +--
 arch/arm/mach-mmp/mmp2-dt.c|  26 +-
 drivers/clk/mmp/Makefile   |   7 +-
 drivers/clk/mmp/clk-frac.c |  74 ++-
 drivers/clk/mmp/clk-gate.c | 133 ++
 drivers/clk/mmp/clk-mix.c  | 513 +
 drivers/clk/mmp/clk-mmp2.c |   6 +-
 drivers/clk/mmp/clk-of-mmp2.c  | 334 ++
 drivers/clk/mmp/clk-of-pxa168.c| 279 +++
 drivers/clk/mmp/clk-of-pxa910.c| 301 
 drivers/clk/mmp/clk-pxa168.c   |   6 +-
 drivers/clk/mmp/clk-pxa910.c   |   6 +-
 drivers/clk/mmp/clk.c  | 192 
 drivers/clk/mmp/clk.h  | 226 -
 drivers/clk/mmp/reset.c|  99 
 drivers/clk/mmp/reset.h|  31 ++
 include/dt-bindings/clock/marvell,mmp2.h   |  74 +++
 include/dt-bindings/clock/marvell,pxa168.h |  57 +++
 include/dt-bindings/clock/marvell,pxa910.h |  54 +++
 30 files changed, 2538 insertions(+), 105 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,mmp2.txt
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa168.txt
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa910.txt
 create mode 100644 drivers/clk/mmp/clk-gate.c
 create mode 100644 drivers/clk/mmp/clk-mix.c
 create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
 create mode 100644 drivers/clk/mmp/clk.c
 create mode 100644 drivers/clk/mmp/reset.c
 create mode 100644 drivers/clk/mmp/reset.h
 create mode 100644 include/dt-bindings/clock/marvell,mmp2.h
 create mode 100644 include/dt-bindings/clock/marvell,pxa168.h
 create mode 100644 include/dt-bindings/clock/marvell,pxa910.h

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 02/13] clk: mmp: add spin lock for clk-frac

2014-10-30 Thread Chao Xie
From: Chao Xie 

The register used by clk-frac may be shared with
other clocks.
So it needs to use spin lock to protect the register
access.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 11 ++-
 drivers/clk/mmp/clk-mmp2.c   |  2 +-
 drivers/clk/mmp/clk-pxa168.c |  2 +-
 drivers/clk/mmp/clk-pxa910.c |  2 +-
 drivers/clk/mmp/clk.h|  3 ++-
 5 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 3fbc9ca..e29d006 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -29,6 +29,7 @@ struct mmp_clk_factor {
struct mmp_clk_factor_masks *masks;
struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
+   spinlock_t *lock;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
@@ -86,6 +87,7 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
+   unsigned long flags = 0;
 
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
@@ -97,6 +99,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
if (i > 0)
i--;
 
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
val = readl_relaxed(factor->base);
 
val &= ~(masks->num_mask << masks->num_shift);
@@ -107,6 +112,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
 
writel_relaxed(val, factor->base);
 
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+
return 0;
 }
 
@@ -120,7 +128,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
unsigned long flags, void __iomem *base,
struct mmp_clk_factor_masks *masks,
struct mmp_clk_factor_tbl *ftbl,
-   unsigned int ftbl_cnt)
+   unsigned int ftbl_cnt, spinlock_t *lock)
 {
struct mmp_clk_factor *factor;
struct clk_init_data init;
@@ -143,6 +151,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
factor->ftbl = ftbl;
factor->ftbl_cnt = ftbl_cnt;
factor->hw.init = &init;
+   factor->lock = lock;
 
init.name = name;
init.ops = &clk_factor_ops;
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 7083f12..5c90a42 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void)
clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(clk, 14745600);
clk_register_clkdev(clk, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 75266ac..93e967c 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void)
uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index f817999..993abcd 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void)
uart_pll =  mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 3fe92be..b71b717 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -31,5 +31,6 @@ extern struct clk *mmp_clk_register_apmu(const char *name,
 extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, st

[PATCH V2 07/13] clk: mmp: add basic support functions for DT support

2014-10-30 Thread Chao Xie
From: Chao Xie 

In order to support DT for mmp SOC clocks, it defines
some basic APIs which are shared by all mmp SOC clock
units.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile |   2 +-
 drivers/clk/mmp/clk.c| 192 +++
 drivers/clk/mmp/clk.h| 106 +-
 3 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/mmp/clk.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b..32b5b90 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c
new file mode 100644
index 000..cf038ef
--- /dev/null
+++ b/drivers/clk/mmp/clk.c
@@ -0,0 +1,192 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
+   int nr_clks)
+{
+   static struct clk **clk_table;
+
+   clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
+   if (!clk_table)
+   return;
+
+   unit->clk_table = clk_table;
+   unit->nr_clks = nr_clks;
+   unit->clk_data.clks = clk_table;
+   unit->clk_data.clk_num = nr_clks;
+   of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
+}
+
+void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_fixed_rate_clk *clks,
+   int size)
+{
+   int i;
+   struct clk *clk;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_fixed_rate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   clks[i].fixed_rate);
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_fixed_factor_clk *clks,
+   int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_fixed_factor(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags, clks[i].mult,
+   clks[i].div);
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_general_gate_clk *clks,
+   void __iomem *base, int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_gate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   base + clks[i].offset,
+   clks[i].bit_idx,
+   clks[i].gate_flags,
+   clks[i].lock);
+
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_gate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_gate_clk *clks,
+   void __iomem *base, int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = mmp_clk_register_gate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   base + clks[i].offset,
+   clks[i].mask,
+  

[PATCH V2 01/13] clk: mmp: add prefix "mmp" for structures defined for clk-frac

2014-10-30 Thread Chao Xie
From: Chao Xie 

The structures defined for clk-frac will be used out side
of clk-frac.c.
To avoid conflicts, add prefix "mmp" for these structures'
name.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 23 ---
 drivers/clk/mmp/clk-mmp2.c   |  4 ++--
 drivers/clk/mmp/clk-pxa168.c |  4 ++--
 drivers/clk/mmp/clk-pxa910.c |  4 ++--
 drivers/clk/mmp/clk.h|  8 
 5 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 23a56f5..3fbc9ca 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -22,19 +22,19 @@
  * numerator/denominator = Fin / (Fout * factor)
  */
 
-#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
-struct clk_factor {
+#define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
+struct mmp_clk_factor {
struct clk_hw   hw;
void __iomem*base;
-   struct clk_factor_masks *masks;
-   struct clk_factor_tbl   *ftbl;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
int i;
 
@@ -58,8 +58,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned 
long drate,
 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
 
val = readl_relaxed(factor->base);
@@ -81,8 +81,8 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
@@ -118,10 +118,11 @@ static struct clk_ops clk_factor_ops = {
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
-   struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+   struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl,
unsigned int ftbl_cnt)
 {
-   struct clk_factor *factor;
+   struct mmp_clk_factor *factor;
struct clk_init_data init;
struct clk *clk;
 
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index b2721ca..7083f12 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -54,7 +54,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 14634, .den = 2165},/*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
{.num = 9679, .den = 5728}, /*58.9824MHZ */
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 014396b..75266ac 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -47,7 +47,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
 };
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index 9efc6a4..f817999 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -45,7 +45,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@

[PATCH V2 03/13] clk: mmp: add init callback for clk-frac

2014-10-30 Thread Chao Xie
From: Chao Xie 

For the clk-frac, we need to make sure that the initial
clock rate is one item of the table.
If it is not, we use the first item in the table by default.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index e29d006..1876d2c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -118,10 +118,50 @@ static int clk_factor_set_rate(struct clk_hw *hw, 
unsigned long drate,
return 0;
 }
 
+void clk_factor_init(struct clk_hw *hw)
+{
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
+   u32 val, num, den;
+   int i;
+   unsigned long flags = 0;
+
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
+   val = readl(factor->base);
+
+   /* calculate numerator */
+   num = (val >> masks->num_shift) & masks->num_mask;
+
+   /* calculate denominator */
+   den = (val >> masks->den_shift) & masks->den_mask;
+
+   for (i = 0; i < factor->ftbl_cnt; i++)
+   if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+   break;
+
+   if (i >= factor->ftbl_cnt) {
+   val &= ~(masks->num_mask << masks->num_shift);
+   val |= (factor->ftbl[0].num & masks->num_mask) <<
+   masks->num_shift;
+
+   val &= ~(masks->den_mask << masks->den_shift);
+   val |= (factor->ftbl[0].den & masks->den_mask) <<
+   masks->den_shift;
+
+   writel(val, factor->base);
+   }
+
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+}
+
 static struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
+   .init = clk_factor_init,
 };
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 04/13] clk: mmp: move definiton of mmp_clk_frac to clk.h

2014-10-30 Thread Chao Xie
From: Chao Xie 

Move the definition of structure of mmp_clk_frac to
clk.h.
So device tree support can use this structure.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c |  8 
 drivers/clk/mmp/clk.h  | 32 ++--
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1876d2c..eeba52c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -23,14 +23,6 @@
  */
 
 #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
-struct mmp_clk_factor {
-   struct clk_hw   hw;
-   void __iomem*base;
-   struct mmp_clk_factor_masks *masks;
-   struct mmp_clk_factor_tbl   *ftbl;
-   unsigned intftbl_cnt;
-   spinlock_t *lock;
-};
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index b71b717..d267639 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -7,12 +7,14 @@
 #define APBC_NO_BUS_CTRL   BIT(0)
 #define APBC_POWER_CTRLBIT(1)
 
+
+/* Clock type "factor" */
 struct mmp_clk_factor_masks {
-   unsigned intfactor;
-   unsigned intnum_mask;
-   unsigned intden_mask;
-   unsigned intnum_shift;
-   unsigned intden_shift;
+   unsigned int factor;
+   unsigned int num_mask;
+   unsigned int den_mask;
+   unsigned int num_shift;
+   unsigned int den_shift;
 };
 
 struct mmp_clk_factor_tbl {
@@ -20,6 +22,21 @@ struct mmp_clk_factor_tbl {
unsigned int den;
 };
 
+struct mmp_clk_factor {
+   struct clk_hw hw;
+   void __iomem *base;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl *ftbl;
+   unsigned int ftbl_cnt;
+   spinlock_t *lock;
+};
+
+extern struct clk *mmp_clk_register_factor(const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *base, struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+   spinlock_t *lock);
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
@@ -28,9 +45,4 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
 extern struct clk *mmp_clk_register_apmu(const char *name,
const char *parent_name, void __iomem *base, u32 enable_mask,
spinlock_t *lock);
-extern struct clk *mmp_clk_register_factor(const char *name,
-   const char *parent_name, unsigned long flags,
-   void __iomem *base, struct mmp_clk_factor_masks *masks,
-   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
-   spinlock_t *lock);
 #endif
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 06/13] clk: mmp: add mmp private gate clock

2014-10-30 Thread Chao Xie
From: Chao Xie 

Some SOCes have this kind of the gate clock
1. There are some bits to control the gate not only one bit.
2. It is not always that "1" is to enable while "0" is to disable
   when write register.

So we have to define the "mask", "enable_val", "disable_val" for
this kind of gate clock.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-gate.c | 133 +
 drivers/clk/mmp/clk.h  |  21 +++
 3 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-gate.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 8bfee860..2855f7b 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c
new file mode 100644
index 000..adbd9d6
--- /dev/null
+++ b/drivers/clk/mmp/clk-gate.c
@@ -0,0 +1,133 @@
+/*
+ * mmp gate clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * Some clocks will have mutiple bits to enable the clocks, and
+ * the bits to disable the clock is not same as enabling bits.
+ */
+
+#define to_clk_mmp_gate(hw)container_of(hw, struct mmp_clk_gate, hw)
+
+static int mmp_clk_gate_enable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   struct clk *clk = hw->clk;
+   unsigned long flags = 0;
+   unsigned long rate;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_enable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
+   rate = __clk_get_rate(clk);
+   /* Need delay 2 cycles. */
+   udelay(200/rate);
+   }
+
+   return 0;
+}
+
+static void mmp_clk_gate_disable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_disable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   return (tmp & gate->mask) == gate->val_enable;
+}
+
+const struct clk_ops mmp_clk_gate_ops = {
+   .enable = mmp_clk_gate_enable,
+   .disable = mmp_clk_gate_disable,
+   .is_enabled = mmp_clk_gate_is_enabled,
+};
+
+struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
+   unsigned int gate_flags, spinlock_t *lock)
+{
+   struct mmp_clk_gate *gate;
+   struct clk *clk;
+   struct clk_init_data init;
+
+   /* allocate the gate */
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate) {
+   pr_err("%s:%s could not allocate gate clk\n", __func__, name);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   init.name = name;
+   init.ops = &mmp_clk_gate_ops;
+   init.flags = flags | CLK_IS_BASIC;
+   init.parent_names = (parent_name ? &parent_name : NULL);
+   init.num_parents = (parent_name ? 1 : 0);
+
+   /* struct clk_gate assignments */
+   gate->reg = reg;
+   gate->mask = mask;
+   gate->val_enable = val_enable;
+   gate->val_disable = val_disable;
+   gate->flags = gate_flags;
+   gate->lock = lock;
+   gate->hw.init = &init;
+
+   clk = clk_register(dev, &gate->hw);
+
+   if (IS_ERR(clk))
+   kfree(gate);
+
+   return cl

[PATCH V2 08/13] clk: mmp: add reset support

2014-10-30 Thread Chao Xie
From: Chao Xie 

Some clock control regsiter has bit to reset the cotroller.
So before enable the clock, we need deassert the reset pin.
Make use of reset controller framework to export reset interface
for device drivers, then device driver can control the reset action.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile |  2 +
 drivers/clk/mmp/reset.c  | 99 
 drivers/clk/mmp/reset.h  | 31 +++
 3 files changed, 132 insertions(+)
 create mode 100644 drivers/clk/mmp/reset.c
 create mode 100644 drivers/clk/mmp/reset.h

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 32b5b90..2573d7c 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -4,6 +4,8 @@
 
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
+obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/reset.c b/drivers/clk/mmp/reset.c
new file mode 100644
index 000..b54da1f
--- /dev/null
+++ b/drivers/clk/mmp/reset.c
@@ -0,0 +1,99 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "reset.h"
+
+#define rcdev_to_unit(rcdev) container_of(rcdev, struct mmp_clk_reset_unit, 
rcdev)
+
+static int mmp_of_reset_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+   struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
+   struct mmp_clk_reset_cell *cell;
+   int i;
+
+   if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+   return -EINVAL;
+
+   for (i = 0; i < rcdev->nr_resets; i++) {
+   cell = &unit->cells[i];
+   if (cell->clk_id == reset_spec->args[0])
+   break;
+   }
+
+   if (i == rcdev->nr_resets)
+   return -EINVAL;
+
+   return i;
+}
+
+static int mmp_clk_reset_assert(struct reset_controller_dev *rcdev,
+   unsigned long id)
+{
+   struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
+   struct mmp_clk_reset_cell *cell;
+   unsigned long flags = 0;
+   u32 val;
+
+   cell = &unit->cells[id];
+   if (cell->lock)
+   spin_lock_irqsave(cell->lock, flags);
+
+   val = readl(cell->reg);
+   val |= cell->bits;
+   writel(val, cell->reg);
+
+   if (cell->lock)
+   spin_unlock_irqrestore(cell->lock, flags);
+
+   return 0;
+}
+
+static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev,
+   unsigned long id)
+{
+   struct mmp_clk_reset_unit *unit = rcdev_to_unit(rcdev);
+   struct mmp_clk_reset_cell *cell;
+   unsigned long flags = 0;
+   u32 val;
+
+   cell = &unit->cells[id];
+   if (cell->lock)
+   spin_lock_irqsave(cell->lock, flags);
+
+   val = readl(cell->reg);
+   val &= ~cell->bits;
+   writel(val, cell->reg);
+
+   if (cell->lock)
+   spin_unlock_irqrestore(cell->lock, flags);
+
+   return 0;
+}
+
+static struct reset_control_ops mmp_clk_reset_ops = {
+   .assert = mmp_clk_reset_assert,
+   .deassert   = mmp_clk_reset_deassert,
+};
+
+void mmp_clk_reset_register(struct device_node *np,
+   struct mmp_clk_reset_cell *cells, int nr_resets)
+{
+   struct mmp_clk_reset_unit *unit;
+
+   unit = kzalloc(sizeof(*unit), GFP_KERNEL);
+   if (!unit)
+   return;
+
+   unit->cells = cells;
+   unit->rcdev.of_reset_n_cells = 1;
+   unit->rcdev.nr_resets = nr_resets;
+   unit->rcdev.ops = &mmp_clk_reset_ops;
+   unit->rcdev.of_node = np;
+   unit->rcdev.of_xlate = mmp_of_reset_xlate;
+
+   reset_controller_register(&unit->rcdev);
+}
diff --git a/drivers/clk/mmp/reset.h b/drivers/clk/mmp/reset.h
new file mode 100644
index 000..be8b1a7
--- /dev/null
+++ b/drivers/clk/mmp/reset.h
@@ -0,0 +1,31 @@
+#ifndef __MACH_MMP_CLK_RESET_H
+#define __MACH_MMP_CLK_RESET_H
+
+#include 
+
+#define MMP_RESET_INVERT   1
+
+struct mmp_clk_reset_cell {
+   unsigned int clk_id;
+   void __iomem *reg;
+   u32 bits;
+   unsigned int flags;
+   spinlock_t *lock;
+};
+
+struct mmp_clk_reset_unit {
+   struct reset_controller_dev rcdev;
+   struct mmp_clk_reset_cell *cells;
+};
+
+#ifdef CONFIG_RESET_CONTROLLER
+void mmp_clk_reset_register(struct device_node *np,
+   struct mmp_clk_reset_cell *cells, int nr_resets);
+#else
+static inline void mmp_clk_reset_register(struct device_node *np,
+   struct mmp_clk_reset_cell *cells, int nr_resets)
+{
+}
+#endif
+
+#endif
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsu

[PATCH V2 12/13] arm: mmp: Make all the dts file to be compiled by Makefile

2014-10-30 Thread Chao Xie
From: Chao Xie 

Add items in arch/arm/boot/dt/Makefile to compile the dtb
for mach-mmp.
Change the dts and dtsi file to use #include instead of \include\

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/Makefile| 3 +++
 arch/arm/boot/dts/mmp2-brownstone.dts | 2 +-
 arch/arm/boot/dts/mmp2.dtsi   | 2 +-
 arch/arm/boot/dts/pxa168-aspenite.dts | 2 +-
 arch/arm/boot/dts/pxa168.dtsi | 2 +-
 arch/arm/boot/dts/pxa910-dkb.dts  | 2 +-
 arch/arm/boot/dts/pxa910.dtsi | 2 +-
 7 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index b8c5cd3..f8f7613 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -159,6 +159,9 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
kirkwood-ts419-6282.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
+dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \
+   pxa910-dkb.dtb \
+   mmp2-brownstone.dtb
 dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
imx25-eukrea-mbimxsd25-baseboard.dtb \
diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts 
b/arch/arm/boot/dts/mmp2-brownstone.dts
index 7f70a39..350208c 100644
--- a/arch/arm/boot/dts/mmp2-brownstone.dts
+++ b/arch/arm/boot/dts/mmp2-brownstone.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "mmp2.dtsi"
+#include "mmp2.dtsi"
 
 / {
model = "Marvell MMP2 Brownstone Development Board";
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 4e8b08c..e44f996 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
diff --git a/arch/arm/boot/dts/pxa168-aspenite.dts 
b/arch/arm/boot/dts/pxa168-aspenite.dts
index e762fac..0a988b3 100644
--- a/arch/arm/boot/dts/pxa168-aspenite.dts
+++ b/arch/arm/boot/dts/pxa168-aspenite.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "pxa168.dtsi"
+#include "pxa168.dtsi"
 
 / {
model = "Marvell PXA168 Aspenite Development Board";
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index 975dad2..bfcbdef 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
diff --git a/arch/arm/boot/dts/pxa910-dkb.dts b/arch/arm/boot/dts/pxa910-dkb.dts
index 595492a..c82f281 100644
--- a/arch/arm/boot/dts/pxa910-dkb.dts
+++ b/arch/arm/boot/dts/pxa910-dkb.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "pxa910.dtsi"
+#include "pxa910.dtsi"
 
 / {
model = "Marvell PXA910 DKB Development Board";
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
index 0247c62..884c6e8 100644
--- a/arch/arm/boot/dts/pxa910.dtsi
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2 11/13] clk: mmp: add mmp2 DT support for clock driver

2014-10-30 Thread Chao Xie
From: Chao Xie 

It adds the DT support for mmp2 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/clock/marvell,mmp2.txt |  21 ++
 drivers/clk/mmp/Makefile   |   1 +
 drivers/clk/mmp/clk-of-mmp2.c  | 334 +
 include/dt-bindings/clock/marvell,mmp2.h   |  74 +
 4 files changed, 430 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,mmp2.txt
 create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
 create mode 100644 include/dt-bindings/clock/marvell,mmp2.h

diff --git a/Documentation/devicetree/bindings/clock/marvell,mmp2.txt 
b/Documentation/devicetree/bindings/clock/marvell,mmp2.txt
new file mode 100644
index 000..af376a0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,mmp2.txt
@@ -0,0 +1,21 @@
+* Marvell MMP2 Clock Controller
+
+The MMP2 clock subsystem generates and supplies clock to various
+controllers within the MMP2 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,mmp2-clock" - controller compatible with MMP2 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 3 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc". So three reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 947cd74..3caaf7c 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -7,6 +7,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o 
clk.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 
 obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
+obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
new file mode 100644
index 000..2cbc2b4
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -0,0 +1,334 @@
+/*
+ * mmp2 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+#include "reset.h"
+
+#define APBC_RTC   0x0
+#define APBC_TWSI0 0x4
+#define APBC_TWSI1 0x8
+#define APBC_TWSI2 0xc
+#define APBC_TWSI3 0x10
+#define APBC_TWSI4 0x7c
+#define APBC_TWSI5 0x80
+#define APBC_KPC   0x18
+#define APBC_UART0 0x2c
+#define APBC_UART1 0x30
+#define APBC_UART2 0x34
+#define APBC_UART3 0x88
+#define APBC_GPIO  0x38
+#define APBC_PWM0  0x3c
+#define APBC_PWM1  0x40
+#define APBC_PWM2  0x44
+#define APBC_PWM3  0x48
+#define APBC_SSP0  0x50
+#define APBC_SSP1  0x54
+#define APBC_SSP2  0x58
+#define APBC_SSP3  0x5c
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_SDH2  0xe8
+#define APMU_SDH3  0xec
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_DISP1 0x110
+#define APMU_CCIC0 0x50
+#define APMU_CCIC1 0xf4
+#define MPMU_UART_PLL  0x14
+
+struct mmp2_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 8},
+   {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 96000},
+   {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {MMP2_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {MMP2_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {MMP2_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {MMP2_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {MMP2_CLK_PLL1_20, "pll1_20", "pll1_4", 1, 5, 0},
+   {MMP2_CLK_PLL1_3, "pll1_3", "pll1", 1, 3, 0},
+   {MMP2_CLK_PLL1_6, "pll1_6", "pll1_3", 1, 2, 0},
+   {MMP2_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {MMP2_CLK_PLL2_2, "pll2_2", "pll2", 1, 2, 0},
+   {MMP2_C

[PATCH V2 10/13] clk: mmp: add pxa910 DT support for clock driver

2014-10-30 Thread Chao Xie
From: Chao Xie 

It adds the DT support for pxa910 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/clock/marvell,pxa910.txt   |  21 ++
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-of-pxa910.c| 301 +
 include/dt-bindings/clock/marvell,pxa910.h |  54 
 4 files changed, 377 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa910.txt
 create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
 create mode 100644 include/dt-bindings/clock/marvell,pxa910.h

diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa910.txt 
b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt
new file mode 100644
index 000..d9f41f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa910.txt
@@ -0,0 +1,21 @@
+* Marvell PXA910 Clock Controller
+
+The PXA910 clock subsystem generates and supplies clock to various
+controllers within the PXA910 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa910-clock" - controller compatible with PXA910 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 4 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc", "apbcp". So four reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 733acc7..947cd74 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o 
clk.o
 
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 
-obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o
+obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
new file mode 100644
index 000..5e3c80d
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -0,0 +1,301 @@
+/*
+ * pxa910 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+#include "reset.h"
+
+#define APBC_RTC   0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC   0x18
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO  0x8
+#define APBC_PWM0  0xc
+#define APBC_PWM1  0x10
+#define APBC_PWM2  0x14
+#define APBC_PWM3  0x18
+#define APBC_SSP0  0x1c
+#define APBC_SSP1  0x20
+#define APBC_SSP2  0x4c
+#define APBCP_TWSI10x28
+#define APBCP_UART20x1c
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC   0x60
+#define MPMU_UART_PLL  0x14
+
+struct pxa910_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+   void __iomem *apbcp_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {PXA910_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {PXA910_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {PXA910_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {PXA910_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {PXA910_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
+   {PXA910_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
+   {PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
+   {PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
+   {PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
+   {PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
+   {PXA910_CLK_PLL1_3_16, "p

[PATCH V2 09/13] clk: mmp: add pxa168 DT support for clock driver

2014-10-30 Thread Chao Xie
From: Chao Xie 

It adds the DT support for pxa168 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/clock/marvell,pxa168.txt   |  21 ++
 drivers/clk/mmp/Makefile   |   2 +
 drivers/clk/mmp/clk-of-pxa168.c| 279 +
 include/dt-bindings/clock/marvell,pxa168.h |  57 +
 4 files changed, 359 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/marvell,pxa168.txt
 create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
 create mode 100644 include/dt-bindings/clock/marvell,pxa168.h

diff --git a/Documentation/devicetree/bindings/clock/marvell,pxa168.txt 
b/Documentation/devicetree/bindings/clock/marvell,pxa168.txt
new file mode 100644
index 000..c62eb1d
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell,pxa168.txt
@@ -0,0 +1,21 @@
+* Marvell PXA168 Clock Controller
+
+The PXA168 clock subsystem generates and supplies clock to various
+controllers within the PXA168 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa168-clock" - controller compatible with PXA168 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 3 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc". So three reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2573d7c..733acc7 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,6 +6,8 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o 
clk.o
 
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
 
+obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o
+
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
new file mode 100644
index 000..5b1810d
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -0,0 +1,279 @@
+/*
+ * pxa168 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+#include "reset.h"
+
+#define APBC_RTC   0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC   0x30
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO  0x8
+#define APBC_PWM0  0xc
+#define APBC_PWM1  0x10
+#define APBC_PWM2  0x14
+#define APBC_PWM3  0x18
+#define APBC_SSP0  0x81c
+#define APBC_SSP1  0x820
+#define APBC_SSP2  0x84c
+#define APBC_SSP3  0x858
+#define APBC_SSP4  0x85c
+#define APBC_TWSI1 0x6c
+#define APBC_UART2 0x70
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC   0x60
+#define MPMU_UART_PLL  0x14
+
+struct pxa168_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {PXA168_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {PXA168_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {PXA168_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {PXA168_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {PXA168_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
+   {PXA168_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
+   {PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
+   {PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
+   {PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
+   {PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
+   {PXA168_CLK_PLL1_3_16, "pll1_3_16", "pll1",

[PATCH V2 13/13] arm: mmp: Make use of the DT supported clock

2014-10-30 Thread Chao Xie
From: Chao Xie 

Change the dtsi and dts file, soc initialization code to make
use of DT support clock.
So now in the code we do only need call of_clk_init to initialize
the clocks.

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/mmp2.dtsi   | 27 
 arch/arm/boot/dts/pxa168.dtsi | 25 +++
 arch/arm/boot/dts/pxa910.dtsi | 26 
 arch/arm/mach-mmp/Kconfig | 12 -
 arch/arm/mach-mmp/mmp-dt.c| 57 ++-
 arch/arm/mach-mmp/mmp2-dt.c   | 26 +++-
 6 files changed, 111 insertions(+), 62 deletions(-)

diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index e44f996..766bbb8 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -8,6 +8,7 @@
  */
 
 #include "skeleton.dtsi"
+#include 
 
 / {
aliases {
@@ -135,6 +136,8 @@
compatible = "mrvl,mmp-uart";
reg = <0xd403 0x1000>;
interrupts = <27>;
+   clocks = <&soc_clocks MMP2_CLK_UART0>;
+   resets = <&soc_clocks MMP2_CLK_UART0>;
status = "disabled";
};
 
@@ -142,6 +145,8 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <28>;
+   clocks = <&soc_clocks MMP2_CLK_UART1>;
+   resets = <&soc_clocks MMP2_CLK_UART1>;
status = "disabled";
};
 
@@ -149,6 +154,8 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <24>;
+   clocks = <&soc_clocks MMP2_CLK_UART2>;
+   resets = <&soc_clocks MMP2_CLK_UART2>;
status = "disabled";
};
 
@@ -156,6 +163,8 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4016000 0x1000>;
interrupts = <46>;
+   clocks = <&soc_clocks MMP2_CLK_UART3>;
+   resets = <&soc_clocks MMP2_CLK_UART3>;
status = "disabled";
};
 
@@ -168,6 +177,8 @@
#gpio-cells = <2>;
interrupts = <49>;
interrupt-names = "gpio_mux";
+   clocks = <&soc_clocks MMP2_CLK_GPIO>;
+   resets = <&soc_clocks MMP2_CLK_GPIO>;
interrupt-controller;
#interrupt-cells = <1>;
ranges;
@@ -201,6 +212,8 @@
compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
+   clocks = <&soc_clocks MMP2_CLK_TWSI0>;
+   resets = <&soc_clocks MMP2_CLK_TWSI0>;
#address-cells = <1>;
#size-cells = <0>;
mrvl,i2c-fast-mode;
@@ -211,6 +224,8 @@
compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
+   clocks = <&soc_clocks MMP2_CLK_TWSI1>;
+   resets = <&soc_clocks MMP2_CLK_TWSI1>;
status = "disabled";
};
 
@@ -220,8 +235,20 @@
interrupts = <1 0>;
interrupt-names = "rtc 1Hz", "rtc alarm";
interrupt-parent = <&intcmux5>;
+   clocks = <&soc_clocks MMP2_CLK_RTC>;
+   resets = <&soc_clocks MMP2_CLK_RTC>;
status = "disabled";
};
};
+
+   soc_clocks: clocks{
+   compatible = "marvell,mmp2-clock";
+   reg = <0xd405 0x1000>,
+ 

[PATCH V2 05/13] clk: mmp: add clock type mix

2014-10-30 Thread Chao Xie
From: Chao Xie 

The clock type mix is a kind of clock combines "div" and "mux".
This kind of clock can not allow to change div first then
mux or change mux first or div.
The reason is
1. Some clock has frequency change bit. Each time want to change
   the frequency, there are some operations based on this bit, and
   these operations are time-cost.
   Seperating div and mux change will make the process longer, and
   waste more time.
2. Seperting the div and mux may generate middle clock that the
   peripharals do not support. It may make the peripharals hang.

There are three kinds of this type of clock in all SOCes.
1. The clock has bit to trigger the frequency change.
2. Same as #1, but the operations for the bit is different
3. Do not have frequency change bit.

So this type of clock has implemented the callbacks
->determine_rate
->set_rate_and_parent
These callbacks can help to change the div and mux together.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile  |   2 +-
 drivers/clk/mmp/clk-mix.c | 513 ++
 drivers/clk/mmp/clk.h |  66 ++
 3 files changed, 580 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 392d780..8bfee860 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
new file mode 100644
index 000..b79742c
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix.c
@@ -0,0 +1,513 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * The mix clock is a clock combined mux and div type clock.
+ * Because the div field and mux field need to be set at same
+ * time, we can not divide it into 2 types of clock
+ */
+
+#define to_clk_mix(hw) container_of(hw, struct mmp_clk_mix, hw)
+
+static unsigned int _get_maxdiv(struct mmp_clk_mix *mix)
+{
+   unsigned int div_mask = (1 << mix->reg_info.width_div) - 1;
+   unsigned int maxdiv = 0;
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return div_mask;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return 1 << div_mask;
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->div > maxdiv)
+   maxdiv = clkt->div;
+   return maxdiv;
+   }
+   return div_mask + 1;
+}
+
+static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
+{
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return val;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return 1 << val;
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->val == val)
+   return clkt->div;
+   if (clkt->div == 0)
+   return 0;
+   }
+   return val + 1;
+}
+
+static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val)
+{
+   int num_parents = __clk_get_num_parents(mix->hw.clk);
+   int i;
+
+   if (mix->mux_flags & CLK_MUX_INDEX_BIT)
+   return ffs(val) - 1;
+   if (mix->mux_flags & CLK_MUX_INDEX_ONE)
+   return val - 1;
+   if (mix->mux_table) {
+   for (i = 0; i < num_parents; i++)
+   if (mix->mux_table[i] == val)
+   return i;
+   if (i == num_parents)
+   return 0;
+   }
+
+   return val;
+}
+static unsigned int _get_div_val(struct mmp_clk_mix *mix, unsigned int div)
+{
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return div;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return __ffs(div);
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->div == div)
+   return clkt->val;
+   if (clkt->div == 0)
+   return 0;
+   }
+
+   

Re:Re: [PATCH 02/12] clk: mmp: add spin lock for clk-frac

2014-09-09 Thread Chao Xie

At 2014-09-04 02:04:24, "Mike Turquette"  wrote:
>Quoting Chao Xie (2014-08-25 21:38:14)
>> From: Chao Xie 
>> 
>> The register used by clk-frac may be shared with
>> other clocks.
>> So it needs to use spin lock to protect the register
>> access.
>> 
>> Signed-off-by: Chao Xie 
>
>This patch will break against the latest clk-next due to api changes.
>You can see more here[0] and use this script to update your code if you
>like[1].
>
>Basically the calls to clk_set_rate need to be changed to
>clk_provider_set_rate.

>
I see the patch set [0] is V10 now, and it is not merged to clk-next yet.
So should i wait for the patch set to be merged, then send out the updated 
patches?

>[0] 
>http://lkml.kernel.org/r/<1409758148-20104-1-git-send-email-tomeu.viz...@collabora.com>
>[1] 
>http://cgit.collabora.com/git/user/tomeu/linux.git/commit/?h=clk-refactoring-9&id=ea48c0d655346cce26329523cf24574f9ea8feee
>
>Regards,
>Mike
N嫥叉靣笡y氊b瞂千v豝�)藓{.n�+壏{睉赙zXФ洝塄}财爖�&j:+v墾�珣赙zZ+€�+zf"穐殘啳嗃iz�畐ア�?櫒璀�&�)撷f旟^j谦y呩@A玜囤
0鹅h�鍜i

Re:Re: [PATCH 06/12] clk: mmp: add mmp private gate clock

2014-09-03 Thread Chao Xie


At 2014-09-04 01:55:37, "Mike Turquette"  wrote:
>Quoting Chao Xie (2014-08-25 21:38:18)
>> From: Chao Xie 
>> 
>> Some SOCes have this kind of the gate clock
>> 1. There are some bits to control the gate not only one bit.
>> 2. Some clocks has operations of "out of reset" and "enable".
>>To enable clock, we need do "out of reset" and "enable".
>>To disable clock, we may not need "set to reset". It depends
>>on the SOCes' design.
>
>Are there any other IP blocks affected by the "out of reset" and "set to
>reset" states? I wonder if you might benefit from the reset controller
>framework?  For example see,
>
>drivers/clk/qcom/gcc-apq8084.c
>
>

>
Thanks to point it out.
To use the reset framework, there are some problem.
1. the reset bit is combined with the clocks disable/enable bits in same 
register. Seperating setting them means spinlock
protection and 2 operations for read-update the bits.


except that, i think reset framework can bring some benefits.


Even without the reset bit, we still need the gate clocks.
The enable/disable is not a bit operation, and it is bits operation for some 
devices.
In fact i want to use it to replace the old clk-apbc and clk-apmu clocks. 

>> +static int mmp_clk_gate_enable(struct clk_hw *hw)
>> +{
>> +   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
>> +   struct clk *clk = hw->clk;
>> +   unsigned long flags = 0;
>> +   unsigned long rate;
>> +   u32 tmp;
>> +
>> +   if (gate->lock)
>> +   spin_lock_irqsave(gate->lock, flags);
>> +
>> +   tmp = readl(gate->reg);
>> +   tmp &= ~gate->mask;
>> +   tmp |= gate->val_enable;
>> +   writel(tmp, gate->reg);
>> +
>> +   if (gate->lock)
>> +   spin_unlock_irqrestore(gate->lock, flags);
>> +
>> +   if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
>> +   rate = __clk_get_rate(clk);
>> +   /* Need delay 2 cycles. */
>> +   udelay(200/rate);
>
>How long are these delays? Long enough to warrant using clk_prepare
>instead of clk_enable? Are these clocks enabled from interrupt context?

>
For power optimization, some clocks need to be enabled/disable in interrupt 
context.
The worst delay is rate=32KHZ, so the delay is 62.5us.

>Regards,
>Mike


N嫥叉靣笡y氊b瞂千v豝�)藓{.n�+壏{睉赙zXФ洝塄}财爖�&j:+v墾�珣赙zZ+€�+zf"穐殘啳嗃iz�畐ア�?櫒璀�&�)撷f旟^j谦y呩@A玜囤
0鹅h�鍜i

[PATCH 05/12] clk: mmp: add clock type mix

2014-08-25 Thread Chao Xie
From: Chao Xie 

The clock type mix is a kind of clock combines "div" and "mux".
This kind of clock can not allow to change div first then
mux or change mux first or div.
The reason is
1. Some clock has frequency change bit. Each time want to change
   the frequency, there are some operations based on this bit, and
   these operations are time-cost.
   Seperating div and mux change will make the process longer, and
   waste more time.
2. Seperting the div and mux may generate middle clock that the
   peripharals do not support. It may make the peripharals hang.

There are three kinds of this type of clock in all SOCes.
1. The clock has bit to trigger the frequency change.
2. Same as #1, but the operations for the bit is different
3. Do not have frequency change bit.

So this type of clock has implemented the callbacks
->determine_rate
->set_rate_and_parent
These callbacks can help to change the div and mux together.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile  |   2 +-
 drivers/clk/mmp/clk-mix.c | 513 ++
 drivers/clk/mmp/clk.h |  66 ++
 3 files changed, 580 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 392d780..8bfee860 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
new file mode 100644
index 000..b79742c
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix.c
@@ -0,0 +1,513 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * The mix clock is a clock combined mux and div type clock.
+ * Because the div field and mux field need to be set at same
+ * time, we can not divide it into 2 types of clock
+ */
+
+#define to_clk_mix(hw) container_of(hw, struct mmp_clk_mix, hw)
+
+static unsigned int _get_maxdiv(struct mmp_clk_mix *mix)
+{
+   unsigned int div_mask = (1 << mix->reg_info.width_div) - 1;
+   unsigned int maxdiv = 0;
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return div_mask;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return 1 << div_mask;
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->div > maxdiv)
+   maxdiv = clkt->div;
+   return maxdiv;
+   }
+   return div_mask + 1;
+}
+
+static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
+{
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return val;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return 1 << val;
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->val == val)
+   return clkt->div;
+   if (clkt->div == 0)
+   return 0;
+   }
+   return val + 1;
+}
+
+static unsigned int _get_mux(struct mmp_clk_mix *mix, unsigned int val)
+{
+   int num_parents = __clk_get_num_parents(mix->hw.clk);
+   int i;
+
+   if (mix->mux_flags & CLK_MUX_INDEX_BIT)
+   return ffs(val) - 1;
+   if (mix->mux_flags & CLK_MUX_INDEX_ONE)
+   return val - 1;
+   if (mix->mux_table) {
+   for (i = 0; i < num_parents; i++)
+   if (mix->mux_table[i] == val)
+   return i;
+   if (i == num_parents)
+   return 0;
+   }
+
+   return val;
+}
+static unsigned int _get_div_val(struct mmp_clk_mix *mix, unsigned int div)
+{
+   struct clk_div_table *clkt;
+
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return div;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return __ffs(div);
+   if (mix->div_table) {
+   for (clkt = mix->div_table; clkt->div; clkt++)
+   if (clkt->div == div)
+   return clkt->val;
+   if (clkt->div == 0)
+   return 0;
+   }
+
+   

[PATCH 00/12] clk: mmp: clock device tree support

2014-08-25 Thread Chao Xie
From: Chao Xie 

The patch set focuses at support device tree for clock.

The first part of the patches
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h It enhances the clk-frac.

The second part of the patches
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock

The third part of the patches
  clk: mmp: add basic support functions for DT support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
It add the device tree support for pxa168, pxa910 and mmp2.

The final part of the patches
  arm: mmp: Make all the dts file to be compiled by Makefile
  arm: mmp: Make use of the DT supported clock
It changes the mmp platform to use device tree to parse the clocks.

Chao Xie (12):
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add basic support functions for DT support
  clk: mmp: add pxa168 DT support for clock driver
  clk: mmp: add pxa910 DT support for clock driver
  clk: mmp: add mmp2 DT support for clock driver
  arm: mmp: Make all the dts file to be compiled by Makefile
  arm: mmp: Make use of the DT supported clock

 .../bindings/clock/marvell-mmp2-clock.txt  |  20 +
 .../bindings/clock/marvell-pxa168-clock.txt|  20 +
 .../bindings/clock/marvell-pxa910-clock.txt|  20 +
 arch/arm/boot/dts/Makefile |   3 +
 arch/arm/boot/dts/mmp2-brownstone.dts  |   2 +-
 arch/arm/boot/dts/mmp2.dtsi|  20 +-
 arch/arm/boot/dts/pxa168-aspenite.dts  |   2 +-
 arch/arm/boot/dts/pxa168.dtsi  |  19 +-
 arch/arm/boot/dts/pxa910-dkb.dts   |   2 +-
 arch/arm/boot/dts/pxa910.dtsi  |  20 +-
 arch/arm/mach-mmp/Kconfig  |  10 +-
 arch/arm/mach-mmp/mmp-dt.c |  57 +--
 arch/arm/mach-mmp/mmp2-dt.c|  26 +-
 drivers/clk/mmp/Makefile   |   5 +-
 drivers/clk/mmp/clk-frac.c |  74 ++-
 drivers/clk/mmp/clk-gate.c | 133 ++
 drivers/clk/mmp/clk-mix.c  | 513 +
 drivers/clk/mmp/clk-mmp2.c |   6 +-
 drivers/clk/mmp/clk-of-mmp2.c  | 307 
 drivers/clk/mmp/clk-of-pxa168.c| 251 ++
 drivers/clk/mmp/clk-of-pxa910.c| 260 +++
 drivers/clk/mmp/clk-pxa168.c   |   6 +-
 drivers/clk/mmp/clk-pxa910.c   |   6 +-
 drivers/clk/mmp/clk.c  | 192 
 drivers/clk/mmp/clk.h  | 226 -
 include/dt-bindings/clock/marvell-mmp2.h   |  74 +++
 include/dt-bindings/clock/marvell-pxa168.h |  57 +++
 include/dt-bindings/clock/marvell-pxa910.h |  54 +++
 28 files changed, 2280 insertions(+), 105 deletions(-)
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
 create mode 100644 drivers/clk/mmp/clk-gate.c
 create mode 100644 drivers/clk/mmp/clk-mix.c
 create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
 create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
 create mode 100644 drivers/clk/mmp/clk.c
 create mode 100644 include/dt-bindings/clock/marvell-mmp2.h
 create mode 100644 include/dt-bindings/clock/marvell-pxa168.h
 create mode 100644 include/dt-bindings/clock/marvell-pxa910.h

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac

2014-08-25 Thread Chao Xie
From: Chao Xie 

The structures defined for clk-frac will be used out side
of clk-frac.c.
To avoid conflicts, add prefix "mmp" for these structures'
name.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 23 ---
 drivers/clk/mmp/clk-mmp2.c   |  4 ++--
 drivers/clk/mmp/clk-pxa168.c |  4 ++--
 drivers/clk/mmp/clk-pxa910.c |  4 ++--
 drivers/clk/mmp/clk.h|  8 
 5 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 23a56f5..3fbc9ca 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -22,19 +22,19 @@
  * numerator/denominator = Fin / (Fout * factor)
  */
 
-#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
-struct clk_factor {
+#define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
+struct mmp_clk_factor {
struct clk_hw   hw;
void __iomem*base;
-   struct clk_factor_masks *masks;
-   struct clk_factor_tbl   *ftbl;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
int i;
 
@@ -58,8 +58,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned 
long drate,
 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
 
val = readl_relaxed(factor->base);
@@ -81,8 +81,8 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
@@ -118,10 +118,11 @@ static struct clk_ops clk_factor_ops = {
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
-   struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+   struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl,
unsigned int ftbl_cnt)
 {
-   struct clk_factor *factor;
+   struct mmp_clk_factor *factor;
struct clk_init_data init;
struct clk *clk;
 
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index b2721ca..7083f12 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -54,7 +54,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 14634, .den = 2165},/*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
{.num = 9679, .den = 5728}, /*58.9824MHZ */
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 014396b..75266ac 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -47,7 +47,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
 };
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index 9efc6a4..f817999 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -45,7 +45,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@

[PATCH 03/12] clk: mmp: add init callback for clk-frac

2014-08-25 Thread Chao Xie
From: Chao Xie 

For the clk-frac, we need to make sure that the initial
clock rate is one item of the table.
If it is not, we use the first item in the table by default.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index e29d006..1876d2c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -118,10 +118,50 @@ static int clk_factor_set_rate(struct clk_hw *hw, 
unsigned long drate,
return 0;
 }
 
+void clk_factor_init(struct clk_hw *hw)
+{
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
+   u32 val, num, den;
+   int i;
+   unsigned long flags = 0;
+
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
+   val = readl(factor->base);
+
+   /* calculate numerator */
+   num = (val >> masks->num_shift) & masks->num_mask;
+
+   /* calculate denominator */
+   den = (val >> masks->den_shift) & masks->den_mask;
+
+   for (i = 0; i < factor->ftbl_cnt; i++)
+   if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+   break;
+
+   if (i >= factor->ftbl_cnt) {
+   val &= ~(masks->num_mask << masks->num_shift);
+   val |= (factor->ftbl[0].num & masks->num_mask) <<
+   masks->num_shift;
+
+   val &= ~(masks->den_mask << masks->den_shift);
+   val |= (factor->ftbl[0].den & masks->den_mask) <<
+   masks->den_shift;
+
+   writel(val, factor->base);
+   }
+
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+}
+
 static struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
+   .init = clk_factor_init,
 };
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 08/12] clk: mmp: add pxa168 DT support for clock driver

2014-08-25 Thread Chao Xie
From: Chao Xie 

It adds the DT support for pxa168 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../bindings/clock/marvell-pxa168-clock.txt|  20 ++
 drivers/clk/mmp/Makefile   |   2 +
 drivers/clk/mmp/clk-of-pxa168.c| 251 +
 include/dt-bindings/clock/marvell-pxa168.h |  57 +
 4 files changed, 330 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
 create mode 100644 drivers/clk/mmp/clk-of-pxa168.c
 create mode 100644 include/dt-bindings/clock/marvell-pxa168.h

diff --git a/Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt 
b/Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
new file mode 100644
index 000..888de87
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell-pxa168-clock.txt
@@ -0,0 +1,20 @@
+* Marvell PXA168 Clock Controller
+
+The PXA168 clock subsystem generates and supplies clock to various
+controllers within the PXA168 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa168-clock" - controller compatible with PXA168 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 3 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc". So three reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 32b5b90..37c14fa 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -4,6 +4,8 @@
 
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
+obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o
+
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-of-pxa168.c b/drivers/clk/mmp/clk-of-pxa168.c
new file mode 100644
index 000..deac716
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa168.c
@@ -0,0 +1,251 @@
+/*
+ * pxa168 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+#define APBC_RTC   0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC   0x30
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO  0x8
+#define APBC_PWM0  0xc
+#define APBC_PWM1  0x10
+#define APBC_PWM2  0x14
+#define APBC_PWM3  0x18
+#define APBC_SSP0  0x81c
+#define APBC_SSP1  0x820
+#define APBC_SSP2  0x84c
+#define APBC_SSP3  0x858
+#define APBC_SSP4  0x85c
+#define APBC_TWSI1 0x6c
+#define APBC_UART2 0x70
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC   0x60
+#define MPMU_UART_PLL  0x14
+
+struct pxa168_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {PXA168_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {PXA168_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {PXA168_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {PXA168_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {PXA168_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {PXA168_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {PXA168_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {PXA168_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
+   {PXA168_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {PXA168_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
+   {PXA168_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
+   {PXA168_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA168_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
+   {PXA168_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
+   {PXA168_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
+   {PXA168_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0},
+};
+
+static struct mmp_clk_factor_masks uart_facto

[PATCH 06/12] clk: mmp: add mmp private gate clock

2014-08-25 Thread Chao Xie
From: Chao Xie 

Some SOCes have this kind of the gate clock
1. There are some bits to control the gate not only one bit.
2. Some clocks has operations of "out of reset" and "enable".
   To enable clock, we need do "out of reset" and "enable".
   To disable clock, we may not need "set to reset". It depends
   on the SOCes' design.
3. It is not always that "1" is to enable while "0" is to disable
   when write register.

So we have to define the "mask", "enable_val", "disable_val" for
this kind of gate clock.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-gate.c | 133 +
 drivers/clk/mmp/clk.h  |  21 +++
 3 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-gate.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 8bfee860..2855f7b 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c
new file mode 100644
index 000..adbd9d6
--- /dev/null
+++ b/drivers/clk/mmp/clk-gate.c
@@ -0,0 +1,133 @@
+/*
+ * mmp gate clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * Some clocks will have mutiple bits to enable the clocks, and
+ * the bits to disable the clock is not same as enabling bits.
+ */
+
+#define to_clk_mmp_gate(hw)container_of(hw, struct mmp_clk_gate, hw)
+
+static int mmp_clk_gate_enable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   struct clk *clk = hw->clk;
+   unsigned long flags = 0;
+   unsigned long rate;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_enable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
+   rate = __clk_get_rate(clk);
+   /* Need delay 2 cycles. */
+   udelay(200/rate);
+   }
+
+   return 0;
+}
+
+static void mmp_clk_gate_disable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_disable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   return (tmp & gate->mask) == gate->val_enable;
+}
+
+const struct clk_ops mmp_clk_gate_ops = {
+   .enable = mmp_clk_gate_enable,
+   .disable = mmp_clk_gate_disable,
+   .is_enabled = mmp_clk_gate_is_enabled,
+};
+
+struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
+   unsigned int gate_flags, spinlock_t *lock)
+{
+   struct mmp_clk_gate *gate;
+   struct clk *clk;
+   struct clk_init_data init;
+
+   /* allocate the gate */
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate) {
+   pr_err("%s:%s could not allocate gate clk\n", __func__, name);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   init.name = name;
+   init.ops = &mmp_clk_gate_ops;
+   init.flags = flags | CLK_IS_BASIC;
+   init.parent_names = (parent_name ? &parent_name : NULL);
+   init.num_parents = (parent_name ? 1 : 0);
+
+   /* struct clk_gate assignments */
+   gate->reg = reg;
+   gate->mask = mask;
+   gate->val_enable = val_enable;
+   gate

[PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h

2014-08-25 Thread Chao Xie
From: Chao Xie 

Move the definition of structure of mmp_clk_frac to
clk.h.
So device tree support can use this structure.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c |  8 
 drivers/clk/mmp/clk.h  | 32 ++--
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1876d2c..eeba52c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -23,14 +23,6 @@
  */
 
 #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
-struct mmp_clk_factor {
-   struct clk_hw   hw;
-   void __iomem*base;
-   struct mmp_clk_factor_masks *masks;
-   struct mmp_clk_factor_tbl   *ftbl;
-   unsigned intftbl_cnt;
-   spinlock_t *lock;
-};
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index b71b717..d267639 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -7,12 +7,14 @@
 #define APBC_NO_BUS_CTRL   BIT(0)
 #define APBC_POWER_CTRLBIT(1)
 
+
+/* Clock type "factor" */
 struct mmp_clk_factor_masks {
-   unsigned intfactor;
-   unsigned intnum_mask;
-   unsigned intden_mask;
-   unsigned intnum_shift;
-   unsigned intden_shift;
+   unsigned int factor;
+   unsigned int num_mask;
+   unsigned int den_mask;
+   unsigned int num_shift;
+   unsigned int den_shift;
 };
 
 struct mmp_clk_factor_tbl {
@@ -20,6 +22,21 @@ struct mmp_clk_factor_tbl {
unsigned int den;
 };
 
+struct mmp_clk_factor {
+   struct clk_hw hw;
+   void __iomem *base;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl *ftbl;
+   unsigned int ftbl_cnt;
+   spinlock_t *lock;
+};
+
+extern struct clk *mmp_clk_register_factor(const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *base, struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+   spinlock_t *lock);
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
@@ -28,9 +45,4 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
 extern struct clk *mmp_clk_register_apmu(const char *name,
const char *parent_name, void __iomem *base, u32 enable_mask,
spinlock_t *lock);
-extern struct clk *mmp_clk_register_factor(const char *name,
-   const char *parent_name, unsigned long flags,
-   void __iomem *base, struct mmp_clk_factor_masks *masks,
-   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
-   spinlock_t *lock);
 #endif
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/12] clk: mmp: add basic support functions for DT support

2014-08-25 Thread Chao Xie
From: Chao Xie 

In order to support DT for mmp SOC clocks, it defines
some basic APIs which are shared by all mmp SOC clock
units.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile |   2 +-
 drivers/clk/mmp/clk.c| 192 +++
 drivers/clk/mmp/clk.h| 106 +-
 3 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 drivers/clk/mmp/clk.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b..32b5b90 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c
new file mode 100644
index 000..cf038ef
--- /dev/null
+++ b/drivers/clk/mmp/clk.c
@@ -0,0 +1,192 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
+   int nr_clks)
+{
+   static struct clk **clk_table;
+
+   clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
+   if (!clk_table)
+   return;
+
+   unit->clk_table = clk_table;
+   unit->nr_clks = nr_clks;
+   unit->clk_data.clks = clk_table;
+   unit->clk_data.clk_num = nr_clks;
+   of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
+}
+
+void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_fixed_rate_clk *clks,
+   int size)
+{
+   int i;
+   struct clk *clk;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_fixed_rate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   clks[i].fixed_rate);
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_fixed_factor_clk *clks,
+   int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_fixed_factor(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags, clks[i].mult,
+   clks[i].div);
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_general_gate_clk *clks,
+   void __iomem *base, int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = clk_register_gate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   base + clks[i].offset,
+   clks[i].bit_idx,
+   clks[i].gate_flags,
+   clks[i].lock);
+
+   if (IS_ERR(clk)) {
+   pr_err("%s: failed to register clock %s\n",
+  __func__, clks[i].name);
+   continue;
+   }
+   if (clks[i].id)
+   unit->clk_table[clks[i].id] = clk;
+   }
+}
+
+void mmp_register_gate_clks(struct mmp_clk_unit *unit,
+   struct mmp_param_gate_clk *clks,
+   void __iomem *base, int size)
+{
+   struct clk *clk;
+   int i;
+
+   for (i = 0; i < size; i++) {
+   clk = mmp_clk_register_gate(NULL, clks[i].name,
+   clks[i].parent_name,
+   clks[i].flags,
+   base + clks[i].offset,
+   clks[i].mask,
+  

[PATCH 12/12] arm: mmp: Make use of the DT supported clock

2014-08-25 Thread Chao Xie
From: Chao Xie 

Change the dtsi and dts file, soc initialization code to make
use of DT support clock.
So now in the code we do only need call of_clk_init to initialize
the clocks.

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/mmp2.dtsi   | 18 ++
 arch/arm/boot/dts/pxa168.dtsi | 17 +
 arch/arm/boot/dts/pxa910.dtsi | 18 ++
 arch/arm/mach-mmp/Kconfig | 10 +++-
 arch/arm/mach-mmp/mmp-dt.c| 57 ++-
 arch/arm/mach-mmp/mmp2-dt.c   | 26 +++-
 6 files changed, 84 insertions(+), 62 deletions(-)

diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index e44f996..8a07a94 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -8,6 +8,7 @@
  */
 
 #include "skeleton.dtsi"
+#include 
 
 / {
aliases {
@@ -135,6 +136,7 @@
compatible = "mrvl,mmp-uart";
reg = <0xd403 0x1000>;
interrupts = <27>;
+   clocks = <&soc_clocks MMP2_CLK_UART0>;
status = "disabled";
};
 
@@ -142,6 +144,7 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4017000 0x1000>;
interrupts = <28>;
+   clocks = <&soc_clocks MMP2_CLK_UART1>;
status = "disabled";
};
 
@@ -149,6 +152,7 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4018000 0x1000>;
interrupts = <24>;
+   clocks = <&soc_clocks MMP2_CLK_UART2>;
status = "disabled";
};
 
@@ -156,6 +160,7 @@
compatible = "mrvl,mmp-uart";
reg = <0xd4016000 0x1000>;
interrupts = <46>;
+   clocks = <&soc_clocks MMP2_CLK_UART3>;
status = "disabled";
};
 
@@ -168,6 +173,7 @@
#gpio-cells = <2>;
interrupts = <49>;
interrupt-names = "gpio_mux";
+   clocks = <&soc_clocks MMP2_CLK_GPIO>;
interrupt-controller;
#interrupt-cells = <1>;
ranges;
@@ -201,6 +207,7 @@
compatible = "mrvl,mmp-twsi";
reg = <0xd4011000 0x1000>;
interrupts = <7>;
+   clocks = <&soc_clocks MMP2_CLK_TWSI0>;
#address-cells = <1>;
#size-cells = <0>;
mrvl,i2c-fast-mode;
@@ -211,6 +218,7 @@
compatible = "mrvl,mmp-twsi";
reg = <0xd4025000 0x1000>;
interrupts = <58>;
+   clocks = <&soc_clocks MMP2_CLK_TWSI1>;
status = "disabled";
};
 
@@ -220,8 +228,18 @@
interrupts = <1 0>;
interrupt-names = "rtc 1Hz", "rtc alarm";
interrupt-parent = <&intcmux5>;
+   clocks = <&soc_clocks MMP2_CLK_RTC>;
status = "disabled";
};
};
+
+   soc_clocks: clocks{
+   compatible = "marvell,mmp2-clock";
+   reg = <0xd405 0x1000>,
+ <0xd4282800 0x400>,
+ <0xd4015000 0x1000>;
+   reg-names = "mpmu", "apmu", "apbc";
+   #clock-cells = <1>;
+   };
};
 };
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index bfcbdef..e631dd6 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -8,6 +8,7 @@
  */
 
 #include "skeleton.dtsi"
+#include 
 
 / {
aliases {
@@ -59,6 +60,7 @@
compatible = "mrvl,mmp-uart";
  

[PATCH 09/12] clk: mmp: add pxa910 DT support for clock driver

2014-08-25 Thread Chao Xie
From: Chao Xie 

It adds the DT support for pxa910 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../bindings/clock/marvell-pxa910-clock.txt|  20 ++
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-of-pxa910.c| 260 +
 include/dt-bindings/clock/marvell-pxa910.h |  54 +
 4 files changed, 335 insertions(+), 1 deletion(-)
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
 create mode 100644 drivers/clk/mmp/clk-of-pxa910.c
 create mode 100644 include/dt-bindings/clock/marvell-pxa910.h

diff --git a/Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt 
b/Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
new file mode 100644
index 000..643b57b0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell-pxa910-clock.txt
@@ -0,0 +1,20 @@
+* Marvell PXA910 Clock Controller
+
+The PXA910 clock subsystem generates and supplies clock to various
+controllers within the PXA910 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,pxa910-clock" - controller compatible with PXA910 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 4 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc", "apbcp". So four reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 37c14fa..b803fac 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -4,7 +4,7 @@
 
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
-obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o
+obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-pxa910.c b/drivers/clk/mmp/clk-of-pxa910.c
new file mode 100644
index 000..f746376
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-pxa910.c
@@ -0,0 +1,260 @@
+/*
+ * pxa910 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+#define APBC_RTC   0x28
+#define APBC_TWSI0 0x2c
+#define APBC_KPC   0x18
+#define APBC_UART0 0x0
+#define APBC_UART1 0x4
+#define APBC_GPIO  0x8
+#define APBC_PWM0  0xc
+#define APBC_PWM1  0x10
+#define APBC_PWM2  0x14
+#define APBC_PWM3  0x18
+#define APBC_SSP0  0x1c
+#define APBC_SSP1  0x20
+#define APBC_SSP2  0x4c
+#define APBCP_TWSI10x28
+#define APBCP_UART20x1c
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_CCIC0 0x50
+#define APMU_DFC   0x60
+#define MPMU_UART_PLL  0x14
+
+struct pxa910_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+   void __iomem *apbcp_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {PXA910_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {PXA910_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {PXA910_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 62400},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {PXA910_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {PXA910_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {PXA910_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {PXA910_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {PXA910_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
+   {PXA910_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {PXA910_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
+   {PXA910_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
+   {PXA910_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
+   {PXA910_CLK_PLL1_13, "pll1_13", "pll1", 1, 13, 0},
+   {PXA910_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
+   {PXA910_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
+   {PXA910_CLK_PLL1_3_16, "pll1_3_16", "pll1", 3, 16, 0},
+};
+
+static struct mmp_clk_fact

[PATCH 11/12] arm: mmp: Make all the dts file to be compiled by Makefile

2014-08-25 Thread Chao Xie
From: Chao Xie 

Add items in arch/arm/boot/dt/Makefile to compile the dtb
for mach-mmp.
Change the dts and dtsi file to use #include instead of \include\

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/Makefile| 3 +++
 arch/arm/boot/dts/mmp2-brownstone.dts | 2 +-
 arch/arm/boot/dts/mmp2.dtsi   | 2 +-
 arch/arm/boot/dts/pxa168-aspenite.dts | 2 +-
 arch/arm/boot/dts/pxa168.dtsi | 2 +-
 arch/arm/boot/dts/pxa910-dkb.dts  | 2 +-
 arch/arm/boot/dts/pxa910.dtsi | 2 +-
 7 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index acb6b42..16f91c9 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -159,6 +159,9 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += kirkwood-b3.dtb \
kirkwood-ts419-6282.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
+dtb-$(CONFIG_ARCH_MMP) += pxa168-aspenite.dtb \
+   pxa910-dkb.dtb \
+   mmp2-brownstone.dtb
 dtb-$(CONFIG_ARCH_MOXART) += moxart-uc7112lx.dtb
 dtb-$(CONFIG_ARCH_MXC) += \
imx25-eukrea-mbimxsd25-baseboard.dtb \
diff --git a/arch/arm/boot/dts/mmp2-brownstone.dts 
b/arch/arm/boot/dts/mmp2-brownstone.dts
index 7f70a39..350208c 100644
--- a/arch/arm/boot/dts/mmp2-brownstone.dts
+++ b/arch/arm/boot/dts/mmp2-brownstone.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "mmp2.dtsi"
+#include "mmp2.dtsi"
 
 / {
model = "Marvell MMP2 Brownstone Development Board";
diff --git a/arch/arm/boot/dts/mmp2.dtsi b/arch/arm/boot/dts/mmp2.dtsi
index 4e8b08c..e44f996 100644
--- a/arch/arm/boot/dts/mmp2.dtsi
+++ b/arch/arm/boot/dts/mmp2.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
diff --git a/arch/arm/boot/dts/pxa168-aspenite.dts 
b/arch/arm/boot/dts/pxa168-aspenite.dts
index e762fac..0a988b3 100644
--- a/arch/arm/boot/dts/pxa168-aspenite.dts
+++ b/arch/arm/boot/dts/pxa168-aspenite.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "pxa168.dtsi"
+#include "pxa168.dtsi"
 
 / {
model = "Marvell PXA168 Aspenite Development Board";
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index 975dad2..bfcbdef 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
diff --git a/arch/arm/boot/dts/pxa910-dkb.dts b/arch/arm/boot/dts/pxa910-dkb.dts
index 595492a..c82f281 100644
--- a/arch/arm/boot/dts/pxa910-dkb.dts
+++ b/arch/arm/boot/dts/pxa910-dkb.dts
@@ -8,7 +8,7 @@
  */
 
 /dts-v1/;
-/include/ "pxa910.dtsi"
+#include "pxa910.dtsi"
 
 / {
model = "Marvell PXA910 DKB Development Board";
diff --git a/arch/arm/boot/dts/pxa910.dtsi b/arch/arm/boot/dts/pxa910.dtsi
index 0247c62..884c6e8 100644
--- a/arch/arm/boot/dts/pxa910.dtsi
+++ b/arch/arm/boot/dts/pxa910.dtsi
@@ -7,7 +7,7 @@
  *  publishhed by the Free Software Foundation.
  */
 
-/include/ "skeleton.dtsi"
+#include "skeleton.dtsi"
 
 / {
aliases {
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/12] clk: mmp: add mmp2 DT support for clock driver

2014-08-25 Thread Chao Xie
From: Chao Xie 

It adds the DT support for mmp2 clock subsystem.

Signed-off-by: Chao Xie 
---
 .../bindings/clock/marvell-mmp2-clock.txt  |  20 ++
 drivers/clk/mmp/Makefile   |   1 +
 drivers/clk/mmp/clk-of-mmp2.c  | 307 +
 include/dt-bindings/clock/marvell-mmp2.h   |  74 +
 4 files changed, 402 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
 create mode 100644 drivers/clk/mmp/clk-of-mmp2.c
 create mode 100644 include/dt-bindings/clock/marvell-mmp2.h

diff --git a/Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt 
b/Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
new file mode 100644
index 000..ad4b409
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/marvell-mmp2-clock.txt
@@ -0,0 +1,20 @@
+* Marvell MMP2 Clock Controller
+
+The MMP2 clock subsystem generates and supplies clock to various
+controllers within the MMP2 SoC.
+
+Required Properties:
+
+- compatible: should be one of the following.
+  - "marvell,mmp2-clock" - controller compatible with MMP2 SoC.
+
+- reg: physical base address of the clock subsystem and length of memory mapped
+  region. There are 3 places in SOC has clock control logic:
+  "mpmu", "apmu", "apbc". So three reg spaces need to be defined.
+
+- #clock-cells: should be 1.
+
+Each clock is assigned an identifier and client nodes use this identifier
+to specify the clock which they consume.
+
+All these identifier could be found in .
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index b803fac..25a2bf1 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -5,6 +5,7 @@
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
 
 obj-$(CONFIG_MACH_MMP_DT) += clk-of-pxa168.o clk-of-pxa910.o
+obj-$(CONFIG_MACH_MMP2_DT) += clk-of-mmp2.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c
new file mode 100644
index 000..3a3e9c2
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-mmp2.c
@@ -0,0 +1,307 @@
+/*
+ * mmp2 clock framework source file
+ *
+ * Copyright (C) 2012 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#include "clk.h"
+
+#define APBC_RTC   0x0
+#define APBC_TWSI0 0x4
+#define APBC_TWSI1 0x8
+#define APBC_TWSI2 0xc
+#define APBC_TWSI3 0x10
+#define APBC_TWSI4 0x7c
+#define APBC_TWSI5 0x80
+#define APBC_KPC   0x18
+#define APBC_UART0 0x2c
+#define APBC_UART1 0x30
+#define APBC_UART2 0x34
+#define APBC_UART3 0x88
+#define APBC_GPIO  0x38
+#define APBC_PWM0  0x3c
+#define APBC_PWM1  0x40
+#define APBC_PWM2  0x44
+#define APBC_PWM3  0x48
+#define APBC_SSP0  0x50
+#define APBC_SSP1  0x54
+#define APBC_SSP2  0x58
+#define APBC_SSP3  0x5c
+#define APMU_SDH0  0x54
+#define APMU_SDH1  0x58
+#define APMU_SDH2  0xe8
+#define APMU_SDH3  0xec
+#define APMU_USB   0x5c
+#define APMU_DISP0 0x4c
+#define APMU_DISP1 0x110
+#define APMU_CCIC0 0x50
+#define APMU_CCIC1 0xf4
+#define MPMU_UART_PLL  0x14
+
+struct mmp2_clk_unit {
+   struct mmp_clk_unit unit;
+   void __iomem *mpmu_base;
+   void __iomem *apmu_base;
+   void __iomem *apbc_base;
+};
+
+static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
+   {MMP2_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
+   {MMP2_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 2600},
+   {MMP2_CLK_PLL1, "pll1", NULL, CLK_IS_ROOT, 8},
+   {MMP2_CLK_PLL2, "pll2", NULL, CLK_IS_ROOT, 96000},
+   {MMP2_CLK_USB_PLL, "usb_pll", NULL, CLK_IS_ROOT, 48000},
+};
+
+static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
+   {MMP2_CLK_PLL1_2, "pll1_2", "pll1", 1, 2, 0},
+   {MMP2_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
+   {MMP2_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
+   {MMP2_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
+   {MMP2_CLK_PLL1_20, "pll1_20", "pll1_4", 1, 5, 0},
+   {MMP2_CLK_PLL1_3, "pll1_3", "pll1", 1, 3, 0},
+   {MMP2_CLK_PLL1_6, "pll1_6", "pll1_3", 1, 2, 0},
+   {MMP2_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
+   {MMP2_CLK_PLL2_2, "pll2_2", "pll2", 1, 2, 0},
+   {MMP2_CLK_PLL2_4, "pll2_4", "pll2_2", 1, 2, 0},
+   {MMP2_CLK_PLL2_

[PATCH 02/12] clk: mmp: add spin lock for clk-frac

2014-08-25 Thread Chao Xie
From: Chao Xie 

The register used by clk-frac may be shared with
other clocks.
So it needs to use spin lock to protect the register
access.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 11 ++-
 drivers/clk/mmp/clk-mmp2.c   |  2 +-
 drivers/clk/mmp/clk-pxa168.c |  2 +-
 drivers/clk/mmp/clk-pxa910.c |  2 +-
 drivers/clk/mmp/clk.h|  3 ++-
 5 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 3fbc9ca..e29d006 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -29,6 +29,7 @@ struct mmp_clk_factor {
struct mmp_clk_factor_masks *masks;
struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
+   spinlock_t *lock;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
@@ -86,6 +87,7 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
+   unsigned long flags = 0;
 
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
@@ -97,6 +99,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
if (i > 0)
i--;
 
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
val = readl_relaxed(factor->base);
 
val &= ~(masks->num_mask << masks->num_shift);
@@ -107,6 +112,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
 
writel_relaxed(val, factor->base);
 
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+
return 0;
 }
 
@@ -120,7 +128,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
unsigned long flags, void __iomem *base,
struct mmp_clk_factor_masks *masks,
struct mmp_clk_factor_tbl *ftbl,
-   unsigned int ftbl_cnt)
+   unsigned int ftbl_cnt, spinlock_t *lock)
 {
struct mmp_clk_factor *factor;
struct clk_init_data init;
@@ -143,6 +151,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
factor->ftbl = ftbl;
factor->ftbl_cnt = ftbl_cnt;
factor->hw.init = &init;
+   factor->lock = lock;
 
init.name = name;
init.ops = &clk_factor_ops;
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 7083f12..5c90a42 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void)
clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(clk, 14745600);
clk_register_clkdev(clk, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 75266ac..93e967c 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void)
uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index f817999..993abcd 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void)
uart_pll =  mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 3fe92be..b71b717 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -31,5 +31,6 @@ extern struct clk *mmp_clk_register_apmu(const char *name,
 extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, st

[PATCH 02/12] clk: mmp: add spin lock for clk-frac

2014-06-09 Thread Chao Xie
From: Chao Xie 

The register used by clk-frac may be shared with
other clocks.
So it needs to use spin lock to protect the register
access.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 11 ++-
 drivers/clk/mmp/clk-mmp2.c   |  2 +-
 drivers/clk/mmp/clk-pxa168.c |  2 +-
 drivers/clk/mmp/clk-pxa910.c |  2 +-
 drivers/clk/mmp/clk.h|  3 ++-
 5 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 3fbc9ca..e29d006 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -29,6 +29,7 @@ struct mmp_clk_factor {
struct mmp_clk_factor_masks *masks;
struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
+   spinlock_t *lock;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
@@ -86,6 +87,7 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
+   unsigned long flags = 0;
 
for (i = 0; i < factor->ftbl_cnt; i++) {
prev_rate = rate;
@@ -97,6 +99,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
if (i > 0)
i--;
 
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
val = readl_relaxed(factor->base);
 
val &= ~(masks->num_mask << masks->num_shift);
@@ -107,6 +112,9 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned 
long drate,
 
writel_relaxed(val, factor->base);
 
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+
return 0;
 }
 
@@ -120,7 +128,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
unsigned long flags, void __iomem *base,
struct mmp_clk_factor_masks *masks,
struct mmp_clk_factor_tbl *ftbl,
-   unsigned int ftbl_cnt)
+   unsigned int ftbl_cnt, spinlock_t *lock)
 {
struct mmp_clk_factor *factor;
struct clk_init_data init;
@@ -143,6 +151,7 @@ struct clk *mmp_clk_register_factor(const char *name, const 
char *parent_name,
factor->ftbl = ftbl;
factor->ftbl_cnt = ftbl_cnt;
factor->hw.init = &init;
+   factor->lock = lock;
 
init.name = name;
init.ops = &clk_factor_ops;
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index 7083f12..5c90a42 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -191,7 +191,7 @@ void __init mmp2_clk_init(void)
clk = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(clk, 14745600);
clk_register_clkdev(clk, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 75266ac..93e967c 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -158,7 +158,7 @@ void __init pxa168_clk_init(void)
uart_pll = mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index f817999..993abcd 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -163,7 +163,7 @@ void __init pxa910_clk_init(void)
uart_pll =  mmp_clk_register_factor("uart_pll", "pll1_4", 0,
mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
-   ARRAY_SIZE(uart_factor_tbl));
+   ARRAY_SIZE(uart_factor_tbl), &clk_lock);
clk_set_rate(uart_pll, 14745600);
clk_register_clkdev(uart_pll, "uart_pll", NULL);
 
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 3fe92be..b71b717 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -31,5 +31,6 @@ extern struct clk *mmp_clk_register_apmu(const char *name,
 extern struct clk *mmp_clk_register_factor(const char *name,
const char *parent_name, unsigned long flags,
void __iomem *base, st

[PATCH 00/12] clk: mmp: clock device tree support

2014-06-09 Thread Chao Xie
From: Chao Xie 

The patch set focuses at support device tree for clock.

The first part of the patches
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
It enhances the clk-frac.

The second part of the patches
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add clock type composite for mix
It add three new types of clocks.

The third part of the patches
  clk: mmp: add clock type master
  clk: mmp: add spin lock automatic detection from device tree
  clk: mmp: add device tree support for composite type clock
  clk: mmp: add device tree support for clocks.
It add the device tree support. The whole clock tree is not
defined in .c file, but be parsed from the device tree file.

The final part of the patches
  arm: mmp: support clock device tree for mmp platforms
Change the mmp platform to use device tree to parse the clocks.

Chao Xie (12):
  clk: mmp: add prefix "mmp" for structures defined for clk-frac
  clk: mmp: add spin lock for clk-frac
  clk: mmp: add init callback for clk-frac
  clk: mmp: move definiton of mmp_clk_frac to clk.h
  clk: mmp: add clock type mix
  clk: mmp: add mmp private gate clock
  clk: mmp: add clock type composite for mix
  clk: mmp: add clock type master
  clk: mmp: add spin lock automatic detection from device tree
  clk: mmp: add device tree support for composite type clock
  clk: mmp: add device tree support for clocks.
  arm: mmp: support clock device tree for mmp platforms

 .../devicetree/bindings/clock/mmp/clk-composite|  58 ++
 .../devicetree/bindings/clock/mmp/clk-div  |  28 +
 .../devicetree/bindings/clock/mmp/clk-factor   |  28 +
 .../devicetree/bindings/clock/mmp/clk-gate |  41 ++
 .../devicetree/bindings/clock/mmp/clk-master   |  47 ++
 .../devicetree/bindings/clock/mmp/clk-mix  |  38 ++
 .../devicetree/bindings/clock/mmp/clk-mux  |  20 +
 Documentation/devicetree/bindings/clock/mmp/lock   |  44 ++
 arch/arm/boot/dts/mmp2-clock.dtsi  | 575 +
 arch/arm/boot/dts/mmp2.dtsi|  11 +
 arch/arm/boot/dts/pxa168-clock.dtsi| 443 +
 arch/arm/boot/dts/pxa168.dtsi  |  10 +
 arch/arm/boot/dts/pxa910-clock.dtsi| 388 
 arch/arm/boot/dts/pxa910.dtsi  |  10 +
 arch/arm/mach-mmp/Kconfig  |   7 +-
 arch/arm/mach-mmp/Makefile |   2 +-
 arch/arm/mach-mmp/common.h |   1 +
 arch/arm/mach-mmp/mmp-dt.c |  57 +-
 arch/arm/mach-mmp/mmp2-dt.c|  50 --
 drivers/clk/mmp/Makefile   |   7 +-
 drivers/clk/mmp/clk-frac.c |  74 ++-
 drivers/clk/mmp/clk-gate.c | 133 
 drivers/clk/mmp/clk-master-node.c  | 195 ++
 drivers/clk/mmp/clk-mix-composite.c| 195 ++
 drivers/clk/mmp/clk-mix.c  | 419 +
 drivers/clk/mmp/clk-mmp2.c |   6 +-
 drivers/clk/mmp/clk-of-composite.c | 253 
 drivers/clk/mmp/clk-of.c   | 689 +
 drivers/clk/mmp/clk-pxa168.c   |   6 +-
 drivers/clk/mmp/clk-pxa910.c   |   6 +-
 drivers/clk/mmp/clk.h  | 164 -
 drivers/clk/mmp/lock.c | 159 +
 32 files changed, 4035 insertions(+), 129 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-composite
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-div
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-factor
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-gate
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-master
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mix
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mux
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/lock
 create mode 100644 arch/arm/boot/dts/mmp2-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa168-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa910-clock.dtsi
 delete mode 100644 arch/arm/mach-mmp/mmp2-dt.c
 create mode 100644 drivers/clk/mmp/clk-gate.c
 create mode 100644 drivers/clk/mmp/clk-master-node.c
 create mode 100644 drivers/clk/mmp/clk-mix-composite.c
 create mode 100644 drivers/clk/mmp/clk-mix.c
 create mode 100644 drivers/clk/mmp/clk-of-composite.c
 create mode 100644 drivers/clk/mmp/clk-of.c
 create mode 100644 drivers/clk/mmp/lock.c

-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to 

[PATCH 01/12] clk: mmp: add prefix "mmp" for structures defined for clk-frac

2014-06-09 Thread Chao Xie
From: Chao Xie 

The structures defined for clk-frac will be used out side
of clk-frac.c.
To avoid conflicts, add prefix "mmp" for these structures'
name.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c   | 23 ---
 drivers/clk/mmp/clk-mmp2.c   |  4 ++--
 drivers/clk/mmp/clk-pxa168.c |  4 ++--
 drivers/clk/mmp/clk-pxa910.c |  4 ++--
 drivers/clk/mmp/clk.h|  8 
 5 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 23a56f5..3fbc9ca 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -22,19 +22,19 @@
  * numerator/denominator = Fin / (Fout * factor)
  */
 
-#define to_clk_factor(hw) container_of(hw, struct clk_factor, hw)
-struct clk_factor {
+#define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
+struct mmp_clk_factor {
struct clk_hw   hw;
void __iomem*base;
-   struct clk_factor_masks *masks;
-   struct clk_factor_tbl   *ftbl;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl   *ftbl;
unsigned intftbl_cnt;
 };
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
unsigned long rate = 0, prev_rate;
int i;
 
@@ -58,8 +58,8 @@ static long clk_factor_round_rate(struct clk_hw *hw, unsigned 
long drate,
 static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
unsigned int val, num, den;
 
val = readl_relaxed(factor->base);
@@ -81,8 +81,8 @@ static unsigned long clk_factor_recalc_rate(struct clk_hw *hw,
 static int clk_factor_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
 {
-   struct clk_factor *factor = to_clk_factor(hw);
-   struct clk_factor_masks *masks = factor->masks;
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
int i;
unsigned long val;
unsigned long prev_rate, rate = 0;
@@ -118,10 +118,11 @@ static struct clk_ops clk_factor_ops = {
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
unsigned long flags, void __iomem *base,
-   struct clk_factor_masks *masks, struct clk_factor_tbl *ftbl,
+   struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl,
unsigned int ftbl_cnt)
 {
-   struct clk_factor *factor;
+   struct mmp_clk_factor *factor;
struct clk_init_data init;
struct clk *clk;
 
diff --git a/drivers/clk/mmp/clk-mmp2.c b/drivers/clk/mmp/clk-mmp2.c
index b2721ca..7083f12 100644
--- a/drivers/clk/mmp/clk-mmp2.c
+++ b/drivers/clk/mmp/clk-mmp2.c
@@ -54,7 +54,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -62,7 +62,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 14634, .den = 2165},/*14.745MHZ */
{.num = 3521, .den = 689},  /*19.23MHZ */
{.num = 9679, .den = 5728}, /*58.9824MHZ */
diff --git a/drivers/clk/mmp/clk-pxa168.c b/drivers/clk/mmp/clk-pxa168.c
index 014396b..75266ac 100644
--- a/drivers/clk/mmp/clk-pxa168.c
+++ b/drivers/clk/mmp/clk-pxa168.c
@@ -47,7 +47,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@@ -55,7 +55,7 @@ static struct clk_factor_masks uart_factor_masks = {
.den_shift = 0,
 };
 
-static struct clk_factor_tbl uart_factor_tbl[] = {
+static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
 };
 
diff --git a/drivers/clk/mmp/clk-pxa910.c b/drivers/clk/mmp/clk-pxa910.c
index 9efc6a4..f817999 100644
--- a/drivers/clk/mmp/clk-pxa910.c
+++ b/drivers/clk/mmp/clk-pxa910.c
@@ -45,7 +45,7 @@
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct clk_factor_masks uart_factor_masks = {
+static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
@

[PATCH 06/12] clk: mmp: add mmp private gate clock

2014-06-09 Thread Chao Xie
From: Chao Xie 

Some SOCes have this kind of the gate clock
1. There are some bits to control the gate not only one bit.
2. Some clocks has operations of "out of reset" and "enable".
   To enable clock, we need do "out of reset" and "enable".
   To disable clock, we may not need "set to reset". It depends
   on the SOCes' design.
3. It is not always that "1" is to enable while "0" is to disable
   when write register.

So we have to define the "mask", "enable_val", "disable_val" for
this kind of gate clock.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-gate.c | 133 +
 drivers/clk/mmp/clk.h  |  21 +++
 3 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-gate.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 8bfee860..2855f7b 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-gate.c b/drivers/clk/mmp/clk-gate.c
new file mode 100644
index 000..adbd9d6
--- /dev/null
+++ b/drivers/clk/mmp/clk-gate.c
@@ -0,0 +1,133 @@
+/*
+ * mmp gate clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * Some clocks will have mutiple bits to enable the clocks, and
+ * the bits to disable the clock is not same as enabling bits.
+ */
+
+#define to_clk_mmp_gate(hw)container_of(hw, struct mmp_clk_gate, hw)
+
+static int mmp_clk_gate_enable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   struct clk *clk = hw->clk;
+   unsigned long flags = 0;
+   unsigned long rate;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_enable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   if (gate->flags & MMP_CLK_GATE_NEED_DELAY) {
+   rate = __clk_get_rate(clk);
+   /* Need delay 2 cycles. */
+   udelay(200/rate);
+   }
+
+   return 0;
+}
+
+static void mmp_clk_gate_disable(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+   tmp &= ~gate->mask;
+   tmp |= gate->val_disable;
+   writel(tmp, gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+}
+
+static int mmp_clk_gate_is_enabled(struct clk_hw *hw)
+{
+   struct mmp_clk_gate *gate = to_clk_mmp_gate(hw);
+   unsigned long flags = 0;
+   u32 tmp;
+
+   if (gate->lock)
+   spin_lock_irqsave(gate->lock, flags);
+
+   tmp = readl(gate->reg);
+
+   if (gate->lock)
+   spin_unlock_irqrestore(gate->lock, flags);
+
+   return (tmp & gate->mask) == gate->val_enable;
+}
+
+const struct clk_ops mmp_clk_gate_ops = {
+   .enable = mmp_clk_gate_enable,
+   .disable = mmp_clk_gate_disable,
+   .is_enabled = mmp_clk_gate_is_enabled,
+};
+
+struct clk *mmp_clk_register_gate(struct device *dev, const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *reg, u32 mask, u32 val_enable, u32 val_disable,
+   unsigned int gate_flags, spinlock_t *lock)
+{
+   struct mmp_clk_gate *gate;
+   struct clk *clk;
+   struct clk_init_data init;
+
+   /* allocate the gate */
+   gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+   if (!gate) {
+   pr_err("%s:%s could not allocate gate clk\n", __func__, name);
+   return ERR_PTR(-ENOMEM);
+   }
+
+   init.name = name;
+   init.ops = &mmp_clk_gate_ops;
+   init.flags = flags | CLK_IS_BASIC;
+   init.parent_names = (parent_name ? &parent_name : NULL);
+   init.num_parents = (parent_name ? 1 : 0);
+
+   /* struct clk_gate assignments */
+   gate->reg = reg;
+   gate->mask = mask;
+   gate->val_enable = val_enable;
+   gate

[PATCH 04/12] clk: mmp: move definiton of mmp_clk_frac to clk.h

2014-06-09 Thread Chao Xie
From: Chao Xie 

Move the definition of structure of mmp_clk_frac to
clk.h.
So device tree support can use this structure.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c |  8 
 drivers/clk/mmp/clk.h  | 32 ++--
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index 1876d2c..eeba52c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -23,14 +23,6 @@
  */
 
 #define to_clk_factor(hw) container_of(hw, struct mmp_clk_factor, hw)
-struct mmp_clk_factor {
-   struct clk_hw   hw;
-   void __iomem*base;
-   struct mmp_clk_factor_masks *masks;
-   struct mmp_clk_factor_tbl   *ftbl;
-   unsigned intftbl_cnt;
-   spinlock_t *lock;
-};
 
 static long clk_factor_round_rate(struct clk_hw *hw, unsigned long drate,
unsigned long *prate)
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index b71b717..d267639 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -7,12 +7,14 @@
 #define APBC_NO_BUS_CTRL   BIT(0)
 #define APBC_POWER_CTRLBIT(1)
 
+
+/* Clock type "factor" */
 struct mmp_clk_factor_masks {
-   unsigned intfactor;
-   unsigned intnum_mask;
-   unsigned intden_mask;
-   unsigned intnum_shift;
-   unsigned intden_shift;
+   unsigned int factor;
+   unsigned int num_mask;
+   unsigned int den_mask;
+   unsigned int num_shift;
+   unsigned int den_shift;
 };
 
 struct mmp_clk_factor_tbl {
@@ -20,6 +22,21 @@ struct mmp_clk_factor_tbl {
unsigned int den;
 };
 
+struct mmp_clk_factor {
+   struct clk_hw hw;
+   void __iomem *base;
+   struct mmp_clk_factor_masks *masks;
+   struct mmp_clk_factor_tbl *ftbl;
+   unsigned int ftbl_cnt;
+   spinlock_t *lock;
+};
+
+extern struct clk *mmp_clk_register_factor(const char *name,
+   const char *parent_name, unsigned long flags,
+   void __iomem *base, struct mmp_clk_factor_masks *masks,
+   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
+   spinlock_t *lock);
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
@@ -28,9 +45,4 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
 extern struct clk *mmp_clk_register_apmu(const char *name,
const char *parent_name, void __iomem *base, u32 enable_mask,
spinlock_t *lock);
-extern struct clk *mmp_clk_register_factor(const char *name,
-   const char *parent_name, unsigned long flags,
-   void __iomem *base, struct mmp_clk_factor_masks *masks,
-   struct mmp_clk_factor_tbl *ftbl, unsigned int ftbl_cnt,
-   spinlock_t *lock);
 #endif
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 05/12] clk: mmp: add clock type mix

2014-06-09 Thread Chao Xie
From: Chao Xie 

The clock type mix is a kind of clock combines "div" and "mux".
This kind of clock can not allow to change div first then
mux or change mux first or div.
The reason is
1. Some clock has frequency change bit. Each time want to change
   the frequency, there are some operations based on this bit, and
   these operations are time-cost.
   Seperating div and mux change will make the process longer, and
   waste more time.
2. Seperting the div and mux may generate middle clock that the
   peripharals do not support. It may make the peripharals hang.

There are three kinds of this type of clock in all SOCes.
1. The clock has bit to trigger the frequency change.
2. Same as #1, but the operations for the bit is different
3. Do not have frequency change bit.

So this type of clock has implemented the callbacks
->determine_rate
->set_rate_and_parent
These callbacks can help to change the div and mux together.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile  |   2 +-
 drivers/clk/mmp/clk-mix.c | 419 ++
 drivers/clk/mmp/clk.h |  62 +++
 3 files changed, 482 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 392d780..8bfee860 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix.c b/drivers/clk/mmp/clk-mix.c
new file mode 100644
index 000..d2f6406
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix.c
@@ -0,0 +1,419 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+/*
+ * The mix clock is a clock combined mux and div type clock.
+ * Because the div field and mux field need to be set at same
+ * time, we can not divide it into 2 types of clock
+ */
+
+#define to_clk_mix(hw) container_of(hw, struct mmp_clk_mix, hw)
+
+static unsigned int _get_div(struct mmp_clk_mix *mix, unsigned int val)
+{
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return val;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return 1 << val;
+   return val + 1;
+}
+
+static unsigned int _get_val(struct mmp_clk_mix *mix, unsigned int div)
+{
+   if (mix->div_flags & CLK_DIVIDER_ONE_BASED)
+   return div;
+   if (mix->div_flags & CLK_DIVIDER_POWER_OF_TWO)
+   return __ffs(div);
+   return div - 1;
+}
+
+static void _filter_clk_table(struct mmp_clk_mix *mix,
+   struct mmp_clk_mix_clk_table *table,
+   unsigned int table_size)
+{
+   int i;
+   struct mmp_clk_mix_clk_table *item;
+   struct clk *parent, *clk;
+   unsigned long parent_rate;
+
+   clk = mix->hw.clk;
+
+   for (i = 0; i < table_size; i++) {
+   item = &table[i];
+   parent = clk_get_parent_by_index(clk, item->parent_index);
+   parent_rate = __clk_get_rate(parent);
+   if (parent_rate % item->rate) {
+   item->valid = 0;
+   } else {
+   item->divisor = parent_rate / item->rate;
+   item->valid = 1;
+   }
+   }
+}
+
+static int _set_rate(struct mmp_clk_mix *mix, u32 mux_val, u32 div_val,
+   unsigned int change_mux, unsigned int change_div)
+{
+   struct mmp_clk_mix_reg_info *ri = &mix->reg_info;
+   u8 width, shift;
+   u32 mux_div, fc_req;
+   int ret, timeout = 50;
+   unsigned long flags = 0;
+
+   if (!change_mux && !change_div)
+   return -EINVAL;
+
+   if (mix->lock)
+   spin_lock_irqsave(mix->lock, flags);
+
+   if (mix->type == MMP_CLK_MIX_TYPE_V1
+   || mix->type == MMP_CLK_MIX_TYPE_V2)
+   mux_div = readl(ri->reg_clk_ctrl);
+   else
+   mux_div = readl(ri->reg_clk_sel);
+
+   if (change_div) {
+   width = ri->width_div;
+   shift = ri->shift_div;
+   mux_div &= ~MMP_CLK_BITS_MASK(width, shift);
+   mux_div |= MMP_CLK_BITS_SET_VAL(div_val, width, shift);
+   }
+
+   if (change_mux) {
+   width = ri->width_mux;
+   shift = ri->shift_mux;
+

[PATCH 08/12] clk: mmp: add clock type master

2014-06-09 Thread Chao Xie
From: Chao Xie 

To support device tree for clock, we need pass the register
base and range to the clock.
There are many clock share same range of registers.
For example, clk1 has register as 0xd4210010 while clk2
has 0xd42100c0. If we map the register seperately. There
will waste some space. If there are many clocks like that,
the waste will be huge.
clock type "master node" will map the register for all clocks
that listed as its child in DT file. Each clock will invoke
the APIs provided by "master node" to get its register base.
The following is a exmaple of master clock usage in DT file

apmu_clocks {
compatible = "marvell,mmp-clk-master";
reg = <0xd421 0x1000>;

ck1 {
marvell,reg-offset = <0 0x10>;
};

clk2 {
marvell,reg-offset = <0 0xc0>;
};
}

Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/clock/mmp/clk-master   |  47 +
 drivers/clk/mmp/Makefile   |   4 +
 drivers/clk/mmp/clk-master-node.c  | 195 +
 drivers/clk/mmp/clk.h  |   7 +
 4 files changed, 253 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-master
 create mode 100644 drivers/clk/mmp/clk-master-node.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-master 
b/Documentation/devicetree/bindings/clock/mmp/clk-master
new file mode 100644
index 000..b6acde1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-master
@@ -0,0 +1,47 @@
+Binding for Marvell MMP series master clock.
+
+The MMP related device tree support for clock based on the clock type not clock
+controller. So specific SOC, user need define the DT file for the clock such as
+pxa910-clock.dtsi.
+
+Almost all types of clock will need parameter as "register", and it will map 
the
+"register" before access it. If every clock map the "register" seperately, 
there
+will be a lot of waste.
+
+A master clock is defined for this kind of situation. It will be responsible 
for
+map the registers for all clocks that lists as its children in DT file.
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-master".
+
+
+Optional properties:
+- reg : The register start and range the master clock covered.
+
+Optional properties for child node:
+- marvell,reg-offset : It is a two-values item - .
+   Master node will map the registers for all its children. So
+   for the child it need to pass the information about register
+   index and offset. "register_index" indicates which register 
space
+   it from because master clock can have mutiple register 
space in
+   "reg". "register_offset" indicates the offset in the 
register
+   space.
+
+Examples
+There are two clocks, clk1 has register at 0xd4210010, and clk2 has register at
+0xd42100c0.
+
+apmu_clk {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xd421 0x1000>;
+
+   clk1 {
+   ...
+   marvell,reg-offset = <0 0x10>;
+   };
+
+   clk2 {
+   ...
+   marvell,reg-offset = <0 0xc0>;
+   };
+};
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2cd7d94..518931e 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -5,6 +5,10 @@
 obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o \
 clk-mix-composite.o
 
+ifneq ($(CONFIG_OF),)
+obj-y += clk-master-node.o
+endif
+
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
 obj-$(CONFIG_CPU_MMP2) += clk-mmp2.o
diff --git a/drivers/clk/mmp/clk-master-node.c 
b/drivers/clk/mmp/clk-master-node.c
new file mode 100644
index 000..584f72f
--- /dev/null
+++ b/drivers/clk/mmp/clk-master-node.c
@@ -0,0 +1,195 @@
+/*
+ * mmp master clock source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define MAX_REG8
+
+struct mmp_clk_master_node {
+   unsigned int reg_base[MAX_REG];
+   void __iomem *reg[MAX_REG];
+   struct device_node *np;
+   struct list_head node;
+};
+
+static LIST_HEAD(master_list);
+static DEFINE_MUTEX(master_mutex);
+
+static void mmp_clk_master_setup(struct device_node *np)
+{
+   struct mmp_clk_master_node *node;
+   struct resource res;
+   int i, ret;
+
+   node = kzalloc(sizeof(*node), GFP_KERNEL);
+   if (!node) {
+  

[PATCH 10/12] clk: mmp: add device tree support for composite type clock

2014-06-09 Thread Chao Xie
From: Chao Xie 

To parse composite clock from device tree file, there are some
rules.
The clock to be composited will be the child of the composite
clock in device tree file.
It can support the composition of (mux,div,gate) clock defined
as common clock and (mix,gate) defined only for MMP series.

Signed-off-by: Chao Xie 

Conflicts:
drivers/clk/mmp/Makefile
---
 .../devicetree/bindings/clock/mmp/clk-composite|  58 +
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-of-composite.c | 253 +
 drivers/clk/mmp/clk.h  |  14 ++
 4 files changed, 326 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-composite
 create mode 100644 drivers/clk/mmp/clk-of-composite.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-composite 
b/Documentation/devicetree/bindings/clock/mmp/clk-composite
new file mode 100644
index 000..224968c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-composite
@@ -0,0 +1,58 @@
+Binding for Marvell MMP series composite clock
+
+The common clock defines a general composite clock with div/mux/gate.
+Because MMP series has clock need combines the div/mux together, so
+there is a new type of clock "mix". The "mix" clock can also be
+composited with gate clock. In fact, many mix clocks and gate clocks
+share same registers.
+
+In the device tree file, the clock to be composited should be child
+of the composite clock.
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-composite" for (mix, gate)
+   composition, or "marvell,mmp-clk-general-composite" for
+   (mux, div, gate) composition.
+
+
+Examples
+1. There are three clocks mux1, div1, gate1.
+
+apmu_clk {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xde21 0x1000>;
+
+   general_composite_clk {
+   compatible = "marvell,mmp-clk-general-composite";
+
+   mux1 {
+   ...
+   };
+   div1 {
+   ...
+   };
+   gate1 {
+   ...
+   };
+   };
+};
+
+2. There are two clocks mix1, gate2
+
+apmu_clk {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xde21 0x1000>;
+
+   composite_clk {
+   compatible = "marvell,mmp-clk-composite";
+
+   mix1 {
+   ...
+   };
+   gate2 {
+   ...
+   };
+   };
+};
+
+
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index e8810b6..84dce78 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o  
\
 clk-mix-composite.o
 
 ifneq ($(CONFIG_OF),)
-obj-y += clk-master-node.o lock.o
+obj-y += clk-master-node.o lock.o clk-of-composite.o
 endif
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
diff --git a/drivers/clk/mmp/clk-of-composite.c 
b/drivers/clk/mmp/clk-of-composite.c
new file mode 100644
index 000..403ebe2
--- /dev/null
+++ b/drivers/clk/mmp/clk-of-composite.c
@@ -0,0 +1,253 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+struct mmp_clk_composite_member {
+   struct device_node *np;
+   struct clk_hw *hw;
+   const struct clk_ops *ops;
+   int num_parents;
+   const char **parent_names;
+};
+
+struct mmp_clk_composite_node {
+   struct device_node *np;
+   struct mmp_clk_composite_member *members[MMP_CLK_COMPOSITE_TYPE_MAX];
+   struct list_head node;
+};
+
+static LIST_HEAD(composite_list);
+static DEFINE_MUTEX(composite_mutex);
+
+int of_mmp_clk_composite_add_member(struct device_node *np, struct clk_hw *hw,
+   const struct clk_ops *ops, int type)
+{
+   struct device_node *parent_np;
+   struct mmp_clk_composite_node *node;
+   struct mmp_clk_composite_member *member;
+   unsigned int found = 0;
+   size_t size;
+   int i, ret;
+
+   mutex_lock(&composite_mutex);
+
+   parent_np = of_get_next_parent(np);
+
+   list_for_each_entry(node, &composite_list, node) {
+   if (node->np == parent_np) {
+   found = 1;
+   break;
+   }
+   }
+
+   if (!found) {
+   pr_err("%s:%s can not find member %s\n",
+   __fu

[PATCH 03/12] clk: mmp: add init callback for clk-frac

2014-06-09 Thread Chao Xie
From: Chao Xie 

For the clk-frac, if it has table, we need to make
sure that the initial clock rate is one item of the
table.
If it is not, we use the first item in the table by default.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/clk-frac.c | 40 
 1 file changed, 40 insertions(+)

diff --git a/drivers/clk/mmp/clk-frac.c b/drivers/clk/mmp/clk-frac.c
index e29d006..1876d2c 100644
--- a/drivers/clk/mmp/clk-frac.c
+++ b/drivers/clk/mmp/clk-frac.c
@@ -118,10 +118,50 @@ static int clk_factor_set_rate(struct clk_hw *hw, 
unsigned long drate,
return 0;
 }
 
+void clk_factor_init(struct clk_hw *hw)
+{
+   struct mmp_clk_factor *factor = to_clk_factor(hw);
+   struct mmp_clk_factor_masks *masks = factor->masks;
+   u32 val, num, den;
+   int i;
+   unsigned long flags = 0;
+
+   if (factor->lock)
+   spin_lock_irqsave(factor->lock, flags);
+
+   val = readl(factor->base);
+
+   /* calculate numerator */
+   num = (val >> masks->num_shift) & masks->num_mask;
+
+   /* calculate denominator */
+   den = (val >> masks->den_shift) & masks->den_mask;
+
+   for (i = 0; i < factor->ftbl_cnt; i++)
+   if (den == factor->ftbl[i].den && num == factor->ftbl[i].num)
+   break;
+
+   if (i >= factor->ftbl_cnt) {
+   val &= ~(masks->num_mask << masks->num_shift);
+   val |= (factor->ftbl[0].num & masks->num_mask) <<
+   masks->num_shift;
+
+   val &= ~(masks->den_mask << masks->den_shift);
+   val |= (factor->ftbl[0].den & masks->den_mask) <<
+   masks->den_shift;
+
+   writel(val, factor->base);
+   }
+
+   if (factor->lock)
+   spin_unlock_irqrestore(factor->lock, flags);
+}
+
 static struct clk_ops clk_factor_ops = {
.recalc_rate = clk_factor_recalc_rate,
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
+   .init = clk_factor_init,
 };
 
 struct clk *mmp_clk_register_factor(const char *name, const char *parent_name,
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 09/12] clk: mmp: add spin lock automatic detection from device tree

2014-06-09 Thread Chao Xie
From: Chao Xie 

For Marvell MMP series SOC, many clocks share same register.
In the operations of these clock, a spin lock is needed to avoid
confilicts.
When parse the clock from the device tree and register the clock,
we do not know whether it share the register with others.
So a common API is provided to get the spin lock for the clock based
on device tree support.
The general idea is record the node (clock device node, regsiter),
and before register a new clock, search the node list based on
register. If a node is found, return the shared spin lock, or create
a new.

Signed-off-by: Chao Xie 

Conflicts:
drivers/clk/mmp/Makefile
---
 Documentation/devicetree/bindings/clock/mmp/lock |  44 +++
 drivers/clk/mmp/Makefile |   2 +-
 drivers/clk/mmp/clk.h|   5 +
 drivers/clk/mmp/lock.c   | 159 +++
 4 files changed, 209 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/lock
 create mode 100644 drivers/clk/mmp/lock.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/lock 
b/Documentation/devicetree/bindings/clock/mmp/lock
new file mode 100644
index 000..7e7b5bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/lock
@@ -0,0 +1,44 @@
+Binding of spin lock support for Marvell MMP series clock
+
+Because some clocks share same register, spinlock need to be used to avoid
+conflicts.
+
+The spin lock sharing detection is based on regsiter address, and it is
+automatically. To support some clocks, the spin lock is not based on
+register address, some properies are provided.
+The properites are used as part of clock's properties in clock device tree
+files.
+
+Optional properties:
+marvell,mmp-clk-spinlock-new : Skip the automatic detection based on
+  register address. Direclty create a new
+  spin lock.
+marvell,mmp-clk-spinlock : It is handle. It points to the clock that share
+  same spin lock.
+
+Examples:
+
+Assume that clk1, clk2, clk3 share same spin lock.
+
+apmu_clk {
+   compatible = "marvell,mmp-clk-master";
+   ...
+
+   clk1 {
+   ...
+   marvell,mmp-clk-spinlock-new;
+   ...
+   };
+
+   clk2 {
+   ...
+   mmp-clk-spinlock = <&clk1>;
+   ...
+   };
+
+   clk3 {
+   ...
+   mmp-clk-spinlock = <&clk1>;
+   ...
+   };
+};
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 518931e..e8810b6 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -6,7 +6,7 @@ obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o  
\
 clk-mix-composite.o
 
 ifneq ($(CONFIG_OF),)
-obj-y += clk-master-node.o
+obj-y += clk-master-node.o lock.o
 endif
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 6d8c3b3..e06a228 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -147,6 +147,11 @@ extern void __iomem *of_mmp_clk_get_reg(struct device_node 
*np,
 struct device_node *of_mmp_clk_master_init(struct device_node *from);
 
 
+/* spin lock sharing support. */
+extern spinlock_t *of_mmp_clk_get_spinlock(struct device_node *np,
+  unsigned int reg_base);
+
+
 extern struct clk *mmp_clk_register_pll2(const char *name,
const char *parent_name, unsigned long flags);
 extern struct clk *mmp_clk_register_apbc(const char *name,
diff --git a/drivers/clk/mmp/lock.c b/drivers/clk/mmp/lock.c
new file mode 100644
index 000..e2e246c
--- /dev/null
+++ b/drivers/clk/mmp/lock.c
@@ -0,0 +1,159 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct mmp_clk_spinlock_node {
+   struct device_node *share;
+   struct list_head node;
+};
+
+struct mmp_clk_spinlock {
+   spinlock_t lock;
+   struct device_node *owner;
+   unsigned int reg_base;
+   struct list_head share_list;
+   struct list_head node;
+};
+
+static LIST_HEAD(lock_list);
+
+static DEFINE_MUTEX(lock_mutex);
+
+static struct mmp_clk_spinlock_node *create_lock_node(struct device_node *np)
+{
+   struct mmp_clk_spinlock_node *node;
+
+   node = kzalloc(sizeof(*node), GFP_KERNEL);
+   if (!node) {
+   pr_err("%s:%s failed to allocate spinlock node.\n",
+   __func__, np->name);
+   return NULL;
+   }
+
+   node->share = np;
+
+   return n

[PATCH 11/12] clk: mmp: add device tree support for clocks.

2014-06-09 Thread Chao Xie
From: Chao Xie 

For MMP series SOC, it will use some types of clock.
Add the device tree support for these kind of clocks.
It includes mux/div/mix/gate/factor clock.

Signed-off-by: Chao Xie 

Conflicts:
drivers/clk/mmp/Makefile
---
 .../devicetree/bindings/clock/mmp/clk-div  |  28 +
 .../devicetree/bindings/clock/mmp/clk-factor   |  28 +
 .../devicetree/bindings/clock/mmp/clk-gate |  41 ++
 .../devicetree/bindings/clock/mmp/clk-mix  |  38 ++
 .../devicetree/bindings/clock/mmp/clk-mux  |  20 +
 drivers/clk/mmp/Makefile   |   2 +-
 drivers/clk/mmp/clk-of.c   | 689 +
 7 files changed, 845 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-div
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-factor
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-gate
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mix
 create mode 100644 Documentation/devicetree/bindings/clock/mmp/clk-mux
 create mode 100644 drivers/clk/mmp/clk-of.c

diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-div 
b/Documentation/devicetree/bindings/clock/mmp/clk-div
new file mode 100644
index 000..62eb7d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-div
@@ -0,0 +1,28 @@
+Binding for div type clock
+
+The div clock is defined as common clock.
+
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-div".
+- clocks : The parents of the clock.
+- marvell,mmp-clk-bits-div : The width and shift of divider bits.
+
+Optional properties:
+- marvell,mmp-clk-div-power-of-two : The value of divider is a power of two.
+- marvell,mmp-clk-div-one-based : The value of divider starts from 1.
+- marvell,mmp-clk-div-table : The value of divider is not continous, and need
+  a table to record it.
+
+
+Examples
+apmu_clk {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xd4282800 0x1000>;
+   dsi_phy_slow_div: dsi_phy_slow_div {
+   compatible = "marvell,mmp-clk-div";
+   marvell,reg-offset = <0 0x44>;
+   clocks = <&vctcxo>;
+   marvell,mmp-clk-bits-div = <5 6>;
+   };
+};
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-factor 
b/Documentation/devicetree/bindings/clock/mmp/clk-factor
new file mode 100644
index 000..9e1816c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-factor
@@ -0,0 +1,28 @@
+Binding for Marvell MMP series factor clock
+
+The factor clock is calculated by
+  Fout = (Fin * (den / num)) / factor;
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-factor";
+- clock: The parent of the clock.
+- marvell,mmp-clk-factor-factor : The "factor" of the clock.
+- marvell,mmp-clk-factor-bits-num : The width and shift of bits for "num".
+- marvell,mmp-clk-factor-bits-den : The width and shift of bits for "dev".
+- marvell,mmp-clk-factor-table : The table of (num, den) for the clock.
+
+Examples
+mpmu_clocks: mpmu_clocks {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xd405 0x1000>;
+   uart_pll: uart_pll {
+   compatible = "marvell,mmp-clk-factor";
+   clocks = <&pll1_4>;
+   marvell,reg-offset = <0 0x14>;
+   marvell,mmp-clk-factor-factor = <2>;
+   marvell,mmp-clk-factor-bits-den = <13 0>;
+   marvell,mmp-clk-factor-bits-num = <13 16>;
+   marvell,mmp-clk-factor-table = <8125 1536>;
+   };
+};
++
diff --git a/Documentation/devicetree/bindings/clock/mmp/clk-gate 
b/Documentation/devicetree/bindings/clock/mmp/clk-gate
new file mode 100644
index 000..5da6c63
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mmp/clk-gate
@@ -0,0 +1,41 @@
+Binding for Marvell MMP series gate clock and common gate clock
+
+There two type of gate clock used by Marvell MMP series SOC.
+The common gate clock and the gate clock defined for MMP series SOC.
+
+For common gate clock
+
+Required properties
+- compatible : It should be "marvell,mmp-clk-general-gate";
+- clock : The parent of the clock.
+- marvell,mmp-clk-bit-gate : The offset of the bit control the gate.
+
+Examples
+apmu_clocks: apmu_clocks {
+   compatible = "marvell,mmp-clk-master";
+   reg = <0xd4282800 0x1000>;
+   pll1_416_gate: pll1_416_gate {
+   compatible = "marvell,mmp-clk-general-gate";
+   clocks = <&pll1_416m>;
+   marvell,reg-offset = <0 0x40>;
+   marvell,mmp-clk-bit-gate = <27>;
+   };
+};
+
+For MMP series gate clock
+
+Required properties
+- compatible : It should be "marvell

[PATCH 07/12] clk: mmp: add clock type composite for mix

2014-06-09 Thread Chao Xie
From: Chao Xie 

The general composite clock supports div/mux/gate.
marvell SOCes have many clocks that need change
div and mux together. So it need the composite
clock that supports mix/gate.

Signed-off-by: Chao Xie 
---
 drivers/clk/mmp/Makefile|   3 +-
 drivers/clk/mmp/clk-mix-composite.c | 195 
 drivers/clk/mmp/clk.h   |  20 
 3 files changed, 217 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/mmp/clk-mix-composite.c

diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b..2cd7d94 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,8 @@
 # Makefile for mmp specific clk
 #
 
-obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o
+obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o \
+clk-mix-composite.o
 
 obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
 obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk-mix-composite.c 
b/drivers/clk/mmp/clk-mix-composite.c
new file mode 100644
index 000..79d5286
--- /dev/null
+++ b/drivers/clk/mmp/clk-mix-composite.c
@@ -0,0 +1,195 @@
+/*
+ * mmp mix(div and mux) clock operation source file
+ *
+ * Copyright (C) 2014 Marvell
+ * Chao Xie 
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "clk.h"
+
+#define to_clk_composite(_hw) container_of(_hw, struct mmp_clk_composite, hw)
+
+static u8 mmp_clk_composite_get_parent(struct clk_hw *hw)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->get_parent(mix_hw);
+}
+
+static int mmp_clk_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->set_parent(mix_hw, index);
+}
+
+static int mmp_clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+  unsigned long parent_rate)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->set_rate(mix_hw, rate, parent_rate);
+}
+
+static unsigned long mmp_clk_composite_recalc_rate(struct clk_hw *hw,
+   unsigned long parent_rate)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->recalc_rate(mix_hw, parent_rate);
+}
+
+static long mmp_clk_composite_determine_rate(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long *best_parent_rate,
+   struct clk **best_parent_p)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->determine_rate(mix_hw, rate, best_parent_rate,
+   best_parent_p);
+}
+
+static int mmp_clk_composite_set_rate_and_parent(struct clk_hw *hw,
+   unsigned long rate,
+   unsigned long parent_rate, u8 index)
+
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *mix_ops = composite->mix_ops;
+   struct clk_hw *mix_hw = composite->mix_hw;
+
+   mix_hw->clk = hw->clk;
+
+   return mix_ops->set_rate_and_parent(mix_hw, rate, parent_rate, index);
+}
+
+static int mmp_clk_composite_is_enabled(struct clk_hw *hw)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *gate_ops = composite->gate_ops;
+   struct clk_hw *gate_hw = composite->gate_hw;
+
+   gate_hw->clk = hw->clk;
+
+   return gate_ops->is_enabled(gate_hw);
+}
+
+static int mmp_clk_composite_enable(struct clk_hw *hw)
+{
+   struct mmp_clk_composite *composite = to_clk_composite(hw);
+   const struct clk_ops *gate_ops = composite->gate_ops;
+   struct clk_hw *gate_hw = composite->gate_hw;
+
+   gate_hw->clk =

[PATCH 12/12] arm: mmp: support clock device tree for mmp platforms

2014-06-09 Thread Chao Xie
From: Chao Xie 

The platforms including pxa168/pxa910/mmp2.

After add clock device tree support. There is no need
to maintain mmp2-dt.c because it is same as mmp-dt.c now.
The file will be removed.

Compiling test for pxa168 because of lacking of platform.
The platform is too old.

Functonality test for pxa910 and mmp2.

Signed-off-by: Chao Xie 
---
 arch/arm/boot/dts/mmp2-clock.dtsi   | 575 
 arch/arm/boot/dts/mmp2.dtsi |  11 +
 arch/arm/boot/dts/pxa168-clock.dtsi | 443 +++
 arch/arm/boot/dts/pxa168.dtsi   |  10 +
 arch/arm/boot/dts/pxa910-clock.dtsi | 388 
 arch/arm/boot/dts/pxa910.dtsi   |  10 +
 arch/arm/mach-mmp/Kconfig   |   7 +-
 arch/arm/mach-mmp/Makefile  |   2 +-
 arch/arm/mach-mmp/common.h  |   1 +
 arch/arm/mach-mmp/mmp-dt.c  |  57 ++--
 arch/arm/mach-mmp/mmp2-dt.c |  50 
 11 files changed, 1462 insertions(+), 92 deletions(-)
 create mode 100644 arch/arm/boot/dts/mmp2-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa168-clock.dtsi
 create mode 100644 arch/arm/boot/dts/pxa910-clock.dtsi
 delete mode 100644 arch/arm/mach-mmp/mmp2-dt.c

diff --git a/arch/arm/boot/dts/mmp2-clock.dtsi 
b/arch/arm/boot/dts/mmp2-clock.dtsi
new file mode 100644
index 000..89f2279
--- /dev/null
+++ b/arch/arm/boot/dts/mmp2-clock.dtsi
@@ -0,0 +1,575 @@
+&soc_clocks {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+   fixed_clocks: fixed_clocks {
+   compatible = "marvell,mmp-clk-master";
+   clk32: clk32 {
+   #clock-cells = <0>;
+   compatible = "fixed-clock";
+   clock-frequency = <32768>;
+   };
+   vctcxo: vctcxo {
+   #clock-cells = <0>;
+   compatible = "fixed-clock";
+   clock-frequency = <2600>;
+   };
+   vctcxo_2: vctcxo_2 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&vctcxo>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   vctcxo_4: vctcxo_4 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&vctcxo_2>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   usb_pll: usb_pll {
+   #clock-cells = <0>;
+   compatible = "fixed-clock";
+   clock-frequency = <48000>;
+   };
+   pll1: pll1 {
+   #clock-cells = <0>;
+   compatible = "fixed-clock";
+   clock-frequency = <62400>;
+   };
+   pll1_2: pll1_2 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   pll1_4: pll1_4 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1_2>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   pll1_8: pll1_8 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1_4>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   pll1_16: pll1_16 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1_8>;
+   clock-div = <2>;
+   clock-mult = <1>;
+   };
+   pll1_20: pll1_20 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1_4>;
+   clock-div = <5>;
+   clock-mult = <1>;
+   };
+   pll1_3: pll1_3 {
+   #clock-cells = <0>;
+   compatible = "fixed-factor-clock";
+   clocks = <&pll1>;
+ 

Re: [patch 09/26] arm: mmp: Remove pointless fiddling with irq internals

2014-02-26 Thread Chao Xie
On Mon, Feb 24, 2014 at 7:31 PM, Thomas Gleixner  wrote:
> On Mon, 24 Feb 2014, Haojian Zhuang wrote:
>
>> On Mon, Feb 24, 2014 at 2:07 PM, Chao Xie  wrote:
>> > On Mon, Feb 24, 2014 at 7:17 AM, Uwe Kleine-König
>> >  wrote:
>> >> Hi Thomas,
>> >>
>> >> On Sun, Feb 23, 2014 at 09:40:13PM -, Thomas Gleixner wrote:
>> >>> The pm-mmp2 and pm-pxa910 power management related irq_set_wake
>> >>> callbacks fiddle pointlessly with the irq actions for no reason except
>> >>> for lack of understanding how the wakeup mechanism works.
>> >>>
>> >>> On supsend the core disables all interrupts lazily, i.e. it does not
>> >>> mask them at the irq controller level. So any interrupt which is
>> >>> firing during supsend will mark the corresponding interrupt line as
>> >> s/supsend/suspend/ twice
>> >>> pending. Just before the core powers down it checks whether there are
>> >>> interrupts pending from interrupt lines which are marked as wakeup
>> >>> sources and if so it aborts the resume and resends the interrupts.
>> >> It's the suspend that is aborted, not the resume.
>> >>
>> >> Other than that your change looks fine.
>> >>
>> > For pxa910 and MMP2, wake up source only wake up the AP subsystem.
>> > The AP subsystem includes the APMU(AP Power Mangament Unit) and cores.
>> > Now the core is still powered down. APMU will check the interrupt
>> > lines, and find
>> > that there are interrupt pending, it will power on the cores.
>> > So if the irq is disabled, even wake up source can wake up AP subsystem, 
>> > but the
>> > core is still powered down. It will not be powered up by APMU.
>> >
>>
>> Yes, suspend/resume can't work if the above code is removed.
>>
>> Interrupt source (logic AND with interrupt mask register) is connected
>> to MPMU as
>> wakeup source. If the interrupt is disabled, there's no wakeup source event.
>>
>> And APMU is waken up by MPMU.
>>
>> So please don't remove the above code. We must keep these interrupt lines 
>> active
>> to wake up the whole system.
>
> They are kept active at the interrupt controller level. You just
> refuse to understand how the internals of the interrupt subsystem
> work.
>
If no irq_disable callback is hooked, when do irq_disable, it will not
actually disable
the interrupt, it will depend on next time when the irq happens, the
handler will first mask
the interrupt as this interrupt never happens.
So after system suspended, the interrupt happens, but the device
driver will not recieve this interrupt
because it is masked.
It results in that the device driver miss a important interrupt which
related to something need to be
handled. If user application for example android has power managment
daemon. It will find that nothing
to handle, it will make the system enter suspend again.

> And even if you would need this flag, then fiddling with the irq desc
> internals is a big NONO. There is a proper way to hand that in.
>

So can you suggest the proper way to handle it? Thanks.

> Thanks,
>
> tglx
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [patch 09/26] arm: mmp: Remove pointless fiddling with irq internals

2014-02-23 Thread Chao Xie
On Mon, Feb 24, 2014 at 7:17 AM, Uwe Kleine-König
 wrote:
> Hi Thomas,
>
> On Sun, Feb 23, 2014 at 09:40:13PM -, Thomas Gleixner wrote:
>> The pm-mmp2 and pm-pxa910 power management related irq_set_wake
>> callbacks fiddle pointlessly with the irq actions for no reason except
>> for lack of understanding how the wakeup mechanism works.
>>
>> On supsend the core disables all interrupts lazily, i.e. it does not
>> mask them at the irq controller level. So any interrupt which is
>> firing during supsend will mark the corresponding interrupt line as
> s/supsend/suspend/ twice
>> pending. Just before the core powers down it checks whether there are
>> interrupts pending from interrupt lines which are marked as wakeup
>> sources and if so it aborts the resume and resends the interrupts.
> It's the suspend that is aborted, not the resume.
>
> Other than that your change looks fine.
>
For pxa910 and MMP2, wake up source only wake up the AP subsystem.
The AP subsystem includes the APMU(AP Power Mangament Unit) and cores.
Now the core is still powered down. APMU will check the interrupt
lines, and find
that there are interrupt pending, it will power on the cores.
So if the irq is disabled, even wake up source can wake up AP subsystem, but the
core is still powered down. It will not be powered up by APMU.


> Uwe
>
> --
> Pengutronix e.K.   | Uwe Kleine-König|
> Industrial Linux Solutions | http://www.pengutronix.de/  |
>
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] mfd: 88pm800: Fix the bug that pdata may be NULL

2013-09-01 Thread Chao Xie
On Fri, Aug 30, 2013 at 8:30 PM, Samuel Ortiz  wrote:
> Hi Xie,
>
> On Tue, Aug 27, 2013 at 02:11:58PM +0800, Chao Xie wrote:
>> On Tue, Aug 20, 2013 at 9:40 AM, Samuel Ortiz  wrote:
>> > Hi Xie,
>> >
>> > On Sun, Aug 18, 2013 at 09:27:54PM -0400, Chao Xie wrote:
>> >> User pass platform data to device, and platform data may be
>> >> NULL.
>> > In which case do you get that ? With DT ?
>> > Should rtc_init fail when pdata is NULL ?
>> >
>> > You need to explain that, be it only for us to know if it's a critical
>> > fix or not.
>> >
>> Sorry for late response.
>> If pdata is NULL, the driver will fail.
> The question is: Why would pdata be NULL ? If there's a fundamental
> issue you're hiding with this patch, you probably want to fix the real
> problem instead.
>
Maybe i do not explain it clearly.
The error is detected y some software checking tool.
Pdata is passed from dev->platform_data.
If the user pass the dev->platform_data to be NULL, at least mfd device driver
need detect it, and reject it if it is not accpetable like return -EINVAL.
Then the following probing code will not cause kernel panic if we
access pdata->xxx.

> Cheers,
> Samuel.
>
> --
> Intel Open Source Technology Centre
> http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] mfd: 88pm800: Fix the bug that pdata may be NULL

2013-08-26 Thread Chao Xie
On Tue, Aug 20, 2013 at 9:40 AM, Samuel Ortiz  wrote:
> Hi Xie,
>
> On Sun, Aug 18, 2013 at 09:27:54PM -0400, Chao Xie wrote:
>> User pass platform data to device, and platform data may be
>> NULL.
> In which case do you get that ? With DT ?
> Should rtc_init fail when pdata is NULL ?
>
> You need to explain that, be it only for us to know if it's a critical
> fix or not.
>
Sorry for late response.
If pdata is NULL, the driver will fail. So the error check should be done at
the beginning of probe.
If (!pdata)
   return -EINVAL;

Is that OK?

> Cheers,
> Samuel.
>
> --
> Intel Open Source Technology Centre
> http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/2] mfd: 88pm8xx: platform data bug fix

2013-08-18 Thread Chao Xie
The patches fix the bug that pdata may be NULL when driver uses it.

Chao Xie (2):
  mfd: 88pm800: Fix the bug that pdata may be NULL
  mfd: 88pm805: Fix the bug that pdata may be NULL

 drivers/mfd/88pm800.c |   10 ++
 drivers/mfd/88pm805.c |2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] mfd: 88pm800: Fix the bug that pdata may be NULL

2013-08-18 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm800.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 6c95483..d4d272f 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -333,9 +333,11 @@ static int device_rtc_init(struct pm80x_chip *chip,
 {
int ret;
 
-   rtc_devs[0].platform_data = pdata->rtc;
-   rtc_devs[0].pdata_size =
-   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   if (pdata) {
+   rtc_devs[0].platform_data = pdata->rtc;
+   rtc_devs[0].pdata_size =
+   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   }
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
  ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
if (ret) {
@@ -578,7 +580,7 @@ static int pm800_probe(struct i2c_client *client,
goto err_device_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
return 0;
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] mfd: 88pm805: Fix the bug that pdata may be NULL

2013-08-18 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm805.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 5216022..57135bb 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -243,7 +243,7 @@ static int pm805_probe(struct i2c_client *client,
goto err_805_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
 err_805_init:
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] mfd: 88pm800: add device tree support

2013-08-15 Thread Chao Xie
On Thu, Aug 15, 2013 at 6:07 PM, Lee Jones  wrote:
>> >> +Optional parent device properties:
>> >> +- marvell,88pm800-irq-write-clear: inicates whether interrupt status is 
>> >> cleared by write
>> >> +- marvell,88pm800-battery-detection: indicats whether need 88pm800 to 
>> >> support battery
>> >> + detection or not.
>> >
>> > Not sure what these are. This is why you need to CC the Device Tree
>> > guys.
>> >
>> It is the 88pm805's own configuration.
>> 88pm800-irq-write-clear: when irq happens, the status register is
>> write clear or read clear.
>> 88pm800-battery-detection: whether the battery is connected to chip.
>> It means that whether
>> the chip be aware of battery or not.
>
> As you are adding vendor specific bindings, you need to Cc the Device
> Tree mailing list.
>
>> >> + if (IS_ENABLED(CONFIG_OF)) {
>> >> + if (!pdata) {
>> >> + pdata = devm_kzalloc(&client->dev,
>> >> +  sizeof(*pdata), GFP_KERNEL);
>> >> + if (!pdata)
>> >> + return -ENOMEM;
>> >> + }
>> >> + ret = pm800_dt_init(node, &client->dev, pdata);
>> >> + if (ret)
>> >> + return ret;
>> >> + } else if (!pdata) {
>> >> + return -EINVAL;
>> >> + }
>> >
>> > Replace with:
>> >
>> > if (!pdata) {
>> > if (node)
>> > /*  populate pdata with DT  */
>> > else
>> > return -EINVAL;
>> > }
>> >
>> The orignial code will cover the following situation.
>> 1. DT enabled, and user pass pdata
>> 2. DT enabled, but user do not pass pdata
>> 3. DT disabled, user pass pdata
>> 4. DT disabled, user do not pass pdata.
>>
>> 88pm805 has a callback for config the it based on platform requirment.
>> I do not want to remove this callback now, because it includes so many
>> configurations.
>> So i allow user can pass pdata with callback if the platform needs to
>> configure the chip.
>
> Mixing DT with pdata is a bad idea. If you need to pass a call-back
> pointer, then _only_ use pdata i.e. get all of your platform specific
> information from pdata, rather than just over-writing sections of it
> with information retrieved from Device Tree.
>
> So:
>
> If pdata  - use pdata and ignore DT completely
> If !pdata:
>If DT  - use DT
>If !DT - return -EINVAL
>
> Out of interest, what does your call-back do?
>
Without the callback, the soc still can work.
The callback does job relates to power saving and CP's requirment.
1. LPM configure for the chip based on AP/CP's requriment.
2. 88pm800 OSC configuration
3. Some output pin configuration of 88pm800, for example reset_out_n pin

I want to abstract the callback step by step, so the first step are the patches
that enable DT first.

For the patch 0001 and 0002 are fixes, so if these two patches are all
right, can you
merge them? Then i will submit the 2 DT related patches again with cc
to device tree maillist.

Thanks.

> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/4] mfd: 88pm800: add device tree support

2013-08-14 Thread Chao Xie
>> +* Marvell 88PM800 Power Management IC
>> +
>> +Required parent device properties:
>> +- compatible : "marvell,88pm800"
>> +- reg : the I2C slave address for the 88pm800 chip
>> +- interrupts : IRQ line for the 88pm800 chip
>> +- interrupt-controller: describes the 88pm800 as an interrupt controller 
>> (has its own domain)
>
> You don't need "(has its own domain)", as this is expected.
>
Will remove it.

>> +- #interrupt-cells : should be 1.
>> + - The cell is the 88pm800 local IRQ number
>
> No need for the last line.
>
will remove it.

>> +Optional parent device properties:
>> +- marvell,88pm800-irq-write-clear: inicates whether interrupt status is 
>> cleared by write
>> +- marvell,88pm800-battery-detection: indicats whether need 88pm800 to 
>> support battery
>> + detection or not.
>
> Not sure what these are. This is why you need to CC the Device Tree
> guys.
>
It is the 88pm805's own configuration.
88pm800-irq-write-clear: when irq happens, the status register is
write clear or read clear.
88pm800-battery-detection: whether the battery is connected to chip.
It means that whether
the chip be aware of battery or not.

>> +88pm800 consists of a large and varied group of sub-devices:
>
> Really? Or just 3?
>
just 3.

>> +DeviceSupply NamesDescription
>> +-----
>> +88pm80x-onkey:   : On key
>> +88pm80x-rtc  :   : RTC
>> +88pm80x-regulator:   : Regulators
>
> If more than 3 please list them.
>
>> +Example:
>> +
>> + pmic: 88pm800@30 {
>> + compatible = "marvell,88pm800";
>> + reg = <0x30>;
>> + interrupts = <0 4 0x4>;
>
> Use the defines in include/dt-bindings.
>
Will change it

>> + };
>> diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
>> + !of_property_read_bool(np, "marvell,88pm800-irq-write-clear");
>> + pdata->batt_det =
>> + of_property_read_bool(np, "marvell,88pm800-battery-detection");
>> +
>> + return 0;
>> +}
>> +
>> +
>
> Why two /n's?
>
Will remove addtional one.

>>  static int pm800_probe(struct i2c_client *client,
>>const struct i2c_device_id *id)
>>  {
>>   int ret = 0;
>>   struct pm80x_chip *chip;
>>   struct pm80x_platform_data *pdata = client->dev.platform_data;
>> + struct device_node *node = client->dev.of_node;
>>   struct pm80x_subchip *subchip;
>>
>> + if (IS_ENABLED(CONFIG_OF)) {
>> + if (!pdata) {
>> + pdata = devm_kzalloc(&client->dev,
>> +  sizeof(*pdata), GFP_KERNEL);
>> + if (!pdata)
>> + return -ENOMEM;
>> + }
>> + ret = pm800_dt_init(node, &client->dev, pdata);
>> + if (ret)
>> + return ret;
>> + } else if (!pdata) {
>> + return -EINVAL;
>> + }
>
> Replace with:
>
> if (!pdata) {
> if (node)
> /*  populate pdata with DT  */
> else
> return -EINVAL;
> }
>
The orignial code will cover the following situation.
1. DT enabled, and user pass pdata
2. DT enabled, but user do not pass pdata
3. DT disabled, user pass pdata
4. DT disabled, user do not pass pdata.

88pm805 has a callback for config the it based on platform requirment.
I do not want to remove this callback now, because it includes so many
configurations.
So i allow user can pass pdata with callback if the platform needs to
configure the chip.

>> + /*
>> +  * RTC in pmic can run even the core is powered off, and user can set
>> +  * alarm in RTC. When the alarm is time out, the PMIC will power up
>> +  * the core, and the whole system will boot up. When PMIC driver is
>> +  * probed, it will read out some register to find out whether this
>> +  * boot is caused by RTC timeout or not, and it need pass this
>> +  * information to RTC driver.
>> +  * So we need rtc platform data to be existed to pass this information.
>> +  */
>> + if (!pdata->rtc) {
>> + pdata->rtc = devm_kzalloc(&client->dev,
>> +   sizeof(*(pdata->rtc)), GFP_KERNEL);
>> + if (!pdata->rtc)
>> + return -ENOMEM;
>> + }
>> +
>>   ret = pm80x_init(client);
>>   if (ret) {
>>   dev_err(&client->dev, "pm800_init fail\n");
>> @@ -612,6 +666,7 @@ static struct i2c_driver pm800_driver = {
>>   .name = "88PM800",
>>   .owner = THIS_MODULE,
>>   .pm = &pm80x_pm_ops,
>> + .of_match_table = of_match_ptr(pm80x_dt_ids),
>>   },
>>   .probe = pm800_probe,
>>   .remove = pm800_remove,
>
> --
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> Linaro.

[PATCH 3/4] mfd: 88pm800: add device tree support

2013-08-14 Thread Chao Xie
Signed-off-by: Chao Xie 
---
 Documentation/devicetree/bindings/mfd/88pm800.c |   55 +++
 drivers/mfd/88pm800.c   |   55 +++
 2 files changed, 110 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.c

diff --git a/Documentation/devicetree/bindings/mfd/88pm800.c 
b/Documentation/devicetree/bindings/mfd/88pm800.c
new file mode 100644
index 000..2299752
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/88pm800.c
@@ -0,0 +1,55 @@
+* Marvell 88PM800 Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800"
+- reg : the I2C slave address for the 88pm800 chip
+- interrupts : IRQ line for the 88pm800 chip
+- interrupt-controller: describes the 88pm800 as an interrupt controller (has 
its own domain)
+- #interrupt-cells : should be 1.
+   - The cell is the 88pm800 local IRQ number
+
+Optional parent device properties:
+- marvell,88pm800-irq-write-clear: inicates whether interrupt status is 
cleared by write
+- marvell,88pm800-battery-detection: indicats whether need 88pm800 to support 
battery
+   detection or not.
+
+88pm800 consists of a large and varied group of sub-devices:
+
+Device  Supply NamesDescription
+--  ---
+88pm80x-onkey  :   : On key
+88pm80x-rtc:   : RTC
+88pm80x-regulator  :   : Regulators
+
+Example:
+
+   pmic: 88pm800@30 {
+   compatible = "marvell,88pm800";
+   reg = <0x30>;
+   interrupts = <0 4 0x4>;
+   interrupt-parent = <&gic>;
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   marvell,88pm800-irq-write-clr;
+
+   regulators {
+   compatible = "marvell,88pm80x-regulator";
+
+   BUCK1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   LDO1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   };
+   rtc {
+   compatible = "marvell,88pm80x-rtc";
+   };
+   };
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index d4d272f..07a24e2 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Interrupt Registers */
 #define PM800_INT_STATUS1  (0x05)
@@ -121,6 +122,12 @@ static const struct i2c_device_id pm80x_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
 
+static const struct of_device_id pm80x_dt_ids[] = {
+   { .compatible = "marvell,88pm800", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, pm80x_dt_ids);
+
 static struct resource rtc_resources[] = {
{
 .name = "88pm80x-rtc",
@@ -133,6 +140,7 @@ static struct resource rtc_resources[] = {
 static struct mfd_cell rtc_devs[] = {
{
 .name = "88pm80x-rtc",
+.of_compatible = "marvell,88pm80x-rtc",
 .num_resources = ARRAY_SIZE(rtc_resources),
 .resources = &rtc_resources[0],
 .id = -1,
@@ -151,6 +159,7 @@ static struct resource onkey_resources[] = {
 static struct mfd_cell onkey_devs[] = {
{
 .name = "88pm80x-onkey",
+.of_compatible = "marvell,88pm80x-onkey",
 .num_resources = 1,
 .resources = &onkey_resources[0],
 .id = -1,
@@ -160,6 +169,7 @@ static struct mfd_cell onkey_devs[] = {
 static struct mfd_cell regulator_devs[] = {
{
 .name = "88pm80x-regulator",
+.of_compatible = "marvell,88pm80x-regulator",
 .id = -1,
},
 };
@@ -538,14 +548,58 @@ out:
return ret;
 }
 
+static int pm800_dt_init(struct device_node *np,
+struct device *dev,
+struct pm80x_platform_data *pdata)
+{
+   pdata->irq_mode =
+   !of_property_read_bool(np, "marvell,88pm800-irq-write-clear");
+   pdata->batt_det =
+   of_property_read_bool(np, "marvell,88pm800-battery-detection");
+
+   return 0;
+}
+
+
 static int pm800_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
int ret = 0;
struct pm

[PATCH 0/4] mfd: 88pn80x: bug fix and device tree support

2013-08-14 Thread Chao Xie
There are 4 patches.
1. Bug fix.
  mfd: 88pm800: Fix the bug that pdata may be NULL
  mfd: 88pm805: Fix the bug that pdata may be NULL
  Above patches fix the bug that pdata may be NULL when driver uses it.

2. Device tree support
  mfd: 88pm800: add device tree support
  mfd: 88pm805: add device tree support
  Add device tree support for 88pm800 and 88pm805

Chao Xie (4):
  mfd: 88pm800: Fix the bug that pdata may be NULL
  mfd: 88pm805: Fix the bug that pdata may be NULL
  mfd: 88pm800: add device tree support
  mfd: 88pm805: add device tree support

 Documentation/devicetree/bindings/mfd/88pm800.c |   55 +++
 Documentation/devicetree/bindings/mfd/88pm805.c |   15 +
 drivers/mfd/88pm800.c   |   65 +--
 drivers/mfd/88pm805.c   |   10 +++-
 4 files changed, 140 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.c
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm805.c

-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/4] mfd: 88pm805: Fix the bug that pdata may be NULL

2013-08-14 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm805.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 5216022..57135bb 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -243,7 +243,7 @@ static int pm805_probe(struct i2c_client *client,
goto err_805_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
 err_805_init:
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] mfd: 88pm800: Fix the bug that pdata may be NULL

2013-08-14 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm800.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 6c95483..d4d272f 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -333,9 +333,11 @@ static int device_rtc_init(struct pm80x_chip *chip,
 {
int ret;
 
-   rtc_devs[0].platform_data = pdata->rtc;
-   rtc_devs[0].pdata_size =
-   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   if (pdata) {
+   rtc_devs[0].platform_data = pdata->rtc;
+   rtc_devs[0].pdata_size =
+   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   }
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
  ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
if (ret) {
@@ -578,7 +580,7 @@ static int pm800_probe(struct i2c_client *client,
goto err_device_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
return 0;
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] mfd: 88pm805: add device tree support

2013-08-14 Thread Chao Xie
Signed-off-by: Chao Xie 
---
 Documentation/devicetree/bindings/mfd/88pm805.c |   15 +++
 drivers/mfd/88pm805.c   |8 
 2 files changed, 23 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm805.c

diff --git a/Documentation/devicetree/bindings/mfd/88pm805.c 
b/Documentation/devicetree/bindings/mfd/88pm805.c
new file mode 100644
index 000..f3878a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/88pm805.c
@@ -0,0 +1,15 @@
+* Marvell 88PM805 Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm805"
+- reg : the I2C slave address for the 88pm805 chip
+- interrupts : IRQ line for the 88pm805 chip
+
+Example:
+
+   pmic: 88pm805@38 {
+   compatible = "marvell,88pm805";
+   reg = <0x38>;
+   interrupt-parent = <&gpio1>;
+   interrupts = <124 0x1>;
+   };
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 57135bb..f6e0e55 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const struct i2c_device_id pm80x_id_table[] = {
{"88PM805", 0},
@@ -35,6 +36,12 @@ static const struct i2c_device_id pm80x_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
 
+static const struct of_device_id pm80x_dt_ids[] = {
+   { .compatible = "marvell,88pm805", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, pm80x_dt_ids);
+
 /* Interrupt Number in 88PM805 */
 enum {
PM805_IRQ_LDO_OFF,  /*0 */
@@ -269,6 +276,7 @@ static struct i2c_driver pm805_driver = {
.name = "88PM805",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
+   .of_match_table = of_match_ptr(pm80x_dt_ids),
},
.probe = pm805_probe,
.remove = pm805_remove,
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/4] mfd: 88pm800: Fix the bug that pdata may be NULL

2013-07-29 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm800.c |   10 ++
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index 6c95483..d4d272f 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -333,9 +333,11 @@ static int device_rtc_init(struct pm80x_chip *chip,
 {
int ret;
 
-   rtc_devs[0].platform_data = pdata->rtc;
-   rtc_devs[0].pdata_size =
-   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   if (pdata) {
+   rtc_devs[0].platform_data = pdata->rtc;
+   rtc_devs[0].pdata_size =
+   pdata->rtc ? sizeof(struct pm80x_rtc_pdata) : 0;
+   }
ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
  ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
if (ret) {
@@ -578,7 +580,7 @@ static int pm800_probe(struct i2c_client *client,
goto err_device_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
return 0;
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 4/4] mfd: 88pm805: add device tree support

2013-07-29 Thread Chao Xie
Signed-off-by: Chao Xie 
---
 Documentation/devicetree/bindings/mfd/88pm805.c |   15 +++
 drivers/mfd/88pm805.c   |8 
 2 files changed, 23 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm805.c

diff --git a/Documentation/devicetree/bindings/mfd/88pm805.c 
b/Documentation/devicetree/bindings/mfd/88pm805.c
new file mode 100644
index 000..f3878a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/88pm805.c
@@ -0,0 +1,15 @@
+* Marvell 88PM805 Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm805"
+- reg : the I2C slave address for the 88pm805 chip
+- interrupts : IRQ line for the 88pm805 chip
+
+Example:
+
+   pmic: 88pm805@38 {
+   compatible = "marvell,88pm805";
+   reg = <0x38>;
+   interrupt-parent = <&gpio1>;
+   interrupts = <124 0x1>;
+   };
diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 57135bb..f6e0e55 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -28,6 +28,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static const struct i2c_device_id pm80x_id_table[] = {
{"88PM805", 0},
@@ -35,6 +36,12 @@ static const struct i2c_device_id pm80x_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
 
+static const struct of_device_id pm80x_dt_ids[] = {
+   { .compatible = "marvell,88pm805", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, pm80x_dt_ids);
+
 /* Interrupt Number in 88PM805 */
 enum {
PM805_IRQ_LDO_OFF,  /*0 */
@@ -269,6 +276,7 @@ static struct i2c_driver pm805_driver = {
.name = "88PM805",
.owner = THIS_MODULE,
.pm = &pm80x_pm_ops,
+   .of_match_table = of_match_ptr(pm80x_dt_ids),
},
.probe = pm805_probe,
.remove = pm805_remove,
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 0/4] mfd: 88pn80x: bug fix and device tree support

2013-07-29 Thread Chao Xie
There are 4 patches.
1. Bug fix.
  mfd: 88pm800: Fix the bug that pdata may be NULL
  mfd: 88pm805: Fix the bug that pdata may be NULL
  Above patches fix the bug that pdata may be NULL when driver uses it.

2. Device tree support
  mfd: 88pm800: add device tree support
  mfd: 88pm805: add device tree support
  Add device tree support for 88pm800 and 88pm805

Chao Xie (4):
  mfd: 88pm800: Fix the bug that pdata may be NULL
  mfd: 88pm805: Fix the bug that pdata may be NULL
  mfd: 88pm800: add device tree support
  mfd: 88pm805: add device tree support

 Documentation/devicetree/bindings/mfd/88pm800.c |   55 +++
 Documentation/devicetree/bindings/mfd/88pm805.c |   15 +
 drivers/mfd/88pm800.c   |   65 +--
 drivers/mfd/88pm805.c   |   10 +++-
 4 files changed, 140 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.c
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm805.c

-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/4] mfd: 88pm805: Fix the bug that pdata may be NULL

2013-07-29 Thread Chao Xie
User pass platform data to device, and platform data may be
NULL. Add the check for pdata.

Signed-off-by: Chao Xie 
---
 drivers/mfd/88pm805.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mfd/88pm805.c b/drivers/mfd/88pm805.c
index 5216022..57135bb 100644
--- a/drivers/mfd/88pm805.c
+++ b/drivers/mfd/88pm805.c
@@ -243,7 +243,7 @@ static int pm805_probe(struct i2c_client *client,
goto err_805_init;
}
 
-   if (pdata->plat_config)
+   if (pdata && pdata->plat_config)
pdata->plat_config(chip, pdata);
 
 err_805_init:
-- 
1.7.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/4] mfd: 88pm800: add device tree support

2013-07-29 Thread Chao Xie
Signed-off-by: Chao Xie 
---
 Documentation/devicetree/bindings/mfd/88pm800.c |   55 +++
 drivers/mfd/88pm800.c   |   55 +++
 2 files changed, 110 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/88pm800.c

diff --git a/Documentation/devicetree/bindings/mfd/88pm800.c 
b/Documentation/devicetree/bindings/mfd/88pm800.c
new file mode 100644
index 000..2299752
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/88pm800.c
@@ -0,0 +1,55 @@
+* Marvell 88PM800 Power Management IC
+
+Required parent device properties:
+- compatible : "marvell,88pm800"
+- reg : the I2C slave address for the 88pm800 chip
+- interrupts : IRQ line for the 88pm800 chip
+- interrupt-controller: describes the 88pm800 as an interrupt controller (has 
its own domain)
+- #interrupt-cells : should be 1.
+   - The cell is the 88pm800 local IRQ number
+
+Optional parent device properties:
+- marvell,88pm800-irq-write-clear: inicates whether interrupt status is 
cleared by write
+- marvell,88pm800-battery-detection: indicats whether need 88pm800 to support 
battery
+   detection or not.
+
+88pm800 consists of a large and varied group of sub-devices:
+
+Device  Supply NamesDescription
+--  ---
+88pm80x-onkey  :   : On key
+88pm80x-rtc:   : RTC
+88pm80x-regulator  :   : Regulators
+
+Example:
+
+   pmic: 88pm800@30 {
+   compatible = "marvell,88pm800";
+   reg = <0x30>;
+   interrupts = <0 4 0x4>;
+   interrupt-parent = <&gic>;
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   marvell,88pm800-irq-write-clr;
+
+   regulators {
+   compatible = "marvell,88pm80x-regulator";
+
+   BUCK1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   LDO1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   };
+   rtc {
+   compatible = "marvell,88pm80x-rtc";
+   };
+   };
diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c
index d4d272f..07a24e2 100644
--- a/drivers/mfd/88pm800.c
+++ b/drivers/mfd/88pm800.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Interrupt Registers */
 #define PM800_INT_STATUS1  (0x05)
@@ -121,6 +122,12 @@ static const struct i2c_device_id pm80x_id_table[] = {
 };
 MODULE_DEVICE_TABLE(i2c, pm80x_id_table);
 
+static const struct of_device_id pm80x_dt_ids[] = {
+   { .compatible = "marvell,88pm800", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, pm80x_dt_ids);
+
 static struct resource rtc_resources[] = {
{
 .name = "88pm80x-rtc",
@@ -133,6 +140,7 @@ static struct resource rtc_resources[] = {
 static struct mfd_cell rtc_devs[] = {
{
 .name = "88pm80x-rtc",
+.of_compatible = "marvell,88pm80x-rtc",
 .num_resources = ARRAY_SIZE(rtc_resources),
 .resources = &rtc_resources[0],
 .id = -1,
@@ -151,6 +159,7 @@ static struct resource onkey_resources[] = {
 static struct mfd_cell onkey_devs[] = {
{
 .name = "88pm80x-onkey",
+.of_compatible = "marvell,88pm80x-onkey",
 .num_resources = 1,
 .resources = &onkey_resources[0],
 .id = -1,
@@ -160,6 +169,7 @@ static struct mfd_cell onkey_devs[] = {
 static struct mfd_cell regulator_devs[] = {
{
 .name = "88pm80x-regulator",
+.of_compatible = "marvell,88pm80x-regulator",
 .id = -1,
},
 };
@@ -538,14 +548,58 @@ out:
return ret;
 }
 
+static int pm800_dt_init(struct device_node *np,
+struct device *dev,
+struct pm80x_platform_data *pdata)
+{
+   pdata->irq_mode =
+   !of_property_read_bool(np, "marvell,88pm800-irq-write-clear");
+   pdata->batt_det =
+   of_property_read_bool(np, "marvell,88pm800-battery-detection");
+
+   return 0;
+}
+
+
 static int pm800_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
int ret = 0;
struct pm

[PATCH V4] regulator: 88pm800: add regulator driver for 88pm800

2013-07-17 Thread Chao Xie
Add the regulator driver for PMIC 88pm800 including device tree
support.
88pm800 is an I2C-based power-management IC containing voltage
regulators, a real-time clock, and some general purpose ADC devices,

Signed-off-by: Yi Zhang 
Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/regulator/88pm800.txt  |   38 ++
 drivers/regulator/88pm800.c|  377 
 drivers/regulator/Kconfig  |   10 +
 drivers/regulator/Makefile |1 +
 4 files changed, 426 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/88pm800.txt
 create mode 100644 drivers/regulator/88pm800.c

diff --git a/Documentation/devicetree/bindings/regulator/88pm800.txt 
b/Documentation/devicetree/bindings/regulator/88pm800.txt
new file mode 100644
index 000..e8a54c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/88pm800.txt
@@ -0,0 +1,38 @@
+Marvell 88PM800 regulator
+
+Required properties:
+- compatible: "marvell,88pm800"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+The valid names for regulators are:
+
+  buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7,
+  ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, 
ldo19
+
+Example:
+
+   pmic: 88pm800@31 {
+   compatible = "marvell,88pm800";
+   reg = <0x31>;
+
+   regulators {
+   buck1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   ldo1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <1500>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+...
+   };
+   };
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
new file mode 100644
index 000..a7d962f
--- /dev/null
+++ b/drivers/regulator/88pm800.c
@@ -0,0 +1,377 @@
+/*
+ * Regulators driver for Marvell 88PM800
+ *
+ * Copyright (C) 2012 Marvell International Ltd.
+ * Joseph(Yossi) Hanin 
+ * Yi Zhang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* LDO1 with DVC[0..3] */
+#define PM800_LDO1_VOUT(0x08) /* VOUT1 */
+#define PM800_LDO1_VOUT_2  (0x09)
+#define PM800_LDO1_VOUT_3  (0x0A)
+#define PM800_LDO2_VOUT(0x0B)
+#define PM800_LDO3_VOUT(0x0C)
+#define PM800_LDO4_VOUT(0x0D)
+#define PM800_LDO5_VOUT(0x0E)
+#define PM800_LDO6_VOUT(0x0F)
+#define PM800_LDO7_VOUT(0x10)
+#define PM800_LDO8_VOUT(0x11)
+#define PM800_LDO9_VOUT(0x12)
+#define PM800_LDO10_VOUT   (0x13)
+#define PM800_LDO11_VOUT   (0x14)
+#define PM800_LDO12_VOUT   (0x15)
+#define PM800_LDO13_VOUT   (0x16)
+#define PM800_LDO14_VOUT   (0x17)
+#define PM800_LDO15_VOUT   (0x18)
+#define PM800_LDO16_VOUT   (0x19)
+#define PM800_LDO17_VOUT   (0x1A)
+#define PM800_LDO18_VOUT   (0x1B)
+#define PM800_LDO19_VOUT   (0x1C)
+
+/* BUCK1 with DVC[0..3] */
+#define PM800_BUCK1(0x3C)
+#define PM800_BUCK1_1  (0x3D)
+#define PM800_BUCK1_2  (0x3E)
+#define PM800_BUCK1_3  (0x3F)
+#define PM800_BUCK2(0x40)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK4(0x42)
+#define PM800_BUCK4_1  (0x43)
+#define PM800_BUCK4_2  (0x44)
+#define PM800_BUCK4_3  (0x45)
+#define PM800_BUCK5(0x46)
+
+#define PM800_BUCK_ENA (0x50)
+#define PM800_LDO_ENA1_1   (0x51)
+#define PM800_LDO_ENA1_2   (0x52)
+#define PM800_LDO_ENA1_3   (0x53)
+
+#define PM800_LDO_ENA2_1   (0x56)
+#define PM800_LDO_ENA2_2   (0x57)
+#define PM800_LDO_ENA2_3   (0x58)
+
+#define PM800_BUCK1_MISC1  (0x78)
+#define PM800_BUCK3_MISC1  (0x7E)
+#define PM800_BUCK4_MISC1  (0x81)
+#define PM800_BUCK5_MISC1  (0x84)
+
+struct pm

RE: [PATCH 1/2] regulator: 88pm800: Add missing config.of_node setting for regulator register

2013-06-30 Thread Chao Xie
> -Original Message-
> From: Mark Brown [mailto:broo...@kernel.org] 
> Sent: Friday, June 28, 2013 9:50 PM
> To: Axel Lin
> Cc: Yi Zhang; Chao Xie; Liam Girdwood; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH 1/2] regulator: 88pm800: Add missing config.of_node 
> setting for regulator register
> 
> On Fri, Jun 28, 2013 at 09:32:34PM +0800, Axel Lin wrote:
>> Signed-off-by: Axel Lin 
>> ---
>> Hi,
>> Seems current code also needs this patch:
>>  mfd: 88pm800: add regulator sub device [1]
>
> Oh dear.  I've just reverted the patch (my build testing hadn't caught up 
> yet).  Chao, please resubmit for v3.12 - when you submit patches you need to 
> either ensure it applies and builds on the relevant branch or mention the 
> dependencies so that the build doesn't break.  In this case sending the 
> regulator driver and matching MFD changes as a single patch series would have 
> been the normal thing.
> 
> Please incorporate Axel's feedback into any resubmission.
It is my mistake. I should add "regulator_data" and "num_regulator" with 
regulator driver.
I have seen that mfd: 88pm800: add regulator sub device is already merged into 
Linux-next. So you mean that I need wait for 3.11 to release, then resubmit the 
regulator patch?
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3] regulator: 88pm800: add regulator driver for 88pm800

2013-06-30 Thread Chao Xie
On Fri, Jun 28, 2013 at 7:56 PM, Mark Brown  wrote:
> On Thu, Jun 27, 2013 at 04:46:04AM -0400, Chao Xie wrote:
>> Add the regulator driver for PMIC 88pm800 including device tree
>> support.
>> 88pm800 is an I2C-based power-management IC containing voltage
>> regulators, a real-time clock, and some general purpose ADC devices,
>
> Applied, thanks.  Your table based list and map voltage functions
> actually look very generic so should be added to the core but I'll do
> that myself as a refactoring so this can go into v3.11.
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] ARM: mmp: bring up pxa988 with device tree support

2013-06-27 Thread Chao Xie
hi, Arnd
SCU registers mapping can not be added to fixmap.
As Russell's suggested, the SCU registers can be mapped to 0x1000
with single page.
Beause the mapping is not a fix map, and i can not use the static
functions in arch/arm/mm/mm.h, I still have to use static mapping for
SCU registers by iotable_init.
So what is your idea about how to make the SCU registers mapping to be
a peice of common code?
Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V3] regulator: 88pm800: add regulator driver for 88pm800

2013-06-27 Thread Chao Xie
Add the regulator driver for PMIC 88pm800 including device tree
support.
88pm800 is an I2C-based power-management IC containing voltage
regulators, a real-time clock, and some general purpose ADC devices,

Signed-off-by: Yi Zhang 
Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/regulator/88pm800.txt  |   38 ++
 drivers/regulator/88pm800.c|  442 
 drivers/regulator/Kconfig  |   10 +
 drivers/regulator/Makefile |1 +
 4 files changed, 491 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/88pm800.txt
 create mode 100644 drivers/regulator/88pm800.c

diff --git a/Documentation/devicetree/bindings/regulator/88pm800.txt 
b/Documentation/devicetree/bindings/regulator/88pm800.txt
new file mode 100644
index 000..e8a54c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/88pm800.txt
@@ -0,0 +1,38 @@
+Marvell 88PM800 regulator
+
+Required properties:
+- compatible: "marvell,88pm800"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+The valid names for regulators are:
+
+  buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7,
+  ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, 
ldo19
+
+Example:
+
+   pmic: 88pm800@31 {
+   compatible = "marvell,88pm800";
+   reg = <0x31>;
+
+   regulators {
+   buck1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   ldo1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <1500>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+...
+   };
+   };
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
new file mode 100644
index 000..ed704ca
--- /dev/null
+++ b/drivers/regulator/88pm800.c
@@ -0,0 +1,442 @@
+/*
+ * Regulators driver for Marvell 88PM800
+ *
+ * Copyright (C) 2012 Marvell International Ltd.
+ * Joseph(Yossi) Hanin 
+ * Yi Zhang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* LDO1 with DVC[0..3] */
+#define PM800_LDO1_VOUT(0x08) /* VOUT1 */
+#define PM800_LDO1_VOUT_2  (0x09)
+#define PM800_LDO1_VOUT_3  (0x0A)
+#define PM800_LDO2_VOUT(0x0B)
+#define PM800_LDO3_VOUT(0x0C)
+#define PM800_LDO4_VOUT(0x0D)
+#define PM800_LDO5_VOUT(0x0E)
+#define PM800_LDO6_VOUT(0x0F)
+#define PM800_LDO7_VOUT(0x10)
+#define PM800_LDO8_VOUT(0x11)
+#define PM800_LDO9_VOUT(0x12)
+#define PM800_LDO10_VOUT   (0x13)
+#define PM800_LDO11_VOUT   (0x14)
+#define PM800_LDO12_VOUT   (0x15)
+#define PM800_LDO13_VOUT   (0x16)
+#define PM800_LDO14_VOUT   (0x17)
+#define PM800_LDO15_VOUT   (0x18)
+#define PM800_LDO16_VOUT   (0x19)
+#define PM800_LDO17_VOUT   (0x1A)
+#define PM800_LDO18_VOUT   (0x1B)
+#define PM800_LDO19_VOUT   (0x1C)
+
+/* BUCK1 with DVC[0..3] */
+#define PM800_BUCK1(0x3C)
+#define PM800_BUCK1_1  (0x3D)
+#define PM800_BUCK1_2  (0x3E)
+#define PM800_BUCK1_3  (0x3F)
+#define PM800_BUCK2(0x40)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK4(0x42)
+#define PM800_BUCK4_1  (0x43)
+#define PM800_BUCK4_2  (0x44)
+#define PM800_BUCK4_3  (0x45)
+#define PM800_BUCK5(0x46)
+
+#define PM800_BUCK_ENA (0x50)
+#define PM800_LDO_ENA1_1   (0x51)
+#define PM800_LDO_ENA1_2   (0x52)
+#define PM800_LDO_ENA1_3   (0x53)
+
+#define PM800_LDO_ENA2_1   (0x56)
+#define PM800_LDO_ENA2_2   (0x57)
+#define PM800_LDO_ENA2_3   (0x58)
+
+#define PM800_BUCK1_MISC1  (0x78)
+#define PM800_BUCK3_MISC1  (0x7E)
+#define PM800_BUCK4_MISC1  (0x81)
+#define PM800_BUCK5_MISC1  (0x84)
+
+struct pm800_reg

Re: [PATCH V2] regulator: 88pm800: add regulator driver for 88pm800

2013-06-25 Thread Chao Xie
On Tue, Jun 25, 2013 at 5:12 PM, Mark Brown  wrote:
> On Tue, Jun 25, 2013 at 10:13:38AM +0800, Chao Xie wrote:
>> On Mon, Jun 24, 2013 at 6:14 PM, Mark Brown  wrote:
>
>> > If you really need to have platform data for all the regulators then
>> > just embed the array inside the platform data so there's no possibility
>> > of any confusion.
>
>> Some regulators will not be exported to kernel depending on boards which are
>> for special usage. So i do not use a array inside the platform data.
>
> Remember that the regulator API won't do anything except read from a
> regulator unless it's got constraints saying it's OK to do so.  Are you
> saying that even reading the hardware state is a problem?
The regulator driver does not only work for 88pm805 but also for the
next lite version 88pm822.
88pm822 only have 14 LDOes. So i defined array of points in pdata.
When user define pdata for 88pm805, it can fill all 19 LDOes, while
for 88pm822, it only fill 14 LDOes, and set
others to be NULL, and do not need fill some dummy data into the left 5 LDOes.
The 88pm822 is just tape out, and we are debugging at it. So the
detection of 88pm822 is not added to this driver yet.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] regulator: 88pm800: add regulator driver for 88pm800

2013-06-24 Thread Chao Xie
On Mon, Jun 24, 2013 at 6:14 PM, Mark Brown  wrote:
> On Mon, Jun 24, 2013 at 10:01:39AM +0800, Chao Xie wrote:
>> On Fri, Jun 21, 2013 at 11:24 PM, Mark Brown  wrote:
>
>> > Just provide get_voltage_sel(), the core will do the mapping to voltages
>> > using list_voltage().
>
>> I am a little confused.
>> The BUCK voltage is not linear, and it contains a lot of voltages.
>> If we use map_voltage_ascend, it will looking a a suitable voltage
>> from begin to end one by one.
>
> What does this have to do with get_voltage()?  And note that you can
> write your own mapping function for a reason...
>
>> If we directly make use of set_voltage and get_voltage, we can
>> directly calculates the voltage which is
>> suitable, and do not go through all the voltags.
>> for example, now BUCK voltage table is
>> range 1 from 60 to 1587500, each step is 12500
>> range 2 from 160 to 180, each step is 5
>
> No, this is nothing at all to do with using the selector versions of the
> API.  Think about what the API is doing and take a look at the code.
>
OK. I will try to define my own mapping function and use the sel APIs.

>> >> + } else if (pdata->num_regulators) {
>> >> + /* Check whether num_regulator is valid. */
>> >> + unsigned int count = 0;
>> >> + for (i = 0; pdata->regulators[i]; i++)
>> >> + count++;
>> >> + if (count != pdata->num_regulators)
>> >> + return -EINVAL;
>
>> > This looks...  odd.
>
>> It is just make sure that pdata has correct number of regulators.
>> It you think that it is redundant, i can remove it.
>
> If you really need to have platform data for all the regulators then
> just embed the array inside the platform data so there's no possibility
> of any confusion.
>
Some regulators will not be exported to kernel depending on boards which are
for special usage. So i do not use a array inside the platform data.

>> > With deferred probing you should just be able to use
>> > module_platform_driver().
>
>> The regulator controlles some BUCK regulators.
>> These regulators may be used by application CPU or CP(communication
>> CPU) for telephony.
>> The CP may need different voltages if it goes deep initialization. if
>> we defer the setting later, it is too late for
>> CP initialization, and will impact the performance.
>
> If your kernel startup is taking long enough for this to be an issue it
> seems like there's much bigger problems here and things are going to be
> very fragile anyway, it's going to be better to figure out what the root
> issue is.
I see. I will use module_platform_driver
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] USB: initialize or shutdown PHY when add or remove host controller

2013-06-24 Thread Chao Xie
On Tue, Jun 25, 2013 at 3:45 AM, Felipe Balbi  wrote:
> Hi,
>
> On Fri, Jun 21, 2013 at 09:07:59AM +0800, Chao Xie wrote:
>> On Fri, Jun 21, 2013 at 1:25 AM, Alan Stern  
>> wrote:
>> > On Thu, 20 Jun 2013, Felipe Balbi wrote:
>> >
>> >> > In fact, the PHY setting and handling is related to platform or SOC,
>> >> > and for different SOC they can
>> >> > have same EHCI HCD but they PHY handling can be different.
>> >> > Omap'a case is the example, and i think some other vendors may have
>> >> > silimar cases.
>> >> > From above point, It is better to leave the PHY initialization and
>> >> > shutdown to be done by each echi-xxx driver.
>> >> >
>> >> > So Alan and Felipe
>> >> > What are your ideas about it?
>> >>
>> >> If we have so many exceptions, then sure. But eventually, the common
>> >> case should be added generically with a flag so that non-generic cases
>> >> (like OMAP) can request to handle the PHY by themselves.
>> >>
>> >> Alan ?
>> >
>> > I don't have very strong feelings about this; Felipe has much more
>> > experience with these things.
>> >
>> > However, when the common case is added into the core, the simplest way
>> > to indicate that the HCD wants to handle the PHY(s) by itself will be
>> > to leave hcd->phy set to NULL or an ERR_PTR value.
>> >
>> > One important thing that hasn't been pointed out yet: When we move
>> > these calls into the core, the same patch must also remove those calls
>> > from the glue drivers that currently do set hcd->phy.  And it must make
>> > sure that the glue drivers which handle the PHY by themselves do not
>> > set hcd->phy.
>> >
>>
>> From device point of view, EHCI is a standlone component. It has the
>> standard sepcification, so each
>> SOC vendor has EHCI HCD need to follow the standards. Then we have
>> common EHCI HCD driver.
>> The PHY is outside of EHCI component, each SOC vendor may have
>> different PHY implementation. Then
>> we have PHY driver.
>> The EHCI glue driver ehci-xxx works like a SOC depended driver. It is
>> its duty to handle the'
>> relationship between the EHCI HCD driver and PHY driver.
>
> that's not entirely true. We build abstractions layers so that the
> commonalities can be written generically. Just look at the amount of
> code I removed on v3.10 merge window by moving all other UDC drivers to
> use generic constructs I introduced earlier.
>
> It just so happens that OMAP's EHCI has two different working modes
> which mandates different ways to handle the PHY, one is pretty much the
> generic way (power up EHCI, then power up PHY) the other is inverted
> (PHY, then EHCI), that's the only reason (as of today) we're having this
> thread.
>
>> It is same as clk, irq requested by ehci-xxx driver.
>
> clocks could be handled generically in some cases, we have pm_clk_add()
> for a reason ;-)
>
> Also, clock handling can be hidden under pm_runtime callbacks (say,
> clk_enable() on ->runtime_resume(), clk_disable() on
> ->runtime_suspend()). IRQ is actually handled by usbcore, you just pass
> a handler which, in most cases, is the normal ehci_irq() handler.
>
> But we'll get to those later, let's focus on PHY for now.
>
clock is another story, and i know that OMAP has full system to handle
the clock with PM runtime,
i would like to discuss it when one day you want to do it.

>> So i think add a flag and use usb_get_phy() is not very good.
>
> Alan was talking about use hcd->phy as that flag, no flag would be
> added. But why isn't it very good ? you didn't mention your resoning.
>
I maybe understand something wrong.
Using hcd->phy as a flag to indicates whether the gule driver need
EHCI HCD to help
phy operation, such as initialization and shutdown, i think it is fine.
If add another member as a flag in EHCI HCD to indicates the PHY
differences of each echi-xxx.c driver,
and handle them in EHCI HCD, i think that is not very good. Because as
you said that make
common part into EHCI HCD is the target, but this member will import
all the differences to EHCI HCD.
It is better to let the ehci-xxx.c driver to handle the differences if
it does not fit EHCI HCD's requirment
for common PHY handling just as this patch did.


>> It is bette to make ehci-xxx to do the phy getting and EHCI HCD
>> initialize it and shut down as the patch did, or let ehci-xxx to
>> handle the PHY as Roger said.
>
> ri

Re: [PATCH V2] regulator: 88pm800: add regulator driver for 88pm800

2013-06-23 Thread Chao Xie
On Fri, Jun 21, 2013 at 11:24 PM, Mark Brown  wrote:
> On Thu, Jun 20, 2013 at 03:31:07AM -0400, Chao Xie wrote:
>
> Looks pretty good, main thing here is that some of the functionality
> here appears to be reproducing standard code.
>
>> +static int pm800_set_voltage(struct regulator_dev *rdev,
>> +  int min_uv, int max_uv, unsigned *selector)
>> +{
>
> Use set_voltage_sel() and map_voltge_ascend()
>
>> +static int pm800_get_voltage(struct regulator_dev *rdev)
>> +{
>> +
>
> Just provide get_voltage_sel(), the core will do the mapping to voltages
> using list_voltage().
>
I am a little confused.
The BUCK voltage is not linear, and it contains a lot of voltages.
If we use map_voltage_ascend, it will looking a a suitable voltage
from begin to end one by one.
It will waist of time.
If we directly make use of set_voltage and get_voltage, we can
directly calculates the voltage which is
suitable, and do not go through all the voltags.
for example, now BUCK voltage table is
range 1 from 60 to 1587500, each step is 12500
range 2 from 160 to 180, each step is 5

When set_voltage(168, 172)
use map_voltage_ascend, it will go through all voltages range 1, and
then find a suitable voltage in range2
for our code, we direclty find the the voltage is in range2, all need
is (min_uv - range->min_uv)/range->step.
We can get the index, and plus the index with range->index_start, then
we can set the value to register.

>> + } else if (pdata->num_regulators) {
>> + /* Check whether num_regulator is valid. */
>> + unsigned int count = 0;
>> + for (i = 0; pdata->regulators[i]; i++)
>> + count++;
>> + if (count != pdata->num_regulators)
>> + return -EINVAL;
>
> This looks...  odd.
>
It is just make sure that pdata has correct number of regulators.
It you think that it is redundant, i can remove it.

>> +static int __init pm800_regulator_init(void)
>> +{
>> + return platform_driver_register(&pm800_regulator_driver);
>> +}
>> +subsys_initcall(pm800_regulator_init);
>> +
>> +static void __exit pm800_regulator_exit(void)
>> +{
>> + platform_driver_unregister(&pm800_regulator_driver);
>> +}
>> +module_exit(pm800_regulator_exit);
>
> With deferred probing you should just be able to use
> module_platform_driver().
>
The regulator controlles some BUCK regulators.
These regulators may be used by application CPU or CP(communication
CPU) for telephony.
The CP may need different voltages if it goes deep initialization. if
we defer the setting later, it is too late for
CP initialization, and will impact the performance.

>> +config REGULATOR_88PM800
>> + bool "Marvell 88PM800 Power regulators"
>> + depends on MFD_88PM800=y
>> + help
>> +   This driver supports Marvell 88PM800 voltage regulator chips.
>> +   It delivers digitally programmable output,
>> +   the voltage is programmed via I2C interface.
>> +   It's suitable to support PXA988 chips to control VCC_MAIN and
>> +   various voltages.
>> +
>
> Keep this file sorted please.
>
I will change it.
>> --- a/drivers/regulator/Makefile
>> +++ b/drivers/regulator/Makefile
>> @@ -70,6 +70,7 @@ obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
>>  obj-$(CONFIG_REGULATOR_WM8350) += wm8350-regulator.o
>>  obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
>>  obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
>> +obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
>
> Same here.
I will change it.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] USB: initialize or shutdown PHY when add or remove host controller

2013-06-20 Thread Chao Xie
correct for irq. irq number is get by gludriver, while irq is
requested by EHCO HCD.

On Fri, Jun 21, 2013 at 9:07 AM, Chao Xie  wrote:
> On Fri, Jun 21, 2013 at 1:25 AM, Alan Stern  wrote:
>> On Thu, 20 Jun 2013, Felipe Balbi wrote:
>>
>>> > In fact, the PHY setting and handling is related to platform or SOC,
>>> > and for different SOC they can
>>> > have same EHCI HCD but they PHY handling can be different.
>>> > Omap'a case is the example, and i think some other vendors may have
>>> > silimar cases.
>>> > From above point, It is better to leave the PHY initialization and
>>> > shutdown to be done by each echi-xxx driver.
>>> >
>>> > So Alan and Felipe
>>> > What are your ideas about it?
>>>
>>> If we have so many exceptions, then sure. But eventually, the common
>>> case should be added generically with a flag so that non-generic cases
>>> (like OMAP) can request to handle the PHY by themselves.
>>>
>>> Alan ?
>>
>> I don't have very strong feelings about this; Felipe has much more
>> experience with these things.
>>
>> However, when the common case is added into the core, the simplest way
>> to indicate that the HCD wants to handle the PHY(s) by itself will be
>> to leave hcd->phy set to NULL or an ERR_PTR value.
>>
>> One important thing that hasn't been pointed out yet: When we move
>> these calls into the core, the same patch must also remove those calls
>> from the glue drivers that currently do set hcd->phy.  And it must make
>> sure that the glue drivers which handle the PHY by themselves do not
>> set hcd->phy.
>>
>
> From device point of view, EHCI is a standlone component. It has the
> standard sepcification, so each
> SOC vendor has EHCI HCD need to follow the standards. Then we have
> common EHCI HCD driver.
> The PHY is outside of EHCI component, each SOC vendor may have
> different PHY implementation. Then
> we have PHY driver.
> The EHCI glue driver ehci-xxx works like a SOC depended driver. It is
> its duty to handle the'
> relationship between the EHCI HCD driver and PHY driver.
> It is same as clk, irq requested by ehci-xxx driver.
>
> So i think add a flag and use usb_get_phy() is not very good.
> It is bette to make ehci-xxx to do the phy getting and EHCI HCD
> initialize it and shut down as the patch did, or let ehci-xxx to
> handle the PHY as Roger said.
>
> Based on the generic work is not too much, and does not look so
> meaningful. I suggest that let to echi-xxx
> do it.
>
>> Alan Stern
>>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] USB: initialize or shutdown PHY when add or remove host controller

2013-06-20 Thread Chao Xie
On Fri, Jun 21, 2013 at 1:25 AM, Alan Stern  wrote:
> On Thu, 20 Jun 2013, Felipe Balbi wrote:
>
>> > In fact, the PHY setting and handling is related to platform or SOC,
>> > and for different SOC they can
>> > have same EHCI HCD but they PHY handling can be different.
>> > Omap'a case is the example, and i think some other vendors may have
>> > silimar cases.
>> > From above point, It is better to leave the PHY initialization and
>> > shutdown to be done by each echi-xxx driver.
>> >
>> > So Alan and Felipe
>> > What are your ideas about it?
>>
>> If we have so many exceptions, then sure. But eventually, the common
>> case should be added generically with a flag so that non-generic cases
>> (like OMAP) can request to handle the PHY by themselves.
>>
>> Alan ?
>
> I don't have very strong feelings about this; Felipe has much more
> experience with these things.
>
> However, when the common case is added into the core, the simplest way
> to indicate that the HCD wants to handle the PHY(s) by itself will be
> to leave hcd->phy set to NULL or an ERR_PTR value.
>
> One important thing that hasn't been pointed out yet: When we move
> these calls into the core, the same patch must also remove those calls
> from the glue drivers that currently do set hcd->phy.  And it must make
> sure that the glue drivers which handle the PHY by themselves do not
> set hcd->phy.
>

>From device point of view, EHCI is a standlone component. It has the
standard sepcification, so each
SOC vendor has EHCI HCD need to follow the standards. Then we have
common EHCI HCD driver.
The PHY is outside of EHCI component, each SOC vendor may have
different PHY implementation. Then
we have PHY driver.
The EHCI glue driver ehci-xxx works like a SOC depended driver. It is
its duty to handle the'
relationship between the EHCI HCD driver and PHY driver.
It is same as clk, irq requested by ehci-xxx driver.

So i think add a flag and use usb_get_phy() is not very good.
It is bette to make ehci-xxx to do the phy getting and EHCI HCD
initialize it and shut down as the patch did, or let ehci-xxx to
handle the PHY as Roger said.

Based on the generic work is not too much, and does not look so
meaningful. I suggest that let to echi-xxx
do it.

> Alan Stern
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH V2] regulator: 88pm800: add regulator driver for 88pm800

2013-06-20 Thread Chao Xie
Add the regulator driver for PMIC 88pm800 including device tree
support.
88pm800 is an I2C-based power-management IC containing voltage
regulators, a real-time clock, and some general purpose ADC devices,

Signed-off-by: Yi Zhang 
Signed-off-by: Chao Xie 
---
 .../devicetree/bindings/regulator/88pm800.txt  |   38 ++
 drivers/regulator/88pm800.c|  455 
 drivers/regulator/Kconfig  |   10 +
 drivers/regulator/Makefile |1 +
 4 files changed, 504 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/88pm800.txt
 create mode 100644 drivers/regulator/88pm800.c

diff --git a/Documentation/devicetree/bindings/regulator/88pm800.txt 
b/Documentation/devicetree/bindings/regulator/88pm800.txt
new file mode 100644
index 000..e8a54c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/88pm800.txt
@@ -0,0 +1,38 @@
+Marvell 88PM800 regulator
+
+Required properties:
+- compatible: "marvell,88pm800"
+- reg: I2C slave address
+- regulators: A node that houses a sub-node for each regulator within the
+  device. Each sub-node is identified using the node's name (or the deprecated
+  regulator-compatible property if present), with valid values listed below.
+  The content of each sub-node is defined by the standard binding for
+  regulators; see regulator.txt.
+
+The valid names for regulators are:
+
+  buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7,
+  ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, 
ldo19
+
+Example:
+
+   pmic: 88pm800@31 {
+   compatible = "marvell,88pm800";
+   reg = <0x31>;
+
+   regulators {
+   buck1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <395>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+   ldo1 {
+   regulator-min-microvolt = <60>;
+   regulator-max-microvolt = <1500>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+...
+   };
+   };
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
new file mode 100644
index 000..89f52b4
--- /dev/null
+++ b/drivers/regulator/88pm800.c
@@ -0,0 +1,455 @@
+/*
+ * Regulators driver for Marvell 88PM800
+ *
+ * Copyright (C) 2012 Marvell International Ltd.
+ * Joseph(Yossi) Hanin 
+ * Yi Zhang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* LDO1 with DVC[0..3] */
+#define PM800_LDO1_VOUT(0x08) /* VOUT1 */
+#define PM800_LDO1_VOUT_2  (0x09)
+#define PM800_LDO1_VOUT_3  (0x0A)
+#define PM800_LDO2_VOUT(0x0B)
+#define PM800_LDO3_VOUT(0x0C)
+#define PM800_LDO4_VOUT(0x0D)
+#define PM800_LDO5_VOUT(0x0E)
+#define PM800_LDO6_VOUT(0x0F)
+#define PM800_LDO7_VOUT(0x10)
+#define PM800_LDO8_VOUT(0x11)
+#define PM800_LDO9_VOUT(0x12)
+#define PM800_LDO10_VOUT   (0x13)
+#define PM800_LDO11_VOUT   (0x14)
+#define PM800_LDO12_VOUT   (0x15)
+#define PM800_LDO13_VOUT   (0x16)
+#define PM800_LDO14_VOUT   (0x17)
+#define PM800_LDO15_VOUT   (0x18)
+#define PM800_LDO16_VOUT   (0x19)
+#define PM800_LDO17_VOUT   (0x1A)
+#define PM800_LDO18_VOUT   (0x1B)
+#define PM800_LDO19_VOUT   (0x1C)
+
+/* BUCK1 with DVC[0..3] */
+#define PM800_BUCK1(0x3C)
+#define PM800_BUCK1_1  (0x3D)
+#define PM800_BUCK1_2  (0x3E)
+#define PM800_BUCK1_3  (0x3F)
+#define PM800_BUCK2(0x40)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK3(0x41)
+#define PM800_BUCK4(0x42)
+#define PM800_BUCK4_1  (0x43)
+#define PM800_BUCK4_2  (0x44)
+#define PM800_BUCK4_3  (0x45)
+#define PM800_BUCK5(0x46)
+
+#define PM800_BUCK_ENA (0x50)
+#define PM800_LDO_ENA1_1   (0x51)
+#define PM800_LDO_ENA1_2   (0x52)
+#define PM800_LDO_ENA1_3   (0x53)
+
+#define PM800_LDO_ENA2_1   (0x56)
+#define PM800_LDO_ENA2_2   (0x57)
+#define PM800_LDO_ENA2_3   (0x58)
+
+#define PM800_BUCK1_MISC1  (0x78)
+#define PM800_BUCK3_MISC1  (0x7E)
+#define PM800_BUCK4_MISC1  (0x81)
+#define PM800_BUCK5_MISC1  (0x84)
+
+struct pm800_reg

RE: linux-next: build failure after merge of the final tree (mfd tree related)

2013-06-19 Thread Chao Xie
> -Original Message-
> From: Samuel Ortiz [mailto:sa...@linux.intel.com] 
> Sent: Wednesday, June 19, 2013 4:25 PM
> To: Stephen Rothwell
> Cc: linux-n...@vger.kernel.org; linux-kernel@vger.kernel.org; Chao Xie; Yi 
> Zhang
> Subject: Re: linux-next: build failure after merge of the final tree (mfd 
> tree related)

> Hi Stephen,

>>On Tue, Jun 18, 2013 at 05:19:57PM +1000, Stephen Rothwell wrote:
>> Hi all,
>> 
>> After merging the final tree, today's linux-next build (powerpc
>> allyesconfig) failed like this:
>> 
>> drivers/mfd/88pm800.c: In function 'pm800_pages_init':
>> drivers/mfd/88pm800.c:434:2: error: implicit declaration of function 
>> 'IS_ERR' [-Werror=implicit-function-declaration]
>>   if (IS_ERR(subchip->regmap_power)) {
>>   ^
>> drivers/mfd/88pm800.c:435:3: error: implicit declaration of function 
>> 'PTR_ERR' [-Werror=implicit-function-declaration]
>>ret = PTR_ERR(subchip->regmap_power);
>>^
>> 
>> Caused by commit f8ca616f67f7 ("mfd: 88pm800: Enhance error handling for
>> sub pages probe/remove") from the mfd tree.  Forgot to include
>> linux/err.h (see Rule 1 in Documentation/SubmitChecklist).
>Sorry about that. This is fixed now.

It is my fault. Thanks for fixing it.

> Cheers,
> Samuel.

> -- 
> Intel Open Source Technology Centre
> http://oss.intel.com/
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 5/5] input: pxa27x-keypad: add device tree support

2013-06-19 Thread Chao Xie
On Wed, Jun 19, 2013 at 7:13 PM, Gerhard Sittig  wrote:
> On Wed, Jun 19, 2013 at 16:38 +0800, Chao Xie wrote:
>>
>> On Wed, Jun 19, 2013 at 4:22 PM, Marek Vasut  wrote:
>> >
>> >> Signed-off-by: Chao Xie 
>> >> [ ... ]
>> >> +++ b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt
>> >> @@ -0,0 +1,60 @@
>> >> +* Marvell PXA Keypad controller
>> >> +
>> >> +Required Properties
>> >> +- compatible : should be "marvell,pxa27x-keypad"
>> >> +- reg : Address and length of the register set for the device
>> >> +- interrupts : The interrupt for the keypad controller
>> >> +- marvell,debounce-interval : How long time the key will be
>> >
>> > Is there no generic prop name for this debounce interval?
>> >
>> I searched at drivers/input and Documents.
>> Two drivers use "debounce-interval", gpio-keys.c and stmpe-keypad.c.
>> They describe the meanings of "debounce-interval" at its own document file.
>> Some other drivers uses "xxx,debounce-delay-ms" or "debounce-delay-ms"
>> So it seems that there is no generic prop name for this debounce interval.
>
> Actually there is, but under a different (more user friendly)
> name:  See the 'debounce-delay-ms' property in
> Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
> which gets referenced in the matrix_keypad_parse_dt() routine in
> the drivers/input/keyboard/matrix_keypad.c source file.  Ah, your
> last sentence mentions that fact.
>
> But when you introduce DT support into an existing driver which
> previously used platform data, then there is no problem with
> backwards compatibility in .dts files.  So I suggest to go with
> the "debounce-delay-ms" name since it better reflects to the .dts
> author (hardware engineer) which unit the number is supposed to
> be specified in.
>
So Arnd
What do you think? I am fine with either one.

>
> Note that I've recently worked on extending the matrix keypad
> input driver (doc improvements, software polling, binary encoded
> column selection), but haven't submitted the patch series yet
> since it's perfectly operational on the target which motivated
> the extension but wasn't tested yet on any other platform or
> matrix setup -- I currently lack access to an ARM based board
> with either lots of accessible GPIOs to connect a matrix to, or
> some matrix already built into the board, but more importantly
> lack free resources for this very driver extension.
>
> Alternatively I might send an RFC series since the current state
> isn't good enough for v1.  Just ask if you'd like to test or
> review what I have come up with so far (it builds but wasn't
> run-tested).
>
Sure, i can help you to test at PXA platform which is ARM based.

>
> virtually yours
> Gerhard Sittig
> --
> DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
> HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
> Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: off...@denx.de
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] ARM: mmp: bring up pxa988 with device tree support

2013-06-19 Thread Chao Xie
On Tue, Jun 18, 2013 at 5:34 AM, Arnd Bergmann  wrote:
> On Monday 17 June 2013, Chao Xie wrote:
>> On Fri, Jun 14, 2013 at 8:56 PM, Arnd Bergmann  wrote:
>> > On Friday 14 June 2013 17:15:33 Chao Xie wrote:
>> >> On Mon, Jun 10, 2013 at 4:35 PM, Arnd Bergmann  wrote:
>> >
>> >> > I guess that is a problem we have on other platforms as well, we should
>> >> > find a generic solution for that. It would be nice to reserve a page
>> >> > in "fixmap" and have common code map the SCU page into that.
>> >> >
>> >>
>> >> So you mean that reserve a page in arch/arm/asm/include/fixmap.h?
>> >
>> > Yes.
>> >
>> >> This reserve will depend on the cpu type beacuse only A9 will have SCU 
>> >> part.
>> >
>> > I think A5 and ARM11MPCore as well.
>> >
>> >> I do not know that in fixmap, the #ifdef is acceptable or not.
>> >
>> > Yes, it is. We don't really use fixmap on ARM for anything other than
>> > kmap_atomic at the moment. Please have a look at the powerpc and x86
>> > implementations.
>> >
>> >> For the common code to map the SCU page, where do you suggest to put it?
>> >
>> > arch/arm/kernel/smp_scu.c.
>> >
>> I think smp_scu.c may not be good place to put the mapping for SCU page.
>> As you know that the fix map will make use of the mapping that set up
>> by vector page.
>> It will make use of top_pmd, and some APIs only provided under arch/arm/mm/.
>> For example
>> get_mem_type: for the pgprot for MT_DEVICE
>> set_top_pte:
>> Is that possible to add a file fixmap.c under arch/arm/mm/? It can
>> including all the fix mapping
>> except highmem. So SCU is one of it.
>
> It's up to Russell, and he probably has an idea where this should be
> going.
>
> Russell, do you think using a fixmap page for the SCU makes sense?
> I'm looking for a method to consolidate the various methods of
> doing early mappings of the SCU for device tree based platforms.
> Where do you think that should be implemented?
>
Hi, Russell

What do you think about above suggestion?

Thanks.


> Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] USB: initialize or shutdown PHY when add or remove host controller

2013-06-19 Thread Chao Xie
On Wed, Jun 19, 2013 at 3:51 PM, Roger Quadros  wrote:
> Hi Chao,
>
> On 06/19/2013 05:31 AM, Chao Xie wrote:
>> Some controller need software to initialize PHY before add
>> host controller, and shut down PHY after remove host controller.
>> Add the generic code for these controllers so they do not need
>> do it in its own host controller driver.
>>
>> Signed-off-by: Chao Xie 
>> ---
>>  drivers/usb/core/hcd.c |   24 +++-
>>  1 files changed, 23 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
>> index d53547d..301c639 100644
>> --- a/drivers/usb/core/hcd.c
>> +++ b/drivers/usb/core/hcd.c
>> @@ -40,9 +40,11 @@
>>  #include 
>>  #include 
>>  #include 
>> +#include 
>>
>>  #include 
>>  #include 
>> +#include 
>>
>>  #include "usb.h"
>>
>> @@ -2531,12 +2533,26 @@ int usb_add_hcd(struct usb_hcd *hcd,
>>*/
>>   set_bit(HCD_FLAG_RH_RUNNING, &hcd->flags);
>>
>> + /* In case hcd->phy contains the error code. */
>> + if (IS_ERR(hcd->phy))
>> + hcd->phy = NULL;
>> +
>> + /* Initialize the PHY before other hardware operation. */
>> + if (hcd->phy) {
>> + retval = usb_phy_init(hcd->phy);
>> + if (retval) {
>> + dev_err(hcd->self.controller,
>> + "can't initialize phy\n");
>> + goto err_hcd_driver_setup;
>> + }
>> + }
>> +
>>   /* "reset" is misnamed; its role is now one-time init. the controller
>>* should already have been reset (and boot firmware kicked off etc).
>>*/
>>   if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
>>   dev_err(hcd->self.controller, "can't setup\n");
>> - goto err_hcd_driver_setup;
>> + goto err_hcd_driver_init_phy;
>>   }
>>   hcd->rh_pollable = 1;
>>
>> @@ -2608,6 +2624,9 @@ err_hcd_driver_start:
>>   if (usb_hcd_is_primary_hcd(hcd) && hcd->irq > 0)
>>   free_irq(irqnum, hcd);
>>  err_request_irq:
>> +err_hcd_driver_init_phy:
>> + if (hcd->phy)
>> + usb_phy_shutdown(hcd->phy);
>>  err_hcd_driver_setup:
>>  err_set_rh_speed:
>>   usb_put_dev(hcd->self.root_hub);
>> @@ -2674,6 +2693,9 @@ void usb_remove_hcd(struct usb_hcd *hcd)
>>   free_irq(hcd->irq, hcd);
>>   }
>>
>> + if (hcd->phy)
>> + usb_phy_shutdown(hcd->phy);
>> +
>>   usb_put_dev(hcd->self.root_hub);
>>   usb_deregister_bus(&hcd->self);
>>   hcd_buffer_destroy(hcd);
>>
>
> I still think that we shouldn't do this because it adds more confusion and is 
> not
> still a generic enough solution.
>
> 1) It is better for the piece of code that does usb_phy_get() to do 
> usb_phy_init/shutdown,
> else there will be lot of confusion. (Felipe pointed this out earlier).
>
> 2) There is no standard way of getting phy for different controllers. It is 
> mostly platform
> dependent and it is best to leave this to the controller drivers. (Pointed 
> out by Alan).
>
> 3) Controllers can have multiple PHYs. e.g. ehci-omap has one PHY per port 
> and it supports
> 3 ports. This is also platform specific and difficult to handle generically.
>
> 4) Controllers can have specific timing requirements as to when the PHY is 
> initialized relative
> to the controller being initialized. I've pointed OMAP specific stuff in the 
> earlier patch.
>
> Considering all these points, I think we should leave things as they are. It 
> isn't that hard
> for controllers to manage phy_init() and phy_shutdown(), and there is not 
> much code space saved
> when compared to the complexity it creates if we move them to HCD layer.
>
In fact, the PHY setting and handling is related to platform or SOC,
and for different SOC they can
have same EHCI HCD but they PHY handling can be different.
Omap'a case is the example, and i think some other vendors may have
silimar cases.
>From above point, It is better to leave the PHY initialization and
shutdown to be done by each echi-xxx driver.

So Alan and Felipe
What are your ideas about it?

> cheers,
> -roger
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V3 5/5] input: pxa27x-keypad: add device tree support

2013-06-19 Thread Chao Xie
On Wed, Jun 19, 2013 at 4:22 PM, Marek Vasut  wrote:
> Dear Chao Xie,
>
>> Signed-off-by: Chao Xie 
>> ---
>>  .../devicetree/bindings/input/pxa27x-keypad.txt|   60 +
>>  drivers/input/keyboard/pxa27x_keypad.c |  232
>> +++- 2 files changed, 288 insertions(+), 4 deletions(-)
>>  create mode 100644
>> Documentation/devicetree/bindings/input/pxa27x-keypad.txt
>>
>> diff --git a/Documentation/devicetree/bindings/input/pxa27x-keypad.txt
>> b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt new file mode
>> 100644
>> index 000..f8674f7
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt
>> @@ -0,0 +1,60 @@
>> +* Marvell PXA Keypad controller
>> +
>> +Required Properties
>> +- compatible : should be "marvell,pxa27x-keypad"
>> +- reg : Address and length of the register set for the device
>> +- interrupts : The interrupt for the keypad controller
>> +- marvell,debounce-interval : How long time the key will be
>
> Is there no generic prop name for this debounce interval?
>
I searched at drivers/input and Documents.
Two drivers use "debounce-interval", gpio-keys.c and stmpe-keypad.c.
They describe the meanings of "debounce-interval" at its own document file.
Some other drivers uses "xxx,debounce-delay-ms" or "debounce-delay-ms"
So it seems that there is no generic prop name for this debounce interval.

> Best regards,
> Marek Vasut
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH V2] USB: initialize or shutdown PHY when add or remove host controller

2013-06-18 Thread Chao Xie
On Wed, Jun 19, 2013 at 10:48 AM, Greg KH  wrote:
> On Tue, Jun 18, 2013 at 10:31:20PM -0400, Chao Xie wrote:
>> Some controller need software to initialize PHY before add
>> host controller, and shut down PHY after remove host controller.
>> Add the generic code for these controllers so they do not need
>> do it in its own host controller driver.
>
> Why?  What breaks if we add this patch, and what gets fixed?  I'm
> guessing you can then remove code?
>
> What out-of-tree code now works properly?  Or gets broken?
>
> we need more info here please...
>
The patch does not fix any bug.
Some echi-xxx driver will need initialize the phy before it do
usb_add_hcd, and shut down phy after
do usb_remove_hcd, and i did a patch for ehci-mv.c to do above thing.
Alan and Felipe comments on my patch, and they think it is a peice of
generic code, and it can be
moved to hcd to handle it, so other ehci-xxx will not do the same thing again.
So i add the patch to add the generic code in hcd to handle phy
initialization and shut down.

> thanks,
>
> greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   >