| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- From e1618e943f60a4f8f778c4f7c389e2fa13eb0a83 Mon Sep 17 00:00:00 2001
- From: Kurt Mahan <[email protected]>
- Date: Thu, 26 Jun 2008 16:29:56 -0600
- Subject: [PATCH] Add I2C support for the M5445x platforms.
- LTIBName: m5445x-i2c
- Signed-off-by: Kurt Mahan <[email protected]>
- ---
- drivers/i2c/busses/Kconfig | 10 +
- drivers/i2c/busses/Makefile | 1 +
- drivers/i2c/busses/i2c-mcf.c | 573 ++++++++++++++++++++++++++++++++++++++++++
- drivers/i2c/busses/i2c-mcf.h | 75 ++++++
- 4 files changed, 659 insertions(+), 0 deletions(-)
- create mode 100644 drivers/i2c/busses/i2c-mcf.c
- create mode 100644 drivers/i2c/busses/i2c-mcf.h
- --- a/drivers/i2c/busses/Kconfig
- +++ b/drivers/i2c/busses/Kconfig
- @@ -302,6 +302,16 @@ config I2C_POWERMAC
- This support is also available as a module. If so, the module
- will be called i2c-powermac.
-
- +config I2C_MCF
- + tristate "MCF ColdFire"
- + depends on I2C && EXPERIMENTAL
- + help
- + If you say yes to this option, support will be included for the
- + I2C on most ColdFire CPUs
- +
- + This driver can also be built as a module. If so, the module
- + will be called i2c-mcf.
- +
- config I2C_MPC
- tristate "MPC107/824x/85xx/52xx/86xx"
- depends on PPC32
- --- a/drivers/i2c/busses/Makefile
- +++ b/drivers/i2c/busses/Makefile
- @@ -53,6 +53,7 @@ obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3
- obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
- obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
- obj-$(CONFIG_I2C_MCF548x) += i2c-mcf548x.o
- +obj-$(CONFIG_I2C_MCF) += i2c-mcf.o
-
- ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
- EXTRA_CFLAGS += -DDEBUG
- --- /dev/null
- +++ b/drivers/i2c/busses/i2c-mcf.c
- @@ -0,0 +1,573 @@
- +/*
- + i2c-mcf.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
- +
- + Copyright (c) 2005, Derek CL Cheung <[email protected]>
- + <http://www3.sympatico.ca/derek.cheung>
- +
- + Copyright (c) 2006-2007, emlix
- + Sebastian Hess <[email protected]>
- +
- + Copyright (c) 2006-2007 Freescale Semiconductor, Inc
- + Yaroslav Vinogradov <[email protected]>
- + Matt Waddel <[email protected]>
- +
- + This program is free software; you can redistribute it and/or modify
- + it under the terms of the GNU General Public License as published by
- + the Free Software Foundation; either version 2 of the License, or
- + (at your option) any later version.
- +
- + This program is distributed in the hope that it will be useful,
- + but WITHOUT ANY WARRANTY; without even the implied warranty of
- + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + GNU General Public License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with this program; if not, write to the Free Software
- + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- +
- + Changes:
- + v0.1 26 March 2005
- + Initial Release - developed on uClinux with 2.6.9 kernel
- +
- + v0.2 29 May 2006
- + Modified to be more generic and added support for
- + i2c_master_xfer
- +
- + This I2C adaptor supports the ColdFire CPU I2C module. Since most Coldfire
- + CPUs' I2C module use the same register set (e.g., MCF5249), the code is very
- + portable and re-usable to other Coldfire CPUs.
- +
- + The transmission frequency is set at about 100KHz for the CPU board with
- + 8MHz crystal. If the CPU board uses different system clock frequency, you
- + should change the following line:
- + static int __init i2c_coldfire_init(void)
- + {
- + .........
- + // Set transmission frequency 0x15 = ~100kHz
- + *MCF_I2C_I2FDR = 0x15;
- + ........
- + }
- +
- + Remember to perform a dummy read to set the ColdFire CPU's I2C module for
- + read before reading the actual byte from a device
- +
- + The I2C_SM_BUS_BLOCK_DATA function are not yet ready but most lm_senors
- + do not care
- +*/
- +
- +#include <linux/init.h>
- +#include <linux/module.h>
- +#include <linux/kernel.h>
- +#include <linux/errno.h>
- +#include <linux/i2c.h>
- +#include <linux/delay.h>
- +#include <linux/string.h>
- +#include <asm/coldfire.h>
- +#include <asm/mcfsim.h>
- +#include <asm/types.h>
- +#include <linux/platform_device.h>
- +#include "i2c-mcf.h"
- +
- +
- +static struct i2c_algorithm coldfire_algorithm = {
- + /*.name = "ColdFire I2C algorithm",
- + .id = I2C_ALGO_SMBUS,*/
- + .smbus_xfer = coldfire_i2c_access,
- + .master_xfer = coldfire_i2c_master,
- + .functionality = coldfire_func,
- +};
- +
- +
- +static struct i2c_adapter coldfire_adapter = {
- + .owner = THIS_MODULE,
- + .class = I2C_CLASS_HWMON,
- + .algo = &coldfire_algorithm,
- + .name = "ColdFire I2C adapter",
- +};
- +
- +
- +__u16 lastaddr;
- +__u16 lastop;
- +
- +static inline int coldfire_do_first_start(__u16 addr,__u16 flags)
- +{
- + int err;
- + /*
- + * Generate a stop and put the I2C module into slave mode
- + */
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
- +
- + /*
- + * Generate a new Start signal
- + */
- + err = coldfire_i2c_start(flags & I2C_M_RD ? I2C_SMBUS_READ : I2C_SMBUS_WRITE,
- + addr, FIRST_START);
- + if(err) return err;
- +
- + lastaddr = addr;
- + lastop = flags & I2C_M_RD; /* Ensure everything for new start */
- + return 0;
- +}
- +
- +
- +/*
- + * read one byte data from the I2C bus
- + */
- +static int coldfire_read_data(u8 * const rxData, const enum I2C_ACK_TYPE ackType) {
- +
- + int timeout;
- +
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MTX; /* master receive mode*/
- +
- + if (ackType == NACK)
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK; /* generate NA */
- + else
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK; /* generate ACK */
- +
- +
- + /* read data from the I2C bus */
- + *rxData = *MCF_I2C_I2DR;
- +
- + /* printk(">>> %s I2DR data is %.2x \n", __FUNCTION__, *rxData); */
- +
- + /* wait for data transfer to complete */
- + timeout = 500;
- + while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
- + udelay(1);
- + if (timeout <= 0)
- + printk("%s - I2C IIF never set. Timeout is %d \n", __FUNCTION__,
- + timeout);
- +
- +
- + /* reset the interrupt bit */
- + *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
- +
- + if (timeout <= 0 )
- + return -1;
- + else
- + return 0;
- +
- +};
- +
- +
- +/*
- + * write one byte data onto the I2C bus
- + */
- +static int coldfire_write_data(const u8 txData) {
- +
- + int timeout;
- +
- + timeout = 500;
- +
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_MTX; /* I2C module into TX mode */
- + *MCF_I2C_I2DR = txData; /* send the data */
- +
- + /* wait for data transfer to complete */
- + /* rely on the interrupt handling bit */
- + timeout = 500;
- + while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
- + udelay(1);
- + if (timeout <=0)
- + printk("%s - I2C IIF never set. Timeout is %d \n", __FUNCTION__,
- + timeout);
- +
- +
- + /* reset the interrupt bit */
- + *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
- +
- + if (timeout <= 0 )
- + return -1;
- + else
- + return 0;
- +
- +};
- +
- +
- +
- +
- +/*
- + * Generate I2C start or repeat start signal
- + * Combine the 7 bit target_address and the R/W bit and put it onto the I2C bus
- + */
- +static int coldfire_i2c_start(const char read_write, const u16 target_address, const enum I2C_START_TYPE start_type) {
- +
- + int timeout;
- +
- + /* printk(">>> %s START TYPE %s \n", __FUNCTION__,
- + start_type == FIRST_START ? "FIRST_START":"REPEAT_START");*/
- +
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_IEN;
- +
- + if (start_type == FIRST_START) {
- + /* Make sure the I2C bus is idle */
- + timeout = 500; /* 500us timeout */
- + while (timeout-- && (*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB))
- + udelay(1);
- + if (timeout <= 0) {
- + printk("%s - I2C bus always busy in the past 500us timeout is %d \n", __FUNCTION__, timeout);
- + goto check_rc;
- + }
- + /* generate a START and put the I2C module into MASTER TX mode*/
- + *MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);
- +
- + /* wait for bus busy to be set */
- + timeout = 500;
- + while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB))
- + udelay(1);
- + if (timeout <= 0) {
- + printk("%s - I2C bus is never busy after START. Timeout is %d \n", __FUNCTION__, timeout);
- + goto check_rc;
- + }
- +
- + } else {
- + /* this is repeat START */
- + udelay(500); /* need some delay before repeat start */
- + *MCF_I2C_I2CR |= (MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_RSTA);
- + }
- +
- +
- + /* combine the R/W bit and the 7 bit target address and put it onto
- + the I2C bus */
- + *MCF_I2C_I2DR = ((target_address & 0x7F) << 1) | (read_write == I2C_SMBUS_WRITE ? 0x00 : 0x01);
- +
- + /* wait for bus transfer to complete */
- + /* when one byte transfer is completed, IIF set at the faling edge of
- + the 9th clock */
- + timeout = 500;
- + while (timeout-- && !(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF))
- + udelay(1);
- + if (timeout <= 0)
- + printk("%s - I2C IIF never set. Timeout is %d \n", __FUNCTION__, timeout);
- +
- +
- +check_rc:
- + /* reset the interrupt bit */
- + *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
- +
- + if (timeout <= 0)
- + return -1;
- + else
- + return 0;
- +};
- +
- +
- +/*
- + * 5282 SMBUS supporting functions
- + */
- +
- +static s32 coldfire_i2c_access(struct i2c_adapter *adap, u16 addr,
- + unsigned short flags, char read_write,
- + u8 command, int size, union i2c_smbus_data *data)
- +{
- + int rc = 0;
- + u8 rxData, tempRxData[2];
- +
- + switch (size) {
- + case I2C_SMBUS_QUICK:
- + rc = coldfire_i2c_start(read_write, addr, FIRST_START); /* generate START */
- + break;
- + case I2C_SMBUS_BYTE:
- + rc = coldfire_i2c_start(read_write, addr, FIRST_START);
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_TXAK; /*generate NA */
- + if (read_write == I2C_SMBUS_WRITE)
- + rc += coldfire_write_data(command);
- + else {
- + coldfire_read_data(&rxData, NACK);/*dummy read*/
- + rc += coldfire_read_data(&rxData, NACK);
- + data->byte = rxData;
- + }
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK; /* reset ACK bit */
- + break;
- + case I2C_SMBUS_BYTE_DATA:
- + rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr, FIRST_START);
- + rc += coldfire_write_data(command);
- + if (read_write == I2C_SMBUS_WRITE)
- + rc += coldfire_write_data(data->byte);
- + else {
- + /* This is SMBus READ Byte Data Request.
- + Perform REPEAT START */
- + rc += coldfire_i2c_start(I2C_SMBUS_READ, addr,
- + REPEAT_START);
- + coldfire_read_data(&rxData, ACK);/* dummy read*/
- + /* Disable Acknowledge, generate STOP after
- + next byte transfer */
- + rc += coldfire_read_data(&rxData, NACK);
- + data->byte = rxData;
- + }
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;/* reset to normal ACk */
- + break;
- + case I2C_SMBUS_PROC_CALL:
- + case I2C_SMBUS_WORD_DATA:
- + dev_info(&adap->dev, "size = I2C_SMBUS_WORD_DATA \n");
- + rc = coldfire_i2c_start(I2C_SMBUS_WRITE, addr,
- + FIRST_START);
- + rc += coldfire_write_data(command);
- + if (read_write == I2C_SMBUS_WRITE) {
- + rc += coldfire_write_data(data->word & 0x00FF);
- + rc += coldfire_write_data((data->word & 0x00FF) >> 8);
- + } else {
- + /* This is SMBUS READ WORD request.
- + Peform REPEAT START */
- + rc += coldfire_i2c_start(I2C_SMBUS_READ, addr,
- + REPEAT_START);
- + coldfire_read_data(&rxData, ACK);/* dummy read*/
- + /* Disable Acknowledge, generate STOP after
- + next byte transfer */
- + /* read the MS byte from the device */
- + rc += coldfire_read_data(&rxData, NACK);
- + tempRxData[1] = rxData;
- + /* read the LS byte from the device */
- + rc += coldfire_read_data(&rxData, NACK);
- + tempRxData[0] = rxData;
- + /* the host driver expect little endian
- + convention. Swap the byte */
- + data->word = (tempRxData[0] << 8)|tempRxData[1];
- + }
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK;
- + break;
- + case I2C_SMBUS_BLOCK_DATA:
- + /* Not done yet */
- + break;
- + default:
- + printk("Unsupported I2C size \n");
- + rc = -1;
- + break;
- + };
- +
- + /* Generate a STOP and put I2C module into slave mode */
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
- +
- + /* restore interrupt */
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_IIEN;
- +
- + if (rc < 0)
- + return -1;
- + else
- + return 0;
- +};
- +
- +
- +/*
- + * List the SMBUS functions supported by this I2C adaptor
- + * Also tell the I2C Subsystem that we are able of master_xfer()
- + */
- +static u32 coldfire_func(struct i2c_adapter *adapter)
- +{
- + return(I2C_FUNC_SMBUS_QUICK |
- + I2C_FUNC_SMBUS_BYTE |
- + I2C_FUNC_SMBUS_PROC_CALL |
- + I2C_FUNC_SMBUS_BYTE_DATA |
- + I2C_FUNC_SMBUS_WORD_DATA |
- + I2C_FUNC_I2C |
- + I2C_FUNC_SMBUS_BLOCK_DATA);
- +};
- +
- +static int coldfire_i2c_master(struct i2c_adapter *adap,struct i2c_msg *msgs,
- + int num)
- +{
- + u8 dummyRead;
- + struct i2c_msg *p;
- + int i, err = 0;
- + int ic=0;
- +
- + lastaddr = 0;
- + lastop = 8;
- +
- + /* disable the IRQ, we are doing polling */
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_IIEN;
- +
- + dev_dbg(&adap->dev,"Num of actions: %d\n", num);
- +
- + for (i = 0; !err && i < num; i++) {
- + p = &msgs[i];
- +
- +
- + if (!p->len)
- + {
- + dev_dbg(&adap->dev,"p->len == 0!\n");
- + continue;
- + }
- + /*
- + * Generate a new Start, if the target address differs from
- + * the last target, generate a stop in this case first
- + */
- + if(p->addr != lastaddr)
- + {
- + err = coldfire_do_first_start(p->addr,p->flags);
- + if(err)
- + {
- + dev_dbg(&adap->dev,"First Init failed!\n");
- + break;
- + }
- + }
- +
- + else if((p->flags & I2C_M_RD) != lastop)
- + {
- + /*
- + * If the Operational Mode changed, we need to do this
- + * here ...
- + */
- + dev_dbg(&adap->dev,"%s(): Direction changed, was: %d; is now: %d\n", __FUNCTION__, lastop, p->flags & I2C_M_RD);
- +
- + /* Last op was an read, now it's write: complete stop
- + and reinit */
- + if (lastop & I2C_M_RD)
- + {
- + dev_dbg(&adap->dev,"%s(): The device is in read state, we must reset!\n", __FUNCTION__);
- + if((err = coldfire_do_first_start(p->addr,p->flags)))
- + break;
- + }
- + else
- + {
- + dev_dbg(&adap->dev,"%s(): We switchted to read mode\n",__FUNCTION__);
- + if((err = coldfire_i2c_start((p->flags & I2C_M_RD) ? I2C_SMBUS_READ : I2C_SMBUS_WRITE,
- + p->addr, REPEAT_START)))
- + break;
- + }
- +
- + lastop = p->flags & I2C_M_RD; /* Save the last op */
- + }
- +
- + if (p->flags & I2C_M_RD)
- + {
- + /*
- + * When ever we get here, a new session was activated,
- + * so read a dummy byte
- + */
- + coldfire_read_data(&dummyRead, ACK);
- + /*
- + * read p->len -1 bytes with ACK to the slave,
- + * read the last byte without the ACK, to inform him
- + * about the stop afterwards
- + */
- + ic = 0;
- + while(!err && (ic < p->len-1 ))
- + {
- + err = coldfire_read_data(p->buf+ic, ACK );
- + ic++;
- + }
- + if(!err)
- + err = coldfire_read_data(p->buf+ic, NACK);
- + dev_dbg(&coldfire_adapter.dev,"read: %2x\n",p->buf[ic]);
- + }
- + else
- + {
- + if(p->len == 2)
- + dev_dbg(&coldfire_adapter.dev,"writing: 0x %2x %2x\n", p->buf[0], p->buf[1]);
- +
- + /*
- + * Write data to the slave
- + */
- + for(ic=0; !err && ic < p->len; ic++)
- + {
- + err = coldfire_write_data(p->buf[ic]);
- + if(err)
- + {
- + dev_dbg(&coldfire_adapter.dev, "Failed to write data\n");
- + }
- + }
- + }
- + }
- +
- + /*
- + * Put the device into slave mode to enable the STOP Generation
- + * (the RTC needs this)
- + */
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_MSTA;
- +
- + *MCF_I2C_I2CR &= ~MCF_I2C_I2CR_TXAK; /* reset the ACK bit */
- +
- + /* restore interrupt */
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_IIEN;
- +
- + /* Return the number of messages processed, or the error code. */
- + if (err == 0)
- + err = num;
- + return err;
- +}
- +
- +
- +/*
- + * Initalize the 5282 I2C module
- + * Disable the 5282 I2C interrupt capability. Just use callback
- + */
- +
- +static int __init i2c_coldfire_init(void)
- +{
- + int retval;
- + u8 dummyRead;
- +
- +#if defined(CONFIG_M532x) || defined(CONFIG_M5445X)
- + /*
- + * Initialize the GPIOs for I2C
- + */
- + MCF_GPIO_PAR_FECI2C |= (0
- + | MCF_GPIO_PAR_FECI2C_PAR_SDA(3)
- + | MCF_GPIO_PAR_FECI2C_PAR_SCL(3));
- +#elif defined(CONFIG_M5253)
- + {
- + volatile u32 *reg;
- + /* GPIO Bit 41 = SCL0, Bit 42 = SDA0 */
- + reg = (volatile u32 *)(MCF_MBAR2 + MCFSIM2_GPIO1FUNC);
- + *reg &= 0xFFFFF9FF;
- + }
- +#else
- + /* Initialize PASP0 and PASP1 to I2C functions, 5282 user guide 26-19 */
- + /* Port AS Pin Assignment Register (PASPAR) */
- + /* PASPA1 = 11 = AS1 pin is I2C SDA */
- + /* PASPA0 = 11 = AS0 pin is I2C SCL */
- + *MCF_GPIO_PASPAR |= 0x000F; /* u16 declaration */
- +#endif
- +
- +
- + /* Set transmission frequency 0x15 = ~100kHz */
- + *MCF_I2C_I2FDR = 0x15;
- +
- + /* set the 5282 I2C slave address though we never use it */
- + *MCF_I2C_I2ADR = 0x6A;
- +
- + /* Enable I2C module and if IBB is set, do the special initialzation */
- + /* procedures as are documented at the 5282 User Guide page 24-11 */
- + *MCF_I2C_I2CR |= MCF_I2C_I2CR_IEN;
- + if ((*MCF_I2C_I2SR & MCF_I2C_I2SR_IBB) == 1) {
- + printk("%s - do special 5282 I2C init procedures \n",
- + __FUNCTION__);
- + *MCF_I2C_I2CR = 0x00;
- + *MCF_I2C_I2CR = 0xA0;
- + dummyRead = *MCF_I2C_I2DR;
- + *MCF_I2C_I2SR = 0x00;
- + *MCF_I2C_I2CR = 0x00;
- + }
- +
- + /* default I2C mode is - slave and receive */
- + *MCF_I2C_I2CR &= ~(MCF_I2C_I2CR_MSTA | MCF_I2C_I2CR_MTX);
- +
- + coldfire_adapter.dev.parent = &platform_bus;
- + retval = i2c_add_adapter(&coldfire_adapter);
- +
- + if (retval < 0)
- + printk("%s - return code is: %d \n", __FUNCTION__, retval);
- +
- + return retval;
- +};
- +
- +
- +/*
- + * I2C module exit function
- + */
- +
- +static void __exit i2c_coldfire_exit(void)
- +{
- + /* disable I2C and Interrupt */
- + *MCF_I2C_I2CR &= ~(MCF_I2C_I2CR_IEN | MCF_I2C_I2CR_IIEN);
- + i2c_del_adapter(&coldfire_adapter);
- +
- +};
- +
- +
- +MODULE_AUTHOR("Derek CL Cheung <[email protected]>");
- +MODULE_DESCRIPTION("MCF5282 I2C adaptor");
- +MODULE_LICENSE("GPL");
- +
- +module_init(i2c_coldfire_init);
- +module_exit(i2c_coldfire_exit);
- --- /dev/null
- +++ b/drivers/i2c/busses/i2c-mcf.h
- @@ -0,0 +1,75 @@
- +/*
- + i2c-mcf.h - header file for i2c-mcf.c
- +
- + Copyright (c) 2005, Derek CL Cheung <[email protected]>
- + <http://www3.sympatico.ca/derek.cheung>
- +
- + Copyright (c) 2006-2007, emlix
- + Sebastian Hess <[email protected]>
- +
- + Copyright (c) 2006-2007 Freescale Semiconductor, Inc
- + Yaroslav Vinogradov <[email protected]>
- + Matt Waddel <[email protected]>
- +
- + This program is free software; you can redistribute it and/or modify
- + it under the terms of the GNU General Public License as published by
- + the Free Software Foundation; either version 2 of the License, or
- + (at your option) any later version.
- +
- + This program is distributed in the hope that it will be useful,
- + but WITHOUT ANY WARRANTY; without even the implied warranty of
- + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + GNU General Public License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with this program; if not, write to the Free Software
- + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- +
- + Changes:
- + v0.1 26 March 2005
- + Initial Release - developed on uClinux with 2.6.9 kernel
- + v0.2 29 May 2006
- + Modified to be more generic and added support for
- + i2c_master_xfer
- +*/
- +
- +
- +#ifndef __I2C_MCF_H__
- +#define __I2C_MCF_H__
- +
- +enum I2C_START_TYPE { FIRST_START, REPEAT_START };
- +enum I2C_ACK_TYPE { ACK, NACK};
- +
- +/* Function prototypes */
- +static u32 coldfire_func(struct i2c_adapter *adapter);
- +static s32 coldfire_i2c_access(struct i2c_adapter *adap, u16 address,
- + unsigned short flags, char read_write,
- + u8 command, int size, union i2c_smbus_data *data);
- +static int coldfire_write_data(const u8 data);
- +static int coldfire_i2c_start(const char read_write, const u16 target_address, const enum I2C_START_TYPE i2c_start);
- +static int coldfire_read_data(u8 * const rxData, const enum I2C_ACK_TYPE ackType);
- +static int coldfire_i2c_master(struct i2c_adapter *adap,struct i2c_msg *msgs, int num);
- +void dumpReg(char *, u16 addr, u8 data);
- +
- +#define MCF_I2C_I2ADR_ADDR(x) (((x)&0x7F)<<0x01)
- +#define MCF_I2C_I2FDR_IC(x) (((x)&0x3F))
- +
- +/* I2C Control Register */
- +#define MCF_I2C_I2CR_IEN (0x80) /* I2C enable */
- +#define MCF_I2C_I2CR_IIEN (0x40) /* interrupt enable */
- +#define MCF_I2C_I2CR_MSTA (0x20) /* master/slave mode */
- +#define MCF_I2C_I2CR_MTX (0x10) /* transmit/receive mode */
- +#define MCF_I2C_I2CR_TXAK (0x08) /* transmit acknowledge enable */
- +#define MCF_I2C_I2CR_RSTA (0x04) /* repeat start */
- +
- +/* I2C Status Register */
- +#define MCF_I2C_I2SR_ICF (0x80) /* data transfer bit */
- +#define MCF_I2C_I2SR_IAAS (0x40) /* I2C addressed as a slave */
- +#define MCF_I2C_I2SR_IBB (0x20) /* I2C bus busy */
- +#define MCF_I2C_I2SR_IAL (0x10) /* aribitration lost */
- +#define MCF_I2C_I2SR_SRW (0x04) /* slave read/write */
- +#define MCF_I2C_I2SR_IIF (0x02) /* I2C interrupt */
- +#define MCF_I2C_I2SR_RXAK (0x01) /* received acknowledge */
- +
- +/********************************************************************/
- +#endif /* __I2C_MCF_H__ */
|