aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorTony Prisk <linux@prisktech.co.nz>2013-06-14 17:52:16 -0400
committerWolfram Sang <wsa@the-dreams.de>2013-06-15 07:37:08 -0400
commit560746eb79d3124a278452c8dd968682b521cc82 (patch)
treed27afb9ec1cd900f41bc645001cc3471cf95610e /drivers/i2c
parent38d7fadef4973bb94e36897fcb6bb6a12fdd10c9 (diff)
i2c: vt8500: Add support for I2C bus on Wondermedia SoCs
This patch adds support for the I2C bus controllers found on Wondermedia 8xxx-series SoCs. Only master-mode is supported. Signed-off-by: Tony Prisk <linux@prisktech.co.nz> [wsa: fixed one macro to shift 8 instead of 16] Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/Kconfig10
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-wmt.c479
3 files changed, 490 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 94364d41686f..6582611bfee6 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -714,6 +714,16 @@ config I2C_VERSATILE
714 This driver can also be built as a module. If so, the module 714 This driver can also be built as a module. If so, the module
715 will be called i2c-versatile. 715 will be called i2c-versatile.
716 716
717config I2C_WMT
718 tristate "Wondermedia WM8xxx SoC I2C bus support"
719 depends on ARCH_VT8500
720 help
721 Say yes if you want to support the I2C bus on Wondermedia 8xxx-series
722 SoCs.
723
724 This driver can also be built as a module. If so, the module will be
725 called i2c-wmt.
726
717config I2C_OCTEON 727config I2C_OCTEON
718 tristate "Cavium OCTEON I2C bus support" 728 tristate "Cavium OCTEON I2C bus support"
719 depends on CPU_CAVIUM_OCTEON 729 depends on CPU_CAVIUM_OCTEON
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 3e07dc53eeae..385f99dd1b45 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -70,6 +70,7 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
70obj-$(CONFIG_I2C_STU300) += i2c-stu300.o 70obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
71obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o 71obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
72obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o 72obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
73obj-$(CONFIG_I2C_WMT) += i2c-wmt.o
73obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o 74obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
74obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o 75obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
75obj-$(CONFIG_I2C_XLR) += i2c-xlr.o 76obj-$(CONFIG_I2C_XLR) += i2c-xlr.o
diff --git a/drivers/i2c/busses/i2c-wmt.c b/drivers/i2c/busses/i2c-wmt.c
new file mode 100644
index 000000000000..baaa7d15b73e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-wmt.c
@@ -0,0 +1,479 @@
1/*
2 * Wondermedia I2C Master Mode Driver
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Derived from GPLv2+ licensed source:
7 * - Copyright (C) 2008 WonderMedia Technologies, Inc.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2, or
11 * (at your option) any later version. as published by the Free Software
12 * Foundation
13 */
14
15#include <linux/clk.h>
16#include <linux/delay.h>
17#include <linux/err.h>
18#include <linux/i2c.h>
19#include <linux/interrupt.h>
20#include <linux/io.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/of_i2c.h>
25#include <linux/of_irq.h>
26#include <linux/platform_device.h>
27
28#define REG_CR 0x00
29#define REG_TCR 0x02
30#define REG_CSR 0x04
31#define REG_ISR 0x06
32#define REG_IMR 0x08
33#define REG_CDR 0x0A
34#define REG_TR 0x0C
35#define REG_MCR 0x0E
36#define REG_SLAVE_CR 0x10
37#define REG_SLAVE_SR 0x12
38#define REG_SLAVE_ISR 0x14
39#define REG_SLAVE_IMR 0x16
40#define REG_SLAVE_DR 0x18
41#define REG_SLAVE_TR 0x1A
42
43/* REG_CR Bit fields */
44#define CR_TX_NEXT_ACK 0x0000
45#define CR_ENABLE 0x0001
46#define CR_TX_NEXT_NO_ACK 0x0002
47#define CR_TX_END 0x0004
48#define CR_CPU_RDY 0x0008
49#define SLAV_MODE_SEL 0x8000
50
51/* REG_TCR Bit fields */
52#define TCR_STANDARD_MODE 0x0000
53#define TCR_MASTER_WRITE 0x0000
54#define TCR_HS_MODE 0x2000
55#define TCR_MASTER_READ 0x4000
56#define TCR_FAST_MODE 0x8000
57#define TCR_SLAVE_ADDR_MASK 0x007F
58
59/* REG_ISR Bit fields */
60#define ISR_NACK_ADDR 0x0001
61#define ISR_BYTE_END 0x0002
62#define ISR_SCL_TIMEOUT 0x0004
63#define ISR_WRITE_ALL 0x0007
64
65/* REG_IMR Bit fields */
66#define IMR_ENABLE_ALL 0x0007
67
68/* REG_CSR Bit fields */
69#define CSR_RCV_NOT_ACK 0x0001
70#define CSR_RCV_ACK_MASK 0x0001
71#define CSR_READY_MASK 0x0002
72
73/* REG_TR */
74#define SCL_TIMEOUT(x) (((x) & 0xFF) << 8)
75#define TR_STD 0x0064
76#define TR_HS 0x0019
77
78/* REG_MCR */
79#define MCR_APB_96M 7
80#define MCR_APB_166M 12
81
82#define I2C_MODE_STANDARD 0
83#define I2C_MODE_FAST 1
84
85#define WMT_I2C_TIMEOUT (msecs_to_jiffies(1000))
86
87struct wmt_i2c_dev {
88 struct i2c_adapter adapter;
89 struct completion complete;
90 struct device *dev;
91 void __iomem *base;
92 struct clk *clk;
93 int mode;
94 int irq;
95 u16 cmd_status;
96};
97
98static int wmt_i2c_wait_bus_not_busy(struct wmt_i2c_dev *i2c_dev)
99{
100 unsigned long timeout;
101
102 timeout = jiffies + WMT_I2C_TIMEOUT;
103 while (!(readw(i2c_dev->base + REG_CSR) & CSR_READY_MASK)) {
104 if (time_after(jiffies, timeout)) {
105 dev_warn(i2c_dev->dev, "timeout waiting for bus ready\n");
106 return -EBUSY;
107 }
108 msleep(20);
109 }
110
111 return 0;
112}
113
114static int wmt_check_status(struct wmt_i2c_dev *i2c_dev)
115{
116 int ret = 0;
117
118 if (i2c_dev->cmd_status & ISR_NACK_ADDR)
119 ret = -EIO;
120
121 if (i2c_dev->cmd_status & ISR_SCL_TIMEOUT)
122 ret = -ETIMEDOUT;
123
124 return ret;
125}
126
127static int wmt_i2c_write(struct i2c_adapter *adap, struct i2c_msg *pmsg,
128 int last)
129{
130 struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
131 u16 val, tcr_val;
132 int ret, wait_result;
133 int xfer_len = 0;
134
135 if (!(pmsg->flags & I2C_M_NOSTART)) {
136 ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
137 if (ret < 0)
138 return ret;
139 }
140
141 if (pmsg->len == 0) {
142 /*
143 * We still need to run through the while (..) once, so
144 * start at -1 and break out early from the loop
145 */
146 xfer_len = -1;
147 writew(0, i2c_dev->base + REG_CDR);
148 } else {
149 writew(pmsg->buf[0] & 0xFF, i2c_dev->base + REG_CDR);
150 }
151
152 if (!(pmsg->flags & I2C_M_NOSTART)) {
153 val = readw(i2c_dev->base + REG_CR);
154 val &= ~CR_TX_END;
155 writew(val, i2c_dev->base + REG_CR);
156
157 val = readw(i2c_dev->base + REG_CR);
158 val |= CR_CPU_RDY;
159 writew(val, i2c_dev->base + REG_CR);
160 }
161
162 INIT_COMPLETION(i2c_dev->complete);
163
164 if (i2c_dev->mode == I2C_MODE_STANDARD)
165 tcr_val = TCR_STANDARD_MODE;
166 else
167 tcr_val = TCR_FAST_MODE;
168
169 tcr_val |= (TCR_MASTER_WRITE | (pmsg->addr & TCR_SLAVE_ADDR_MASK));
170
171 writew(tcr_val, i2c_dev->base + REG_TCR);
172
173 if (pmsg->flags & I2C_M_NOSTART) {
174 val = readw(i2c_dev->base + REG_CR);
175 val |= CR_CPU_RDY;
176 writew(val, i2c_dev->base + REG_CR);
177 }
178
179 while (xfer_len < pmsg->len) {
180 wait_result = wait_for_completion_timeout(&i2c_dev->complete,
181 500 * HZ / 1000);
182
183 if (wait_result == 0)
184 return -ETIMEDOUT;
185
186 ret = wmt_check_status(i2c_dev);
187 if (ret)
188 return ret;
189
190 xfer_len++;
191
192 val = readw(i2c_dev->base + REG_CSR);
193 if ((val & CSR_RCV_ACK_MASK) == CSR_RCV_NOT_ACK) {
194 dev_dbg(i2c_dev->dev, "write RCV NACK error\n");
195 return -EIO;
196 }
197
198 if (pmsg->len == 0) {
199 val = CR_TX_END | CR_CPU_RDY | CR_ENABLE;
200 writew(val, i2c_dev->base + REG_CR);
201 break;
202 }
203
204 if (xfer_len == pmsg->len) {
205 if (last != 1)
206 writew(CR_ENABLE, i2c_dev->base + REG_CR);
207 } else {
208 writew(pmsg->buf[xfer_len] & 0xFF, i2c_dev->base +
209 REG_CDR);
210 writew(CR_CPU_RDY | CR_ENABLE, i2c_dev->base + REG_CR);
211 }
212 }
213
214 return 0;
215}
216
217static int wmt_i2c_read(struct i2c_adapter *adap, struct i2c_msg *pmsg,
218 int last)
219{
220 struct wmt_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
221 u16 val, tcr_val;
222 int ret, wait_result;
223 u32 xfer_len = 0;
224
225 if (!(pmsg->flags & I2C_M_NOSTART)) {
226 ret = wmt_i2c_wait_bus_not_busy(i2c_dev);
227 if (ret < 0)
228 return ret;
229 }
230
231 val = readw(i2c_dev->base + REG_CR);
232 val &= ~CR_TX_END;
233 writew(val, i2c_dev->base + REG_CR);
234
235 val = readw(i2c_dev->base + REG_CR);
236 val &= ~CR_TX_NEXT_NO_ACK;
237 writew(val, i2c_dev->base + REG_CR);
238
239 if (!(pmsg->flags & I2C_M_NOSTART)) {
240 val = readw(i2c_dev->base + REG_CR);
241 val |= CR_CPU_RDY;
242 writew(val, i2c_dev->base + REG_CR);
243 }
244
245 if (pmsg->len == 1) {
246 val = readw(i2c_dev->base + REG_CR);
247 val |= CR_TX_NEXT_NO_ACK;
248 writew(val, i2c_dev->base + REG_CR);
249 }
250
251 INIT_COMPLETION(i2c_dev->complete);
252
253 if (i2c_dev->mode == I2C_MODE_STANDARD)
254 tcr_val = TCR_STANDARD_MODE;
255 else
256 tcr_val = TCR_FAST_MODE;
257
258 tcr_val |= TCR_MASTER_READ | (pmsg->addr & TCR_SLAVE_ADDR_MASK);
259
260 writew(tcr_val, i2c_dev->base + REG_TCR);
261
262 if (pmsg->flags & I2C_M_NOSTART) {
263 val = readw(i2c_dev->base + REG_CR);
264 val |= CR_CPU_RDY;
265 writew(val, i2c_dev->base + REG_CR);
266 }
267
268 while (xfer_len < pmsg->len) {
269 wait_result = wait_for_completion_timeout(&i2c_dev->complete,
270 500 * HZ / 1000);
271
272 if (!wait_result)
273 return -ETIMEDOUT;
274
275 ret = wmt_check_status(i2c_dev);
276 if (ret)
277 return ret;
278
279 pmsg->buf[xfer_len] = readw(i2c_dev->base + REG_CDR) >> 8;
280 xfer_len++;
281
282 if (xfer_len == pmsg->len - 1) {
283 val = readw(i2c_dev->base + REG_CR);
284 val |= (CR_TX_NEXT_NO_ACK | CR_CPU_RDY);
285 writew(val, i2c_dev->base + REG_CR);
286 } else {
287 val = readw(i2c_dev->base + REG_CR);
288 val |= CR_CPU_RDY;
289 writew(val, i2c_dev->base + REG_CR);
290 }
291 }
292
293 return 0;
294}
295
296static int wmt_i2c_xfer(struct i2c_adapter *adap,
297 struct i2c_msg msgs[],
298 int num)
299{
300 struct i2c_msg *pmsg;
301 int i, is_last;
302 int ret = 0;
303
304 for (i = 0; ret >= 0 && i < num; i++) {
305 is_last = ((i + 1) == num);
306
307 pmsg = &msgs[i];
308 if (pmsg->flags & I2C_M_RD)
309 ret = wmt_i2c_read(adap, pmsg, is_last);
310 else
311 ret = wmt_i2c_write(adap, pmsg, is_last);
312 }
313
314 return (ret < 0) ? ret : i;
315}
316
317static u32 wmt_i2c_func(struct i2c_adapter *adap)
318{
319 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_NOSTART;
320}
321
322static const struct i2c_algorithm wmt_i2c_algo = {
323 .master_xfer = wmt_i2c_xfer,
324 .functionality = wmt_i2c_func,
325};
326
327static irqreturn_t wmt_i2c_isr(int irq, void *data)
328{
329 struct wmt_i2c_dev *i2c_dev = data;
330
331 /* save the status and write-clear it */
332 i2c_dev->cmd_status = readw(i2c_dev->base + REG_ISR);
333 writew(i2c_dev->cmd_status, i2c_dev->base + REG_ISR);
334
335 complete(&i2c_dev->complete);
336
337 return IRQ_HANDLED;
338}
339
340static int wmt_i2c_reset_hardware(struct wmt_i2c_dev *i2c_dev)
341{
342 int err;
343
344 err = clk_prepare_enable(i2c_dev->clk);
345 if (err) {
346 dev_err(i2c_dev->dev, "failed to enable clock\n");
347 return err;
348 }
349
350 err = clk_set_rate(i2c_dev->clk, 20000000);
351 if (err) {
352 dev_err(i2c_dev->dev, "failed to set clock = 20Mhz\n");
353 return err;
354 }
355
356 writew(0, i2c_dev->base + REG_CR);
357 writew(MCR_APB_166M, i2c_dev->base + REG_MCR);
358 writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
359 writew(IMR_ENABLE_ALL, i2c_dev->base + REG_IMR);
360 writew(CR_ENABLE, i2c_dev->base + REG_CR);
361 readw(i2c_dev->base + REG_CSR); /* read clear */
362 writew(ISR_WRITE_ALL, i2c_dev->base + REG_ISR);
363
364 if (i2c_dev->mode == I2C_MODE_STANDARD)
365 writew(SCL_TIMEOUT(128) | TR_STD, i2c_dev->base + REG_TR);
366 else
367 writew(SCL_TIMEOUT(128) | TR_HS, i2c_dev->base + REG_TR);
368
369 return 0;
370}
371
372static int wmt_i2c_probe(struct platform_device *pdev)
373{
374 struct device_node *np = pdev->dev.of_node;
375 struct wmt_i2c_dev *i2c_dev;
376 struct i2c_adapter *adap;
377 struct resource *res;
378 int err;
379 u32 clk_rate;
380
381 i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
382 if (!i2c_dev) {
383 dev_err(&pdev->dev, "device memory allocation failed\n");
384 return -ENOMEM;
385 }
386
387 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
388 i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
389 if (IS_ERR(i2c_dev->base))
390 return PTR_ERR(i2c_dev->base);
391
392 i2c_dev->irq = irq_of_parse_and_map(np, 0);
393 if (!i2c_dev->irq) {
394 dev_err(&pdev->dev, "irq missing or invalid\n");
395 return -EINVAL;
396 }
397
398 i2c_dev->clk = of_clk_get(np, 0);
399 if (IS_ERR(i2c_dev->clk)) {
400 dev_err(&pdev->dev, "unable to request clock\n");
401 return PTR_ERR(i2c_dev->clk);
402 }
403
404 i2c_dev->mode = I2C_MODE_STANDARD;
405 err = of_property_read_u32(np, "clock-frequency", &clk_rate);
406 if ((!err) && (clk_rate == 400000))
407 i2c_dev->mode = I2C_MODE_FAST;
408
409 i2c_dev->dev = &pdev->dev;
410
411 err = devm_request_irq(&pdev->dev, i2c_dev->irq, wmt_i2c_isr, 0,
412 "i2c", i2c_dev);
413 if (err) {
414 dev_err(&pdev->dev, "failed to request irq %i\n", i2c_dev->irq);
415 return err;
416 }
417
418 adap = &i2c_dev->adapter;
419 i2c_set_adapdata(adap, i2c_dev);
420 strlcpy(adap->name, "WMT I2C adapter", sizeof(adap->name));
421 adap->owner = THIS_MODULE;
422 adap->algo = &wmt_i2c_algo;
423 adap->dev.parent = &pdev->dev;
424 adap->dev.of_node = pdev->dev.of_node;
425
426 init_completion(&i2c_dev->complete);
427
428 err = wmt_i2c_reset_hardware(i2c_dev);
429 if (err) {
430 dev_err(&pdev->dev, "error initializing hardware\n");
431 return err;
432 }
433
434 err = i2c_add_adapter(adap);
435 if (err) {
436 dev_err(&pdev->dev, "failed to add adapter\n");
437 return err;
438 }
439
440 platform_set_drvdata(pdev, i2c_dev);
441
442 of_i2c_register_devices(adap);
443
444 return 0;
445}
446
447static int wmt_i2c_remove(struct platform_device *pdev)
448{
449 struct wmt_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
450
451 /* Disable interrupts, clock and delete adapter */
452 writew(0, i2c_dev->base + REG_IMR);
453 clk_disable_unprepare(i2c_dev->clk);
454 i2c_del_adapter(&i2c_dev->adapter);
455
456 return 0;
457}
458
459static struct of_device_id wmt_i2c_dt_ids[] = {
460 { .compatible = "wm,wm8505-i2c" },
461 { /* Sentinel */ },
462};
463
464static struct platform_driver wmt_i2c_driver = {
465 .probe = wmt_i2c_probe,
466 .remove = wmt_i2c_remove,
467 .driver = {
468 .name = "wmt-i2c",
469 .owner = THIS_MODULE,
470 .of_match_table = wmt_i2c_dt_ids,
471 },
472};
473
474module_platform_driver(wmt_i2c_driver);
475
476MODULE_DESCRIPTION("Wondermedia I2C master-mode bus adapter");
477MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
478MODULE_LICENSE("GPL");
479MODULE_DEVICE_TABLE(of, wmt_i2c_dt_ids);