Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux

Pull i2c-embedded changes from Wolfram Sang:
 - CBUS driver (an I2C variant)
 - continued rework of the omap driver
 - s3c2410 gets lots of fixes and gains pinctrl support
 - at91 gains DMA support
 - the GPIO muxer gains devicetree probing
 - typical fixes and additions all over

* 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux: (45 commits)
  i2c: omap: Remove the OMAP_I2C_FLAG_RESET_REGS_POSTIDLE flag
  i2c: at91: add dma support
  i2c: at91: change struct members indentation
  i2c: at91: fix compilation warning
  i2c: mxs: Do not disable the I2C SMBus quick mode
  i2c: mxs: Handle i2c DMA failure properly
  i2c: s3c2410: Remove recently introduced performance overheads
  i2c: ocores: Move grlib set/get functions into #ifdef CONFIG_OF block
  i2c: s3c2410: Add fix for i2c suspend/resume
  i2c: s3c2410: Fix code to free gpios
  i2c: i2c-cbus-gpio: introduce driver
  i2c: ocores: Add support for the GRLIB port of the controller and use function pointers for getreg and setreg functions
  i2c: ocores: Add irq support for sparc
  i2c: omap: Move the remove constraint
  ARM: dts: cfa10049: Add the i2c muxer buses to the CFA-10049
  i2c: s3c2410: do not special case HDMIPHY stuck bus detection
  i2c: s3c2410: use exponential back off while polling for bus idle
  i2c: s3c2410: do not generate STOP for QUIRK_HDMIPHY
  i2c: s3c2410: grab adapter lock while changing i2c clock
  i2c: s3c2410: Add support for pinctrl
  ...
This commit is contained in:
Linus Torvalds 2012-12-18 16:51:10 -08:00
commit 752451f01c
27 changed files with 1483 additions and 362 deletions

View File

@ -0,0 +1,27 @@
Device tree bindings for i2c-cbus-gpio driver
Required properties:
- compatible = "i2c-cbus-gpio";
- gpios: clk, dat, sel
- #address-cells = <1>;
- #size-cells = <0>;
Optional properties:
- child nodes conforming to i2c bus binding
Example:
i2c@0 {
compatible = "i2c-cbus-gpio";
gpios = <&gpio 66 0 /* clk */
&gpio 65 0 /* dat */
&gpio 64 0 /* sel */
>;
#address-cells = <1>;
#size-cells = <0>;
retu-mfd: retu@1 {
compatible = "retu-mfd";
reg = <0x1>;
};
};

View File

@ -0,0 +1,81 @@
GPIO-based I2C Bus Mux
This binding describes an I2C bus multiplexer that uses GPIOs to
route the I2C signals.
+-----+ +-----+
| dev | | dev |
+------------+ +-----+ +-----+
| SoC | | |
| | /--------+--------+
| +------+ | +------+ child bus A, on GPIO value set to 0
| | I2C |-|--| Mux |
| +------+ | +--+---+ child bus B, on GPIO value set to 1
| | | \----------+--------+--------+
| +------+ | | | | |
| | GPIO |-|-----+ +-----+ +-----+ +-----+
| +------+ | | dev | | dev | | dev |
+------------+ +-----+ +-----+ +-----+
Required properties:
- compatible: i2c-mux-gpio
- i2c-parent: The phandle of the I2C bus that this multiplexer's master-side
port is connected to.
- mux-gpios: list of gpios used to control the muxer
* Standard I2C mux properties. See mux.txt in this directory.
* I2C child bus nodes. See mux.txt in this directory.
Optional properties:
- idle-state: value to set the muxer to when idle. When no value is
given, it defaults to the last value used.
For each i2c child node, an I2C child bus will be created. They will
be numbered based on their order in the device tree.
Whenever an access is made to a device on a child bus, the value set
in the revelant node's reg property will be output using the list of
GPIOs, the first in the list holding the least-significant value.
If an idle state is defined, using the idle-state (optional) property,
whenever an access is not being made to a device on a child bus, the
GPIOs will be set according to the idle value.
If an idle state is not defined, the most recently used value will be
left programmed into hardware whenever no access is being made to a
device on a child bus.
Example:
i2cmux {
compatible = "i2c-mux-gpio";
#address-cells = <1>;
#size-cells = <0>;
mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
i2c-parent = <&i2c1>;
i2c@1 {
reg = <1>;
#address-cells = <1>;
#size-cells = <0>;
ssd1307: oled@3c {
compatible = "solomon,ssd1307fb-i2c";
reg = <0x3c>;
pwms = <&pwm 4 3000>;
reset-gpios = <&gpio2 7 1>;
reset-active-low;
};
};
i2c@3 {
reg = <3>;
#address-cells = <1>;
#size-cells = <0>;
pca9555: pca9555@20 {
compatible = "nxp,pca9555";
gpio-controller;
#gpio-cells = <2>;
reg = <0x20>;
};
};
};

View File

@ -1,7 +1,7 @@
Device tree configuration for i2c-ocores Device tree configuration for i2c-ocores
Required properties: Required properties:
- compatible : "opencores,i2c-ocores" - compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst"
- reg : bus address start and address range size of device - reg : bus address start and address range size of device
- interrupts : interrupt number - interrupts : interrupt number
- clock-frequency : frequency of bus clock in Hz - clock-frequency : frequency of bus clock in Hz

View File

@ -13,11 +13,17 @@ Required properties:
- interrupts: interrupt number to the cpu. - interrupts: interrupt number to the cpu.
- samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. - samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
Required for all cases except "samsung,s3c2440-hdmiphy-i2c":
- Samsung GPIO variant (deprecated):
- gpios: The order of the gpios should be the following: <SDA, SCL>.
The gpio specifier depends on the gpio controller. Required in all
cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
lines are permanently wired to the respective clienta
- Pinctrl variant (preferred, if available):
- pinctrl-0: Pin control group to be used for this controller.
- pinctrl-names: Should contain only one value - "default".
Optional properties: Optional properties:
- gpios: The order of the gpios should be the following: <SDA, SCL>.
The gpio specifier depends on the gpio controller. Required in all
cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
lines are permanently wired to the respective client
- samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
specified, default value is 0. specified, default value is 0.
- samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not - samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
@ -31,8 +37,14 @@ Example:
interrupts = <345>; interrupts = <345>;
samsung,i2c-sda-delay = <100>; samsung,i2c-sda-delay = <100>;
samsung,i2c-max-bus-freq = <100000>; samsung,i2c-max-bus-freq = <100000>;
/* Samsung GPIO variant begins here */
gpios = <&gpd1 2 0 /* SDA */ gpios = <&gpd1 2 0 /* SDA */
&gpd1 3 0 /* SCL */>; &gpd1 3 0 /* SCL */>;
/* Samsung GPIO variant ends here */
/* Pinctrl variant begins here */
pinctrl-0 = <&i2c3_bus>;
pinctrl-names = "default";
/* Pinctrl variant ends here */
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;

View File

@ -92,6 +92,30 @@
status = "okay"; status = "okay";
}; };
i2cmux {
compatible = "i2c-mux-gpio";
#address-cells = <1>;
#size-cells = <0>;
mux-gpios = <&gpio1 22 0 &gpio1 23 0>;
i2c-parent = <&i2c1>;
i2c@0 {
reg = <0>;
};
i2c@1 {
reg = <1>;
};
i2c@2 {
reg = <2>;
};
i2c@3 {
reg = <3>;
};
};
usbphy1: usbphy@8007e000 { usbphy1: usbphy@8007e000 {
status = "okay"; status = "okay";
}; };

View File

@ -16,10 +16,12 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/usb/musb.h> #include <linux/usb/musb.h>
#include <linux/platform_data/i2c-cbus-gpio.h>
#include <linux/platform_data/spi-omap2-mcspi.h> #include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/mtd-onenand-omap2.h> #include <linux/platform_data/mtd-onenand-omap2.h>
#include <linux/mfd/menelaus.h> #include <linux/mfd/menelaus.h>
@ -40,6 +42,45 @@
#define TUSB6010_GPIO_ENABLE 0 #define TUSB6010_GPIO_ENABLE 0
#define TUSB6010_DMACHAN 0x3f #define TUSB6010_DMACHAN 0x3f
#if defined(CONFIG_I2C_CBUS_GPIO) || defined(CONFIG_I2C_CBUS_GPIO_MODULE)
static struct i2c_cbus_platform_data n8x0_cbus_data = {
.clk_gpio = 66,
.dat_gpio = 65,
.sel_gpio = 64,
};
static struct platform_device n8x0_cbus_device = {
.name = "i2c-cbus-gpio",
.id = 3,
.dev = {
.platform_data = &n8x0_cbus_data,
},
};
static struct i2c_board_info n8x0_i2c_board_info_3[] __initdata = {
{
I2C_BOARD_INFO("retu-mfd", 0x01),
},
};
static void __init n8x0_cbus_init(void)
{
const int retu_irq_gpio = 108;
if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ"))
return;
irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING);
n8x0_i2c_board_info_3[0].irq = gpio_to_irq(retu_irq_gpio);
i2c_register_board_info(3, n8x0_i2c_board_info_3,
ARRAY_SIZE(n8x0_i2c_board_info_3));
platform_device_register(&n8x0_cbus_device);
}
#else /* CONFIG_I2C_CBUS_GPIO */
static void __init n8x0_cbus_init(void)
{
}
#endif /* CONFIG_I2C_CBUS_GPIO */
#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) #if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
/* /*
* Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@ -678,6 +719,7 @@ static void __init n8x0_init_machine(void)
gpmc_onenand_init(board_onenand_data); gpmc_onenand_init(board_onenand_data);
n8x0_mmc_init(); n8x0_mmc_init();
n8x0_usb_init(); n8x0_usb_init();
n8x0_cbus_init();
} }
MACHINE_START(NOKIA_N800, "Nokia N800") MACHINE_START(NOKIA_N800, "Nokia N800")

View File

@ -120,6 +120,16 @@ static int __init omap_i2c_nr_ports(void)
return ports; return ports;
} }
/*
* XXX This function is a temporary compatibility wrapper - only
* needed until the I2C driver can be converted to call
* omap_pm_set_max_dev_wakeup_lat() and handle a return code.
*/
static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
{
omap_pm_set_max_mpu_wakeup_lat(dev, t);
}
static const char name[] = "omap_i2c"; static const char name[] = "omap_i2c";
int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata, int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
@ -157,6 +167,15 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
pdata->flags = dev_attr->flags; pdata->flags = dev_attr->flags;
/*
* When waiting for completion of a i2c transfer, we need to
* set a wake up latency constraint for the MPU. This is to
* ensure quick enough wakeup from idle, when transfer
* completes.
* Only omap3 has support for constraints
*/
if (cpu_is_omap34xx())
pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
pdev = omap_device_build(name, bus_id, oh, pdata, pdev = omap_device_build(name, bus_id, oh, pdata,
sizeof(struct omap_i2c_bus_platform_data), sizeof(struct omap_i2c_bus_platform_data),
NULL, 0, 0); NULL, 0, 0);

View File

@ -77,8 +77,7 @@ static struct omap_hwmod_class i2c_class = {
static struct omap_i2c_dev_attr i2c_dev_attr = { static struct omap_i2c_dev_attr i2c_dev_attr = {
.fifo_depth = 8, /* bytes */ .fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | .flags = OMAP_I2C_FLAG_BUS_SHIFT_2 |
OMAP_I2C_FLAG_BUS_SHIFT_2 |
OMAP_I2C_FLAG_FORCE_19200_INT_CLK, OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
}; };

View File

@ -1118,8 +1118,7 @@ static struct omap_hwmod_class i2c_class = {
}; };
static struct omap_i2c_dev_attr i2c_dev_attr = { static struct omap_i2c_dev_attr i2c_dev_attr = {
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE | .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
}; };
/* i2c1 */ /* i2c1 */

