aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMagnus Damm <damm@igel.co.jp>2008-10-31 07:20:55 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-12-22 04:42:51 -0500
commita5616bd0f19730a780c354110454ce37209f1ded (patch)
tree367e0b2d8be763d40323c2c30e3d00a49df54a08
parentf2eb0109fb4268505b0737cfe661542eb6151907 (diff)
sh: sh_mobile i2c clock framework support
Add clock framework support to the sh_mobile i2c driver and adjust the processor specific code accordingly. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7343.c4
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7366.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7723.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c73
5 files changed, 41 insertions, 42 deletions
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
index 78881b4214da..e88577f4074a 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7343.c
@@ -30,6 +30,7 @@ static struct resource iic0_resources[] = {
30 30
31static struct platform_device iic0_device = { 31static struct platform_device iic0_device = {
32 .name = "i2c-sh_mobile", 32 .name = "i2c-sh_mobile",
33 .id = 0, /* "i2c0" clock */
33 .num_resources = ARRAY_SIZE(iic0_resources), 34 .num_resources = ARRAY_SIZE(iic0_resources),
34 .resource = iic0_resources, 35 .resource = iic0_resources,
35}; 36};
@@ -50,6 +51,7 @@ static struct resource iic1_resources[] = {
50 51
51static struct platform_device iic1_device = { 52static struct platform_device iic1_device = {
52 .name = "i2c-sh_mobile", 53 .name = "i2c-sh_mobile",
54 .id = 1, /* "i2c1" clock */
53 .num_resources = ARRAY_SIZE(iic1_resources), 55 .num_resources = ARRAY_SIZE(iic1_resources),
54 .resource = iic1_resources, 56 .resource = iic1_resources,
55}; 57};
@@ -147,8 +149,6 @@ static int __init sh7343_devices_setup(void)
147 clk_always_enable("mstp023"); /* INTC3 */ 149 clk_always_enable("mstp023"); /* INTC3 */
148 clk_always_enable("mstp022"); /* INTC */ 150 clk_always_enable("mstp022"); /* INTC */
149 clk_always_enable("mstp020"); /* SuperHyway */ 151 clk_always_enable("mstp020"); /* SuperHyway */
150 clk_always_enable("mstp109"); /* I2C0 */
151 clk_always_enable("mstp108"); /* I2C1 */
152 clk_always_enable("mstp202"); /* VEU */ 152 clk_always_enable("mstp202"); /* VEU */
153 clk_always_enable("mstp201"); /* VPU */ 153 clk_always_enable("mstp201"); /* VPU */
154 154
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
index e17db39b97aa..2f0905a1b211 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7366.c
@@ -32,6 +32,7 @@ static struct resource iic_resources[] = {
32 32
33static struct platform_device iic_device = { 33static struct platform_device iic_device = {
34 .name = "i2c-sh_mobile", 34 .name = "i2c-sh_mobile",
35 .id = 0, /* "i2c0" clock */
35 .num_resources = ARRAY_SIZE(iic_resources), 36 .num_resources = ARRAY_SIZE(iic_resources),
36 .resource = iic_resources, 37 .resource = iic_resources,
37}; 38};
@@ -184,7 +185,6 @@ static int __init sh7366_devices_setup(void)
184 clk_always_enable("mstp023"); /* INTC3 */ 185 clk_always_enable("mstp023"); /* INTC3 */
185 clk_always_enable("mstp022"); /* INTC */ 186 clk_always_enable("mstp022"); /* INTC */
186 clk_always_enable("mstp020"); /* SuperHyway */ 187 clk_always_enable("mstp020"); /* SuperHyway */
187 clk_always_enable("mstp109"); /* I2C */
188 clk_always_enable("mstp211"); /* USB */ 188 clk_always_enable("mstp211"); /* USB */
189 clk_always_enable("mstp207"); /* VEU-2 */ 189 clk_always_enable("mstp207"); /* VEU-2 */
190 clk_always_enable("mstp202"); /* VEU-1 */ 190 clk_always_enable("mstp202"); /* VEU-1 */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index ef77ee1d9f53..786eaf1cf4c3 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -87,6 +87,7 @@ static struct resource iic_resources[] = {
87 87
88static struct platform_device iic_device = { 88static struct platform_device iic_device = {
89 .name = "i2c-sh_mobile", 89 .name = "i2c-sh_mobile",
90 .id = 0, /* "i2c0" clock */
90 .num_resources = ARRAY_SIZE(iic_resources), 91 .num_resources = ARRAY_SIZE(iic_resources),
91 .resource = iic_resources, 92 .resource = iic_resources,
92}; 93};
@@ -197,7 +198,6 @@ static int __init sh7722_devices_setup(void)
197 clk_always_enable("mstp026"); /* XYMEM */ 198 clk_always_enable("mstp026"); /* XYMEM */
198 clk_always_enable("mstp022"); /* INTC */ 199 clk_always_enable("mstp022"); /* INTC */
199 clk_always_enable("mstp020"); /* SuperHyway */ 200 clk_always_enable("mstp020"); /* SuperHyway */
200 clk_always_enable("mstp109"); /* I2C */
201 clk_always_enable("mstp211"); /* USB */ 201 clk_always_enable("mstp211"); /* USB */
202 clk_always_enable("mstp202"); /* VEU */ 202 clk_always_enable("mstp202"); /* VEU */
203 clk_always_enable("mstp201"); /* VPU */ 203 clk_always_enable("mstp201"); /* VPU */
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
index 6d9e6972cfc9..63ec348dec70 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7723.c
@@ -215,6 +215,7 @@ static struct resource iic_resources[] = {
215 215
216static struct platform_device iic_device = { 216static struct platform_device iic_device = {
217 .name = "i2c-sh_mobile", 217 .name = "i2c-sh_mobile",
218 .id = 0, /* "i2c0" clock */
218 .num_resources = ARRAY_SIZE(iic_resources), 219 .num_resources = ARRAY_SIZE(iic_resources),
219 .resource = iic_resources, 220 .resource = iic_resources,
220}; 221};
@@ -238,7 +239,6 @@ static int __init sh7723_devices_setup(void)
238 clk_always_enable("mstp022"); /* INTC */ 239 clk_always_enable("mstp022"); /* INTC */
239 clk_always_enable("mstp020"); /* SuperHyway */ 240 clk_always_enable("mstp020"); /* SuperHyway */
240 clk_always_enable("mstp000"); /* MERAM */ 241 clk_always_enable("mstp000"); /* MERAM */
241 clk_always_enable("mstp109"); /* I2C */
242 clk_always_enable("mstp108"); /* RTC */ 242 clk_always_enable("mstp108"); /* RTC */
243 clk_always_enable("mstp211"); /* USB */ 243 clk_always_enable("mstp211"); /* USB */
244 clk_always_enable("mstp206"); /* VEU2H1 */ 244 clk_always_enable("mstp206"); /* VEU2H1 */
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index 3384a717fec0..6c3d60b939bf 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -160,9 +160,39 @@ struct sh_mobile_i2c_data {
160 160
161static void activate_ch(struct sh_mobile_i2c_data *pd) 161static void activate_ch(struct sh_mobile_i2c_data *pd)
162{ 162{
163 unsigned long i2c_clk;
164 u_int32_t num;
165 u_int32_t denom;
166 u_int32_t tmp;
167
163 /* Make sure the clock is enabled */ 168 /* Make sure the clock is enabled */
164 clk_enable(pd->clk); 169 clk_enable(pd->clk);
165 170
171 /* Get clock rate after clock is enabled */
172 i2c_clk = clk_get_rate(pd->clk);
173
174 /* Calculate the value for iccl. From the data sheet:
175 * iccl = (p clock / transfer rate) * (L / (L + H))
176 * where L and H are the SCL low/high ratio (5/4 in this case).
177 * We also round off the result.
178 */
179 num = i2c_clk * 5;
180 denom = NORMAL_SPEED * 9;
181 tmp = num * 10 / denom;
182 if (tmp % 10 >= 5)
183 pd->iccl = (u_int8_t)((num/denom) + 1);
184 else
185 pd->iccl = (u_int8_t)(num/denom);
186
187 /* Calculate the value for icch. From the data sheet:
188 icch = (p clock / transfer rate) * (H / (L + H)) */
189 num = i2c_clk * 4;
190 tmp = num * 10 / denom;
191 if (tmp % 10 >= 5)
192 pd->icch = (u_int8_t)((num/denom) + 1);
193 else
194 pd->icch = (u_int8_t)(num/denom);
195
166 /* Enable channel and configure rx ack */ 196 /* Enable channel and configure rx ack */
167 iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd)); 197 iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
168 198
@@ -459,40 +489,6 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = {
459 .master_xfer = sh_mobile_i2c_xfer, 489 .master_xfer = sh_mobile_i2c_xfer,
460}; 490};
461 491
462static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
463{
464 struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
465 unsigned long peripheral_clk = clk_get_rate(pd->clk);
466 u_int32_t num;
467 u_int32_t denom;
468 u_int32_t tmp;
469
470 spin_lock_init(&pd->lock);
471 init_waitqueue_head(&pd->wait);
472
473 /* Calculate the value for iccl. From the data sheet:
474 * iccl = (p clock / transfer rate) * (L / (L + H))
475 * where L and H are the SCL low/high ratio (5/4 in this case).
476 * We also round off the result.
477 */
478 num = peripheral_clk * 5;
479 denom = NORMAL_SPEED * 9;
480 tmp = num * 10 / denom;
481 if (tmp % 10 >= 5)
482 pd->iccl = (u_int8_t)((num/denom) + 1);
483 else
484 pd->iccl = (u_int8_t)(num/denom);
485
486 /* Calculate the value for icch. From the data sheet:
487 icch = (p clock / transfer rate) * (H / (L + H)) */
488 num = peripheral_clk * 4;
489 tmp = num * 10 / denom;
490 if (tmp % 10 >= 5)
491 pd->icch = (u_int8_t)((num/denom) + 1);
492 else
493 pd->icch = (u_int8_t)(num/denom);
494}
495
496static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) 492static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
497{ 493{
498 struct resource *res; 494 struct resource *res;
@@ -533,6 +529,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
533 struct sh_mobile_i2c_data *pd; 529 struct sh_mobile_i2c_data *pd;
534 struct i2c_adapter *adap; 530 struct i2c_adapter *adap;
535 struct resource *res; 531 struct resource *res;
532 char clk_name[8];
536 int size; 533 int size;
537 int ret; 534 int ret;
538 535
@@ -542,9 +539,10 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
542 return -ENOMEM; 539 return -ENOMEM;
543 } 540 }
544 541
545 pd->clk = clk_get(&dev->dev, "peripheral_clk"); 542 snprintf(clk_name, sizeof(clk_name), "i2c%d", dev->id);
543 pd->clk = clk_get(&dev->dev, clk_name);
546 if (IS_ERR(pd->clk)) { 544 if (IS_ERR(pd->clk)) {
547 dev_err(&dev->dev, "cannot get peripheral clock\n"); 545 dev_err(&dev->dev, "cannot get clock \"%s\"\n", clk_name);
548 ret = PTR_ERR(pd->clk); 546 ret = PTR_ERR(pd->clk);
549 goto err; 547 goto err;
550 } 548 }
@@ -586,7 +584,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
586 584
587 strlcpy(adap->name, dev->name, sizeof(adap->name)); 585 strlcpy(adap->name, dev->name, sizeof(adap->name));
588 586
589 sh_mobile_i2c_setup_channel(dev); 587 spin_lock_init(&pd->lock);
588 init_waitqueue_head(&pd->wait);
590 589
591 ret = i2c_add_numbered_adapter(adap); 590 ret = i2c_add_numbered_adapter(adap);
592 if (ret < 0) { 591 if (ret < 0) {