diff options
Diffstat (limited to 'target/linux/coldfire/patches/055-m547x_8x_i2c.patch')
-rw-r--r-- | target/linux/coldfire/patches/055-m547x_8x_i2c.patch | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/target/linux/coldfire/patches/055-m547x_8x_i2c.patch b/target/linux/coldfire/patches/055-m547x_8x_i2c.patch new file mode 100644 index 0000000..0a2a277 --- /dev/null +++ b/target/linux/coldfire/patches/055-m547x_8x_i2c.patch @@ -0,0 +1,808 @@ +From ce57fc22543d0ee0ca33157264815a52fc8cf9a3 Mon Sep 17 00:00:00 2001 +From: Kurt Mahan <kmahan@freescale.com> +Date: Thu, 15 May 2008 13:23:27 -0600 +Subject: [PATCH] Add I2C bus driver for MCF547x and MCF548x. + +LTIBName: m547x-8x-i2c +Signed-off-by: Kurt Mahan <kmahan@freescale.com> +Signed-off-by: Shrek Wu <b16972@freescale.com> +--- + arch/m68k/coldfire/Makefile | 1 + + arch/m68k/coldfire/mcf548x-devices.c | 94 ++++++ + drivers/i2c/busses/Kconfig | 12 + + drivers/i2c/busses/Makefile | 1 + + drivers/i2c/busses/i2c-algo-mcf.h | 23 ++ + drivers/i2c/busses/i2c-mcf548x.c | 573 ++++++++++++++++++++++++++++++++++ + include/asm-m68k/m5485i2c.h | 45 +++ + 7 files changed, 749 insertions(+), 0 deletions(-) + create mode 100644 arch/m68k/coldfire/mcf548x-devices.c + create mode 100644 drivers/i2c/busses/i2c-algo-mcf.h + create mode 100644 drivers/i2c/busses/i2c-mcf548x.c + create mode 100644 include/asm-m68k/m5485i2c.h + +--- a/arch/m68k/coldfire/Makefile ++++ b/arch/m68k/coldfire/Makefile +@@ -11,4 +11,5 @@ endif + obj-$(CONFIG_PCI) += pci.o mcf5445x-pci.o iomap.o + obj-$(CONFIG_M54455) += mcf5445x-devices.o + obj-$(CONFIG_M547X_8X) += m547x_8x-devices.o ++obj-$(CONFIG_M547X_8X) += mcf548x-devices.o + obj-$(CONFIG_MCD_DMA) += m547x_8x-dma.o +--- /dev/null ++++ b/arch/m68k/coldfire/mcf548x-devices.c +@@ -0,0 +1,94 @@ ++/* ++ * arch/m68k/coldfire/mcf5445x-devices.c ++ * ++ * Coldfire M5445x Platform Device Configuration ++ * ++ * Based on the Freescale MXC devices.c ++ * ++ * Copyright (c) 2007 Freescale Semiconductor, Inc. ++ * Kurt Mahan <kmahan@freescale.com> ++ */ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++#include <linux/fsl_devices.h> ++ ++#include <asm/coldfire.h> ++#include <asm/mcfsim.h> ++ ++static struct resource coldfire_i2c_resources[] = { ++ [0] = { /* I/O */ ++ .start = MCF_MBAR + 0x008F00, ++ .end = MCF_MBAR + 0x008F20, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { /* IRQ */ ++ .start = 40, ++ .end = 40, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device coldfire_i2c_device = { ++ .name = "MCF548X-i2c", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(coldfire_i2c_resources), ++ .resource = coldfire_i2c_resources, ++}; ++ ++static struct resource coldfire_sec_resources[] = { ++ [0] = { /* I/O */ ++ .start = MCF_MBAR + 0x00020000, ++ .end = MCF_MBAR + 0x00033000, ++ .flags = IORESOURCE_MEM, ++ }, ++ [2] = { /* IRQ */ ++ .start = ISC_SEC, ++ .end = ISC_SEC, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device coldfire_sec_device = { ++ .name = "fsl-sec1", ++ .id = -1, ++ .num_resources = ARRAY_SIZE(coldfire_sec_resources), ++ .resource = coldfire_sec_resources, ++}; ++ ++#if defined(CONFIG_MTD_PHYSMAP) ++static struct physmap_flash_data mcf5485_flash_data = { ++ .width = 2, ++}; ++ ++static struct resource mcf5485_flash_resource = { ++ .start = 0xf8000000, ++ .end = 0xf80fffff, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct platform_device mcf5485_flash_device = { ++ .name = "physmap-flash", ++ .id = 0, ++ .dev = { ++ .platform_data = &mcf5485_flash_data, ++ }, ++ .num_resources = 1, ++ .resource = &mcf5485_flash_resource, ++}; ++#endif ++ ++static int __init mcf5485_init_devices(void) ++{ ++ printk(KERN_INFO "MCF5485x INIT_DEVICES\n"); ++ ++ platform_device_register(&coldfire_i2c_device); ++ platform_device_register(&coldfire_sec_device); ++/*#if defined(CONFIG_MTD_PHYSMAP) ++ platform_device_register(&mcf5485_flash_device); ++#endif*/ ++ return 0; ++} ++arch_initcall(mcf5485_init_devices); +--- a/drivers/i2c/busses/Kconfig ++++ b/drivers/i2c/busses/Kconfig +@@ -4,6 +4,18 @@ + + menu "I2C Hardware Bus support" + ++config I2C_MCF548x ++ tristate "I2C MCF547x/548x interfaces" ++ depends on I2C ++ help ++ This allows you to use the I2C adapters found on the Freescale ++ MCF547x/548x microcontrollers. ++ Say Y if you own an I2C adapter belonging to this class and then say ++ Y to the specific driver for you adapter below. ++ ++ This support is also available as a module. If so, the module ++ will be called i2c-algo-mcf. ++ + config I2C_ALI1535 + tristate "ALI 1535" + depends on PCI +--- a/drivers/i2c/busses/Makefile ++++ b/drivers/i2c/busses/Makefile +@@ -52,6 +52,7 @@ obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o + obj-$(CONFIG_I2C_VOODOO3) += i2c-voodoo3.o + obj-$(CONFIG_SCx200_ACB) += scx200_acb.o + obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o ++obj-$(CONFIG_I2C_MCF548x) += i2c-mcf548x.o + + ifeq ($(CONFIG_I2C_DEBUG_BUS),y) + EXTRA_CFLAGS += -DDEBUG +--- /dev/null ++++ b/drivers/i2c/busses/i2c-algo-mcf.h +@@ -0,0 +1,23 @@ ++#ifndef I2C_ALGO_MCF_H ++#define I2C_ALGO_MCF_H 1 ++ ++/* --- Defines for pcf-adapters --------------------------------------- */ ++#include <linux/i2c.h> ++ ++struct i2c_algo_mcf_data { ++ void *data; /* private data for lolevel routines */ ++ void (*setmcf) (void *data, int ctl, int val); ++ int (*getmcf) (void *data, int ctl); ++ int (*getown) (void *data); ++ int (*getclock) (void *data); ++ void (*waitforpin) (void); ++ /* local settings */ ++ int udelay; ++ int mdelay; ++ int timeout; ++}; ++ ++int i2c_mcf_add_bus(struct i2c_adapter *); ++int i2c_mcf_del_bus(struct i2c_adapter *); ++ ++#endif /* I2C_ALGO_MCF_H */ +--- /dev/null ++++ b/drivers/i2c/busses/i2c-mcf548x.c +@@ -0,0 +1,573 @@ ++/* ++ * Performance and stability improvements: (C) Copyright 2008, ++ * Adrian Cox <adrian@humboldt.co.uk> ++ * ColdFire 547x/548x I2C master support ++ * Shrek Wu (b16972@freescale.com )moved the code driver/i2c/alg/mcf.c ++ * into driver/i2c/busses.And changed the driver to a platform driver. ++ */ ++#include <linux/i2c.h> ++#include "i2c-algo-mcf.h" ++ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <linux/sched.h> ++#include <linux/interrupt.h> ++#include <asm/io.h> ++ ++#include <asm/coldfire.h> ++#include <asm/m5485sim.h> ++#include <asm/m5485i2c.h> ++ ++#define get_clock(adap) (clock) ++#define get_own(adap) (own) ++ ++static int clock = 0x3b; /*50000 / 1024 ~ 49 KHz*/ ++module_param(clock, int, 0); ++MODULE_PARM_DESC(clock, ++ "Set I2C clock in kHz: 400=fast mode (default == 49khz)"); ++ ++static int own = 0x78; ++module_param(own, int, 0); ++MODULE_PARM_DESC(clock, "Set I2C Master controller address(0x78)"); ++ ++static struct i2c_algo_mcf_data i2c_mcf_board_data = { ++ .timeout = 10000, ++}; ++ ++static struct i2c_adapter i2c_mcf_board_adapter = { ++ .owner = THIS_MODULE, ++ .name = "MCF5485 adapter", ++ .id = I2C_HW_MPC107, ++ .algo_data = &i2c_mcf_board_data, ++ .class = I2C_CLASS_HWMON, ++ .timeout = 1, ++ .retries = 1 ++}; ++/* ++ * static void i2c_start() ++ * ++ * Generates START signal ++ */ ++static void ++i2c_start( ++ struct i2c_algo_mcf_data *adap ++) { ++ MCF_I2CR |= MCF_I2CR_MSTA; ++} ++ ++ ++/* ++ * static void i2c_stop() ++ * ++ * Generates STOP signal ++ */ ++static void ++i2c_stop( ++ struct i2c_algo_mcf_data *adap ++) { ++ MCF_I2CR &= ~MCF_I2CR_MSTA; ++} ++ ++static int ++i2c_getack( ++ struct i2c_algo_mcf_data *adap ++) { ++ return !(MCF_I2SR & MCF_I2SR_RXAK); ++} ++ ++/* ++ * static void i2c_repstart() ++ * ++ * Generates repeated start signal (without STOP while mastering the bus) ++ */ ++static void ++i2c_repstart( ++ struct i2c_algo_mcf_data *adap ++) { ++ MCF_I2CR |= MCF_I2CR_RSTA; ++ MCF_I2CR |= MCF_I2CR_MTX; ++} ++ ++ ++/* ++ * static void wait_for_bb() ++ * ++ * Wait for bus idle state ++ */ ++static int ++wait_for_bb( ++ struct i2c_algo_mcf_data *adap ++) { ++ int i; ++ for (i = 0; i < adap->timeout; i++) { ++ if (!(MCF_I2SR & MCF_I2SR_IBB)) ++ return 0; ++ udelay(10); ++ } ++ printk(KERN_ERR "%s: timeout", __FUNCTION__); ++ return -ETIMEDOUT; ++} ++ ++/* ++ * static void wait_for_not_bb() ++ * ++ * Wait for bus busy state ++ */ ++static int ++wait_for_not_bb( ++ struct i2c_algo_mcf_data *adap ++) { ++ int i; ++ for (i = 0; i < adap->timeout; i++) { ++ if (MCF_I2SR & MCF_I2SR_IBB) ++ return 0; ++ udelay(10); ++ } ++ printk(KERN_ERR "%s: timeout", __FUNCTION__); ++ return -ETIMEDOUT; ++} ++ ++/* ++ * static void wait_xfer_done() ++ * ++ * Wait for transfer to complete ++ */ ++static int ++wait_xfer_done( ++ struct i2c_algo_mcf_data *adap ++) { ++ int i; ++ ++ for (i = 0; i < adap->timeout; i++) { ++ if (MCF_I2SR & MCF_I2SR_IIF) { ++ MCF_I2SR &= ~MCF_I2SR_IIF; ++ return 0; ++ } ++ udelay(1); ++ } ++ printk(KERN_ERR "%s: timeout", __FUNCTION__); ++ return -ETIMEDOUT; ++} ++ ++ ++/* ++ * static void i2c_set_addr() ++ * ++ * Sets slave address to communicate ++ */ ++static int ++i2c_set_addr( ++ struct i2c_algo_mcf_data *adap, ++ struct i2c_msg *msg, ++ int retries ++) { ++ unsigned short flags = msg->flags; ++ unsigned char addr; ++ ++ if ((flags & I2C_M_TEN)) { ++ /* 10 bit address not supported yet */ ++ return -EIO; ++ } else { ++ /* normal 7bit address */ ++ addr = (msg->addr << 1); ++ if (flags & I2C_M_RD) ++ addr |= 1; ++ if (flags & I2C_M_REV_DIR_ADDR) ++ addr ^= 1; ++ ++ MCF_I2DR = addr; ++ } ++ return 0; ++} ++ ++ ++/* ++ * static void mcf_i2c_init() ++ * ++ * Perform ColdFire i2c initialization ++ */ ++static void ++mcf_i2c_init(struct i2c_algo_mcf_data *adap) ++{ ++ u8 dummy; ++ /* Setup GPIO lines */ ++ MCF_PAR_FECI2CIRQ |= MCF_PAR_SDA; ++ MCF_PAR_FECI2CIRQ |= MCF_PAR_SCL; ++ ++ /* Ensure slaves are in idle state */ ++ if (MCF_I2SR & MCF_I2SR_IBB) { ++ MCF_I2ICR = 0x00; ++ MCF_I2CR = 0x00; ++ MCF_I2CR = 0x0A; ++ dummy = MCF_I2DR; ++ MCF_I2SR = 0x00; ++ MCF_I2CR = 0x00; ++ MCF_I2ICR = 0x01; ++ } ++ ++ /* setup SCL clock */ ++ MCF_I2FDR = get_clock(adap); ++ ++ /* set slave address */ ++ MCF_I2AR = get_own(adap); ++ ++ /* enable I2C module */ ++ MCF_I2CR = MCF_I2CR_IEN; ++} ++ ++static int i2c_outb( ++ struct i2c_adapter *i2c_adap, ++ char c ++) { ++ ++ struct i2c_algo_mcf_data *adap = i2c_adap->algo_data; ++ int timeout; ++ /* Put data to be sent */ ++ MCF_I2DR = c; ++ /* Wait for xfer completed*/ ++ timeout = wait_xfer_done(adap); ++ if (timeout) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ printk(KERN_ERR "i2c-algo-mcf: %s i2c_write: " ++ "error - timeout.\n", i2c_adap->name); ++ return -EREMOTEIO; /* got a better one ?? */ ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * static void mcf_sendbytes() ++ * ++ * Perform tx data transfer ++ */ ++static int ++mcf_sendbytes( ++ struct i2c_adapter *i2c_adap, ++ const char *buf, ++ int count, int last ++) { ++ struct i2c_algo_mcf_data *adap = i2c_adap->algo_data; ++ int ret, i; ++ ++ /* Set master TX mode */ ++ MCF_I2CR |= MCF_I2CR_MTX; ++ ++ for (i = 0; i < count; ++i) { ++ printk(KERN_DEBUG "i2c-algo-mcf: %s i2c_write: writing %2.2X\n", ++ i2c_adap->name, buf[i]&0xff); ++ ret = i2c_outb(i2c_adap, buf[i]); ++ if (ret < 0) ++ return ret; ++ } ++ if (last) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ } else { ++ i2c_repstart(adap); ++ } ++ ++ return (i); ++} ++ ++ ++/* ++ * static void mcf_readbytes() ++ * ++ * Perform rx data transfer ++ */ ++static int ++mcf_readbytes( ++ struct i2c_adapter *i2c_adap, ++ char *buf, ++ int count, int last ++) { ++ int i; ++ struct i2c_algo_mcf_data *adap = i2c_adap->algo_data; ++ u8 dummy; ++ ++ /* Set master RX mode */ ++ MCF_I2CR &= ~MCF_I2CR_MTX; ++ MCF_I2CR &= ~MCF_I2CR_TXAK; ++ dummy = MCF_I2DR; ++ ++ for (i = 0; i < count-1; i++) { ++ if (wait_xfer_done(adap)) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ printk(KERN_DEBUG ++ "i2c-algo-mcf: mcf_readbytes timed out.\n"); ++ return (-1); ++ } ++ ++ /* store next data byte */ ++ buf[i] = MCF_I2DR; ++ } ++ ++ if (wait_xfer_done(adap)) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n"); ++ return (-1); ++ } ++ ++ /* Disable acknowlege (set I2CR.TXAK) */ ++ MCF_I2CR |= MCF_I2CR_TXAK; ++ buf[i] = MCF_I2DR; ++ if (wait_xfer_done(adap)) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ printk(KERN_DEBUG "i2c-algo-mcf: mcf_readbytes timed out.\n"); ++ return (-1); ++ } ++ ++ if (last) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ } else { ++ i2c_repstart(adap); ++ } ++ ++ return (i+1); ++} ++ ++ ++/* ++ * static void mcf_xfer() ++ * ++ * Perform master data I/O transfer ++ */ ++static int ++mcf_xfer( ++ struct i2c_adapter *i2c_adap, ++ struct i2c_msg *msgs, ++ int num ++) { ++ struct i2c_algo_mcf_data *adap = i2c_adap->algo_data; ++ struct i2c_msg *pmsg; ++ int i; ++ int ret = 0, timeout; ++ ++ /* Skip own address */ ++ if (get_own(adap) == (msgs[0].addr << 1)) ++ return -EIO; ++ ++ /* Ensure slaves are in idle state */ ++ if (MCF_I2SR & MCF_I2SR_IBB) { ++ MCF_I2ICR = 0x00; ++ MCF_I2CR = 0x00; ++ MCF_I2CR = 0x0A; ++ timeout = MCF_I2DR; ++ MCF_I2SR = 0x00; ++ MCF_I2CR = 0x00; ++ MCF_I2ICR = 0x01; ++ } ++ /* setup SCL clock */ ++ MCF_I2FDR = get_clock(adap); ++ /* set slave address */ ++ MCF_I2AR = get_own(adap); ++ /* enable I2C module */ ++ MCF_I2CR = MCF_I2CR_IEN; ++ ++ MCF_I2CR |= MCF_I2CR_TXAK; ++ ++ /* Check for bus busy */ ++ wait_for_bb(adap); ++ ++ for (i = 0; ret >= 0 && i < num; i++) { ++ pmsg = &msgs[i]; ++ ++ printk(KERN_DEBUG "i2c-algo-mcf: Doing %s %d bytes " ++ "to 0x%02x - %d of %d messages\n", ++ pmsg->flags & I2C_M_RD ? "read" : "write", ++ pmsg->len, pmsg->addr, i + 1, num); ++ ++ /* Send START */ ++ if (i == 0) ++ i2c_start(adap); ++ ++ /* Wait for Bus Busy */ ++ wait_for_not_bb(adap); ++ ++ MCF_I2CR |= MCF_I2CR_MTX; ++ ++ ret = i2c_set_addr(adap, pmsg, i2c_adap->retries); ++ if (ret < 0) ++ return ret; ++ ++ /* Wait for address transfer completion */ ++ wait_xfer_done(adap); ++ ++ /* Check for ACK */ ++ if (!i2c_getack(adap)) { ++ i2c_stop(adap); ++ wait_for_bb(adap); ++ printk(KERN_DEBUG "i2c-algo-mcf: No ack after " ++ "send address in mcf_xfer\n"); ++ return (-EREMOTEIO); ++ } ++ ++ printk(KERN_DEBUG "i2c-algo-mcf: Msg %d, " ++ "addr = 0x%x, flags = 0x%x, len = %d\n", ++ i, msgs[i].addr, msgs[i].flags, msgs[i].len); ++ /* Read */ ++ if (pmsg->flags & I2C_M_RD) { ++ /* read bytes into buffer*/ ++ ret = mcf_readbytes(i2c_adap, pmsg->buf, pmsg->len, ++ (i + 1 == num)); ++ ++ if (ret != pmsg->len) { ++ printk(KERN_DEBUG "i2c-algo-mcf: fail: " ++ "only read %d bytes.\n", ret); ++ } else { ++ printk(KERN_DEBUG "i2c-algo-mcf: " ++ "read %d bytes.\n", ret); ++ } ++ } else { ++ /* write bytes into buffer*/ ++ ret = mcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len, ++ (i + 1 == num)); ++ if (ret != pmsg->len) { ++ printk(KERN_DEBUG "i2c-algo-mcf: fail: " ++ "only wrote %d bytes.\n", ret); ++ } else { ++ printk(KERN_DEBUG "i2c-algo-mcf: wrote" ++ "%d bytes.\n", ret); ++ } ++ } ++ } ++ ++ /* Disable I2C module */ ++ MCF_I2CR = 0; ++ return (i); ++} ++ ++ ++/* ++ * static void mcf_func() ++ * ++ * Return algorithm funtionality ++ */ ++static u32 ++mcf_func( ++ struct i2c_adapter *i2c_adap ++) { ++ return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; ++} ++ ++/* ++ * ColdFire bus algorithm callbacks ++ */ ++static struct i2c_algorithm mcf_algo = { ++ .master_xfer = mcf_xfer, ++ .functionality = mcf_func, ++}; ++ ++/***********************************************************/ ++struct coldfire_i2c { ++ void __iomem *base; ++ struct resource *irqarea; ++ struct resource *ioarea; ++ u32 irq; ++ struct i2c_adapter *adap; ++ u32 flags; ++}; ++ ++/* ++ * registering functions to load algorithms at runtime ++ */ ++int i2c_mcf_add_bus(struct i2c_adapter *adap) ++{ ++ struct i2c_algo_mcf_data *mcf_adap = adap->algo_data; ++ ++ /*adap->id |= mcf_algo.id;*/ ++ adap->algo = &mcf_algo; ++ adap->timeout = 100; ++ ++ mcf_i2c_init(mcf_adap); ++ ++#ifdef MODULE ++ MOD_INC_USE_COUNT; ++#endif ++ ++ i2c_add_adapter(adap); ++ ++ return 0; ++} ++ ++static int mcf548x_i2c_probe(struct platform_device *pdev) ++{ ++ struct coldfire_i2c *i2c; ++ int rc = 0; ++ ++ /************************************************************/ ++ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); ++ if (!i2c) { ++ printk(KERN_ERR "%s kzalloc coldfire_i2c faile\n", ++ __FUNCTION__); ++ return -ENOMEM; ++ } ++ /****************************************************************/ ++ platform_set_drvdata(pdev, i2c); ++ ++ i2c->adap = &i2c_mcf_board_adapter; ++ i2c->adap->dev.parent = &pdev->dev; ++ rc = i2c_mcf_add_bus(i2c->adap); ++ if (rc < 0) { ++ printk(KERN_ERR "%s - failed to add adapter\n", __FUNCTION__); ++ rc = -ENODEV; ++ goto fail_add; ++ } ++ ++ printk(KERN_INFO "i2c-algo-mcf.o: I2C ColdFire algorithm" ++ " module is loaded.\n"); ++ return rc; ++ ++fail_add: ++ kfree(i2c); ++ return rc; ++}; ++ ++static int mcf548x_i2c_remove(struct platform_device *pdev) ++{ ++ struct coldfire_i2c *i2c = platform_get_drvdata(pdev); ++ ++ i2c_del_adapter(i2c->adap); ++ platform_set_drvdata(pdev, NULL); ++ iounmap(i2c->base); ++ kfree(i2c); ++ return 0; ++}; ++ ++/* Structure for a device driver */ ++static struct platform_driver mcf548x_i2c_driver = { ++ .probe = mcf548x_i2c_probe, ++ .remove = mcf548x_i2c_remove, ++ .driver = { ++ .owner = THIS_MODULE, ++ .name = "MCF548X-i2c", ++ }, ++}; ++ ++static int __init coldfire_i2c_init(void) ++{ ++ return platform_driver_register(&mcf548x_i2c_driver); ++} ++ ++static void __exit coldfire_i2c_exit(void) ++{ ++ platform_driver_unregister(&mcf548x_i2c_driver); ++} ++ ++module_init(coldfire_i2c_init); ++module_exit(coldfire_i2c_exit); ++ ++MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); ++MODULE_DESCRIPTION ++ ("I2C-Bus adapter for MCF547x and MCF548x processors"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/include/asm-m68k/m5485i2c.h +@@ -0,0 +1,45 @@ ++/* ++ * m5485i2c.h -- ColdFire 547x/548x i2c controller support. ++ */ ++#ifndef M548X_I2C_H ++#define M548X_I2C_H ++ ++/* Register read/write macros */ ++#define MCF_I2AR MCF_REG08(0x008F00) /* I2C Address */ ++#define MCF_I2FDR MCF_REG08(0x008F04) /* I2C Frequency Divider */ ++#define MCF_I2CR MCF_REG08(0x008F08) /* I2C Control */ ++#define MCF_I2SR MCF_REG08(0x008F0C) /* I2C Status */ ++#define MCF_I2DR MCF_REG08(0x008F10) /* I2C Data I/O */ ++#define MCF_I2ICR MCF_REG08(0x008F20) /* I2C Interrupt Control */ ++ ++/* Bit definitions and macros for MCF_I2C_I2AR */ ++#define MCF_I2AR_ADR(x) (((x)&0x7F)<<1) ++ ++/* Bit definitions and macros for MCF_I2C_I2FDR */ ++#define MCF_I2FDR_IC(x) (((x)&0x3F)<<0) ++ ++/* Bit definitions and macros for MCF_I2C_I2CR */ ++#define MCF_I2CR_RSTA (0x04) ++#define MCF_I2CR_TXAK (0x08) ++#define MCF_I2CR_MTX (0x10) ++#define MCF_I2CR_MSTA (0x20) ++#define MCF_I2CR_IIEN (0x40) ++#define MCF_I2CR_IEN (0x80) ++ ++/* Bit definitions and macros for MCF_I2C_I2SR */ ++#define MCF_I2SR_RXAK (0x01) ++#define MCF_I2SR_IIF (0x02) ++#define MCF_I2SR_SRW (0x04) ++#define MCF_I2SR_IAL (0x10) ++#define MCF_I2SR_IBB (0x20) ++#define MCF_I2SR_IAAS (0x40) ++#define MCF_I2SR_ICF (0x80) ++ ++/* Bit definitions and macros for MCF_I2C_I2ICR */ ++#define MCF_I2ICR_IE (0x01) ++#define MCF_I2ICR_RE (0x02) ++#define MCF_I2ICR_TE (0x04) ++#define MCF_I2ICR_BNBE (0x08) ++ ++/********************************************************************/ ++#endif |