xref: /OK3568_Linux_fs/kernel/drivers/i2c/busses/i2c-sh7760.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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