Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6

* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6:
  i2c: Fix platform driver hotplug/coldplug
  i2c: New driver for the SuperH Mobile I2C bus controller
  i2c/scx200_acb: Don't use 0 as NULL pointer
  i2c-bfin-twi: Fix mismatch in add timer and delete timer
  i2c-bfin-twi: Just let i2c-bfin-twi driver depends on BLACKFIN
  i2c-bfin-twi: Use simpler comment headers and strip out information that is maintained in the scm's log
  i2c-bfin-twi: Cleanup driver descriptions, versions and some module useful information
  i2c-bfin-twi: Add missing pin mux operation
  i2c-bfin-twi: Add platform_resource interface to support multi-port TWI controllers
  i2c-bfin-twi: Add repeat start feature to avoid break of a bundle of i2c master xfer operation
  i2c: Remove trailing whitespaces in busses/Kconfig
  i2c: Replace remaining __FUNCTION__ occurrences
  i2c: Renesas SH7760 I2C master driver
  i2c-dev: Split i2cdev_ioctl
  i2c-ibm_iic: Support building as an of_platform driver
  i2c-ibm_iic: Change the log levels
  i2c: Add platform driver on top of the new pca-algorithm
  i2c-algo-pca: Extend for future drivers
  i2c-algo-pca: Remove trailing whitespaces and unnecessary UTF
  i2c: Remove the algorithm drivers from the config menu
This commit is contained in:
Linus Torvalds 2008-04-22 13:59:30 -07:00
commit b24a31442e
34 changed files with 2326 additions and 588 deletions

View File

@ -1,45 +1,16 @@
#
# Character device configuration
# I2C algorithm drivers configuration
#
menu "I2C Algorithms"
config I2C_ALGOBIT
tristate "I2C bit-banging interfaces"
help
This allows you to use a range of I2C adapters called bit-banging
adapters. 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-bit.
tristate
config I2C_ALGOPCF
tristate "I2C PCF 8584 interfaces"
help
This allows you to use a range of I2C adapters called PCF adapters.
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-pcf.
tristate
config I2C_ALGOPCA
tristate "I2C PCA 9564 interfaces"
help
This allows you to use a range of I2C adapters called PCA adapters.
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-pca.
tristate
config I2C_ALGO_SGI
tristate "I2C SGI interfaces"
tristate
depends on SGI_IP22 || SGI_IP32 || X86_VISWS
help
Supports the SGI interfaces like the ones found on SGI Indy VINO
or SGI O2 MACE.
endmenu

View File