View File

@ -794,9 +794,7 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
/* I2C1 */ /* I2C1 */
static struct omap_i2c_dev_attr i2c1_dev_attr = { static struct omap_i2c_dev_attr i2c1_dev_attr = {
.fifo_depth = 8, /* bytes */ .fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
}; };
static struct omap_hwmod omap3xxx_i2c1_hwmod = { static struct omap_hwmod omap3xxx_i2c1_hwmod = {
@ -821,9 +819,7 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
/* I2C2 */ /* I2C2 */
static struct omap_i2c_dev_attr i2c2_dev_attr = { static struct omap_i2c_dev_attr i2c2_dev_attr = {
.fifo_depth = 8, /* bytes */ .fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
}; };
static struct omap_hwmod omap3xxx_i2c2_hwmod = { static struct omap_hwmod omap3xxx_i2c2_hwmod = {
@ -848,9 +844,7 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
/* I2C3 */ /* I2C3 */
static struct omap_i2c_dev_attr i2c3_dev_attr = { static struct omap_i2c_dev_attr i2c3_dev_attr = {
.fifo_depth = 64, /* bytes */ .fifo_depth = 64, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
}; };
static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = { static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {

View File

@ -1529,8 +1529,7 @@ static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
}; };
static struct omap_i2c_dev_attr i2c_dev_attr = { static struct omap_i2c_dev_attr i2c_dev_attr = {
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE | .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
}; };
/* i2c1 */ /* i2c1 */

View File

@ -337,6 +337,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
help help
The unit of the TWI clock is kHz. The unit of the TWI clock is kHz.
config I2C_CBUS_GPIO
tristate "CBUS I2C driver"
depends on GENERIC_GPIO
help
Support for CBUS access using I2C API. Mostly relevant for Nokia
Internet Tablets (770, N800 and N810).
This driver can also be built as a module. If so, the module
will be called i2c-cbus-gpio.
config I2C_CPM config I2C_CPM
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
depends on (CPM1 || CPM2) && OF_I2C depends on (CPM1 || CPM2) && OF_I2C

View File

@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o

View File

@ -19,6 +19,8 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
@ -29,9 +31,11 @@
#include <linux/of_i2c.h> #include <linux/of_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/platform_data/dma-atmel.h>
#define TWI_CLK_HZ 100000 /* max 400 Kbits/s */ #define TWI_CLK_HZ 100000 /* max 400 Kbits/s */
#define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */ #define AT91_I2C_TIMEOUT msecs_to_jiffies(100) /* transfer timeout */
#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */
/* AT91 TWI register definitions */ /* AT91 TWI register definitions */
#define AT91_TWI_CR 0x0000 /* Control Register */ #define AT91_TWI_CR 0x0000 /* Control Register */
@ -66,24 +70,39 @@
#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */ #define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
struct at91_twi_pdata { struct at91_twi_pdata {
unsigned clk_max_div; unsigned clk_max_div;
unsigned clk_offset; unsigned clk_offset;
bool has_unre_flag; bool has_unre_flag;
bool has_dma_support;
struct at_dma_slave dma_slave;
};
struct at91_twi_dma {
struct dma_chan *chan_rx;
struct dma_chan *chan_tx;
struct scatterlist sg;
struct dma_async_tx_descriptor *data_desc;
enum dma_data_direction direction;
bool buf_mapped;
bool xfer_in_progress;
}; };
struct at91_twi_dev { struct at91_twi_dev {
struct device *dev; struct device *dev;
void __iomem *base; void __iomem *base;
struct completion cmd_complete; struct completion cmd_complete;
struct clk *clk; struct clk *clk;
u8 *buf; u8 *buf;
size_t buf_len; size_t buf_len;
struct i2c_msg *msg; struct i2c_msg *msg;
int irq; int irq;
unsigned transfer_status; unsigned imr;
struct i2c_adapter adapter; unsigned transfer_status;
unsigned twi_cwgr_reg; struct i2c_adapter adapter;
struct at91_twi_pdata *pdata; unsigned twi_cwgr_reg;
struct at91_twi_pdata *pdata;
bool use_dma;
struct at91_twi_dma dma;
}; };
static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
@ -102,6 +121,17 @@ static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
} }
static void at91_twi_irq_save(struct at91_twi_dev *dev)
{
dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & 0x7;
at91_disable_twi_interrupts(dev);
}
static void at91_twi_irq_restore(struct at91_twi_dev *dev)
{
at91_twi_write(dev, AT91_TWI_IER, dev->imr);
}
static void at91_init_twi_bus(struct at91_twi_dev *dev) static void at91_init_twi_bus(struct at91_twi_dev *dev)
{ {
at91_disable_twi_interrupts(dev); at91_disable_twi_interrupts(dev);
@ -138,6 +168,28 @@ static void __devinit at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv); dev_dbg(dev->dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
} }
static void at91_twi_dma_cleanup(struct at91_twi_dev *dev)
{
struct at91_twi_dma *dma = &dev->dma;
at91_twi_irq_save(dev);
if (dma->xfer_in_progress) {
if (dma->direction == DMA_FROM_DEVICE)
dmaengine_terminate_all(dma->chan_rx);
else
dmaengine_terminate_all(dma->chan_tx);
dma->xfer_in_progress = false;
}
if (dma->buf_mapped) {
dma_unmap_single(dev->dev, sg_dma_address(&dma->sg),
dev->buf_len, dma->direction);
dma->buf_mapped = false;
}
at91_twi_irq_restore(dev);
}
static void at91_twi_write_next_byte(struct at91_twi_dev *dev) static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
{ {
if (dev->buf_len <= 0) if (dev->buf_len <= 0)
@ -154,6 +206,60 @@ static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
++dev->buf; ++dev->buf;
} }
static void at91_twi_write_data_dma_callback(void *data)
{
struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
dev->buf_len, DMA_MEM_TO_DEV);
at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
}
static void at91_twi_write_data_dma(struct at91_twi_dev *dev)
{
dma_addr_t dma_addr;
struct dma_async_tx_descriptor *txdesc;
struct at91_twi_dma *dma = &dev->dma;
struct dma_chan *chan_tx = dma->chan_tx;
if (dev->buf_len <= 0)
return;
dma->direction = DMA_TO_DEVICE;
at91_twi_irq_save(dev);
dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len,
DMA_TO_DEVICE);
if (dma_mapping_error(dev->dev, dma_addr)) {
dev_err(dev->dev, "dma map failed\n");
return;
}
dma->buf_mapped = true;
at91_twi_irq_restore(dev);
sg_dma_len(&dma->sg) = dev->buf_len;
sg_dma_address(&dma->sg) = dma_addr;
txdesc = dmaengine_prep_slave_sg(chan_tx, &dma->sg, 1, DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!txdesc) {
dev_err(dev->dev, "dma prep slave sg failed\n");
goto error;
}
txdesc->callback = at91_twi_write_data_dma_callback;
txdesc->callback_param = dev;
dma->xfer_in_progress = true;
dmaengine_submit(txdesc);
dma_async_issue_pending(chan_tx);
return;
error:
at91_twi_dma_cleanup(dev);
}
static void at91_twi_read_next_byte(struct at91_twi_dev *dev) static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
{ {
if (dev->buf_len <= 0) if (dev->buf_len <= 0)
@ -179,6 +285,61 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
++dev->buf; ++dev->buf;
} }
static void at91_twi_read_data_dma_callback(void *data)
{
struct at91_twi_dev *dev = (struct at91_twi_dev *)data;
dma_unmap_single(dev->dev, sg_dma_address(&dev->dma.sg),
dev->buf_len, DMA_DEV_TO_MEM);
/* The last two bytes have to be read without using dma */
dev->buf += dev->buf_len - 2;
dev->buf_len = 2;
at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_RXRDY);
}
static void at91_twi_read_data_dma(struct at91_twi_dev *dev)
{
dma_addr_t dma_addr;
struct dma_async_tx_descriptor *rxdesc;
struct at91_twi_dma *dma = &dev->dma;
struct dma_chan *chan_rx = dma->chan_rx;
dma->direction = DMA_FROM_DEVICE;
/* Keep in mind that we won't use dma to read the last two bytes */
at91_twi_irq_save(dev);
dma_addr = dma_map_single(dev->dev, dev->buf, dev->buf_len - 2,
DMA_FROM_DEVICE);
if (dma_mapping_error(dev->dev, dma_addr)) {
dev_err(dev->dev, "dma map failed\n");
return;
}
dma->buf_mapped = true;
at91_twi_irq_restore(dev);
dma->sg.dma_address = dma_addr;
sg_dma_len(&dma->sg) = dev->buf_len - 2;
rxdesc = dmaengine_prep_slave_sg(chan_rx, &dma->sg, 1, DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!rxdesc) {
dev_err(dev->dev, "dma prep slave sg failed\n");
goto error;
}
rxdesc->callback = at91_twi_read_data_dma_callback;
rxdesc->callback_param = dev;
dma->xfer_in_progress = true;
dmaengine_submit(rxdesc);
dma_async_issue_pending(dma->chan_rx);
return;
error:
at91_twi_dma_cleanup(dev);
}
static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id) static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
{ {
struct at91_twi_dev *dev = dev_id; struct at91_twi_dev *dev = dev_id;
@ -229,12 +390,36 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN)) if (dev->buf_len <= 1 && !(dev->msg->flags & I2C_M_RECV_LEN))
start_flags |= AT91_TWI_STOP; start_flags |= AT91_TWI_STOP;
at91_twi_write(dev, AT91_TWI_CR, start_flags); at91_twi_write(dev, AT91_TWI_CR, start_flags);
at91_twi_write(dev, AT91_TWI_IER, /*
* When using dma, the last byte has to be read manually in
* order to not send the stop command too late and then
* to receive extra data. In practice, there are some issues
* if you use the dma to read n-1 bytes because of latency.
* Reading n-2 bytes with dma and the two last ones manually
* seems to be the best solution.
*/
if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
at91_twi_read_data_dma(dev);
/*
* It is important to enable TXCOMP irq here because
* doing it only when transferring the last two bytes
* will mask NACK errors since TXCOMP is set when a
* NACK occurs.
*/
at91_twi_write(dev, AT91_TWI_IER,
AT91_TWI_TXCOMP);
} else
at91_twi_write(dev, AT91_TWI_IER,
AT91_TWI_TXCOMP | AT91_TWI_RXRDY); AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
} else { } else {
at91_twi_write_next_byte(dev); if (dev->use_dma && (dev->buf_len > AT91_I2C_DMA_THRESHOLD)) {
at91_twi_write(dev, AT91_TWI_IER, at91_twi_write_data_dma(dev);
AT91_TWI_TXCOMP | AT91_TWI_TXRDY); at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
} else {
at91_twi_write_next_byte(dev);
at91_twi_write(dev, AT91_TWI_IER,
AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
}
} }
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
@ -242,23 +427,31 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
if (ret == 0) { if (ret == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
at91_init_twi_bus(dev); at91_init_twi_bus(dev);
return -ETIMEDOUT; ret = -ETIMEDOUT;
goto error;
} }
if (dev->transfer_status & AT91_TWI_NACK) { if (dev->transfer_status & AT91_TWI_NACK) {
dev_dbg(dev->dev, "received nack\n"); dev_dbg(dev->dev, "received nack\n");
return -EREMOTEIO; ret = -EREMOTEIO;
goto error;
} }
if (dev->transfer_status & AT91_TWI_OVRE) { if (dev->transfer_status & AT91_TWI_OVRE) {
dev_err(dev->dev, "overrun while reading\n"); dev_err(dev->dev, "overrun while reading\n");
return -EIO; ret = -EIO;
goto error;
} }
if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) { if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
dev_err(dev->dev, "underrun while writing\n"); dev_err(dev->dev, "underrun while writing\n");
return -EIO; ret = -EIO;
goto error;
} }
dev_dbg(dev->dev, "transfer complete\n"); dev_dbg(dev->dev, "transfer complete\n");
return 0; return 0;
error:
at91_twi_dma_cleanup(dev);
return ret;
} }
static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
@ -329,36 +522,42 @@ static struct at91_twi_pdata at91rm9200_config = {
.clk_max_div = 5, .clk_max_div = 5,
.clk_offset = 3, .clk_offset = 3,
.has_unre_flag = true, .has_unre_flag = true,
.has_dma_support = false,
}; };
static struct at91_twi_pdata at91sam9261_config = { static struct at91_twi_pdata at91sam9261_config = {
.clk_max_div = 5, .clk_max_div = 5,
.clk_offset = 4, .clk_offset = 4,
.has_unre_flag = false, .has_unre_flag = false,
.has_dma_support = false,
}; };
static struct at91_twi_pdata at91sam9260_config = { static struct at91_twi_pdata at91sam9260_config = {
.clk_max_div = 7, .clk_max_div = 7,
.clk_offset = 4, .clk_offset = 4,
.has_unre_flag = false, .has_unre_flag = false,
.has_dma_support = false,
}; };
static struct at91_twi_pdata at91sam9g20_config = { static struct at91_twi_pdata at91sam9g20_config = {
.clk_max_div = 7, .clk_max_div = 7,
.clk_offset = 4, .clk_offset = 4,
.has_unre_flag = false, .has_unre_flag = false,
.has_dma_support = false,
}; };
static struct at91_twi_pdata at91sam9g10_config = { static struct at91_twi_pdata at91sam9g10_config = {
.clk_max_div = 7, .clk_max_div = 7,
.clk_offset = 4, .clk_offset = 4,
.has_unre_flag = false, .has_unre_flag = false,
.has_dma_support = false,
}; };
static struct at91_twi_pdata at91sam9x5_config = { static struct at91_twi_pdata at91sam9x5_config = {
.clk_max_div = 7, .clk_max_div = 7,
.clk_offset = 4, .clk_offset = 4,
.has_unre_flag = false, .has_unre_flag = false,
.has_dma_support = true,
}; };
static const struct platform_device_id at91_twi_devtypes[] = { static const struct platform_device_id at91_twi_devtypes[] = {
@ -405,6 +604,90 @@ MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
#define atmel_twi_dt_ids NULL #define atmel_twi_dt_ids NULL
#endif #endif
static bool __devinit filter(struct dma_chan *chan, void *slave)
{
struct at_dma_slave *sl = slave;
if (sl->dma_dev == chan->device->dev) {
chan->private = sl;
return true;
} else {
return false;
}
}
static int __devinit at91_twi_configure_dma(struct at91_twi_dev *dev, u32 phy_addr)
{
int ret = 0;
struct at_dma_slave *sdata;
struct dma_slave_config slave_config;
struct at91_twi_dma *dma = &dev->dma;
sdata = &dev->pdata->dma_slave;
memset(&slave_config, 0, sizeof(slave_config));
slave_config.src_addr = (dma_addr_t)phy_addr + AT91_TWI_RHR;
slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.src_maxburst = 1;
slave_config.dst_addr = (dma_addr_t)phy_addr + AT91_TWI_THR;
slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
slave_config.dst_maxburst = 1;
slave_config.device_fc = false;
if (sdata && sdata->dma_dev) {
dma_cap_mask_t mask;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
dma->chan_tx = dma_request_channel(mask, filter, sdata);
if (!dma->chan_tx) {
dev_err(dev->dev, "no DMA channel available for tx\n");
ret = -EBUSY;
goto error;
}
dma->chan_rx = dma_request_channel(mask, filter, sdata);
if (!dma->chan_rx) {
dev_err(dev->dev, "no DMA channel available for rx\n");
ret = -EBUSY;
goto error;
}
} else {
ret = -EINVAL;
goto error;
}
slave_config.direction = DMA_MEM_TO_DEV;
if (dmaengine_slave_config(dma->chan_tx, &slave_config)) {
dev_err(dev->dev, "failed to configure tx channel\n");
ret = -EINVAL;
goto error;
}
slave_config.direction = DMA_DEV_TO_MEM;
if (dmaengine_slave_config(dma->chan_rx, &slave_config)) {
dev_err(dev->dev, "failed to configure rx channel\n");
ret = -EINVAL;
goto error;
}
sg_init_table(&dma->sg, 1);
dma->buf_mapped = false;
dma->xfer_in_progress = false;
dev_info(dev->dev, "using %s (tx) and %s (rx) for DMA transfers\n",
dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
return ret;
error:
dev_info(dev->dev, "can't use DMA\n");
if (dma->chan_rx)
dma_release_channel(dma->chan_rx);
if (dma->chan_tx)
dma_release_channel(dma->chan_tx);
return ret;
}
static struct at91_twi_pdata * __devinit at91_twi_get_driver_data( static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
struct platform_device *pdev) struct platform_device *pdev)
{ {
@ -413,7 +696,7 @@ static struct at91_twi_pdata * __devinit at91_twi_get_driver_data(
match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node); match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
if (!match) if (!match)
return NULL; return NULL;
return match->data; return (struct at91_twi_pdata *)match->data;
} }
return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data; return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
} }
@ -423,6 +706,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
struct at91_twi_dev *dev; struct at91_twi_dev *dev;
struct resource *mem; struct resource *mem;
int rc; int rc;
u32 phy_addr;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev) if (!dev)
@ -433,6 +717,7 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) if (!mem)
return -ENODEV; return -ENODEV;
phy_addr = mem->start;
dev->pdata = at91_twi_get_driver_data(pdev); dev->pdata = at91_twi_get_driver_data(pdev);
if (!dev->pdata) if (!dev->pdata)
@ -462,6 +747,11 @@ static int __devinit at91_twi_probe(struct platform_device *pdev)
} }
clk_prepare_enable(dev->clk); clk_prepare_enable(dev->clk);
if (dev->pdata->has_dma_support) {
if (at91_twi_configure_dma(dev, phy_addr) == 0)
dev->use_dma = true;
}
at91_calc_twi_clock(dev, TWI_CLK_HZ); at91_calc_twi_clock(dev, TWI_CLK_HZ);
at91_init_twi_bus(dev); at91_init_twi_bus(dev);

