Root/target/linux/cns3xxx/patches/050-cns3xxx_i2c_controller.patch

1--- a/drivers/i2c/busses/Kconfig
2+++ b/drivers/i2c/busses/Kconfig
3@@ -327,6 +327,18 @@ config I2C_BLACKFIN_TWI_CLK_KHZ
4     help
5       The unit of the TWI clock is kHz.
6 
7+config I2C_CNS3XXX
8+ tristate "Cavium CNS3xxx I2C driver"
9+ depends on ARCH_CNS3XXX
10+ help
11+ Support for Cavium CNS3xxx I2C controller driver.
12+
13+ This driver can also be built as a module. If so, the module
14+ will be called i2c-cns3xxx.
15+
16+ Please note that this driver might be needed to bring up other
17+ devices such as Cavium CNS3xxx Ethernet.
18+
19 config I2C_CPM
20     tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
21     depends on (CPM1 || CPM2) && OF_I2C
22--- a/drivers/i2c/busses/Makefile
23+++ b/drivers/i2c/busses/Makefile
24@@ -80,6 +80,7 @@ obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor
25 obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
26 obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
27 obj-$(CONFIG_I2C_STUB) += i2c-stub.o
28+obj-$(CONFIG_I2C_CNS3XXX) += i2c-cns3xxx.o
29 obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
30 obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
31 
32--- /dev/null
33+++ b/drivers/i2c/busses/i2c-cns3xxx.c
34@@ -0,0 +1,387 @@
35+/*
36+ * Cavium CNS3xxx I2C Host Controller
37+ *
38+ * Copyright 2010 Cavium Network
39+ * Copyright 2011 Gateworks Corporation
40+ * Chris Lang <clang@gateworks.com>
41+ *
42+ * This file is free software; you can redistribute it and/or modify
43+ * it under the terms of the GNU General Public License, Version 2, as
44+ * published by the Free Software Foundation.
45+ */
46+
47+#include <linux/kernel.h>
48+#include <linux/module.h>
49+#include <linux/init.h>
50+#include <linux/platform_device.h>
51+#include <asm/io.h>
52+#include <linux/wait.h>
53+#include <linux/interrupt.h>
54+#include <linux/delay.h>
55+#include <linux/i2c.h>
56+#include <linux/slab.h>
57+#include <mach/pm.h>
58+#include <mach/cns3xxx.h>
59+
60+/*
61+ * We need the memory map
62+ */
63+
64+
65+#define MISC_MEM_MAP_VALUE(reg_offset) (*((uint32_t volatile *)(CNS3XXX_MISC_BASE_VIRT + reg_offset)))
66+#define MISC_IOCDB_CTRL MISC_MEM_MAP_VALUE(0x020)
67+
68+#define I2C_MEM_MAP_ADDR(x) (CNS3XXX_SSP_BASE_VIRT + x)
69+#define I2C_MEM_MAP_VALUE(x) (*((unsigned int volatile*)I2C_MEM_MAP_ADDR(x)))
70+
71+#define I2C_CONTROLLER_REG I2C_MEM_MAP_VALUE(0x20)
72+#define I2C_TIME_OUT_REG I2C_MEM_MAP_VALUE(0x24)
73+#define I2C_SLAVE_ADDRESS_REG I2C_MEM_MAP_VALUE(0x28)
74+#define I2C_WRITE_DATA_REG I2C_MEM_MAP_VALUE(0x2C)
75+#define I2C_READ_DATA_REG I2C_MEM_MAP_VALUE(0x30)
76+#define I2C_INTERRUPT_STATUS_REG I2C_MEM_MAP_VALUE(0x34)
77+#define I2C_INTERRUPT_ENABLE_REG I2C_MEM_MAP_VALUE(0x38)
78+#define I2C_TWI_OUT_DLY_REG I2C_MEM_MAP_VALUE(0x3C)
79+
80+#define I2C_BUS_ERROR_FLAG (0x1)
81+#define I2C_ACTION_DONE_FLAG (0x2)
82+
83+#define CNS3xxx_I2C_ENABLE() (I2C_CONTROLLER_REG) |= ((unsigned int)0x1 << 31)
84+#define CNS3xxx_I2C_DISABLE() (I2C_CONTROLLER_REG) &= ~((unsigned int)0x1 << 31)
85+#define CNS3xxx_I2C_ENABLE_INTR() (I2C_INTERRUPT_ENABLE_REG) |= 0x03
86+#define CNS3xxx_I2C_DISABLE_INTR() (I2C_INTERRUPT_ENABLE_REG) &= 0xfc
87+
88+#define TWI_TIMEOUT (10*HZ)
89+#define I2C_100KHZ 100000
90+#define I2C_200KHZ 200000
91+#define I2C_300KHZ 300000
92+#define I2C_400KHZ 400000
93+
94+#define CNS3xxx_I2C_CLK I2C_100KHZ
95+
96+#define STATE_DONE 1
97+#define STATE_ERROR 2
98+
99+struct cns3xxx_i2c {
100+ void __iomem *base;
101+ wait_queue_head_t wait;
102+ struct i2c_adapter adap;
103+ struct i2c_msg *msg;
104+ int state; /* see STATE_ */
105+ int rd_wr_len;
106+ u8 *buf;
107+};
108+
109+static u32 cns3xxx_i2c_func(struct i2c_adapter *adap)
110+{
111+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
112+}
113+
114+static int
115+cns3xxx_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg)
116+{
117+ struct cns3xxx_i2c *i2c = i2c_get_adapdata(adap);
118+ int i, j;
119+ u8 buf[1] = { 0 };
120+
121+ if (msg->len == 0) {
122+ /*
123+ * We are probably doing a probe for a device here,
124+ * so set the length to one, and data to 0
125+ */
126+ msg->len = 1;
127+ i2c->buf = buf;
128+ } else {
129+ i2c->buf = msg->buf;
130+ }
131+
132+ if (msg->flags & I2C_M_TEN) {
133+ printk
134+ ("%s:%d: Presently the driver does not handle extended addressing\n",
135+ __FUNCTION__, __LINE__);
136+ return -EINVAL;
137+ }
138+ i2c->msg = msg;
139+
140+ for (i = 0; i < msg->len; i++) {
141+ if (msg->len - i >= 4)
142+ i2c->rd_wr_len = 3;
143+ else
144+ i2c->rd_wr_len = msg->len - i - 1;
145+
146+ // Set Data Width and TWI_EN
147+ I2C_CONTROLLER_REG = 0x80000000 | (i2c->rd_wr_len << 2) | (i2c->rd_wr_len);
148+
149+ // Clear Write Reg
150+ I2C_WRITE_DATA_REG = 0;
151+
152+ // Set the slave address
153+ I2C_SLAVE_ADDRESS_REG = (msg->addr << 1);
154+
155+ // Are we Writing
156+ if (!(msg->flags & I2C_M_RD)) {
157+ I2C_CONTROLLER_REG |= (1 << 4);
158+ if (i != 0) {
159+ /*
160+ * We need to set the address in the first byte.
161+ * The base address is going to be in buf[0] and then
162+ * it needs to be incremented by i - 1.
163+ */
164+ i2c->buf--;
165+ *i2c->buf = buf[0] + i - 1;
166+
167+ if (i2c->rd_wr_len < 3) {
168+ i += i2c->rd_wr_len;
169+ i2c->rd_wr_len++;
170+ I2C_CONTROLLER_REG = 0x80000000 | (1 << 4) | (i2c->rd_wr_len << 2) | (i2c->rd_wr_len);
171+ } else {
172+ i += i2c->rd_wr_len - 1;
173+ }
174+ } else {
175+ i += i2c->rd_wr_len;
176+ buf[0] = *i2c->buf;
177+ }
178+ for (j = 0; j <= i2c->rd_wr_len; j++) {
179+ I2C_WRITE_DATA_REG |= ((*i2c->buf++) << (8 * j));
180+ }
181+ } else {
182+ i += i2c->rd_wr_len;
183+ }
184+
185+ // Start the Transfer
186+ i2c->state = 0; // Clear out the State
187+ I2C_CONTROLLER_REG |= (1 << 6);
188+
189+ if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
190+ (i2c->state == STATE_DONE), TWI_TIMEOUT)) {
191+ if (i2c->state == STATE_ERROR) {
192+ return -EIO;
193+ }
194+ } else {
195+ return -ETIMEDOUT;
196+ }
197+ }
198+ return 0;
199+}
200+
201+static int
202+cns3xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
203+{
204+ int i;
205+ int ret;
206+ for (i = 0; i < num; i++)
207+ {
208+ ret = cns3xxx_i2c_xfer_msg(adap, &msgs[i]);
209+ if (ret < 0) {
210+ return ret;
211+ }
212+ }
213+ return num;
214+}
215+
216+
217+static struct i2c_algorithm cns3xxx_i2c_algo = {
218+ .master_xfer = cns3xxx_i2c_xfer,
219+ .functionality = cns3xxx_i2c_func,
220+};
221+
222+static struct i2c_adapter cns3xxx_i2c_adapter = {
223+ .owner = THIS_MODULE,
224+ .algo = &cns3xxx_i2c_algo,
225+ .algo_data = NULL,
226+ .nr = 0,
227+ .name = "CNS3xxx I2C 0",
228+ .retries = 5,
229+};
230+
231+static void cns3xxx_i2c_adapter_init(struct cns3xxx_i2c *i2c)
232+{
233+ cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
234+ cns3xxx_pwr_power_up(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
235+ cns3xxx_pwr_soft_rst(1 << PM_CLK_GATE_REG_OFFSET_SPI_PCM_I2C);
236+
237+ /* Disable the I2C */
238+ I2C_CONTROLLER_REG = 0; /* Disabled the I2C */
239+
240+ //enable SCL and SDA which share pin with GPIOB_PIN_EN(0x18)
241+ //GPIOB[12]: SCL
242+ //GPIOB[13]: SDA
243+ (*(u32*)(CNS3XXX_MISC_BASE_VIRT+0x18)) |= ((1<<12)|(1<<13));
244+
245+ MISC_IOCDB_CTRL &= ~0x300;
246+ MISC_IOCDB_CTRL |= 0x300; //21mA...
247+
248+ /* Check the Reg Dump when testing */
249+ I2C_TIME_OUT_REG =
250+ ((((((cns3xxx_cpu_clock()*(1000000/8)) / (2 * CNS3xxx_I2C_CLK)) -
251+ 1) & 0x3FF) << 8) | (1 << 7) | 0x7F);
252+ I2C_TWI_OUT_DLY_REG |= 0x3;
253+
254+ /* Enable The Interrupt */
255+ CNS3xxx_I2C_ENABLE_INTR();
256+
257+ /* Clear Interrupt Status (0x2 | 0x1) */
258+ I2C_INTERRUPT_STATUS_REG |= (I2C_ACTION_DONE_FLAG | I2C_BUS_ERROR_FLAG);
259+
260+ /* Enable the I2C Controller */
261+ CNS3xxx_I2C_ENABLE();
262+}
263+
264+static irqreturn_t cns3xxx_i2c_isr(int irq, void *dev_id)
265+{
266+ struct cns3xxx_i2c *i2c = dev_id;
267+ int i;
268+ uint32_t stat = I2C_INTERRUPT_STATUS_REG;
269+
270+ /* Clear Interrupt */
271+ I2C_INTERRUPT_STATUS_REG |= 0x1;
272+
273+ if (stat & I2C_BUS_ERROR_FLAG) {
274+ i2c->state = STATE_ERROR;
275+ } else {
276+ if (i2c->msg->flags & I2C_M_RD) {
277+ for (i = 0; i <= i2c->rd_wr_len; i++)
278+ {
279+ *i2c->buf++ = ((I2C_READ_DATA_REG >> (8 * i)) & 0xff);
280+ }
281+ }
282+ i2c->state = STATE_DONE;
283+ }
284+ wake_up(&i2c->wait);
285+ return IRQ_HANDLED;
286+}
287+
288+static int __devinit cns3xxx_i2c_probe(struct platform_device *pdev)
289+{
290+ struct cns3xxx_i2c *i2c;
291+ struct resource *res, *res2;
292+ int ret;
293+
294+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
295+ if (!res) {
296+ printk("%s: IORESOURCE_MEM not defined \n", __FUNCTION__);
297+ return -ENODEV;
298+ }
299+
300+ res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
301+ if (!res2) {
302+ printk("%s: IORESOURCE_IRQ not defined \n", __FUNCTION__);
303+ return -ENODEV;
304+ }
305+
306+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
307+ if (!i2c)
308+ return -ENOMEM;
309+
310+ if (!request_mem_region(res->start, res->end - res->start + 1,
311+ pdev->name)) {
312+ dev_err(&pdev->dev, "Memory region busy\n");
313+ ret = -EBUSY;
314+ goto request_mem_failed;
315+ }
316+
317+ i2c->base = ioremap(res->start, res->end - res->start + 1);
318+ if (!i2c->base) {
319+ dev_err(&pdev->dev, "Unable to map registers\n");
320+ ret = -EIO;
321+ goto map_failed;
322+ }
323+
324+ cns3xxx_i2c_adapter_init(i2c);
325+
326+ init_waitqueue_head(&i2c->wait);
327+ ret = request_irq(res2->start, cns3xxx_i2c_isr, 0, pdev->name, i2c);
328+ if (ret) {
329+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
330+ goto request_irq_failed;
331+ }
332+
333+ platform_set_drvdata(pdev, i2c);
334+ i2c->adap = cns3xxx_i2c_adapter;
335+ i2c_set_adapdata(&i2c->adap, i2c);
336+ i2c->adap.dev.parent = &pdev->dev;
337+
338+ /* add i2c adapter to i2c tree */
339+ ret = i2c_add_numbered_adapter(&i2c->adap);
340+ if (ret) {
341+ dev_err(&pdev->dev, "Failed to add adapter\n");
342+ goto add_adapter_failed;
343+ }
344+
345+ return 0;
346+
347+ add_adapter_failed:
348+ free_irq(res2->start, i2c);
349+ request_irq_failed:
350+ iounmap(i2c->base);
351+ map_failed:
352+ release_mem_region(res->start, res->end - res->start + 1);
353+ request_mem_failed:
354+ kfree(i2c);
355+
356+ return ret;
357+}
358+
359+static int __devexit cns3xxx_i2c_remove(struct platform_device *pdev)
360+{
361+ struct cns3xxx_i2c *i2c = platform_get_drvdata(pdev);
362+ struct resource *res;
363+
364+ /* disable i2c logic */
365+ CNS3xxx_I2C_DISABLE_INTR();
366+ CNS3xxx_I2C_DISABLE();
367+ /* remove adapter & data */
368+ i2c_del_adapter(&i2c->adap);
369+ platform_set_drvdata(pdev, NULL);
370+
371+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
372+ if (res)
373+ free_irq(res->start, i2c);
374+
375+ iounmap(i2c->base);
376+
377+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
378+ if (res)
379+ release_mem_region(res->start, res->end - res->start + 1);
380+
381+ kfree(i2c);
382+
383+ return 0;
384+}
385+
386+#ifdef CONFIG_PM
387+#warning "CONFIG_PM defined: suspend and resume not implemented"
388+#define cns3xxx_i2c_suspend NULL
389+#define cns3xxx_i2c_resume NULL
390+#else
391+#define cns3xxx_i2c_suspend NULL
392+#define cns3xxx_i2c_resume NULL
393+#endif
394+
395+static struct platform_driver cns3xxx_i2c_driver = {
396+ .probe = cns3xxx_i2c_probe,
397+ .remove = cns3xxx_i2c_remove,
398+ .suspend = cns3xxx_i2c_suspend,
399+ .resume = cns3xxx_i2c_resume,
400+ .driver = {
401+ .owner = THIS_MODULE,
402+ .name = "cns3xxx-i2c",
403+ },
404+};
405+
406+static int __init cns3xxx_i2c_init(void)
407+{
408+ return platform_driver_register(&cns3xxx_i2c_driver);
409+}
410+
411+static void __exit cns3xxx_i2c_exit(void)
412+{
413+ platform_driver_unregister(&cns3xxx_i2c_driver);
414+}
415+
416+module_init(cns3xxx_i2c_init);
417+module_exit(cns3xxx_i2c_exit);
418+
419+MODULE_AUTHOR("Cavium Networks");
420+MODULE_DESCRIPTION("Cavium CNS3XXX I2C Controller");
421+MODULE_LICENSE("GPL");
422

Archive Download this file



interactive