aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt27
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c42
-rw-r--r--drivers/i2c/busses/Kconfig10
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-cbus-gpio.c300
-rw-r--r--include/linux/platform_data/i2c-cbus-gpio.h27
6 files changed, 407 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
new file mode 100644
index 000000000000..8ce9cd2855b5
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
@@ -0,0 +1,27 @@
1Device tree bindings for i2c-cbus-gpio driver
2
3Required properties:
4 - compatible = "i2c-cbus-gpio";
5 - gpios: clk, dat, sel
6 - #address-cells = <1>;
7 - #size-cells = <0>;
8
9Optional properties:
10 - child nodes conforming to i2c bus binding
11
12Example:
13
14i2c@0 {
15 compatible = "i2c-cbus-gpio";
16 gpios = <&gpio 66 0 /* clk */
17 &gpio 65 0 /* dat */
18 &gpio 64 0 /* sel */
19 >;
20 #address-cells = <1>;
21 #size-cells = <0>;
22
23 retu-mfd: retu@1 {
24 compatible = "retu-mfd";
25 reg = <0x1>;
26 };
27};
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index d95f727ca39a..bbfd74263c42 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -16,10 +16,12 @@
16#include <linux/gpio.h> 16#include <linux/gpio.h>
17#include <linux/init.h> 17#include <linux/init.h>
18#include <linux/io.h> 18#include <linux/io.h>
19#include <linux/irq.h>
19#include <linux/stddef.h> 20#include <linux/stddef.h>
20#include <linux/i2c.h> 21#include <linux/i2c.h>
21#include <linux/spi/spi.h> 22#include <linux/spi/spi.h>
22#include <linux/usb/musb.h> 23#include <linux/usb/musb.h>
24#include <linux/platform_data/i2c-cbus-gpio.h>
23#include <linux/platform_data/spi-omap2-mcspi.h> 25#include <linux/platform_data/spi-omap2-mcspi.h>
24#include <linux/platform_data/mtd-onenand-omap2.h> 26#include <linux/platform_data/mtd-onenand-omap2.h>
25#include <sound/tlv320aic3x.h> 27#include <sound/tlv320aic3x.h>
@@ -39,6 +41,45 @@
39#define TUSB6010_GPIO_ENABLE 0 41#define TUSB6010_GPIO_ENABLE 0
40#define TUSB6010_DMACHAN 0x3f 42#define TUSB6010_DMACHAN 0x3f
41 43
44#if defined(CONFIG_I2C_CBUS_GPIO) || defined(CONFIG_I2C_CBUS_GPIO_MODULE)
45static struct i2c_cbus_platform_data n8x0_cbus_data = {
46 .clk_gpio = 66,
47 .dat_gpio = 65,
48 .sel_gpio = 64,
49};
50
51static struct platform_device n8x0_cbus_device = {
52 .name = "i2c-cbus-gpio",
53 .id = 3,
54 .dev = {
55 .platform_data = &n8x0_cbus_data,
56 },
57};
58
59static struct i2c_board_info n8x0_i2c_board_info_3[] __initdata = {
60 {
61 I2C_BOARD_INFO("retu-mfd", 0x01),
62 },
63};
64
65static void __init n8x0_cbus_init(void)
66{
67 const int retu_irq_gpio = 108;
68
69 if (gpio_request_one(retu_irq_gpio, GPIOF_IN, "Retu IRQ"))
70 return;
71 irq_set_irq_type(gpio_to_irq(retu_irq_gpio), IRQ_TYPE_EDGE_RISING);
72 n8x0_i2c_board_info_3[0].irq = gpio_to_irq(retu_irq_gpio);
73 i2c_register_board_info(3, n8x0_i2c_board_info_3,
74 ARRAY_SIZE(n8x0_i2c_board_info_3));
75 platform_device_register(&n8x0_cbus_device);
76}
77#else /* CONFIG_I2C_CBUS_GPIO */
78static void __init n8x0_cbus_init(void)
79{
80}
81#endif /* CONFIG_I2C_CBUS_GPIO */
82
42#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE) 83#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
43/* 84/*
44 * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and 85 * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
@@ -677,6 +718,7 @@ static void __init n8x0_init_machine(void)
677 gpmc_onenand_init(board_onenand_data); 718 gpmc_onenand_init(board_onenand_data);
678 n8x0_mmc_init(); 719 n8x0_mmc_init();
679 n8x0_usb_init(); 720 n8x0_usb_init();
721 n8x0_cbus_init();
680} 722}
681 723
682MACHINE_START(NOKIA_N800, "Nokia N800") 724MACHINE_START(NOKIA_N800, "Nokia N800")
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index e9df4612b7eb..e949edf644d4 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -337,6 +337,16 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
337 help 337 help
338 The unit of the TWI clock is kHz. 338 The unit of the TWI clock is kHz.
339 339
340config I2C_CBUS_GPIO
341 tristate "CBUS I2C driver"
342 depends on GENERIC_GPIO
343 help
344 Support for CBUS access using I2C API. Mostly relevant for Nokia
345 Internet Tablets (770, N800 and N810).
346
347 This driver can also be built as a module. If so, the module
348 will be called i2c-cbus-gpio.
349
340config I2C_CPM 350config I2C_CPM
341 tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" 351 tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
342 depends on (CPM1 || CPM2) && OF_I2C 352 depends on (CPM1 || CPM2) && OF_I2C
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 395b516ffa08..f9e3e0b5c827 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o
31obj-$(CONFIG_I2C_AT91) += i2c-at91.o 31obj-$(CONFIG_I2C_AT91) += i2c-at91.o
32obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o 32obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
33obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o 33obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
34obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o
34obj-$(CONFIG_I2C_CPM) += i2c-cpm.o 35obj-$(CONFIG_I2C_CPM) += i2c-cpm.o
35obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o 36obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o
36obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o 37obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o
diff --git a/drivers/i2c/busses/i2c-cbus-gpio.c b/drivers/i2c/busses/i2c-cbus-gpio.c
new file mode 100644
index 000000000000..98386d659318
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cbus-gpio.c
@@ -0,0 +1,300 @@
1/*
2 * CBUS I2C driver for Nokia Internet Tablets.
3 *
4 * Copyright (C) 2004-2010 Nokia Corporation
5 *
6 * Based on code written by Juha Yrjölä, David Weinehall, Mikko Ylinen and
7 * Felipe Balbi. Converted to I2C driver by Aaro Koskinen.
8 *
9 * This file is subject to the terms and conditions of the GNU General
10 * Public License. See the file "COPYING" in the main directory of this
11 * archive for more details.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/io.h>
20#include <linux/i2c.h>
21#include <linux/gpio.h>
22#include <linux/init.h>
23#include <linux/slab.h>
24#include <linux/delay.h>
25#include <linux/errno.h>
26#include <linux/kernel.h>
27#include <linux/module.h>
28#include <linux/of_gpio.h>
29#include <linux/interrupt.h>
30#include <linux/platform_device.h>
31#include <linux/platform_data/i2c-cbus-gpio.h>
32
33/*
34 * Bit counts are derived from Nokia implementation. These should be checked
35 * if other CBUS implementations appear.
36 */
37#define CBUS_ADDR_BITS 3
38#define CBUS_REG_BITS 5
39
40struct cbus_host {
41 spinlock_t lock; /* host lock */
42 struct device *dev;
43 int clk_gpio;
44 int dat_gpio;
45 int sel_gpio;
46};
47
48/**
49 * cbus_send_bit - sends one bit over the bus
50 * @host: the host we're using
51 * @bit: one bit of information to send
52 */
53static void cbus_send_bit(struct cbus_host *host, unsigned bit)
54{
55 gpio_set_value(host->dat_gpio, bit ? 1 : 0);
56 gpio_set_value(host->clk_gpio, 1);
57 gpio_set_value(host->clk_gpio, 0);
58}
59
60/**
61 * cbus_send_data - sends @len amount of data over the bus
62 * @host: the host we're using
63 * @data: the data to send
64 * @len: size of the transfer
65 */
66static void cbus_send_data(struct cbus_host *host, unsigned data, unsigned len)
67{
68 int i;
69
70 for (i = len; i > 0; i--)
71 cbus_send_bit(host, data & (1 << (i - 1)));
72}
73
74/**
75 * cbus_receive_bit - receives one bit from the bus
76 * @host: the host we're using
77 */
78static int cbus_receive_bit(struct cbus_host *host)
79{
80 int ret;
81
82 gpio_set_value(host->clk_gpio, 1);
83 ret = gpio_get_value(host->dat_gpio);
84 gpio_set_value(host->clk_gpio, 0);
85 return ret;
86}
87
88/**
89 * cbus_receive_word - receives 16-bit word from the bus
90 * @host: the host we're using
91 */
92static int cbus_receive_word(struct cbus_host *host)
93{
94 int ret = 0;
95 int i;
96
97 for (i = 16; i > 0; i--) {
98 int bit = cbus_receive_bit(host);
99
100 if (bit < 0)
101 return bit;
102
103 if (bit)
104 ret |= 1 << (i - 1);
105 }
106 return ret;
107}
108
109/**
110 * cbus_transfer - transfers data over the bus
111 * @host: the host we're using
112 * @rw: read/write flag
113 * @dev: device address
114 * @reg: register address
115 * @data: if @rw == I2C_SBUS_WRITE data to send otherwise 0
116 */
117static int cbus_transfer(struct cbus_host *host, char rw, unsigned dev,
118 unsigned reg, unsigned data)
119{
120 unsigned long flags;
121 int ret;
122
123 /* We don't want interrupts disturbing our transfer */
124 spin_lock_irqsave(&host->lock, flags);
125
126 /* Reset state and start of transfer, SEL stays down during transfer */
127 gpio_set_value(host->sel_gpio, 0);
128
129 /* Set the DAT pin to output */
130 gpio_direction_output(host->dat_gpio, 1);
131
132 /* Send the device address */
133 cbus_send_data(host, dev, CBUS_ADDR_BITS);
134
135 /* Send the rw flag */
136 cbus_send_bit(host, rw == I2C_SMBUS_READ);
137
138 /* Send the register address */
139 cbus_send_data(host, reg, CBUS_REG_BITS);
140
141 if (rw == I2C_SMBUS_WRITE) {
142 cbus_send_data(host, data, 16);
143 ret = 0;
144 } else {
145 ret = gpio_direction_input(host->dat_gpio);
146 if (ret) {
147 dev_dbg(host->dev, "failed setting direction\n");
148 goto out;
149 }
150 gpio_set_value(host->clk_gpio, 1);
151
152 ret = cbus_receive_word(host);
153 if (ret < 0) {
154 dev_dbg(host->dev, "failed receiving data\n");
155 goto out;
156 }
157 }
158
159 /* Indicate end of transfer, SEL goes up until next transfer */
160 gpio_set_value(host->sel_gpio, 1);
161 gpio_set_value(host->clk_gpio, 1);
162 gpio_set_value(host->clk_gpio, 0);
163
164out:
165 spin_unlock_irqrestore(&host->lock, flags);
166
167 return ret;
168}
169
170static int cbus_i2c_smbus_xfer(struct i2c_adapter *adapter,
171 u16 addr,
172 unsigned short flags,
173 char read_write,
174 u8 command,
175 int size,
176 union i2c_smbus_data *data)
177{
178 struct cbus_host *chost = i2c_get_adapdata(adapter);
179 int ret;
180
181 if (size != I2C_SMBUS_WORD_DATA)
182 return -EINVAL;
183
184 ret = cbus_transfer(chost, read_write == I2C_SMBUS_READ, addr,
185 command, data->word);
186 if (ret < 0)
187 return ret;
188
189 if (read_write == I2C_SMBUS_READ)
190 data->word = ret;
191
192 return 0;
193}
194
195static u32 cbus_i2c_func(struct i2c_adapter *adapter)
196{
197 return I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
198}
199
200static const struct i2c_algorithm cbus_i2c_algo = {
201 .smbus_xfer = cbus_i2c_smbus_xfer,
202 .functionality = cbus_i2c_func,
203};
204
205static int cbus_i2c_remove(struct platform_device *pdev)
206{
207 struct i2c_adapter *adapter = platform_get_drvdata(pdev);
208
209 return i2c_del_adapter(adapter);
210}
211
212static int cbus_i2c_probe(struct platform_device *pdev)
213{
214 struct i2c_adapter *adapter;
215 struct cbus_host *chost;
216 int ret;
217
218 adapter = devm_kzalloc(&pdev->dev, sizeof(struct i2c_adapter),
219 GFP_KERNEL);
220 if (!adapter)
221 return -ENOMEM;
222
223 chost = devm_kzalloc(&pdev->dev, sizeof(*chost), GFP_KERNEL);
224 if (!chost)
225 return -ENOMEM;
226
227 if (pdev->dev.of_node) {
228 struct device_node *dnode = pdev->dev.of_node;
229 if (of_gpio_count(dnode) != 3)
230 return -ENODEV;
231 chost->clk_gpio = of_get_gpio(dnode, 0);
232 chost->dat_gpio = of_get_gpio(dnode, 1);
233 chost->sel_gpio = of_get_gpio(dnode, 2);
234 } else if (pdev->dev.platform_data) {
235 struct i2c_cbus_platform_data *pdata = pdev->dev.platform_data;
236 chost->clk_gpio = pdata->clk_gpio;
237 chost->dat_gpio = pdata->dat_gpio;
238 chost->sel_gpio = pdata->sel_gpio;
239 } else {
240 return -ENODEV;
241 }
242
243 adapter->owner = THIS_MODULE;
244 adapter->class = I2C_CLASS_HWMON;
245 adapter->dev.parent = &pdev->dev;
246 adapter->nr = pdev->id;
247 adapter->timeout = HZ;
248 adapter->algo = &cbus_i2c_algo;
249 strlcpy(adapter->name, "CBUS I2C adapter", sizeof(adapter->name));
250
251 spin_lock_init(&chost->lock);
252 chost->dev = &pdev->dev;
253
254 ret = devm_gpio_request_one(&pdev->dev, chost->clk_gpio,
255 GPIOF_OUT_INIT_LOW, "CBUS clk");
256 if (ret)
257 return ret;
258
259 ret = devm_gpio_request_one(&pdev->dev, chost->dat_gpio, GPIOF_IN,
260 "CBUS data");
261 if (ret)
262 return ret;
263
264 ret = devm_gpio_request_one(&pdev->dev, chost->sel_gpio,
265 GPIOF_OUT_INIT_HIGH, "CBUS sel");
266 if (ret)
267 return ret;
268
269 i2c_set_adapdata(adapter, chost);
270 platform_set_drvdata(pdev, adapter);
271
272 return i2c_add_numbered_adapter(adapter);
273}
274
275#if defined(CONFIG_OF)
276static const struct of_device_id i2c_cbus_dt_ids[] = {
277 { .compatible = "i2c-cbus-gpio", },
278 { }
279};
280MODULE_DEVICE_TABLE(of, i2c_cbus_dt_ids);
281#endif
282
283static struct platform_driver cbus_i2c_driver = {
284 .probe = cbus_i2c_probe,
285 .remove = cbus_i2c_remove,
286 .driver = {
287 .owner = THIS_MODULE,
288 .name = "i2c-cbus-gpio",
289 },
290};
291module_platform_driver(cbus_i2c_driver);
292
293MODULE_ALIAS("platform:i2c-cbus-gpio");
294MODULE_DESCRIPTION("CBUS I2C driver");
295MODULE_AUTHOR("Juha Yrjölä");
296MODULE_AUTHOR("David Weinehall");
297MODULE_AUTHOR("Mikko Ylinen");
298MODULE_AUTHOR("Felipe Balbi");
299MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
300MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/i2c-cbus-gpio.h b/include/linux/platform_data/i2c-cbus-gpio.h
new file mode 100644
index 000000000000..6faa992a9502
--- /dev/null
+++ b/include/linux/platform_data/i2c-cbus-gpio.h
@@ -0,0 +1,27 @@
1/*
2 * i2c-cbus-gpio.h - CBUS I2C platform_data definition
3 *
4 * Copyright (C) 2004-2009 Nokia Corporation
5 *
6 * Written by Felipe Balbi and Aaro Koskinen.
7 *
8 * This file is subject to the terms and conditions of the GNU General
9 * Public License. See the file "COPYING" in the main directory of this
10 * archive for more details.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#ifndef __INCLUDE_LINUX_I2C_CBUS_GPIO_H
19#define __INCLUDE_LINUX_I2C_CBUS_GPIO_H
20
21struct i2c_cbus_platform_data {
22 int dat_gpio;
23 int clk_gpio;
24 int sel_gpio;
25};
26
27#endif /* __INCLUDE_LINUX_I2C_CBUS_GPIO_H */