Commit 752451f0 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 673ab878 972deb4f
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>;
};
};
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>;
};
};
};
Device tree configuration for i2c-ocores
Required properties:
- compatible : "opencores,i2c-ocores"
- compatible : "opencores,i2c-ocores" or "aeroflexgaisler,i2cmst"
- reg : bus address start and address range size of device
- interrupts : interrupt number
- clock-frequency : frequency of bus clock in Hz
......
......@@ -13,11 +13,17 @@ Required properties:
- interrupts: interrupt number to the cpu.
- 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:
- 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
specified, default value is 0.
- samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
......@@ -31,8 +37,14 @@ Example:
interrupts = <345>;
samsung,i2c-sda-delay = <100>;
samsung,i2c-max-bus-freq = <100000>;
/* Samsung GPIO variant begins here */
gpios = <&gpd1 2 0 /* SDA */
&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>;
#size-cells = <0>;
......
......@@ -92,6 +92,30 @@ i2c1: i2c@8005a000 {
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 {
status = "okay";
};
......
......@@ -16,10 +16,12 @@
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/stddef.h>
#include <linux/i2c.h>
#include <linux/spi/spi.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/mtd-onenand-omap2.h>
#include <linux/mfd/menelaus.h>
......@@ -40,6 +42,45 @@
#define TUSB6010_GPIO_ENABLE 0
#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)
/*
* 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);
n8x0_mmc_init();
n8x0_usb_init();
n8x0_cbus_init();
}
MACHINE_START(NOKIA_N800, "Nokia N800")
......
......@@ -120,6 +120,16 @@ static int __init omap_i2c_nr_ports(void)
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";
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;
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,
sizeof(struct omap_i2c_bus_platform_data),
NULL, 0, 0);
......
......@@ -77,8 +77,7 @@ static struct omap_hwmod_class i2c_class = {
static struct omap_i2c_dev_attr i2c_dev_attr = {
.fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
OMAP_I2C_FLAG_BUS_SHIFT_2 |
.flags = OMAP_I2C_FLAG_BUS_SHIFT_2 |
OMAP_I2C_FLAG_FORCE_19200_INT_CLK,
};
......
......@@ -1118,8 +1118,7 @@ static struct omap_hwmod_class i2c_class = {
};
static struct omap_i2c_dev_attr i2c_dev_attr = {
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
};
/* i2c1 */
......
......@@ -794,9 +794,7 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
/* I2C1 */
static struct omap_i2c_dev_attr i2c1_dev_attr = {
.fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
.flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod omap3xxx_i2c1_hwmod = {
......@@ -821,9 +819,7 @@ static struct omap_hwmod omap3xxx_i2c1_hwmod = {
/* I2C2 */
static struct omap_i2c_dev_attr i2c2_dev_attr = {
.fifo_depth = 8, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
.flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod omap3xxx_i2c2_hwmod = {
......@@ -848,9 +844,7 @@ static struct omap_hwmod omap3xxx_i2c2_hwmod = {
/* I2C3 */
static struct omap_i2c_dev_attr i2c3_dev_attr = {
.fifo_depth = 64, /* bytes */
.flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE |
OMAP_I2C_FLAG_BUS_SHIFT_2,
.flags = OMAP_I2C_FLAG_BUS_SHIFT_2,
};
static struct omap_hwmod_irq_info i2c3_mpu_irqs[] = {
......
......@@ -1529,8 +1529,7 @@ static struct omap_hwmod_class omap44xx_i2c_hwmod_class = {
};
static struct omap_i2c_dev_attr i2c_dev_attr = {
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE |
OMAP_I2C_FLAG_RESET_REGS_POSTIDLE,
.flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE,
};
/* i2c1 */
......
......@@ -337,6 +337,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
help
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
tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
depends on (CPM1 || CPM2) && OF_I2C
......
......@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.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_DAVINCI) += i2c-davinci.o
obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o
......
This diff is collapsed.
/*
* 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");
......@@ -184,7 +184,11 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
bit_data->data = pdata;
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->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
adap->dev.parent = &pdev->dev;
......
......@@ -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)
{
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)
......
......@@ -435,13 +435,6 @@ static int read_i2c(struct nmk_i2c_dev *dev, u16 flags)
timeout = wait_for_completion_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) {
/* Controller timed out */
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(
&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) {
/* Controller timed out */
dev_err(&dev->adev->dev, "write to slave 0x%x timed out\n",
......
......@@ -4,6 +4,9 @@
*
* 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
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
......@@ -34,6 +37,8 @@ struct ocores_i2c {
int nmsgs;
int state; /* see STATE_ */
int clock_khz;
void (*setreg)(struct ocores_i2c *i2c, int reg, u8 value);
u8 (*getreg)(struct ocores_i2c *i2c, int reg);
};
/* registers */
......@@ -67,24 +72,47 @@ struct ocores_i2c {
#define STATE_READ 3
#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)
{
if (i2c->reg_io_width == 4)
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));
i2c->setreg(i2c, reg, value);
}
static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
{
if (i2c->reg_io_width == 4)
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));
return i2c->getreg(i2c, reg);
}
static void ocores_process(struct ocores_i2c *i2c)
......@@ -223,11 +251,59 @@ static struct i2c_adapter ocores_adapter = {
.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
/* 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,
struct ocores_i2c *i2c)
{
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *match;
u32 val;
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",
&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;
}
#else
......@@ -263,7 +347,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
{
struct ocores_i2c *i2c;
struct ocores_i2c_platform_data *pdata;
struct resource *res, *res2;
struct resource *res;
int irq;
int ret;
int i;
......@@ -271,26 +356,17 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (!res)
return -ENODEV;
res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res2)
return -ENODEV;
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
if (!i2c)
return -ENOMEM;
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), pdev->name)) {
dev_err(&pdev->dev, "Memory region busy\n");
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;
}
i2c->base = devm_request_and_ioremap(&pdev->dev, res);
if (!i2c->base)
return -EADDRNOTAVAIL;
pdata = pdev->dev.platform_data;
if (pdata) {
......@@ -306,10 +382,34 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (i2c->reg_io_width == 0)
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);
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);
if (ret) {
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
#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 = {
.probe = ocores_i2c_probe,
.remove = __devexit_p(ocores_i2c_remove),
......
This diff is collapsed.
......@@ -642,7 +642,7 @@ static int __devinit rcar_i2c_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
priv->io = devm_ioremap(dev, res->start, resource_size(res));
priv->io = devm_request_and_ioremap(dev, res);
if (!priv->io) {
dev_err(dev, "cannot ioremap\n");
return -ENODEV;
......@@ -693,7 +693,7 @@ static int __devexit rcar_i2c_remove(struct platform_device *pdev)
return 0;
}
static struct platform_driver rcar_i2c_drv = {
static struct platform_driver rcar_i2c_driver = {
.driver = {
.name = "i2c-rcar",
.owner = THIS_MODULE,
......@@ -702,7 +702,7 @@ static struct platform_driver rcar_i2c_drv = {
.remove = __devexit_p(rcar_i2c_remove),
};
module_platform_driver(rcar_i2c_drv);
module_platform_driver(rcar_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Renesas R-Car I2C bus driver");
......
This diff is collapsed.
......@@ -120,11 +120,12 @@ struct sh_mobile_i2c_data {
void __iomem *reg;
struct i2c_adapter adap;
unsigned long bus_speed;
unsigned int clks_per_count;
struct clk *clk;
u_int8_t icic;
u_int8_t iccl;
u_int8_t icch;
u_int8_t flags;
u_int16_t iccl;
u_int16_t icch;
spinlock_t lock;
wait_queue_head_t wait;
......@@ -135,7 +136,8 @@ struct sh_mobile_i2c_data {
#define IIC_FLAG_HAS_ICIC67 (1 << 0)
#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
#define STANDARD_MODE 100000
#define FAST_MODE 400000
/* Register offsets */
#define ICDR 0x00
......@@ -187,57 +189,90 @@ static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs,
iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr);
}
static void activate_ch(struct sh_mobile_i2c_data *pd)
static u32 sh_mobile_i2c_iccl(unsigned long count_khz, u32 tLOW, u32 tf, int offset)
{
unsigned long i2c_clk;
u_int32_t num;
u_int32_t denom;
u_int32_t tmp;
/* Wake up device and enable clock */
pm_runtime_get_sync(pd->dev);
clk_enable(pd->clk);
/* Get clock rate after clock is enabled */
i2c_clk = clk_get_rate(pd->clk);
/*
* 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;
}
/* 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.
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.
*/
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);
return (((count_khz * (tHIGH + tf)) + 5000) / 10000) + offset;
}
/* 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;
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;
}
/* 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);
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->icch = (u_int8_t)(num/denom);
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->flags & IIC_FLAG_HAS_ICIC67) {
if ((num/denom) > 0xff)
pd->icic |= ICIC_ICCHB8;
else
pd->icic &= ~ICIC_ICCHB8;
}
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)
{
/* Wake up device and enable clock */
pm_runtime_get_sync(pd->dev);
clk_enable(pd->clk);
/* Enable channel and configure rx ack */
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);
/* Set the clock */
iic_wr(pd, ICCL, pd->iccl);
iic_wr(pd, ICCH, pd->icch);
iic_wr(pd, ICCL, pd->iccl & 0xff);
iic_wr(pd, ICCH, pd->icch & 0xff);
}
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);
}
/* defeat write posting to avoid spurious WAIT interrupts */
iic_rd(pd, ICSR);
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);
/* Set the clock */
iic_wr(pd, ICCL, pd->iccl);
iic_wr(pd, ICCH, pd->icch);
iic_wr(pd, ICCL, pd->iccl & 0xff);
iic_wr(pd, ICCH, pd->icch & 0xff);
pd->msg = usr_msg;
pd->pos = -1;
......@@ -621,10 +659,13 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
goto err_irq;
}
/* Use platformd data bus speed or NORMAL_SPEED */
pd->bus_speed = NORMAL_SPEED;
/* Use platform data bus speed or STANDARD_MODE */
pd->bus_speed = STANDARD_MODE;
if (pdata && 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
* come with two new bits in ICIC.
......@@ -632,6 +673,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
if (size > 0x17)
pd->flags |= IIC_FLAG_HAS_ICIC67;
sh_mobile_i2c_init(pd);
/* Enable Runtime PM for this device.
*
* 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;
}
dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
adap->nr, pd->bus_speed);
dev_info(&dev->dev,
"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);
return 0;
......
......@@ -16,6 +16,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_i2c.h>
#include <linux/of_gpio.h>
struct gpiomux {
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);
}
#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)
{
struct gpiomux *mux;
struct i2c_mux_gpio_platform_data *pdata;
struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state, gpio_base;
int i, ret;
pdata = pdev->dev.platform_data;
if (!pdata) {
dev_err(&pdev->dev, "Missing platform data\n");
return -ENODEV;
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
dev_err(&pdev->dev, "Cannot allocate gpiomux structure");
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
* relative to its base GPIO number. Otherwise they are absolute.
*/
if (pdata->gpio_chip) {
if (mux->data.gpio_chip) {
struct gpio_chip *gpio;
gpio = gpiochip_find(pdata->gpio_chip,
gpio = gpiochip_find(mux->data.gpio_chip,
match_gpio_chip_by_label);
if (!gpio)
return -EPROBE_DEFER;
......@@ -89,49 +172,44 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
gpio_base = 0;
}
parent = i2c_get_adapter(pdata->parent);
parent = i2c_get_adapter(mux->data.parent);
if (!parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
pdata->parent);
mux->data.parent);
return -ENODEV;
}
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
ret = -ENOMEM;
goto alloc_failed;
}
mux->parent = parent;
mux->data = *pdata;
mux->gpio_base = gpio_base;
mux->adap = devm_kzalloc(&pdev->dev,
sizeof(*mux->adap) * pdata->n_values,
sizeof(*mux->adap) * mux->data.n_values,
GFP_KERNEL);
if (!mux->adap) {
dev_err(&pdev->dev, "Cannot allocate i2c_adapter structure");
ret = -ENOMEM;
goto alloc_failed;
}
if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = pdata->idle;
if (mux->data.idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = mux->data.idle;
deselect = i2c_mux_gpio_deselect;
} else {
initial_state = pdata->values[0];
initial_state = mux->data.values[0];
deselect = NULL;
}
for (i = 0; i < pdata->n_gpios; i++) {
ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio");
for (i = 0; i < mux->data.n_gpios; i++) {
ret = gpio_request(gpio_base + mux->data.gpios[i], "i2c-mux-gpio");
if (ret)
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));
}
for (i = 0; i < pdata->n_values; i++) {
u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
unsigned int class = pdata->classes ? pdata->classes[i] : 0;
for (i = 0; i < mux->data.n_values; i++) {
u32 nr = mux->data.base_nr ? (mux->data.base_nr + 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,
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",
pdata->n_values, parent->name);
platform_set_drvdata(pdev, mux);
mux->data.n_values, parent->name);
return 0;
add_adapter_failed:
for (; i > 0; i--)
i2c_del_mux_adapter(mux->adap[i - 1]);
i = pdata->n_gpios;
i = mux->data.n_gpios;
err_request_gpio:
for (; i > 0; i--)
gpio_free(gpio_base + pdata->gpios[i - 1]);
gpio_free(gpio_base + mux->data.gpios[i - 1]);
alloc_failed:
i2c_put_adapter(parent);
......@@ -180,12 +256,19 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
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 = {
.probe = i2c_mux_gpio_probe,
.remove = __devexit_p(i2c_mux_gpio_remove),
.driver = {
.owner = THIS_MODULE,
.name = "i2c-mux-gpio",
.of_match_table = of_match_ptr(i2c_mux_gpio_of_match),
},
};
......
......@@ -20,8 +20,6 @@
#define OMAP_I2C_FLAG_NO_FIFO BIT(0)
#define OMAP_I2C_FLAG_SIMPLE_CLOCK BIT(1)
#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_FORCE_19200_INT_CLK BIT(6)
/* how the CPU address bus must be translated for I2C unit access */
......
......@@ -5,6 +5,7 @@
struct i2c_sh_mobile_platform_data {
unsigned long bus_speed;
unsigned int clks_per_count;
};
#endif /* __I2C_SH_MOBILE_H__ */
/*
* 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment