diff options
Diffstat (limited to 'drivers/i2c/busses')
-rw-r--r-- | drivers/i2c/busses/Kconfig | 19 | ||||
-rw-r--r-- | drivers/i2c/busses/Makefile | 1 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-pnx.c | 708 |
3 files changed, 728 insertions, 0 deletions
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 7c9ab337d180..291da25e84d1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -536,4 +536,23 @@ config I2C_MV64XXX | |||
536 | This driver can also be built as a module. If so, the module | 536 | This driver can also be built as a module. If so, the module |
537 | will be called i2c-mv64xxx. | 537 | will be called i2c-mv64xxx. |
538 | 538 | ||
539 | config I2C_PNX | ||
540 | tristate "I2C bus support for Philips PNX targets" | ||
541 | depends on ARCH_PNX4008 && I2C | ||
542 | help | ||
543 | This driver supports the Philips IP3204 I2C IP block master and/or | ||
544 | slave controller | ||
545 | |||
546 | This driver can also be built as a module. If so, the module | ||
547 | will be called i2c-pnx. | ||
548 | |||
549 | config I2C_PNX_EARLY | ||
550 | bool "Early initialization for I2C on PNXxxxx" | ||
551 | depends on I2C_PNX=y | ||
552 | help | ||
553 | Under certain circumstances one may need to make sure I2C on PNXxxxx | ||
554 | is initialized earlier than some other driver that depends on it | ||
555 | (for instance, that might be USB in case of PNX4008). With this | ||
556 | option turned on you can guarantee that. | ||
557 | |||
539 | endmenu | 558 | endmenu |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index bf5fd078b292..626ac71af959 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -28,6 +28,7 @@ obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o | |||
28 | obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o | 28 | obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o |
29 | obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o | 29 | obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o |
30 | obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o | 30 | obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o |
31 | obj-$(CONFIG_I2C_PNX) += i2c-pnx.o | ||
31 | obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o | 32 | obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o |
32 | obj-$(CONFIG_I2C_PXA) += i2c-pxa.o | 33 | obj-$(CONFIG_I2C_PXA) += i2c-pxa.o |
33 | obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o | 34 | obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o |
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c new file mode 100644 index 000000000000..de0bca77e926 --- /dev/null +++ b/drivers/i2c/busses/i2c-pnx.c | |||
@@ -0,0 +1,708 @@ | |||
1 | /* | ||
2 | * Provides I2C support for Philips PNX010x/PNX4008 boards. | ||
3 | * | ||
4 | * Authors: Dennis Kovalev <dkovalev@ru.mvista.com> | ||
5 | * Vitaly Wool <vwool@ru.mvista.com> | ||
6 | * | ||
7 | * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under | ||
8 | * the terms of the GNU General Public License version 2. This program | ||
9 | * is licensed "as is" without any warranty of any kind, whether express | ||
10 | * or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/ioport.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <linux/timer.h> | ||
19 | #include <linux/completion.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/i2c-pnx.h> | ||
22 | #include <asm/hardware.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/uaccess.h> | ||
25 | |||
26 | #define I2C_PNX_TIMEOUT 10 /* msec */ | ||
27 | #define I2C_PNX_SPEED_KHZ 100 | ||
28 | #define I2C_PNX_REGION_SIZE 0x100 | ||
29 | #define PNX_DEFAULT_FREQ 13 /* MHz */ | ||
30 | |||
31 | static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) | ||
32 | { | ||
33 | while (timeout > 0 && | ||
34 | (ioread32(I2C_REG_STS(data)) & mstatus_active)) { | ||
35 | mdelay(1); | ||
36 | timeout--; | ||
37 | } | ||
38 | return (timeout <= 0); | ||
39 | } | ||
40 | |||
41 | static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) | ||
42 | { | ||
43 | while (timeout > 0 && | ||
44 | (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) { | ||
45 | mdelay(1); | ||
46 | timeout--; | ||
47 | } | ||
48 | return (timeout <= 0); | ||
49 | } | ||
50 | |||
51 | static inline void i2c_pnx_arm_timer(struct i2c_adapter *adap) | ||
52 | { | ||
53 | struct i2c_pnx_algo_data *data = adap->algo_data; | ||
54 | struct timer_list *timer = &data->mif.timer; | ||
55 | int expires = I2C_PNX_TIMEOUT / (1000 / HZ); | ||
56 | |||
57 | del_timer_sync(timer); | ||
58 | |||
59 | dev_dbg(&adap->dev, "Timer armed at %lu plus %u jiffies.\n", | ||
60 | jiffies, expires); | ||
61 | |||
62 | timer->expires = jiffies + expires; | ||
63 | timer->data = (unsigned long)adap; | ||
64 | |||
65 | add_timer(timer); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * i2c_pnx_start - start a device | ||
70 | * @slave_addr: slave address | ||
71 | * @adap: pointer to adapter structure | ||
72 | * | ||
73 | * Generate a START signal in the desired mode. | ||
74 | */ | ||
75 | static int i2c_pnx_start(unsigned char slave_addr, struct i2c_adapter *adap) | ||
76 | { | ||
77 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
78 | |||
79 | dev_dbg(&adap->dev, "%s(): addr 0x%x mode %d\n", __FUNCTION__, | ||
80 | slave_addr, alg_data->mif.mode); | ||
81 | |||
82 | /* Check for 7 bit slave addresses only */ | ||
83 | if (slave_addr & ~0x7f) { | ||
84 | dev_err(&adap->dev, "%s: Invalid slave address %x. " | ||
85 | "Only 7-bit addresses are supported\n", | ||
86 | adap->name, slave_addr); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | |||
90 | /* First, make sure bus is idle */ | ||
91 | if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { | ||
92 | /* Somebody else is monopolizing the bus */ | ||
93 | dev_err(&adap->dev, "%s: Bus busy. Slave addr = %02x, " | ||
94 | "cntrl = %x, stat = %x\n", | ||
95 | adap->name, slave_addr, | ||
96 | ioread32(I2C_REG_CTL(alg_data)), | ||
97 | ioread32(I2C_REG_STS(alg_data))); | ||
98 | return -EBUSY; | ||
99 | } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) { | ||
100 | /* Sorry, we lost the bus */ | ||
101 | dev_err(&adap->dev, "%s: Arbitration failure. " | ||
102 | "Slave addr = %02x\n", adap->name, slave_addr); | ||
103 | return -EIO; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * OK, I2C is enabled and we have the bus. | ||
108 | * Clear the current TDI and AFI status flags. | ||
109 | */ | ||
110 | iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi, | ||
111 | I2C_REG_STS(alg_data)); | ||
112 | |||
113 | dev_dbg(&adap->dev, "%s(): sending %#x\n", __FUNCTION__, | ||
114 | (slave_addr << 1) | start_bit | alg_data->mif.mode); | ||
115 | |||
116 | /* Write the slave address, START bit and R/W bit */ | ||
117 | iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode, | ||
118 | I2C_REG_TX(alg_data)); | ||
119 | |||
120 | dev_dbg(&adap->dev, "%s(): exit\n", __FUNCTION__); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * i2c_pnx_stop - stop a device | ||
127 | * @adap: pointer to I2C adapter structure | ||
128 | * | ||
129 | * Generate a STOP signal to terminate the master transaction. | ||
130 | */ | ||
131 | static void i2c_pnx_stop(struct i2c_adapter *adap) | ||
132 | { | ||
133 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
134 | /* Only 1 msec max timeout due to interrupt context */ | ||
135 | long timeout = 1000; | ||
136 | |||
137 | dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", | ||
138 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
139 | |||
140 | /* Write a STOP bit to TX FIFO */ | ||
141 | iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data)); | ||
142 | |||
143 | /* Wait until the STOP is seen. */ | ||
144 | while (timeout > 0 && | ||
145 | (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) { | ||
146 | /* may be called from interrupt context */ | ||
147 | udelay(1); | ||
148 | timeout--; | ||
149 | } | ||
150 | |||
151 | dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", | ||
152 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * i2c_pnx_master_xmit - transmit data to slave | ||
157 | * @adap: pointer to I2C adapter structure | ||
158 | * | ||
159 | * Sends one byte of data to the slave | ||
160 | */ | ||
161 | static int i2c_pnx_master_xmit(struct i2c_adapter *adap) | ||
162 | { | ||
163 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
164 | u32 val; | ||
165 | |||
166 | dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", | ||
167 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
168 | |||
169 | if (alg_data->mif.len > 0) { | ||
170 | /* We still have something to talk about... */ | ||
171 | val = *alg_data->mif.buf++; | ||
172 | |||
173 | if (alg_data->mif.len == 1) { | ||
174 | val |= stop_bit; | ||
175 | if (!alg_data->last) | ||
176 | val |= start_bit; | ||
177 | } | ||
178 | |||
179 | alg_data->mif.len--; | ||
180 | iowrite32(val, I2C_REG_TX(alg_data)); | ||
181 | |||
182 | dev_dbg(&adap->dev, "%s(): xmit %#x [%d]\n", __FUNCTION__, | ||
183 | val, alg_data->mif.len + 1); | ||
184 | |||
185 | if (alg_data->mif.len == 0) { | ||
186 | if (alg_data->last) { | ||
187 | /* Wait until the STOP is seen. */ | ||
188 | if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) | ||
189 | dev_err(&adap->dev, "The bus is still " | ||
190 | "active after timeout\n"); | ||
191 | } | ||
192 | /* Disable master interrupts */ | ||
193 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) & | ||
194 | ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), | ||
195 | I2C_REG_CTL(alg_data)); | ||
196 | |||
197 | del_timer_sync(&alg_data->mif.timer); | ||
198 | |||
199 | dev_dbg(&adap->dev, "%s(): Waking up xfer routine.\n", | ||
200 | __FUNCTION__); | ||
201 | |||
202 | complete(&alg_data->mif.complete); | ||
203 | } | ||
204 | } else if (alg_data->mif.len == 0) { | ||
205 | /* zero-sized transfer */ | ||
206 | i2c_pnx_stop(adap); | ||
207 | |||
208 | /* Disable master interrupts. */ | ||
209 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) & | ||
210 | ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), | ||
211 | I2C_REG_CTL(alg_data)); | ||
212 | |||
213 | /* Stop timer. */ | ||
214 | del_timer_sync(&alg_data->mif.timer); | ||
215 | dev_dbg(&adap->dev, "%s(): Waking up xfer routine after " | ||
216 | "zero-xfer.\n", __FUNCTION__); | ||
217 | |||
218 | complete(&alg_data->mif.complete); | ||
219 | } | ||
220 | |||
221 | dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", | ||
222 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | /** | ||
228 | * i2c_pnx_master_rcv - receive data from slave | ||
229 | * @adap: pointer to I2C adapter structure | ||
230 | * | ||
231 | * Reads one byte data from the slave | ||
232 | */ | ||
233 | static int i2c_pnx_master_rcv(struct i2c_adapter *adap) | ||
234 | { | ||
235 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
236 | unsigned int val = 0; | ||
237 | u32 ctl = 0; | ||
238 | |||
239 | dev_dbg(&adap->dev, "%s(): entering: stat = %04x.\n", | ||
240 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
241 | |||
242 | /* Check, whether there is already data, | ||
243 | * or we didn't 'ask' for it yet. | ||
244 | */ | ||
245 | if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { | ||
246 | dev_dbg(&adap->dev, "%s(): Write dummy data to fill " | ||
247 | "Rx-fifo...\n", __FUNCTION__); | ||
248 | |||
249 | if (alg_data->mif.len == 1) { | ||
250 | /* Last byte, do not acknowledge next rcv. */ | ||
251 | val |= stop_bit; | ||
252 | if (!alg_data->last) | ||
253 | val |= start_bit; | ||
254 | |||
255 | /* | ||
256 | * Enable interrupt RFDAIE (data in Rx fifo), | ||
257 | * and disable DRMIE (need data for Tx) | ||
258 | */ | ||
259 | ctl = ioread32(I2C_REG_CTL(alg_data)); | ||
260 | ctl |= mcntrl_rffie | mcntrl_daie; | ||
261 | ctl &= ~mcntrl_drmie; | ||
262 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Now we'll 'ask' for data: | ||
267 | * For each byte we want to receive, we must | ||
268 | * write a (dummy) byte to the Tx-FIFO. | ||
269 | */ | ||
270 | iowrite32(val, I2C_REG_TX(alg_data)); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /* Handle data. */ | ||
276 | if (alg_data->mif.len > 0) { | ||
277 | val = ioread32(I2C_REG_RX(alg_data)); | ||
278 | *alg_data->mif.buf++ = (u8) (val & 0xff); | ||
279 | dev_dbg(&adap->dev, "%s(): rcv 0x%x [%d]\n", __FUNCTION__, val, | ||
280 | alg_data->mif.len); | ||
281 | |||
282 | alg_data->mif.len--; | ||
283 | if (alg_data->mif.len == 0) { | ||
284 | if (alg_data->last) | ||
285 | /* Wait until the STOP is seen. */ | ||
286 | if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) | ||
287 | dev_err(&adap->dev, "The bus is still " | ||
288 | "active after timeout\n"); | ||
289 | |||
290 | /* Disable master interrupts */ | ||
291 | ctl = ioread32(I2C_REG_CTL(alg_data)); | ||
292 | ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | | ||
293 | mcntrl_drmie | mcntrl_daie); | ||
294 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
295 | |||
296 | /* Kill timer. */ | ||
297 | del_timer_sync(&alg_data->mif.timer); | ||
298 | complete(&alg_data->mif.complete); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | dev_dbg(&adap->dev, "%s(): exiting: stat = %04x.\n", | ||
303 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static irqreturn_t | ||
309 | i2c_pnx_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
310 | { | ||
311 | u32 stat, ctl; | ||
312 | struct i2c_adapter *adap = dev_id; | ||
313 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
314 | |||
315 | dev_dbg(&adap->dev, "%s(): mstat = %x mctrl = %x, mode = %d\n", | ||
316 | __FUNCTION__, | ||
317 | ioread32(I2C_REG_STS(alg_data)), | ||
318 | ioread32(I2C_REG_CTL(alg_data)), | ||
319 | alg_data->mif.mode); | ||
320 | stat = ioread32(I2C_REG_STS(alg_data)); | ||
321 | |||
322 | /* let's see what kind of event this is */ | ||
323 | if (stat & mstatus_afi) { | ||
324 | /* We lost arbitration in the midst of a transfer */ | ||
325 | alg_data->mif.ret = -EIO; | ||
326 | |||
327 | /* Disable master interrupts. */ | ||
328 | ctl = ioread32(I2C_REG_CTL(alg_data)); | ||
329 | ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | | ||
330 | mcntrl_drmie); | ||
331 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
332 | |||
333 | /* Stop timer, to prevent timeout. */ | ||
334 | del_timer_sync(&alg_data->mif.timer); | ||
335 | complete(&alg_data->mif.complete); | ||
336 | } else if (stat & mstatus_nai) { | ||
337 | /* Slave did not acknowledge, generate a STOP */ | ||
338 | dev_dbg(&adap->dev, "%s(): " | ||
339 | "Slave did not acknowledge, generating a STOP.\n", | ||
340 | __FUNCTION__); | ||
341 | i2c_pnx_stop(adap); | ||
342 | |||
343 | /* Disable master interrupts. */ | ||
344 | ctl = ioread32(I2C_REG_CTL(alg_data)); | ||
345 | ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | | ||
346 | mcntrl_drmie); | ||
347 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
348 | |||
349 | /* Our return value. */ | ||
350 | alg_data->mif.ret = -EIO; | ||
351 | |||
352 | /* Stop timer, to prevent timeout. */ | ||
353 | del_timer_sync(&alg_data->mif.timer); | ||
354 | complete(&alg_data->mif.complete); | ||
355 | } else { | ||
356 | /* | ||
357 | * Two options: | ||
358 | * - Master Tx needs data. | ||
359 | * - There is data in the Rx-fifo | ||
360 | * The latter is only the case if we have requested for data, | ||
361 | * via a dummy write. (See 'i2c_pnx_master_rcv'.) | ||
362 | * We therefore check, as a sanity check, whether that interrupt | ||
363 | * has been enabled. | ||
364 | */ | ||
365 | if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) { | ||
366 | if (alg_data->mif.mode == I2C_SMBUS_WRITE) { | ||
367 | i2c_pnx_master_xmit(adap); | ||
368 | } else if (alg_data->mif.mode == I2C_SMBUS_READ) { | ||
369 | i2c_pnx_master_rcv(adap); | ||
370 | } | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* Clear TDI and AFI bits */ | ||
375 | stat = ioread32(I2C_REG_STS(alg_data)); | ||
376 | iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); | ||
377 | |||
378 | dev_dbg(&adap->dev, "%s(): exiting, stat = %x ctrl = %x.\n", | ||
379 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data)), | ||
380 | ioread32(I2C_REG_CTL(alg_data))); | ||
381 | |||
382 | return IRQ_HANDLED; | ||
383 | } | ||
384 | |||
385 | static void i2c_pnx_timeout(unsigned long data) | ||
386 | { | ||
387 | struct i2c_adapter *adap = (struct i2c_adapter *)data; | ||
388 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
389 | u32 ctl; | ||
390 | |||
391 | dev_err(&adap->dev, "Master timed out. stat = %04x, cntrl = %04x. " | ||
392 | "Resetting master...\n", | ||
393 | ioread32(I2C_REG_STS(alg_data)), | ||
394 | ioread32(I2C_REG_CTL(alg_data))); | ||
395 | |||
396 | /* Reset master and disable interrupts */ | ||
397 | ctl = ioread32(I2C_REG_CTL(alg_data)); | ||
398 | ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie); | ||
399 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
400 | |||
401 | ctl |= mcntrl_reset; | ||
402 | iowrite32(ctl, I2C_REG_CTL(alg_data)); | ||
403 | wait_reset(I2C_PNX_TIMEOUT, alg_data); | ||
404 | alg_data->mif.ret = -EIO; | ||
405 | complete(&alg_data->mif.complete); | ||
406 | } | ||
407 | |||
408 | static inline void bus_reset_if_active(struct i2c_adapter *adap) | ||
409 | { | ||
410 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
411 | u32 stat; | ||
412 | |||
413 | if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { | ||
414 | dev_err(&adap->dev, | ||
415 | "%s: Bus is still active after xfer. Reset it...\n", | ||
416 | adap->name); | ||
417 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, | ||
418 | I2C_REG_CTL(alg_data)); | ||
419 | wait_reset(I2C_PNX_TIMEOUT, alg_data); | ||
420 | } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) { | ||
421 | /* If there is data in the fifo's after transfer, | ||
422 | * flush fifo's by reset. | ||
423 | */ | ||
424 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, | ||
425 | I2C_REG_CTL(alg_data)); | ||
426 | wait_reset(I2C_PNX_TIMEOUT, alg_data); | ||
427 | } else if (stat & mstatus_nai) { | ||
428 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, | ||
429 | I2C_REG_CTL(alg_data)); | ||
430 | wait_reset(I2C_PNX_TIMEOUT, alg_data); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * i2c_pnx_xfer - generic transfer entry point | ||
436 | * @adap: pointer to I2C adapter structure | ||
437 | * @msgs: array of messages | ||
438 | * @num: number of messages | ||
439 | * | ||
440 | * Initiates the transfer | ||
441 | */ | ||
442 | static int | ||
443 | i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | ||
444 | { | ||
445 | struct i2c_msg *pmsg; | ||
446 | int rc = 0, completed = 0, i; | ||
447 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
448 | u32 stat = ioread32(I2C_REG_STS(alg_data)); | ||
449 | |||
450 | dev_dbg(&adap->dev, "%s(): entering: %d messages, stat = %04x.\n", | ||
451 | __FUNCTION__, num, ioread32(I2C_REG_STS(alg_data))); | ||
452 | |||
453 | bus_reset_if_active(adap); | ||
454 | |||
455 | /* Process transactions in a loop. */ | ||
456 | for (i = 0; rc >= 0 && i < num; i++) { | ||
457 | u8 addr; | ||
458 | |||
459 | pmsg = &msgs[i]; | ||
460 | addr = pmsg->addr; | ||
461 | |||
462 | if (pmsg->flags & I2C_M_TEN) { | ||
463 | dev_err(&adap->dev, | ||
464 | "%s: 10 bits addr not supported!\n", | ||
465 | adap->name); | ||
466 | rc = -EINVAL; | ||
467 | break; | ||
468 | } | ||
469 | |||
470 | alg_data->mif.buf = pmsg->buf; | ||
471 | alg_data->mif.len = pmsg->len; | ||
472 | alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? | ||
473 | I2C_SMBUS_READ : I2C_SMBUS_WRITE; | ||
474 | alg_data->mif.ret = 0; | ||
475 | alg_data->last = (i == num - 1); | ||
476 | |||
477 | dev_dbg(&adap->dev, "%s(): mode %d, %d bytes\n", __FUNCTION__, | ||
478 | alg_data->mif.mode, | ||
479 | alg_data->mif.len); | ||
480 | |||
481 | i2c_pnx_arm_timer(adap); | ||
482 | |||
483 | /* initialize the completion var */ | ||
484 | init_completion(&alg_data->mif.complete); | ||
485 | |||
486 | /* Enable master interrupt */ | ||
487 | iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie | | ||
488 | mcntrl_naie | mcntrl_drmie, | ||
489 | I2C_REG_CTL(alg_data)); | ||
490 | |||
491 | /* Put start-code and slave-address on the bus. */ | ||
492 | rc = i2c_pnx_start(addr, adap); | ||
493 | if (rc < 0) | ||
494 | break; | ||
495 | |||
496 | /* Wait for completion */ | ||
497 | wait_for_completion(&alg_data->mif.complete); | ||
498 | |||
499 | if (!(rc = alg_data->mif.ret)) | ||
500 | completed++; | ||
501 | dev_dbg(&adap->dev, "%s(): Complete, return code = %d.\n", | ||
502 | __FUNCTION__, rc); | ||
503 | |||
504 | /* Clear TDI and AFI bits in case they are set. */ | ||
505 | if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { | ||
506 | dev_dbg(&adap->dev, | ||
507 | "%s: TDI still set... clearing now.\n", | ||
508 | adap->name); | ||
509 | iowrite32(stat, I2C_REG_STS(alg_data)); | ||
510 | } | ||
511 | if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { | ||
512 | dev_dbg(&adap->dev, | ||
513 | "%s: AFI still set... clearing now.\n", | ||
514 | adap->name); | ||
515 | iowrite32(stat, I2C_REG_STS(alg_data)); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | bus_reset_if_active(adap); | ||
520 | |||
521 | /* Cleanup to be sure... */ | ||
522 | alg_data->mif.buf = NULL; | ||
523 | alg_data->mif.len = 0; | ||
524 | |||
525 | dev_dbg(&adap->dev, "%s(): exiting, stat = %x\n", | ||
526 | __FUNCTION__, ioread32(I2C_REG_STS(alg_data))); | ||
527 | |||
528 | if (completed != num) | ||
529 | return ((rc < 0) ? rc : -EREMOTEIO); | ||
530 | |||
531 | return num; | ||
532 | } | ||
533 | |||
534 | static u32 i2c_pnx_func(struct i2c_adapter *adapter) | ||
535 | { | ||
536 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
537 | } | ||
538 | |||
539 | static struct i2c_algorithm pnx_algorithm = { | ||
540 | .master_xfer = i2c_pnx_xfer, | ||
541 | .functionality = i2c_pnx_func, | ||
542 | }; | ||
543 | |||
544 | static int i2c_pnx_controller_suspend(struct platform_device *pdev, | ||
545 | pm_message_t state) | ||
546 | { | ||
547 | struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); | ||
548 | return i2c_pnx->suspend(pdev, state); | ||
549 | } | ||
550 | |||
551 | static int i2c_pnx_controller_resume(struct platform_device *pdev) | ||
552 | { | ||
553 | struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); | ||
554 | return i2c_pnx->resume(pdev); | ||
555 | } | ||
556 | |||
557 | static int __devinit i2c_pnx_probe(struct platform_device *pdev) | ||
558 | { | ||
559 | unsigned long tmp; | ||
560 | int ret = 0; | ||
561 | struct i2c_pnx_algo_data *alg_data; | ||
562 | int freq_mhz; | ||
563 | struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; | ||
564 | |||
565 | if (!i2c_pnx || !i2c_pnx->adapter) { | ||
566 | dev_err(&pdev->dev, "%s: no platform data supplied\n", | ||
567 | __FUNCTION__); | ||
568 | ret = -EINVAL; | ||
569 | goto out; | ||
570 | } | ||
571 | |||
572 | platform_set_drvdata(pdev, i2c_pnx); | ||
573 | |||
574 | if (i2c_pnx->calculate_input_freq) | ||
575 | freq_mhz = i2c_pnx->calculate_input_freq(pdev); | ||
576 | else { | ||
577 | freq_mhz = PNX_DEFAULT_FREQ; | ||
578 | dev_info(&pdev->dev, "Setting bus frequency to default value: " | ||
579 | "%d MHz", freq_mhz); | ||
580 | } | ||
581 | |||
582 | i2c_pnx->adapter->algo = &pnx_algorithm; | ||
583 | |||
584 | alg_data = i2c_pnx->adapter->algo_data; | ||
585 | init_timer(&alg_data->mif.timer); | ||
586 | alg_data->mif.timer.function = i2c_pnx_timeout; | ||
587 | alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; | ||
588 | |||
589 | /* Register I/O resource */ | ||
590 | if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) { | ||
591 | dev_err(&pdev->dev, | ||
592 | "I/O region 0x%08x for I2C already in use.\n", | ||
593 | alg_data->base); | ||
594 | ret = -ENODEV; | ||
595 | goto out_drvdata; | ||
596 | } | ||
597 | |||
598 | if (!(alg_data->ioaddr = | ||
599 | (u32)ioremap(alg_data->base, I2C_PNX_REGION_SIZE))) { | ||
600 | dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); | ||
601 | ret = -ENOMEM; | ||
602 | goto out_release; | ||
603 | } | ||
604 | |||
605 | i2c_pnx->set_clock_run(pdev); | ||
606 | |||
607 | /* | ||
608 | * Clock Divisor High This value is the number of system clocks | ||
609 | * the serial clock (SCL) will be high. | ||
610 | * For example, if the system clock period is 50 ns and the maximum | ||
611 | * desired serial period is 10000 ns (100 kHz), then CLKHI would be | ||
612 | * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value | ||
613 | * programmed into CLKHI will vary from this slightly due to | ||
614 | * variations in the output pad's rise and fall times as well as | ||
615 | * the deglitching filter length. | ||
616 | */ | ||
617 | |||
618 | tmp = ((freq_mhz * 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; | ||
619 | iowrite32(tmp, I2C_REG_CKH(alg_data)); | ||
620 | iowrite32(tmp, I2C_REG_CKL(alg_data)); | ||
621 | |||
622 | iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); | ||
623 | if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { | ||
624 | ret = -ENODEV; | ||
625 | goto out_unmap; | ||
626 | } | ||
627 | init_completion(&alg_data->mif.complete); | ||
628 | |||
629 | ret = request_irq(alg_data->irq, i2c_pnx_interrupt, | ||
630 | 0, pdev->name, i2c_pnx->adapter); | ||
631 | if (ret) | ||
632 | goto out_clock; | ||
633 | |||
634 | /* Register this adapter with the I2C subsystem */ | ||
635 | i2c_pnx->adapter->dev.parent = &pdev->dev; | ||
636 | ret = i2c_add_adapter(i2c_pnx->adapter); | ||
637 | if (ret < 0) { | ||
638 | dev_err(&pdev->dev, "I2C: Failed to add bus\n"); | ||
639 | goto out_irq; | ||
640 | } | ||
641 | |||
642 | dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", | ||
643 | i2c_pnx->adapter->name, alg_data->base, alg_data->irq); | ||
644 | |||
645 | return 0; | ||
646 | |||
647 | out_irq: | ||
648 | free_irq(alg_data->irq, alg_data); | ||
649 | out_clock: | ||
650 | i2c_pnx->set_clock_stop(pdev); | ||
651 | out_unmap: | ||
652 | iounmap((void *)alg_data->ioaddr); | ||
653 | out_release: | ||
654 | release_region(alg_data->base, I2C_PNX_REGION_SIZE); | ||
655 | out_drvdata: | ||
656 | platform_set_drvdata(pdev, NULL); | ||
657 | out: | ||
658 | return ret; | ||
659 | } | ||
660 | |||
661 | static int __devexit i2c_pnx_remove(struct platform_device *pdev) | ||
662 | { | ||
663 | struct i2c_pnx_data *i2c_pnx = platform_get_drvdata(pdev); | ||
664 | struct i2c_adapter *adap = i2c_pnx->adapter; | ||
665 | struct i2c_pnx_algo_data *alg_data = adap->algo_data; | ||
666 | |||
667 | free_irq(alg_data->irq, alg_data); | ||
668 | i2c_del_adapter(adap); | ||
669 | i2c_pnx->set_clock_stop(pdev); | ||
670 | iounmap((void *)alg_data->ioaddr); | ||
671 | release_region(alg_data->base, I2C_PNX_REGION_SIZE); | ||
672 | platform_set_drvdata(pdev, NULL); | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static struct platform_driver i2c_pnx_driver = { | ||
678 | .driver = { | ||
679 | .name = "pnx-i2c", | ||
680 | .owner = THIS_MODULE, | ||
681 | }, | ||
682 | .probe = i2c_pnx_probe, | ||
683 | .remove = __devexit_p(i2c_pnx_remove), | ||
684 | .suspend = i2c_pnx_controller_suspend, | ||
685 | .resume = i2c_pnx_controller_resume, | ||
686 | }; | ||
687 | |||
688 | static int __init i2c_adap_pnx_init(void) | ||
689 | { | ||
690 | return platform_driver_register(&i2c_pnx_driver); | ||
691 | } | ||
692 | |||
693 | static void __exit i2c_adap_pnx_exit(void) | ||
694 | { | ||
695 | platform_driver_unregister(&i2c_pnx_driver); | ||
696 | } | ||
697 | |||
698 | MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>"); | ||
699 | MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); | ||
700 | MODULE_LICENSE("GPL"); | ||
701 | |||
702 | #ifdef CONFIG_I2C_PNX_EARLY | ||
703 | /* We need to make sure I2C is initialized before USB */ | ||
704 | subsys_initcall(i2c_adap_pnx_init); | ||
705 | #else | ||
706 | mudule_init(i2c_adap_pnx_init); | ||
707 | #endif | ||
708 | module_exit(i2c_adap_pnx_exit); | ||