diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:45:12 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-07 11:45:12 -0400 |
commit | 0e26da0f2200a2fb51844aaa43e365ea9dd5a93d (patch) | |
tree | 73409a696901934da5f6df976c6521d3e50e8749 /drivers/i2c/busses | |
parent | 10a0d912898ac2fe49094acf2c1339d0fb4c2bc6 (diff) | |
parent | 65de394df21f8ccc61525f77b0e4ee6940a0932e (diff) |
Merge branch 'i2c-for-2630-v2' of git://aeryn.fluff.org.uk/bjdooks/linux
* 'i2c-for-2630-v2' of git://aeryn.fluff.org.uk/bjdooks/linux:
i2c: imx: Make disable_delay a per-device variable
i2c: xtensa s6000 i2c driver
powerpc/85xx: i2c-mpc: use new I2C bindings for the Socates board
i2c: i2c-mpc: make I2C bus speed configurable
i2c: i2c-mpc: use dev based printout function
i2c: i2c-mpc: various coding style fixes
i2c: imx: Add missing request_mem_region in probe()
i2c: i2c-s3c2410: Initialise Samsung I2C controller early
i2c-s3c2410: Simplify bus frequency calculation
i2c-s3c2410: sda_delay should be in ns, not clock ticks
i2c: iMX/MXC support
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 20 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 624 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mpc.c | 322 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s3c2410.c | 77 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s6000.c | 407 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-s6000.h | 79 |
7 files changed, 1437 insertions, 94 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index da809ad0996a..94eae5c3cbc7 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -356,6 +356,16 @@ config I2C_IBM_IIC | |||
356 | This driver can also be built as a module. If so, the module | 356 | This driver can also be built as a module. If so, the module |
357 | will be called i2c-ibm_iic. | 357 | will be called i2c-ibm_iic. |
358 | 358 | ||
359 | config I2C_IMX | ||
360 | tristate "IMX I2C interface" | ||
361 | depends on ARCH_MXC | ||
362 | help | ||
363 | Say Y here if you want to use the IIC bus controller on | ||
364 | the Freescale i.MX/MXC processors. | ||
365 | |||
366 | This driver can also be built as a module. If so, the module | ||
367 | will be called i2c-imx. | ||
368 | |||
359 | config I2C_IOP3XX | 369 | config I2C_IOP3XX |
360 | tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" | 370 | tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" |
361 | depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX | 371 | depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX |
@@ -462,6 +472,16 @@ config I2C_S3C2410 | |||
462 | Say Y here to include support for I2C controller in the | 472 | Say Y here to include support for I2C controller in the |
463 | Samsung S3C2410 based System-on-Chip devices. | 473 | Samsung S3C2410 based System-on-Chip devices. |
464 | 474 | ||
475 | config I2C_S6000 | ||
476 | tristate "S6000 I2C support" | ||
477 | depends on XTENSA_VARIANT_S6000 | ||
478 | help | ||
479 | This driver supports the on chip I2C device on the | ||
480 | S6000 xtensa processor family. | ||
481 | |||
482 | To compile this driver as a module, choose M here. The module | ||
483 | will be called i2c-s6000. | ||
484 | |||
465 | config I2C_SH7760 | 485 | config I2C_SH7760 |
466 | tristate "Renesas SH7760 I2C Controller" | 486 | tristate "Renesas SH7760 I2C Controller" |
467 | depends on CPU_SUBTYPE_SH7760 | 487 | depends on CPU_SUBTYPE_SH7760 |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 0c2c4b26cdf1..776acb6403a7 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -33,6 +33,7 @@ obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o | |||
33 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o | 33 | obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o |
34 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o | 34 | obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o |
35 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o | 35 | obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o |
36 | obj-$(CONFIG_I2C_IMX) += i2c-imx.o | ||
36 | obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o | 37 | obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o |
37 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o | 38 | obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o |
38 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o | 39 | obj-$(CONFIG_I2C_MPC) += i2c-mpc.o |
@@ -43,6 +44,7 @@ obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o | |||
43 | obj-$(CONFIG_I2C_PNX) += i2c-pnx.o | 44 | obj-$(CONFIG_I2C_PNX) += i2c-pnx.o |
44 | obj-$(CONFIG_I2C_PXA) += i2c-pxa.o | 45 | obj-$(CONFIG_I2C_PXA) += i2c-pxa.o |
45 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o | 46 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o |
47 | obj-$(CONFIG_I2C_S6000) += i2c-s6000.o | ||
46 | obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o | 48 | obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o |
47 | obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o | 49 | obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o |
48 | obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o | 50 | obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o |
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c new file mode 100644 index 000000000000..0b486a63460d --- /dev/null +++ b/drivers/i2c/busses/i2c-imx.c | |||
@@ -0,0 +1,624 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2002 Motorola GSG-China | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version 2 | ||
7 | * of the License, or (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | ||
17 | * USA. | ||
18 | * | ||
19 | * Author: | ||
20 | * Darius Augulis, Teltonika Inc. | ||
21 | * | ||
22 | * Desc.: | ||
23 | * Implementation of I2C Adapter/Algorithm Driver | ||
24 | * for I2C Bus integrated in Freescale i.MX/MXC processors | ||
25 | * | ||
26 | * Derived from Motorola GSG China I2C example driver | ||
27 | * | ||
28 | * Copyright (C) 2005 Torsten Koschorrek <koschorrek at synertronixx.de | ||
29 | * Copyright (C) 2005 Matthias Blaschke <blaschke at synertronixx.de | ||
30 | * Copyright (C) 2007 RightHand Technologies, Inc. | ||
31 | * Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt> | ||
32 | * | ||
33 | */ | ||
34 | |||
35 | /** Includes ******************************************************************* | ||
36 | *******************************************************************************/ | ||
37 | |||
38 | #include <linux/init.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/module.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/err.h> | ||
43 | #include <linux/interrupt.h> | ||
44 | #include <linux/delay.h> | ||
45 | #include <linux/i2c.h> | ||
46 | #include <linux/io.h> | ||
47 | #include <linux/sched.h> | ||
48 | #include <linux/platform_device.h> | ||
49 | #include <linux/clk.h> | ||
50 | |||
51 | #include <mach/irqs.h> | ||
52 | #include <mach/hardware.h> | ||
53 | #include <mach/i2c.h> | ||
54 | |||
55 | /** Defines ******************************************************************** | ||
56 | *******************************************************************************/ | ||
57 | |||
58 | /* This will be the driver name the kernel reports */ | ||
59 | #define DRIVER_NAME "imx-i2c" | ||
60 | |||
61 | /* Default value */ | ||
62 | #define IMX_I2C_BIT_RATE 100000 /* 100kHz */ | ||
63 | |||
64 | /* IMX I2C registers */ | ||
65 | #define IMX_I2C_IADR 0x00 /* i2c slave address */ | ||
66 | #define IMX_I2C_IFDR 0x04 /* i2c frequency divider */ | ||
67 | #define IMX_I2C_I2CR 0x08 /* i2c control */ | ||
68 | #define IMX_I2C_I2SR 0x0C /* i2c status */ | ||
69 | #define IMX_I2C_I2DR 0x10 /* i2c transfer data */ | ||
70 | |||
71 | /* Bits of IMX I2C registers */ | ||
72 | #define I2SR_RXAK 0x01 | ||
73 | #define I2SR_IIF 0x02 | ||
74 | #define I2SR_SRW 0x04 | ||
75 | #define I2SR_IAL 0x10 | ||
76 | #define I2SR_IBB 0x20 | ||
77 | #define I2SR_IAAS 0x40 | ||
78 | #define I2SR_ICF 0x80 | ||
79 | #define I2CR_RSTA 0x04 | ||
80 | #define I2CR_TXAK 0x08 | ||
81 | #define I2CR_MTX 0x10 | ||
82 | #define I2CR_MSTA 0x20 | ||
83 | #define I2CR_IIEN 0x40 | ||
84 | #define I2CR_IEN 0x80 | ||
85 | |||
86 | /** Variables ****************************************************************** | ||
87 | *******************************************************************************/ | ||
88 | |||
89 | /* | ||
90 | * sorted list of clock divider, register value pairs | ||
91 | * taken from table 26-5, p.26-9, Freescale i.MX | ||
92 | * Integrated Portable System Processor Reference Manual | ||
93 | * Document Number: MC9328MXLRM, Rev. 5.1, 06/2007 | ||
94 | * | ||
95 | * Duplicated divider values removed from list | ||
96 | */ | ||
97 | |||
98 | static u16 __initdata i2c_clk_div[50][2] = { | ||
99 | { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, | ||
100 | { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, | ||
101 | { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, | ||
102 | { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, | ||
103 | { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, | ||
104 | { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, | ||
105 | { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, | ||
106 | { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, | ||
107 | { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, | ||
108 | { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, | ||
109 | { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, | ||
110 | { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, | ||
111 | { 3072, 0x1E }, { 3840, 0x1F } | ||
112 | }; | ||
113 | |||
114 | struct imx_i2c_struct { | ||
115 | struct i2c_adapter adapter; | ||
116 | struct resource *res; | ||
117 | struct clk *clk; | ||
118 | void __iomem *base; | ||
119 | int irq; | ||
120 | wait_queue_head_t queue; | ||
121 | unsigned long i2csr; | ||
122 | unsigned int disable_delay; | ||
123 | }; | ||
124 | |||
125 | /** Functions for IMX I2C adapter driver *************************************** | ||
126 | *******************************************************************************/ | ||
127 | |||
128 | static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx) | ||
129 | { | ||
130 | unsigned long orig_jiffies = jiffies; | ||
131 | |||
132 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); | ||
133 | |||
134 | /* wait for bus not busy */ | ||
135 | while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) { | ||
136 | if (signal_pending(current)) { | ||
137 | dev_dbg(&i2c_imx->adapter.dev, | ||
138 | "<%s> I2C Interrupted\n", __func__); | ||
139 | return -EINTR; | ||
140 | } | ||
141 | if (time_after(jiffies, orig_jiffies + HZ / 1000)) { | ||
142 | dev_dbg(&i2c_imx->adapter.dev, | ||
143 | "<%s> I2C bus is busy\n", __func__); | ||
144 | return -EIO; | ||
145 | } | ||
146 | schedule(); | ||
147 | } | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) | ||
153 | { | ||
154 | int result; | ||
155 | |||
156 | result = wait_event_interruptible_timeout(i2c_imx->queue, | ||
157 | i2c_imx->i2csr & I2SR_IIF, HZ / 10); | ||
158 | |||
159 | if (unlikely(result < 0)) { | ||
160 | dev_dbg(&i2c_imx->adapter.dev, "<%s> result < 0\n", __func__); | ||
161 | return result; | ||
162 | } else if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { | ||
163 | dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); | ||
164 | return -ETIMEDOUT; | ||
165 | } | ||
166 | dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); | ||
167 | i2c_imx->i2csr = 0; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) | ||
172 | { | ||
173 | if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) { | ||
174 | dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); | ||
175 | return -EIO; /* No ACK */ | ||
176 | } | ||
177 | |||
178 | dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__); | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static void i2c_imx_start(struct imx_i2c_struct *i2c_imx) | ||
183 | { | ||
184 | unsigned int temp = 0; | ||
185 | |||
186 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); | ||
187 | |||
188 | /* Enable I2C controller */ | ||
189 | writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); | ||
190 | /* Start I2C transaction */ | ||
191 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
192 | temp |= I2CR_MSTA; | ||
193 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
194 | temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; | ||
195 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
196 | } | ||
197 | |||
198 | static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) | ||
199 | { | ||
200 | unsigned int temp = 0; | ||
201 | |||
202 | /* Stop I2C transaction */ | ||
203 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); | ||
204 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
205 | temp &= ~I2CR_MSTA; | ||
206 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
207 | /* setup chip registers to defaults */ | ||
208 | writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); | ||
209 | writeb(0, i2c_imx->base + IMX_I2C_I2SR); | ||
210 | /* | ||
211 | * This delay caused by an i.MXL hardware bug. | ||
212 | * If no (or too short) delay, no "STOP" bit will be generated. | ||
213 | */ | ||
214 | udelay(i2c_imx->disable_delay); | ||
215 | /* Disable I2C controller */ | ||
216 | writeb(0, i2c_imx->base + IMX_I2C_I2CR); | ||
217 | } | ||
218 | |||
219 | static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, | ||
220 | unsigned int rate) | ||
221 | { | ||
222 | unsigned int i2c_clk_rate; | ||
223 | unsigned int div; | ||
224 | int i; | ||
225 | |||
226 | /* Divider value calculation */ | ||
227 | i2c_clk_rate = clk_get_rate(i2c_imx->clk); | ||
228 | div = (i2c_clk_rate + rate - 1) / rate; | ||
229 | if (div < i2c_clk_div[0][0]) | ||
230 | i = 0; | ||
231 | else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0]) | ||
232 | i = ARRAY_SIZE(i2c_clk_div) - 1; | ||
233 | else | ||
234 | for (i = 0; i2c_clk_div[i][0] < div; i++); | ||
235 | |||
236 | /* Write divider value to register */ | ||
237 | writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR); | ||
238 | |||
239 | /* | ||
240 | * There dummy delay is calculated. | ||
241 | * It should be about one I2C clock period long. | ||
242 | * This delay is used in I2C bus disable function | ||
243 | * to fix chip hardware bug. | ||
244 | */ | ||
245 | i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] | ||
246 | + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); | ||
247 | |||
248 | /* dev_dbg() can't be used, because adapter is not yet registered */ | ||
249 | #ifdef CONFIG_I2C_DEBUG_BUS | ||
250 | printk(KERN_DEBUG "I2C: <%s> I2C_CLK=%d, REQ DIV=%d\n", | ||
251 | __func__, i2c_clk_rate, div); | ||
252 | printk(KERN_DEBUG "I2C: <%s> IFDR[IC]=0x%x, REAL DIV=%d\n", | ||
253 | __func__, i2c_clk_div[i][1], i2c_clk_div[i][0]); | ||
254 | #endif | ||
255 | } | ||
256 | |||
257 | static irqreturn_t i2c_imx_isr(int irq, void *dev_id) | ||
258 | { | ||
259 | struct imx_i2c_struct *i2c_imx = dev_id; | ||
260 | unsigned int temp; | ||
261 | |||
262 | temp = readb(i2c_imx->base + IMX_I2C_I2SR); | ||
263 | if (temp & I2SR_IIF) { | ||
264 | /* save status register */ | ||
265 | i2c_imx->i2csr = temp; | ||
266 | temp &= ~I2SR_IIF; | ||
267 | writeb(temp, i2c_imx->base + IMX_I2C_I2SR); | ||
268 | wake_up_interruptible(&i2c_imx->queue); | ||
269 | return IRQ_HANDLED; | ||
270 | } | ||
271 | |||
272 | return IRQ_NONE; | ||
273 | } | ||
274 | |||
275 | static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) | ||
276 | { | ||
277 | int i, result; | ||
278 | |||
279 | dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", | ||
280 | __func__, msgs->addr << 1); | ||
281 | |||
282 | /* write slave address */ | ||
283 | writeb(msgs->addr << 1, i2c_imx->base + IMX_I2C_I2DR); | ||
284 | result = i2c_imx_trx_complete(i2c_imx); | ||
285 | if (result) | ||
286 | return result; | ||
287 | result = i2c_imx_acked(i2c_imx); | ||
288 | if (result) | ||
289 | return result; | ||
290 | dev_dbg(&i2c_imx->adapter.dev, "<%s> write data\n", __func__); | ||
291 | |||
292 | /* write data */ | ||
293 | for (i = 0; i < msgs->len; i++) { | ||
294 | dev_dbg(&i2c_imx->adapter.dev, | ||
295 | "<%s> write byte: B%d=0x%X\n", | ||
296 | __func__, i, msgs->buf[i]); | ||
297 | writeb(msgs->buf[i], i2c_imx->base + IMX_I2C_I2DR); | ||
298 | result = i2c_imx_trx_complete(i2c_imx); | ||
299 | if (result) | ||
300 | return result; | ||
301 | result = i2c_imx_acked(i2c_imx); | ||
302 | if (result) | ||
303 | return result; | ||
304 | } | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) | ||
309 | { | ||
310 | int i, result; | ||
311 | unsigned int temp; | ||
312 | |||
313 | dev_dbg(&i2c_imx->adapter.dev, | ||
314 | "<%s> write slave address: addr=0x%x\n", | ||
315 | __func__, (msgs->addr << 1) | 0x01); | ||
316 | |||
317 | /* write slave address */ | ||
318 | writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR); | ||
319 | result = i2c_imx_trx_complete(i2c_imx); | ||
320 | if (result) | ||
321 | return result; | ||
322 | result = i2c_imx_acked(i2c_imx); | ||
323 | if (result) | ||
324 | return result; | ||
325 | |||
326 | dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__); | ||
327 | |||
328 | /* setup bus to read data */ | ||
329 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
330 | temp &= ~I2CR_MTX; | ||
331 | if (msgs->len - 1) | ||
332 | temp &= ~I2CR_TXAK; | ||
333 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
334 | readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */ | ||
335 | |||
336 | dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__); | ||
337 | |||
338 | /* read data */ | ||
339 | for (i = 0; i < msgs->len; i++) { | ||
340 | result = i2c_imx_trx_complete(i2c_imx); | ||
341 | if (result) | ||
342 | return result; | ||
343 | if (i == (msgs->len - 1)) { | ||
344 | dev_dbg(&i2c_imx->adapter.dev, | ||
345 | "<%s> clear MSTA\n", __func__); | ||
346 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
347 | temp &= ~I2CR_MSTA; | ||
348 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
349 | } else if (i == (msgs->len - 2)) { | ||
350 | dev_dbg(&i2c_imx->adapter.dev, | ||
351 | "<%s> set TXAK\n", __func__); | ||
352 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
353 | temp |= I2CR_TXAK; | ||
354 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
355 | } | ||
356 | msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR); | ||
357 | dev_dbg(&i2c_imx->adapter.dev, | ||
358 | "<%s> read byte: B%d=0x%X\n", | ||
359 | __func__, i, msgs->buf[i]); | ||
360 | } | ||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | static int i2c_imx_xfer(struct i2c_adapter *adapter, | ||
365 | struct i2c_msg *msgs, int num) | ||
366 | { | ||
367 | unsigned int i, temp; | ||
368 | int result; | ||
369 | struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); | ||
370 | |||
371 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); | ||
372 | |||
373 | /* Check if i2c bus is not busy */ | ||
374 | result = i2c_imx_bus_busy(i2c_imx); | ||
375 | if (result) | ||
376 | goto fail0; | ||
377 | |||
378 | /* Start I2C transfer */ | ||
379 | i2c_imx_start(i2c_imx); | ||
380 | |||
381 | /* read/write data */ | ||
382 | for (i = 0; i < num; i++) { | ||
383 | if (i) { | ||
384 | dev_dbg(&i2c_imx->adapter.dev, | ||
385 | "<%s> repeated start\n", __func__); | ||
386 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
387 | temp |= I2CR_RSTA; | ||
388 | writeb(temp, i2c_imx->base + IMX_I2C_I2CR); | ||
389 | } | ||
390 | dev_dbg(&i2c_imx->adapter.dev, | ||
391 | "<%s> transfer message: %d\n", __func__, i); | ||
392 | /* write/read data */ | ||
393 | #ifdef CONFIG_I2C_DEBUG_BUS | ||
394 | temp = readb(i2c_imx->base + IMX_I2C_I2CR); | ||
395 | dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, " | ||
396 | "MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__, | ||
397 | (temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0), | ||
398 | (temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0), | ||
399 | (temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0)); | ||
400 | temp = readb(i2c_imx->base + IMX_I2C_I2SR); | ||
401 | dev_dbg(&i2c_imx->adapter.dev, | ||
402 | "<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, " | ||
403 | "IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__, | ||
404 | (temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0), | ||
405 | (temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0), | ||
406 | (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), | ||
407 | (temp & I2SR_RXAK ? 1 : 0)); | ||
408 | #endif | ||
409 | if (msgs[i].flags & I2C_M_RD) | ||
410 | result = i2c_imx_read(i2c_imx, &msgs[i]); | ||
411 | else | ||
412 | result = i2c_imx_write(i2c_imx, &msgs[i]); | ||
413 | } | ||
414 | |||
415 | fail0: | ||
416 | /* Stop I2C transfer */ | ||
417 | i2c_imx_stop(i2c_imx); | ||
418 | |||
419 | dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, | ||
420 | (result < 0) ? "error" : "success msg", | ||
421 | (result < 0) ? result : num); | ||
422 | return (result < 0) ? result : num; | ||
423 | } | ||
424 | |||
425 | static u32 i2c_imx_func(struct i2c_adapter *adapter) | ||
426 | { | ||
427 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
428 | } | ||
429 | |||
430 | static struct i2c_algorithm i2c_imx_algo = { | ||
431 | .master_xfer = i2c_imx_xfer, | ||
432 | .functionality = i2c_imx_func, | ||
433 | }; | ||
434 | |||
435 | static int __init i2c_imx_probe(struct platform_device *pdev) | ||
436 | { | ||
437 | struct imx_i2c_struct *i2c_imx; | ||
438 | struct resource *res; | ||
439 | struct imxi2c_platform_data *pdata; | ||
440 | void __iomem *base; | ||
441 | resource_size_t res_size; | ||
442 | int irq; | ||
443 | int ret; | ||
444 | |||
445 | dev_dbg(&pdev->dev, "<%s>\n", __func__); | ||
446 | |||
447 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
448 | if (!res) { | ||
449 | dev_err(&pdev->dev, "can't get device resources\n"); | ||
450 | return -ENOENT; | ||
451 | } | ||
452 | irq = platform_get_irq(pdev, 0); | ||
453 | if (irq < 0) { | ||
454 | dev_err(&pdev->dev, "can't get irq number\n"); | ||
455 | return -ENOENT; | ||
456 | } | ||
457 | |||
458 | pdata = pdev->dev.platform_data; | ||
459 | |||
460 | if (pdata && pdata->init) { | ||
461 | ret = pdata->init(&pdev->dev); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | } | ||
465 | |||
466 | res_size = resource_size(res); | ||
467 | base = ioremap(res->start, res_size); | ||
468 | if (!base) { | ||
469 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
470 | ret = -EIO; | ||
471 | goto fail0; | ||
472 | } | ||
473 | |||
474 | i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); | ||
475 | if (!i2c_imx) { | ||
476 | dev_err(&pdev->dev, "can't allocate interface\n"); | ||
477 | ret = -ENOMEM; | ||
478 | goto fail1; | ||
479 | } | ||
480 | |||
481 | if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { | ||
482 | ret = -EBUSY; | ||
483 | goto fail2; | ||
484 | } | ||
485 | |||
486 | /* Setup i2c_imx driver structure */ | ||
487 | strcpy(i2c_imx->adapter.name, pdev->name); | ||
488 | i2c_imx->adapter.owner = THIS_MODULE; | ||
489 | i2c_imx->adapter.algo = &i2c_imx_algo; | ||
490 | i2c_imx->adapter.dev.parent = &pdev->dev; | ||
491 | i2c_imx->adapter.nr = pdev->id; | ||
492 | i2c_imx->irq = irq; | ||
493 | i2c_imx->base = base; | ||
494 | i2c_imx->res = res; | ||
495 | |||
496 | /* Get I2C clock */ | ||
497 | i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); | ||
498 | if (IS_ERR(i2c_imx->clk)) { | ||
499 | ret = PTR_ERR(i2c_imx->clk); | ||
500 | dev_err(&pdev->dev, "can't get I2C clock\n"); | ||
501 | goto fail3; | ||
502 | } | ||
503 | clk_enable(i2c_imx->clk); | ||
504 | |||
505 | /* Request IRQ */ | ||
506 | ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); | ||
507 | if (ret) { | ||
508 | dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); | ||
509 | goto fail4; | ||
510 | } | ||
511 | |||
512 | /* Init queue */ | ||
513 | init_waitqueue_head(&i2c_imx->queue); | ||
514 | |||
515 | /* Set up adapter data */ | ||
516 | i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); | ||
517 | |||
518 | /* Set up clock divider */ | ||
519 | if (pdata && pdata->bitrate) | ||
520 | i2c_imx_set_clk(i2c_imx, pdata->bitrate); | ||
521 | else | ||
522 | i2c_imx_set_clk(i2c_imx, IMX_I2C_BIT_RATE); | ||
523 | |||
524 | /* Set up chip registers to defaults */ | ||
525 | writeb(0, i2c_imx->base + IMX_I2C_I2CR); | ||
526 | writeb(0, i2c_imx->base + IMX_I2C_I2SR); | ||
527 | |||
528 | /* Add I2C adapter */ | ||
529 | ret = i2c_add_numbered_adapter(&i2c_imx->adapter); | ||
530 | if (ret < 0) { | ||
531 | dev_err(&pdev->dev, "registration failed\n"); | ||
532 | goto fail5; | ||
533 | } | ||
534 | |||
535 | /* Set up platform driver data */ | ||
536 | platform_set_drvdata(pdev, i2c_imx); | ||
537 | |||
538 | dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); | ||
539 | dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", | ||
540 | i2c_imx->res->start, i2c_imx->res->end); | ||
541 | dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", | ||
542 | res_size, i2c_imx->res->start); | ||
543 | dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", | ||
544 | i2c_imx->adapter.name); | ||
545 | dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); | ||
546 | |||
547 | return 0; /* Return OK */ | ||
548 | |||
549 | fail5: | ||
550 | free_irq(i2c_imx->irq, i2c_imx); | ||
551 | fail4: | ||
552 | clk_disable(i2c_imx->clk); | ||
553 | clk_put(i2c_imx->clk); | ||
554 | fail3: | ||
555 | release_mem_region(i2c_imx->res->start, resource_size(res)); | ||
556 | fail2: | ||
557 | kfree(i2c_imx); | ||
558 | fail1: | ||
559 | iounmap(base); | ||
560 | fail0: | ||
561 | if (pdata && pdata->exit) | ||
562 | pdata->exit(&pdev->dev); | ||
563 | return ret; /* Return error number */ | ||
564 | } | ||
565 | |||
566 | static int __exit i2c_imx_remove(struct platform_device *pdev) | ||
567 | { | ||
568 | struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); | ||
569 | struct imxi2c_platform_data *pdata = pdev->dev.platform_data; | ||
570 | |||
571 | /* remove adapter */ | ||
572 | dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n"); | ||
573 | i2c_del_adapter(&i2c_imx->adapter); | ||
574 | platform_set_drvdata(pdev, NULL); | ||
575 | |||
576 | /* free interrupt */ | ||
577 | free_irq(i2c_imx->irq, i2c_imx); | ||
578 | |||
579 | /* setup chip registers to defaults */ | ||
580 | writeb(0, i2c_imx->base + IMX_I2C_IADR); | ||
581 | writeb(0, i2c_imx->base + IMX_I2C_IFDR); | ||
582 | writeb(0, i2c_imx->base + IMX_I2C_I2CR); | ||
583 | writeb(0, i2c_imx->base + IMX_I2C_I2SR); | ||
584 | |||
585 | /* Shut down hardware */ | ||
586 | if (pdata && pdata->exit) | ||
587 | pdata->exit(&pdev->dev); | ||
588 | |||
589 | /* Disable I2C clock */ | ||
590 | clk_disable(i2c_imx->clk); | ||
591 | clk_put(i2c_imx->clk); | ||
592 | |||
593 | release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); | ||
594 | iounmap(i2c_imx->base); | ||
595 | kfree(i2c_imx); | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static struct platform_driver i2c_imx_driver = { | ||
600 | .probe = i2c_imx_probe, | ||
601 | .remove = __exit_p(i2c_imx_remove), | ||
602 | .driver = { | ||
603 | .name = DRIVER_NAME, | ||
604 | .owner = THIS_MODULE, | ||
605 | } | ||
606 | }; | ||
607 | |||
608 | static int __init i2c_adap_imx_init(void) | ||
609 | { | ||
610 | return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe); | ||
611 | } | ||
612 | |||
613 | static void __exit i2c_adap_imx_exit(void) | ||
614 | { | ||
615 | platform_driver_unregister(&i2c_imx_driver); | ||
616 | } | ||
617 | |||
618 | module_init(i2c_adap_imx_init); | ||
619 | module_exit(i2c_adap_imx_exit); | ||
620 | |||
621 | MODULE_LICENSE("GPL"); | ||
622 | MODULE_AUTHOR("Darius Augulis"); | ||
623 | MODULE_DESCRIPTION("I2C adapter driver for IMX I2C bus"); | ||
624 | MODULE_ALIAS("platform:" DRIVER_NAME); | ||
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c index 26bf37010586..4af5c09f0e8f 100644 --- a/drivers/i2c/busses/i2c-mpc.c +++ b/drivers/i2c/busses/i2c-mpc.c | |||
@@ -20,18 +20,21 @@ | |||
20 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
21 | #include <linux/of_i2c.h> | 21 | #include <linux/of_i2c.h> |
22 | 22 | ||
23 | #include <asm/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/fsl_devices.h> | 24 | #include <linux/fsl_devices.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | 28 | ||
29 | #include <asm/mpc52xx.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | |||
29 | #define DRV_NAME "mpc-i2c" | 32 | #define DRV_NAME "mpc-i2c" |
30 | 33 | ||
31 | #define MPC_I2C_FDR 0x04 | 34 | #define MPC_I2C_FDR 0x04 |
32 | #define MPC_I2C_CR 0x08 | 35 | #define MPC_I2C_CR 0x08 |
33 | #define MPC_I2C_SR 0x0c | 36 | #define MPC_I2C_SR 0x0c |
34 | #define MPC_I2C_DR 0x10 | 37 | #define MPC_I2C_DR 0x10 |
35 | #define MPC_I2C_DFSRR 0x14 | 38 | #define MPC_I2C_DFSRR 0x14 |
36 | 39 | ||
37 | #define CCR_MEN 0x80 | 40 | #define CCR_MEN 0x80 |
@@ -50,15 +53,27 @@ | |||
50 | #define CSR_RXAK 0x01 | 53 | #define CSR_RXAK 0x01 |
51 | 54 | ||
52 | struct mpc_i2c { | 55 | struct mpc_i2c { |
56 | struct device *dev; | ||
53 | void __iomem *base; | 57 | void __iomem *base; |
54 | u32 interrupt; | 58 | u32 interrupt; |
55 | wait_queue_head_t queue; | 59 | wait_queue_head_t queue; |
56 | struct i2c_adapter adap; | 60 | struct i2c_adapter adap; |
57 | int irq; | 61 | int irq; |
58 | u32 flags; | ||
59 | }; | 62 | }; |
60 | 63 | ||
61 | static __inline__ void writeccr(struct mpc_i2c *i2c, u32 x) | 64 | struct mpc_i2c_divider { |
65 | u16 divider; | ||
66 | u16 fdr; /* including dfsrr */ | ||
67 | }; | ||
68 | |||
69 | struct mpc_i2c_match_data { | ||
70 | void (*setclock)(struct device_node *node, | ||
71 | struct mpc_i2c *i2c, | ||
72 | u32 clock, u32 prescaler); | ||
73 | u32 prescaler; | ||
74 | }; | ||
75 | |||
76 | static inline void writeccr(struct mpc_i2c *i2c, u32 x) | ||
62 | { | 77 | { |
63 | writeb(x, i2c->base + MPC_I2C_CR); | 78 | writeb(x, i2c->base + MPC_I2C_CR); |
64 | } | 79 | } |
@@ -100,12 +115,11 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) | |||
100 | u32 x; | 115 | u32 x; |
101 | int result = 0; | 116 | int result = 0; |
102 | 117 | ||
103 | if (i2c->irq == NO_IRQ) | 118 | if (i2c->irq == NO_IRQ) { |
104 | { | ||
105 | while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { | 119 | while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { |
106 | schedule(); | 120 | schedule(); |
107 | if (time_after(jiffies, orig_jiffies + timeout)) { | 121 | if (time_after(jiffies, orig_jiffies + timeout)) { |
108 | pr_debug("I2C: timeout\n"); | 122 | dev_dbg(i2c->dev, "timeout\n"); |
109 | writeccr(i2c, 0); | 123 | writeccr(i2c, 0); |
110 | result = -EIO; | 124 | result = -EIO; |
111 | break; | 125 | break; |
@@ -119,7 +133,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) | |||
119 | (i2c->interrupt & CSR_MIF), timeout); | 133 | (i2c->interrupt & CSR_MIF), timeout); |
120 | 134 | ||
121 | if (unlikely(!(i2c->interrupt & CSR_MIF))) { | 135 | if (unlikely(!(i2c->interrupt & CSR_MIF))) { |
122 | pr_debug("I2C: wait timeout\n"); | 136 | dev_dbg(i2c->dev, "wait timeout\n"); |
123 | writeccr(i2c, 0); | 137 | writeccr(i2c, 0); |
124 | result = -ETIMEDOUT; | 138 | result = -ETIMEDOUT; |
125 | } | 139 | } |
@@ -132,17 +146,17 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) | |||
132 | return result; | 146 | return result; |
133 | 147 | ||
134 | if (!(x & CSR_MCF)) { | 148 | if (!(x & CSR_MCF)) { |
135 | pr_debug("I2C: unfinished\n"); | 149 | dev_dbg(i2c->dev, "unfinished\n"); |
136 | return -EIO; | 150 | return -EIO; |
137 | } | 151 | } |
138 | 152 | ||
139 | if (x & CSR_MAL) { | 153 | if (x & CSR_MAL) { |
140 | pr_debug("I2C: MAL\n"); | 154 | dev_dbg(i2c->dev, "MAL\n"); |
141 | return -EIO; | 155 | return -EIO; |
142 | } | 156 | } |
143 | 157 | ||
144 | if (writing && (x & CSR_RXAK)) { | 158 | if (writing && (x & CSR_RXAK)) { |
145 | pr_debug("I2C: No RXAK\n"); | 159 | dev_dbg(i2c->dev, "No RXAK\n"); |
146 | /* generate stop */ | 160 | /* generate stop */ |
147 | writeccr(i2c, CCR_MEN); | 161 | writeccr(i2c, CCR_MEN); |
148 | return -EIO; | 162 | return -EIO; |
@@ -150,18 +164,181 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) | |||
150 | return 0; | 164 | return 0; |
151 | } | 165 | } |
152 | 166 | ||
153 | static void mpc_i2c_setclock(struct mpc_i2c *i2c) | 167 | #ifdef CONFIG_PPC_52xx |
168 | static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = { | ||
169 | {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, | ||
170 | {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02}, | ||
171 | {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28}, | ||
172 | {52, 0x63}, {56, 0x29}, {60, 0x41}, {64, 0x2a}, | ||
173 | {68, 0x07}, {72, 0x2b}, {80, 0x2c}, {88, 0x09}, | ||
174 | {96, 0x2d}, {104, 0x0a}, {112, 0x2e}, {120, 0x81}, | ||
175 | {128, 0x2f}, {136, 0x47}, {144, 0x0c}, {160, 0x30}, | ||
176 | {176, 0x49}, {192, 0x31}, {208, 0x4a}, {224, 0x32}, | ||
177 | {240, 0x0f}, {256, 0x33}, {272, 0x87}, {288, 0x10}, | ||
178 | {320, 0x34}, {352, 0x89}, {384, 0x35}, {416, 0x8a}, | ||
179 | {448, 0x36}, {480, 0x13}, {512, 0x37}, {576, 0x14}, | ||
180 | {640, 0x38}, {768, 0x39}, {896, 0x3a}, {960, 0x17}, | ||
181 | {1024, 0x3b}, {1152, 0x18}, {1280, 0x3c}, {1536, 0x3d}, | ||
182 | {1792, 0x3e}, {1920, 0x1b}, {2048, 0x3f}, {2304, 0x1c}, | ||
183 | {2560, 0x1d}, {3072, 0x1e}, {3584, 0x7e}, {3840, 0x1f}, | ||
184 | {4096, 0x7f}, {4608, 0x5c}, {5120, 0x5d}, {6144, 0x5e}, | ||
185 | {7168, 0xbe}, {7680, 0x5f}, {8192, 0xbf}, {9216, 0x9c}, | ||
186 | {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f} | ||
187 | }; | ||
188 | |||
189 | int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler) | ||
190 | { | ||
191 | const struct mpc52xx_i2c_divider *div = NULL; | ||
192 | unsigned int pvr = mfspr(SPRN_PVR); | ||
193 | u32 divider; | ||
194 | int i; | ||
195 | |||
196 | if (!clock) | ||
197 | return -EINVAL; | ||
198 | |||
199 | /* Determine divider value */ | ||
200 | divider = mpc52xx_find_ipb_freq(node) / clock; | ||
201 | |||
202 | /* | ||
203 | * We want to choose an FDR/DFSR that generates an I2C bus speed that | ||
204 | * is equal to or lower than the requested speed. | ||
205 | */ | ||
206 | for (i = 0; i < ARRAY_SIZE(mpc52xx_i2c_dividers); i++) { | ||
207 | div = &mpc_i2c_dividers_52xx[i]; | ||
208 | /* Old MPC5200 rev A CPUs do not support the high bits */ | ||
209 | if (div->fdr & 0xc0 && pvr == 0x80822011) | ||
210 | continue; | ||
211 | if (div->divider >= divider) | ||
212 | break; | ||
213 | } | ||
214 | |||
215 | return div ? (int)div->fdr : -EINVAL; | ||
216 | } | ||
217 | |||
218 | static void mpc_i2c_setclock_52xx(struct device_node *node, | ||
219 | struct mpc_i2c *i2c, | ||
220 | u32 clock, u32 prescaler) | ||
154 | { | 221 | { |
155 | /* Set clock and filters */ | 222 | int fdr = mpc52xx_i2c_get_fdr(node, clock, prescaler); |
156 | if (i2c->flags & FSL_I2C_DEV_SEPARATE_DFSRR) { | 223 | |
157 | writeb(0x31, i2c->base + MPC_I2C_FDR); | 224 | if (fdr < 0) |
158 | writeb(0x10, i2c->base + MPC_I2C_DFSRR); | 225 | fdr = 0x3f; /* backward compatibility */ |
159 | } else if (i2c->flags & FSL_I2C_DEV_CLOCK_5200) | 226 | writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); |
160 | writeb(0x3f, i2c->base + MPC_I2C_FDR); | 227 | dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr); |
161 | else | 228 | } |
162 | writel(0x1031, i2c->base + MPC_I2C_FDR); | 229 | #else /* !CONFIG_PPC_52xx */ |
230 | static void mpc_i2c_setclock_52xx(struct device_node *node, | ||
231 | struct mpc_i2c *i2c, | ||
232 | u32 clock, u32 prescaler) | ||
233 | { | ||
234 | } | ||
235 | #endif /* CONFIG_PPC_52xx*/ | ||
236 | |||
237 | #ifdef CONFIG_FSL_SOC | ||
238 | static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = { | ||
239 | {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123}, | ||
240 | {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102}, | ||
241 | {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127}, | ||
242 | {544, 0x0b03}, {576, 0x0104}, {608, 0x1603}, {640, 0x0105}, | ||
243 | {672, 0x2003}, {704, 0x0b05}, {736, 0x2b03}, {768, 0x0106}, | ||
244 | {800, 0x3603}, {832, 0x0b06}, {896, 0x012a}, {960, 0x0107}, | ||
245 | {1024, 0x012b}, {1088, 0x1607}, {1152, 0x0108}, {1216, 0x2b07}, | ||
246 | {1280, 0x0109}, {1408, 0x1609}, {1536, 0x010a}, {1664, 0x160a}, | ||
247 | {1792, 0x012e}, {1920, 0x010b}, {2048, 0x012f}, {2176, 0x2b0b}, | ||
248 | {2304, 0x010c}, {2560, 0x010d}, {2816, 0x2b0d}, {3072, 0x010e}, | ||
249 | {3328, 0x2b0e}, {3584, 0x0132}, {3840, 0x010f}, {4096, 0x0133}, | ||
250 | {4608, 0x0110}, {5120, 0x0111}, {6144, 0x0112}, {7168, 0x0136}, | ||
251 | {7680, 0x0113}, {8192, 0x0137}, {9216, 0x0114}, {10240, 0x0115}, | ||
252 | {12288, 0x0116}, {14336, 0x013a}, {15360, 0x0117}, {16384, 0x013b}, | ||
253 | {18432, 0x0118}, {20480, 0x0119}, {24576, 0x011a}, {28672, 0x013e}, | ||
254 | {30720, 0x011b}, {32768, 0x013f}, {36864, 0x011c}, {40960, 0x011d}, | ||
255 | {49152, 0x011e}, {61440, 0x011f} | ||
256 | }; | ||
257 | |||
258 | u32 mpc_i2c_get_sec_cfg_8xxx(void) | ||
259 | { | ||
260 | struct device_node *node = NULL; | ||
261 | u32 __iomem *reg; | ||
262 | u32 val = 0; | ||
263 | |||
264 | node = of_find_node_by_name(NULL, "global-utilities"); | ||
265 | if (node) { | ||
266 | const u32 *prop = of_get_property(node, "reg", NULL); | ||
267 | if (prop) { | ||
268 | /* | ||
269 | * Map and check POR Device Status Register 2 | ||
270 | * (PORDEVSR2) at 0xE0014 | ||
271 | */ | ||
272 | reg = ioremap(get_immrbase() + *prop + 0x14, 0x4); | ||
273 | if (!reg) | ||
274 | printk(KERN_ERR | ||
275 | "Error: couldn't map PORDEVSR2\n"); | ||
276 | else | ||
277 | val = in_be32(reg) & 0x00000080; /* sec-cfg */ | ||
278 | iounmap(reg); | ||
279 | } | ||
280 | } | ||
281 | if (node) | ||
282 | of_node_put(node); | ||
283 | |||
284 | return val; | ||
163 | } | 285 | } |
164 | 286 | ||
287 | int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler) | ||
288 | { | ||
289 | const struct mpc_i2c_divider *div = NULL; | ||
290 | u32 divider; | ||
291 | int i; | ||
292 | |||
293 | if (!clock) | ||
294 | return -EINVAL; | ||
295 | |||
296 | /* Determine proper divider value */ | ||
297 | if (of_device_is_compatible(node, "fsl,mpc8544-i2c")) | ||
298 | prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2; | ||
299 | if (!prescaler) | ||
300 | prescaler = 1; | ||
301 | |||
302 | divider = fsl_get_sys_freq() / clock / prescaler; | ||
303 | |||
304 | pr_debug("I2C: src_clock=%d clock=%d divider=%d\n", | ||
305 | fsl_get_sys_freq(), clock, divider); | ||
306 | |||
307 | /* | ||
308 | * We want to choose an FDR/DFSR that generates an I2C bus speed that | ||
309 | * is equal to or lower than the requested speed. | ||
310 | */ | ||
311 | for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_8xxx); i++) { | ||
312 | div = &mpc_i2c_dividers_8xxx[i]; | ||
313 | if (div->divider >= divider) | ||
314 | break; | ||
315 | } | ||
316 | |||
317 | return div ? (int)div->fdr : -EINVAL; | ||
318 | } | ||
319 | |||
320 | static void mpc_i2c_setclock_8xxx(struct device_node *node, | ||
321 | struct mpc_i2c *i2c, | ||
322 | u32 clock, u32 prescaler) | ||
323 | { | ||
324 | int fdr = mpc_i2c_get_fdr_8xxx(node, clock, prescaler); | ||
325 | |||
326 | if (fdr < 0) | ||
327 | fdr = 0x1031; /* backward compatibility */ | ||
328 | writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); | ||
329 | writeb((fdr >> 8) & 0xff, i2c->base + MPC_I2C_DFSRR); | ||
330 | dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n", | ||
331 | clock, fdr >> 8, fdr & 0xff); | ||
332 | } | ||
333 | |||
334 | #else /* !CONFIG_FSL_SOC */ | ||
335 | static void mpc_i2c_setclock_8xxx(struct device_node *node, | ||
336 | struct mpc_i2c *i2c, | ||
337 | u32 clock, u32 prescaler) | ||
338 | { | ||
339 | } | ||
340 | #endif /* CONFIG_FSL_SOC */ | ||
341 | |||
165 | static void mpc_i2c_start(struct mpc_i2c *i2c) | 342 | static void mpc_i2c_start(struct mpc_i2c *i2c) |
166 | { | 343 | { |
167 | /* Clear arbitration */ | 344 | /* Clear arbitration */ |
@@ -176,7 +353,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c) | |||
176 | } | 353 | } |
177 | 354 | ||
178 | static int mpc_write(struct mpc_i2c *i2c, int target, | 355 | static int mpc_write(struct mpc_i2c *i2c, int target, |
179 | const u8 * data, int length, int restart) | 356 | const u8 *data, int length, int restart) |
180 | { | 357 | { |
181 | int i, result; | 358 | int i, result; |
182 | unsigned timeout = i2c->adap.timeout; | 359 | unsigned timeout = i2c->adap.timeout; |
@@ -207,7 +384,7 @@ static int mpc_write(struct mpc_i2c *i2c, int target, | |||
207 | } | 384 | } |
208 | 385 | ||
209 | static int mpc_read(struct mpc_i2c *i2c, int target, | 386 | static int mpc_read(struct mpc_i2c *i2c, int target, |
210 | u8 * data, int length, int restart) | 387 | u8 *data, int length, int restart) |
211 | { | 388 | { |
212 | unsigned timeout = i2c->adap.timeout; | 389 | unsigned timeout = i2c->adap.timeout; |
213 | int i, result; | 390 | int i, result; |
@@ -264,12 +441,12 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
264 | /* Allow bus up to 1s to become not busy */ | 441 | /* Allow bus up to 1s to become not busy */ |
265 | while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { | 442 | while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { |
266 | if (signal_pending(current)) { | 443 | if (signal_pending(current)) { |
267 | pr_debug("I2C: Interrupted\n"); | 444 | dev_dbg(i2c->dev, "Interrupted\n"); |
268 | writeccr(i2c, 0); | 445 | writeccr(i2c, 0); |
269 | return -EINTR; | 446 | return -EINTR; |
270 | } | 447 | } |
271 | if (time_after(jiffies, orig_jiffies + HZ)) { | 448 | if (time_after(jiffies, orig_jiffies + HZ)) { |
272 | pr_debug("I2C: timeout\n"); | 449 | dev_dbg(i2c->dev, "timeout\n"); |
273 | if (readb(i2c->base + MPC_I2C_SR) == | 450 | if (readb(i2c->base + MPC_I2C_SR) == |
274 | (CSR_MCF | CSR_MBB | CSR_RXAK)) | 451 | (CSR_MCF | CSR_MBB | CSR_RXAK)) |
275 | mpc_i2c_fixup(i2c); | 452 | mpc_i2c_fixup(i2c); |
@@ -280,9 +457,10 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
280 | 457 | ||
281 | for (i = 0; ret >= 0 && i < num; i++) { | 458 | for (i = 0; ret >= 0 && i < num; i++) { |
282 | pmsg = &msgs[i]; | 459 | pmsg = &msgs[i]; |
283 | pr_debug("Doing %s %d bytes to 0x%02x - %d of %d messages\n", | 460 | dev_dbg(i2c->dev, |
284 | pmsg->flags & I2C_M_RD ? "read" : "write", | 461 | "Doing %s %d bytes to 0x%02x - %d of %d messages\n", |
285 | pmsg->len, pmsg->addr, i + 1, num); | 462 | pmsg->flags & I2C_M_RD ? "read" : "write", |
463 | pmsg->len, pmsg->addr, i + 1, num); | ||
286 | if (pmsg->flags & I2C_M_RD) | 464 | if (pmsg->flags & I2C_M_RD) |
287 | ret = | 465 | ret = |
288 | mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); | 466 | mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); |
@@ -311,27 +489,26 @@ static struct i2c_adapter mpc_ops = { | |||
311 | .timeout = HZ, | 489 | .timeout = HZ, |
312 | }; | 490 | }; |
313 | 491 | ||
314 | static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match) | 492 | static int __devinit fsl_i2c_probe(struct of_device *op, |
493 | const struct of_device_id *match) | ||
315 | { | 494 | { |
316 | int result = 0; | ||
317 | struct mpc_i2c *i2c; | 495 | struct mpc_i2c *i2c; |
496 | const u32 *prop; | ||
497 | u32 clock = 0; | ||
498 | int result = 0; | ||
499 | int plen; | ||
318 | 500 | ||
319 | i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); | 501 | i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); |
320 | if (!i2c) | 502 | if (!i2c) |
321 | return -ENOMEM; | 503 | return -ENOMEM; |
322 | 504 | ||
323 | if (of_get_property(op->node, "dfsrr", NULL)) | 505 | i2c->dev = &op->dev; /* for debug and error output */ |
324 | i2c->flags |= FSL_I2C_DEV_SEPARATE_DFSRR; | ||
325 | |||
326 | if (of_device_is_compatible(op->node, "fsl,mpc5200-i2c") || | ||
327 | of_device_is_compatible(op->node, "mpc5200-i2c")) | ||
328 | i2c->flags |= FSL_I2C_DEV_CLOCK_5200; | ||
329 | 506 | ||
330 | init_waitqueue_head(&i2c->queue); | 507 | init_waitqueue_head(&i2c->queue); |
331 | 508 | ||
332 | i2c->base = of_iomap(op->node, 0); | 509 | i2c->base = of_iomap(op->node, 0); |
333 | if (!i2c->base) { | 510 | if (!i2c->base) { |
334 | printk(KERN_ERR "i2c-mpc - failed to map controller\n"); | 511 | dev_err(i2c->dev, "failed to map controller\n"); |
335 | result = -ENOMEM; | 512 | result = -ENOMEM; |
336 | goto fail_map; | 513 | goto fail_map; |
337 | } | 514 | } |
@@ -341,12 +518,27 @@ static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_ | |||
341 | result = request_irq(i2c->irq, mpc_i2c_isr, | 518 | result = request_irq(i2c->irq, mpc_i2c_isr, |
342 | IRQF_SHARED, "i2c-mpc", i2c); | 519 | IRQF_SHARED, "i2c-mpc", i2c); |
343 | if (result < 0) { | 520 | if (result < 0) { |
344 | printk(KERN_ERR "i2c-mpc - failed to attach interrupt\n"); | 521 | dev_err(i2c->dev, "failed to attach interrupt\n"); |
345 | goto fail_request; | 522 | goto fail_request; |
346 | } | 523 | } |
347 | } | 524 | } |
348 | 525 | ||
349 | mpc_i2c_setclock(i2c); | 526 | if (!of_get_property(op->node, "fsl,preserve-clocking", NULL)) { |
527 | prop = of_get_property(op->node, "clock-frequency", &plen); | ||
528 | if (prop && plen == sizeof(u32)) | ||
529 | clock = *prop; | ||
530 | |||
531 | if (match->data) { | ||
532 | struct mpc_i2c_match_data *data = | ||
533 | (struct mpc_i2c_match_data *)match->data; | ||
534 | data->setclock(op->node, i2c, clock, data->prescaler); | ||
535 | } else { | ||
536 | /* Backwards compatibility */ | ||
537 | if (of_get_property(op->node, "dfsrr", NULL)) | ||
538 | mpc_i2c_setclock_8xxx(op->node, i2c, | ||
539 | clock, 0); | ||
540 | } | ||
541 | } | ||
350 | 542 | ||
351 | dev_set_drvdata(&op->dev, i2c); | 543 | dev_set_drvdata(&op->dev, i2c); |
352 | 544 | ||
@@ -356,7 +548,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_ | |||
356 | 548 | ||
357 | result = i2c_add_adapter(&i2c->adap); | 549 | result = i2c_add_adapter(&i2c->adap); |
358 | if (result < 0) { | 550 | if (result < 0) { |
359 | printk(KERN_ERR "i2c-mpc - failed to add adapter\n"); | 551 | dev_err(i2c->dev, "failed to add adapter\n"); |
360 | goto fail_add; | 552 | goto fail_add; |
361 | } | 553 | } |
362 | of_register_i2c_devices(&i2c->adap, op->node); | 554 | of_register_i2c_devices(&i2c->adap, op->node); |
@@ -368,7 +560,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_ | |||
368 | free_irq(i2c->irq, i2c); | 560 | free_irq(i2c->irq, i2c); |
369 | fail_request: | 561 | fail_request: |
370 | irq_dispose_mapping(i2c->irq); | 562 | irq_dispose_mapping(i2c->irq); |
371 | iounmap(i2c->base); | 563 | iounmap(i2c->base); |
372 | fail_map: | 564 | fail_map: |
373 | kfree(i2c); | 565 | kfree(i2c); |
374 | return result; | 566 | return result; |
@@ -391,9 +583,43 @@ static int __devexit fsl_i2c_remove(struct of_device *op) | |||
391 | }; | 583 | }; |
392 | 584 | ||
393 | static const struct of_device_id mpc_i2c_of_match[] = { | 585 | static const struct of_device_id mpc_i2c_of_match[] = { |
394 | {.compatible = "fsl-i2c",}, | 586 | {.compatible = "mpc5200-i2c", |
587 | .data = &(struct mpc_i2c_match_data) { | ||
588 | .setclock = mpc_i2c_setclock_52xx, | ||
589 | }, | ||
590 | }, | ||
591 | {.compatible = "fsl,mpc5200b-i2c", | ||
592 | .data = &(struct mpc_i2c_match_data) { | ||
593 | .setclock = mpc_i2c_setclock_52xx, | ||
594 | }, | ||
595 | }, | ||
596 | {.compatible = "fsl,mpc5200-i2c", | ||
597 | .data = &(struct mpc_i2c_match_data) { | ||
598 | .setclock = mpc_i2c_setclock_52xx, | ||
599 | }, | ||
600 | }, | ||
601 | {.compatible = "fsl,mpc8313-i2c", | ||
602 | .data = &(struct mpc_i2c_match_data) { | ||
603 | .setclock = mpc_i2c_setclock_8xxx, | ||
604 | }, | ||
605 | }, | ||
606 | {.compatible = "fsl,mpc8543-i2c", | ||
607 | .data = &(struct mpc_i2c_match_data) { | ||
608 | .setclock = mpc_i2c_setclock_8xxx, | ||
609 | .prescaler = 2, | ||
610 | }, | ||
611 | }, | ||
612 | {.compatible = "fsl,mpc8544-i2c", | ||
613 | .data = &(struct mpc_i2c_match_data) { | ||
614 | .setclock = mpc_i2c_setclock_8xxx, | ||
615 | .prescaler = 3, | ||
616 | }, | ||
617 | /* Backward compatibility */ | ||
618 | }, | ||
619 | {.compatible = "fsl-i2c", }, | ||
395 | {}, | 620 | {}, |
396 | }; | 621 | }; |
622 | |||
397 | MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); | 623 | MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); |
398 | 624 | ||
399 | 625 | ||
@@ -414,7 +640,7 @@ static int __init fsl_i2c_init(void) | |||
414 | 640 | ||
415 | rv = of_register_platform_driver(&mpc_i2c_driver); | 641 | rv = of_register_platform_driver(&mpc_i2c_driver); |
416 | if (rv) | 642 | if (rv) |
417 | printk(KERN_ERR DRV_NAME | 643 | printk(KERN_ERR DRV_NAME |
418 | " of_register_platform_driver failed (%i)\n", rv); | 644 | " of_register_platform_driver failed (%i)\n", rv); |
419 | return rv; | 645 | return rv; |
420 | } | 646 | } |
@@ -428,6 +654,6 @@ module_init(fsl_i2c_init); | |||
428 | module_exit(fsl_i2c_exit); | 654 | module_exit(fsl_i2c_exit); |
429 | 655 | ||
430 | MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); | 656 | MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); |
431 | MODULE_DESCRIPTION | 657 | MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and " |
432 | ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors"); | 658 | "MPC824x/85xx/52xx processors"); |
433 | MODULE_LICENSE("GPL"); | 659 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 5b7f95641ba4..1691ef0f1ee1 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* linux/drivers/i2c/busses/i2c-s3c2410.c | 1 | /* linux/drivers/i2c/busses/i2c-s3c2410.c |
2 | * | 2 | * |
3 | * Copyright (C) 2004,2005 Simtec Electronics | 3 | * Copyright (C) 2004,2005,2009 Simtec Electronics |
4 | * Ben Dooks <ben@simtec.co.uk> | 4 | * Ben Dooks <ben@simtec.co.uk> |
5 | * | 5 | * |
6 | * S3C2410 I2C Controller | 6 | * S3C2410 I2C Controller |
@@ -590,18 +590,6 @@ static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, | |||
590 | return clkin / (calc_divs * calc_div1); | 590 | return clkin / (calc_divs * calc_div1); |
591 | } | 591 | } |
592 | 592 | ||
593 | /* freq_acceptable | ||
594 | * | ||
595 | * test wether a frequency is within the acceptable range of error | ||
596 | */ | ||
597 | |||
598 | static inline int freq_acceptable(unsigned int freq, unsigned int wanted) | ||
599 | { | ||
600 | int diff = freq - wanted; | ||
601 | |||
602 | return diff >= -2 && diff <= 2; | ||
603 | } | ||
604 | |||
605 | /* s3c24xx_i2c_clockrate | 593 | /* s3c24xx_i2c_clockrate |
606 | * | 594 | * |
607 | * work out a divisor for the user requested frequency setting, | 595 | * work out a divisor for the user requested frequency setting, |
@@ -614,44 +602,28 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) | |||
614 | struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data; | 602 | struct s3c2410_platform_i2c *pdata = i2c->dev->platform_data; |
615 | unsigned long clkin = clk_get_rate(i2c->clk); | 603 | unsigned long clkin = clk_get_rate(i2c->clk); |
616 | unsigned int divs, div1; | 604 | unsigned int divs, div1; |
605 | unsigned long target_frequency; | ||
617 | u32 iiccon; | 606 | u32 iiccon; |
618 | int freq; | 607 | int freq; |
619 | int start, end; | ||
620 | 608 | ||
621 | i2c->clkrate = clkin; | 609 | i2c->clkrate = clkin; |
622 | clkin /= 1000; /* clkin now in KHz */ | 610 | clkin /= 1000; /* clkin now in KHz */ |
623 | 611 | ||
624 | dev_dbg(i2c->dev, "pdata %p, freq %lu %lu..%lu\n", | 612 | dev_dbg(i2c->dev, "pdata desired frequency %lu\n", pdata->frequency); |
625 | pdata, pdata->bus_freq, pdata->min_freq, pdata->max_freq); | ||
626 | |||
627 | if (pdata->bus_freq != 0) { | ||
628 | freq = s3c24xx_i2c_calcdivisor(clkin, pdata->bus_freq/1000, | ||
629 | &div1, &divs); | ||
630 | if (freq_acceptable(freq, pdata->bus_freq/1000)) | ||
631 | goto found; | ||
632 | } | ||
633 | |||
634 | /* ok, we may have to search for something suitable... */ | ||
635 | 613 | ||
636 | start = (pdata->max_freq == 0) ? pdata->bus_freq : pdata->max_freq; | 614 | target_frequency = pdata->frequency ? pdata->frequency : 100000; |
637 | end = pdata->min_freq; | ||
638 | 615 | ||
639 | start /= 1000; | 616 | target_frequency /= 1000; /* Target frequency now in KHz */ |
640 | end /= 1000; | ||
641 | 617 | ||
642 | /* search loop... */ | 618 | freq = s3c24xx_i2c_calcdivisor(clkin, target_frequency, &div1, &divs); |
643 | 619 | ||
644 | for (; start > end; start--) { | 620 | if (freq > target_frequency) { |
645 | freq = s3c24xx_i2c_calcdivisor(clkin, start, &div1, &divs); | 621 | dev_err(i2c->dev, |
646 | if (freq_acceptable(freq, start)) | 622 | "Unable to achieve desired frequency %luKHz." \ |
647 | goto found; | 623 | " Lowest achievable %dKHz\n", target_frequency, freq); |
624 | return -EINVAL; | ||
648 | } | 625 | } |
649 | 626 | ||
650 | /* cannot find frequency spec */ | ||
651 | |||
652 | return -EINVAL; | ||
653 | |||
654 | found: | ||
655 | *got = freq; | 627 | *got = freq; |
656 | 628 | ||
657 | iiccon = readl(i2c->regs + S3C2410_IICCON); | 629 | iiccon = readl(i2c->regs + S3C2410_IICCON); |
@@ -663,6 +635,23 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) | |||
663 | 635 | ||
664 | writel(iiccon, i2c->regs + S3C2410_IICCON); | 636 | writel(iiccon, i2c->regs + S3C2410_IICCON); |
665 | 637 | ||
638 | if (s3c24xx_i2c_is2440(i2c)) { | ||
639 | unsigned long sda_delay; | ||
640 | |||
641 | if (pdata->sda_delay) { | ||
642 | sda_delay = (freq / 1000) * pdata->sda_delay; | ||
643 | sda_delay /= 1000000; | ||
644 | sda_delay = DIV_ROUND_UP(sda_delay, 5); | ||
645 | if (sda_delay > 3) | ||
646 | sda_delay = 3; | ||
647 | sda_delay |= S3C2410_IICLC_FILTER_ON; | ||
648 | } else | ||
649 | sda_delay = 0; | ||
650 | |||
651 | dev_dbg(i2c->dev, "IICLC=%08lx\n", sda_delay); | ||
652 | writel(sda_delay, i2c->regs + S3C2440_IICLC); | ||
653 | } | ||
654 | |||
666 | return 0; | 655 | return 0; |
667 | } | 656 | } |
668 | 657 | ||
@@ -769,11 +758,8 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) | |||
769 | 758 | ||
770 | /* check for s3c2440 i2c controller */ | 759 | /* check for s3c2440 i2c controller */ |
771 | 760 | ||
772 | if (s3c24xx_i2c_is2440(i2c)) { | 761 | if (s3c24xx_i2c_is2440(i2c)) |
773 | dev_dbg(i2c->dev, "S3C2440_IICLC=%08x\n", pdata->sda_delay); | 762 | writel(0x0, i2c->regs + S3C2440_IICLC); |
774 | |||
775 | writel(pdata->sda_delay, i2c->regs + S3C2440_IICLC); | ||
776 | } | ||
777 | 763 | ||
778 | return 0; | 764 | return 0; |
779 | } | 765 | } |
@@ -1018,14 +1004,13 @@ static int __init i2c_adap_s3c_init(void) | |||
1018 | 1004 | ||
1019 | return ret; | 1005 | return ret; |
1020 | } | 1006 | } |
1007 | subsys_initcall(i2c_adap_s3c_init); | ||
1021 | 1008 | ||
1022 | static void __exit i2c_adap_s3c_exit(void) | 1009 | static void __exit i2c_adap_s3c_exit(void) |
1023 | { | 1010 | { |
1024 | platform_driver_unregister(&s3c2410_i2c_driver); | 1011 | platform_driver_unregister(&s3c2410_i2c_driver); |
1025 | platform_driver_unregister(&s3c2440_i2c_driver); | 1012 | platform_driver_unregister(&s3c2440_i2c_driver); |
1026 | } | 1013 | } |
1027 | |||
1028 | module_init(i2c_adap_s3c_init); | ||
1029 | module_exit(i2c_adap_s3c_exit); | 1014 | module_exit(i2c_adap_s3c_exit); |
1030 | 1015 | ||
1031 | MODULE_DESCRIPTION("S3C24XX I2C Bus driver"); | 1016 | MODULE_DESCRIPTION("S3C24XX I2C Bus driver"); |
diff --git a/drivers/i2c/busses/i2c-s6000.c b/drivers/i2c/busses/i2c-s6000.c new file mode 100644 index 000000000000..c91359f4965c --- /dev/null +++ b/drivers/i2c/busses/i2c-s6000.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-s6000.c | ||
3 | * | ||
4 | * Description: Driver for S6000 Family I2C Interface | ||
5 | * Copyright (c) 2008 emlix GmbH | ||
6 | * Author: Oskar Schirmer <os@emlix.com> | ||
7 | * | ||
8 | * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com> | ||
9 | * Copyright (c) 2005-2007 Analog Devices, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/clk.h> | ||
27 | #include <linux/err.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/i2c.h> | ||
33 | #include <linux/i2c/s6000.h> | ||
34 | #include <linux/timer.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/completion.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include "i2c-s6000.h" | ||
42 | |||
43 | #define DRV_NAME "i2c-s6000" | ||
44 | |||
45 | #define POLL_TIMEOUT (2 * HZ) | ||
46 | |||
47 | struct s6i2c_if { | ||
48 | u8 __iomem *reg; /* memory mapped registers */ | ||
49 | int irq; | ||
50 | spinlock_t lock; | ||
51 | struct i2c_msg *msgs; /* messages currently handled */ | ||
52 | int msgs_num; /* nb of msgs to do */ | ||
53 | int msgs_push; /* nb of msgs read/written */ | ||
54 | int msgs_done; /* nb of msgs finally handled */ | ||
55 | unsigned push; /* nb of bytes read/written in msg */ | ||
56 | unsigned done; /* nb of bytes finally handled */ | ||
57 | int timeout_count; /* timeout retries left */ | ||
58 | struct timer_list timeout_timer; | ||
59 | struct i2c_adapter adap; | ||
60 | struct completion complete; | ||
61 | struct clk *clk; | ||
62 | struct resource *res; | ||
63 | }; | ||
64 | |||
65 | static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n) | ||
66 | { | ||
67 | return readw(iface->reg + (n)); | ||
68 | } | ||
69 | |||
70 | static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v) | ||
71 | { | ||
72 | writew(v, iface->reg + (n)); | ||
73 | } | ||
74 | |||
75 | static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n) | ||
76 | { | ||
77 | return readl(iface->reg + (n)); | ||
78 | } | ||
79 | |||
80 | static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v) | ||
81 | { | ||
82 | writel(v, iface->reg + (n)); | ||
83 | } | ||
84 | |||
85 | static struct s6i2c_if s6i2c_if; | ||
86 | |||
87 | static void s6i2c_handle_interrupt(struct s6i2c_if *iface) | ||
88 | { | ||
89 | if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) { | ||
90 | i2c_rd16(iface, S6_I2C_CLRTXABRT); | ||
91 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
92 | complete(&iface->complete); | ||
93 | return; | ||
94 | } | ||
95 | if (iface->msgs_done >= iface->msgs_num) { | ||
96 | dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n", | ||
97 | i2c_rd16(iface, S6_I2C_INTRSTAT)); | ||
98 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
99 | return; | ||
100 | } | ||
101 | while ((iface->msgs_push < iface->msgs_num) | ||
102 | && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) { | ||
103 | struct i2c_msg *m = &iface->msgs[iface->msgs_push]; | ||
104 | if (!(m->flags & I2C_M_RD)) | ||
105 | i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]); | ||
106 | else | ||
107 | i2c_wr16(iface, S6_I2C_DATACMD, | ||
108 | 1 << S6_I2C_DATACMD_READ); | ||
109 | if (++iface->push >= m->len) { | ||
110 | iface->push = 0; | ||
111 | iface->msgs_push += 1; | ||
112 | } | ||
113 | } | ||
114 | do { | ||
115 | struct i2c_msg *m = &iface->msgs[iface->msgs_done]; | ||
116 | if (!(m->flags & I2C_M_RD)) { | ||
117 | if (iface->msgs_done < iface->msgs_push) | ||
118 | iface->msgs_done += 1; | ||
119 | else | ||
120 | break; | ||
121 | } else if (i2c_rd16(iface, S6_I2C_STATUS) | ||
122 | & (1 << S6_I2C_STATUS_RFNE)) { | ||
123 | m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD); | ||
124 | if (++iface->done >= m->len) { | ||
125 | iface->done = 0; | ||
126 | iface->msgs_done += 1; | ||
127 | } | ||
128 | } else{ | ||
129 | break; | ||
130 | } | ||
131 | } while (iface->msgs_done < iface->msgs_num); | ||
132 | if (iface->msgs_done >= iface->msgs_num) { | ||
133 | i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT); | ||
134 | complete(&iface->complete); | ||
135 | } else if (iface->msgs_push >= iface->msgs_num) { | ||
136 | i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) | | ||
137 | (1 << S6_I2C_INTR_RXFULL)); | ||
138 | } else { | ||
139 | i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) | | ||
140 | (1 << S6_I2C_INTR_TXEMPTY) | | ||
141 | (1 << S6_I2C_INTR_RXFULL)); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id) | ||
146 | { | ||
147 | struct s6i2c_if *iface = dev_id; | ||
148 | if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER) | ||
149 | | (1 << S6_I2C_INTR_RXOVER) | ||
150 | | (1 << S6_I2C_INTR_RXFULL) | ||
151 | | (1 << S6_I2C_INTR_TXOVER) | ||
152 | | (1 << S6_I2C_INTR_TXEMPTY) | ||
153 | | (1 << S6_I2C_INTR_RDREQ) | ||
154 | | (1 << S6_I2C_INTR_TXABRT) | ||
155 | | (1 << S6_I2C_INTR_RXDONE) | ||
156 | | (1 << S6_I2C_INTR_ACTIVITY) | ||
157 | | (1 << S6_I2C_INTR_STOPDET) | ||
158 | | (1 << S6_I2C_INTR_STARTDET) | ||
159 | | (1 << S6_I2C_INTR_GENCALL)))) | ||
160 | return IRQ_NONE; | ||
161 | |||
162 | spin_lock(&iface->lock); | ||
163 | del_timer(&iface->timeout_timer); | ||
164 | s6i2c_handle_interrupt(iface); | ||
165 | spin_unlock(&iface->lock); | ||
166 | return IRQ_HANDLED; | ||
167 | } | ||
168 | |||
169 | static void s6i2c_timeout(unsigned long data) | ||
170 | { | ||
171 | struct s6i2c_if *iface = (struct s6i2c_if *)data; | ||
172 | unsigned long flags; | ||
173 | |||
174 | spin_lock_irqsave(&iface->lock, flags); | ||
175 | s6i2c_handle_interrupt(iface); | ||
176 | if (--iface->timeout_count > 0) { | ||
177 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
178 | add_timer(&iface->timeout_timer); | ||
179 | } else { | ||
180 | complete(&iface->complete); | ||
181 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
182 | } | ||
183 | spin_unlock_irqrestore(&iface->lock, flags); | ||
184 | } | ||
185 | |||
186 | static int s6i2c_master_xfer(struct i2c_adapter *adap, | ||
187 | struct i2c_msg *msgs, int num) | ||
188 | { | ||
189 | struct s6i2c_if *iface = adap->algo_data; | ||
190 | int i; | ||
191 | if (num == 0) | ||
192 | return 0; | ||
193 | if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY)) | ||
194 | yield(); | ||
195 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
196 | i2c_rd16(iface, S6_I2C_CLRINTR); | ||
197 | for (i = 0; i < num; i++) { | ||
198 | if (msgs[i].flags & I2C_M_TEN) { | ||
199 | dev_err(&adap->dev, | ||
200 | "s6i2c: 10 bits addr not supported\n"); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | if (msgs[i].len == 0) { | ||
204 | dev_err(&adap->dev, | ||
205 | "s6i2c: zero length message not supported\n"); | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | if (msgs[i].addr != msgs[0].addr) { | ||
209 | dev_err(&adap->dev, | ||
210 | "s6i2c: multiple xfer cannot change target\n"); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | iface->msgs = msgs; | ||
216 | iface->msgs_num = num; | ||
217 | iface->msgs_push = 0; | ||
218 | iface->msgs_done = 0; | ||
219 | iface->push = 0; | ||
220 | iface->done = 0; | ||
221 | iface->timeout_count = 10; | ||
222 | i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr); | ||
223 | i2c_wr16(iface, S6_I2C_ENABLE, 1); | ||
224 | i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) | | ||
225 | (1 << S6_I2C_INTR_TXABRT)); | ||
226 | |||
227 | iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; | ||
228 | add_timer(&iface->timeout_timer); | ||
229 | wait_for_completion(&iface->complete); | ||
230 | del_timer_sync(&iface->timeout_timer); | ||
231 | while (i2c_rd32(iface, S6_I2C_TXFLR) > 0) | ||
232 | schedule(); | ||
233 | while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY)) | ||
234 | schedule(); | ||
235 | |||
236 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
237 | i2c_wr16(iface, S6_I2C_ENABLE, 0); | ||
238 | return iface->msgs_done; | ||
239 | } | ||
240 | |||
241 | static u32 s6i2c_functionality(struct i2c_adapter *adap) | ||
242 | { | ||
243 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
244 | } | ||
245 | |||
246 | static struct i2c_algorithm s6i2c_algorithm = { | ||
247 | .master_xfer = s6i2c_master_xfer, | ||
248 | .functionality = s6i2c_functionality, | ||
249 | }; | ||
250 | |||
251 | static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns) | ||
252 | { | ||
253 | u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000; | ||
254 | if (dividend > 0xffff) | ||
255 | return 0xffff; | ||
256 | return dividend; | ||
257 | } | ||
258 | |||
259 | static int __devinit s6i2c_probe(struct platform_device *dev) | ||
260 | { | ||
261 | struct s6i2c_if *iface = &s6i2c_if; | ||
262 | struct i2c_adapter *p_adap; | ||
263 | const char *clock; | ||
264 | int bus_num, rc; | ||
265 | spin_lock_init(&iface->lock); | ||
266 | init_completion(&iface->complete); | ||
267 | iface->irq = platform_get_irq(dev, 0); | ||
268 | if (iface->irq < 0) { | ||
269 | rc = iface->irq; | ||
270 | goto err_out; | ||
271 | } | ||
272 | iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
273 | if (!iface->res) { | ||
274 | rc = -ENXIO; | ||
275 | goto err_out; | ||
276 | } | ||
277 | iface->res = request_mem_region(iface->res->start, | ||
278 | resource_size(iface->res), | ||
279 | dev->dev.bus_id); | ||
280 | if (!iface->res) { | ||
281 | rc = -EBUSY; | ||
282 | goto err_out; | ||
283 | } | ||
284 | iface->reg = ioremap_nocache(iface->res->start, | ||
285 | resource_size(iface->res)); | ||
286 | if (!iface->reg) { | ||
287 | rc = -ENOMEM; | ||
288 | goto err_reg; | ||
289 | } | ||
290 | |||
291 | clock = 0; | ||
292 | bus_num = -1; | ||
293 | if (dev->dev.platform_data) { | ||
294 | struct s6_i2c_platform_data *pdata = dev->dev.platform_data; | ||
295 | bus_num = pdata->bus_num; | ||
296 | clock = pdata->clock; | ||
297 | } | ||
298 | iface->clk = clk_get(&dev->dev, clock); | ||
299 | if (IS_ERR(iface->clk)) { | ||
300 | rc = PTR_ERR(iface->clk); | ||
301 | goto err_map; | ||
302 | } | ||
303 | rc = clk_enable(iface->clk); | ||
304 | if (rc < 0) | ||
305 | goto err_clk_put; | ||
306 | init_timer(&iface->timeout_timer); | ||
307 | iface->timeout_timer.function = s6i2c_timeout; | ||
308 | iface->timeout_timer.data = (unsigned long)iface; | ||
309 | |||
310 | p_adap = &iface->adap; | ||
311 | strlcpy(p_adap->name, dev->name, sizeof(p_adap->name)); | ||
312 | p_adap->algo = &s6i2c_algorithm; | ||
313 | p_adap->algo_data = iface; | ||
314 | p_adap->nr = bus_num; | ||
315 | p_adap->class = 0; | ||
316 | p_adap->dev.parent = &dev->dev; | ||
317 | i2c_wr16(iface, S6_I2C_INTRMASK, 0); | ||
318 | rc = request_irq(iface->irq, s6i2c_interrupt_entry, | ||
319 | IRQF_SHARED, dev->name, iface); | ||
320 | if (rc) { | ||
321 | dev_err(&p_adap->dev, "s6i2c: cant get IRQ %d\n", iface->irq); | ||
322 | goto err_clk_dis; | ||
323 | } | ||
324 | |||
325 | i2c_wr16(iface, S6_I2C_ENABLE, 0); | ||
326 | udelay(1); | ||
327 | i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST); | ||
328 | i2c_wr16(iface, S6_I2C_CLRTXABRT, 1); | ||
329 | i2c_wr16(iface, S6_I2C_CON, | ||
330 | (1 << S6_I2C_CON_MASTER) | | ||
331 | (S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) | | ||
332 | (0 << S6_I2C_CON_10BITSLAVE) | | ||
333 | (0 << S6_I2C_CON_10BITMASTER) | | ||
334 | (1 << S6_I2C_CON_RESTARTENA) | | ||
335 | (1 << S6_I2C_CON_SLAVEDISABLE)); | ||
336 | i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000)); | ||
337 | i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700)); | ||
338 | i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600)); | ||
339 | i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300)); | ||
340 | i2c_wr16(iface, S6_I2C_RXTL, 0); | ||
341 | i2c_wr16(iface, S6_I2C_TXTL, 0); | ||
342 | |||
343 | platform_set_drvdata(dev, iface); | ||
344 | if (bus_num < 0) | ||
345 | rc = i2c_add_adapter(p_adap); | ||
346 | else | ||
347 | rc = i2c_add_numbered_adapter(p_adap); | ||
348 | if (rc) | ||
349 | goto err_irq_free; | ||
350 | return 0; | ||
351 | |||
352 | err_irq_free: | ||
353 | free_irq(iface->irq, iface); | ||
354 | err_clk_dis: | ||
355 | clk_disable(iface->clk); | ||
356 | err_clk_put: | ||
357 | clk_put(iface->clk); | ||
358 | err_map: | ||
359 | iounmap(iface->reg); | ||
360 | err_reg: | ||
361 | release_mem_region(iface->res->start, | ||
362 | resource_size(iface->res)); | ||
363 | err_out: | ||
364 | return rc; | ||
365 | } | ||
366 | |||
367 | static int __devexit s6i2c_remove(struct platform_device *pdev) | ||
368 | { | ||
369 | struct s6i2c_if *iface = platform_get_drvdata(pdev); | ||
370 | i2c_wr16(iface, S6_I2C_ENABLE, 0); | ||
371 | platform_set_drvdata(pdev, NULL); | ||
372 | i2c_del_adapter(&iface->adap); | ||
373 | free_irq(iface->irq, iface); | ||
374 | clk_disable(iface->clk); | ||
375 | clk_put(iface->clk); | ||
376 | iounmap(iface->reg); | ||
377 | release_mem_region(iface->res->start, | ||
378 | resource_size(iface->res)); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static struct platform_driver s6i2c_driver = { | ||
383 | .probe = s6i2c_probe, | ||
384 | .remove = __devexit_p(s6i2c_remove), | ||
385 | .driver = { | ||
386 | .name = DRV_NAME, | ||
387 | .owner = THIS_MODULE, | ||
388 | }, | ||
389 | }; | ||
390 | |||
391 | static int __init s6i2c_init(void) | ||
392 | { | ||
393 | pr_info("I2C: S6000 I2C driver\n"); | ||
394 | return platform_driver_register(&s6i2c_driver); | ||
395 | } | ||
396 | |||
397 | static void __exit s6i2c_exit(void) | ||
398 | { | ||
399 | platform_driver_unregister(&s6i2c_driver); | ||
400 | } | ||
401 | |||
402 | MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C"); | ||
403 | MODULE_LICENSE("GPL"); | ||
404 | MODULE_ALIAS("platform:" DRV_NAME); | ||
405 | |||
406 | subsys_initcall(s6i2c_init); | ||
407 | module_exit(s6i2c_exit); | ||
diff --git a/drivers/i2c/busses/i2c-s6000.h b/drivers/i2c/busses/i2c-s6000.h new file mode 100644 index 000000000000..ff23b81ded44 --- /dev/null +++ b/drivers/i2c/busses/i2c-s6000.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * drivers/i2c/busses/i2c-s6000.h | ||
3 | * | ||
4 | * This file is subject to the terms and conditions of the GNU General Public | ||
5 | * License. See the file "COPYING" in the main directory of this archive | ||
6 | * for more details. | ||
7 | * | ||
8 | * Copyright (C) 2008 Emlix GmbH <info@emlix.com> | ||
9 | * Author: Oskar Schirmer <os@emlix.com> | ||
10 | */ | ||
11 | |||
12 | #ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H | ||
13 | #define __DRIVERS_I2C_BUSSES_I2C_S6000_H | ||
14 | |||
15 | #define S6_I2C_CON 0x000 | ||
16 | #define S6_I2C_CON_MASTER 0 | ||
17 | #define S6_I2C_CON_SPEED 1 | ||
18 | #define S6_I2C_CON_SPEED_NORMAL 1 | ||
19 | #define S6_I2C_CON_SPEED_FAST 2 | ||
20 | #define S6_I2C_CON_SPEED_MASK 3 | ||
21 | #define S6_I2C_CON_10BITSLAVE 3 | ||
22 | #define S6_I2C_CON_10BITMASTER 4 | ||
23 | #define S6_I2C_CON_RESTARTENA 5 | ||
24 | #define S6_I2C_CON_SLAVEDISABLE 6 | ||
25 | #define S6_I2C_TAR 0x004 | ||
26 | #define S6_I2C_TAR_GCORSTART 10 | ||
27 | #define S6_I2C_TAR_SPECIAL 11 | ||
28 | #define S6_I2C_SAR 0x008 | ||
29 | #define S6_I2C_HSMADDR 0x00C | ||
30 | #define S6_I2C_DATACMD 0x010 | ||
31 | #define S6_I2C_DATACMD_READ 8 | ||
32 | #define S6_I2C_SSHCNT 0x014 | ||
33 | #define S6_I2C_SSLCNT 0x018 | ||
34 | #define S6_I2C_FSHCNT 0x01C | ||
35 | #define S6_I2C_FSLCNT 0x020 | ||
36 | #define S6_I2C_INTRSTAT 0x02C | ||
37 | #define S6_I2C_INTRMASK 0x030 | ||
38 | #define S6_I2C_RAWINTR 0x034 | ||
39 | #define S6_I2C_INTR_RXUNDER 0 | ||
40 | #define S6_I2C_INTR_RXOVER 1 | ||
41 | #define S6_I2C_INTR_RXFULL 2 | ||
42 | #define S6_I2C_INTR_TXOVER 3 | ||
43 | #define S6_I2C_INTR_TXEMPTY 4 | ||
44 | #define S6_I2C_INTR_RDREQ 5 | ||
45 | #define S6_I2C_INTR_TXABRT 6 | ||
46 | #define S6_I2C_INTR_RXDONE 7 | ||
47 | #define S6_I2C_INTR_ACTIVITY 8 | ||
48 | #define S6_I2C_INTR_STOPDET 9 | ||
49 | #define S6_I2C_INTR_STARTDET 10 | ||
50 | #define S6_I2C_INTR_GENCALL 11 | ||
51 | #define S6_I2C_RXTL 0x038 | ||
52 | #define S6_I2C_TXTL 0x03C | ||
53 | #define S6_I2C_CLRINTR 0x040 | ||
54 | #define S6_I2C_CLRRXUNDER 0x044 | ||
55 | #define S6_I2C_CLRRXOVER 0x048 | ||
56 | #define S6_I2C_CLRTXOVER 0x04C | ||
57 | #define S6_I2C_CLRRDREQ 0x050 | ||
58 | #define S6_I2C_CLRTXABRT 0x054 | ||
59 | #define S6_I2C_CLRRXDONE 0x058 | ||
60 | #define S6_I2C_CLRACTIVITY 0x05C | ||
61 | #define S6_I2C_CLRSTOPDET 0x060 | ||
62 | #define S6_I2C_CLRSTARTDET 0x064 | ||
63 | #define S6_I2C_CLRGENCALL 0x068 | ||
64 | #define S6_I2C_ENABLE 0x06C | ||
65 | #define S6_I2C_STATUS 0x070 | ||
66 | #define S6_I2C_STATUS_ACTIVITY 0 | ||
67 | #define S6_I2C_STATUS_TFNF 1 | ||
68 | #define S6_I2C_STATUS_TFE 2 | ||
69 | #define S6_I2C_STATUS_RFNE 3 | ||
70 | #define S6_I2C_STATUS_RFF 4 | ||
71 | #define S6_I2C_TXFLR 0x074 | ||
72 | #define S6_I2C_RXFLR 0x078 | ||
73 | #define S6_I2C_SRESET 0x07C | ||
74 | #define S6_I2C_SRESET_IC_SRST 0 | ||
75 | #define S6_I2C_SRESET_IC_MASTER_SRST 1 | ||
76 | #define S6_I2C_SRESET_IC_SLAVE_SRST 2 | ||
77 | #define S6_I2C_TXABRTSOURCE 0x080 | ||
78 | |||
79 | #endif | ||