@ -1,6 +1,7 @@
/*
* i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
* i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters
* Copyright (C) 2004 Arcom Control Systems
* Copyright (C) 2008 Pengutronix
*
* 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
@ -21,14 +22,10 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-pca.h>
#include "i2c-algo-pca.h"
#define DRIVER "i2c-algo-pca"
#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
@ -36,15 +33,15 @@
static int i2c_debug;
#define pca_outw(adap, reg, val) adap->write_byte(adap, reg, val)
#define pca_inw(adap, reg) adap->read_byte(adap, reg)
#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val)
#define pca_inw(adap, reg) adap->read_byte(adap->data, reg)
#define pca_status(adap) pca_inw(adap, I2C_PCA_STA)
#define pca_clock(adap) adap->get_clock(adap)
#define pca_own(adap) adap->get_own(adap)
#define pca_clock(adap) adap->i2c_clock
#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val)
#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON)
#define pca_wait(adap) adap->wait_for_interrupt(adap)
#define pca_wait(adap) adap->wait_for_completion(adap->data)
#define pca_reset(adap) adap->reset_chip(adap->data)
/*
* Generate a start condition on the i2c bus.
@ -99,7 +96,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
*
* returns after the address has been sent
*/
static void pca_address(struct i2c_algo_pca_data *adap,
static void pca_address(struct i2c_algo_pca_data *adap,
struct i2c_msg *msg)
{
int sta = pca_get_con(adap);
@ -108,9 +105,9 @@ static void pca_address(struct i2c_algo_pca_data *adap,
addr = ( (0x7f & msg->addr) << 1 );
if (msg->flags & I2C_M_RD )
addr |= 1;
DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
pca_outw(adap, I2C_PCA_DAT, addr);
sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
@ -124,7 +121,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
*
* Returns after the byte has been transmitted
*/
static void pca_tx_byte(struct i2c_algo_pca_data *adap,
static void pca_tx_byte(struct i2c_algo_pca_data *adap,
__u8 b)
{
int sta = pca_get_con(adap);
@ -142,19 +139,19 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
*
* returns immediately.
*/
static void pca_rx_byte(struct i2c_algo_pca_data *adap,
static void pca_rx_byte(struct i2c_algo_pca_data *adap,
__u8 *b, int ack)
{
*b = pca_inw(adap, I2C_PCA_DAT);
DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK");
}
/*
/*
* Setup ACK or NACK for next received byte and wait for it to arrive.
*
* Returns after next byte has arrived.
*/
static void pca_rx_ack(struct i2c_algo_pca_data *adap,
static void pca_rx_ack(struct i2c_algo_pca_data *adap,
int ack)
{
int sta = pca_get_con(adap);
@ -168,15 +165,6 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
pca_wait(adap);
}
/*
* Reset the i2c bus / SIO
*/
static void pca_reset(struct i2c_algo_pca_data *adap)
{
/* apparently only an external reset will do it. not a lot can be done */
printk(KERN_ERR DRIVER ": Haven't figured out how to do a reset yet\n");
}
static int pca_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msgs,
int num)
@ -187,7 +175,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
int numbytes = 0;
int state;
int ret;
int timeout = 100;
int timeout = i2c_adap->timeout;
while ((state = pca_status(adap)) != 0xf8 && timeout--) {
msleep(10);
@ -203,14 +191,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
for (curmsg = 0; curmsg < num; curmsg++) {
int addr, i;
msg = &msgs[curmsg];
addr = (0x7f & msg->addr) ;
if (msg->flags & I2C_M_RD )
printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n",
curmsg, msg->len, addr, (addr<<1) | 1);
else {
printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s",
curmsg, msg->len, addr, addr<<1,
msg->len == 0 ? "" : ", ");
for(i=0; i < msg->len; i++)
@ -237,7 +225,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x10: /* A repeated start condition has been transmitted */
pca_address(adap, msg);
break;
case 0x18: /* SLA+W has been transmitted; ACK has been received */
case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
if (numbytes < msg->len) {
@ -287,7 +275,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
DEB2("Arbitration lost\n");
goto out;
case 0x58: /* Data byte has been received; NOT ACK has been returned */
if ( numbytes == msg->len - 1 ) {
pca_rx_byte(adap, &msg->buf[numbytes], 0);
@ -317,16 +305,16 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
pca_reset(adap);
goto out;
default:
printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n", state);
break;
}
}
ret = curmsg;
out:
DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
"status is %#04x. control is %#04x\n",
"status is %#04x. control is %#04x\n",
curmsg, num, pca_status(adap),
pca_get_con(adap));
return ret;
@ -337,53 +325,65 @@ static u32 pca_func(struct i2c_adapter *adap)
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static int pca_init(struct i2c_algo_pca_data *adap)
{
static int freqs[] = {330,288,217,146,88,59,44,36};
int own, clock;
own = pca_own(adap);
clock = pca_clock(adap);
DEB1(KERN_INFO DRIVER ": own address is %#04x\n", own);
DEB1(KERN_INFO DRIVER ": clock freqeuncy is %dkHz\n", freqs[clock]);
pca_outw(adap, I2C_PCA_ADR, own << 1);
pca_set_con(adap, I2C_PCA_CON_ENSIO | clock);
udelay(500); /* 500 µs for oscilator to stabilise */
return 0;
}
static const struct i2c_algorithm pca_algo = {
.master_xfer = pca_xfer,
.functionality = pca_func,
};
/*
* registering functions to load algorithms at runtime
static int pca_init(struct i2c_adapter *adap)
{
static int freqs[] = {330,288,217,146,88,59,44,36};
int clock;
struct i2c_algo_pca_data *pca_data = adap->algo_data;
if (pca_data->i2c_clock > 7) {
printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
adap->name);
pca_data->i2c_clock = I2C_PCA_CON_59kHz;
}
adap->algo = &pca_algo;
pca_reset(pca_data);
clock = pca_clock(pca_data);
DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
udelay(500); /* 500 us for oscilator to stabilise */
return 0;
}
/*
* registering functions to load algorithms at runtime
*/
int i2c_pca_add_bus(struct i2c_adapter *adap)
{
struct i2c_algo_pca_data *pca_adap = adap->algo_data;
int rval;
/* register new adapter to i2c module... */
adap->algo = &pca_algo;
adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */
if ((rval = pca_init(pca_adap)))
rval = pca_init(adap);
if (rval)
return rval;
rval = i2c_add_adapter(adap);
return rval;
return i2c_add_adapter(adap);
}
EXPORT_SYMBOL(i2c_pca_add_bus);
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
int i2c_pca_add_numbered_bus(struct i2c_adapter *adap)
{
int rval;
rval = pca_init(adap);
if (rval)
return rval;
return i2c_add_numbered_adapter(adap);
}
EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>, "
"Wolfram Sang <w.sang@pengutronix.de>");
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
MODULE_LICENSE("GPL");

View File

@ -1,26 +0,0 @@
#ifndef I2C_PCA9564_H
#define I2C_PCA9564_H 1
#define I2C_PCA_STA 0x00 /* STATUS Read Only */
#define I2C_PCA_TO 0x00 /* TIMEOUT Write Only */
#define I2C_PCA_DAT 0x01 /* DATA Read/Write */
#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
#define I2C_PCA_CON_STA 0x20 /* Start */
#define I2C_PCA_CON_STO 0x10 /* Stop */
#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
#define I2C_PCA_CON_330kHz 0x00
#define I2C_PCA_CON_288kHz 0x01
#define I2C_PCA_CON_217kHz 0x02
#define I2C_PCA_CON_146kHz 0x03
#define I2C_PCA_CON_88kHz 0x04
#define I2C_PCA_CON_59kHz 0x05
#define I2C_PCA_CON_44kHz 0x06
#define I2C_PCA_CON_36kHz 0x07
#endif /* I2C_PCA9564_H */

View File

@ -100,9 +100,12 @@ config I2C_AU1550
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BF534 || BF536 || BF537
depends on BLACKFIN
help
This is the TWI I2C device driver for Blackfin 534/536/537/54x.
This is the TWI I2C device driver for Blackfin BF522, BF525,
BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
please don't use this driver.
This driver can also be built as a module. If so, the module
will be called i2c-bfin-twi.
@ -135,7 +138,7 @@ config I2C_ELEKTOR
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
such an adapter.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called i2c-elektor.
config I2C_GPIO
@ -190,7 +193,7 @@ config I2C_I810
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the Intel
810/815 family of mainboard I2C interfaces. Specifically, the
810/815 family of mainboard I2C interfaces. Specifically, the
following versions of the chipset are supported:
i810AA
i810AB
@ -246,10 +249,10 @@ config I2C_PIIX4
config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface"
depends on IBM_OCP
depends on 4xx
help
Say Y here if you want to use IIC peripheral found on
embedded IBM PPC 4xx based systems.
Say Y here if you want to use IIC peripheral found on
embedded IBM PPC 4xx based systems.
This driver can also be built as a module. If so, the module
will be called i2c-ibm_iic.
@ -269,7 +272,7 @@ config I2C_IXP2000
depends on ARCH_IXP2000
select I2C_ALGOBIT
help
Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
system and are using GPIO lines for an I2C bus.
This support is also available as a module. If so, the module
@ -354,7 +357,7 @@ config I2C_PARPORT
on the parport driver. This is meant for embedded systems. Don't say
Y here if you intend to say Y or M there.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called i2c-parport.
config I2C_PARPORT_LIGHT
@ -372,12 +375,12 @@ config I2C_PARPORT_LIGHT
the clean but heavy parport handling is not an option. The
drawback is a reduced portability and the impossibility to
daisy-chain other parallel port devices.
Don't say Y here if you said Y or M to i2c-parport. Saying M to
both is possible but both modules should not be loaded at the same
time.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called i2c-parport-light.
config I2C_PASEMI
@ -401,7 +404,7 @@ config I2C_PROSAVAGE
This driver is deprecated in favor of the savagefb driver.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called i2c-prosavage.
config I2C_S3C2410
@ -417,7 +420,7 @@ config I2C_SAVAGE4
depends on PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the
If you say yes to this option, support will be included for the
S3 Savage 4 I2C interface.
This driver is deprecated in favor of the savagefb driver.
@ -452,7 +455,7 @@ config SCx200_I2C
If you don't know what to do here, say N.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called scx200_i2c.
This driver is deprecated and will be dropped soon. Use i2c-gpio
@ -483,14 +486,14 @@ config SCx200_ACB
If you don't know what to do here, say N.
This support is also available as a module. If so, the module
This support is also available as a module. If so, the module
will be called scx200_acb.
config I2C_SIS5595
tristate "SiS 5595"
depends on PCI
help
If you say yes to this option, support will be included for the
If you say yes to this option, support will be included for the
SiS5595 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
@ -500,7 +503,7 @@ config I2C_SIS630
tristate "SiS 630/730"
depends on PCI
help
If you say yes to this option, support will be included for the
If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface.
This driver can also be built as a module. If so, the module
@ -632,9 +635,9 @@ config I2C_PCA_ISA
select I2C_ALGOPCA
default n
help
This driver supports ISA boards using the Philips PCA 9564
Parallel bus to I2C bus controller
This driver supports ISA boards using the Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-isa.
@ -643,6 +646,17 @@ config I2C_PCA_ISA
delays when I2C/SMBus chip drivers are loaded (e.g. at boot
time). If unsure, say N.
config I2C_PCA_PLATFORM
tristate "PCA9564 as platform device"
select I2C_ALGOPCA
default n
help
This driver supports a memory mapped Philips PCA9564
parallel bus to I2C bus controller.
This driver can also be built as a module. If so, the module
will be called i2c-pca-platform.
config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller"
depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
@ -672,4 +686,23 @@ config I2C_PMCMSP
This driver can also be built as module. If so, the module
will be called i2c-pmcmsp.
config I2C_SH7760
tristate "Renesas SH7760 I2C Controller"
depends on CPU_SUBTYPE_SH7760
help
This driver supports the 2 I2C interfaces on the Renesas SH7760.
This driver can also be built as a module. If so, the module
will be called i2c-sh7760.
config I2C_SH_MOBILE
tristate "SuperH Mobile I2C Controller"
depends on SUPERH
help
If you say yes to this option, support will be included for the
built-in I2C interface on the Renesas SH-Mobile processor.
This driver can also be built as a module. If so, the module
will be called i2c-sh_mobile.
endmenu

View File

@ -30,6 +30,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
@ -37,6 +38,8 @@ obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o

View File

@ -298,7 +298,7 @@ static int at91_i2c_resume(struct platform_device *pdev)
#endif
/* work with "modprobe at91_i2c" from hotplugging or coldplugging */
MODULE_ALIAS("at91_i2c");
MODULE_ALIAS("platform:at91_i2c");
static struct platform_driver at91_i2c_driver = {
.probe = at91_i2c_probe,

View File

@ -472,6 +472,7 @@ i2c_au1550_exit(void)
MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:au1xpsc_smbus");
module_init (i2c_au1550_init);
module_exit (i2c_au1550_exit);

View File

@ -1,25 +1,11 @@
/*
* drivers/i2c/busses/i2c-bfin-twi.c
* Blackfin On-Chip Two Wire Interface Driver
*
* Description: Driver for Blackfin Two Wire Interface
* Copyright 2005-2007 Analog Devices Inc.
*
* Author: sonicz <sonic.zhang@analog.com>
* Enter bugs at http://blackfin.uclinux.org/
*
* Copyright (c) 2005-2007 Analog Devices, Inc.
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Licensed under the GPL-2 or later.
*/
#include <linux/module.h>
@ -34,14 +20,16 @@
#include <linux/platform_device.h>
#include <asm/blackfin.h>
#include <asm/portmux.h>
#include <asm/irq.h>
#define POLL_TIMEOUT (2 * HZ)
/* SMBus mode*/
#define TWI_I2C_MODE_STANDARD 0x01
#define TWI_I2C_MODE_STANDARDSUB 0x02
#define TWI_I2C_MODE_COMBINED 0x04
#define TWI_I2C_MODE_STANDARD 1
#define TWI_I2C_MODE_STANDARDSUB 2
#define TWI_I2C_MODE_COMBINED 3
#define TWI_I2C_MODE_REPEAT 4
struct bfin_twi_iface {
int irq;
@ -58,39 +46,74 @@ struct bfin_twi_iface {
struct timer_list timeout_timer;
struct i2c_adapter adap;
struct completion complete;
struct i2c_msg *pmsg;
int msg_num;
int cur_msg;
void __iomem *regs_base;
};
static struct bfin_twi_iface twi_iface;
#define DEFINE_TWI_REG(reg, off) \
static inline u16 read_##reg(struct bfin_twi_iface *iface) \
{ return bfin_read16(iface->regs_base + (off)); } \
static inline void write_##reg(struct bfin_twi_iface *iface, u16 v) \
{ bfin_write16(iface->regs_base + (off), v); }
DEFINE_TWI_REG(CLKDIV, 0x00)
DEFINE_TWI_REG(CONTROL, 0x04)
DEFINE_TWI_REG(SLAVE_CTL, 0x08)
DEFINE_TWI_REG(SLAVE_STAT, 0x0C)
DEFINE_TWI_REG(SLAVE_ADDR, 0x10)
DEFINE_TWI_REG(MASTER_CTL, 0x14)
DEFINE_TWI_REG(MASTER_STAT, 0x18)
DEFINE_TWI_REG(MASTER_ADDR, 0x1C)
DEFINE_TWI_REG(INT_STAT, 0x20)
DEFINE_TWI_REG(INT_MASK, 0x24)
DEFINE_TWI_REG(FIFO_CTL, 0x28)
DEFINE_TWI_REG(FIFO_STAT, 0x2C)
DEFINE_TWI_REG(XMT_DATA8, 0x80)
DEFINE_TWI_REG(XMT_DATA16, 0x84)
DEFINE_TWI_REG(RCV_DATA8, 0x88)
DEFINE_TWI_REG(RCV_DATA16, 0x8C)
static const u16 pin_req[2][3] = {
{P_TWI0_SCL, P_TWI0_SDA, 0},
{P_TWI1_SCL, P_TWI1_SDA, 0},
};
static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
{
unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
unsigned short twi_int_status = read_INT_STAT(iface);
unsigned short mast_stat = read_MASTER_STAT(iface);
if (twi_int_status & XMTSERV) {
/* Transmit next data */
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
write_XMT_DATA8(iface, *(iface->transPtr++));
iface->writeNum--;
}
/* start receive immediately after complete sending in
* combine mode.
*/
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| MDIR | RSTART);
} else if (iface->manual_stop)
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| STOP);
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | MDIR | RSTART);
else if (iface->manual_stop)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | STOP);
else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num)
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART);
SSYNC();
/* Clear status */
bfin_write_TWI_INT_STAT(XMTSERV);
write_INT_STAT(iface, XMTSERV);
SSYNC();
}
if (twi_int_status & RCVSERV) {
if (iface->readNum > 0) {
/* Receive next data */
*(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
*(iface->transPtr) = read_RCV_DATA8(iface);
if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
/* Change combine mode into sub mode after
* read first data.
@ -105,28 +128,33 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
iface->transPtr++;
iface->readNum--;
} else if (iface->manual_stop) {
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
| STOP);
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | STOP);
SSYNC();
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num) {
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | RSTART);
SSYNC();
}
/* Clear interrupt source */
bfin_write_TWI_INT_STAT(RCVSERV);
write_INT_STAT(iface, RCVSERV);
SSYNC();
}
if (twi_int_status & MERR) {
bfin_write_TWI_INT_STAT(MERR);
bfin_write_TWI_INT_MASK(0);
bfin_write_TWI_MASTER_STAT(0x3e);
bfin_write_TWI_MASTER_CTL(0);
write_INT_STAT(iface, MERR);
write_INT_MASK(iface, 0);
write_MASTER_STAT(iface, 0x3e);
write_MASTER_CTL(iface, 0);
SSYNC();
iface->result = -1;
iface->result = -EIO;
/* if both err and complete int stats are set, return proper
* results.
*/
if (twi_int_status & MCOMP) {
bfin_write_TWI_INT_STAT(MCOMP);
bfin_write_TWI_INT_MASK(0);
bfin_write_TWI_MASTER_CTL(0);
write_INT_STAT(iface, MCOMP);
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
/* If it is a quick transfer, only address bug no data,
* not an err, return 1.
@ -143,7 +171,7 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
return;
}
if (twi_int_status & MCOMP) {
bfin_write_TWI_INT_STAT(MCOMP);
write_INT_STAT(iface, MCOMP);
SSYNC();
if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
if (iface->readNum == 0) {
@ -152,28 +180,63 @@ static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
*/
iface->readNum = 1;
iface->manual_stop = 1;
bfin_write_TWI_MASTER_CTL(
bfin_read_TWI_MASTER_CTL()
| (0xff << 6));
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | (0xff << 6));
} else {
/* set the readd number in other
* combine mode.
*/
bfin_write_TWI_MASTER_CTL(
(bfin_read_TWI_MASTER_CTL() &
write_MASTER_CTL(iface,
(read_MASTER_CTL(iface) &
(~(0xff << 6))) |
( iface->readNum << 6));
(iface->readNum << 6));
}
/* remove restart bit and enable master receive */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
~RSTART);
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
MEN | MDIR);
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) | MEN | MDIR);
SSYNC();
} else if (iface->cur_mode == TWI_I2C_MODE_REPEAT &&
iface->cur_msg+1 < iface->msg_num) {
iface->cur_msg++;
iface->transPtr = iface->pmsg[iface->cur_msg].buf;
iface->writeNum = iface->readNum =
iface->pmsg[iface->cur_msg].len;
/* Set Transmit device address */
write_MASTER_ADDR(iface,
iface->pmsg[iface->cur_msg].addr);
if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
write_XMT_DATA8(iface,
*(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
}
if (iface->pmsg[iface->cur_msg].len <= 255)
write_MASTER_CTL(iface,
iface->pmsg[iface->cur_msg].len << 6);
else {
write_MASTER_CTL(iface, 0xff << 6);
iface->manual_stop = 1;
}
/* remove restart bit and enable master receive */
write_MASTER_CTL(iface,
read_MASTER_CTL(iface) & ~RSTART);
write_MASTER_CTL(iface, read_MASTER_CTL(iface) |
MEN | ((iface->read_write == I2C_SMBUS_READ) ?
MDIR : 0));
SSYNC();
} else {
iface->result = 1;
bfin_write_TWI_INT_MASK(0);
bfin_write_TWI_MASTER_CTL(0);
write_INT_MASK(iface, 0);
write_MASTER_CTL(iface, 0);
SSYNC();
complete(&iface->complete);
}
@ -221,91 +284,85 @@ static int bfin_twi_master_xfer(struct i2c_adapter *adap,
{
struct bfin_twi_iface *iface = adap->algo_data;
struct i2c_msg *pmsg;
int i, ret;
int rc = 0;
if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO;
while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
while (read_MASTER_STAT(iface) & BUSBUSY)
yield();
iface->pmsg = msgs;
iface->msg_num = num;
iface->cur_msg = 0;
pmsg = &msgs[0];
if (pmsg->flags & I2C_M_TEN) {
dev_err(&adap->dev, "10 bits addr not supported!\n");
return -EINVAL;
}
ret = 0;
for (i = 0; rc >= 0 && i < num; i++) {
pmsg = &msgs[i];
if (pmsg->flags & I2C_M_TEN) {
dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
"not supported !\n");
rc = -EINVAL;
break;
iface->cur_mode = TWI_I2C_MODE_REPEAT;
iface->manual_stop = 0;
iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
iface->result = 0;
iface->timeout_count = 10;
init_completion(&(iface->complete));
/* Set Transmit device address */
write_MASTER_ADDR(iface, pmsg->addr);
/* FIFO Initiation. Data in FIFO should be
* discarded before start a new operation.
*/
write_FIFO_CTL(iface, 0x3);
SSYNC();
write_FIFO_CTL(iface, 0);
SSYNC();
if (pmsg->flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
write_XMT_DATA8(iface, *(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
iface->cur_mode = TWI_I2C_MODE_STANDARD;
iface->manual_stop = 0;
iface->transPtr = pmsg->buf;
iface->writeNum = iface->readNum = pmsg->len;
iface->result = 0;
iface->timeout_count = 10;
/* Set Transmit device address */
bfin_write_TWI_MASTER_ADDR(pmsg->addr);
/* FIFO Initiation. Data in FIFO should be
* discarded before start a new operation.
*/
bfin_write_TWI_FIFO_CTL(0x3);
SSYNC();
bfin_write_TWI_FIFO_CTL(0);
SSYNC();
if (pmsg->flags & I2C_M_RD)
iface->read_write = I2C_SMBUS_READ;
else {
iface->read_write = I2C_SMBUS_WRITE;
/* Transmit first data */
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
iface->writeNum--;
SSYNC();
}
}
/* clear int stat */
bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
/* Interrupt mask . Enable XMT, RCV interrupt */
bfin_write_TWI_INT_MASK(MCOMP | MERR |
((iface->read_write == I2C_SMBUS_READ)?
RCVSERV : XMTSERV));
SSYNC();
if (pmsg->len > 0 && pmsg->len <= 255)
bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
else if (pmsg->len > 255) {
bfin_write_TWI_MASTER_CTL(0xff << 6);
iface->manual_stop = 1;
} else
break;
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
add_timer(&iface->timeout_timer);
/* Master enable */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
SSYNC();
wait_for_completion(&iface->complete);
rc = iface->result;
if (rc == 1)
ret++;
else if (rc == -1)
break;
}
return ret;
/* clear int stat */
write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
/* Interrupt mask . Enable XMT, RCV interrupt */
write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
SSYNC();
if (pmsg->len <= 255)
write_MASTER_CTL(iface, pmsg->len << 6);
else {
write_MASTER_CTL(iface, 0xff << 6);
iface->manual_stop = 1;
}
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
add_timer(&iface->timeout_timer);
/* Master enable */
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
SSYNC();
wait_for_completion(&iface->complete);
rc = iface->result;
if (rc == 1)
return num;
else
return rc;
}
/*
@ -319,12 +376,11 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
struct bfin_twi_iface *iface = adap->algo_data;
int rc = 0;
if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
if (!(read_CONTROL(iface) & TWI_ENA))
return -ENXIO;
while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
while (read_MASTER_STAT(iface) & BUSBUSY)
yield();
}
iface->writeNum = 0;
iface->readNum = 0;
@ -392,19 +448,20 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
iface->read_write = read_write;
iface->command = command;
iface->timeout_count = 10;
init_completion(&(iface->complete));
/* FIFO Initiation. Data in FIFO should be discarded before
* start a new operation.
*/
bfin_write_TWI_FIFO_CTL(0x3);
write_FIFO_CTL(iface, 0x3);
SSYNC();
bfin_write_TWI_FIFO_CTL(0);
write_FIFO_CTL(iface, 0);
/* clear int stat */
bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV);
/* Set Transmit device address */
bfin_write_TWI_MASTER_ADDR(addr);
write_MASTER_ADDR(iface, addr);
SSYNC();
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
@ -412,60 +469,64 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
switch (iface->cur_mode) {
case TWI_I2C_MODE_STANDARDSUB:
bfin_write_TWI_XMT_DATA8(iface->command);
bfin_write_TWI_INT_MASK(MCOMP | MERR |
write_XMT_DATA8(iface, iface->command);
write_INT_MASK(iface, MCOMP | MERR |
((iface->read_write == I2C_SMBUS_READ) ?
RCVSERV : XMTSERV));
SSYNC();
if (iface->writeNum + 1 <= 255)
bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
else {
bfin_write_TWI_MASTER_CTL(0xff << 6);
write_MASTER_CTL(iface, 0xff << 6);
iface->manual_stop = 1;
}
/* Master enable */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
break;
case TWI_I2C_MODE_COMBINED:
bfin_write_TWI_XMT_DATA8(iface->command);
bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
write_XMT_DATA8(iface, iface->command);
write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV);
SSYNC();
if (iface->writeNum > 0)
bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
write_MASTER_CTL(iface, (iface->writeNum + 1) << 6);
else
bfin_write_TWI_MASTER_CTL(0x1 << 6);
write_MASTER_CTL(iface, 0x1 << 6);
/* Master enable */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
break;
default:
bfin_write_TWI_MASTER_CTL(0);
write_MASTER_CTL(iface, 0);
if (size != I2C_SMBUS_QUICK) {
/* Don't access xmit data register when this is a
* read operation.
*/
if (iface->read_write != I2C_SMBUS_READ) {
if (iface->writeNum > 0) {
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
write_XMT_DATA8(iface,
*(iface->transPtr++));
if (iface->writeNum <= 255)
bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
write_MASTER_CTL(iface,
iface->writeNum << 6);
else {
bfin_write_TWI_MASTER_CTL(0xff << 6);
write_MASTER_CTL(iface,
0xff << 6);
iface->manual_stop = 1;
}
iface->writeNum--;
} else {
bfin_write_TWI_XMT_DATA8(iface->command);
bfin_write_TWI_MASTER_CTL(1 << 6);
write_XMT_DATA8(iface, iface->command);
write_MASTER_CTL(iface, 1 << 6);
}
} else {
if (iface->readNum > 0 && iface->readNum <= 255)
bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
write_MASTER_CTL(iface,
iface->readNum << 6);
else if (iface->readNum > 255) {
bfin_write_TWI_MASTER_CTL(0xff << 6);
write_MASTER_CTL(iface, 0xff << 6);
iface->manual_stop = 1;
} else {
del_timer(&iface->timeout_timer);
@ -473,13 +534,13 @@ int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
}
}
}
bfin_write_TWI_INT_MASK(MCOMP | MERR |
write_INT_MASK(iface, MCOMP | MERR |
((iface->read_write == I2C_SMBUS_READ) ?
RCVSERV : XMTSERV));
SSYNC();
/* Master enable */
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN |
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
break;
@ -514,10 +575,10 @@ static struct i2c_algorithm bfin_twi_algorithm = {
static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
{
/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
struct bfin_twi_iface *iface = platform_get_drvdata(dev);
/* Disable TWI */
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
write_CONTROL(iface, read_CONTROL(iface) & ~TWI_ENA);
SSYNC();
return 0;
@ -525,24 +586,52 @@ static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
static int i2c_bfin_twi_resume(struct platform_device *dev)
{
/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
struct bfin_twi_iface *iface = platform_get_drvdata(dev);
/* Enable TWI */
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
SSYNC();
return 0;
}
static int i2c_bfin_twi_probe(struct platform_device *dev)
static int i2c_bfin_twi_probe(struct platform_device *pdev)
{
struct bfin_twi_iface *iface = &twi_iface;
struct bfin_twi_iface *iface;
struct i2c_adapter *p_adap;
struct resource *res;
int rc;
iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL);
if (!iface) {
dev_err(&pdev->dev, "Cannot allocate memory\n");
rc = -ENOMEM;
goto out_error_nomem;
}
spin_lock_init(&(iface->lock));
init_completion(&(iface->complete));
iface->irq = IRQ_TWI;
/* Find and map our resources */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
rc = -ENOENT;
goto out_error_get_res;
}
iface->regs_base = ioremap(res->start, res->end - res->start + 1);
if (iface->regs_base == NULL) {
dev_err(&pdev->dev, "Cannot map IO\n");
rc = -ENXIO;
goto out_error_ioremap;
}
iface->irq = platform_get_irq(pdev, 0);
if (iface->irq < 0) {
dev_err(&pdev->dev, "No IRQ specified\n");
rc = -ENOENT;
goto out_error_no_irq;
}
init_timer(&(iface->timeout_timer));
iface->timeout_timer.function = bfin_twi_timeout;
@ -550,39 +639,63 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
p_adap = &iface->adap;
p_adap->id = I2C_HW_BLACKFIN;
p_adap->nr = dev->id;
strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
p_adap->nr = pdev->id;
strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name));
p_adap->algo = &bfin_twi_algorithm;
p_adap->algo_data = iface;
p_adap->class = I2C_CLASS_ALL;
p_adap->dev.parent = &dev->dev;
p_adap->dev.parent = &pdev->dev;
rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi");
if (rc) {
dev_err(&pdev->dev, "Can't setup pin mux!\n");
goto out_error_pin_mux;
}
rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
IRQF_DISABLED, dev->name, iface);
IRQF_DISABLED, pdev->name, iface);
if (rc) {
dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
iface->irq);
return -ENODEV;
dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq);
rc = -ENODEV;
goto out_error_req_irq;
}
/* Set TWI internal clock as 10MHz */
bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
/* Set Twi interface clock as specified */
bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
<< 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
write_CLKDIV(iface, ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
<< 8) | ((5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ)
& 0xFF));
/* Enable TWI */
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA);
SSYNC();
rc = i2c_add_numbered_adapter(p_adap);
if (rc < 0)
free_irq(iface->irq, iface);
else
platform_set_drvdata(dev, iface);
if (rc < 0) {
dev_err(&pdev->dev, "Can't add i2c adapter!\n");
goto out_error_add_adapter;
}
platform_set_drvdata(pdev, iface);
dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
"regs_base@%p\n", iface->regs_base);
return 0;
out_error_add_adapter:
free_irq(iface->irq, iface);
out_error_req_irq:
out_error_no_irq:
peripheral_free_list(pin_req[pdev->id]);
out_error_pin_mux:
iounmap(iface->regs_base);
out_error_ioremap:
out_error_get_res:
kfree(iface);
out_error_nomem:
return rc;
}
@ -594,6 +707,9 @@ static int i2c_bfin_twi_remove(struct platform_device *pdev)
i2c_del_adapter(&(iface->adap));
free_irq(iface->irq, iface);
peripheral_free_list(pin_req[pdev->id]);
iounmap(iface->regs_base);
kfree(iface);
return 0;
}
@ -611,8 +727,6 @@ static struct platform_driver i2c_bfin_twi_driver = {
static int __init i2c_bfin_twi_init(void)
{
pr_info("I2C: Blackfin I2C TWI driver\n");
return platform_driver_register(&i2c_bfin_twi_driver);
}
@ -621,9 +735,10 @@ static void __exit i2c_bfin_twi_exit(void)
platform_driver_unregister(&i2c_bfin_twi_driver);
}
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
MODULE_LICENSE("GPL");
module_init(i2c_bfin_twi_init);
module_exit(i2c_bfin_twi_exit);
MODULE_AUTHOR("Bryan Wu, Sonic Zhang");
MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:i2c-bfin-twi");

