1 From a7c7130d916c1f7e0d27ad9b338912496ad53089 Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:46 +0800
4 Subject: [PATCH 25/52] Add I2C driver for MCF5445x/MCF547x/MCF548x.
6 Add common I2C driver for MCF5445x/MCF547x/MCF548x and add I2C slave
7 mode support for MCF5445x.
9 Configure I2C adaptor as slave mode and Support I2C adaptor as a
10 "eeprom-like" slave device.
12 Signed-off-by: Alison Wang <b18965@freescale.com>
14 arch/m68k/include/asm/mcfi2c.h | 57 +++
15 drivers/i2c/busses/Kconfig | 24 ++
16 drivers/i2c/busses/Makefile | 2 +
17 drivers/i2c/busses/i2c-algo-mcf.h | 23 ++
18 drivers/i2c/busses/i2c-mcf-slave.c | 358 ++++++++++++++++++
19 drivers/i2c/busses/i2c-mcf.c | 698 ++++++++++++++++++++++++++++++++++++
20 6 files changed, 1162 insertions(+), 0 deletions(-)
21 create mode 100644 arch/m68k/include/asm/mcfi2c.h
22 create mode 100644 drivers/i2c/busses/i2c-algo-mcf.h
23 create mode 100644 drivers/i2c/busses/i2c-mcf-slave.c
24 create mode 100644 drivers/i2c/busses/i2c-mcf.c
27 +++ b/arch/m68k/include/asm/mcfi2c.h
30 + * mcfi2c.h -- ColdFire mcfv4/mcfv4e i2c controller support.
31 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
36 +/* Register read/write macros */
37 +#if defined(CONFIG_M547X_8X)
38 +#define MCF_I2AR MCF_REG08(0x008F00) /* I2C Address */
39 +#define MCF_I2FDR MCF_REG08(0x008F04) /* I2C Frequency Divider */
40 +#define MCF_I2CR MCF_REG08(0x008F08) /* I2C Control */
41 +#define MCF_I2SR MCF_REG08(0x008F0C) /* I2C Status */
42 +#define MCF_I2DR MCF_REG08(0x008F10) /* I2C Data I/O */
43 +#define MCF_I2ICR MCF_REG08(0x008F20) /* I2C Interrupt Control */
44 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
45 +#define MCF_I2AR (*(volatile u8 *)(0xFC058000)) /* I2C Address */
46 +/* I2C Frequency Divider */
47 +#define MCF_I2FDR (*(volatile u8 *)(0xFC058004))
48 +#define MCF_I2CR (*(volatile u8 *)(0xFC058008)) /* I2C Control */
49 +#define MCF_I2SR (*(volatile u8 *)(0xFC05800C)) /* I2C Status */
50 +#define MCF_I2DR (*(volatile u8 *)(0xFC058010)) /* I2C Data I/O */
53 +/* Bit definitions and macros for MCF_I2C_I2AR */
54 +#define MCF_I2AR_ADR(x) (((x)&0x7F)<<1)
56 +/* Bit definitions and macros for MCF_I2C_I2FDR */
57 +#define MCF_I2FDR_IC(x) (((x)&0x3F)<<0)
59 +/* Bit definitions and macros for MCF_I2C_I2CR */
60 +#define MCF_I2CR_RSTA (0x04)
61 +#define MCF_I2CR_TXAK (0x08)
62 +#define MCF_I2CR_MTX (0x10)
63 +#define MCF_I2CR_MSTA (0x20)
64 +#define MCF_I2CR_IIEN (0x40)
65 +#define MCF_I2CR_IEN (0x80)
67 +/* Bit definitions and macros for MCF_I2C_I2SR */
68 +#define MCF_I2SR_RXAK (0x01)
69 +#define MCF_I2SR_IIF (0x02)
70 +#define MCF_I2SR_SRW (0x04)
71 +#define MCF_I2SR_IAL (0x10)
72 +#define MCF_I2SR_IBB (0x20)
73 +#define MCF_I2SR_IAAS (0x40)
74 +#define MCF_I2SR_ICF (0x80)
76 +/* Bit definitions and macros for MCF_I2C_I2ICR */
77 +#if defined(CONFIG_M547X_8X)
78 +#define MCF_I2ICR_IE (0x01)
79 +#define MCF_I2ICR_RE (0x02)
80 +#define MCF_I2ICR_TE (0x04)
81 +#define MCF_I2ICR_BNBE (0x08)
84 +/********************************************************************/
86 --- a/drivers/i2c/busses/Kconfig
87 +++ b/drivers/i2c/busses/Kconfig
88 @@ -431,6 +431,30 @@ config I2C_IXP2000
89 This driver is deprecated and will be dropped soon. Use i2c-gpio
93 + tristate "MCF ColdFire I2C Interface"
94 + depends on I2C && COLDFIRE
96 + If you say yes to this option, support will be included for the
97 + I2C on most ColdFire CPUs
99 + This driver can also be built as a module. If so, the module
100 + will be called i2c-mcf.
102 +config I2C_MCF_SLAVE
103 + tristate "MCF ColdFire I2C Slave Interface"
104 + depends on !(I2C_MCF)
107 + mcf i2c adapter slave mode, only supported on mcf5445x platform.
109 +config I2C_SLAVE_TEST
110 + bool "I2C Slave Mode Test Configuration"
111 + depends on I2C_MCF_SLAVE
114 + This configuration help to test I2C slave mode
117 tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
119 --- a/drivers/i2c/busses/Makefile
120 +++ b/drivers/i2c/busses/Makefile
121 @@ -77,5 +77,7 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
122 obj-$(CONFIG_I2C_STUB) += i2c-stub.o
123 obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
124 obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
125 +obj-$(CONFIG_I2C_MCF) += i2c-mcf.o
126 +obj-$(CONFIG_I2C_MCF_SLAVE) += i2c-mcf-slave.o
128 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
130 +++ b/drivers/i2c/busses/i2c-algo-mcf.h
132 +#ifndef I2C_ALGO_MCF_H
133 +#define I2C_ALGO_MCF_H 1
135 +/* --- Defines for pcf-adapters --------------------------------------- */
136 +#include <linux/i2c.h>
138 +struct i2c_algo_mcf_data {
139 + void *data; /* private data for lolevel routines */
140 + void (*setmcf) (void *data, int ctl, int val);
141 + int (*getmcf) (void *data, int ctl);
142 + int (*getown) (void *data);
143 + int (*getclock) (void *data);
144 + void (*waitforpin) (void);
145 + /* local settings */
151 +int i2c_mcf_add_bus(struct i2c_adapter *);
152 +int i2c_mcf_del_bus(struct i2c_adapter *);
154 +#endif /* I2C_ALGO_MCF_H */
156 +++ b/drivers/i2c/busses/i2c-mcf-slave.c
159 + * i2c-mcf-slave.c - support adpater slave mode, now only support
160 + * mcf5445x platform
162 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
163 + * Lanttor Guo <lanttor.guo@freescale.com>
165 + * This program is free software; you can redistribute it and/or modify
166 + * it under the terms of the GNU General Public License as published by
167 + * the Free Software Foundation; either version 2 of the License, or
168 + * (at your option) any later version.
171 +#ifdef CONFIG_I2C_SLAVE_TEST
175 +#include <linux/init.h>
176 +#include <linux/module.h>
177 +#include <linux/kernel.h>
178 +#include <linux/errno.h>
179 +#include <linux/i2c.h>
180 +#include <linux/delay.h>
181 +#include <linux/string.h>
182 +#include <linux/platform_device.h>
183 +#include <linux/interrupt.h>
184 +#include <linux/proc_fs.h>
185 +#include <linux/types.h>
186 +#include <asm/coldfire.h>
187 +#include <asm/mcfsim.h>
188 +#include <asm/irq.h>
189 +#include <asm/mcfi2c.h>
190 +#if defined(CONFIG_M5445X)
191 +#include <asm/mcf5445x_intc.h>
195 +#define SLAVE_HANDLER_NAME "mcf-i2c slave handler"
196 +#define I2C_BUFFER_SIZE 50
198 +/* Structure for storing I2C transfer data */
200 + int tx_index; /* TX index */
201 + int rx_index; /* RX index */
202 + u16 length; /* Length of the buffer in bytes */
203 + u8 buf[I2C_BUFFER_SIZE]; /* Data buffer */
206 +struct i2c_buffer i2c_tx_buffer;
207 +struct i2c_buffer i2c_rx_buffer;
209 +u8 *tx_string = "abcdefghijklmnopqrstuvwxyz0123456789)!@#$%^&*([].";
212 + * I2C slave mode interrupt handler
215 +static irqreturn_t i2c_slave_handler(int this_irq, void *dev_id)
221 + printk(KERN_INFO "i2c adapter slave mode irq handler.\n");
224 + /* Clear I2C interupt flag */
225 + MCF_I2SR = ~MCF_I2SR_IIF;
227 + /* Check if this device is in Master or Slave Mode. */
228 + if (MCF_I2CR & MCF_I2CR_MSTA) {
229 + /* Master mode, do nothing here */
230 + printk(KERN_INFO "i2c master mode at %s(), do nothing!\n",
234 + /* Slave Mode - Check if Arbitration Lost. */
235 + if (MCF_I2SR & MCF_I2SR_IAL) {
238 + printk(KERN_INFO "Arbitration Lost.\n");
241 + /* Clear IAL bit */
242 + MCF_I2SR &= ~MCF_I2SR_IAL;
244 + /* Arbitration Lost -
245 + * Check if this device is being addressed as slave.
246 + *(If not, nothing more needs to be done.)
248 + if (MCF_I2SR & MCF_I2SR_IAAS) {
249 + /* Addressed as slave -
250 + * Check if master was reading from slave or
251 + * writing to slave.
253 + if (MCF_I2SR & MCF_I2SR_SRW) {
254 + /* Set tx_index to 0 */
255 + if (i2c_tx_buffer.length == 0) {
256 + i2c_tx_buffer.length =
258 + i2c_tx_buffer.tx_index = 0;
261 + /* Master was reading from slave -
262 + * Set Transmit Mode.
264 + MCF_I2CR |= MCF_I2CR_MTX;
266 + /* Write data to MBDR. */
267 + tmp_index = i2c_tx_buffer.tx_index++;
268 + MCF_I2DR = i2c_tx_buffer.buf[tmp_index];
269 + i2c_tx_buffer.length--;
272 + printk(KERN_INFO "Arbitration Lost: "
273 + "Addressed as slave - "
277 + /* Set rx_index to 0 */
278 + i2c_rx_buffer.rx_index = 0;
280 + /* Master was writing to slave -
281 + Set Receive Mode. */
282 + MCF_I2CR &= ~MCF_I2CR_MTX;
284 + /* Dummy read from MBDR, to clear
286 + dummy_read = MCF_I2DR;
289 + printk(KERN_INFO "Arbitration Lost: "
290 + "Addressed as slave - "
297 + /* Arbitration Not Lost - Check if data byte is this
298 + devices's Slave Address byte. */
299 + if (MCF_I2SR & MCF_I2SR_IAAS) {
300 + /* Data byte is Slave Address byte -
301 + Check Slave Read/Write bit. */
302 + if (MCF_I2SR & MCF_I2SR_SRW) {
303 + /* Set tx_index to 0 */
304 + if (i2c_tx_buffer.length == 0) {
305 + i2c_tx_buffer.length =
307 + i2c_tx_buffer.tx_index = 0;
310 + /* Master was reading from slave -
311 + Set Transmit Mode. */
312 + MCF_I2CR |= MCF_I2CR_MTX;
314 + /* Write data to MBDR. */
315 + tmp_index = i2c_tx_buffer.tx_index++;
316 + MCF_I2DR = i2c_tx_buffer.buf[tmp_index];
317 + i2c_tx_buffer.length--;
320 + tmp_index = i2c_tx_buffer.tx_index - 1;
321 + printk(KERN_INFO "Slave TX: First byte"
323 + i2c_tx_buffer.buf[tmp_index]);
326 + /* Master has specified Slave Receive
327 + Mode. Set Receive Mode. (Writing to
328 + MBCR clears IAAS.) */
330 + /* Set rx_index to 0 */
331 + i2c_rx_buffer.rx_index = 0;
333 + MCF_I2CR &= ~MCF_I2CR_MTX;
335 + /* Dummy read from MBDR, to clear
337 + dummy_read = MCF_I2DR;
340 + printk(KERN_INFO "Slave RX: Receive "
345 + /* Data byte received is not Slave Address byte
346 + Check if this device is in Transmit or
348 + if (MCF_I2CR & MCF_I2CR_MTX) {
349 + /* Last byte received? */
350 + if (MCF_I2SR & MCF_I2SR_RXAK) {
351 + MCF_I2CR &= ~MCF_I2CR_MTX;
352 + dummy_read = MCF_I2DR;
355 + printk(KERN_INFO "Slave TX: "
356 + "Last byte has been "
360 + /* Write data to MBDR. */
362 + i2c_tx_buffer.tx_index++;
364 + i2c_tx_buffer.buf[tmp_index];
365 + i2c_tx_buffer.length--;
367 + if (i2c_tx_buffer.length == 0) {
368 + i2c_tx_buffer.length =
370 + i2c_tx_buffer.tx_index =
376 + /* Receive Mode - Read data from
377 + MBDR and store it. */
378 + tmp_index = i2c_rx_buffer.rx_index++;
379 + i2c_rx_buffer.buf[tmp_index] = MCF_I2DR;
380 + i2c_rx_buffer.length++;
384 + return IRQ_HANDLED;
388 +#ifdef CONFIG_PROC_FS
391 + * Info exported via "/proc/driver/i2c".
394 +static int gen_i2c_proc_output(char *buf)
403 + MCF_I2CR, MCF_I2SR, MCF_I2DR);
408 +static int gen_i2c_read_proc(char *page, char **start, off_t off,
409 + int count, int *eof, void *data)
411 + int len = gen_i2c_proc_output(page);
412 + if (len <= off+count)
414 + *start = page + off;
423 +static int __init gen_i2c_proc_init(void)
425 + struct proc_dir_entry *r;
427 + r = create_proc_read_entry("driver/i2c-adaptor-register", 0, NULL,
428 + gen_i2c_read_proc, NULL);
434 +static inline int gen_i2c_proc_init(void) { return 0; }
435 +#endif /* CONFIG_PROC_FS */
438 + * Initalize I2C module
440 +static int __init i2c_coldfire_init(void)
446 + printk(KERN_INFO "init i2c adaptor slave mode!\n");
449 + /* Initialize the tx buffer */
450 + strcpy((char *)&i2c_tx_buffer.buf, (const char *)tx_string);
451 + i2c_tx_buffer.length = I2C_BUFFER_SIZE;
453 +#if defined(CONFIG_M5445X)
455 + * Initialize the GPIOs for I2C
457 + MCF_GPIO_PAR_FECI2C |= (0
458 + | MCF_GPIO_PAR_FECI2C_PAR_SDA(3)
459 + | MCF_GPIO_PAR_FECI2C_PAR_SCL(3));
462 + /* Set transmission frequency 0x19 = ~100kHz */
465 + /* set the I2C slave address */
468 + /* Enable I2C module and if IBB is set, do the special initialzation */
469 + /* procedures as are documented */
471 + if ((MCF_I2SR & MCF_I2SR_IBB) == 1) {
472 + printk(KERN_INFO "%s - do special I2C init procedures\n",
476 + dummy_read = MCF_I2DR;
481 + MCF_I2CR |= (MCF_I2CR_IEN | MCF_I2CR_IIEN);
483 + /* default I2C mode is - slave and receive */
484 + MCF_I2CR &= ~(MCF_I2CR_MSTA | MCF_I2CR_MTX);
486 + retval = request_irq(IRQ, i2c_slave_handler, IRQF_DISABLED,
487 + SLAVE_HANDLER_NAME, NULL);
489 + printk(KERN_INFO "request_irq for i2c slave mode failed!\n");
491 + retval = gen_i2c_proc_init();
494 + printk(KERN_INFO "gen /proc/i2c-adaptor-register for i2c slave mode failed!\n");
500 + * I2C module exit function
503 +static void __exit i2c_coldfire_exit(void)
505 + /* disable I2C and Interrupt */
506 + MCF_I2CR &= ~(MCF_I2CR_IEN | MCF_I2CR_IIEN);
507 + free_irq(IRQ, NULL);
511 +MODULE_DESCRIPTION("MCF5445x I2C adaptor slave mode support");
512 +MODULE_LICENSE("GPL");
514 +module_init(i2c_coldfire_init);
515 +module_exit(i2c_coldfire_exit);
517 +++ b/drivers/i2c/busses/i2c-mcf.c
520 + * Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All Rights Reserved.
521 + * Lanttor.Guo@freescale.com
523 + * I2C bus driver on mcfv4/mcfv4e platform
525 + * This program is free software; you can redistribute it and/or modify
526 + * it under the terms of the GNU General Public License as published by
527 + * the Free Software Foundation; either version 2 of the License, or
528 + * (at your option) any later version.
530 +#include <linux/i2c.h>
531 +#include "i2c-algo-mcf.h"
533 +#include <linux/init.h>
534 +#include <linux/kernel.h>
535 +#include <linux/module.h>
536 +#include <linux/delay.h>
537 +#include <linux/platform_device.h>
538 +#include <linux/sched.h>
539 +#include <linux/interrupt.h>
540 +#include <linux/io.h>
541 +#include <linux/proc_fs.h>
543 +#include <asm/coldfire.h>
544 +#include <asm/mcfi2c.h>
546 +#if defined(CONFIG_M547X_8X)
547 +#include <asm/m5485sim.h>
548 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
549 +#include <asm/mcfsim.h>
552 +#define get_clock(adap) (clock)
553 +#define get_own(adap) (own)
555 +#if defined(CONFIG_M547X_8X)
556 +static int clock = 0x3b;
557 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
558 +static int clock = 0x19;
560 +module_param(clock, int, 0);
561 +MODULE_PARM_DESC(clock,
562 + "Set I2C clock in kHz: 400=fast mode (default == 100khz)");
564 +static int own = 0x78;
565 +module_param(own, int, 0);
566 +MODULE_PARM_DESC(clock, "Set I2C Master controller address");
568 +static struct i2c_algo_mcf_data i2c_mcf_board_data = {
572 +static struct i2c_adapter i2c_mcf_board_adapter = {
573 + .owner = THIS_MODULE,
574 + .name = "mcf i2c adapter",
575 + .algo_data = &i2c_mcf_board_data,
576 + .class = I2C_CLASS_HWMON,
581 + * static void i2c_start()
583 + * Generates START signal
587 + struct i2c_algo_mcf_data *adap
589 + MCF_I2CR |= MCF_I2CR_MSTA;
594 + * static void i2c_stop()
596 + * Generates STOP signal
600 + struct i2c_algo_mcf_data *adap
602 + MCF_I2CR &= ~MCF_I2CR_MSTA;
607 + struct i2c_algo_mcf_data *adap
609 + return !(MCF_I2SR & MCF_I2SR_RXAK);
613 + * static void wait_for_bb()
615 + * Wait for bus idle state
619 + struct i2c_algo_mcf_data *adap
622 + for (i = 0; i < adap->timeout; i++) {
623 + if (!(MCF_I2SR & MCF_I2SR_IBB))
627 + printk(KERN_ERR "%s: timeout", __func__);
632 + * static void wait_for_not_bb()
634 + * Wait for bus busy state
638 + struct i2c_algo_mcf_data *adap
641 + for (i = 0; i < adap->timeout; i++) {
642 + if (MCF_I2SR & MCF_I2SR_IBB)
646 + printk(KERN_ERR "%s: timeout", __func__);
651 + * static void wait_xfer_done()
653 + * Wait for transfer to complete
657 + struct i2c_algo_mcf_data *adap
661 + for (i = 0; i < adap->timeout; i++) {
662 + if (MCF_I2SR & MCF_I2SR_IIF) {
663 + MCF_I2SR &= ~MCF_I2SR_IIF;
668 + printk(KERN_ERR "%s: timeout", __func__);
674 + * static void i2c_set_addr()
676 + * Sets slave address to communicate
680 + struct i2c_algo_mcf_data *adap,
681 + struct i2c_msg *msg,
684 + unsigned short flags = msg->flags;
685 + unsigned char addr;
686 + MCF_I2CR |= MCF_I2CR_MTX;
687 + if ((flags & I2C_M_TEN)) {
688 + /* 10 bit address not supported yet */
691 + /* normal 7bit address */
692 + addr = (msg->addr << 1);
693 + if (flags & I2C_M_RD)
695 + if (flags & I2C_M_REV_DIR_ADDR)
705 + * static void mcf_i2c_init()
707 + * Perform ColdFire i2c initialization
710 +mcf_i2c_init(struct i2c_algo_mcf_data *adap)
714 + /* Setup GPIO lines */
715 +#if defined(CONFIG_M547X_8X)
716 + MCF_PAR_FECI2CIRQ |= MCF_PAR_SDA;
717 + MCF_PAR_FECI2CIRQ |= MCF_PAR_SCL;
718 +#elif defined(CONFIG_M5445X)
719 + MCF_GPIO_PAR_FECI2C |= (0
720 + | MCF_GPIO_PAR_FECI2C_PAR_SDA(3)
721 + | MCF_GPIO_PAR_FECI2C_PAR_SCL(3));
722 +#elif defined(CONFIG_M5441X)
723 + MCF_GPIO_PAR_CANI2C =
724 + (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SCL_MASK) |
725 + MCF_GPIO_PAR_CANI2C_I2C0SCL_I2C0SCL;
726 + MCF_GPIO_PAR_CANI2C =
727 + (MCF_GPIO_PAR_CANI2C & MCF_GPIO_PAR_CANI2C_I2C0SDA_MASK) |
728 + MCF_GPIO_PAR_CANI2C_I2C0SDA_I2C0SDA;
731 + /* Ensure slaves are in idle state */
732 + if (MCF_I2SR & MCF_I2SR_IBB) {
733 +#if defined(CONFIG_M547X_8X)
741 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
751 + /* setup SCL clock */
752 + MCF_I2FDR = get_clock(adap);
754 + /* set slave address */
755 + MCF_I2AR = get_own(adap);
757 + /* enable I2C module */
758 +#if defined(CONFIG_M5441X)
759 + MCF_I2CR = (MCF_I2CR_IEN | MCF_I2CR_IIEN);
761 + MCF_I2CR = MCF_I2CR_IEN;
765 +static int i2c_outb(
766 + struct i2c_adapter *i2c_adap,
770 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
772 + /* Put data to be sent */
774 + /* Wait for xfer completed*/
775 + timeout = wait_xfer_done(adap);
779 + printk(KERN_ERR "i2c-algo-mcf: %s i2c_write: "
780 + "error - timeout.\n", i2c_adap->name);
781 + return -EREMOTEIO; /* got a better one ?? */
789 + * static void mcf_sendbytes()
791 + * Perform tx data transfer
795 + struct i2c_adapter *i2c_adap,
797 + int count, int last
799 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
802 + /* Set master TX mode */
803 + MCF_I2CR |= MCF_I2CR_MTX;
805 + for (i = 0; i < count; ++i) {
806 + printk(KERN_DEBUG "i2c-algo-mcf: %s i2c_write: writing %2.2X\n",
807 + i2c_adap->name, buf[i]&0xff);
808 + ret = i2c_outb(i2c_adap, buf[i]);
816 + /* i2c_repstart(adap);*/
824 + * static void mcf_readbytes()
826 + * Perform rx data transfer
830 + struct i2c_adapter *i2c_adap,
832 + int count, int last
835 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
838 + /* Set master RX mode */
839 + MCF_I2CR &= ~MCF_I2CR_MTX;
840 + MCF_I2CR &= ~MCF_I2CR_TXAK;
843 + for (i = 0; i < count-1; i++) {
844 + if (wait_xfer_done(adap)) {
848 + "i2c-algo-mcf: mcf_readbytes timed out.\n");
852 + /* store next data byte */
856 + if (wait_xfer_done(adap)) {
859 + printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n");
863 + /* Disable acknowlege (set I2CR.TXAK) */
864 + MCF_I2CR |= MCF_I2CR_TXAK;
866 + if (wait_xfer_done(adap)) {
869 + printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n");
877 + /* i2c_repstart(adap);*/
885 + * static void mcf_xfer()
887 + * Perform master data I/O transfer
891 + struct i2c_adapter *i2c_adap,
892 + struct i2c_msg *msgs,
895 + struct i2c_algo_mcf_data *adap = i2c_adap->algo_data;
896 + struct i2c_msg *pmsg;
898 + int ret = 0, timeout;
900 + /* Skip own address */
901 + if (get_own(adap) == (msgs[0].addr << 1))
904 + /* Ensure slaves are in idle state */
905 + if (MCF_I2SR & MCF_I2SR_IBB) {
906 +#if defined(CONFIG_M547X_8X)
910 + timeout = MCF_I2DR;
914 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
917 + timeout = MCF_I2DR;
924 + /* setup SCL clock */
925 + MCF_I2FDR = get_clock(adap);
926 + /* set slave address */
927 + MCF_I2AR = get_own(adap);
928 + /* enable I2C module */
929 +#if defined(CONFIG_M5441X)
930 + MCF_I2CR = (MCF_I2CR_IEN | MCF_I2CR_IIEN);
932 + MCF_I2CR = MCF_I2CR_IEN;
934 + MCF_I2CR |= MCF_I2CR_TXAK;
936 + /* Check for bus busy */
939 + for (i = 0; ret >= 0 && i < num; i++) {
940 + if (MCF_I2SR & MCF_I2SR_IBB) {
941 +#if defined(CONFIG_M547X_8X)
945 + timeout = MCF_I2DR;
949 +#elif defined(CONFIG_M5445X) || defined(CONFIG_M5441X)
952 + timeout = MCF_I2DR;
958 + /* setup SCL clock */
959 + MCF_I2FDR = get_clock(adap);
960 + /* set slave address */
961 + MCF_I2AR = get_own(adap);
962 + /* enable I2C module */
963 +#if defined(CONFIG_M5441X)
964 + MCF_I2CR = (MCF_I2CR_IEN | MCF_I2CR_IIEN);
966 + MCF_I2CR = MCF_I2CR_IEN;
968 + MCF_I2CR |= MCF_I2CR_TXAK;
970 + /* Check for bus busy */
975 + printk(KERN_DEBUG "i2c-algo-mcf: Doing %s %d bytes "
976 + "to 0x%02x - %d of %d messages\n",
977 + pmsg->flags & I2C_M_RD ? "read" : "write",
978 + pmsg->len, pmsg->addr, i + 1, num);
984 + /* Wait for Bus Busy */
985 + wait_for_not_bb(adap);
987 + MCF_I2CR |= MCF_I2CR_MTX;
989 + ret = i2c_set_addr(adap, pmsg, i2c_adap->retries);
993 + /* Wait for address transfer completion */
994 + wait_xfer_done(adap);
996 + /* Check for ACK */
997 + if (!i2c_getack(adap)) {
1000 + printk(KERN_DEBUG "i2c-algo-mcf: No ack after "
1001 + "send address in mcf_xfer\n");
1002 + return -EREMOTEIO;
1005 + printk(KERN_DEBUG "i2c-algo-mcf: Msg %d, "
1006 + "addr = 0x%x, flags = 0x%x, len = %d\n",
1007 + i, msgs[i].addr, msgs[i].flags, msgs[i].len);
1009 + if (pmsg->flags & I2C_M_RD) {
1010 + /* read bytes into buffer*/
1011 + ret = mcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
1014 + if (ret != pmsg->len) {
1015 + printk(KERN_DEBUG "i2c-algo-mcf: fail: "
1016 + "only read %d bytes.\n", ret);
1018 + printk(KERN_DEBUG "i2c-algo-mcf: "
1019 + "read %d bytes.\n", ret);
1022 + /* write bytes into buffer*/
1023 + ret = mcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
1025 + if (ret != pmsg->len) {
1026 + printk(KERN_DEBUG "i2c-algo-mcf: fail: "
1027 + "only wrote %d bytes.\n", ret);
1029 + printk(KERN_DEBUG "i2c-algo-mcf: wrote"
1030 + "%d bytes.\n", ret);
1036 + /* Disable I2C module */
1043 + * static void mcf_func()
1045 + * Return algorithm funtionality
1049 + struct i2c_adapter *i2c_adap
1051 + return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C;
1055 + * ColdFire bus algorithm callbacks
1057 +static struct i2c_algorithm mcf_algo = {
1058 + .master_xfer = mcf_xfer,
1059 + .functionality = mcf_func,
1062 +/***********************************************************/
1063 +struct coldfire_i2c {
1064 + void __iomem *base;
1065 + struct resource *irqarea;
1066 + struct resource *ioarea;
1068 + struct i2c_adapter *adap;
1073 + * registering functions to load algorithms at runtime
1075 +int i2c_mcf_add_bus(struct i2c_adapter *adap)
1077 + struct i2c_algo_mcf_data *mcf_adap = adap->algo_data;
1079 + /*adap->id |= mcf_algo.id;*/
1080 + adap->algo = &mcf_algo;
1081 + adap->timeout = 100;
1083 + mcf_i2c_init(mcf_adap);
1085 + i2c_add_numbered_adapter(adap);
1090 +static int mcf_i2c_probe(struct platform_device *pdev)
1092 + struct coldfire_i2c *i2c;
1095 + /************************************************************/
1096 + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
1098 + printk(KERN_ERR "%s kzalloc coldfire_i2c faile\n",
1102 + /****************************************************************/
1103 + platform_set_drvdata(pdev, i2c);
1105 + i2c->adap = &i2c_mcf_board_adapter;
1106 + i2c->adap->dev.parent = &pdev->dev;
1107 + i2c->adap->nr = pdev->id;
1108 + rc = i2c_mcf_add_bus(i2c->adap);
1110 + printk(KERN_ERR "%s - failed to add adapter\n", __func__);
1115 + printk(KERN_INFO "i2c-algo-mcf.o: I2C ColdFire algorithm"
1116 + " module is loaded.\n");
1124 +static int mcf_i2c_remove(struct platform_device *pdev)
1126 + struct coldfire_i2c *i2c = platform_get_drvdata(pdev);
1128 + i2c_del_adapter(i2c->adap);
1129 + platform_set_drvdata(pdev, NULL);
1130 + iounmap(i2c->base);
1135 +/* Structure for a device driver */
1136 +static struct platform_driver mcf_i2c_driver = {
1137 + .probe = mcf_i2c_probe,
1138 + .remove = mcf_i2c_remove,
1140 + .owner = THIS_MODULE,
1141 + .name = "mcf-i2c",
1145 +#ifdef CONFIG_PROC_FS
1148 + * Info exported via "/proc/driver/i2c".
1151 +static int gen_i2c_proc_output(char *buf)
1160 + MCF_I2CR, MCF_I2SR, MCF_I2DR);
1165 +static int gen_i2c_read_proc(char *page, char **start, off_t off,
1166 + int count, int *eof, void *data)
1168 + int len = gen_i2c_proc_output(page);
1169 + if (len <= off+count)
1171 + *start = page + off;
1180 +static int __init gen_i2c_proc_init(void)
1182 + struct proc_dir_entry *r;
1184 + r = create_proc_read_entry("driver/i2c-adaptor-register", 0, NULL,
1185 + gen_i2c_read_proc, NULL);
1191 +static inline int gen_i2c_proc_init(void) { return 0; }
1192 +#endif /* CONFIG_PROC_FS */
1194 +static int __init coldfire_i2c_init(void)
1198 + retval = gen_i2c_proc_init();
1200 + printk(KERN_INFO "generate /proc/i2c-adaptor-register "
1201 + "for i2c master mode failed!\n");
1203 + return platform_driver_register(&mcf_i2c_driver);
1206 +static void __exit coldfire_i2c_exit(void)
1208 + platform_driver_unregister(&mcf_i2c_driver);
1211 +module_init(coldfire_i2c_init);
1212 +module_exit(coldfire_i2c_exit);
1214 +MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
1215 +MODULE_DESCRIPTION("I2C-Bus adapter for MCFV4/MCFV4E processors");
1216 +MODULE_LICENSE("GPL");