1 From ce57fc22543d0ee0ca33157264815a52fc8cf9a3 Mon Sep 17 00:00:00 2001
2 From: Kurt Mahan <kmahan@freescale.com>
3 Date: Thu, 15 May 2008 13:23:27 -0600
4 Subject: [PATCH] Add I2C bus driver for MCF547x and MCF548x.
7 Signed-off-by: Kurt Mahan <kmahan@freescale.com>
8 Signed-off-by: Shrek Wu <b16972@freescale.com>
10 arch/m68k/coldfire/Makefile | 1 +
11 arch/m68k/coldfire/mcf548x-devices.c | 94 ++++++
12 drivers/i2c/busses/Kconfig | 12 +
13 drivers/i2c/busses/Makefile | 1 +
14 drivers/i2c/busses/i2c-algo-mcf.h | 23 ++
15 drivers/i2c/busses/i2c-mcf548x.c | 573 ++++++++++++++++++++++++++++++++++
16 include/asm-m68k/m5485i2c.h | 45 +++
17 7 files changed, 749 insertions(+), 0 deletions(-)
18 create mode 100644 arch/m68k/coldfire/mcf548x-devices.c
19 create mode 100644 drivers/i2c/busses/i2c-algo-mcf.h
20 create mode 100644 drivers/i2c/busses/i2c-mcf548x.c
21 create mode 100644 include/asm-m68k/m5485i2c.h
23 --- a/arch/m68k/coldfire/Makefile
24 +++ b/arch/m68k/coldfire/Makefile
25 @@ -11,4 +11,5 @@ endif
26 obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o
27 obj-$(CONFIG_M54455) += mcf5445x-devices.o
28 obj-$(CONFIG_M547X_8X) += m547x_8x-devices.o
29 +obj-$(CONFIG_M547X_8X) += mcf548x-devices.o
30 obj-$(CONFIG_MCD_DMA) += m547x_8x-dma.o
32 +++ b/arch/m68k/coldfire/mcf548x-devices.c
35 + * arch/m68k/coldfire/mcf5445x-devices.c
37 + * Coldfire M5445x Platform Device Configuration
39 + * Based on the Freescale MXC devices.c
41 + * Copyright (c) 2007 Freescale Semiconductor, Inc.
42 + * Kurt Mahan <kmahan@freescale.com>
44 +#include <linux/module.h>
45 +#include <linux/kernel.h>
46 +#include <linux/init.h>
47 +#include <linux/mtd/physmap.h>
48 +#include <linux/platform_device.h>
49 +#include <linux/fsl_devices.h>
51 +#include <asm/coldfire.h>
52 +#include <asm/mcfsim.h>
54 +static struct resource coldfire_i2c_resources[] = {
56 + .start = MCF_MBAR + 0x008F00,
57 + .end = MCF_MBAR + 0x008F20,
58 + .flags = IORESOURCE_MEM,
63 + .flags = IORESOURCE_IRQ,
67 +static struct platform_device coldfire_i2c_device = {
68 + .name = "MCF548X-i2c",
70 + .num_resources = ARRAY_SIZE(coldfire_i2c_resources),
71 + .resource = coldfire_i2c_resources,
74 +static struct resource coldfire_sec_resources[] = {
76 + .start = MCF_MBAR + 0x00020000,
77 + .end = MCF_MBAR + 0x00033000,
78 + .flags = IORESOURCE_MEM,
83 + .flags = IORESOURCE_IRQ,
87 +static struct platform_device coldfire_sec_device = {
90 + .num_resources = ARRAY_SIZE(coldfire_sec_resources),
91 + .resource = coldfire_sec_resources,
94 +#if defined(CONFIG_MTD_PHYSMAP)
95 +static struct physmap_flash_data mcf5485_flash_data = {
99 +static struct resource mcf5485_flash_resource = {
100 + .start = 0xf8000000,
102 + .flags = IORESOURCE_MEM,
105 +static struct platform_device mcf5485_flash_device = {
106 + .name = "physmap-flash",
109 + .platform_data = &mcf5485_flash_data,
111 + .num_resources = 1,
112 + .resource = &mcf5485_flash_resource,
116 +static int __init mcf5485_init_devices(void)
118 + printk(KERN_INFO "MCF5485x INIT_DEVICES\n");
120 + platform_device_register(&coldfire_i2c_device);
121 + platform_device_register(&coldfire_sec_device);
122 +/*#if defined(CONFIG_MTD_PHYSMAP)
123 + platform_device_register(&mcf5485_flash_device);
127 +arch_initcall(mcf5485_init_devices);
128 --- a/drivers/i2c/busses/Kconfig
129 +++ b/drivers/i2c/busses/Kconfig
132 menu "I2C Hardware Bus support"
135 + tristate "I2C MCF547x/548x interfaces"
138 + This allows you to use the I2C adapters found on the Freescale
139 + MCF547x/548x microcontrollers.
140 + Say Y if you own an I2C adapter belonging to this class and then say
141 + Y to the specific driver for you adapter below.
143 + This support is also available as a module. If so, the module
144 + will be called i2c-algo-mcf.
149 --- a/drivers/i2c/busses/Makefile
150 +++ b/drivers/i2c/busses/Makefile
151 @@ -52,6 +52,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o
152 obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o
153 obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
154 obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
155 +obj-$(CONFIG_I2C_MCF548x) += i2c-mcf548x.o
157 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
158 EXTRA_CFLAGS += -DDEBUG
160 +++ b/drivers/i2c/busses/i2c-algo-mcf.h
162 +#ifndef I2C_ALGO_MCF_H
163 +#define I2C_ALGO_MCF_H 1
165 +/* --- Defines for pcf-adapters --------------------------------------- */
166 +#include <linux/i2c.h>
168 +struct i2c_algo_mcf_data {
169 + void *data; /* private data for lolevel routines */
170 + void (*setmcf) (void *data, int ctl, int val);
171 + int (*getmcf) (void *data, int ctl);
172 + int (*getown) (void *data);
173 + int (*getclock) (void *data);
174 + void (*waitforpin) (void);
175 + /* local settings */
181 +int i2c_mcf_add_bus(struct i2c_adapter *);
182 +int i2c_mcf_del_bus(struct i2c_adapter *);
184 +#endif /* I2C_ALGO_MCF_H */
186 +++ b/drivers/i2c/busses/i2c-mcf548x.c
189 + * Performance and stability improvements: (C) Copyright 2008,
190 + * Adrian Cox <adrian@humboldt.co.uk>
191 + * ColdFire 547x/548x I2C master support
192 + * Shrek Wu (b16972@freescale.com )moved the code driver/i2c/alg/mcf.c
193 + * into driver/i2c/busses.And changed the driver to a platform driver.
195 +#include <linux/i2c.h>
196 +#include "i2c-algo-mcf.h"
198 +#include <linux/init.h>
199 +#include <linux/kernel.h>
200 +#include <linux/module.h>
201 +#include <linux/delay.h>
202 +#include <linux/platform_device.h>
203 +#include <linux/sched.h>
204 +#include <linux/interrupt.h>
207 +#include <asm/coldfire.h>
208 +#include <asm/m5485sim.h>
209 +#include <asm/m5485i2c.h>
211 +#define get_clock(adap) (clock)
212 +#define get_own(adap) (own)
214 +static int clock = 0x3b; /*50000 / 1024 ~ 49 KHz*/
215 +module_param(clock, int, 0);
216 +MODULE_PARM_DESC(clock,
217 + "Set I2C clock in kHz: 400=fast mode (default == 49khz)");
219 +static int own = 0x78;
220 +module_param(own, int, 0);
221 +MODULE_PARM_DESC(clock, "Set I2C Master controller address(0x78)");
223 +static struct i2c_algo_mcf_data i2c_mcf_board_data = {
227 +static struct i2c_adapter i2c_mcf_board_adapter = {
228 + .owner = THIS_MODULE,
229 + .name = "MCF5485 adapter",
230 + .id = I2C_HW_MPC107,
231 + .algo_data = &i2c_mcf_board_data,
232 + .class = I2C_CLASS_HWMON,
237 + * static void i2c_start()
239 + * Generates START signal
243 + struct i2c_algo_mcf_data *adap
245 + MCF_I2CR |= MCF_I2CR_MSTA;
250 + * static void i2c_stop()
252 + * Generates STOP signal
256 + struct i2c_algo_mcf_data *adap
258 + MCF_I2CR &= ~MCF_I2CR_MSTA;
263 + struct i2c_algo_mcf_data *adap
265 + return !(MCF_I2SR & MCF_I2SR_RXAK);
269 + * static void i2c_repstart()
271 + * Generates repeated start signal (without STOP while mastering the bus)
275 + struct i2c_algo_mcf_data *adap
277 + MCF_I2CR |= MCF_I2CR_RSTA;
278 + MCF_I2CR |= MCF_I2CR_MTX;
283 + * static void wait_for_bb()
285 + * Wait for bus idle state
289 + struct i2c_algo_mcf_data *adap
292 + for (i = 0; i < adap->timeout; i++) {
293 + if (!(MCF_I2SR & MCF_I2SR_IBB))
297 + printk(KERN_ERR "%s: timeout", __FUNCTION__);
302 + * static void wait_for_not_bb()
304 + * Wait for bus busy state
308 + struct i2c_algo_mcf_data *adap
311 + for (i = 0; i < adap->timeout; i++) {
312 + if (MCF_I2SR & MCF_I2SR_IBB)
316 + printk(KERN_ERR "%s: timeout", __FUNCTION__);
321 + * static void wait_xfer_done()
323 + * Wait for transfer to complete
327 + struct i2c_algo_mcf_data *adap
331 + for (i = 0; i < adap->timeout; i++) {
332 + if (MCF_I2SR & MCF_I2SR_IIF) {
333 + MCF_I2SR &= ~MCF_I2SR_IIF;
338 + printk(KERN_ERR "%s: timeout", __FUNCTION__);
344 + * static void i2c_set_addr()
346 + * Sets slave address to communicate
350 + struct i2c_algo_mcf_data *adap,
351 + struct i2c_msg *msg,
354 + unsigned short flags = msg->flags;
355 + unsigned char addr;
357 + if ((flags & I2C_M_TEN)) {
358 + /* 10 bit address not supported yet */
361 + /* normal 7bit address */
362 + addr = (msg->addr << 1);
363 + if (flags & I2C_M_RD)
365 + if (flags & I2C_M_REV_DIR_ADDR)
375 + * static void mcf_i2c_init()
377 + * Perform ColdFire i2c initialization
380 +mcf_i2c_init(struct i2c_algo_mcf_data *adap)
383 + /* Setup GPIO lines */
384 + MCF_PAR_FECI2CIRQ |= MCF_PAR_SDA;
385 + MCF_PAR_FECI2CIRQ |= MCF_PAR_SCL;
387 + /* Ensure slaves are in idle state */
388 + if (MCF_I2SR & MCF_I2SR_IBB) {
398 + /* setup SCL clock */
399 + MCF_I2FDR = get_clock(adap);
401 + /* set slave address */
402 + MCF_I2AR = get_own(adap);
404 + /* enable I2C module */
405 + MCF_I2CR = MCF_I2CR_IEN;
408 +static int i2c_outb(
409 + struct i2c_adapter *i2c_adap,
413 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
415 + /* Put data to be sent */
417 + /* Wait for xfer completed*/
418 + timeout = wait_xfer_done(adap);
422 + printk(KERN_ERR "i2c-algo-mcf: %s i2c_write: "
423 + "error - timeout.\n", i2c_adap->name);
424 + return -EREMOTEIO; /* got a better one ?? */
432 + * static void mcf_sendbytes()
434 + * Perform tx data transfer
438 + struct i2c_adapter *i2c_adap,
440 + int count, int last
442 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
445 + /* Set master TX mode */
446 + MCF_I2CR |= MCF_I2CR_MTX;
448 + for (i = 0; i < count; ++i) {
449 + printk(KERN_DEBUG "i2c-algo-mcf: %s i2c_write: writing %2.2X\n",
450 + i2c_adap->name, buf[i]&0xff);
451 + ret = i2c_outb(i2c_adap, buf[i]);
459 + i2c_repstart(adap);
467 + * static void mcf_readbytes()
469 + * Perform rx data transfer
473 + struct i2c_adapter *i2c_adap,
475 + int count, int last
478 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
481 + /* Set master RX mode */
482 + MCF_I2CR &= ~MCF_I2CR_MTX;
483 + MCF_I2CR &= ~MCF_I2CR_TXAK;
486 + for (i = 0; i < count-1; i++) {
487 + if (wait_xfer_done(adap)) {
491 + "i2c-algo-mcf: mcf_readbytes timed out.\n");
495 + /* store next data byte */
499 + if (wait_xfer_done(adap)) {
502 + printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n");
506 + /* Disable acknowlege (set I2CR.TXAK) */
507 + MCF_I2CR |= MCF_I2CR_TXAK;
509 + if (wait_xfer_done(adap)) {
512 + printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n");
520 + i2c_repstart(adap);
528 + * static void mcf_xfer()
530 + * Perform master data I/O transfer
534 + struct i2c_adapter *i2c_adap,
535 + struct i2c_msg *msgs,
538 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
539 + struct i2c_msg *pmsg;
541 + int ret = 0, timeout;
543 + /* Skip own address */
544 + if (get_own(adap) == (msgs[0].addr << 1))
547 + /* Ensure slaves are in idle state */
548 + if (MCF_I2SR & MCF_I2SR_IBB) {
552 + timeout = MCF_I2DR;
557 + /* setup SCL clock */
558 + MCF_I2FDR = get_clock(adap);
559 + /* set slave address */
560 + MCF_I2AR = get_own(adap);
561 + /* enable I2C module */
562 + MCF_I2CR = MCF_I2CR_IEN;
564 + MCF_I2CR |= MCF_I2CR_TXAK;
566 + /* Check for bus busy */
569 + for (i = 0; ret >= 0 && i < num; i++) {
572 + printk(KERN_DEBUG "i2c-algo-mcf: Doing %s %d bytes "
573 + "to 0x%02x - %d of %d messages\n",
574 + pmsg->flags & I2C_M_RD ? "read" : "write",
575 + pmsg->len, pmsg->addr, i + 1, num);
581 + /* Wait for Bus Busy */
582 + wait_for_not_bb(adap);
584 + MCF_I2CR |= MCF_I2CR_MTX;
586 + ret = i2c_set_addr(adap, pmsg, i2c_adap->retries);
590 + /* Wait for address transfer completion */
591 + wait_xfer_done(adap);
593 + /* Check for ACK */
594 + if (!i2c_getack(adap)) {
597 + printk(KERN_DEBUG "i2c-algo-mcf: No ack after "
598 + "send address in mcf_xfer\n");
599 + return (-EREMOTEIO);
602 + printk(KERN_DEBUG "i2c-algo-mcf: Msg %d, "
603 + "addr = 0x%x, flags = 0x%x, len = %d\n",
604 + i, msgs[i].addr, msgs[i].flags, msgs[i].len);
606 + if (pmsg->flags & I2C_M_RD) {
607 + /* read bytes into buffer*/
608 + ret = mcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
611 + if (ret != pmsg->len) {
612 + printk(KERN_DEBUG "i2c-algo-mcf: fail: "
613 + "only read %d bytes.\n", ret);
615 + printk(KERN_DEBUG "i2c-algo-mcf: "
616 + "read %d bytes.\n", ret);
619 + /* write bytes into buffer*/
620 + ret = mcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
622 + if (ret != pmsg->len) {
623 + printk(KERN_DEBUG "i2c-algo-mcf: fail: "
624 + "only wrote %d bytes.\n", ret);
626 + printk(KERN_DEBUG "i2c-algo-mcf: wrote"
627 + "%d bytes.\n", ret);
632 + /* Disable I2C module */
639 + * static void mcf_func()
641 + * Return algorithm funtionality
645 + struct i2c_adapter *i2c_adap
647 + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
651 + * ColdFire bus algorithm callbacks
653 +static struct i2c_algorithm mcf_algo = {
654 + .master_xfer = mcf_xfer,
655 + .functionality = mcf_func,
658 +/***********************************************************/
659 +struct coldfire_i2c {
660 + void __iomem *base;
661 + struct resource *irqarea;
662 + struct resource *ioarea;
664 + struct i2c_adapter *adap;
669 + * registering functions to load algorithms at runtime
671 +int i2c_mcf_add_bus(struct i2c_adapter *adap)
673 + struct i2c_algo_mcf_data *mcf_adap = adap->algo_data;
675 + /*adap->id |= mcf_algo.id;*/
676 + adap->algo = &mcf_algo;
677 + adap->timeout = 100;
679 + mcf_i2c_init(mcf_adap);
685 + i2c_add_adapter(adap);
690 +static int mcf548x_i2c_probe(struct platform_device *pdev)
692 + struct coldfire_i2c *i2c;
695 + /************************************************************/
696 + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
698 + printk(KERN_ERR "%s kzalloc coldfire_i2c faile\n",
702 + /****************************************************************/
703 + platform_set_drvdata(pdev, i2c);
705 + i2c->adap = &i2c_mcf_board_adapter;
706 + i2c->adap->dev.parent = &pdev->dev;
707 + rc = i2c_mcf_add_bus(i2c->adap);
709 + printk(KERN_ERR "%s - failed to add adapter\n", __FUNCTION__);
714 + printk(KERN_INFO "i2c-algo-mcf.o: I2C ColdFire algorithm"
715 + " module is loaded.\n");
723 +static int mcf548x_i2c_remove(struct platform_device *pdev)
725 + struct coldfire_i2c *i2c = platform_get_drvdata(pdev);
727 + i2c_del_adapter(i2c->adap);
728 + platform_set_drvdata(pdev, NULL);
729 + iounmap(i2c->base);
734 +/* Structure for a device driver */
735 +static struct platform_driver mcf548x_i2c_driver = {
736 + .probe = mcf548x_i2c_probe,
737 + .remove = mcf548x_i2c_remove,
739 + .owner = THIS_MODULE,
740 + .name = "MCF548X-i2c",
744 +static int __init coldfire_i2c_init(void)
746 + return platform_driver_register(&mcf548x_i2c_driver);
749 +static void __exit coldfire_i2c_exit(void)
751 + platform_driver_unregister(&mcf548x_i2c_driver);
754 +module_init(coldfire_i2c_init);
755 +module_exit(coldfire_i2c_exit);
757 +MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
759 + ("I2C-Bus adapter for MCF547x and MCF548x processors");
760 +MODULE_LICENSE("GPL");
762 +++ b/include/asm-m68k/m5485i2c.h
765 + * m5485i2c.h -- ColdFire 547x/548x i2c controller support.
770 +/* Register read/write macros */
771 +#define MCF_I2AR MCF_REG08(0x008F00) /* I2C Address */
772 +#define MCF_I2FDR MCF_REG08(0x008F04) /* I2C Frequency Divider */
773 +#define MCF_I2CR MCF_REG08(0x008F08) /* I2C Control */
774 +#define MCF_I2SR MCF_REG08(0x008F0C) /* I2C Status */
775 +#define MCF_I2DR MCF_REG08(0x008F10) /* I2C Data I/O */
776 +#define MCF_I2ICR MCF_REG08(0x008F20) /* I2C Interrupt Control */
778 +/* Bit definitions and macros for MCF_I2C_I2AR */
779 +#define MCF_I2AR_ADR(x) (((x)&0x7F)<<1)
781 +/* Bit definitions and macros for MCF_I2C_I2FDR */
782 +#define MCF_I2FDR_IC(x) (((x)&0x3F)<<0)
784 +/* Bit definitions and macros for MCF_I2C_I2CR */
785 +#define MCF_I2CR_RSTA (0x04)
786 +#define MCF_I2CR_TXAK (0x08)
787 +#define MCF_I2CR_MTX (0x10)
788 +#define MCF_I2CR_MSTA (0x20)
789 +#define MCF_I2CR_IIEN (0x40)
790 +#define MCF_I2CR_IEN (0x80)
792 +/* Bit definitions and macros for MCF_I2C_I2SR */
793 +#define MCF_I2SR_RXAK (0x01)
794 +#define MCF_I2SR_IIF (0x02)
795 +#define MCF_I2SR_SRW (0x04)
796 +#define MCF_I2SR_IAL (0x10)
797 +#define MCF_I2SR_IBB (0x20)
798 +#define MCF_I2SR_IAAS (0x40)
799 +#define MCF_I2SR_ICF (0x80)
801 +/* Bit definitions and macros for MCF_I2C_I2ICR */
802 +#define MCF_I2ICR_IE (0x01)
803 +#define MCF_I2ICR_RE (0x02)
804 +#define MCF_I2ICR_TE (0x04)
805 +#define MCF_I2ICR_BNBE (0x08)
807 +/********************************************************************/