aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Wool <vitalywool@gmail.com>2006-12-10 15:21:29 -0500
committerJean Delvare <khali@arrakis.delvare>2006-12-10 15:21:29 -0500
commit41561f28e76a47dc6de0a954da85d0b5c42874eb (patch)
tree0113700403e5fffb57ee41b564ea68bcaab311d9
parent51fd554b6547b74c7e6d1f52885ba8532b531023 (diff)
i2c: New Philips PNX bus driver
New I2C bus driver for Philips ARM boards (Philips IP3204 I2C IP block). This I2C controller can be found on (at least) PNX010x, PNX52xx and PNX4008 Philips boards. Signed-off-by: Vitaly Wool <vitalywool@gmail.com> Signed-off-by: Jean Delvare <khali@linux-fr.org>
-rw-r--r--arch/arm/mach-pnx4008/Makefile2
-rw-r--r--arch/arm/mach-pnx4008/i2c.c167
-rw-r--r--drivers/i2c/busses/Kconfig19
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-pnx.c708
-rw-r--r--include/asm-arm/arch-pnx4008/i2c.h67
-rw-r--r--include/linux/i2c-pnx.h43
7 files changed, 1006 insertions, 1 deletions
diff --git a/arch/arm/mach-pnx4008/Makefile b/arch/arm/mach-pnx4008/Makefile
index b457ca0a431a..777564c90a12 100644
--- a/arch/arm/mach-pnx4008/Makefile
+++ b/arch/arm/mach-pnx4008/Makefile
@@ -2,7 +2,7 @@
2# Makefile for the linux kernel. 2# Makefile for the linux kernel.
3# 3#
4 4
5obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o 5obj-y := core.o irq.o time.o clock.o gpio.o serial.o dma.o i2c.o
6obj-m := 6obj-m :=
7obj-n := 7obj-n :=
8obj- := 8obj- :=
diff --git a/arch/arm/mach-pnx4008/i2c.c b/arch/arm/mach-pnx4008/i2c.c
new file mode 100644
index 000000000000..6f308827c4fe
--- /dev/null
+++ b/arch/arm/mach-pnx4008/i2c.c
@@ -0,0 +1,167 @@
1/*
2 * I2C initialization for PNX4008.
3 *
4 * Author: Vitaly Wool <vitalywool@gmail.com>
5 *
6 * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#include <linux/clk.h>
13#include <linux/i2c.h>
14#include <linux/i2c-pnx.h>
15#include <linux/platform_device.h>
16#include <linux/err.h>
17#include <asm/arch/platform.h>
18#include <asm/arch/i2c.h>
19
20static int set_clock_run(struct platform_device *pdev)
21{
22 struct clk *clk;
23 char name[10];
24 int retval = 0;
25
26 snprintf(name, 10, "i2c%d_ck", pdev->id);
27 clk = clk_get(&pdev->dev, name);
28 if (!IS_ERR(clk)) {
29 clk_set_rate(clk, 1);
30 clk_put(clk);
31 } else
32 retval = -ENOENT;
33
34 return retval;
35}
36
37static int set_clock_stop(struct platform_device *pdev)
38{
39 struct clk *clk;
40 char name[10];
41 int retval = 0;
42
43 snprintf(name, 10, "i2c%d_ck", pdev->id);
44 clk = clk_get(&pdev->dev, name);
45 if (!IS_ERR(clk)) {
46 clk_set_rate(clk, 0);
47 clk_put(clk);
48 } else
49 retval = -ENOENT;
50
51 return retval;
52}
53
54static int i2c_pnx_suspend(struct platform_device *pdev, pm_message_t state)
55{
56 int retval = 0;
57#ifdef CONFIG_PM
58 retval = set_clock_run(pdev);
59#endif
60 return retval;
61}
62
63static int i2c_pnx_resume(struct platform_device *pdev)
64{
65 int retval = 0;
66#ifdef CONFIG_PM
67 retval = set_clock_run(pdev);
68#endif
69 return retval;
70}
71
72static u32 calculate_input_freq(struct platform_device *pdev)
73{
74 return HCLK_MHZ;
75}
76
77
78static struct i2c_pnx_algo_data pnx_algo_data0 = {
79 .base = PNX4008_I2C1_BASE,
80 .irq = I2C_1_INT,
81};
82
83static struct i2c_pnx_algo_data pnx_algo_data1 = {
84 .base = PNX4008_I2C2_BASE,
85 .irq = I2C_2_INT,
86};
87
88static struct i2c_pnx_algo_data pnx_algo_data2 = {
89 .base = (PNX4008_USB_CONFIG_BASE + 0x300),
90 .irq = USB_I2C_INT,
91};
92
93static struct i2c_adapter pnx_adapter0 = {
94 .name = I2C_CHIP_NAME "0",
95 .algo_data = &pnx_algo_data0,
96};
97static struct i2c_adapter pnx_adapter1 = {
98 .name = I2C_CHIP_NAME "1",
99 .algo_data = &pnx_algo_data1,
100};
101
102static struct i2c_adapter pnx_adapter2 = {
103 .name = "USB-I2C",
104 .algo_data = &pnx_algo_data2,
105};
106
107static struct i2c_pnx_data i2c0_data = {
108 .suspend = i2c_pnx_suspend,
109 .resume = i2c_pnx_resume,
110 .calculate_input_freq = calculate_input_freq,
111 .set_clock_run = set_clock_run,
112 .set_clock_stop = set_clock_stop,
113 .adapter = &pnx_adapter0,
114};
115
116static struct i2c_pnx_data i2c1_data = {
117 .suspend = i2c_pnx_suspend,
118 .resume = i2c_pnx_resume,
119 .calculate_input_freq = calculate_input_freq,
120 .set_clock_run = set_clock_run,
121 .set_clock_stop = set_clock_stop,
122 .adapter = &pnx_adapter1,
123};
124
125static struct i2c_pnx_data i2c2_data = {
126 .suspend = i2c_pnx_suspend,
127 .resume = i2c_pnx_resume,
128 .calculate_input_freq = calculate_input_freq,
129 .set_clock_run = set_clock_run,
130 .set_clock_stop = set_clock_stop,
131 .adapter = &pnx_adapter2,
132};
133
134static struct platform_device i2c0_device = {
135 .name = "pnx-i2c",
136 .id = 0,
137 .dev = {
138 .platform_data = &i2c0_data,
139 },
140};
141
142static struct platform_device i2c1_device = {
143 .name = "pnx-i2c",
144 .id = 1,
145 .dev = {
146 .platform_data = &i2c1_data,
147 },
148};
149
150static struct platform_device i2c2_device = {
151 .name = "pnx-i2c",
152 .id = 2,
153 .dev = {
154 .platform_data = &i2c2_data,
155 },
156};
157
158static struct platform_device *devices[] __initdata = {
159 &i2c0_device,
160 &i2c1_device,
161 &i2c2_device,
162};
163
164void __init pnx4008_register_i2c_devices(void)
165{
166 platform_add_devices(devices, ARRAY_SIZE(devices));
167}
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
539config 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
549config 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
539endmenu 558endmenu
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
28obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o 28obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
29obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o 29obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
30obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o 30obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
31obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
31obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o 32obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o
32obj-$(CONFIG_I2C_PXA) += i2c-pxa.o 33obj-$(CONFIG_I2C_PXA) += i2c-pxa.o
33obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o 34obj-$(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
31static 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
41static 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
51static 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 */
75static 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 */
131static 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 */
161static 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 */
233static 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
308static irqreturn_t
309i2c_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
385static 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
408static 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 */
442static int
443i2c_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
534static u32 i2c_pnx_func(struct i2c_adapter *adapter)
535{
536 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
537}
538
539static struct i2c_algorithm pnx_algorithm = {
540 .master_xfer = i2c_pnx_xfer,
541 .functionality = i2c_pnx_func,
542};
543
544static 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
551static 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
557static 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
647out_irq:
648 free_irq(alg_data->irq, alg_data);
649out_clock:
650 i2c_pnx->set_clock_stop(pdev);
651out_unmap:
652 iounmap((void *)alg_data->ioaddr);
653out_release:
654 release_region(alg_data->base, I2C_PNX_REGION_SIZE);
655out_drvdata:
656 platform_set_drvdata(pdev, NULL);
657out:
658 return ret;
659}
660
661static 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
677static 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
688static int __init i2c_adap_pnx_init(void)
689{
690 return platform_driver_register(&i2c_pnx_driver);
691}
692
693static void __exit i2c_adap_pnx_exit(void)
694{
695 platform_driver_unregister(&i2c_pnx_driver);
696}
697
698MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
699MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
700MODULE_LICENSE("GPL");
701
702#ifdef CONFIG_I2C_PNX_EARLY
703/* We need to make sure I2C is initialized before USB */
704subsys_initcall(i2c_adap_pnx_init);
705#else
706mudule_init(i2c_adap_pnx_init);
707#endif
708module_exit(i2c_adap_pnx_exit);
diff --git a/include/asm-arm/arch-pnx4008/i2c.h b/include/asm-arm/arch-pnx4008/i2c.h
new file mode 100644
index 000000000000..92e8d65006f7
--- /dev/null
+++ b/include/asm-arm/arch-pnx4008/i2c.h
@@ -0,0 +1,67 @@
1/*
2 * PNX4008-specific tweaks for I2C IP3204 block
3 *
4 * Author: Vitaly Wool <vwool@ru.mvista.com>
5 *
6 * 2005 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#ifndef __ASM_ARCH_I2C_H__
13#define __ASM_ARCH_I2C_H__
14
15#include <linux/pm.h>
16#include <linux/platform_device.h>
17
18enum {
19 mstatus_tdi = 0x00000001,
20 mstatus_afi = 0x00000002,
21 mstatus_nai = 0x00000004,
22 mstatus_drmi = 0x00000008,
23 mstatus_active = 0x00000020,
24 mstatus_scl = 0x00000040,
25 mstatus_sda = 0x00000080,
26 mstatus_rff = 0x00000100,
27 mstatus_rfe = 0x00000200,
28 mstatus_tff = 0x00000400,
29 mstatus_tfe = 0x00000800,
30};
31
32enum {
33 mcntrl_tdie = 0x00000001,
34 mcntrl_afie = 0x00000002,
35 mcntrl_naie = 0x00000004,
36 mcntrl_drmie = 0x00000008,
37 mcntrl_daie = 0x00000020,
38 mcntrl_rffie = 0x00000040,
39 mcntrl_tffie = 0x00000080,
40 mcntrl_reset = 0x00000100,
41 mcntrl_cdbmode = 0x00000400,
42};
43
44enum {
45 rw_bit = 1 << 0,
46 start_bit = 1 << 8,
47 stop_bit = 1 << 9,
48};
49
50#define I2C_REG_RX(a) ((a)->ioaddr) /* Rx FIFO reg (RO) */
51#define I2C_REG_TX(a) ((a)->ioaddr) /* Tx FIFO reg (WO) */
52#define I2C_REG_STS(a) ((a)->ioaddr + 0x04) /* Status reg (RO) */
53#define I2C_REG_CTL(a) ((a)->ioaddr + 0x08) /* Ctl reg */
54#define I2C_REG_CKL(a) ((a)->ioaddr + 0x0c) /* Clock divider low */
55#define I2C_REG_CKH(a) ((a)->ioaddr + 0x10) /* Clock divider high */
56#define I2C_REG_ADR(a) ((a)->ioaddr + 0x14) /* I2C address */
57#define I2C_REG_RFL(a) ((a)->ioaddr + 0x18) /* Rx FIFO level (RO) */
58#define I2C_REG_TFL(a) ((a)->ioaddr + 0x1c) /* Tx FIFO level (RO) */
59#define I2C_REG_RXB(a) ((a)->ioaddr + 0x20) /* Num of bytes Rx-ed (RO) */
60#define I2C_REG_TXB(a) ((a)->ioaddr + 0x24) /* Num of bytes Tx-ed (RO) */
61#define I2C_REG_TXS(a) ((a)->ioaddr + 0x28) /* Tx slave FIFO (RO) */
62#define I2C_REG_STFL(a) ((a)->ioaddr + 0x2c) /* Tx slave FIFO level (RO) */
63
64#define HCLK_MHZ 13
65#define I2C_CHIP_NAME "PNX4008-I2C"
66
67#endif /* __ASM_ARCH_I2C_H___ */
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
new file mode 100644
index 000000000000..e6e9c814da61
--- /dev/null
+++ b/include/linux/i2c-pnx.h
@@ -0,0 +1,43 @@
1/*
2 * Header file for I2C support on PNX010x/4008.
3 *
4 * Author: Dennis Kovalev <dkovalev@ru.mvista.com>
5 *
6 * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11
12#ifndef __I2C_PNX_H__
13#define __I2C_PNX_H__
14
15#include <asm/arch/i2c.h>
16
17struct i2c_pnx_mif {
18 int ret; /* Return value */
19 int mode; /* Interface mode */
20 struct completion complete; /* I/O completion */
21 struct timer_list timer; /* Timeout */
22 char * buf; /* Data buffer */
23 int len; /* Length of data buffer */
24};
25
26struct i2c_pnx_algo_data {
27 u32 base;
28 u32 ioaddr;
29 int irq;
30 struct i2c_pnx_mif mif;
31 int last;
32};
33
34struct i2c_pnx_data {
35 int (*suspend) (struct platform_device *pdev, pm_message_t state);
36 int (*resume) (struct platform_device *pdev);
37 u32 (*calculate_input_freq) (struct platform_device *pdev);
38 int (*set_clock_run) (struct platform_device *pdev);
39 int (*set_clock_stop) (struct platform_device *pdev);
40 struct i2c_adapter *adapter;
41};
42
43#endif /* __I2C_PNX_H__ */