View File

@ -328,7 +328,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
int i;
int ret;
dev_dbg(dev->dev, "%s: msgs: %d\n", __FUNCTION__, num);
dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
ret = i2c_davinci_wait_bus_not_busy(dev, 1);
if (ret < 0) {
@ -342,7 +342,7 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
return ret;
}
dev_dbg(dev->dev, "%s:%d ret: %d\n", __FUNCTION__, __LINE__, ret);
dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
return num;
}
@ -364,7 +364,7 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
u16 w;
while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
dev_dbg(dev->dev, "%s: stat=0x%x\n", __FUNCTION__, stat);
dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
if (count++ == 100) {
dev_warn(dev->dev, "Too much work in one IRQ\n");
break;
@ -553,6 +553,9 @@ static int davinci_i2c_remove(struct platform_device *pdev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c_davinci");
static struct platform_driver davinci_i2c_driver = {
.probe = davinci_i2c_probe,
.remove = davinci_i2c_remove,

View File

@ -220,3 +220,4 @@ module_exit(i2c_gpio_exit);
MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:i2c-gpio");

View File

@ -6,6 +6,9 @@
* Copyright (c) 2003, 2004 Zultys Technologies.
* Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
*
* Copyright (c) 2008 PIKA Technologies
* Sean MacLennan <smaclennan@pikatech.com>
*
* Based on original work by
* Ian DaSilva <idasilva@mvista.com>
* Armin Kuster <akuster@mvista.com>
@ -39,12 +42,17 @@
#include <asm/io.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#ifdef CONFIG_IBM_OCP
#include <asm/ocp.h>
#include <asm/ibm4xx.h>
#else
#include <linux/of_platform.h>
#endif
#include "i2c-ibm_iic.h"
#define DRIVER_VERSION "2.1"
#define DRIVER_VERSION "2.2"
MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION);
MODULE_LICENSE("GPL");
@ -650,13 +658,14 @@ static inline u8 iic_clckdiv(unsigned int opb)
opb /= 1000000;
if (opb < 20 || opb > 150){
printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n",
opb);
opb = opb < 20 ? 20 : 150;
}
return (u8)((opb + 9) / 10 - 1);
}
#ifdef CONFIG_IBM_OCP
/*
* Register single IIC interface
*/
@ -672,7 +681,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
ocp->def->index);
if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
printk(KERN_CRIT "ibm-iic%d: failed to allocate device data\n",
printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
ocp->def->index);
return -ENOMEM;
}
@ -687,7 +696,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
}
if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
printk(KERN_CRIT "ibm-iic%d: failed to ioremap device registers\n",
printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
dev->idx);
ret = -ENXIO;
goto fail2;
@ -745,7 +754,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
adap->nr = dev->idx >= 0 ? dev->idx : 0;
if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
printk(KERN_CRIT "ibm-iic%d: failed to register i2c adapter\n",
printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
dev->idx);
goto fail;
}
@ -778,7 +787,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
BUG_ON(dev == NULL);
if (i2c_del_adapter(&dev->adap)){
printk(KERN_CRIT "ibm-iic%d: failed to delete i2c adapter :(\n",
printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
dev->idx);
/* That's *very* bad, just shutdown IRQ ... */
if (dev->irq >= 0){
@ -828,5 +837,181 @@ static void __exit iic_exit(void)
ocp_unregister_driver(&ibm_iic_driver);
}
#else /* !CONFIG_IBM_OCP */
static int __devinit iic_request_irq(struct of_device *ofdev,
struct ibm_iic_private *dev)
{
struct device_node *np = ofdev->node;
int irq;
if (iic_force_poll)
return NO_IRQ;
irq = irq_of_parse_and_map(np, 0);
if (irq == NO_IRQ) {
dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n");
return NO_IRQ;
}
/* Disable interrupts until we finish initialization, assumes
* level-sensitive IRQ setup...
*/
iic_interrupt_mode(dev, 0);
if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) {
dev_err(&ofdev->dev, "request_irq %d failed\n", irq);
/* Fallback to the polling mode */
return NO_IRQ;
}
return irq;
}
/*
* Register single IIC interface
*/
static int __devinit iic_probe(struct of_device *ofdev,
const struct of_device_id *match)
{
struct device_node *np = ofdev->node;
struct ibm_iic_private *dev;
struct i2c_adapter *adap;
const u32 *indexp, *freq;
int ret;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
dev_err(&ofdev->dev, "failed to allocate device data\n");
return -ENOMEM;
}
dev_set_drvdata(&ofdev->dev, dev);
indexp = of_get_property(np, "index", NULL);
if (!indexp) {
dev_err(&ofdev->dev, "no index specified\n");
ret = -EINVAL;
goto error_cleanup;
}
dev->idx = *indexp;
dev->vaddr = of_iomap(np, 0);
if (dev->vaddr == NULL) {
dev_err(&ofdev->dev, "failed to iomap device\n");
ret = -ENXIO;
goto error_cleanup;
}
init_waitqueue_head(&dev->wq);
dev->irq = iic_request_irq(ofdev, dev);
if (dev->irq == NO_IRQ)
dev_warn(&ofdev->dev, "using polling mode\n");
/* Board specific settings */
if (iic_force_fast || of_get_property(np, "fast-mode", NULL))
dev->fast_mode = 1;
freq = of_get_property(np, "clock-frequency", NULL);
if (freq == NULL) {
freq = of_get_property(np->parent, "clock-frequency", NULL);
if (freq == NULL) {
dev_err(&ofdev->dev, "Unable to get bus frequency\n");
ret = -EINVAL;
goto error_cleanup;
}
}
dev->clckdiv = iic_clckdiv(*freq);
dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv);
/* Initialize IIC interface */
iic_dev_init(dev);
/* Register it with i2c layer */
adap = &dev->adap;
adap->dev.parent = &ofdev->dev;
strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
i2c_set_adapdata(adap, dev);
adap->id = I2C_HW_OCP;
adap->class = I2C_CLASS_HWMON;
adap->algo = &iic_algo;
adap->timeout = 1;
adap->nr = dev->idx;
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(&ofdev->dev, "failed to register i2c adapter\n");
goto error_cleanup;
}
dev_info(&ofdev->dev, "using %s mode\n",
dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
return 0;
error_cleanup:
if (dev->irq != NO_IRQ) {
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
if (dev->vaddr)
iounmap(dev->vaddr);
dev_set_drvdata(&ofdev->dev, NULL);
kfree(dev);
return ret;
}
/*
* Cleanup initialized IIC interface
*/
static int __devexit iic_remove(struct of_device *ofdev)
{
struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev);
dev_set_drvdata(&ofdev->dev, NULL);
i2c_del_adapter(&dev->adap);
if (dev->irq != NO_IRQ) {
iic_interrupt_mode(dev, 0);
free_irq(dev->irq, dev);
}
iounmap(dev->vaddr);
kfree(dev);
return 0;
}
static const struct of_device_id ibm_iic_match[] = {
{ .compatible = "ibm,iic-405ex", },
{ .compatible = "ibm,iic-405gp", },
{ .compatible = "ibm,iic-440gp", },
{ .compatible = "ibm,iic-440gpx", },
{ .compatible = "ibm,iic-440grx", },
{}
};
static struct of_platform_driver ibm_iic_driver = {
.name = "ibm-iic",
.match_table = ibm_iic_match,
.probe = iic_probe,
.remove = __devexit_p(iic_remove),
};
static int __init iic_init(void)
{
return of_register_platform_driver(&ibm_iic_driver);
}
static void __exit iic_exit(void)
{
of_unregister_platform_driver(&ibm_iic_driver);
}
#endif /* CONFIG_IBM_OCP */
module_init(iic_init);
module_exit(iic_exit);

