diff options
| author | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-06-23 21:04:37 +0000 | 
|---|---|---|
| committer | kaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2009-06-23 21:04:37 +0000 | 
| commit | 343c185b7d7383b1f5b5144e837045af28afc42b (patch) | |
| tree | 6d3382662fa3ad4119d3a3cda223c53949ca4894 /target/linux/coldfire/patches/055-m547x_8x_i2c.patch | |
| parent | 145f9652a593d19b149d2f25febd4aa0c1ab57d1 (diff) | |
use broken-out patches for the coldfire to make it easier to follow differences against the bsp
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@16547 3c298f89-4303-0410-b956-a3cf2f4a3e73
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 000000000..0a2a277d3 --- /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 | 
