1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * I2C bus driver for the SH7760 I2C Interfaces.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * licensed under the terms outlined in the file COPYING.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/completion.h>
11*4882a593Smuzhiyun #include <linux/delay.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/i2c.h>
14*4882a593Smuzhiyun #include <linux/interrupt.h>
15*4882a593Smuzhiyun #include <linux/ioport.h>
16*4882a593Smuzhiyun #include <linux/platform_device.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/io.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include <asm/clock.h>
22*4882a593Smuzhiyun #include <asm/i2c-sh7760.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* register offsets */
25*4882a593Smuzhiyun #define I2CSCR 0x0 /* slave ctrl */
26*4882a593Smuzhiyun #define I2CMCR 0x4 /* master ctrl */
27*4882a593Smuzhiyun #define I2CSSR 0x8 /* slave status */
28*4882a593Smuzhiyun #define I2CMSR 0xC /* master status */
29*4882a593Smuzhiyun #define I2CSIER 0x10 /* slave irq enable */
30*4882a593Smuzhiyun #define I2CMIER 0x14 /* master irq enable */
31*4882a593Smuzhiyun #define I2CCCR 0x18 /* clock dividers */
32*4882a593Smuzhiyun #define I2CSAR 0x1c /* slave address */
33*4882a593Smuzhiyun #define I2CMAR 0x20 /* master address */
34*4882a593Smuzhiyun #define I2CRXTX 0x24 /* data port */
35*4882a593Smuzhiyun #define I2CFCR 0x28 /* fifo control */
36*4882a593Smuzhiyun #define I2CFSR 0x2C /* fifo status */
37*4882a593Smuzhiyun #define I2CFIER 0x30 /* fifo irq enable */
38*4882a593Smuzhiyun #define I2CRFDR 0x34 /* rx fifo count */
39*4882a593Smuzhiyun #define I2CTFDR 0x38 /* tx fifo count */
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define REGSIZE 0x3C
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #define MCR_MDBS 0x80 /* non-fifo mode switch */
44*4882a593Smuzhiyun #define MCR_FSCL 0x40 /* override SCL pin */
45*4882a593Smuzhiyun #define MCR_FSDA 0x20 /* override SDA pin */
46*4882a593Smuzhiyun #define MCR_OBPC 0x10 /* override pins */
47*4882a593Smuzhiyun #define MCR_MIE 0x08 /* master if enable */
48*4882a593Smuzhiyun #define MCR_TSBE 0x04
49*4882a593Smuzhiyun #define MCR_FSB 0x02 /* force stop bit */
50*4882a593Smuzhiyun #define MCR_ESG 0x01 /* en startbit gen. */
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define MSR_MNR 0x40 /* nack received */
53*4882a593Smuzhiyun #define MSR_MAL 0x20 /* arbitration lost */
54*4882a593Smuzhiyun #define MSR_MST 0x10 /* sent a stop */
55*4882a593Smuzhiyun #define MSR_MDE 0x08
56*4882a593Smuzhiyun #define MSR_MDT 0x04
57*4882a593Smuzhiyun #define MSR_MDR 0x02
58*4882a593Smuzhiyun #define MSR_MAT 0x01 /* slave addr xfer done */
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun #define MIE_MNRE 0x40 /* nack irq en */
61*4882a593Smuzhiyun #define MIE_MALE 0x20 /* arblos irq en */
62*4882a593Smuzhiyun #define MIE_MSTE 0x10 /* stop irq en */
63*4882a593Smuzhiyun #define MIE_MDEE 0x08
64*4882a593Smuzhiyun #define MIE_MDTE 0x04
65*4882a593Smuzhiyun #define MIE_MDRE 0x02
66*4882a593Smuzhiyun #define MIE_MATE 0x01 /* address sent irq en */
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #define FCR_RFRST 0x02 /* reset rx fifo */
69*4882a593Smuzhiyun #define FCR_TFRST 0x01 /* reset tx fifo */
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #define FSR_TEND 0x04 /* last byte sent */
72*4882a593Smuzhiyun #define FSR_RDF 0x02 /* rx fifo trigger */
73*4882a593Smuzhiyun #define FSR_TDFE 0x01 /* tx fifo empty */
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #define FIER_TEIE 0x04 /* tx fifo empty irq en */
76*4882a593Smuzhiyun #define FIER_RXIE 0x02 /* rx fifo trig irq en */
77*4882a593Smuzhiyun #define FIER_TXIE 0x01 /* tx fifo trig irq en */
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #define FIFO_SIZE 16
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun struct cami2c {
82*4882a593Smuzhiyun void __iomem *iobase;
83*4882a593Smuzhiyun struct i2c_adapter adap;
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* message processing */
86*4882a593Smuzhiyun struct i2c_msg *msg;
87*4882a593Smuzhiyun #define IDF_SEND 1
88*4882a593Smuzhiyun #define IDF_RECV 2
89*4882a593Smuzhiyun #define IDF_STOP 4
90*4882a593Smuzhiyun int flags;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun #define IDS_DONE 1
93*4882a593Smuzhiyun #define IDS_ARBLOST 2
94*4882a593Smuzhiyun #define IDS_NACK 4
95*4882a593Smuzhiyun int status;
96*4882a593Smuzhiyun struct completion xfer_done;
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun int irq;
99*4882a593Smuzhiyun struct resource *ioarea;
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun
OUT32(struct cami2c * cam,int reg,unsigned long val)102*4882a593Smuzhiyun static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun __raw_writel(val, (unsigned long)cam->iobase + reg);
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
IN32(struct cami2c * cam,int reg)107*4882a593Smuzhiyun static inline unsigned long IN32(struct cami2c *cam, int reg)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun return __raw_readl((unsigned long)cam->iobase + reg);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun
sh7760_i2c_irq(int irq,void * ptr)112*4882a593Smuzhiyun static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun struct cami2c *id = ptr;
115*4882a593Smuzhiyun struct i2c_msg *msg = id->msg;
116*4882a593Smuzhiyun char *data = msg->buf;
117*4882a593Smuzhiyun unsigned long msr, fsr, fier, len;
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun msr = IN32(id, I2CMSR);
120*4882a593Smuzhiyun fsr = IN32(id, I2CFSR);
121*4882a593Smuzhiyun
122*4882a593Smuzhiyun /* arbitration lost */
123*4882a593Smuzhiyun if (msr & MSR_MAL) {
124*4882a593Smuzhiyun OUT32(id, I2CMCR, 0);
125*4882a593Smuzhiyun OUT32(id, I2CSCR, 0);
126*4882a593Smuzhiyun OUT32(id, I2CSAR, 0);
127*4882a593Smuzhiyun id->status |= IDS_DONE | IDS_ARBLOST;
128*4882a593Smuzhiyun goto out;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (msr & MSR_MNR) {
132*4882a593Smuzhiyun /* NACK handling is very screwed up. After receiving a
133*4882a593Smuzhiyun * NAK IRQ one has to wait a bit before writing to any
134*4882a593Smuzhiyun * registers, or the ctl will lock up. After that delay
135*4882a593Smuzhiyun * do a normal i2c stop. Then wait at least 1 ms before
136*4882a593Smuzhiyun * attempting another transfer or ctl will stop working
137*4882a593Smuzhiyun */
138*4882a593Smuzhiyun udelay(100); /* wait or risk ctl hang */
139*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
140*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
141*4882a593Smuzhiyun OUT32(id, I2CFIER, 0);
142*4882a593Smuzhiyun OUT32(id, I2CMIER, MIE_MSTE);
143*4882a593Smuzhiyun OUT32(id, I2CSCR, 0);
144*4882a593Smuzhiyun OUT32(id, I2CSAR, 0);
145*4882a593Smuzhiyun id->status |= IDS_NACK;
146*4882a593Smuzhiyun msr &= ~MSR_MAT;
147*4882a593Smuzhiyun fsr = 0;
148*4882a593Smuzhiyun /* In some cases the MST bit is also set. */
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* i2c-stop was sent */
152*4882a593Smuzhiyun if (msr & MSR_MST) {
153*4882a593Smuzhiyun id->status |= IDS_DONE;
154*4882a593Smuzhiyun goto out;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* i2c slave addr was sent; set to "normal" operation */
158*4882a593Smuzhiyun if (msr & MSR_MAT)
159*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun fier = IN32(id, I2CFIER);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun if (fsr & FSR_RDF) {
164*4882a593Smuzhiyun len = IN32(id, I2CRFDR);
165*4882a593Smuzhiyun if (msg->len <= len) {
166*4882a593Smuzhiyun if (id->flags & IDF_STOP) {
167*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
168*4882a593Smuzhiyun OUT32(id, I2CFIER, 0);
169*4882a593Smuzhiyun /* manual says: wait >= 0.5 SCL times */
170*4882a593Smuzhiyun udelay(5);
171*4882a593Smuzhiyun /* next int should be MST */
172*4882a593Smuzhiyun } else {
173*4882a593Smuzhiyun id->status |= IDS_DONE;
174*4882a593Smuzhiyun /* keep the RDF bit: ctrl holds SCL low
175*4882a593Smuzhiyun * until the setup for the next i2c_msg
176*4882a593Smuzhiyun * clears this bit.
177*4882a593Smuzhiyun */
178*4882a593Smuzhiyun fsr &= ~FSR_RDF;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun while (msg->len && len) {
182*4882a593Smuzhiyun *data++ = IN32(id, I2CRXTX);
183*4882a593Smuzhiyun msg->len--;
184*4882a593Smuzhiyun len--;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (msg->len) {
188*4882a593Smuzhiyun len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1
189*4882a593Smuzhiyun : msg->len - 1;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4));
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun } else if (id->flags & IDF_SEND) {
195*4882a593Smuzhiyun if ((fsr & FSR_TEND) && (msg->len < 1)) {
196*4882a593Smuzhiyun if (id->flags & IDF_STOP) {
197*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE | MCR_FSB);
198*4882a593Smuzhiyun } else {
199*4882a593Smuzhiyun id->status |= IDS_DONE;
200*4882a593Smuzhiyun /* keep the TEND bit: ctl holds SCL low
201*4882a593Smuzhiyun * until the setup for the next i2c_msg
202*4882a593Smuzhiyun * clears this bit.
203*4882a593Smuzhiyun */
204*4882a593Smuzhiyun fsr &= ~FSR_TEND;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun if (fsr & FSR_TDFE) {
208*4882a593Smuzhiyun while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) {
209*4882a593Smuzhiyun OUT32(id, I2CRXTX, *data++);
210*4882a593Smuzhiyun msg->len--;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (msg->len < 1) {
214*4882a593Smuzhiyun fier &= ~FIER_TXIE;
215*4882a593Smuzhiyun OUT32(id, I2CFIER, fier);
216*4882a593Smuzhiyun } else {
217*4882a593Smuzhiyun len = (msg->len >= FIFO_SIZE) ? 2 : 0;
218*4882a593Smuzhiyun OUT32(id, I2CFCR,
219*4882a593Smuzhiyun FCR_RFRST | ((len & 3) << 2));
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun out:
224*4882a593Smuzhiyun if (id->status & IDS_DONE) {
225*4882a593Smuzhiyun OUT32(id, I2CMIER, 0);
226*4882a593Smuzhiyun OUT32(id, I2CFIER, 0);
227*4882a593Smuzhiyun id->msg = NULL;
228*4882a593Smuzhiyun complete(&id->xfer_done);
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun /* clear status flags and ctrl resumes work */
231*4882a593Smuzhiyun OUT32(id, I2CMSR, ~msr);
232*4882a593Smuzhiyun OUT32(id, I2CFSR, ~fsr);
233*4882a593Smuzhiyun OUT32(id, I2CSSR, 0);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun return IRQ_HANDLED;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun /* prepare and start a master receive operation */
sh7760_i2c_mrecv(struct cami2c * id)240*4882a593Smuzhiyun static void sh7760_i2c_mrecv(struct cami2c *id)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun int len;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun id->flags |= IDF_RECV;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /* set the slave addr reg; otherwise rcv wont work! */
247*4882a593Smuzhiyun OUT32(id, I2CSAR, 0xfe);
248*4882a593Smuzhiyun OUT32(id, I2CMAR, (id->msg->addr << 1) | 1);
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun /* adjust rx fifo trigger */
251*4882a593Smuzhiyun if (id->msg->len >= FIFO_SIZE)
252*4882a593Smuzhiyun len = FIFO_SIZE - 1; /* trigger at fifo full */
253*4882a593Smuzhiyun else
254*4882a593Smuzhiyun len = id->msg->len - 1; /* trigger before all received */
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
257*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4));
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun OUT32(id, I2CMSR, 0);
260*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
261*4882a593Smuzhiyun OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
262*4882a593Smuzhiyun OUT32(id, I2CFIER, FIER_RXIE);
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun /* prepare and start a master send operation */
sh7760_i2c_msend(struct cami2c * id)266*4882a593Smuzhiyun static void sh7760_i2c_msend(struct cami2c *id)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun int len;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun id->flags |= IDF_SEND;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun /* set the slave addr reg; otherwise xmit wont work! */
273*4882a593Smuzhiyun OUT32(id, I2CSAR, 0xfe);
274*4882a593Smuzhiyun OUT32(id, I2CMAR, (id->msg->addr << 1) | 0);
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun /* adjust tx fifo trigger */
277*4882a593Smuzhiyun if (id->msg->len >= FIFO_SIZE)
278*4882a593Smuzhiyun len = 2; /* trig: 2 bytes left in TX fifo */
279*4882a593Smuzhiyun else
280*4882a593Smuzhiyun len = 0; /* trig: 8 bytes left in TX fifo */
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
283*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2));
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) {
286*4882a593Smuzhiyun OUT32(id, I2CRXTX, *(id->msg->buf));
287*4882a593Smuzhiyun (id->msg->len)--;
288*4882a593Smuzhiyun (id->msg->buf)++;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun OUT32(id, I2CMSR, 0);
292*4882a593Smuzhiyun OUT32(id, I2CMCR, MCR_MIE | MCR_ESG);
293*4882a593Smuzhiyun OUT32(id, I2CFSR, 0);
294*4882a593Smuzhiyun OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE);
295*4882a593Smuzhiyun OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0));
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
sh7760_i2c_busy_check(struct cami2c * id)298*4882a593Smuzhiyun static inline int sh7760_i2c_busy_check(struct cami2c *id)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun return (IN32(id, I2CMCR) & MCR_FSDA);
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
sh7760_i2c_master_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)303*4882a593Smuzhiyun static int sh7760_i2c_master_xfer(struct i2c_adapter *adap,
304*4882a593Smuzhiyun struct i2c_msg *msgs,
305*4882a593Smuzhiyun int num)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun struct cami2c *id = adap->algo_data;
308*4882a593Smuzhiyun int i, retr;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun if (sh7760_i2c_busy_check(id)) {
311*4882a593Smuzhiyun dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr);
312*4882a593Smuzhiyun return -EBUSY;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun i = 0;
316*4882a593Smuzhiyun while (i < num) {
317*4882a593Smuzhiyun retr = adap->retries;
318*4882a593Smuzhiyun retry:
319*4882a593Smuzhiyun id->flags = ((i == (num-1)) ? IDF_STOP : 0);
320*4882a593Smuzhiyun id->status = 0;
321*4882a593Smuzhiyun id->msg = msgs;
322*4882a593Smuzhiyun init_completion(&id->xfer_done);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun if (msgs->flags & I2C_M_RD)
325*4882a593Smuzhiyun sh7760_i2c_mrecv(id);
326*4882a593Smuzhiyun else
327*4882a593Smuzhiyun sh7760_i2c_msend(id);
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun wait_for_completion(&id->xfer_done);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (id->status == 0) {
332*4882a593Smuzhiyun num = -EIO;
333*4882a593Smuzhiyun break;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if (id->status & IDS_NACK) {
337*4882a593Smuzhiyun /* wait a bit or i2c module stops working */
338*4882a593Smuzhiyun mdelay(1);
339*4882a593Smuzhiyun num = -EREMOTEIO;
340*4882a593Smuzhiyun break;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun if (id->status & IDS_ARBLOST) {
344*4882a593Smuzhiyun if (retr--) {
345*4882a593Smuzhiyun mdelay(2);
346*4882a593Smuzhiyun goto retry;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun num = -EREMOTEIO;
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun msgs++;
353*4882a593Smuzhiyun i++;
354*4882a593Smuzhiyun }
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun id->msg = NULL;
357*4882a593Smuzhiyun id->flags = 0;
358*4882a593Smuzhiyun id->status = 0;
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun OUT32(id, I2CMCR, 0);
361*4882a593Smuzhiyun OUT32(id, I2CMSR, 0);
362*4882a593Smuzhiyun OUT32(id, I2CMIER, 0);
363*4882a593Smuzhiyun OUT32(id, I2CFIER, 0);
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun /* reset slave module registers too: master mode enables slave
366*4882a593Smuzhiyun * module for receive ops (ack, data). Without this reset,
367*4882a593Smuzhiyun * eternal bus activity might be reported after NACK / ARBLOST.
368*4882a593Smuzhiyun */
369*4882a593Smuzhiyun OUT32(id, I2CSCR, 0);
370*4882a593Smuzhiyun OUT32(id, I2CSAR, 0);
371*4882a593Smuzhiyun OUT32(id, I2CSSR, 0);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun return num;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun
sh7760_i2c_func(struct i2c_adapter * adap)376*4882a593Smuzhiyun static u32 sh7760_i2c_func(struct i2c_adapter *adap)
377*4882a593Smuzhiyun {
378*4882a593Smuzhiyun return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun static const struct i2c_algorithm sh7760_i2c_algo = {
382*4882a593Smuzhiyun .master_xfer = sh7760_i2c_master_xfer,
383*4882a593Smuzhiyun .functionality = sh7760_i2c_func,
384*4882a593Smuzhiyun };
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun /* calculate CCR register setting for a desired scl clock. SCL clock is
387*4882a593Smuzhiyun * derived from I2C module clock (iclk) which in turn is derived from
388*4882a593Smuzhiyun * peripheral module clock (mclk, usually around 33MHz):
389*4882a593Smuzhiyun * iclk = mclk/(CDF + 1). iclk must be < 20MHz.
390*4882a593Smuzhiyun * scl = iclk/(SCGD*8 + 20).
391*4882a593Smuzhiyun */
calc_CCR(unsigned long scl_hz)392*4882a593Smuzhiyun static int calc_CCR(unsigned long scl_hz)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun struct clk *mclk;
395*4882a593Smuzhiyun unsigned long mck, m1, dff, odff, iclk;
396*4882a593Smuzhiyun signed char cdf, cdfm;
397*4882a593Smuzhiyun int scgd, scgdm, scgds;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun mclk = clk_get(NULL, "peripheral_clk");
400*4882a593Smuzhiyun if (IS_ERR(mclk)) {
401*4882a593Smuzhiyun return PTR_ERR(mclk);
402*4882a593Smuzhiyun } else {
403*4882a593Smuzhiyun mck = mclk->rate;
404*4882a593Smuzhiyun clk_put(mclk);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun odff = scl_hz;
408*4882a593Smuzhiyun scgdm = cdfm = m1 = 0;
409*4882a593Smuzhiyun for (cdf = 3; cdf >= 0; cdf--) {
410*4882a593Smuzhiyun iclk = mck / (1 + cdf);
411*4882a593Smuzhiyun if (iclk >= 20000000)
412*4882a593Smuzhiyun continue;
413*4882a593Smuzhiyun scgds = ((iclk / scl_hz) - 20) >> 3;
414*4882a593Smuzhiyun for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) {
415*4882a593Smuzhiyun m1 = iclk / (20 + (scgd << 3));
416*4882a593Smuzhiyun dff = abs(scl_hz - m1);
417*4882a593Smuzhiyun if (dff < odff) {
418*4882a593Smuzhiyun odff = dff;
419*4882a593Smuzhiyun cdfm = cdf;
420*4882a593Smuzhiyun scgdm = scgd;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun /* fail if more than 25% off of requested SCL */
425*4882a593Smuzhiyun if (odff > (scl_hz >> 2))
426*4882a593Smuzhiyun return -EINVAL;
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /* create a CCR register value */
429*4882a593Smuzhiyun return ((scgdm << 2) | cdfm);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
sh7760_i2c_probe(struct platform_device * pdev)432*4882a593Smuzhiyun static int sh7760_i2c_probe(struct platform_device *pdev)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun struct sh7760_i2c_platdata *pd;
435*4882a593Smuzhiyun struct resource *res;
436*4882a593Smuzhiyun struct cami2c *id;
437*4882a593Smuzhiyun int ret;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun pd = dev_get_platdata(&pdev->dev);
440*4882a593Smuzhiyun if (!pd) {
441*4882a593Smuzhiyun dev_err(&pdev->dev, "no platform_data!\n");
442*4882a593Smuzhiyun ret = -ENODEV;
443*4882a593Smuzhiyun goto out0;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun id = kzalloc(sizeof(struct cami2c), GFP_KERNEL);
447*4882a593Smuzhiyun if (!id) {
448*4882a593Smuzhiyun dev_err(&pdev->dev, "no mem for private data\n");
449*4882a593Smuzhiyun ret = -ENOMEM;
450*4882a593Smuzhiyun goto out0;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
454*4882a593Smuzhiyun if (!res) {
455*4882a593Smuzhiyun dev_err(&pdev->dev, "no mmio resources\n");
456*4882a593Smuzhiyun ret = -ENODEV;
457*4882a593Smuzhiyun goto out1;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name);
461*4882a593Smuzhiyun if (!id->ioarea) {
462*4882a593Smuzhiyun dev_err(&pdev->dev, "mmio already reserved\n");
463*4882a593Smuzhiyun ret = -EBUSY;
464*4882a593Smuzhiyun goto out1;
465*4882a593Smuzhiyun }
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun id->iobase = ioremap(res->start, REGSIZE);
468*4882a593Smuzhiyun if (!id->iobase) {
469*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot ioremap\n");
470*4882a593Smuzhiyun ret = -ENODEV;
471*4882a593Smuzhiyun goto out2;
472*4882a593Smuzhiyun }
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun ret = platform_get_irq(pdev, 0);
475*4882a593Smuzhiyun if (ret < 0)
476*4882a593Smuzhiyun goto out3;
477*4882a593Smuzhiyun id->irq = ret;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun id->adap.nr = pdev->id;
480*4882a593Smuzhiyun id->adap.algo = &sh7760_i2c_algo;
481*4882a593Smuzhiyun id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
482*4882a593Smuzhiyun id->adap.retries = 3;
483*4882a593Smuzhiyun id->adap.algo_data = id;
484*4882a593Smuzhiyun id->adap.dev.parent = &pdev->dev;
485*4882a593Smuzhiyun snprintf(id->adap.name, sizeof(id->adap.name),
486*4882a593Smuzhiyun "SH7760 I2C at %08lx", (unsigned long)res->start);
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun OUT32(id, I2CMCR, 0);
489*4882a593Smuzhiyun OUT32(id, I2CMSR, 0);
490*4882a593Smuzhiyun OUT32(id, I2CMIER, 0);
491*4882a593Smuzhiyun OUT32(id, I2CMAR, 0);
492*4882a593Smuzhiyun OUT32(id, I2CSIER, 0);
493*4882a593Smuzhiyun OUT32(id, I2CSAR, 0);
494*4882a593Smuzhiyun OUT32(id, I2CSCR, 0);
495*4882a593Smuzhiyun OUT32(id, I2CSSR, 0);
496*4882a593Smuzhiyun OUT32(id, I2CFIER, 0);
497*4882a593Smuzhiyun OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST);
498*4882a593Smuzhiyun OUT32(id, I2CFSR, 0);
499*4882a593Smuzhiyun
500*4882a593Smuzhiyun ret = calc_CCR(pd->speed_khz * 1000);
501*4882a593Smuzhiyun if (ret < 0) {
502*4882a593Smuzhiyun dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n",
503*4882a593Smuzhiyun pd->speed_khz);
504*4882a593Smuzhiyun goto out3;
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun OUT32(id, I2CCCR, ret);
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun if (request_irq(id->irq, sh7760_i2c_irq, 0,
509*4882a593Smuzhiyun SH7760_I2C_DEVNAME, id)) {
510*4882a593Smuzhiyun dev_err(&pdev->dev, "cannot get irq %d\n", id->irq);
511*4882a593Smuzhiyun ret = -EBUSY;
512*4882a593Smuzhiyun goto out3;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun ret = i2c_add_numbered_adapter(&id->adap);
516*4882a593Smuzhiyun if (ret < 0)
517*4882a593Smuzhiyun goto out4;
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun platform_set_drvdata(pdev, id);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n",
522*4882a593Smuzhiyun pd->speed_khz, res->start, id->irq);
523*4882a593Smuzhiyun
524*4882a593Smuzhiyun return 0;
525*4882a593Smuzhiyun
526*4882a593Smuzhiyun out4:
527*4882a593Smuzhiyun free_irq(id->irq, id);
528*4882a593Smuzhiyun out3:
529*4882a593Smuzhiyun iounmap(id->iobase);
530*4882a593Smuzhiyun out2:
531*4882a593Smuzhiyun release_resource(id->ioarea);
532*4882a593Smuzhiyun kfree(id->ioarea);
533*4882a593Smuzhiyun out1:
534*4882a593Smuzhiyun kfree(id);
535*4882a593Smuzhiyun out0:
536*4882a593Smuzhiyun return ret;
537*4882a593Smuzhiyun }
538*4882a593Smuzhiyun
sh7760_i2c_remove(struct platform_device * pdev)539*4882a593Smuzhiyun static int sh7760_i2c_remove(struct platform_device *pdev)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun struct cami2c *id = platform_get_drvdata(pdev);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun i2c_del_adapter(&id->adap);
544*4882a593Smuzhiyun free_irq(id->irq, id);
545*4882a593Smuzhiyun iounmap(id->iobase);
546*4882a593Smuzhiyun release_resource(id->ioarea);
547*4882a593Smuzhiyun kfree(id->ioarea);
548*4882a593Smuzhiyun kfree(id);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun static struct platform_driver sh7760_i2c_drv = {
554*4882a593Smuzhiyun .driver = {
555*4882a593Smuzhiyun .name = SH7760_I2C_DEVNAME,
556*4882a593Smuzhiyun },
557*4882a593Smuzhiyun .probe = sh7760_i2c_probe,
558*4882a593Smuzhiyun .remove = sh7760_i2c_remove,
559*4882a593Smuzhiyun };
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun module_platform_driver(sh7760_i2c_drv);
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun MODULE_LICENSE("GPL");
564*4882a593Smuzhiyun MODULE_DESCRIPTION("SH7760 I2C bus driver");
565*4882a593Smuzhiyun MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
566