View File

@ -550,3 +550,4 @@ module_exit (i2c_iop3xx_exit);
MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>");
MODULE_DESCRIPTION("IOP3xx iic algorithm and driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:IOP3xx-I2C");

View File

@ -164,4 +164,5 @@ module_exit(ixp2000_i2c_exit);
MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:IXP2000-I2C");

View File

@ -392,6 +392,9 @@ static int fsl_i2c_remove(struct platform_device *pdev)
return 0;
};
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:fsl-i2c");
/* Structure for a device driver */
static struct platform_driver fsl_i2c_driver = {
.probe = fsl_i2c_probe,

View File

@ -312,6 +312,9 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
return 0;
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:ocores-i2c");
static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove),

View File

@ -693,3 +693,4 @@ module_exit(omap_i2c_exit_driver);
MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:i2c_omap");

View File

@ -1,6 +1,7 @@
/*
* i2c-pca-isa.c driver for PCA9564 on ISA boards
* Copyright (C) 2004 Arcom Control Systems
* Copyright (C) 2008 Pengutronix
*
* 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
@ -22,11 +23,9 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/isa.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-pca.h>
@ -34,13 +33,9 @@
#include <asm/io.h>
#include <asm/irq.h>
#include "../algos/i2c-algo-pca.h"
#define DRIVER "i2c-pca-isa"
#define IO_SIZE 4
#undef DEBUG_IO
//#define DEBUG_IO
static unsigned long base = 0x330;
static int irq = 10;
@ -48,22 +43,9 @@ static int irq = 10;
* in the actual clock rate */
static int clock = I2C_PCA_CON_59kHz;
static int own = 0x55;
static wait_queue_head_t pca_wait;
static int pca_isa_getown(struct i2c_algo_pca_data *adap)
{
return (own);
}
static int pca_isa_getclock(struct i2c_algo_pca_data *adap)
{
return (clock);
}
static void
pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
static void pca_isa_writebyte(void *pd, int reg, int val)
{
#ifdef DEBUG_IO
static char *names[] = { "T/O", "DAT", "ADR", "CON" };
@ -72,44 +54,49 @@ pca_isa_writebyte(struct i2c_algo_pca_data *adap, int reg, int val)
outb(val, base+reg);
}
static int
pca_isa_readbyte(struct i2c_algo_pca_data *adap, int reg)
static int pca_isa_readbyte(void *pd, int reg)
{
int res = inb(base+reg);
#ifdef DEBUG_IO
{
static char *names[] = { "STA", "DAT", "ADR", "CON" };
static char *names[] = { "STA", "DAT", "ADR", "CON" };
printk("*** read %s => %#04x\n", names[reg], res);
}
#endif
return res;
}
static int pca_isa_waitforinterrupt(struct i2c_algo_pca_data *adap)
static int pca_isa_waitforcompletion(void *pd)
{
int ret = 0;
if (irq > -1) {
ret = wait_event_interruptible(pca_wait,
pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI);
pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
} else {
while ((pca_isa_readbyte(adap, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
udelay(100);
}
return ret;
}
static void pca_isa_resetchip(void *pd)
{
/* apparently only an external reset will do it. not a lot can be done */
printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n");
}
static irqreturn_t pca_handler(int this_irq, void *dev_id) {
wake_up_interruptible(&pca_wait);
return IRQ_HANDLED;
}
static struct i2c_algo_pca_data pca_isa_data = {
.get_own = pca_isa_getown,
.get_clock = pca_isa_getclock,
/* .data intentionally left NULL, not needed with ISA */
.write_byte = pca_isa_writebyte,
.read_byte = pca_isa_readbyte,
.wait_for_interrupt = pca_isa_waitforinterrupt,
.wait_for_completion = pca_isa_waitforcompletion,
.reset_chip = pca_isa_resetchip,
};
static struct i2c_adapter pca_isa_ops = {
@ -117,6 +104,7 @@ static struct i2c_adapter pca_isa_ops = {
.id = I2C_HW_A_ISA,
.algo_data = &pca_isa_data,
.name = "PCA9564 ISA Adapter",
.timeout = 100,
};
static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
@ -144,6 +132,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
}
}
pca_isa_data.i2c_clock = clock;
if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
dev_err(dev, "Failed to add i2c bus\n");
goto out_irq;
@ -178,7 +167,7 @@ static struct isa_driver pca_isa_driver = {
.remove = __devexit_p(pca_isa_remove),
.driver = {
.owner = THIS_MODULE,
.name = "i2c-pca-isa",
.name = DRIVER,
}
};
@ -204,7 +193,5 @@ MODULE_PARM_DESC(irq, "IRQ");
module_param(clock, int, 0);
MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
module_param(own, int, 0); /* the driver can't do slave mode, so there's no real point in this */
module_init(pca_isa_init);
module_exit(pca_isa_exit);

View File

@ -0,0 +1,298 @@
/*
* i2c_pca_platform.c
*
* Platform driver for the PCA9564 I2C controller.
*
* Copyright (C) 2008 Pengutronix
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c-algo-pca.h>
#include <linux/i2c-pca-platform.h>
#include <linux/gpio.h>
#include <asm/irq.h>
#include <asm/io.h>
#define res_len(r) ((r)->end - (r)->start + 1)
struct i2c_pca_pf_data {
void __iomem *reg_base;
int irq; /* if 0, use polling */
int gpio;
wait_queue_head_t wait;
struct i2c_adapter adap;
struct i2c_algo_pca_data algo_data;
unsigned long io_base;
unsigned long io_size;
};
/* Read/Write functions for different register alignments */
static int i2c_pca_pf_readbyte8(void *pd, int reg)
{
struct i2c_pca_pf_data *i2c = pd;
return ioread8(i2c->reg_base + reg);
}
static int i2c_pca_pf_readbyte16(void *pd, int reg)
{
struct i2c_pca_pf_data *i2c = pd;
return ioread8(i2c->reg_base + reg * 2);
}
static int i2c_pca_pf_readbyte32(void *pd, int reg)
{
struct i2c_pca_pf_data *i2c = pd;
return ioread8(i2c->reg_base + reg * 4);
}
static void i2c_pca_pf_writebyte8(void *pd, int reg, int val)
{
struct i2c_pca_pf_data *i2c = pd;
iowrite8(val, i2c->reg_base + reg);
}
static void i2c_pca_pf_writebyte16(void *pd, int reg, int val)
{
struct i2c_pca_pf_data *i2c = pd;
iowrite8(val, i2c->reg_base + reg * 2);
}
static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
{
struct i2c_pca_pf_data *i2c = pd;
iowrite8(val, i2c->reg_base + reg * 4);
}
static int i2c_pca_pf_waitforcompletion(void *pd)
{
struct i2c_pca_pf_data *i2c = pd;
int ret = 0;
if (i2c->irq) {
ret = wait_event_interruptible(i2c->wait,
i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
& I2C_PCA_CON_SI);
} else {
/*
* Do polling...
* XXX: Could get stuck in extreme cases!
* Maybe add timeout, but using irqs is preferred anyhow.
*/
while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
& I2C_PCA_CON_SI) == 0)
udelay(100);
}
return ret;
}
static void i2c_pca_pf_dummyreset(void *pd)
{
struct i2c_pca_pf_data *i2c = pd;
printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n",
i2c->adap.name);
}
static void i2c_pca_pf_resetchip(void *pd)
{
struct i2c_pca_pf_data *i2c = pd;
gpio_set_value(i2c->gpio, 0);
ndelay(100);
gpio_set_value(i2c->gpio, 1);
}
static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id)
{
struct i2c_pca_pf_data *i2c = dev_id;
if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
return IRQ_NONE;
wake_up_interruptible(&i2c->wait);
return IRQ_HANDLED;
}
static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
{
struct i2c_pca_pf_data *i2c;
struct resource *res;
struct i2c_pca9564_pf_platform_data *platform_data =
pdev->dev.platform_data;
int ret = 0;
int irq;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
/* If irq is 0, we do polling. */
if (res == NULL) {
ret = -ENODEV;
goto e_print;
}
if (!request_mem_region(res->start, res_len(res), res->name)) {
ret = -ENOMEM;
goto e_print;
}
i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL);
if (!i2c) {
ret = -ENOMEM;
goto e_alloc;
}
init_waitqueue_head(&i2c->wait);
i2c->reg_base = ioremap(res->start, res_len(res));
if (!i2c->reg_base) {
ret = -EIO;
goto e_remap;
}
i2c->io_base = res->start;
i2c->io_size = res_len(res);
i2c->irq = irq;
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
i2c->adap.owner = THIS_MODULE;
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx",
(unsigned long) res->start);
i2c->adap.algo_data = &i2c->algo_data;
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.timeout = platform_data->timeout;
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
i2c->algo_data.data = i2c;
switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
case IORESOURCE_MEM_32BIT:
i2c->algo_data.write_byte = i2c_pca_pf_writebyte32;
i2c->algo_data.read_byte = i2c_pca_pf_readbyte32;
break;
case IORESOURCE_MEM_16BIT:
i2c->algo_data.write_byte = i2c_pca_pf_writebyte16;
i2c->algo_data.read_byte = i2c_pca_pf_readbyte16;
break;
case IORESOURCE_MEM_8BIT:
default:
i2c->algo_data.write_byte = i2c_pca_pf_writebyte8;
i2c->algo_data.read_byte = i2c_pca_pf_readbyte8;
break;
}
i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
i2c->gpio = platform_data->gpio;
i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
/* Use gpio_is_valid() when in mainline */
if (i2c->gpio > -1) {
ret = gpio_request(i2c->gpio, i2c->adap.name);
if (ret == 0) {
gpio_direction_output(i2c->gpio, 1);
i2c->algo_data.reset_chip = i2c_pca_pf_resetchip;
} else {
printk(KERN_WARNING "%s: Registering gpio failed!\n",
i2c->adap.name);
i2c->gpio = ret;
}
}
if (irq) {
ret = request_irq(irq, i2c_pca_pf_handler,
IRQF_TRIGGER_FALLING, i2c->adap.name, i2c);
if (ret)
goto e_reqirq;
}
if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) {
ret = -ENODEV;
goto e_adapt;
}
platform_set_drvdata(pdev, i2c);
printk(KERN_INFO "%s registered.\n", i2c->adap.name);
return 0;
e_adapt:
if (irq)
free_irq(irq, i2c);
e_reqirq:
if (i2c->gpio > -1)
gpio_free(i2c->gpio);
iounmap(i2c->reg_base);
e_remap:
kfree(i2c);
e_alloc:
release_mem_region(res->start, res_len(res));
e_print:
printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
return ret;
}
static int __devexit i2c_pca_pf_remove(struct platform_device *pdev)
{
struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev);
platform_set_drvdata(pdev, NULL);
i2c_del_adapter(&i2c->adap);
if (i2c->irq)
free_irq(i2c->irq, i2c);
if (i2c->gpio > -1)
gpio_free(i2c->gpio);
iounmap(i2c->reg_base);
release_mem_region(i2c->io_base, i2c->io_size);
kfree(i2c);
return 0;
}
static struct platform_driver i2c_pca_pf_driver = {
.probe = i2c_pca_pf_probe,
.remove = __devexit_p(i2c_pca_pf_remove),
.driver = {
.name = "i2c-pca-platform",
.owner = THIS_MODULE,
},
};
static int __init i2c_pca_pf_init(void)
{
return platform_driver_register(&i2c_pca_pf_driver);
}
static void __exit i2c_pca_pf_exit(void)
{
platform_driver_unregister(&i2c_pca_pf_driver);
}
MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
MODULE_LICENSE("GPL");
module_init(i2c_pca_pf_init);
module_exit(i2c_pca_pf_exit);

