2 * drivers/i2c/busses/i2c-s6000.c
4 * Description: Driver for S6000 Family I2C Interface
5 * Copyright (c) 2008 emlix GmbH
6 * Author: Oskar Schirmer <os@emlix.com>
8 * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com>
9 * Copyright (c) 2005-2007 Analog Devices, Inc.
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.
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.
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
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>
41 #include "i2c-s6000.h"
43 #define DRV_NAME "i2c-s6000"
45 #define POLL_TIMEOUT (2 * HZ)
48 u8 __iomem
*reg
; /* memory mapped registers */
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
;
65 static inline u16
i2c_rd16(struct s6i2c_if
*iface
, unsigned n
)
67 return readw(iface
->reg
+ (n
));
70 static inline void i2c_wr16(struct s6i2c_if
*iface
, unsigned n
, u16 v
)
72 writew(v
, iface
->reg
+ (n
));
75 static inline u32
i2c_rd32(struct s6i2c_if
*iface
, unsigned n
)
77 return readl(iface
->reg
+ (n
));
80 static inline void i2c_wr32(struct s6i2c_if
*iface
, unsigned n
, u32 v
)
82 writel(v
, iface
->reg
+ (n
));
85 static struct s6i2c_if s6i2c_if
;
87 static void s6i2c_handle_interrupt(struct s6i2c_if
*iface
)
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
);
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);
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
]);
107 i2c_wr16(iface
, S6_I2C_DATACMD
,
108 1 << S6_I2C_DATACMD_READ
);
109 if (++iface
->push
>= m
->len
) {
111 iface
->msgs_push
+= 1;
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;
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
) {
126 iface
->msgs_done
+= 1;
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
));
139 i2c_wr16(iface
, S6_I2C_INTRMASK
, (1 << S6_I2C_INTR_TXABRT
) |
140 (1 << S6_I2C_INTR_TXEMPTY
) |
141 (1 << S6_I2C_INTR_RXFULL
));
145 static irqreturn_t
s6i2c_interrupt_entry(int irq
, void *dev_id
)
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
))))
162 spin_lock(&iface
->lock
);
163 del_timer(&iface
->timeout_timer
);
164 s6i2c_handle_interrupt(iface
);
165 spin_unlock(&iface
->lock
);
169 static void s6i2c_timeout(unsigned long data
)
171 struct s6i2c_if
*iface
= (struct s6i2c_if
*)data
;
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
);
180 complete(&iface
->complete
);
181 i2c_wr16(iface
, S6_I2C_INTRMASK
, 0);
183 spin_unlock_irqrestore(&iface
->lock
, flags
);
186 static int s6i2c_master_xfer(struct i2c_adapter
*adap
,
187 struct i2c_msg
*msgs
, int num
)
189 struct s6i2c_if
*iface
= adap
->algo_data
;
193 if (i2c_rd16(iface
, S6_I2C_STATUS
) & (1 << S6_I2C_STATUS_ACTIVITY
))
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
) {
200 "s6i2c: 10 bits addr not supported\n");
203 if (msgs
[i
].len
== 0) {
205 "s6i2c: zero length message not supported\n");
208 if (msgs
[i
].addr
!= msgs
[0].addr
) {
210 "s6i2c: multiple xfer cannot change target\n");
216 iface
->msgs_num
= num
;
217 iface
->msgs_push
= 0;
218 iface
->msgs_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
));
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)
233 while (i2c_rd16(iface
, S6_I2C_STATUS
) & (1 << S6_I2C_STATUS_ACTIVITY
))
236 i2c_wr16(iface
, S6_I2C_INTRMASK
, 0);
237 i2c_wr16(iface
, S6_I2C_ENABLE
, 0);
238 return iface
->msgs_done
;
241 static u32
s6i2c_functionality(struct i2c_adapter
*adap
)
243 return I2C_FUNC_I2C
| I2C_FUNC_SMBUS_EMUL
;
246 static struct i2c_algorithm s6i2c_algorithm
= {
247 .master_xfer
= s6i2c_master_xfer
,
248 .functionality
= s6i2c_functionality
,
251 static u16 __devinit
nanoseconds_on_clk(struct s6i2c_if
*iface
, u32 ns
)
253 u32 dividend
= ((clk_get_rate(iface
->clk
) / 1000) * ns
) / 1000000;
254 if (dividend
> 0xffff)
259 static int __devinit
s6i2c_probe(struct platform_device
*dev
)
261 struct s6i2c_if
*iface
= &s6i2c_if
;
262 struct i2c_adapter
*p_adap
;
265 spin_lock_init(&iface
->lock
);
266 init_completion(&iface
->complete
);
267 iface
->irq
= platform_get_irq(dev
, 0);
268 if (iface
->irq
< 0) {
272 iface
->res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
277 iface
->res
= request_mem_region(iface
->res
->start
,
278 resource_size(iface
->res
),
284 iface
->reg
= ioremap_nocache(iface
->res
->start
,
285 resource_size(iface
->res
));
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
;
298 iface
->clk
= clk_get(&dev
->dev
, clock
);
299 if (IS_ERR(iface
->clk
)) {
300 rc
= PTR_ERR(iface
->clk
);
303 rc
= clk_enable(iface
->clk
);
306 init_timer(&iface
->timeout_timer
);
307 iface
->timeout_timer
.function
= s6i2c_timeout
;
308 iface
->timeout_timer
.data
= (unsigned long)iface
;
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
;
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
);
321 dev_err(&p_adap
->dev
, "s6i2c: cant get IRQ %d\n", iface
->irq
);
325 i2c_wr16(iface
, S6_I2C_ENABLE
, 0);
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);
343 platform_set_drvdata(dev
, iface
);
345 rc
= i2c_add_adapter(p_adap
);
347 rc
= i2c_add_numbered_adapter(p_adap
);
353 free_irq(iface
->irq
, iface
);
355 clk_disable(iface
->clk
);
361 release_mem_region(iface
->res
->start
,
362 resource_size(iface
->res
));
367 static int __devexit
s6i2c_remove(struct platform_device
*pdev
)
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
);
377 release_mem_region(iface
->res
->start
,
378 resource_size(iface
->res
));
382 static struct platform_driver s6i2c_driver
= {
383 .probe
= s6i2c_probe
,
384 .remove
= __devexit_p(s6i2c_remove
),
387 .owner
= THIS_MODULE
,
391 static int __init
s6i2c_init(void)
393 pr_info("I2C: S6000 I2C driver\n");
394 return platform_driver_register(&s6i2c_driver
);
397 static void __exit
s6i2c_exit(void)
399 platform_driver_unregister(&s6i2c_driver
);
402 MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C");
403 MODULE_LICENSE("GPL");
404 MODULE_ALIAS("platform:" DRV_NAME
);
406 subsys_initcall(s6i2c_init
);
407 module_exit(s6i2c_exit
);