View File

@ -0,0 +1,300 @@
/*
* CBUS I2C driver for Nokia Internet Tablets.
*
* Copyright (C) 2004-2010 Nokia Corporation
*
* Based on code written by Juha Yrjölä, David Weinehall, Mikko Ylinen and
* Felipe Balbi. Converted to I2C driver by Aaro Koskinen.
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
* archive for more details.
*
* 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.
*/
#include <linux/io.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/platform_data/i2c-cbus-gpio.h>
/*
* Bit counts are derived from Nokia implementation. These should be checked
* if other CBUS implementations appear.
*/
#define CBUS_ADDR_BITS 3
#define CBUS_REG_BITS 5
struct cbus_host {
spinlock_t lock; /* host lock */
struct device *dev;
int clk_gpio;
int dat_gpio;
int sel_gpio;
};
/**
* cbus_send_bit - sends one bit over the bus
* @host: the host we're using
* @bit: one bit of information to send
*/
static void cbus_send_bit(struct cbus_host *host, unsigned bit)
{
gpio_set_value(host->dat_gpio, bit ? 1 : 0);
gpio_set_value(host->clk_gpio, 1);
gpio_set_value(host->clk_gpio, 0);
}
/**
* cbus_send_data - sends @len amount of data over the bus
* @host: the host we're using
* @data: the data to send
* @len: size of the transfer
*/
static void cbus_send_data(struct cbus_host *host, unsigned data, unsigned len)
{
int i;
for (i = len; i > 0; i--)
cbus_send_bit(host, data & (1 << (i - 1)));
}
/**
* cbus_receive_bit - receives one bit from the bus
* @host: the host we're using
*/
static int cbus_receive_bit(struct cbus_host *host)
{
int ret;
gpio_set_value(host->clk_gpio, 1);
ret = gpio_get_value(host->dat_gpio);
gpio_set_value(host->clk_gpio, 0);
return ret;
}
/**
* cbus_receive_word - receives 16-bit word from the bus
* @host: the host we're using
*/
static int cbus_receive_word(struct cbus_host *host)
{
int ret = 0;
int i;
for (i = 16; i > 0; i--) {
int bit = cbus_receive_bit(host);
if (bit < 0)
return bit;
if (bit)
ret |= 1 << (i - 1);
}
return ret;
}
/**
* cbus_transfer - transfers data over the bus
* @host: the host we're using
* @rw: read/write flag
* @dev: device address
* @reg: register address
* @data: if @rw == I2C_SBUS_WRITE data to send otherwise 0
*/
static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,
unsigned reg, unsigned data)
{
unsigned long flags;
int ret;
/* We don't want interrupts disturbing our transfer */
spin_lock_irqsave(&host->lock, flags);
/* Reset state and start of transfer, SEL stays down during transfer */
gpio_set_value(host->sel_gpio, 0);
/* Set the DAT pin to output */
gpio_direction_output(host->dat_gpio, 1);
/* Send the device address */
cbus_send_data(host, dev, CBUS_ADDR_BITS);
/* Send the rw flag */
cbus_send_bit(host, rw == I2C_SMBUS_READ);
/* Send the register address */
cbus_send_data(host, reg, CBUS_REG_BITS);
if (rw == I2C_SMBUS_WRITE) {
cbus_send_data(host, data, 16);
ret = 0;
} else {
ret = gpio_direction_input(host->dat_gpio);
if (ret) {
dev_dbg(host->dev, "failed setting direction\n");
goto out;
}
gpio_set_value(host->clk_gpio, 1);
ret = cbus_receive_word(host);
if (ret < 0) {
dev_dbg(host->dev, "failed receiving data\n");
goto out;
}
}
/* Indicate end of transfer, SEL goes up until next transfer */
gpio_set_value(host->sel_gpio, 1);
gpio_set_value(host->clk_gpio, 1);
gpio_set_value(host->clk_gpio, 0);
out:
spin_unlock_irqrestore(&host->lock, flags);
return ret;
}
static int cbus_i2c_smbus_xfer(struct i2c_adapter *adapter,
u16 addr,
unsigned short flags,
char read_write,
u8 command,
int size,
union i2c_smbus_data *data)
{
struct cbus_host *chost = i2c_get_adapdata(adapter);
int ret;
if (size != I2C_SMBUS_WORD_DATA)
return -EINVAL;
ret = cbus_transfer(chost, read_write == I2C_SMBUS_READ, addr,
command, data->word);
if (ret < 0)
return ret;
if (read_write == I2C_SMBUS_READ)
data->word = ret;
return 0;
}
static u32 cbus_i2c_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
}
static const struct i2c_algorithm cbus_i2c_algo = {
.smbus_xfer = cbus_i2c_smbus_xfer,
.functionality = cbus_i2c_func,
};
static int cbus_i2c_remove(struct platform_device *pdev)
{
struct i2c_adapter *adapter = platform_get_drvdata(pdev);
return i2c_del_adapter(adapter);
}
static int cbus_i2c_probe(struct platform_device *pdev)
{
struct i2c_adapter *adapter;
struct cbus_host *chost;
int ret;
adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),
GFP_KERNEL);
if (!adapter)
return -ENOMEM;
chost = devm_kzalloc(&pdev->dev, sizeof(*chost), GFP_KERNEL);
if (!chost)
return -ENOMEM;
if (pdev->dev.of_node) {
struct device_node *dnode = pdev->dev.of_node;
if (of_gpio_count(dnode) != 3)
return -ENODEV;
chost->clk_gpio = of_get_gpio(dnode, 0);
chost->dat_gpio = of_get_gpio(dnode, 1);
chost->sel_gpio = of_get_gpio(dnode, 2);
} else if (pdev->dev.platform_data) {
struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data;
chost->clk_gpio = pdata->clk_gpio;
chost->dat_gpio = pdata->dat_gpio;
chost->sel_gpio = pdata->sel_gpio;
} else {
return -ENODEV;
}
adapter->owner = THIS_MODULE;
adapter->class = I2C_CLASS_HWMON;
adapter->dev.parent = &pdev->dev;
adapter->nr = pdev->id;
adapter->timeout = HZ;
adapter->algo = &cbus_i2c_algo;
strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name));
spin_lock_init(&chost->lock);
chost->dev = &pdev->dev;
ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio,
GPIOF_OUT_INIT_LOW, "CBUS clk");
if (ret)
return ret;
ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN,
"CBUS data");
if (ret)
return ret;
ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio,
GPIOF_OUT_INIT_HIGH, "CBUS sel");
if (ret)
return ret;
i2c_set_adapdata(adapter, chost);
platform_set_drvdata(pdev, adapter);
return i2c_add_numbered_adapter(adapter);
}
#if defined(CONFIG_OF)
static const struct of_device_id i2c_cbus_dt_ids[] = {
{ .compatible = "i2c-cbus-gpio", },
{ }
};
MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids);
#endif
static struct platform_driver cbus_i2c_driver = {
.probe = cbus_i2c_probe,
.remove = cbus_i2c_remove,
.driver = {
.owner = THIS_MODULE,
.name = "i2c-cbus-gpio",
},
};
module_platform_driver(cbus_i2c_driver);
MODULE_ALIAS("platform:i2c-cbus-gpio");
MODULE_DESCRIPTION("CBUS I2C driver");
MODULE_AUTHOR("Juha Yrjölä");
MODULE_AUTHOR("David Weinehall");
MODULE_AUTHOR("Mikko Ylinen");
MODULE_AUTHOR("Felipe Balbi");
MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
MODULE_LICENSE("GPL");

