aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2010-03-07 17:29:13 -0500
committerBen Dooks <ben-linux@fluff.org>2010-03-07 17:29:13 -0500
commitaaa02ab55796341e713f798c57c5099153869278 (patch)
tree9461dfd82fd275b2d7052a624742961edd3a9b5d /drivers
parentad0194e8d624df67a970a36e8ef9e61514e25553 (diff)
parent192505bdb4e43ecbd11627bc0e205875edba473c (diff)
Merge branch 'next-i2c-mpc-v8' into next-i2c
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/Kconfig7
-rw-r--r--drivers/i2c/busses/i2c-mpc.c194
2 files changed, 124 insertions, 77 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 10041813c6ed..ecf079b7f931 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -419,13 +419,12 @@ config I2C_IXP2000
419 instead. 419 instead.
420 420
421config I2C_MPC 421config I2C_MPC
422 tristate "MPC107/824x/85xx/52xx/86xx" 422 tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
423 depends on PPC32 423 depends on PPC32
424 help 424 help
425 If you say yes to this option, support will be included for the 425 If you say yes to this option, support will be included for the
426 built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and 426 built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
427 MPC85xx/MPC8641 family processors. The driver may also work on 52xx 427 MPC8240, MPC8245, MPC83xx, MPC85xx and MPC8641 family processors.
428 family processors, though interrupts are known not to work.
429 428
430 This driver can also be built as a module. If so, the module 429 This driver can also be built as a module. If so, the module
431 will be called i2c-mpc. 430 will be called i2c-mpc.
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f627001108b8..78a15af32942 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -31,6 +31,9 @@
31 31
32#define DRV_NAME "mpc-i2c" 32#define DRV_NAME "mpc-i2c"
33 33
34#define MPC_I2C_CLOCK_LEGACY 0
35#define MPC_I2C_CLOCK_PRESERVE (~0U)
36
34#define MPC_I2C_FDR 0x04 37#define MPC_I2C_FDR 0x04
35#define MPC_I2C_CR 0x08 38#define MPC_I2C_CR 0x08
36#define MPC_I2C_SR 0x0c 39#define MPC_I2C_SR 0x0c
@@ -66,10 +69,9 @@ struct mpc_i2c_divider {
66 u16 fdr; /* including dfsrr */ 69 u16 fdr; /* including dfsrr */
67}; 70};
68 71
69struct mpc_i2c_match_data { 72struct mpc_i2c_data {
70 void (*setclock)(struct device_node *node, 73 void (*setup)(struct device_node *node, struct mpc_i2c *i2c,
71 struct mpc_i2c *i2c, 74 u32 clock, u32 prescaler);
72 u32 clock, u32 prescaler);
73 u32 prescaler; 75 u32 prescaler;
74}; 76};
75 77
@@ -164,8 +166,8 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
164 return 0; 166 return 0;
165} 167}
166 168
167#ifdef CONFIG_PPC_MPC52xx 169#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
168static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { 170static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
169 {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, 171 {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
170 {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02}, 172 {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
171 {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28}, 173 {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
@@ -186,14 +188,15 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
186 {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f} 188 {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
187}; 189};
188 190
189int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler) 191static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
192 int prescaler)
190{ 193{
191 const struct mpc_i2c_divider *div = NULL; 194 const struct mpc_i2c_divider *div = NULL;
192 unsigned int pvr = mfspr(SPRN_PVR); 195 unsigned int pvr = mfspr(SPRN_PVR);
193 u32 divider; 196 u32 divider;
194 int i; 197 int i;
195 198
196 if (!clock) 199 if (clock == MPC_I2C_CLOCK_LEGACY)
197 return -EINVAL; 200 return -EINVAL;
198 201
199 /* Determine divider value */ 202 /* Determine divider value */
@@ -215,12 +218,18 @@ int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler)
215 return div ? (int)div->fdr : -EINVAL; 218 return div ? (int)div->fdr : -EINVAL;
216} 219}
217 220
218static void mpc_i2c_setclock_52xx(struct device_node *node, 221static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
219 struct mpc_i2c *i2c, 222 struct mpc_i2c *i2c,
220 u32 clock, u32 prescaler) 223 u32 clock, u32 prescaler)
221{ 224{
222 int ret, fdr; 225 int ret, fdr;
223 226
227 if (clock == MPC_I2C_CLOCK_PRESERVE) {
228 dev_dbg(i2c->dev, "using fdr %d\n",
229 readb(i2c->base + MPC_I2C_FDR));
230 return;
231 }
232
224 ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler); 233 ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler);
225 fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */ 234 fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */
226 235
@@ -229,16 +238,52 @@ static void mpc_i2c_setclock_52xx(struct device_node *node,
229 if (ret >= 0) 238 if (ret >= 0)
230 dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr); 239 dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr);
231} 240}
232#else /* !CONFIG_PPC_MPC52xx */ 241#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
233static void mpc_i2c_setclock_52xx(struct device_node *node, 242static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
234 struct mpc_i2c *i2c, 243 struct mpc_i2c *i2c,
235 u32 clock, u32 prescaler) 244 u32 clock, u32 prescaler)
245{
246}
247#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
248
249#ifdef CONFIG_PPC_MPC512x
250static void __devinit mpc_i2c_setup_512x(struct device_node *node,
251 struct mpc_i2c *i2c,
252 u32 clock, u32 prescaler)
253{
254 struct device_node *node_ctrl;
255 void __iomem *ctrl;
256 const u32 *pval;
257 u32 idx;
258
259 /* Enable I2C interrupts for mpc5121 */
260 node_ctrl = of_find_compatible_node(NULL, NULL,
261 "fsl,mpc5121-i2c-ctrl");
262 if (node_ctrl) {
263 ctrl = of_iomap(node_ctrl, 0);
264 if (ctrl) {
265 /* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
266 pval = of_get_property(node, "reg", NULL);
267 idx = (*pval & 0xff) / 0x20;
268 setbits32(ctrl, 1 << (24 + idx * 2));
269 iounmap(ctrl);
270 }
271 of_node_put(node_ctrl);
272 }
273
274 /* The clock setup for the 52xx works also fine for the 512x */
275 mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
276}
277#else /* CONFIG_PPC_MPC512x */
278static void __devinit mpc_i2c_setup_512x(struct device_node *node,
279 struct mpc_i2c *i2c,
280 u32 clock, u32 prescaler)
236{ 281{
237} 282}
238#endif /* CONFIG_PPC_MPC52xx*/ 283#endif /* CONFIG_PPC_MPC512x */
239 284
240#ifdef CONFIG_FSL_SOC 285#ifdef CONFIG_FSL_SOC
241static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = { 286static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
242 {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123}, 287 {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
243 {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102}, 288 {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
244 {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127}, 289 {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
@@ -258,7 +303,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
258 {49152, 0x011e}, {61440, 0x011f} 303 {49152, 0x011e}, {61440, 0x011f}
259}; 304};
260 305
261u32 mpc_i2c_get_sec_cfg_8xxx(void) 306static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
262{ 307{
263 struct device_node *node = NULL; 308 struct device_node *node = NULL;
264 u32 __iomem *reg; 309 u32 __iomem *reg;
@@ -287,13 +332,14 @@ u32 mpc_i2c_get_sec_cfg_8xxx(void)
287 return val; 332 return val;
288} 333}
289 334
290int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler) 335static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
336 u32 prescaler)
291{ 337{
292 const struct mpc_i2c_divider *div = NULL; 338 const struct mpc_i2c_divider *div = NULL;
293 u32 divider; 339 u32 divider;
294 int i; 340 int i;
295 341
296 if (!clock) 342 if (clock == MPC_I2C_CLOCK_LEGACY)
297 return -EINVAL; 343 return -EINVAL;
298 344
299 /* Determine proper divider value */ 345 /* Determine proper divider value */
@@ -320,12 +366,19 @@ int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler)
320 return div ? (int)div->fdr : -EINVAL; 366 return div ? (int)div->fdr : -EINVAL;
321} 367}
322 368
323static void mpc_i2c_setclock_8xxx(struct device_node *node, 369static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
324 struct mpc_i2c *i2c, 370 struct mpc_i2c *i2c,
325 u32 clock, u32 prescaler) 371 u32 clock, u32 prescaler)
326{ 372{
327 int ret, fdr; 373 int ret, fdr;
328 374
375 if (clock == MPC_I2C_CLOCK_PRESERVE) {
376 dev_dbg(i2c->dev, "using dfsrr %d, fdr %d\n",
377 readb(i2c->base + MPC_I2C_DFSRR),
378 readb(i2c->base + MPC_I2C_FDR));
379 return;
380 }
381
329 ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler); 382 ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler);
330 fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */ 383 fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */
331 384
@@ -338,9 +391,9 @@ static void mpc_i2c_setclock_8xxx(struct device_node *node,
338} 391}
339 392
340#else /* !CONFIG_FSL_SOC */ 393#else /* !CONFIG_FSL_SOC */
341static void mpc_i2c_setclock_8xxx(struct device_node *node, 394static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
342 struct mpc_i2c *i2c, 395 struct mpc_i2c *i2c,
343 u32 clock, u32 prescaler) 396 u32 clock, u32 prescaler)
344{ 397{
345} 398}
346#endif /* CONFIG_FSL_SOC */ 399#endif /* CONFIG_FSL_SOC */
@@ -494,7 +547,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
494{ 547{
495 struct mpc_i2c *i2c; 548 struct mpc_i2c *i2c;
496 const u32 *prop; 549 const u32 *prop;
497 u32 clock = 0; 550 u32 clock = MPC_I2C_CLOCK_LEGACY;
498 int result = 0; 551 int result = 0;
499 int plen; 552 int plen;
500 553
@@ -523,21 +576,21 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
523 } 576 }
524 } 577 }
525 578
526 if (!of_get_property(op->node, "fsl,preserve-clocking", NULL)) { 579 if (of_get_property(op->node, "fsl,preserve-clocking", NULL)) {
580 clock = MPC_I2C_CLOCK_PRESERVE;
581 } else {
527 prop = of_get_property(op->node, "clock-frequency", &plen); 582 prop = of_get_property(op->node, "clock-frequency", &plen);
528 if (prop && plen == sizeof(u32)) 583 if (prop && plen == sizeof(u32))
529 clock = *prop; 584 clock = *prop;
585 }
530 586
531 if (match->data) { 587 if (match->data) {
532 struct mpc_i2c_match_data *data = 588 struct mpc_i2c_data *data = match->data;
533 (struct mpc_i2c_match_data *)match->data; 589 data->setup(op->node, i2c, clock, data->prescaler);
534 data->setclock(op->node, i2c, clock, data->prescaler); 590 } else {
535 } else { 591 /* Backwards compatibility */
536 /* Backwards compatibility */ 592 if (of_get_property(op->node, "dfsrr", NULL))
537 if (of_get_property(op->node, "dfsrr", NULL)) 593 mpc_i2c_setup_8xxx(op->node, i2c, clock, 0);
538 mpc_i2c_setclock_8xxx(op->node, i2c,
539 clock, 0);
540 }
541 } 594 }
542 595
543 dev_set_drvdata(&op->dev, i2c); 596 dev_set_drvdata(&op->dev, i2c);
@@ -582,47 +635,42 @@ static int __devexit fsl_i2c_remove(struct of_device *op)
582 return 0; 635 return 0;
583}; 636};
584 637
638static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
639 .setup = mpc_i2c_setup_512x,
640};
641
642static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
643 .setup = mpc_i2c_setup_52xx,
644};
645
646static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
647 .setup = mpc_i2c_setup_8xxx,
648};
649
650static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
651 .setup = mpc_i2c_setup_8xxx,
652 .prescaler = 2,
653};
654
655static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
656 .setup = mpc_i2c_setup_8xxx,
657 .prescaler = 3,
658};
659
585static const struct of_device_id mpc_i2c_of_match[] = { 660static const struct of_device_id mpc_i2c_of_match[] = {
586 {.compatible = "mpc5200-i2c", 661 {.compatible = "mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
587 .data = &(struct mpc_i2c_match_data) { 662 {.compatible = "fsl,mpc5200b-i2c", .data = &mpc_i2c_data_52xx, },
588 .setclock = mpc_i2c_setclock_52xx, 663 {.compatible = "fsl,mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
589 }, 664 {.compatible = "fsl,mpc5121-i2c", .data = &mpc_i2c_data_512x, },
590 }, 665 {.compatible = "fsl,mpc8313-i2c", .data = &mpc_i2c_data_8313, },
591 {.compatible = "fsl,mpc5200b-i2c", 666 {.compatible = "fsl,mpc8543-i2c", .data = &mpc_i2c_data_8543, },
592 .data = &(struct mpc_i2c_match_data) { 667 {.compatible = "fsl,mpc8544-i2c", .data = &mpc_i2c_data_8544, },
593 .setclock = mpc_i2c_setclock_52xx,
594 },
595 },
596 {.compatible = "fsl,mpc5200-i2c",
597 .data = &(struct mpc_i2c_match_data) {
598 .setclock = mpc_i2c_setclock_52xx,
599 },
600 },
601 {.compatible = "fsl,mpc8313-i2c",
602 .data = &(struct mpc_i2c_match_data) {
603 .setclock = mpc_i2c_setclock_8xxx,
604 },
605 },
606 {.compatible = "fsl,mpc8543-i2c",
607 .data = &(struct mpc_i2c_match_data) {
608 .setclock = mpc_i2c_setclock_8xxx,
609 .prescaler = 2,
610 },
611 },
612 {.compatible = "fsl,mpc8544-i2c",
613 .data = &(struct mpc_i2c_match_data) {
614 .setclock = mpc_i2c_setclock_8xxx,
615 .prescaler = 3,
616 },
617 /* Backward compatibility */ 668 /* Backward compatibility */
618 },
619 {.compatible = "fsl-i2c", }, 669 {.compatible = "fsl-i2c", },
620 {}, 670 {},
621}; 671};
622
623MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); 672MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
624 673
625
626/* Structure for a device driver */ 674/* Structure for a device driver */
627static struct of_platform_driver mpc_i2c_driver = { 675static struct of_platform_driver mpc_i2c_driver = {
628 .match_table = mpc_i2c_of_match, 676 .match_table = mpc_i2c_of_match,
@@ -655,5 +703,5 @@ module_exit(fsl_i2c_exit);
655 703
656MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); 704MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
657MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and " 705MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
658 "MPC824x/85xx/52xx processors"); 706 "MPC824x/83xx/85xx/86xx/512x/52xx processors");
659MODULE_LICENSE("GPL"); 707MODULE_LICENSE("GPL");