• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/cx25821/
1/*
2 *  Driver for the Conexant CX25821 PCIe bridge
3 *
4 *  Copyright (C) 2009 Conexant Systems Inc.
5 *  Authors  <shu.lin@conexant.com>, <hiep.huynh@conexant.com>
6 *	Based on Steven Toth <stoth@linuxtv.org> cx23885 driver
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24#include "cx25821.h"
25#include <linux/i2c.h>
26
27static unsigned int i2c_debug;
28module_param(i2c_debug, int, 0644);
29MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
30
31static unsigned int i2c_scan;
32module_param(i2c_scan, int, 0444);
33MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
34
35#define dprintk(level, fmt, arg...)\
36	do { if (i2c_debug >= level)\
37		printk(KERN_DEBUG "%s/0: " fmt, dev->name, ## arg);\
38	} while (0)
39
40#define I2C_WAIT_DELAY 32
41#define I2C_WAIT_RETRY 64
42
43#define I2C_EXTEND  (1 << 3)
44#define I2C_NOSTOP  (1 << 4)
45
46static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
47{
48	struct cx25821_i2c *bus = i2c_adap->algo_data;
49	struct cx25821_dev *dev = bus->dev;
50	return cx_read(bus->reg_stat) & 0x01;
51}
52
53static inline int i2c_is_busy(struct i2c_adapter *i2c_adap)
54{
55	struct cx25821_i2c *bus = i2c_adap->algo_data;
56	struct cx25821_dev *dev = bus->dev;
57	return cx_read(bus->reg_stat) & 0x02 ? 1 : 0;
58}
59
60static int i2c_wait_done(struct i2c_adapter *i2c_adap)
61{
62	int count;
63
64	for (count = 0; count < I2C_WAIT_RETRY; count++) {
65		if (!i2c_is_busy(i2c_adap))
66			break;
67		udelay(I2C_WAIT_DELAY);
68	}
69
70	if (I2C_WAIT_RETRY == count)
71		return 0;
72
73	return 1;
74}
75
76static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
77			 const struct i2c_msg *msg, int joined_rlen)
78{
79	struct cx25821_i2c *bus = i2c_adap->algo_data;
80	struct cx25821_dev *dev = bus->dev;
81	u32 wdata, addr, ctrl;
82	int retval, cnt;
83
84	if (joined_rlen)
85		dprintk(1, "%s(msg->wlen=%d, nextmsg->rlen=%d)\n", __func__,
86			msg->len, joined_rlen);
87	else
88		dprintk(1, "%s(msg->len=%d)\n", __func__, msg->len);
89
90	/* Deal with i2c probe functions with zero payload */
91	if (msg->len == 0) {
92		cx_write(bus->reg_addr, msg->addr << 25);
93		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2));
94
95		if (!i2c_wait_done(i2c_adap))
96			return -EIO;
97
98		if (!i2c_slave_did_ack(i2c_adap))
99			return -EIO;
100
101		dprintk(1, "%s() returns 0\n", __func__);
102		return 0;
103	}
104
105	/* dev, reg + first byte */
106	addr = (msg->addr << 25) | msg->buf[0];
107	wdata = msg->buf[0];
108
109	ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
110
111	if (msg->len > 1)
112		ctrl |= I2C_NOSTOP | I2C_EXTEND;
113	else if (joined_rlen)
114		ctrl |= I2C_NOSTOP;
115
116	cx_write(bus->reg_addr, addr);
117	cx_write(bus->reg_wdata, wdata);
118	cx_write(bus->reg_ctrl, ctrl);
119
120	retval = i2c_wait_done(i2c_adap);
121	if (retval < 0)
122		goto err;
123
124	if (retval == 0)
125		goto eio;
126
127	if (i2c_debug) {
128		if (!(ctrl & I2C_NOSTOP))
129			printk(" >\n");
130	}
131
132	for (cnt = 1; cnt < msg->len; cnt++) {
133		/* following bytes */
134		wdata = msg->buf[cnt];
135		ctrl = bus->i2c_period | (1 << 12) | (1 << 2);
136
137		if (cnt < msg->len - 1)
138			ctrl |= I2C_NOSTOP | I2C_EXTEND;
139		else if (joined_rlen)
140			ctrl |= I2C_NOSTOP;
141
142		cx_write(bus->reg_addr, addr);
143		cx_write(bus->reg_wdata, wdata);
144		cx_write(bus->reg_ctrl, ctrl);
145
146		retval = i2c_wait_done(i2c_adap);
147		if (retval < 0)
148			goto err;
149
150		if (retval == 0)
151			goto eio;
152
153		if (i2c_debug) {
154			dprintk(1, " %02x", msg->buf[cnt]);
155			if (!(ctrl & I2C_NOSTOP))
156				dprintk(1, " >\n");
157		}
158	}
159
160	return msg->len;
161
162eio:
163	retval = -EIO;
164err:
165	if (i2c_debug)
166		printk(KERN_ERR " ERR: %d\n", retval);
167	return retval;
168}
169
170static int i2c_readbytes(struct i2c_adapter *i2c_adap,
171			 const struct i2c_msg *msg, int joined)
172{
173	struct cx25821_i2c *bus = i2c_adap->algo_data;
174	struct cx25821_dev *dev = bus->dev;
175	u32 ctrl, cnt;
176	int retval;
177
178	if (i2c_debug && !joined)
179		dprintk(1, "6-%s(msg->len=%d)\n", __func__, msg->len);
180
181	/* Deal with i2c probe functions with zero payload */
182	if (msg->len == 0) {
183		cx_write(bus->reg_addr, msg->addr << 25);
184		cx_write(bus->reg_ctrl, bus->i2c_period | (1 << 2) | 1);
185		if (!i2c_wait_done(i2c_adap))
186			return -EIO;
187		if (!i2c_slave_did_ack(i2c_adap))
188			return -EIO;
189
190		dprintk(1, "%s() returns 0\n", __func__);
191		return 0;
192	}
193
194	if (i2c_debug) {
195		if (joined)
196			dprintk(1, " R");
197		else
198			dprintk(1, " <R %02x", (msg->addr << 1) + 1);
199	}
200
201	for (cnt = 0; cnt < msg->len; cnt++) {
202
203		ctrl = bus->i2c_period | (1 << 12) | (1 << 2) | 1;
204
205		if (cnt < msg->len - 1)
206			ctrl |= I2C_NOSTOP | I2C_EXTEND;
207
208		cx_write(bus->reg_addr, msg->addr << 25);
209		cx_write(bus->reg_ctrl, ctrl);
210
211		retval = i2c_wait_done(i2c_adap);
212		if (retval < 0)
213			goto err;
214		if (retval == 0)
215			goto eio;
216		msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff;
217
218		if (i2c_debug) {
219			dprintk(1, " %02x", msg->buf[cnt]);
220			if (!(ctrl & I2C_NOSTOP))
221				dprintk(1, " >\n");
222		}
223	}
224
225	return msg->len;
226eio:
227	retval = -EIO;
228err:
229	if (i2c_debug)
230		printk(KERN_ERR " ERR: %d\n", retval);
231	return retval;
232}
233
234static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
235{
236	struct cx25821_i2c *bus = i2c_adap->algo_data;
237	struct cx25821_dev *dev = bus->dev;
238	int i, retval = 0;
239
240	dprintk(1, "%s(num = %d)\n", __func__, num);
241
242	for (i = 0; i < num; i++) {
243		dprintk(1, "%s(num = %d) addr = 0x%02x  len = 0x%x\n",
244			__func__, num, msgs[i].addr, msgs[i].len);
245
246		if (msgs[i].flags & I2C_M_RD) {
247			/* read */
248			retval = i2c_readbytes(i2c_adap, &msgs[i], 0);
249		} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
250			   msgs[i].addr == msgs[i + 1].addr) {
251			/* write then read from same address */
252			retval =
253			    i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len);
254
255			if (retval < 0)
256				goto err;
257			i++;
258			retval = i2c_readbytes(i2c_adap, &msgs[i], 1);
259		} else {
260			/* write */
261			retval = i2c_sendbytes(i2c_adap, &msgs[i], 0);
262		}
263
264		if (retval < 0)
265			goto err;
266	}
267	return num;
268
269err:
270	return retval;
271}
272
273
274static u32 cx25821_functionality(struct i2c_adapter *adap)
275{
276	return I2C_FUNC_SMBUS_EMUL |
277	    I2C_FUNC_I2C |
278	    I2C_FUNC_SMBUS_WORD_DATA |
279	    I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA;
280}
281
282static struct i2c_algorithm cx25821_i2c_algo_template = {
283	.master_xfer = i2c_xfer,
284	.functionality = cx25821_functionality,
285#ifdef NEED_ALGO_CONTROL
286       .algo_control = dummy_algo_control,
287#endif
288};
289
290static struct i2c_adapter cx25821_i2c_adap_template = {
291	.name = "cx25821",
292	.owner = THIS_MODULE,
293	.algo = &cx25821_i2c_algo_template,
294};
295
296static struct i2c_client cx25821_i2c_client_template = {
297	.name = "cx25821 internal",
298};
299
300/* init + register i2c algo-bit adapter */
301int cx25821_i2c_register(struct cx25821_i2c *bus)
302{
303	struct cx25821_dev *dev = bus->dev;
304
305	dprintk(1, "%s(bus = %d)\n", __func__, bus->nr);
306
307	memcpy(&bus->i2c_adap, &cx25821_i2c_adap_template,
308	       sizeof(bus->i2c_adap));
309	memcpy(&bus->i2c_algo, &cx25821_i2c_algo_template,
310	       sizeof(bus->i2c_algo));
311	memcpy(&bus->i2c_client, &cx25821_i2c_client_template,
312	       sizeof(bus->i2c_client));
313
314	bus->i2c_adap.dev.parent = &dev->pci->dev;
315
316	strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
317
318	bus->i2c_algo.data = bus;
319	bus->i2c_adap.algo_data = bus;
320	i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
321	i2c_add_adapter(&bus->i2c_adap);
322
323	bus->i2c_client.adapter = &bus->i2c_adap;
324
325	/* set up the I2c */
326	bus->i2c_client.addr = (0x88 >> 1);
327
328	return bus->i2c_rc;
329}
330
331int cx25821_i2c_unregister(struct cx25821_i2c *bus)
332{
333	i2c_del_adapter(&bus->i2c_adap);
334	return 0;
335}
336
337void cx25821_av_clk(struct cx25821_dev *dev, int enable)
338{
339	/* write 0 to bus 2 addr 0x144 via i2x_xfer() */
340	char buffer[3];
341	struct i2c_msg msg;
342	dprintk(1, "%s(enabled = %d)\n", __func__, enable);
343
344	/* Register 0x144 */
345	buffer[0] = 0x01;
346	buffer[1] = 0x44;
347	if (enable == 1)
348		buffer[2] = 0x05;
349	else
350		buffer[2] = 0x00;
351
352	msg.addr = 0x44;
353	msg.flags = I2C_M_TEN;
354	msg.len = 3;
355	msg.buf = buffer;
356
357	i2c_xfer(&dev->i2c_bus[0].i2c_adap, &msg, 1);
358}
359
360int cx25821_i2c_read(struct cx25821_i2c *bus, u16 reg_addr, int *value)
361{
362	struct i2c_client *client = &bus->i2c_client;
363	int retval = 0;
364	int v = 0;
365	u8 addr[2] = { 0, 0 };
366	u8 buf[4] = { 0, 0, 0, 0 };
367
368	struct i2c_msg msgs[2] = {
369		{
370		 .addr = client->addr,
371		 .flags = 0,
372		 .len = 2,
373		 .buf = addr,
374		 }, {
375		     .addr = client->addr,
376		     .flags = I2C_M_RD,
377		     .len = 4,
378		     .buf = buf,
379		     }
380	};
381
382	addr[0] = (reg_addr >> 8);
383	addr[1] = (reg_addr & 0xff);
384	msgs[0].addr = 0x44;
385	msgs[1].addr = 0x44;
386
387	retval = i2c_xfer(client->adapter, msgs, 2);
388
389	v = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
390	*value = v;
391
392	return v;
393}
394
395int cx25821_i2c_write(struct cx25821_i2c *bus, u16 reg_addr, int value)
396{
397	struct i2c_client *client = &bus->i2c_client;
398	int retval = 0;
399	u8 buf[6] = { 0, 0, 0, 0, 0, 0 };
400
401	struct i2c_msg msgs[1] = {
402		{
403		 .addr = client->addr,
404		 .flags = 0,
405		 .len = 6,
406		 .buf = buf,
407		 }
408	};
409
410	buf[0] = reg_addr >> 8;
411	buf[1] = reg_addr & 0xff;
412	buf[5] = (value >> 24) & 0xff;
413	buf[4] = (value >> 16) & 0xff;
414	buf[3] = (value >> 8) & 0xff;
415	buf[2] = value & 0xff;
416	client->flags = 0;
417	msgs[0].addr = 0x44;
418
419	retval = i2c_xfer(client->adapter, msgs, 1);
420
421	return retval;
422}
423