View File

@ -184,7 +184,11 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
bit_data->data = pdata; bit_data->data = pdata;
adap->owner = THIS_MODULE; adap->owner = THIS_MODULE;
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); if (pdev->dev.of_node)
strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name));
else
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
adap->algo_data = bit_data; adap->algo_data = bit_data;
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;

View File

@ -359,7 +359,7 @@ static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
static u32 mxs_i2c_func(struct i2c_adapter *adap) static u32 mxs_i2c_func(struct i2c_adapter *adap)
{ {
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
} }
static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)

View File

@ -435,13 +435,6 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
timeout = wait_for_completion_timeout( timeout = wait_for_completion_timeout(
&dev->xfer_complete, dev->adap.timeout); &dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) {
dev_err(&dev->adev->dev,
"wait_for_completion_timeout "
"returned %d waiting for event\n", timeout);
status = timeout;
}
if (timeout == 0) { if (timeout == 0) {
/* Controller timed out */ /* Controller timed out */
dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n", dev_err(&dev->adev->dev, "read from slave 0x%x timed out\n",
@ -523,13 +516,6 @@ static int write_i2c(struct nmk_i2c_dev *dev, u16 flags)
timeout = wait_for_completion_timeout( timeout = wait_for_completion_timeout(
&dev->xfer_complete, dev->adap.timeout); &dev->xfer_complete, dev->adap.timeout);
if (timeout < 0) {
dev_err(&dev->adev->dev,
"wait_for_completion_timeout "
"returned %d waiting for event\n", timeout);
status = timeout;
}
if (timeout == 0) { if (timeout == 0) {
/* Controller timed out */ /* Controller timed out */
dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n", dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n",

View File

@ -4,6 +4,9 @@
* *
* Peter Korsgaard <jacmet@sunsite.dk> * Peter Korsgaard <jacmet@sunsite.dk>
* *
* Support for the GRLIB port of the controller by
* Andreas Larsson <andreas@gaisler.com>
*
* This file is licensed under the terms of the GNU General Public License * This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any * version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied. * kind, whether express or implied.
@ -34,6 +37,8 @@ struct ocores_i2c {
int nmsgs; int nmsgs;
int state; /* see STATE_ */ int state; /* see STATE_ */
int clock_khz; int clock_khz;
void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
u8 (*getreg)(struct ocores_i2c *i2c, int reg);
}; };
/* registers */ /* registers */
@ -67,24 +72,47 @@ struct ocores_i2c {
#define STATE_READ 3 #define STATE_READ 3
#define STATE_ERROR 4 #define STATE_ERROR 4
#define TYPE_OCORES 0
#define TYPE_GRLIB 1
static void oc_setreg_8(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite8(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_16(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite16(value, i2c->base + (reg << i2c->reg_shift));
}
static void oc_setreg_32(struct ocores_i2c *i2c, int reg, u8 value)
{
iowrite32(value, i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_8(struct ocores_i2c *i2c, int reg)
{
return ioread8(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_16(struct ocores_i2c *i2c, int reg)
{
return ioread16(i2c->base + (reg << i2c->reg_shift));
}
static inline u8 oc_getreg_32(struct ocores_i2c *i2c, int reg)
{
return ioread32(i2c->base + (reg << i2c->reg_shift));
}
static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value)
{ {
if (i2c->reg_io_width == 4) i2c->setreg(i2c, reg, value);
iowrite32(value, i2c->base + (reg << i2c->reg_shift));
else if (i2c->reg_io_width == 2)
iowrite16(value, i2c->base + (reg << i2c->reg_shift));
else
iowrite8(value, i2c->base + (reg << i2c->reg_shift));
} }
static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
{ {
if (i2c->reg_io_width == 4) return i2c->getreg(i2c, reg);
return ioread32(i2c->base + (reg << i2c->reg_shift));
else if (i2c->reg_io_width == 2)
return ioread16(i2c->base + (reg << i2c->reg_shift));
else
return ioread8(i2c->base + (reg << i2c->reg_shift));
} }
static void ocores_process(struct ocores_i2c *i2c) static void ocores_process(struct ocores_i2c *i2c)
@ -223,11 +251,59 @@ static struct i2c_adapter ocores_adapter = {
.algo = &ocores_algorithm, .algo = &ocores_algorithm,
}; };
static struct of_device_id ocores_i2c_match[] = {
{
.compatible = "opencores,i2c-ocores",
.data = (void *)TYPE_OCORES,
},
{
.compatible = "aeroflexgaisler,i2cmst",
.data = (void *)TYPE_GRLIB,
},
{},
};
MODULE_DEVICE_TABLE(of, ocores_i2c_match);
#ifdef CONFIG_OF #ifdef CONFIG_OF
/* Read and write functions for the GRLIB port of the controller. Registers are
* 32-bit big endian and the PRELOW and PREHIGH registers are merged into one
* register. The subsequent registers has their offset decreased accordingly. */
static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)
{
u32 rd;
int rreg = reg;
if (reg != OCI2C_PRELOW)
rreg--;
rd = ioread32be(i2c->base + (rreg << i2c->reg_shift));
if (reg == OCI2C_PREHIGH)
return (u8)(rd >> 8);
else
return (u8)rd;
}
static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)
{
u32 curr, wr;
int rreg = reg;
if (reg != OCI2C_PRELOW)
rreg--;
if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) {
curr = ioread32be(i2c->base + (rreg << i2c->reg_shift));
if (reg == OCI2C_PRELOW)
wr = (curr & 0xff00) | value;
else
wr = (((u32)value) << 8) | (curr & 0xff);
} else {
wr = value;
}
iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift));
}
static int ocores_i2c_of_probe(struct platform_device *pdev, static int ocores_i2c_of_probe(struct platform_device *pdev,
struct ocores_i2c *i2c) struct ocores_i2c *i2c)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
u32 val; u32 val;
if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) { if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
@ -253,6 +329,14 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
of_property_read_u32(pdev->dev.of_node, "reg-io-width", of_property_read_u32(pdev->dev.of_node, "reg-io-width",
&i2c->reg_io_width); &i2c->reg_io_width);
match = of_match_node(ocores_i2c_match, pdev->dev.of_node);
if (match && (int)match->data == TYPE_GRLIB) {
dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n");
i2c->setreg = oc_setreg_grlib;
i2c->getreg = oc_getreg_grlib;
}
return 0; return 0;
} }
#else #else
@ -263,7 +347,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
{ {
struct ocores_i2c *i2c; struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata; struct ocores_i2c_platform_data *pdata;
struct resource *res, *res2; struct resource *res;
int irq;
int ret; int ret;
int i; int i;
@ -271,26 +356,17 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (!res) if (!res)
return -ENODEV; return -ENODEV;
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); irq = platform_get_irq(pdev, 0);
if (!res2) if (irq < 0)
return -ENODEV; return irq;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c) if (!i2c)
return -ENOMEM; return -ENOMEM;
if (!devm_request_mem_region(&pdev->dev, res->start, i2c->base = devm_request_and_ioremap(&pdev->dev, res);
resource_size(res), pdev->name)) { if (!i2c->base)
dev_err(&pdev->dev, "Memory region busy\n"); return -EADDRNOTAVAIL;
return -EBUSY;
}
i2c->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!i2c->base) {
dev_err(&pdev->dev, "Unable to map registers\n");
return -EIO;
}
pdata = pdev->dev.platform_data; pdata = pdev->dev.platform_data;
if (pdata) { if (pdata) {
@ -306,10 +382,34 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (i2c->reg_io_width == 0) if (i2c->reg_io_width == 0)
i2c->reg_io_width = 1; /* Set to default value */ i2c->reg_io_width = 1; /* Set to default value */
if (!i2c->setreg || !i2c->getreg) {
switch (i2c->reg_io_width) {
case 1:
i2c->setreg = oc_setreg_8;
i2c->getreg = oc_getreg_8;
break;
case 2:
i2c->setreg = oc_setreg_16;
i2c->getreg = oc_getreg_16;
break;
case 4:
i2c->setreg = oc_setreg_32;
i2c->getreg = oc_getreg_32;
break;
default:
dev_err(&pdev->dev, "Unsupported I/O width (%d)\n",
i2c->reg_io_width);
return -EINVAL;
}
}
ocores_init(i2c); ocores_init(i2c);
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, ret = devm_request_irq(&pdev->dev, irq, ocores_isr, 0,
pdev->name, i2c); pdev->name, i2c);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Cannot claim IRQ\n"); dev_err(&pdev->dev, "Cannot claim IRQ\n");
@ -383,12 +483,6 @@ static SIMPLE_DEV_PM_OPS(ocores_i2c_pm, ocores_i2c_suspend, ocores_i2c_resume);
#define OCORES_I2C_PM NULL #define OCORES_I2C_PM NULL
#endif #endif
static struct of_device_id ocores_i2c_match[] = {
{ .compatible = "opencores,i2c-ocores", },
{},
};
MODULE_DEVICE_TABLE(of, ocores_i2c_match);
static struct platform_driver ocores_i2c_driver = { static struct platform_driver ocores_i2c_driver = {
.probe = ocores_i2c_probe, .probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove), .remove = __devexit_p(ocores_i2c_remove),

View File

@ -43,14 +43,16 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c-omap.h> #include <linux/i2c-omap.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
/* I2C controller revisions */ /* I2C controller revisions */
#define OMAP_I2C_OMAP1_REV_2 0x20 #define OMAP_I2C_OMAP1_REV_2 0x20
/* I2C controller revisions present on specific hardware */ /* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36 #define OMAP_I2C_REV_ON_2430 0x00000036
#define OMAP_I2C_REV_ON_3430_3530 0x3C #define OMAP_I2C_REV_ON_3430_3530 0x0000003C
#define OMAP_I2C_REV_ON_3630_4430 0x40 #define OMAP_I2C_REV_ON_3630 0x00000040
#define OMAP_I2C_REV_ON_4430_PLUS 0x50400002
/* timeout waiting for the controller to respond */ /* timeout waiting for the controller to respond */
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
@ -190,7 +192,6 @@ struct omap_i2c_dev {
void (*set_mpu_wkup_lat)(struct device *dev, void (*set_mpu_wkup_lat)(struct device *dev,
long latency); long latency);
u32 speed; /* Speed of bus in kHz */ u32 speed; /* Speed of bus in kHz */
u32 dtrev; /* extra revision from DT */
u32 flags; u32 flags;
u16 cmd_err; u16 cmd_err;
u8 *buf; u8 *buf;
@ -202,17 +203,18 @@ struct omap_i2c_dev {
* fifo_size==0 implies no fifo * fifo_size==0 implies no fifo
* if set, should be trsh+1 * if set, should be trsh+1
*/ */
u8 rev; u32 rev;
unsigned b_hw:1; /* bad h/w fixes */ unsigned b_hw:1; /* bad h/w fixes */
unsigned receiver:1; /* true when we're in receiver mode */ unsigned receiver:1; /* true when we're in receiver mode */
u16 iestate; /* Saved interrupt register */ u16 iestate; /* Saved interrupt register */
u16 pscstate; u16 pscstate;
u16 scllstate; u16 scllstate;
u16 sclhstate; u16 sclhstate;
u16 bufstate;
u16 syscstate; u16 syscstate;
u16 westate; u16 westate;
u16 errata; u16 errata;
struct pinctrl *pins;
}; };
static const u8 reg_map_ip_v1[] = { static const u8 reg_map_ip_v1[] = {
@ -275,16 +277,39 @@ static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
(i2c_dev->regs[reg] << i2c_dev->reg_shift)); (i2c_dev->regs[reg] << i2c_dev->reg_shift));
} }
static int omap_i2c_init(struct omap_i2c_dev *dev) static void __omap_i2c_init(struct omap_i2c_dev *dev)
{
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
/* SCL low and high time values */
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
if (dev->rev >= OMAP_I2C_REV_ON_3430_3530)
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/*
* Don't write to this register if the IE state is 0 as it can
* cause deadlock.
*/
if (dev->iestate)
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
}
static int omap_i2c_reset(struct omap_i2c_dev *dev)
{ {
u16 psc = 0, scll = 0, sclh = 0, buf = 0;
u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long timeout; unsigned long timeout;
unsigned long internal_clk = 0; u16 sysc;
struct clk *fclk;
if (dev->rev >= OMAP_I2C_OMAP1_REV_2) { if (dev->rev >= OMAP_I2C_OMAP1_REV_2) {
sysc = omap_i2c_read_reg(dev, OMAP_I2C_SYSC_REG);
/* Disable I2C controller before soft reset */ /* Disable I2C controller before soft reset */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
@ -306,32 +331,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
} }
/* SYSC register is cleared by the reset; rewrite it */ /* SYSC register is cleared by the reset; rewrite it */
if (dev->rev == OMAP_I2C_REV_ON_2430) { omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, sysc);
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
SYSC_AUTOIDLE_MASK);
} else if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) {
dev->syscstate = SYSC_AUTOIDLE_MASK;
dev->syscstate |= SYSC_ENAWAKEUP_MASK;
dev->syscstate |= (SYSC_IDLEMODE_SMART <<
__ffs(SYSC_SIDLEMODE_MASK));
dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
__ffs(SYSC_CLOCKACTIVITY_MASK));
omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
dev->syscstate);
/*
* Enabling all wakup sources to stop I2C freezing on
* WFI instruction.
* REVISIT: Some wkup sources might not be needed.
*/
dev->westate = OMAP_I2C_WE_ALL;
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
dev->westate);
}
} }
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); return 0;
}
static int omap_i2c_init(struct omap_i2c_dev *dev)
{
u16 psc = 0, scll = 0, sclh = 0;
u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
unsigned long fclk_rate = 12000000;
unsigned long internal_clk = 0;
struct clk *fclk;
if (dev->rev >= OMAP_I2C_REV_ON_3430_3530) {
/*
* Enabling all wakup sources to stop I2C freezing on
* WFI instruction.
* REVISIT: Some wkup sources might not be needed.
*/
dev->westate = OMAP_I2C_WE_ALL;
}
if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) { if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) {
/* /*
@ -416,28 +437,17 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
sclh = fclk_rate / (dev->speed * 2) - 7 + psc; sclh = fclk_rate / (dev->speed * 2) - 7 + psc;
} }
/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
/* SCL low and high time values */
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
/* Take the I2C module out of reset: */
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
/* Enable interrupts */
dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
OMAP_I2C_IE_AL) | ((dev->fifo_size) ? OMAP_I2C_IE_AL) | ((dev->fifo_size) ?
(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { dev->pscstate = psc;
dev->pscstate = psc; dev->scllstate = scll;
dev->scllstate = scll; dev->sclhstate = sclh;
dev->sclhstate = sclh;
dev->bufstate = buf; __omap_i2c_init(dev);
}
return 0; return 0;
} }
@ -490,7 +500,7 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
if (dev->rev < OMAP_I2C_REV_ON_3630_4430) if (dev->rev < OMAP_I2C_REV_ON_3630)
dev->b_hw = 1; /* Enable hardware fixes */ dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */ /* calculate wakeup latency constraint for MPU */
@ -586,7 +596,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
OMAP_I2C_TIMEOUT); OMAP_I2C_TIMEOUT);
if (timeout == 0) { if (timeout == 0) {
dev_err(dev->dev, "controller timed out\n"); dev_err(dev->dev, "controller timed out\n");
omap_i2c_init(dev); omap_i2c_reset(dev);
__omap_i2c_init(dev);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -596,7 +607,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
/* We have an error */ /* We have an error */
if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR | if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
OMAP_I2C_STAT_XUDF)) { OMAP_I2C_STAT_XUDF)) {
omap_i2c_init(dev); omap_i2c_reset(dev);
__omap_i2c_init(dev);
return -EIO; return -EIO;
} }
@ -642,13 +654,14 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
break; break;
} }
if (dev->set_mpu_wkup_lat != NULL)
dev->set_mpu_wkup_lat(dev->dev, -1);
if (r == 0) if (r == 0)
r = num; r = num;
omap_i2c_wait_for_bb(dev); omap_i2c_wait_for_bb(dev);
if (dev->set_mpu_wkup_lat != NULL)
dev->set_mpu_wkup_lat(dev->dev, -1);
out: out:
pm_runtime_mark_last_busy(dev->dev); pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev); pm_runtime_put_autosuspend(dev->dev);
@ -1025,9 +1038,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct omap_i2c_bus_platform_data omap3_pdata = { static struct omap_i2c_bus_platform_data omap3_pdata = {
.rev = OMAP_I2C_IP_VERSION_1, .rev = OMAP_I2C_IP_VERSION_1,
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | .flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
}; };
static struct omap_i2c_bus_platform_data omap4_pdata = { static struct omap_i2c_bus_platform_data omap4_pdata = {
@ -1048,6 +1059,16 @@ static const struct of_device_id omap_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, omap_i2c_of_match); MODULE_DEVICE_TABLE(of, omap_i2c_of_match);
#endif #endif
#define OMAP_I2C_SCHEME(rev) ((rev & 0xc000) >> 14)
#define OMAP_I2C_REV_SCHEME_0_MAJOR(rev) (rev >> 4)
#define OMAP_I2C_REV_SCHEME_0_MINOR(rev) (rev & 0xf)
#define OMAP_I2C_REV_SCHEME_1_MAJOR(rev) ((rev & 0x0700) >> 7)
#define OMAP_I2C_REV_SCHEME_1_MINOR(rev) (rev & 0x1f)
#define OMAP_I2C_SCHEME_0 0
#define OMAP_I2C_SCHEME_1 1
static int __devinit static int __devinit
omap_i2c_probe(struct platform_device *pdev) omap_i2c_probe(struct platform_device *pdev)
{ {
@ -1060,6 +1081,8 @@ omap_i2c_probe(struct platform_device *pdev)
const struct of_device_id *match; const struct of_device_id *match;
int irq; int irq;
int r; int r;
u32 rev;
u16 minor, major, scheme;
/* NOTE: driver uses the static register mapping */ /* NOTE: driver uses the static register mapping */
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@ -1091,7 +1114,6 @@ omap_i2c_probe(struct platform_device *pdev)
u32 freq = 100000; /* default to 100000 Hz */ u32 freq = 100000; /* default to 100000 Hz */
pdata = match->data; pdata = match->data;
dev->dtrev = pdata->rev;
dev->flags = pdata->flags; dev->flags = pdata->flags;
of_property_read_u32(node, "clock-frequency", &freq); of_property_read_u32(node, "clock-frequency", &freq);
@ -1101,7 +1123,16 @@ omap_i2c_probe(struct platform_device *pdev)
dev->speed = pdata->clkrate; dev->speed = pdata->clkrate;
dev->flags = pdata->flags; dev->flags = pdata->flags;
dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
dev->dtrev = pdata->rev; }
dev->pins = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(dev->pins)) {
if (PTR_ERR(dev->pins) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_warn(&pdev->dev, "did not get pins for i2c error: %li\n",
PTR_ERR(dev->pins));
dev->pins = NULL;
} }
dev->dev = &pdev->dev; dev->dev = &pdev->dev;
@ -1114,11 +1145,6 @@ omap_i2c_probe(struct platform_device *pdev)
dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3;
if (dev->dtrev == OMAP_I2C_IP_VERSION_2)
dev->regs = (u8 *)reg_map_ip_v2;
else
dev->regs = (u8 *)reg_map_ip_v1;
pm_runtime_enable(dev->dev); pm_runtime_enable(dev->dev);
pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT); pm_runtime_set_autosuspend_delay(dev->dev, OMAP_I2C_PM_TIMEOUT);
pm_runtime_use_autosuspend(dev->dev); pm_runtime_use_autosuspend(dev->dev);
@ -1127,11 +1153,37 @@ omap_i2c_probe(struct platform_device *pdev)
if (IS_ERR_VALUE(r)) if (IS_ERR_VALUE(r))
goto err_free_mem; goto err_free_mem;
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; /*
* Read the Rev hi bit-[15:14] ie scheme this is 1 indicates ver2.
* On omap1/3/2 Offset 4 is IE Reg the bit [15:14] is 0 at reset.
* Also since the omap_i2c_read_reg uses reg_map_ip_* a
* raw_readw is done.
*/
rev = __raw_readw(dev->base + 0x04);
scheme = OMAP_I2C_SCHEME(rev);
switch (scheme) {
case OMAP_I2C_SCHEME_0:
dev->regs = (u8 *)reg_map_ip_v1;
dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG);
minor = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev);
major = OMAP_I2C_REV_SCHEME_0_MAJOR(dev->rev);
break;
case OMAP_I2C_SCHEME_1:
/* FALLTHROUGH */
default:
dev->regs = (u8 *)reg_map_ip_v2;
rev = (rev << 16) |
omap_i2c_read_reg(dev, OMAP_I2C_IP_V2_REVNB_LO);
minor = OMAP_I2C_REV_SCHEME_1_MINOR(rev);
major = OMAP_I2C_REV_SCHEME_1_MAJOR(rev);
dev->rev = rev;
}
dev->errata = 0; dev->errata = 0;
if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) if (dev->rev >= OMAP_I2C_REV_ON_2430 &&
dev->rev < OMAP_I2C_REV_ON_4430_PLUS)
dev->errata |= I2C_OMAP_ERRATA_I207; dev->errata |= I2C_OMAP_ERRATA_I207;
if (dev->rev <= OMAP_I2C_REV_ON_3430_3530) if (dev->rev <= OMAP_I2C_REV_ON_3430_3530)
@ -1152,7 +1204,7 @@ omap_i2c_probe(struct platform_device *pdev)
dev->fifo_size = (dev->fifo_size / 2); dev->fifo_size = (dev->fifo_size / 2);
if (dev->rev < OMAP_I2C_REV_ON_3630_4430) if (dev->rev < OMAP_I2C_REV_ON_3630)
dev->b_hw = 1; /* Enable hardware fixes */ dev->b_hw = 1; /* Enable hardware fixes */
/* calculate wakeup latency constraint for MPU */ /* calculate wakeup latency constraint for MPU */
@ -1195,8 +1247,8 @@ omap_i2c_probe(struct platform_device *pdev)
goto err_unuse_clocks; goto err_unuse_clocks;
} }
dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", adap->nr, dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n", adap->nr,
dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); major, minor, dev->speed);
of_i2c_register_devices(adap); of_i2c_register_devices(adap);
@ -1239,14 +1291,13 @@ static int omap_i2c_runtime_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
u16 iv;
_dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG); _dev->iestate = omap_i2c_read_reg(_dev, OMAP_I2C_IE_REG);
omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0); omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, 0);
if (_dev->rev < OMAP_I2C_OMAP1_REV_2) { if (_dev->rev < OMAP_I2C_OMAP1_REV_2) {
iv = omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */ omap_i2c_read_reg(_dev, OMAP_I2C_IV_REG); /* Read clears */
} else { } else {
omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate); omap_i2c_write_reg(_dev, OMAP_I2C_STAT_REG, _dev->iestate);
@ -1262,23 +1313,10 @@ static int omap_i2c_runtime_resume(struct device *dev)
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); struct omap_i2c_dev *_dev = platform_get_drvdata(pdev);
if (_dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { if (!_dev->regs)
omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, 0); return 0;
omap_i2c_write_reg(_dev, OMAP_I2C_PSC_REG, _dev->pscstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SCLL_REG, _dev->scllstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SCLH_REG, _dev->sclhstate);
omap_i2c_write_reg(_dev, OMAP_I2C_BUF_REG, _dev->bufstate);
omap_i2c_write_reg(_dev, OMAP_I2C_SYSC_REG, _dev->syscstate);
omap_i2c_write_reg(_dev, OMAP_I2C_WE_REG, _dev->westate);
omap_i2c_write_reg(_dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
}
/* __omap_i2c_init(_dev);
* Don't write to this register if the IE state is 0 as it can
* cause deadlock.
*/
if (_dev->iestate)
omap_i2c_write_reg(_dev, OMAP_I2C_IE_REG, _dev->iestate);
return 0; return 0;
} }