View File

@ -467,7 +467,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
(cmd->read_len == 0 || cmd->write_len == 0))) {
dev_err(&pmcmsptwi_adapter.dev,
"%s: Cannot transfer less than 1 byte\n",
__FUNCTION__);
__func__);
return -EINVAL;
}
@ -475,7 +475,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd(
cmd->write_len > MSP_MAX_BYTES_PER_RW) {
dev_err(&pmcmsptwi_adapter.dev,
"%s: Cannot transfer more than %d bytes\n",
__FUNCTION__, MSP_MAX_BYTES_PER_RW);
__func__, MSP_MAX_BYTES_PER_RW);
return -EINVAL;
}
@ -627,6 +627,9 @@ static struct i2c_adapter pmcmsptwi_adapter = {
.name = DRV_NAME,
};
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:" DRV_NAME);
static struct platform_driver pmcmsptwi_driver = {
.probe = pmcmsptwi_probe,
.remove = __devexit_p(pmcmsptwi_remove),

View File

@ -76,7 +76,7 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
{
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__,
dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __func__,
slave_addr, alg_data->mif.mode);
/* Check for 7 bit slave addresses only */
@ -110,14 +110,14 @@ static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap)
iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__,
dev_dbg(&adap->dev, "%s(): sending %#x\n", __func__,
(slave_addr << 1) | start_bit | alg_data->mif.mode);
/* Write the slave address, START bit and R/W bit */
iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
I2C_REG_TX(alg_data));
dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__);
dev_dbg(&adap->dev, "%s(): exit\n", __func__);
return 0;
}
@ -135,7 +135,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
long timeout = 1000;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
/* Write a STOP bit to TX FIFO */
iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
@ -149,7 +149,7 @@ static void i2c_pnx_stop(struct i2c_adapter *adap)
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
}
/**
@ -164,7 +164,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
u32 val;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
if (alg_data->mif.len > 0) {
/* We still have something to talk about... */
@ -179,7 +179,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
alg_data->mif.len--;
iowrite32(val, I2C_REG_TX(alg_data));
dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__,
dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __func__,
val, alg_data->mif.len + 1);
if (alg_data->mif.len == 0) {
@ -197,7 +197,7 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
del_timer_sync(&alg_data->mif.timer);
dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n",
__FUNCTION__);
__func__);
complete(&alg_data->mif.complete);
}
@ -213,13 +213,13 @@ static int i2c_pnx_master_xmit(struct i2c_adapter *adap)
/* Stop timer. */
del_timer_sync(&alg_data->mif.timer);
dev_dbg(&adap->dev, "%s(): Waking up xfer routine after "
"zero-xfer.\n", __FUNCTION__);
"zero-xfer.\n", __func__);
complete(&alg_data->mif.complete);
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
return 0;
}
@ -237,14 +237,14 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
u32 ctl = 0;
dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
/* Check, whether there is already data,
* or we didn't 'ask' for it yet.
*/
if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
dev_dbg(&adap->dev, "%s(): Write dummy data to fill "
"Rx-fifo...\n", __FUNCTION__);
"Rx-fifo...\n", __func__);
if (alg_data->mif.len == 1) {
/* Last byte, do not acknowledge next rcv. */
@ -276,7 +276,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
if (alg_data->mif.len > 0) {
val = ioread32(I2C_REG_RX(alg_data));
*alg_data->mif.buf++ = (u8) (val & 0xff);
dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val,
dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __func__, val,
alg_data->mif.len);
alg_data->mif.len--;
@ -300,7 +300,7 @@ static int i2c_pnx_master_rcv(struct i2c_adapter *adap)
}
dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
return 0;
}
@ -312,7 +312,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n",
__FUNCTION__,
__func__,
ioread32(I2C_REG_STS(alg_data)),
ioread32(I2C_REG_CTL(alg_data)),
alg_data->mif.mode);
@ -336,7 +336,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
/* Slave did not acknowledge, generate a STOP */
dev_dbg(&adap->dev, "%s(): "
"Slave did not acknowledge, generating a STOP.\n",
__FUNCTION__);
__func__);
i2c_pnx_stop(adap);
/* Disable master interrupts. */
@ -375,7 +375,7 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)),
__func__, ioread32(I2C_REG_STS(alg_data)),
ioread32(I2C_REG_CTL(alg_data)));
return IRQ_HANDLED;
@ -447,7 +447,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
u32 stat = ioread32(I2C_REG_STS(alg_data));
dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n",
__FUNCTION__, num, ioread32(I2C_REG_STS(alg_data)));
__func__, num, ioread32(I2C_REG_STS(alg_data)));
bus_reset_if_active(adap);
@ -473,7 +473,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
alg_data->mif.ret = 0;
alg_data->last = (i == num - 1);
dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__,
dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __func__,
alg_data->mif.mode,
alg_data->mif.len);
@ -498,7 +498,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
if (!(rc = alg_data->mif.ret))
completed++;
dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n",
__FUNCTION__, rc);
__func__, rc);
/* Clear TDI and AFI bits in case they are set. */
if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
@ -522,7 +522,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
alg_data->mif.len = 0;
dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n",
__FUNCTION__, ioread32(I2C_REG_STS(alg_data)));
__func__, ioread32(I2C_REG_STS(alg_data)));
if (completed != num)
return ((rc < 0) ? rc : -EREMOTEIO);
@ -563,7 +563,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev)
if (!i2c_pnx || !i2c_pnx->adapter) {
dev_err(&pdev->dev, "%s: no platform data supplied\n",
__FUNCTION__);
__func__);
ret = -EINVAL;
goto out;
}
@ -697,6 +697,7 @@ static void __exit i2c_adap_pnx_exit(void)
MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pnx-i2c");
/* We need to make sure I2C is initialized before USB */
subsys_initcall(i2c_adap_pnx_init);

View File

@ -263,6 +263,9 @@ static int __devexit i2c_powermac_probe(struct platform_device *dev)
}
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c-powermac");
static struct platform_driver i2c_powermac_driver = {
.probe = i2c_powermac_probe,
.remove = __devexit_p(i2c_powermac_remove),

View File

@ -155,7 +155,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c)));
}
#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__)
#else
#define i2c_debug 0
@ -1132,6 +1132,7 @@ static void __exit i2c_adap_pxa_exit(void)
}
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:pxa2xx-i2c");
module_init(i2c_adap_pxa_init);
module_exit(i2c_adap_pxa_exit);

View File

@ -276,12 +276,12 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
switch (i2c->state) {
case STATE_IDLE:
dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __FUNCTION__);
dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__);
goto out;
break;
case STATE_STOP:
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __FUNCTION__);
dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__);
s3c24xx_i2c_disable_irq(i2c);
goto out_ack;
@ -948,3 +948,4 @@ module_exit(i2c_adap_s3c_exit);
MODULE_DESCRIPTION("S3C24XX I2C Bus driver");
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:s3c2410-i2c");

View File