View File

@ -642,7 +642,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
return ret; return ret;
priv->io = devm_ioremap(dev, res->start, resource_size(res)); priv->io = devm_request_and_ioremap(dev, res);
if (!priv->io) { if (!priv->io) {
dev_err(dev, "cannot ioremap\n"); dev_err(dev, "cannot ioremap\n");
return -ENODEV; return -ENODEV;
@ -693,7 +693,7 @@ static int __devexit rcar_i2c_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct platform_driver rcar_i2c_drv = { static struct platform_driver rcar_i2c_driver = {
.driver = { .driver = {
.name = "i2c-rcar", .name = "i2c-rcar",
.owner = THIS_MODULE, .owner = THIS_MODULE,
@ -702,7 +702,7 @@ static struct platform_driver rcar_i2c_drv = {
.remove = __devexit_p(rcar_i2c_remove), .remove = __devexit_p(rcar_i2c_remove),
}; };
module_platform_driver(rcar_i2c_drv); module_platform_driver(rcar_i2c_driver);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Renesas R-Car I2C bus driver"); MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");

View File

@ -38,6 +38,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_i2c.h> #include <linux/of_i2c.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>
#include <asm/irq.h> #include <asm/irq.h>
@ -49,6 +50,9 @@
#define QUIRK_HDMIPHY (1 << 1) #define QUIRK_HDMIPHY (1 << 1)
#define QUIRK_NO_GPIO (1 << 2) #define QUIRK_NO_GPIO (1 << 2)
/* Max time to wait for bus to become idle after a xfer (in us) */
#define S3C2410_IDLE_TIMEOUT 5000
/* i2c controller state */ /* i2c controller state */
enum s3c24xx_i2c_state { enum s3c24xx_i2c_state {
STATE_IDLE, STATE_IDLE,
@ -59,7 +63,6 @@ enum s3c24xx_i2c_state {
}; };
struct s3c24xx_i2c { struct s3c24xx_i2c {
spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
unsigned int quirks; unsigned int quirks;
unsigned int suspended:1; unsigned int suspended:1;
@ -78,11 +81,11 @@ struct s3c24xx_i2c {
void __iomem *regs; void __iomem *regs;
struct clk *clk; struct clk *clk;
struct device *dev; struct device *dev;
struct resource *ioarea;
struct i2c_adapter adap; struct i2c_adapter adap;
struct s3c2410_platform_i2c *pdata; struct s3c2410_platform_i2c *pdata;
int gpios[2]; int gpios[2];
struct pinctrl *pctrl;
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition; struct notifier_block freq_transition;
#endif #endif
@ -235,8 +238,47 @@ static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret)
dev_dbg(i2c->dev, "STOP\n"); dev_dbg(i2c->dev, "STOP\n");
/* stop the transfer */ /*
iicstat &= ~S3C2410_IICSTAT_START; * The datasheet says that the STOP sequence should be:
* 1) I2CSTAT.5 = 0 - Clear BUSY (or 'generate STOP')
* 2) I2CCON.4 = 0 - Clear IRQPEND
* 3) Wait until the stop condition takes effect.
* 4*) I2CSTAT.4 = 0 - Clear TXRXEN
*
* Where, step "4*" is only for buses with the "HDMIPHY" quirk.
*
* However, after much experimentation, it appears that:
* a) normal buses automatically clear BUSY and transition from
* Master->Slave when they complete generating a STOP condition.
* Therefore, step (3) can be done in doxfer() by polling I2CCON.4
* after starting the STOP generation here.
* b) HDMIPHY bus does neither, so there is no way to do step 3.
* There is no indication when this bus has finished generating
* STOP.
*
* In fact, we have found that as soon as the IRQPEND bit is cleared in
* step 2, the HDMIPHY bus generates the STOP condition, and then
* immediately starts transferring another data byte, even though the
* bus is supposedly stopped. This is presumably because the bus is
* still in "Master" mode, and its BUSY bit is still set.
*
* To avoid these extra post-STOP transactions on HDMI phy devices, we
* just disable Serial Output on the bus (I2CSTAT.4 = 0) directly,
* instead of first generating a proper STOP condition. This should
* float SDA & SCK terminating the transfer. Subsequent transfers
* start with a proper START condition, and proceed normally.
*
* The HDMIPHY bus is an internal bus that always has exactly two
* devices, the host as Master and the HDMIPHY device as the slave.
* Skipping the STOP condition has been tested on this bus and works.
*/
if (i2c->quirks & QUIRK_HDMIPHY) {
/* Stop driving the I2C pins */
iicstat &= ~S3C2410_IICSTAT_TXRXEN;
} else {
/* stop the transfer */
iicstat &= ~S3C2410_IICSTAT_START;
}
writel(iicstat, i2c->regs + S3C2410_IICSTAT); writel(iicstat, i2c->regs + S3C2410_IICSTAT);
i2c->state = STATE_STOP; i2c->state = STATE_STOP;
@ -490,13 +532,6 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
unsigned long iicstat; unsigned long iicstat;
int timeout = 400; int timeout = 400;
/* the timeout for HDMIPHY is reduced to 10 ms because
* the hangup is expected to happen, so waiting 400 ms
* causes only unnecessary system hangup
*/
if (i2c->quirks & QUIRK_HDMIPHY)
timeout = 10;
while (timeout-- > 0) { while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT); iicstat = readl(i2c->regs + S3C2410_IICSTAT);
@ -506,16 +541,61 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
msleep(1); msleep(1);
} }
/* hang-up of bus dedicated for HDMIPHY occurred, resetting */ return -ETIMEDOUT;
if (i2c->quirks & QUIRK_HDMIPHY) { }
writel(0, i2c->regs + S3C2410_IICCON);
writel(0, i2c->regs + S3C2410_IICSTAT);
writel(0, i2c->regs + S3C2410_IICDS);
return 0; /* s3c24xx_i2c_wait_idle
*
* wait for the i2c bus to become idle.
*/
static void s3c24xx_i2c_wait_idle(struct s3c24xx_i2c *i2c)
{
unsigned long iicstat;
ktime_t start, now;
unsigned long delay;
int spins;
/* ensure the stop has been through the bus */
dev_dbg(i2c->dev, "waiting for bus idle\n");
start = now = ktime_get();
/*
* Most of the time, the bus is already idle within a few usec of the
* end of a transaction. However, really slow i2c devices can stretch
* the clock, delaying STOP generation.
*
* On slower SoCs this typically happens within a very small number of
* instructions so busy wait briefly to avoid scheduling overhead.
*/
spins = 3;
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
while ((iicstat & S3C2410_IICSTAT_START) && --spins) {
cpu_relax();
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
} }
return -ETIMEDOUT; /*
* If we do get an appreciable delay as a compromise between idle
* detection latency for the normal, fast case, and system load in the
* slow device case, use an exponential back off in the polling loop,
* up to 1/10th of the total timeout, then continue to poll at a
* constant rate up to the timeout.
*/
delay = 1;
while ((iicstat & S3C2410_IICSTAT_START) &&
ktime_us_delta(now, start) < S3C2410_IDLE_TIMEOUT) {
usleep_range(delay, 2 * delay);
if (delay < S3C2410_IDLE_TIMEOUT / 10)
delay <<= 1;
now = ktime_get();
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
}
if (iicstat & S3C2410_IICSTAT_START)
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
} }
/* s3c24xx_i2c_doxfer /* s3c24xx_i2c_doxfer
@ -526,8 +606,7 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
struct i2c_msg *msgs, int num) struct i2c_msg *msgs, int num)
{ {
unsigned long iicstat, timeout; unsigned long timeout;
int spins = 20;
int ret; int ret;
if (i2c->suspended) if (i2c->suspended)
@ -540,8 +619,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
goto out; goto out;
} }
spin_lock_irq(&i2c->lock);
i2c->msg = msgs; i2c->msg = msgs;
i2c->msg_num = num; i2c->msg_num = num;
i2c->msg_ptr = 0; i2c->msg_ptr = 0;
@ -550,7 +627,6 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_enable_irq(i2c);
s3c24xx_i2c_message_start(i2c, msgs); s3c24xx_i2c_message_start(i2c, msgs);
spin_unlock_irq(&i2c->lock);
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
@ -564,24 +640,11 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c,
else if (ret != num) else if (ret != num)
dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret);
/* ensure the stop has been through the bus */ /* For QUIRK_HDMIPHY, bus is already disabled */
if (i2c->quirks & QUIRK_HDMIPHY)
goto out;
dev_dbg(i2c->dev, "waiting for bus idle\n"); s3c24xx_i2c_wait_idle(i2c);
/* first, try busy waiting briefly */
do {
cpu_relax();
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
} while ((iicstat & S3C2410_IICSTAT_START) && --spins);
/* if that timed out sleep */
if (!spins) {
msleep(1);
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
}
if (iicstat & S3C2410_IICSTAT_START)
dev_warn(i2c->dev, "timeout waiting for bus idle\n");
out: out:
return ret; return ret;
@ -740,7 +803,6 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
unsigned long val, void *data) unsigned long val, void *data)
{ {
struct s3c24xx_i2c *i2c = freq_to_i2c(nb); struct s3c24xx_i2c *i2c = freq_to_i2c(nb);
unsigned long flags;
unsigned int got; unsigned int got;
int delta_f; int delta_f;
int ret; int ret;
@ -754,9 +816,9 @@ static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb,
if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) ||
(val == CPUFREQ_PRECHANGE && delta_f > 0)) { (val == CPUFREQ_PRECHANGE && delta_f > 0)) {
spin_lock_irqsave(&i2c->lock, flags); i2c_lock_adapter(&i2c->adap);
ret = s3c24xx_i2c_clockrate(i2c, &got); ret = s3c24xx_i2c_clockrate(i2c, &got);
spin_unlock_irqrestore(&i2c->lock, flags); i2c_unlock_adapter(&i2c->adap);
if (ret < 0) if (ret < 0)
dev_err(i2c->dev, "cannot find frequency\n"); dev_err(i2c->dev, "cannot find frequency\n");
@ -858,14 +920,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
pdata = i2c->pdata; pdata = i2c->pdata;
/* inititalise the gpio */
if (pdata->cfg_gpio)
pdata->cfg_gpio(to_platform_device(i2c->dev));
else
if (s3c24xx_i2c_parse_dt_gpio(i2c))
return -EINVAL;
/* write slave address */ /* write slave address */
writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD);
@ -963,7 +1017,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
i2c->tx_setup = 50; i2c->tx_setup = 50;
spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait); init_waitqueue_head(&i2c->wait);
/* find the clock and enable it */ /* find the clock and enable it */
@ -989,36 +1042,38 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_clk; goto err_clk;
} }
i2c->ioarea = request_mem_region(res->start, resource_size(res), i2c->regs = devm_request_and_ioremap(&pdev->dev, res);
pdev->name);
if (i2c->ioarea == NULL) {
dev_err(&pdev->dev, "cannot request IO\n");
ret = -ENXIO;
goto err_clk;
}
i2c->regs = ioremap(res->start, resource_size(res));
if (i2c->regs == NULL) { if (i2c->regs == NULL) {
dev_err(&pdev->dev, "cannot map IO\n"); dev_err(&pdev->dev, "cannot map IO\n");
ret = -ENXIO; ret = -ENXIO;
goto err_ioarea; goto err_clk;
} }
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", dev_dbg(&pdev->dev, "registers %p (%p)\n",
i2c->regs, i2c->ioarea, res); i2c->regs, res);
/* setup info block for the i2c core */ /* setup info block for the i2c core */
i2c->adap.algo_data = i2c; i2c->adap.algo_data = i2c;
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->pctrl = devm_pinctrl_get_select_default(i2c->dev);
/* inititalise the i2c gpio lines */
if (i2c->pdata->cfg_gpio) {
i2c->pdata->cfg_gpio(to_platform_device(i2c->dev));
} else if (IS_ERR(i2c->pctrl) && s3c24xx_i2c_parse_dt_gpio(i2c)) {
ret = -EINVAL;
goto err_clk;
}
/* initialise the i2c controller */ /* initialise the i2c controller */
ret = s3c24xx_i2c_init(i2c); ret = s3c24xx_i2c_init(i2c);
if (ret != 0) if (ret != 0)
goto err_iomap; goto err_clk;
/* find the IRQ for this unit (note, this relies on the init call to /* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending * ensure no current IRQs pending
@ -1027,7 +1082,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
i2c->irq = ret = platform_get_irq(pdev, 0); i2c->irq = ret = platform_get_irq(pdev, 0);
if (ret <= 0) { if (ret <= 0) {
dev_err(&pdev->dev, "cannot find IRQ\n"); dev_err(&pdev->dev, "cannot find IRQ\n");
goto err_iomap; goto err_clk;
} }
ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0, ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0,
@ -1035,7 +1090,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq);
goto err_iomap; goto err_clk;
} }
ret = s3c24xx_i2c_register_cpufreq(i2c); ret = s3c24xx_i2c_register_cpufreq(i2c);
@ -1075,13 +1130,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
err_irq: err_irq:
free_irq(i2c->irq, i2c); free_irq(i2c->irq, i2c);
err_iomap:
iounmap(i2c->regs);
err_ioarea:
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
err_clk: err_clk:
clk_disable_unprepare(i2c->clk); clk_disable_unprepare(i2c->clk);
clk_put(i2c->clk); clk_put(i2c->clk);
@ -1110,16 +1158,13 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
clk_disable_unprepare(i2c->clk); clk_disable_unprepare(i2c->clk);
clk_put(i2c->clk); clk_put(i2c->clk);
iounmap(i2c->regs); if (pdev->dev.of_node && IS_ERR(i2c->pctrl))
s3c24xx_i2c_dt_gpio_free(i2c);
release_resource(i2c->ioarea);
s3c24xx_i2c_dt_gpio_free(i2c);
kfree(i2c->ioarea);
return 0; return 0;
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP
static int s3c24xx_i2c_suspend_noirq(struct device *dev) static int s3c24xx_i2c_suspend_noirq(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
@ -1142,10 +1187,14 @@ static int s3c24xx_i2c_resume(struct device *dev)
return 0; return 0;
} }
#endif
#ifdef CONFIG_PM
static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
#ifdef CONFIG_PM_SLEEP
.suspend_noirq = s3c24xx_i2c_suspend_noirq, .suspend_noirq = s3c24xx_i2c_suspend_noirq,
.resume = s3c24xx_i2c_resume, .resume = s3c24xx_i2c_resume,
#endif
}; };
#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops) #define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops)

View File

@ -120,11 +120,12 @@ struct sh_mobile_i2c_data {
void __iomem *reg; void __iomem *reg;
struct i2c_adapter adap; struct i2c_adapter adap;
unsigned long bus_speed; unsigned long bus_speed;
unsigned int clks_per_count;
struct clk *clk; struct clk *clk;
u_int8_t icic; u_int8_t icic;
u_int8_t iccl;
u_int8_t icch;
u_int8_t flags; u_int8_t flags;
u_int16_t iccl;
u_int16_t icch;
spinlock_t lock; spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
@ -135,7 +136,8 @@ struct sh_mobile_i2c_data {
#define IIC_FLAG_HAS_ICIC67 (1 << 0) #define IIC_FLAG_HAS_ICIC67 (1 << 0)
#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ #define STANDARD_MODE 100000
#define FAST_MODE 400000
/* Register offsets */ /* Register offsets */
#define ICDR 0x00 #define ICDR 0x00
@ -187,58 +189,91 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
} }
static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
{
/*
* Conditional expression:
* ICCL >= COUNT_CLK * (tLOW + tf)
*
* SH-Mobile IIC hardware starts counting the LOW period of
* the SCL signal (tLOW) as soon as it pulls the SCL line.
* In order to meet the tLOW timing spec, we need to take into
* account the fall time of SCL signal (tf). Default tf value
* should be 0.3 us, for safety.
*/
return (((count_khz * (tLOW + tf)) + 5000) / 10000) + offset;
}
static u32 sh_mobile_i2c_icch(unsigned long count_khz, u32 tHIGH, u32 tf, int offset)
{
/*
* Conditional expression:
* ICCH >= COUNT_CLK * (tHIGH + tf)
*
* SH-Mobile IIC hardware is aware of SCL transition period 'tr',
* and can ignore it. SH-Mobile IIC controller starts counting
* the HIGH period of the SCL signal (tHIGH) after the SCL input
* voltage increases at VIH.
*
* Afterward it turned out calculating ICCH using only tHIGH spec
* will result in violation of the tHD;STA timing spec. We need
* to take into account the fall time of SDA signal (tf) at START
* condition, in order to meet both tHIGH and tHD;STA specs.
*/
return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
}
static void sh_mobile_i2c_init(struct sh_mobile_i2c_data *pd)
{
unsigned long i2c_clk_khz;
u32 tHIGH, tLOW, tf;
int offset;
/* Get clock rate after clock is enabled */
clk_enable(pd->clk);
i2c_clk_khz = clk_get_rate(pd->clk) / 1000;
i2c_clk_khz /= pd->clks_per_count;
if (pd->bus_speed == STANDARD_MODE) {
tLOW = 47; /* tLOW = 4.7 us */
tHIGH = 40; /* tHD;STA = tHIGH = 4.0 us */
tf = 3; /* tf = 0.3 us */
offset = 0; /* No offset */
} else if (pd->bus_speed == FAST_MODE) {
tLOW = 13; /* tLOW = 1.3 us */
tHIGH = 6; /* tHD;STA = tHIGH = 0.6 us */
tf = 3; /* tf = 0.3 us */
offset = 0; /* No offset */
} else {
dev_err(pd->dev, "unrecognized bus speed %lu Hz\n",
pd->bus_speed);
goto out;
}
pd->iccl = sh_mobile_i2c_iccl(i2c_clk_khz, tLOW, tf, offset);
/* one more bit of ICCL in ICIC */
if ((pd->iccl > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
pd->icic |= ICIC_ICCLB8;
else
pd->icic &= ~ICIC_ICCLB8;
pd->icch = sh_mobile_i2c_icch(i2c_clk_khz, tHIGH, tf, offset);
/* one more bit of ICCH in ICIC */
if ((pd->icch > 0xff) && (pd->flags & IIC_FLAG_HAS_ICIC67))
pd->icic |= ICIC_ICCHB8;
else
pd->icic &= ~ICIC_ICCHB8;
out:
clk_disable(pd->clk);
}
static void activate_ch(struct sh_mobile_i2c_data *pd) static void activate_ch(struct sh_mobile_i2c_data *pd)
{ {
unsigned long i2c_clk;
u_int32_t num;
u_int32_t denom;
u_int32_t tmp;
/* Wake up device and enable clock */ /* Wake up device and enable clock */
pm_runtime_get_sync(pd->dev); pm_runtime_get_sync(pd->dev);
clk_enable(pd->clk); clk_enable(pd->clk);
/* Get clock rate after clock is enabled */
i2c_clk = clk_get_rate(pd->clk);
/* 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 = i2c_clk * 5;
denom = pd->bus_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);
/* one more bit of ICCL in ICIC */
if (pd->flags & IIC_FLAG_HAS_ICIC67) {
if ((num/denom) > 0xff)
pd->icic |= ICIC_ICCLB8;
else
pd->icic &= ~ICIC_ICCLB8;
}
/* Calculate the value for icch. From the data sheet:
icch = (p clock / transfer rate) * (H / (L + H)) */
num = i2c_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);
/* one more bit of ICCH in ICIC */
if (pd->flags & IIC_FLAG_HAS_ICIC67) {
if ((num/denom) > 0xff)
pd->icic |= ICIC_ICCHB8;
else
pd->icic &= ~ICIC_ICCHB8;
}
/* Enable channel and configure rx ack */ /* Enable channel and configure rx ack */
iic_set_clr(pd, ICCR, ICCR_ICE, 0); iic_set_clr(pd, ICCR, ICCR_ICE, 0);
@ -246,8 +281,8 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
iic_wr(pd, ICIC, 0); iic_wr(pd, ICIC, 0);
/* Set the clock */ /* Set the clock */
iic_wr(pd, ICCL, pd->iccl); iic_wr(pd, ICCL, pd->iccl & 0xff);
iic_wr(pd, ICCH, pd->icch); iic_wr(pd, ICCH, pd->icch & 0xff);
} }
static void deactivate_ch(struct sh_mobile_i2c_data *pd) static void deactivate_ch(struct sh_mobile_i2c_data *pd)
@ -434,6 +469,9 @@ static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id)
wake_up(&pd->wait); wake_up(&pd->wait);
} }
/* defeat write posting to avoid spurious WAIT interrupts */
iic_rd(pd, ICSR);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -451,8 +489,8 @@ static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg)
iic_set_clr(pd, ICCR, ICCR_ICE, 0); iic_set_clr(pd, ICCR, ICCR_ICE, 0);
/* Set the clock */ /* Set the clock */
iic_wr(pd, ICCL, pd->iccl); iic_wr(pd, ICCL, pd->iccl & 0xff);
iic_wr(pd, ICCH, pd->icch); iic_wr(pd, ICCH, pd->icch & 0xff);
pd->msg = usr_msg; pd->msg = usr_msg;
pd->pos = -1; pd->pos = -1;
@ -621,10 +659,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
goto err_irq; goto err_irq;
} }
/* Use platformd data bus speed or NORMAL_SPEED */ /* Use platform data bus speed or STANDARD_MODE */
pd->bus_speed = NORMAL_SPEED; pd->bus_speed = STANDARD_MODE;
if (pdata && pdata->bus_speed) if (pdata && pdata->bus_speed)
pd->bus_speed = pdata->bus_speed; pd->bus_speed = pdata->bus_speed;
pd->clks_per_count = 1;
if (pdata && pdata->clks_per_count)
pd->clks_per_count = pdata->clks_per_count;
/* The IIC blocks on SH-Mobile ARM processors /* The IIC blocks on SH-Mobile ARM processors
* come with two new bits in ICIC. * come with two new bits in ICIC.
@ -632,6 +673,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
if (size > 0x17) if (size > 0x17)
pd->flags |= IIC_FLAG_HAS_ICIC67; pd->flags |= IIC_FLAG_HAS_ICIC67;
sh_mobile_i2c_init(pd);
/* Enable Runtime PM for this device. /* Enable Runtime PM for this device.
* *
* Also tell the Runtime PM core to ignore children * Also tell the Runtime PM core to ignore children
@ -667,8 +710,9 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
goto err_all; goto err_all;
} }
dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n", dev_info(&dev->dev,
adap->nr, pd->bus_speed); "I2C adapter %d with bus speed %lu Hz (L/H=%x/%x)\n",
adap->nr, pd->bus_speed, pd->iccl, pd->icch);
of_i2c_register_devices(adap); of_i2c_register_devices(adap);
return 0; return 0;

View File

@ -16,6 +16,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_i2c.h>
#include <linux/of_gpio.h>
struct gpiomux { struct gpiomux {
struct i2c_adapter *parent; struct i2c_adapter *parent;
@ -57,29 +59,110 @@ static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
return !strcmp(chip->label, data); return !strcmp(chip->label, data);
} }
#ifdef CONFIG_OF
static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *adapter_np, *child;
struct i2c_adapter *adapter;
unsigned *values, *gpios;
int i = 0;
if (!np)
return -ENODEV;
adapter_np = of_parse_phandle(np, "i2c-parent", 0);
if (!adapter_np) {
dev_err(&pdev->dev, "Cannot parse i2c-parent\n");
return -ENODEV;
}
adapter = of_find_i2c_adapter_by_node(adapter_np);
if (!adapter) {
dev_err(&pdev->dev, "Cannot find parent bus\n");
return -ENODEV;
}
mux->data.parent = i2c_adapter_id(adapter);
put_device(&adapter->dev);
mux->data.n_values = of_get_child_count(np);
values = devm_kzalloc(&pdev->dev,
sizeof(*mux->data.values) * mux->data.n_values,
GFP_KERNEL);
if (!values) {
dev_err(&pdev->dev, "Cannot allocate values array");
return -ENOMEM;
}
for_each_child_of_node(np, child) {
of_property_read_u32(child, "reg", values + i);
i++;
}
mux->data.values = values;
if (of_property_read_u32(np, "idle-state", &mux->data.idle))
mux->data.idle = I2C_MUX_GPIO_NO_IDLE;
mux->data.n_gpios = of_gpio_named_count(np, "mux-gpios");
if (mux->data.n_gpios < 0) {
dev_err(&pdev->dev, "Missing mux-gpios property in the DT.\n");
return -EINVAL;
}
gpios = devm_kzalloc(&pdev->dev,
sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL);
if (!gpios) {
dev_err(&pdev->dev, "Cannot allocate gpios array");
return -ENOMEM;
}
for (i = 0; i < mux->data.n_gpios; i++)
gpios[i] = of_get_named_gpio(np, "mux-gpios", i);
mux->data.gpios = gpios;
return 0;
}
#else
static int __devinit i2c_mux_gpio_probe_dt(struct gpiomux *mux,
struct platform_device *pdev)
{
return 0;
}
#endif
static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev) static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
{ {
struct gpiomux *mux; struct gpiomux *mux;
struct i2c_mux_gpio_platform_data *pdata;
struct i2c_adapter *parent; struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32); int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state, gpio_base; unsigned initial_state, gpio_base;
int i, ret; int i, ret;
pdata = pdev->dev.platform_data; mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!pdata) { if (!mux) {
dev_err(&pdev->dev, "Missing platform data\n"); dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
return -ENODEV; return -ENOMEM;
} }
platform_set_drvdata(pdev, mux);
if (!pdev->dev.platform_data) {
ret = i2c_mux_gpio_probe_dt(mux, pdev);
if (ret < 0)
return ret;
} else
memcpy(&mux->data, pdev->dev.platform_data, sizeof(mux->data));
/* /*
* If a GPIO chip name is provided, the GPIO pin numbers provided are * If a GPIO chip name is provided, the GPIO pin numbers provided are
* relative to its base GPIO number. Otherwise they are absolute. * relative to its base GPIO number. Otherwise they are absolute.
*/ */
if (pdata->gpio_chip) { if (mux->data.gpio_chip) {
struct gpio_chip *gpio; struct gpio_chip *gpio;
gpio = gpiochip_find(pdata->gpio_chip, gpio = gpiochip_find(mux->data.gpio_chip,
match_gpio_chip_by_label); match_gpio_chip_by_label);
if (!gpio) if (!gpio)
return -EPROBE_DEFER; return -EPROBE_DEFER;
@ -89,49 +172,44 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
gpio_base = 0; gpio_base = 0;
} }
parent = i2c_get_adapter(pdata->parent); parent = i2c_get_adapter(mux->data.parent);
if (!parent) { if (!parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n", dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
pdata->parent); mux->data.parent);
return -ENODEV; return -ENODEV;
} }
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
ret = -ENOMEM;
goto alloc_failed;
}
mux->parent = parent; mux->parent = parent;
mux->data = *pdata;
mux->gpio_base = gpio_base; mux->gpio_base = gpio_base;
mux->adap = devm_kzalloc(&pdev->dev, mux->adap = devm_kzalloc(&pdev->dev,
sizeof(*mux->adap) * pdata->n_values, sizeof(*mux->adap) * mux->data.n_values,
GFP_KERNEL); GFP_KERNEL);
if (!mux->adap) { if (!mux->adap) {
dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
ret = -ENOMEM; ret = -ENOMEM;
goto alloc_failed; goto alloc_failed;
} }
if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) { if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = pdata->idle; initial_state = mux->data.idle;
deselect = i2c_mux_gpio_deselect; deselect = i2c_mux_gpio_deselect;
} else { } else {
initial_state = pdata->values[0]; initial_state = mux->data.values[0];
deselect = NULL; deselect = NULL;
} }
for (i = 0; i < pdata->n_gpios; i++) { for (i = 0; i < mux->data.n_gpios; i++) {
ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio"); ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
if (ret) if (ret)
goto err_request_gpio; goto err_request_gpio;
gpio_direction_output(gpio_base + pdata->gpios[i], gpio_direction_output(gpio_base + mux->data.gpios[i],
initial_state & (1 << i)); initial_state & (1 << i));
} }
for (i = 0; i < pdata->n_values; i++) { for (i = 0; i < mux->data.n_values; i++) {
u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; u32 nr = mux->data.base_nr ? (mux->data.base_nr + i) : 0;
unsigned int class = pdata->classes ? pdata->classes[i] : 0; unsigned int class = mux->data.classes ? mux->data.classes[i] : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
i, class, i, class,
@ -144,19 +222,17 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
} }
dev_info(&pdev->dev, "%d port mux on %s adapter\n", dev_info(&pdev->dev, "%d port mux on %s adapter\n",
pdata->n_values, parent->name); mux->data.n_values, parent->name);
platform_set_drvdata(pdev, mux);
return 0; return 0;
add_adapter_failed: add_adapter_failed:
for (; i > 0; i--) for (; i > 0; i--)
i2c_del_mux_adapter(mux->adap[i - 1]); i2c_del_mux_adapter(mux->adap[i - 1]);
i = pdata->n_gpios; i = mux->data.n_gpios;
err_request_gpio: err_request_gpio:
for (; i > 0; i--) for (; i > 0; i--)
gpio_free(gpio_base + pdata->gpios[i - 1]); gpio_free(gpio_base + mux->data.gpios[i - 1]);
alloc_failed: alloc_failed:
i2c_put_adapter(parent); i2c_put_adapter(parent);
@ -180,12 +256,19 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id i2c_mux_gpio_of_match[] __devinitconst = {
{ .compatible = "i2c-mux-gpio", },
{},
};
MODULE_DEVICE_TABLE(of, i2c_mux_gpio_of_match);
static struct platform_driver i2c_mux_gpio_driver = { static struct platform_driver i2c_mux_gpio_driver = {
.probe = i2c_mux_gpio_probe, .probe = i2c_mux_gpio_probe,
.remove = __devexit_p(i2c_mux_gpio_remove), .remove = __devexit_p(i2c_mux_gpio_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "i2c-mux-gpio", .name = "i2c-mux-gpio",
.of_match_table = of_match_ptr(i2c_mux_gpio_of_match),
}, },
}; };

View File

@ -20,8 +20,6 @@
#define OMAP_I2C_FLAG_NO_FIFO BIT(0) #define OMAP_I2C_FLAG_NO_FIFO BIT(0)
#define OMAP_I2C_FLAG_SIMPLE_CLOCK BIT(1) #define OMAP_I2C_FLAG_SIMPLE_CLOCK BIT(1)
#define OMAP_I2C_FLAG_16BIT_DATA_REG BIT(2) #define OMAP_I2C_FLAG_16BIT_DATA_REG BIT(2)
#define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE BIT(3)
#define OMAP_I2C_FLAG_APPLY_ERRATA_I207 BIT(4)
#define OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK BIT(5) #define OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK BIT(5)
#define OMAP_I2C_FLAG_FORCE_19200_INT_CLK BIT(6) #define OMAP_I2C_FLAG_FORCE_19200_INT_CLK BIT(6)
/* how the CPU address bus must be translated for I2C unit access */ /* how the CPU address bus must be translated for I2C unit access */

View File

@ -5,6 +5,7 @@
struct i2c_sh_mobile_platform_data { struct i2c_sh_mobile_platform_data {
unsigned long bus_speed; unsigned long bus_speed;
unsigned int clks_per_count;
}; };
#endif /* __I2C_SH_MOBILE_H__ */ #endif /* __I2C_SH_MOBILE_H__ */

View File

@ -0,0 +1,27 @@
/*
* i2c-cbus-gpio.h - CBUS I2C platform_data definition
*
* Copyright (C) 2004-2009 Nokia Corporation
*
* Written by Felipe Balbi and Aaro Koskinen.
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
* archive for more details.
*
* 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.
*/
#ifndef __INCLUDE_LINUX_I2C_CBUS_GPIO_H
#define __INCLUDE_LINUX_I2C_CBUS_GPIO_H
struct i2c_cbus_platform_data {
int dat_gpio;
int clk_gpio;
int sel_gpio;
};
#endif /* __INCLUDE_LINUX_I2C_CBUS_GPIO_H */