@ -0,0 +1,577 @@
/*
* I2C bus driver for the SH7760 I2C Interfaces.
*
* (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
*
* licensed under the terms outlined in the file COPYING.
*
*/
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <asm/clock.h>
#include <asm/i2c-sh7760.h>
#include <asm/io.h>
/* register offsets */
#define I2CSCR 0x0 /* slave ctrl */
#define I2CMCR 0x4 /* master ctrl */
#define I2CSSR 0x8 /* slave status */
#define I2CMSR 0xC /* master status */
#define I2CSIER 0x10 /* slave irq enable */
#define I2CMIER 0x14 /* master irq enable */
#define I2CCCR 0x18 /* clock dividers */
#define I2CSAR 0x1c /* slave address */
#define I2CMAR 0x20 /* master address */
#define I2CRXTX 0x24 /* data port */
#define I2CFCR 0x28 /* fifo control */
#define I2CFSR 0x2C /* fifo status */
#define I2CFIER 0x30 /* fifo irq enable */
#define I2CRFDR 0x34 /* rx fifo count */
#define I2CTFDR 0x38 /* tx fifo count */
#define REGSIZE 0x3C
#define MCR_MDBS 0x80 /* non-fifo mode switch */
#define MCR_FSCL 0x40 /* override SCL pin */
#define MCR_FSDA 0x20 /* override SDA pin */
#define MCR_OBPC 0x10 /* override pins */
#define MCR_MIE 0x08 /* master if enable */
#define MCR_TSBE 0x04
#define MCR_FSB 0x02 /* force stop bit */
#define MCR_ESG 0x01 /* en startbit gen. */
#define MSR_MNR 0x40 /* nack received */
#define MSR_MAL 0x20 /* arbitration lost */
#define MSR_MST 0x10 /* sent a stop */
#define MSR_MDE 0x08
#define MSR_MDT 0x04
#define MSR_MDR 0x02
#define MSR_MAT 0x01 /* slave addr xfer done */
#define MIE_MNRE 0x40 /* nack irq en */
#define MIE_MALE 0x20 /* arblos irq en */
#define MIE_MSTE 0x10 /* stop irq en */
#define MIE_MDEE 0x08
#define MIE_MDTE 0x04
#define MIE_MDRE 0x02
#define MIE_MATE 0x01 /* address sent irq en */
#define FCR_RFRST 0x02 /* reset rx fifo */
#define FCR_TFRST 0x01 /* reset tx fifo */
#define FSR_TEND 0x04 /* last byte sent */
#define FSR_RDF 0x02 /* rx fifo trigger */
#define FSR_TDFE 0x01 /* tx fifo empty */
#define FIER_TEIE 0x04 /* tx fifo empty irq en */
#define FIER_RXIE 0x02 /* rx fifo trig irq en */
#define FIER_TXIE 0x01 /* tx fifo trig irq en */
#define FIFO_SIZE 16
struct cami2c {
void __iomem *iobase;
struct i2c_adapter adap;
/* message processing */
struct i2c_msg *msg;
#define IDF_SEND 1
#define IDF_RECV 2
#define IDF_STOP 4
int flags;
#define IDS_DONE 1
#define IDS_ARBLOST 2
#define IDS_NACK 4
int status;
struct completion xfer_done;
int irq;
struct resource *ioarea;
};
static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
{
ctrl_outl(val, (unsigned long)cam->iobase + reg);
}
static inline unsigned long IN32(struct cami2c *cam, int reg)
{
return ctrl_inl((unsigned long)cam->iobase + reg);
}
static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
{
struct cami2c *id = ptr;
struct i2c_msg *msg = id->msg;
char *data = msg->buf;
unsigned long msr, fsr, fier, len;
msr = IN32(id, I2CMSR);
fsr = IN32(id, I2CFSR);
/* arbitration lost */
if (msr & MSR_MAL) {
OUT32(id, I2CMCR, 0);
OUT32(id, I2CSCR, 0);
OUT32(id, I2CSAR, 0);
id->status |= IDS_DONE | IDS_ARBLOST;
goto out;
}
if (msr & MSR_MNR) {
/* NACK handling is very screwed up. After receiving a
* NAK IRQ one has to wait a bit before writing to any
* registers, or the ctl will lock up. After that delay
* do a normal i2c stop. Then wait at least 1 ms before
* attempting another transfer or ctl will stop working
*/
udelay(100); /* wait or risk ctl hang */
OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
OUT32(id, I2CFIER, 0);
OUT32(id, I2CMIER, MIE_MSTE);
OUT32(id, I2CSCR, 0);
OUT32(id, I2CSAR, 0);
id->status |= IDS_NACK;
msr &= ~MSR_MAT;
fsr = 0;
/* In some cases the MST bit is also set. */
}
/* i2c-stop was sent */
if (msr & MSR_MST) {
id->status |= IDS_DONE;
goto out;
}
/* i2c slave addr was sent; set to "normal" operation */
if (msr & MSR_MAT)
OUT32(id, I2CMCR, MCR_MIE);
fier = IN32(id, I2CFIER);
if (fsr & FSR_RDF) {
len = IN32(id, I2CRFDR);
if (msg->len <= len) {
if (id->flags & IDF_STOP) {
OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
OUT32(id, I2CFIER, 0);
/* manual says: wait >= 0.5 SCL times */
udelay(5);
/* next int should be MST */
} else {
id->status |= IDS_DONE;
/* keep the RDF bit: ctrl holds SCL low
* until the setup for the next i2c_msg
* clears this bit.
*/
fsr &= ~FSR_RDF;
}
}
while (msg->len && len) {
*data++ = IN32(id, I2CRXTX);
msg->len--;
len--;
}
if (msg->len) {
len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
: msg->len - 1;
OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
}
} else if (id->flags & IDF_SEND) {
if ((fsr & FSR_TEND) && (msg->len < 1)) {
if (id->flags & IDF_STOP) {
OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
} else {
id->status |= IDS_DONE;
/* keep the TEND bit: ctl holds SCL low
* until the setup for the next i2c_msg
* clears this bit.
*/
fsr &= ~FSR_TEND;
}
}
if (fsr & FSR_TDFE) {
while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) {
OUT32(id, I2CRXTX, *data++);
msg->len--;
}
if (msg->len < 1) {
fier &= ~FIER_TXIE;
OUT32(id, I2CFIER, fier);
} else {
len = (msg->len >= FIFO_SIZE) ? 2 : 0;
OUT32(id, I2CFCR,
FCR_RFRST | ((len & 3) << 2));
}
}
}
out:
if (id->status & IDS_DONE) {
OUT32(id, I2CMIER, 0);
OUT32(id, I2CFIER, 0);
id->msg = NULL;
complete(&id->xfer_done);
}
/* clear status flags and ctrl resumes work */
OUT32(id, I2CMSR, ~msr);
OUT32(id, I2CFSR, ~fsr);
OUT32(id, I2CSSR, 0);
return IRQ_HANDLED;
}
/* prepare and start a master receive operation */
static void sh7760_i2c_mrecv(struct cami2c *id)
{
int len;
id->flags |= IDF_RECV;
/* set the slave addr reg; otherwise rcv wont work! */
OUT32(id, I2CSAR, 0xfe);
OUT32(id, I2CMAR, (id->msg->addr << 1) | 1);
/* adjust rx fifo trigger */
if (id->msg->len >= FIFO_SIZE)
len = FIFO_SIZE - 1; /* trigger at fifo full */
else
len = id->msg->len - 1; /* trigger before all received */
OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4));
OUT32(id, I2CMSR, 0);
OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
OUT32(id, I2CFIER, FIER_RXIE);
}
/* prepare and start a master send operation */
static void sh7760_i2c_msend(struct cami2c *id)
{
int len;
id->flags |= IDF_SEND;
/* set the slave addr reg; otherwise xmit wont work! */
OUT32(id, I2CSAR, 0xfe);
OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
/* adjust tx fifo trigger */
if (id->msg->len >= FIFO_SIZE)
len = 2; /* trig: 2 bytes left in TX fifo */
else
len = 0; /* trig: 8 bytes left in TX fifo */
OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
OUT32(id, I2CRXTX, *(id->msg->buf));
(id->msg->len)--;
(id->msg->buf)++;
}
OUT32(id, I2CMSR, 0);
OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
OUT32(id, I2CFSR, 0);
OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0));
}
static inline int sh7760_i2c_busy_check(struct cami2c *id)
{
return (IN32(id, I2CMCR) & MCR_FSDA);
}
static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs,
int num)
{
struct cami2c *id = adap->algo_data;
int i, retr;
if (sh7760_i2c_busy_check(id)) {
dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
return -EBUSY;
}
i = 0;
while (i < num) {
retr = adap->retries;
retry:
id->flags = ((i == (num-1)) ? IDF_STOP : 0);
id->status = 0;
id->msg = msgs;
init_completion(&id->xfer_done);
if (msgs->flags & I2C_M_RD)
sh7760_i2c_mrecv(id);
else
sh7760_i2c_msend(id);
wait_for_completion(&id->xfer_done);
if (id->status == 0) {
num = -EIO;
break;
}
if (id->status & IDS_NACK) {
/* wait a bit or i2c module stops working */
mdelay(1);
num = -EREMOTEIO;
break;
}
if (id->status & IDS_ARBLOST) {
if (retr--) {
mdelay(2);
goto retry;
}
num = -EREMOTEIO;
break;
}
msgs++;
i++;
}
id->msg = NULL;
id->flags = 0;
id->status = 0;
OUT32(id, I2CMCR, 0);
OUT32(id, I2CMSR, 0);
OUT32(id, I2CMIER, 0);
OUT32(id, I2CFIER, 0);
/* reset slave module registers too: master mode enables slave
* module for receive ops (ack, data). Without this reset,
* eternal bus activity might be reported after NACK / ARBLOST.
*/
OUT32(id, I2CSCR, 0);
OUT32(id, I2CSAR, 0);
OUT32(id, I2CSSR, 0);
return num;
}
static u32 sh7760_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
}
static const struct i2c_algorithm sh7760_i2c_algo = {
.master_xfer = sh7760_i2c_master_xfer,
.functionality = sh7760_i2c_func,
};
/* calculate CCR register setting for a desired scl clock. SCL clock is
* derived from I2C module clock (iclk) which in turn is derived from
* peripheral module clock (mclk, usually around 33MHz):
* iclk = mclk/(CDF + 1). iclk must be < 20MHz.
* scl = iclk/(SCGD*8 + 20).
*/
static int __devinit calc_CCR(unsigned long scl_hz)
{
struct clk *mclk;
unsigned long mck, m1, dff, odff, iclk;
signed char cdf, cdfm;
int scgd, scgdm, scgds;
mclk = clk_get(NULL, "module_clk");
if (IS_ERR(mclk)) {
return PTR_ERR(mclk);
} else {
mck = mclk->rate;
clk_put(mclk);
}
odff = scl_hz;
scgdm = cdfm = m1 = 0;
for (cdf = 3; cdf >= 0; cdf--) {
iclk = mck / (1 + cdf);
if (iclk >= 20000000)
continue;
scgds = ((iclk / scl_hz) - 20) >> 3;
for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) {
m1 = iclk / (20 + (scgd << 3));
dff = abs(scl_hz - m1);
if (dff < odff) {
odff = dff;
cdfm = cdf;
scgdm = scgd;
}
}
}
/* fail if more than 25% off of requested SCL */
if (odff > (scl_hz >> 2))
return -EINVAL;
/* create a CCR register value */
return ((scgdm << 2) | cdfm);
}
static int __devinit sh7760_i2c_probe(struct platform_device *pdev)
{
struct sh7760_i2c_platdata *pd;
struct resource *res;
struct cami2c *id;
int ret;
pd = pdev->dev.platform_data;
if (!pd) {
dev_err(&pdev->dev, "no platform_data!\n");
ret = -ENODEV;
goto out0;
}
id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
if (!id) {
dev_err(&pdev->dev, "no mem for private data\n");
ret = -ENOMEM;
goto out0;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "no mmio resources\n");
ret = -ENODEV;
goto out1;
}
id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name);
if (!id->ioarea) {
dev_err(&pdev->dev, "mmio already reserved\n");
ret = -EBUSY;
goto out1;
}
id->iobase = ioremap(res->start, REGSIZE);
if (!id->iobase) {
dev_err(&pdev->dev, "cannot ioremap\n");
ret = -ENODEV;
goto out2;
}
id->irq = platform_get_irq(pdev, 0);
id->adap.nr = pdev->id;
id->adap.algo = &sh7760_i2c_algo;
id->adap.class = I2C_CLASS_ALL;
id->adap.retries = 3;
id->adap.algo_data = id;
id->adap.dev.parent = &pdev->dev;
snprintf(id->adap.name, sizeof(id->adap.name),
"SH7760 I2C at %08lx", (unsigned long)res->start);
OUT32(id, I2CMCR, 0);
OUT32(id, I2CMSR, 0);
OUT32(id, I2CMIER, 0);
OUT32(id, I2CMAR, 0);
OUT32(id, I2CSIER, 0);
OUT32(id, I2CSAR, 0);
OUT32(id, I2CSCR, 0);
OUT32(id, I2CSSR, 0);
OUT32(id, I2CFIER, 0);
OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
OUT32(id, I2CFSR, 0);
ret = calc_CCR(pd->speed_khz * 1000);
if (ret < 0) {
dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n",
pd->speed_khz);
goto out3;
}
OUT32(id, I2CCCR, ret);
if (request_irq(id->irq, sh7760_i2c_irq, IRQF_DISABLED,
SH7760_I2C_DEVNAME, id)) {
dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
ret = -EBUSY;
goto out3;
}
ret = i2c_add_numbered_adapter(&id->adap);
if (ret < 0) {
dev_err(&pdev->dev, "reg adap failed: %d\n", ret);
goto out4;
}
platform_set_drvdata(pdev, id);
dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n",
pd->speed_khz, res->start, id->irq);
return 0;
out4:
free_irq(id->irq, id);
out3:
iounmap(id->iobase);
out2:
release_resource(id->ioarea);
kfree(id->ioarea);
out1:
kfree(id);
out0:
return ret;
}
static int __devexit sh7760_i2c_remove(struct platform_device *pdev)
{
struct cami2c *id = platform_get_drvdata(pdev);
i2c_del_adapter(&id->adap);
free_irq(id->irq, id);
iounmap(id->iobase);
release_resource(id->ioarea);
kfree(id->ioarea);
kfree(id);
platform_set_drvdata(pdev, NULL);
return 0;
}
static struct platform_driver sh7760_i2c_drv = {
.driver = {
.name = SH7760_I2C_DEVNAME,
.owner = THIS_MODULE,
},
.probe = sh7760_i2c_probe,
.remove = __devexit_p(sh7760_i2c_remove),
};
static int __init sh7760_i2c_init(void)
{
return platform_driver_register(&sh7760_i2c_drv);
}
static void __exit sh7760_i2c_exit(void)
{
platform_driver_unregister(&sh7760_i2c_drv);
}
module_init(sh7760_i2c_init);
module_exit(sh7760_i2c_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 I2C bus driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");

View File

@ -0,0 +1,500 @@
/*
* SuperH Mobile I2C Controller
*
* Copyright (C) 2008 Magnus Damm
*
* Portions of the code based on out-of-tree driver i2c-sh7343.c
* Copyright (c) 2006 Carlos Munoz <carlos@kenati.com>
*
* 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
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
enum sh_mobile_i2c_op {
OP_START = 0,
OP_TX_ONLY,
OP_TX_STOP,
OP_TX_TO_RX,
OP_RX_ONLY,
OP_RX_STOP,
};
struct sh_mobile_i2c_data {
struct device *dev;
void __iomem *reg;
struct i2c_adapter adap;
struct clk *clk;
u_int8_t iccl;
u_int8_t icch;
spinlock_t lock;
wait_queue_head_t wait;
struct i2c_msg *msg;
int pos;
int sr;
};
#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
/* Register offsets */
#define ICDR(pd) (pd->reg + 0x00)
#define ICCR(pd) (pd->reg + 0x04)
#define ICSR(pd) (pd->reg + 0x08)
#define ICIC(pd) (pd->reg + 0x0c)
#define ICCL(pd) (pd->reg + 0x10)
#define ICCH(pd) (pd->reg + 0x14)
/* Register bits */
#define ICCR_ICE 0x80
#define ICCR_RACK 0x40
#define ICCR_TRS 0x10
#define ICCR_BBSY 0x04
#define ICCR_SCP 0x01
#define ICSR_SCLM 0x80
#define ICSR_SDAM 0x40
#define SW_DONE 0x20
#define ICSR_BUSY 0x10
#define ICSR_AL 0x08
#define ICSR_TACK 0x04
#define ICSR_WAIT 0x02
#define ICSR_DTE 0x01
#define ICIC_ALE 0x08
#define ICIC_TACKE 0x04
#define ICIC_WAITE 0x02
#define ICIC_DTEE 0x01
static void activate_ch(struct sh_mobile_i2c_data *pd)
{
/* Make sure the clock is enabled */
clk_enable(pd->clk);
/* Enable channel and configure rx ack */
iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
/* Mask all interrupts */
iowrite8(0, ICIC(pd));
/* Set the clock */
iowrite8(pd->iccl, ICCL(pd));
iowrite8(pd->icch, ICCH(pd));
}
static void deactivate_ch(struct sh_mobile_i2c_data *pd)
{
/* Clear/disable interrupts */
iowrite8(0, ICSR(pd));
iowrite8(0, ICIC(pd));
/* Disable channel */
iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
/* Disable clock */
clk_disable(pd->clk);
}
static unsigned char i2c_op(struct sh_mobile_i2c_data *pd,
enum sh_mobile_i2c_op op, unsigned char data)
{
unsigned char ret = 0;
unsigned long flags;
dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data);
spin_lock_irqsave(&pd->lock, flags);
switch (op) {
case OP_START:
iowrite8(0x94, ICCR(pd));
break;
case OP_TX_ONLY:
iowrite8(data, ICDR(pd));
break;
case OP_TX_STOP:
iowrite8(data, ICDR(pd));
iowrite8(0x90, ICCR(pd));
iowrite8(ICIC_ALE | ICIC_TACKE, ICIC(pd));
break;
case OP_TX_TO_RX:
iowrite8(data, ICDR(pd));
iowrite8(0x81, ICCR(pd));
break;
case OP_RX_ONLY:
ret = ioread8(ICDR(pd));
break;
case OP_RX_STOP:
ret = ioread8(ICDR(pd));
iowrite8(0xc0, ICCR(pd));
break;
}
spin_unlock_irqrestore(&pd->lock, flags);
dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret);
return ret;
}
static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
{
struct platform_device *dev = dev_id;
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
struct i2c_msg *msg = pd->msg;
unsigned char data, sr;
int wakeup = 0;
sr = ioread8(ICSR(pd));
pd->sr |= sr;
dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr,
(msg->flags & I2C_M_RD) ? "read" : "write",
pd->pos, msg->len);
if (sr & (ICSR_AL | ICSR_TACK)) {
iowrite8(0, ICIC(pd)); /* disable interrupts */
wakeup = 1;
goto do_wakeup;
}
if (pd->pos == msg->len) {
i2c_op(pd, OP_RX_ONLY, 0);
wakeup = 1;
goto do_wakeup;
}
if (pd->pos == -1) {
data = (msg->addr & 0x7f) << 1;
data |= (msg->flags & I2C_M_RD) ? 1 : 0;
} else
data = msg->buf[pd->pos];
if ((pd->pos == -1) || !(msg->flags & I2C_M_RD)) {
if (msg->flags & I2C_M_RD)
i2c_op(pd, OP_TX_TO_RX, data);
else if (pd->pos == (msg->len - 1)) {
i2c_op(pd, OP_TX_STOP, data);
wakeup = 1;
} else
i2c_op(pd, OP_TX_ONLY, data);
} else {
if (pd->pos == (msg->len - 1))
data = i2c_op(pd, OP_RX_STOP, 0);
else
data = i2c_op(pd, OP_RX_ONLY, 0);
msg->buf[pd->pos] = data;
}
pd->pos++;
do_wakeup:
if (wakeup) {
pd->sr |= SW_DONE;
wake_up(&pd->wait);
}
return IRQ_HANDLED;
}
static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
{
/* Initialize channel registers */
iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd));
/* Enable channel and configure rx ack */
iowrite8(ioread8(ICCR(pd)) | ICCR_ICE, ICCR(pd));
/* Set the clock */
iowrite8(pd->iccl, ICCL(pd));
iowrite8(pd->icch, ICCH(pd));
pd->msg = usr_msg;
pd->pos = -1;
pd->sr = 0;
/* Enable all interrupts except wait */
iowrite8(ioread8(ICIC(pd)) | ICIC_ALE | ICIC_TACKE | ICIC_DTEE,
ICIC(pd));
return 0;
}
static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter,
struct i2c_msg *msgs,
int num)
{
struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter);
struct i2c_msg *msg;
int err = 0;
u_int8_t val;
int i, k, retry_count;
activate_ch(pd);
/* Process all messages */
for (i = 0; i < num; i++) {
msg = &msgs[i];
err = start_ch(pd, msg);
if (err)
break;
i2c_op(pd, OP_START, 0);
/* The interrupt handler takes care of the rest... */
k = wait_event_timeout(pd->wait,
pd->sr & (ICSR_TACK | SW_DONE),
5 * HZ);
if (!k)
dev_err(pd->dev, "Transfer request timed out\n");
retry_count = 10;
again:
val = ioread8(ICSR(pd));
dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr);
if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) {
err = -EIO;
break;
}
/* the interrupt handler may wake us up before the
* transfer is finished, so poll the hardware
* until we're done.
*/
if (!(!(val & ICSR_BUSY) && (val & ICSR_SCLM) &&
(val & ICSR_SDAM))) {
msleep(1);
if (retry_count--)
goto again;
err = -EIO;
dev_err(pd->dev, "Polling timed out\n");
break;
}
}
deactivate_ch(pd);
if (!err)
err = num;
return err;
}
static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}
static struct i2c_algorithm sh_mobile_i2c_algorithm = {
.functionality = sh_mobile_i2c_func,
.master_xfer = sh_mobile_i2c_xfer,
};
static void sh_mobile_i2c_setup_channel(struct platform_device *dev)
{
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
unsigned long peripheral_clk = clk_get_rate(pd->clk);
u_int32_t num;
u_int32_t denom;
u_int32_t tmp;
spin_lock_init(&pd->lock);
init_waitqueue_head(&pd->wait);
/* Calculate the value for iccl. From the data sheet:
* iccl = (p clock / transfer rate) * (L / (L + H))
* where L and H are the SCL low/high ratio (5/4 in this case).
* We also round off the result.
*/
num = peripheral_clk * 5;
denom = NORMAL_SPEED * 9;
tmp = num * 10 / denom;
if (tmp % 10 >= 5)
pd->iccl = (u_int8_t)((num/denom) + 1);
else
pd->iccl = (u_int8_t)(num/denom);
/* Calculate the value for icch. From the data sheet:
icch = (p clock / transfer rate) * (H / (L + H)) */
num = peripheral_clk * 4;
tmp = num * 10 / denom;
if (tmp % 10 >= 5)
pd->icch = (u_int8_t)((num/denom) + 1);
else
pd->icch = (u_int8_t)(num/denom);
}
static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
{
struct resource *res;
int ret = -ENXIO;
int q, m;
int k = 0;
int n = 0;
while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
for (n = res->start; hook && n <= res->end; n++) {
if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
dev->dev.bus_id, dev))
goto rollback;
}
k++;
}
if (hook)
return k > 0 ? 0 : -ENOENT;
k--;
ret = 0;
rollback:
for (q = k; k >= 0; k--) {
for (m = n; m >= res->start; m--)
free_irq(m, dev);
res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
m = res->end;
}
return ret;
}
static int sh_mobile_i2c_probe(struct platform_device *dev)
{
struct sh_mobile_i2c_data *pd;
struct i2c_adapter *adap;
struct resource *res;
int size;
int ret;
pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL);
if (pd == NULL) {
dev_err(&dev->dev, "cannot allocate private data\n");
return -ENOMEM;
}
pd->clk = clk_get(&dev->dev, "peripheral_clk");
if (IS_ERR(pd->clk)) {
dev_err(&dev->dev, "cannot get peripheral clock\n");
ret = PTR_ERR(pd->clk);
goto err;
}
ret = sh_mobile_i2c_hook_irqs(dev, 1);
if (ret) {
dev_err(&dev->dev, "cannot request IRQ\n");
goto err_clk;
}
pd->dev = &dev->dev;
platform_set_drvdata(dev, pd);
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (res == NULL) {
dev_err(&dev->dev, "cannot find IO resource\n");
ret = -ENOENT;
goto err_irq;
}
size = (res->end - res->start) + 1;
pd->reg = ioremap(res->start, size);
if (pd->reg == NULL) {
dev_err(&dev->dev, "cannot map IO\n");
ret = -ENXIO;
goto err_irq;
}
/* setup the private data */
adap = &pd->adap;
i2c_set_adapdata(adap, pd);
adap->owner = THIS_MODULE;
adap->algo = &sh_mobile_i2c_algorithm;
adap->dev.parent = &dev->dev;
adap->retries = 5;
adap->nr = dev->id;
strlcpy(adap->name, dev->name, sizeof(adap->name));
sh_mobile_i2c_setup_channel(dev);
ret = i2c_add_numbered_adapter(adap);
if (ret < 0) {
dev_err(&dev->dev, "cannot add numbered adapter\n");
goto err_all;
}
return 0;
err_all:
iounmap(pd->reg);
err_irq:
sh_mobile_i2c_hook_irqs(dev, 0);
err_clk:
clk_put(pd->clk);
err:
kfree(pd);
return ret;
}
static int sh_mobile_i2c_remove(struct platform_device *dev)
{
struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev);
i2c_del_adapter(&pd->adap);
iounmap(pd->reg);
sh_mobile_i2c_hook_irqs(dev, 0);
clk_put(pd->clk);
kfree(pd);
return 0;
}
static struct platform_driver sh_mobile_i2c_driver = {
.driver = {
.name = "i2c-sh_mobile",
.owner = THIS_MODULE,
},
.probe = sh_mobile_i2c_probe,
.remove = sh_mobile_i2c_remove,
};
static int __init sh_mobile_i2c_adap_init(void)
{
return platform_driver_register(&sh_mobile_i2c_driver);
}
static void __exit sh_mobile_i2c_adap_exit(void)
{
platform_driver_unregister(&sh_mobile_i2c_driver);
}
module_init(sh_mobile_i2c_adap_init);
module_exit(sh_mobile_i2c_adap_exit);
MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver");
MODULE_AUTHOR("Magnus Damm");
MODULE_LICENSE("GPL v2");

View File

@ -159,6 +159,9 @@ static int simtec_i2c_remove(struct platform_device *dev)
/* device driver */
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:simtec-i2c");
static struct platform_driver simtec_i2c_driver = {
.driver = {
.name = "simtec-i2c",

View File

@ -151,3 +151,4 @@ module_exit(i2c_versatile_exit);
MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:versatile-i2c");

View File

@ -527,7 +527,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base,
if (iface == NULL)
return -ENOMEM;
if (request_region(base, 8, iface->adapter.name) == 0) {
if (!request_region(base, 8, iface->adapter.name)) {
printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
base, base + 8 - 1);
rc = -EBUSY;

View File

@ -658,7 +658,7 @@ pulldown:
OTG_CTRL_REG |= OTG_PULLUP;
}
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
dump_regs(isp, "otg->isp1301");
}
@ -782,7 +782,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
if (otg_ctrl & OTG_DRIVER_SEL) {
switch (isp->otg.state) {
case OTG_STATE_A_IDLE:
b_idle(isp, __FUNCTION__);
b_idle(isp, __func__);
break;
default:
break;
@ -826,7 +826,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp)
isp->otg.host->otg_port);
}
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
return ret;
}
@ -837,7 +837,7 @@ static int otg_init(struct isp1301 *isp)
if (!otg_dev)
return -ENODEV;
dump_regs(isp, __FUNCTION__);
dump_regs(isp, __func__);
/* some of these values are board-specific... */
OTG_SYSCON_2_REG |= OTG_EN
/* for B-device: */
@ -853,9 +853,9 @@ static int otg_init(struct isp1301 *isp)
update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE));
update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
pr_debug("otg: %s, %s %06x\n",
state_name(isp), __FUNCTION__, OTG_CTRL_REG);
state_name(isp), __func__, OTG_CTRL_REG);
OTG_IRQ_EN_REG = DRIVER_SWITCH | OPRT_CHG
| B_SRP_TMROUT | B_HNP_FAIL
@ -1041,11 +1041,11 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
OTG1_DP_PULLDOWN);
isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1,
OTG1_DP_PULLUP);
dump_regs(isp, __FUNCTION__);
dump_regs(isp, __func__);
#endif
/* FALLTHROUGH */
case OTG_STATE_B_SRP_INIT:
b_idle(isp, __FUNCTION__);
b_idle(isp, __func__);
OTG_CTRL_REG &= OTG_CTRL_REG & OTG_XCEIV_OUTPUTS;
/* FALLTHROUGH */
case OTG_STATE_B_IDLE:
@ -1077,7 +1077,7 @@ static void isp_update_otg(struct isp1301 *isp, u8 stat)
*/
update_otg1(isp, isp_stat);
update_otg2(isp, isp_bstat);
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
#endif
dump_regs(isp, "isp1301->otg");
@ -1310,7 +1310,7 @@ isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host)
*/
isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV);
dump_regs(isp, __FUNCTION__);
dump_regs(isp, __func__);
return 0;
@ -1365,7 +1365,7 @@ isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget)
isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING,
INTR_VBUS_VLD);
dev_info(&isp->client.dev, "B-Peripheral sessions ok\n");
dump_regs(isp, __FUNCTION__);
dump_regs(isp, __func__);
/* If this has a Mini-AB connector, this mode is highly
* nonstandard ... but can be handy for testing, so long
@ -1416,7 +1416,7 @@ isp1301_start_srp(struct otg_transceiver *dev)
pr_debug("otg: SRP, %s ... %06x\n", state_name(isp), OTG_CTRL_REG);
#ifdef CONFIG_USB_OTG
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
#endif
return 0;
}
@ -1463,7 +1463,7 @@ isp1301_start_hnp(struct otg_transceiver *dev)
}
pr_debug("otg: HNP %s, %06x ...\n",
state_name(isp), OTG_CTRL_REG);
check_state(isp, __FUNCTION__);
check_state(isp, __func__);
return 0;
#else
/* srp-only */
@ -1601,7 +1601,7 @@ fail2:
update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS));
#endif
dump_regs(isp, __FUNCTION__);
dump_regs(isp, __func__);
#ifdef VERBOSE
mod_timer(&isp->timer, jiffies + TIMER_JIFFIES);

View File

@ -1506,7 +1506,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
read_write = I2C_SMBUS_READ;
if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
dev_err(&adapter->dev, "%s called with invalid "
"block proc call size (%d)\n", __FUNCTION__,
"block proc call size (%d)\n", __func__,
data->block[0]);
return -1;
}

View File

@ -200,16 +200,176 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
}
static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client,
unsigned long arg)
{
struct i2c_rdwr_ioctl_data rdwr_arg;
struct i2c_msg *rdwr_pa;
u8 __user **data_ptrs;
int i, res;
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
rdwr_pa = (struct i2c_msg *)
kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
GFP_KERNEL);
if (!rdwr_pa)
return -ENOMEM;
if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
kfree(rdwr_pa);
return -EFAULT;
}
data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(rdwr_pa);
return -ENOMEM;
}
res = 0;
for (i = 0; i < rdwr_arg.nmsgs; i++) {
/* Limit the size of the message to a sane amount;
* and don't let length change either. */
if ((rdwr_pa[i].len > 8192) ||
(rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
res = -EINVAL;
break;
}
data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
if (rdwr_pa[i].buf == NULL) {
res = -ENOMEM;
break;
}
if (copy_from_user(rdwr_pa[i].buf, data_ptrs[i],
rdwr_pa[i].len)) {
++i; /* Needs to be kfreed too */
res = -EFAULT;
break;
}
}
if (res < 0) {
int j;
for (j = 0; j < i; ++j)
kfree(rdwr_pa[j].buf);
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
}
res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs);
while (i-- > 0) {
if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) {
if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf,
rdwr_pa[i].len))
res = -EFAULT;
}
kfree(rdwr_pa[i].buf);
}
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
}
static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
unsigned long arg)
{
struct i2c_smbus_ioctl_data data_arg;
union i2c_smbus_data temp;
int datasize, res;
if (copy_from_user(&data_arg,
(struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
(data_arg.size != I2C_SMBUS_QUICK) &&
(data_arg.size != I2C_SMBUS_BYTE_DATA) &&
(data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
dev_dbg(&client->adapter->dev,
"size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size);
return -EINVAL;
}
/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
so the check is valid if size==I2C_SMBUS_QUICK too. */
if ((data_arg.read_write != I2C_SMBUS_READ) &&
(data_arg.read_write != I2C_SMBUS_WRITE)) {
dev_dbg(&client->adapter->dev,
"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.read_write);
return -EINVAL;
}
/* Note that command values are always valid! */
if ((data_arg.size == I2C_SMBUS_QUICK) ||
((data_arg.size == I2C_SMBUS_BYTE) &&
(data_arg.read_write == I2C_SMBUS_WRITE)))
/* These are special: we do not use data */
return i2c_smbus_xfer(client->adapter, client->addr,
client->flags, data_arg.read_write,
data_arg.command, data_arg.size, NULL);
if (data_arg.data == NULL) {
dev_dbg(&client->adapter->dev,
"data is NULL pointer in ioctl I2C_SMBUS.\n");
return -EINVAL;
}
if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
(data_arg.size == I2C_SMBUS_BYTE))
datasize = sizeof(data_arg.data->byte);
else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
(data_arg.size == I2C_SMBUS_PROC_CALL))
datasize = sizeof(data_arg.data->word);
else /* size == smbus block, i2c block, or block proc. call */
datasize = sizeof(data_arg.data->block);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
}
if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
/* Convert old I2C block commands to the new
convention. This preserves binary compatibility. */
data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
if (data_arg.read_write == I2C_SMBUS_READ)
temp.block[0] = I2C_SMBUS_BLOCK_MAX;
}
res = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
data_arg.read_write, data_arg.command, data_arg.size, &temp);
if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT;
}
return res;
}
static int i2cdev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = (struct i2c_client *)file->private_data;
struct i2c_rdwr_ioctl_data rdwr_arg;
struct i2c_smbus_ioctl_data data_arg;
union i2c_smbus_data temp;
struct i2c_msg *rdwr_pa;
u8 __user **data_ptrs;
int i,datasize,res;
unsigned long funcs;
dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
@ -253,164 +413,11 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR:
if (copy_from_user(&rdwr_arg,
(struct i2c_rdwr_ioctl_data __user *)arg,
sizeof(rdwr_arg)))
return -EFAULT;
/* Put an arbitrary limit on the number of messages that can
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
rdwr_pa = (struct i2c_msg *)
kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg),
GFP_KERNEL);
if (rdwr_pa == NULL) return -ENOMEM;
if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
kfree(rdwr_pa);
return -EFAULT;
}
data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(rdwr_pa);
return -ENOMEM;
}
res = 0;
for( i=0; i<rdwr_arg.nmsgs; i++ ) {
/* Limit the size of the message to a sane amount;
* and don't let length change either. */
if ((rdwr_pa[i].len > 8192) ||
(rdwr_pa[i].flags & I2C_M_RECV_LEN)) {
res = -EINVAL;
break;
}
data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf;
rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
if(rdwr_pa[i].buf == NULL) {
res = -ENOMEM;
break;
}
if(copy_from_user(rdwr_pa[i].buf,
data_ptrs[i],
rdwr_pa[i].len)) {
++i; /* Needs to be kfreed too */
res = -EFAULT;
break;
}
}
if (res < 0) {
int j;
for (j = 0; j < i; ++j)
kfree(rdwr_pa[j].buf);
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
}
res = i2c_transfer(client->adapter,
rdwr_pa,
rdwr_arg.nmsgs);
while(i-- > 0) {
if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD)) {
if(copy_to_user(
data_ptrs[i],
rdwr_pa[i].buf,
rdwr_pa[i].len)) {
res = -EFAULT;
}
}
kfree(rdwr_pa[i].buf);
}
kfree(data_ptrs);
kfree(rdwr_pa);
return res;
return i2cdev_ioctl_rdrw(client, arg);
case I2C_SMBUS:
if (copy_from_user(&data_arg,
(struct i2c_smbus_ioctl_data __user *) arg,
sizeof(struct i2c_smbus_ioctl_data)))
return -EFAULT;
if ((data_arg.size != I2C_SMBUS_BYTE) &&
(data_arg.size != I2C_SMBUS_QUICK) &&
(data_arg.size != I2C_SMBUS_BYTE_DATA) &&
(data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
dev_dbg(&client->adapter->dev,
"size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size);
return -EINVAL;
}
/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
so the check is valid if size==I2C_SMBUS_QUICK too. */
if ((data_arg.read_write != I2C_SMBUS_READ) &&
(data_arg.read_write != I2C_SMBUS_WRITE)) {
dev_dbg(&client->adapter->dev,
"read_write out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.read_write);
return -EINVAL;
}
return i2cdev_ioctl_smbus(client, arg);
/* Note that command values are always valid! */
if ((data_arg.size == I2C_SMBUS_QUICK) ||
((data_arg.size == I2C_SMBUS_BYTE) &&
(data_arg.read_write == I2C_SMBUS_WRITE)))
/* These are special: we do not use data */
return i2c_smbus_xfer(client->adapter, client->addr,
client->flags,
data_arg.read_write,
data_arg.command,
data_arg.size, NULL);
if (data_arg.data == NULL) {
dev_dbg(&client->adapter->dev,
"data is NULL pointer in ioctl I2C_SMBUS.\n");
return -EINVAL;
}
if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
(data_arg.size == I2C_SMBUS_BYTE))
datasize = sizeof(data_arg.data->byte);
else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
(data_arg.size == I2C_SMBUS_PROC_CALL))
datasize = sizeof(data_arg.data->word);
else /* size == smbus block, i2c block, or block proc. call */
datasize = sizeof(data_arg.data->block);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
}
if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) {
/* Convert old I2C block commands to the new
convention. This preserves binary compatibility. */
data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA;
if (data_arg.read_write == I2C_SMBUS_READ)
temp.block[0] = I2C_SMBUS_BLOCK_MAX;
}
res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT;
}
return res;
case I2C_RETRIES:
client->adapter->retries = arg;
break;

View File

@ -0,0 +1,22 @@
/*
* MMIO/IRQ and platform data for SH7760 I2C channels
*/
#ifndef _I2C_SH7760_H_
#define _I2C_SH7760_H_
#define SH7760_I2C_DEVNAME "sh7760-i2c"
#define SH7760_I2C0_MMIO 0xFE140000
#define SH7760_I2C0_MMIOEND 0xFE14003B
#define SH7760_I2C0_IRQ 62
#define SH7760_I2C1_MMIO 0xFE150000
#define SH7760_I2C1_MMIOEND 0xFE15003B
#define SH7760_I2C1_IRQ 63
struct sh7760_i2c_platdata {
unsigned int speed_khz;
};
#endif

View File

@ -1,14 +1,41 @@
#ifndef _LINUX_I2C_ALGO_PCA_H
#define _LINUX_I2C_ALGO_PCA_H
/* Clock speeds for the bus */
#define I2C_PCA_CON_330kHz 0x00
#define I2C_PCA_CON_288kHz 0x01
#define I2C_PCA_CON_217kHz 0x02
#define I2C_PCA_CON_146kHz 0x03
#define I2C_PCA_CON_88kHz 0x04
#define I2C_PCA_CON_59kHz 0x05
#define I2C_PCA_CON_44kHz 0x06
#define I2C_PCA_CON_36kHz 0x07
/* PCA9564 registers */
#define I2C_PCA_STA 0x00 /* STATUS Read Only */
#define I2C_PCA_TO 0x00 /* TIMEOUT Write Only */
#define I2C_PCA_DAT 0x01 /* DATA Read/Write */
#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
#define I2C_PCA_CON_STA 0x20 /* Start */
#define I2C_PCA_CON_STO 0x10 /* Stop */
#define I2C_PCA_CON_SI 0x08 /* Serial Interrupt */
#define I2C_PCA_CON_CR 0x07 /* Clock Rate (MASK) */
struct i2c_algo_pca_data {
int (*get_own) (struct i2c_algo_pca_data *adap); /* Obtain own address */
int (*get_clock) (struct i2c_algo_pca_data *adap);
void (*write_byte) (struct i2c_algo_pca_data *adap, int reg, int val);
int (*read_byte) (struct i2c_algo_pca_data *adap, int reg);
int (*wait_for_interrupt) (struct i2c_algo_pca_data *adap);
void *data; /* private low level data */
void (*write_byte) (void *data, int reg, int val);
int (*read_byte) (void *data, int reg);
int (*wait_for_completion) (void *data);
void (*reset_chip) (void *data);
/* i2c_clock values are defined in linux/i2c-algo-pca.h */
unsigned int i2c_clock;
};
int i2c_pca_add_bus(struct i2c_adapter *);
int i2c_pca_add_numbered_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_PCA_H */

View File

@ -0,0 +1,12 @@
#ifndef I2C_PCA9564_PLATFORM_H
#define I2C_PCA9564_PLATFORM_H
struct i2c_pca9564_pf_platform_data {
int gpio; /* pin to reset chip. driver will work when
* not supplied (negative value), but it
* cannot exit some error conditions then */
int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */
int timeout; /* timeout = this value * 10us */
};
#endif /* I2C_PCA9564_PLATFORM_H */