• 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/i2c/busses/
1/*
2 * I2C master mode driver for 5301x chip.
3 *
4 * Copyright (C) 2015, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * $Id:  $
19 */
20
21#include <linux/module.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <linux/interrupt.h>
25#include <linux/delay.h>
26#include <linux/completion.h>
27#include <linux/i2c.h>
28#include <linux/i2c-algo-bit.h>
29
30#include <osl.h>
31#include <siutils.h>
32#include <hndsoc.h>
33#include <chipcommonb.h>
34
35/* Configuration */
36#define BCM5301X_CFG_DRV_NAME					"i2c-bcm5301x"
37#define BCM5301X_CFG_BB_DRV_NAME				"i2c-bcm5301x-bb"
38#define BCM5301X_CFG_DBG					0
39#define BCM5301X_CFG_INFO					0
40#define BCM5301X_CFG_ERR					1
41#define BCM5301X_CFG_SMBUS_RETRY_CNT				4
42#define BCM5301X_CFG_SMBUS_IDLE_TIME				100
43#define BCM5301X_CFG_TIMEOUT_MS(len)				(200 + (len))
44#define BCM5301X_CFG_TIMEOUT(len)				msecs_to_jiffies(BCM5301X_CFG_TIMEOUT_MS(len))
45#define BCM5301X_CFG_MIN_RETRY_CNT				3
46#define BCM5301X_CFG_MIN_RETRY_MS				20
47#define BCM5301X_CFG_RX_THRESH					(BCM5301X_SMBUS_FIFO_DEPTH / 2)
48/***************************************************/
49
50/*
51 * Debug
52 *
53 * Please be careful with printing debug messages over serial line.
54 * Printing messages in ISR cost me several hours of debugging.
55 * Print is finished quickly, but later I2C controller ISR postponed for ~20 milliseconds because of UART activities.
56 * In couple milliseconds I2C RX FIFO became full and triggered RX FIFO full interrupt - which is normal.
57 * But UART acitivities hold off I2C ISR for much longer. When finally I2C ISR begin execution it found that
58 * RX FIFO is actually empty (seems somehow self-resetted) and I2C device is not acting sane anymore.
59 * Theory that relatively long time keeping device paused in the middle of transaction make device
60 * fail and send some signals and reaction to them was I2C controller cleared RX FIFO.
61 */
62#define BCM5301X_2STR_1(x)					BCM5301X_2STR_2(x)
63#define BCM5301X_2STR_2(x)					#x
64#define BCM5301X_LINE						BCM5301X_2STR_1(__LINE__)
65#define BCM5301X_MSG(level, fmt, args...)			printk(level __FILE__ " : " BCM5301X_LINE " : " fmt "\n", ## args)
66#if BCM5301X_CFG_DBG
67# define BCM5301X_MSG_DBG(...)					BCM5301X_MSG(KERN_DEBUG, __VA_ARGS__)
68#else
69# define BCM5301X_MSG_DBG(...)
70#endif
71#if BCM5301X_CFG_INFO
72# define BCM5301X_MSG_INFO(...)					BCM5301X_MSG(KERN_INFO, __VA_ARGS__)
73#else
74# define BCM5301X_MSG_INFO(...)
75#endif
76#if BCM5301X_CFG_ERR
77# define BCM5301X_MSG_ERR(...)					BCM5301X_MSG(KERN_ERR, __VA_ARGS__)
78#else
79# define BCM5301X_MSG_ERR(...)
80#endif
81#define BCM5301X_MSG_MAX_LEN					16
82/***************************************************/
83
84/* Hardware */
85
86#define BCM5301X_BIT(shift)					(1 << (shift))
87#define BCM5301X_MASK_S(val, mask, shift)			(((val) & (mask)) << (shift))
88#define BCM5301X_MASK_G(val, mask, shift)			(((val) >> (shift)) & (mask))
89
90#define BCM5301X_SMBUS_CFG_RESET_B				BCM5301X_BIT(31)
91#define BCM5301X_SMBUS_CFG_SMB_EN_B				BCM5301X_BIT(30)
92#define BCM5301X_SMBUS_CFG_BITBANG_EN_B				BCM5301X_BIT(29)
93#define BCM5301X_SMBUS_CFG_EN_NIC_SMB_ADDR_0_B			BCM5301X_BIT(28)
94#define BCM5301X_SMBUS_CFG_PROMISCOUS_MODE_B			BCM5301X_BIT(27)
95#define BCM5301X_SMBUS_CFG_TIMESTAMP_CNT_EN_B			BCM5301X_BIT(26)
96#define BCM5301X_SMBUS_CFG_MASTER_RETRY_CNT_S(v)		BCM5301X_MASK_S(v, 0xF, 16)
97
98#define BCM5301X_SMBUS_TIMING_CFG_MODE_400_B			BCM5301X_BIT(31)
99#define BCM5301X_SMBUS_TIMING_CFG_RANDOM_SLAVE_STRETCH_S(v)	BCM5301X_MASK_S(v, 0x7F, 24)
100#define BCM5301X_SMBUS_TIMING_CFG_PERIODIC_SLAVE_STRETCH_S(v)	BCM5301X_MASK_S(v, 0xFF, 16)
101#define BCM5301X_SMBUS_TIMING_CFG_SMBUS_IDLE_TIME_S(v)		BCM5301X_MASK_S(v, 0xFF, 8)
102
103#define BCM5301X_SMBUS_MASTER_FIFO_CTRL_RX_FIFO_FLUSH_B		BCM5301X_BIT(31)
104#define BCM5301X_SMBUS_MASTER_FIFO_CTRL_TX_FIFO_FLUSH_B		BCM5301X_BIT(30)
105#define BCM5301X_SMBUS_MASTER_FIFO_CTRL_RX_PKT_CNT_G(v)		BCM5301X_MASK_G(v, 0x7F, 16)
106#define BCM5301X_SMBUS_MASTER_FIFO_CTRL_RX_FIFO_THRESH_S(v)	BCM5301X_MASK_S(v, 0x3F, 8)
107
108#define BCM5301X_SMBUS_BB_CLK_IN				BCM5301X_BIT(31)
109#define BCM5301X_SMBUS_BB_CLK_OUT_EN				BCM5301X_BIT(30)
110#define BCM5301X_SMBUS_BB_DAT_IN				BCM5301X_BIT(29)
111#define BCM5301X_SMBUS_BB_DAT_OUT_EN				BCM5301X_BIT(28)
112
113#define BCM5301X_SMBUS_MASTER_CMD_START_BUSY_COMM_B		BCM5301X_BIT(31)
114#define BCM5301X_SMBUS_MASTER_CMD_ABORT_B			BCM5301X_BIT(30)
115#define BCM5301X_SMBUS_MASTER_CMD_STATUS_G(v)			BCM5301X_MASK_G(v, 0x7, 25)
116#define BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(v)		BCM5301X_MASK_S(v, 0xF, 9)
117#define BCM5301X_SMBUS_MASTER_CMD_PEC_B				BCM5301X_BIT(8)
118#define BCM5301X_SMBUS_MASTER_CMD_RD_BYTE_CNT_S(v)		BCM5301X_MASK_S(v, 0xFF, 0)
119#define BCM5301X_SMBUS_MASTER_CMD_RD_BYTE_CNT_G(v)		BCM5301X_MASK_G(v, 0xFF, 0)
120
121#define BCM5301X_SMBUS_MASTER_CMD_STATUS_SUCCESS		0x0
122#define BCM5301X_SMBUS_MASTER_CMD_STATUS_LOST_ARB		0x1
123#define BCM5301X_SMBUS_MASTER_CMD_STATUS_OFFLINE		0x2
124#define BCM5301X_SMBUS_MASTER_CMD_STATUS_NACK			0x3
125#define BCM5301X_SMBUS_MASTER_CMD_STATUS_DEV_TIMEOUT		0x4
126#define BCM5301X_SMBUS_MASTER_CMD_STATUS_TX_UNDERRUN_TIMEOUT	0x5
127#define BCM5301X_SMBUS_MASTER_CMD_STATUS_RX_FULL_TIMEOUT	0x6
128
129#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_QUICK_CMD_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x0)
130#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_SEND_BYTE_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x1)
131#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_RECEIVE_BYTE_B	BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x2)
132#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_WRITE_BYTE_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x3)
133#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_READ_BYTE_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x4)
134#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_WRITE_WORD_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x5)
135#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_READ_WORD_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x6)
136#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_BLOCK_WRITE_B	BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x7)
137#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_BLOCK_READ_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x8)
138#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_PROC_CALL_B		BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0x9)
139#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_BLOCK_PROC_CALL_B	BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0xA)
140#define BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_HOST_NOTIFY_B	BCM5301X_SMBUS_MASTER_CMD_SMBUS_PROTOCOL_S(0xB)
141
142#define BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_FIFO_FULL_B	BCM5301X_BIT(31)
143#define BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_THRESH_HIT_B	BCM5301X_BIT(30)
144#define BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_EVENT_B		BCM5301X_BIT(29)
145#define BCM5301X_SMBUS_EVENT_ENABLE_MASTER_START_BUSY_B		BCM5301X_BIT(28)
146#define BCM5301X_SMBUS_EVENT_ENABLE_MASTER_TX_UNDERRUN_B	BCM5301X_BIT(27)
147#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_RX_FIFO_FULL_B	BCM5301X_BIT(26)
148#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_RX_THRESH_HIT_B	BCM5301X_BIT(25)
149#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_RX_EVENT_B		BCM5301X_BIT(24)
150#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_START_BUSY_B		BCM5301X_BIT(23)
151#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_TX_UNDERRUN_B		BCM5301X_BIT(22)
152#define BCM5301X_SMBUS_EVENT_ENABLE_SLAVE_RD_EVENT_B		BCM5301X_BIT(21)
153
154#define BCM5301X_SMBUS_EVENT_STATUS_MASTER_RX_FIFO_FULL_B	BCM5301X_BIT(31)
155#define BCM5301X_SMBUS_EVENT_STATUS_MASTER_RX_THRESH_HIT_B	BCM5301X_BIT(30)
156#define BCM5301X_SMBUS_EVENT_STATUS_MASTER_RX_EVENT_B		BCM5301X_BIT(29)
157#define BCM5301X_SMBUS_EVENT_STATUS_MASTER_START_BUSY_B		BCM5301X_BIT(28)
158#define BCM5301X_SMBUS_EVENT_STATUS_MASTER_TX_UNDERRUN_B	BCM5301X_BIT(27)
159#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_RX_FIFO_FULL_B	BCM5301X_BIT(26)
160#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_RX_THRESH_HIT_B	BCM5301X_BIT(25)
161#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_RX_EVENT_B		BCM5301X_BIT(24)
162#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_START_BUSY_B		BCM5301X_BIT(23)
163#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_TX_UNDERRUN_B		BCM5301X_BIT(22)
164#define BCM5301X_SMBUS_EVENT_STATUS_SLAVE_RD_EVENT_B		BCM5301X_BIT(21)
165
166#define BCM5301X_SMBUS_MASTER_DATA_WRITE_STATUS_B		BCM5301X_BIT(31)
167#define BCM5301X_SMBUS_MASTER_DATA_WRITE_DATA_S(v)		BCM5301X_MASK_S(v, 0xFF, 0)
168
169#define BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_G(v)		BCM5301X_MASK_G(v, 0x3, 30)
170#define BCM5301X_SMBUS_MASTER_DATA_READ_PEC_ERR_B		BCM5301X_BIT(29)
171#define BCM5301X_SMBUS_MASTER_DATA_READ_DATA_G(v)		BCM5301X_MASK_G(v, 0xFF, 0)
172
173#define BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_EMPTY		0x0
174#define BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_START		0x1
175#define BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_MIDDLE		0x2
176#define BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_END		0x3
177
178#define BCM5301X_SMBUS_FIFO_DEPTH				64
179
180#define BCM5301X_SMBUS_RX_MAX_CNT				BCM5301X_SMBUS_MASTER_CMD_RD_BYTE_CNT_G(~((uint32)0))
181
182#define BCM5301X_SMBUS_TX_EVENT_MASK				BCM5301X_SMBUS_EVENT_ENABLE_MASTER_TX_UNDERRUN_B
183#define BCM5301X_SMBUS_RX_EVENT_MASK \
184	(BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_FIFO_FULL_B | \
185	BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_THRESH_HIT_B | \
186	BCM5301X_SMBUS_EVENT_ENABLE_MASTER_RX_EVENT_B)
187
188#define BCM5301X_SMBUS_TX_STATUS_MASK				BCM5301X_SMBUS_TX_EVENT_MASK
189#define BCM5301X_SMBUS_RX_STATUS_MASK				BCM5301X_SMBUS_RX_EVENT_MASK
190
191/***************************************************/
192
193struct bcm5301x_i2c_data
194{
195	struct i2c_adapter adap;
196	int irq;
197	chipcommonbregs_t *ccb;
198	bool fast;
199	uint16 consumed;
200	struct i2c_msg *pmsg;
201	struct completion done;
202	struct i2c_adapter bb_adap;
203	struct i2c_algo_bit_data bb_data;
204};
205
206static void bcm5301x_bb_setsda(void *data, int state)
207{
208	struct bcm5301x_i2c_data *pdata = data;
209	chipcommonbregs_t *ccb = pdata->ccb;
210	uint32 bb_reg = R_REG(SI_OSH, &ccb->smbus_bit_bang_control);
211
212	if (state) {
213		bb_reg |= BCM5301X_SMBUS_BB_DAT_OUT_EN;
214	} else {
215		bb_reg &= ~BCM5301X_SMBUS_BB_DAT_OUT_EN;
216	}
217
218	W_REG(SI_OSH, &ccb->smbus_bit_bang_control, bb_reg);
219}
220
221static void bcm5301x_bb_setscl(void *data, int state)
222{
223	struct bcm5301x_i2c_data *pdata = data;
224	chipcommonbregs_t *ccb = pdata->ccb;
225	uint32 bb_reg = R_REG(SI_OSH, &ccb->smbus_bit_bang_control);
226
227	if (state) {
228		bb_reg |= BCM5301X_SMBUS_BB_CLK_OUT_EN;
229	} else {
230		bb_reg &= ~BCM5301X_SMBUS_BB_CLK_OUT_EN;
231	}
232
233	W_REG(SI_OSH, &ccb->smbus_bit_bang_control, bb_reg);
234}
235
236static int bcm5301x_bb_getsda(void *data)
237{
238	struct bcm5301x_i2c_data *pdata = data;
239	chipcommonbregs_t *ccb = pdata->ccb;
240
241	return (R_REG(SI_OSH, &ccb->smbus_bit_bang_control) & BCM5301X_SMBUS_BB_DAT_IN) ? 1 : 0;
242}
243
244static int bcm5301x_bb_getscl(void *data)
245{
246	struct bcm5301x_i2c_data *pdata = data;
247	chipcommonbregs_t *ccb = pdata->ccb;
248
249	return (R_REG(SI_OSH, &ccb->smbus_bit_bang_control) & BCM5301X_SMBUS_BB_CLK_IN) ? 1 : 0;
250}
251
252static int bcm5301x_bb_pre_xfer(struct i2c_adapter *adap)
253{
254	struct i2c_algo_bit_data *bit_data = adap->algo_data;
255	struct bcm5301x_i2c_data *pdata = bit_data->data;
256	chipcommonbregs_t *ccb = pdata->ccb;
257
258	W_REG(SI_OSH, &ccb->smbus_config,
259		R_REG(SI_OSH, &ccb->smbus_config) | BCM5301X_SMBUS_CFG_BITBANG_EN_B);
260
261	return 0;
262}
263
264static void bcm5301x_bb_post_xfer(struct i2c_adapter *adap)
265{
266	struct i2c_algo_bit_data *bit_data = adap->algo_data;
267	struct bcm5301x_i2c_data *pdata = bit_data->data;
268	chipcommonbregs_t *ccb = pdata->ccb;
269
270	W_REG(SI_OSH, &ccb->smbus_config,
271		R_REG(SI_OSH, &ccb->smbus_config) & ~BCM5301X_SMBUS_CFG_BITBANG_EN_B);
272}
273
274static int __devinit bcm5301x_bb_init(struct platform_device *pdev, struct bcm5301x_i2c_data *pdata)
275{
276	struct i2c_algo_bit_data *bb_data = &pdata->bb_data;
277	struct i2c_adapter *bb_adap = &pdata->bb_adap;
278
279	bb_data->setsda = bcm5301x_bb_setsda;
280	bb_data->setscl = bcm5301x_bb_setscl;
281	bb_data->getsda = bcm5301x_bb_getsda;
282	bb_data->getscl = bcm5301x_bb_getscl;
283	bb_data->pre_xfer = bcm5301x_bb_pre_xfer;
284	bb_data->post_xfer = bcm5301x_bb_post_xfer;
285	bb_data->udelay = 5; /* 100 KHz; borrowed from i2c-gpio.c */
286	bb_data->timeout = BCM5301X_CFG_TIMEOUT(0);
287	bb_data->data = pdata;
288
289	bb_adap->owner = THIS_MODULE;
290	snprintf(bb_adap->name, sizeof(bb_adap->name), BCM5301X_CFG_BB_DRV_NAME);
291	bb_adap->algo_data = bb_data;
292	bb_adap->dev.parent = &pdev->dev;
293	bb_adap->nr = pdev->id + 1;
294
295	return i2c_bit_add_numbered_bus(bb_adap);
296}
297
298static bool bcm5301x_i2c_read(struct i2c_msg *pmsg)
299{
300	return ((pmsg->flags & I2C_M_RD) != 0);
301}
302
303const char* bcm5301x_i2c_dirstr(struct i2c_msg *pmsg)
304{
305	return bcm5301x_i2c_read(pmsg) ? "read" : "write";
306}
307
308static void bcm5301x_dump_before(struct i2c_msg *pmsg)
309{
310#if BCM5301X_CFG_DBG
311	int i;
312
313	BCM5301X_MSG_DBG("+++ xfer : %s addr 0x%x flags 0x%x len %u",
314		bcm5301x_i2c_dirstr(pmsg),
315		pmsg->addr,
316		pmsg->flags,
317		pmsg->len);
318
319	if (!bcm5301x_i2c_read(pmsg)) {
320		for (i = 0; i < min(pmsg->len, BCM5301X_MSG_MAX_LEN); ++i) {
321			BCM5301X_MSG_DBG("\t%d : 0x%x", i, pmsg->buf[i]);
322		}
323	}
324#endif /* BCM5301X_CFG_DBG */
325}
326
327static void bcm5301x_dump_after(struct i2c_msg *pmsg, int rc)
328{
329#if BCM5301X_CFG_DBG
330	bool failure = (rc < 0);
331	int i;
332
333	if (!failure && bcm5301x_i2c_read(pmsg)) {
334		for (i = 0; i < min(pmsg->len, BCM5301X_MSG_MAX_LEN); ++i) {
335			BCM5301X_MSG_DBG("\t%d : 0x%x", i, pmsg->buf[i]);
336		}
337	}
338
339	BCM5301X_MSG_DBG("--- xfer : %s addr 0x%x flags 0x%x len %u rc %d %s",
340		bcm5301x_i2c_dirstr(pmsg),
341		pmsg->addr,
342		pmsg->flags,
343		pmsg->len,
344		rc,
345		failure ? "FAILURE" : "SUCCESS");
346#endif /* BCM5301X_CFG_DBG */
347}
348
349static int bcm5301x_check_before(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
350{
351	chipcommonbregs_t *ccb = pdata->ccb;
352	uint32 cmd_reg = R_REG(SI_OSH, &ccb->smbus_master_command);
353
354	if (cmd_reg & BCM5301X_SMBUS_MASTER_CMD_START_BUSY_COMM_B) {
355		BCM5301X_MSG_DBG("not ready reg 0x%x", cmd_reg);
356		return -EBUSY;
357	}
358
359	return 0;
360}
361
362static int bcm5301x_check_after(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
363{
364	chipcommonbregs_t *ccb = pdata->ccb;
365	uint32 cmd_reg = R_REG(SI_OSH, &ccb->smbus_master_command);
366	uint32 cmd_status = BCM5301X_SMBUS_MASTER_CMD_STATUS_G(cmd_reg);
367
368	if (cmd_reg & BCM5301X_SMBUS_MASTER_CMD_START_BUSY_COMM_B) {
369		BCM5301X_MSG_DBG("not ready reg 0x%x", cmd_reg);
370		return -EBUSY;
371	} else if (cmd_status == BCM5301X_SMBUS_MASTER_CMD_STATUS_OFFLINE) {
372		BCM5301X_MSG_DBG("dev offline");
373		return -EAGAIN;
374	} else if (cmd_status != BCM5301X_SMBUS_MASTER_CMD_STATUS_SUCCESS) {
375		BCM5301X_MSG_DBG("failed status 0x%x", cmd_status);
376		return -EIO;
377	} else if (pdata->consumed != pmsg->len) {
378		BCM5301X_MSG_DBG("failed len %d of %d", pdata->consumed, pmsg->len);
379		return -EIO;
380	}
381
382	return 0;
383}
384
385static void bcm5301x_reset(struct bcm5301x_i2c_data *pdata)
386{
387	chipcommonbregs_t *ccb = pdata->ccb;
388
389	W_REG(SI_OSH, &ccb->smbus_config, BCM5301X_SMBUS_CFG_RESET_B);
390	udelay(10);
391}
392
393static void bcm5301x_reset_and_en(struct bcm5301x_i2c_data *pdata)
394{
395	chipcommonbregs_t *ccb = pdata->ccb;
396
397	bcm5301x_reset(pdata);
398
399	W_REG(SI_OSH, &ccb->smbus_master_fifo_control,
400		BCM5301X_SMBUS_MASTER_FIFO_CTRL_RX_FIFO_THRESH_S(BCM5301X_CFG_RX_THRESH));
401	W_REG(SI_OSH, &ccb->smbus_timing_config,
402		(pdata->fast ? BCM5301X_SMBUS_TIMING_CFG_MODE_400_B : 0) |
403		BCM5301X_SMBUS_TIMING_CFG_SMBUS_IDLE_TIME_S(BCM5301X_CFG_SMBUS_IDLE_TIME));
404	W_REG(SI_OSH, &ccb->smbus_config,
405		BCM5301X_SMBUS_CFG_SMB_EN_B |
406		BCM5301X_SMBUS_CFG_MASTER_RETRY_CNT_S(BCM5301X_CFG_SMBUS_RETRY_CNT));
407
408	BCM5301X_MSG_INFO("config 0x%x timing 0x%x",
409		R_REG(SI_OSH, &ccb->smbus_config),
410		R_REG(SI_OSH, &ccb->smbus_timing_config));
411}
412
413static void bcm5301x_xfer_trigger(struct bcm5301x_i2c_data *pdata, uint32 irq, uint32 cmd)
414{
415	chipcommonbregs_t *ccb = pdata->ccb;
416
417	irq |= BCM5301X_SMBUS_EVENT_ENABLE_MASTER_START_BUSY_B;
418	cmd |= BCM5301X_SMBUS_MASTER_CMD_START_BUSY_COMM_B;
419	BCM5301X_MSG_DBG("trigger cmd 0x%x irq 0x%x js %lu", cmd, irq, jiffies);
420
421	/* Cleanup, for safety */
422	while (try_wait_for_completion(&pdata->done)) {
423		BCM5301X_MSG_ERR("spurious irq");
424	}
425
426	/* Enable interrupt */
427	W_REG(SI_OSH, &ccb->smbus_event_enable, irq);
428
429	/* Start transaction */
430	W_REG(SI_OSH, &ccb->smbus_master_command, cmd);
431}
432
433static void bcm5301x_tx_data(struct bcm5301x_i2c_data *pdata, uint16 max_write_len)
434{
435	chipcommonbregs_t *ccb = pdata->ccb;
436	struct i2c_msg *pmsg = pdata->pmsg;
437	uint16 max_offset = pdata->consumed + max_write_len;
438	uint16 last_offset = min(pmsg->len, max_offset);
439
440	while (pdata->consumed < last_offset) {
441		uint32 data = BCM5301X_SMBUS_MASTER_DATA_WRITE_DATA_S(pmsg->buf[pdata->consumed++]);
442
443		if (pdata->consumed == pmsg->len) {
444			/* indicate this is last byte */
445			data |= BCM5301X_SMBUS_MASTER_DATA_WRITE_STATUS_B;
446		}
447
448		W_REG(SI_OSH, &ccb->smbus_master_data_write, data);
449	}
450}
451
452static void bcm5301x_rx_data(struct bcm5301x_i2c_data *pdata)
453{
454	chipcommonbregs_t *ccb = pdata->ccb;
455	struct i2c_msg *pmsg = pdata->pmsg;
456
457	while (pdata->consumed < pmsg->len) {
458		uint32 reg = R_REG(SI_OSH, &ccb->smbus_master_data_read);
459		uint32 status = BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_G(reg);
460
461		if (status == BCM5301X_SMBUS_MASTER_DATA_READ_STATUS_EMPTY) {
462			break;
463		}
464
465		pmsg->buf[pdata->consumed++] = (uint8)BCM5301X_SMBUS_MASTER_DATA_READ_DATA_G(reg);
466	}
467}
468
469static void bcm5301x_tx_start(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
470{
471	chipcommonbregs_t *ccb = pdata->ccb;
472
473	/* Write 7-bit address and keep LSB zero for write operations */
474	W_REG(SI_OSH, &ccb->smbus_master_data_write,
475		BCM5301X_SMBUS_MASTER_DATA_WRITE_DATA_S(pmsg->addr << 1));
476
477	/* Write data to FIFO */
478	bcm5301x_tx_data(pdata, BCM5301X_SMBUS_FIFO_DEPTH - 1 /* addr */);
479
480	/* Trigger transaction */
481	bcm5301x_xfer_trigger(pdata,
482		BCM5301X_SMBUS_TX_EVENT_MASK,
483		BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_BLOCK_WRITE_B);
484}
485
486static void bcm5301x_rx_start(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
487{
488	chipcommonbregs_t *ccb = pdata->ccb;
489
490	/* Write 7-bit address and set LSB for read operations */
491	W_REG(SI_OSH, &ccb->smbus_master_data_write,
492		BCM5301X_SMBUS_MASTER_DATA_WRITE_DATA_S((pmsg->addr << 1) | 0x1));
493
494	/* Trigger transaction */
495	bcm5301x_xfer_trigger(pdata,
496		BCM5301X_SMBUS_RX_EVENT_MASK,
497		BCM5301X_SMBUS_MASTER_CMD_PROTOCOL_BLOCK_READ_B |
498			BCM5301X_SMBUS_MASTER_CMD_RD_BYTE_CNT_S(pmsg->len));
499}
500
501static void bcm5301x_xfer_cleanup(struct bcm5301x_i2c_data *pdata)
502{
503	chipcommonbregs_t *ccb = pdata->ccb;
504
505	/* Disable and ack interrupts */
506	W_REG(SI_OSH, &ccb->smbus_event_enable, 0);
507	W_REG(SI_OSH, &ccb->smbus_event_status, R_REG(SI_OSH, &ccb->smbus_event_status));
508
509	/* Flush FIFOs */
510	W_REG(SI_OSH, &ccb->smbus_master_fifo_control,
511		R_REG(SI_OSH, &ccb->smbus_master_fifo_control) |
512		BCM5301X_SMBUS_MASTER_FIFO_CTRL_RX_FIFO_FLUSH_B |
513		BCM5301X_SMBUS_MASTER_FIFO_CTRL_TX_FIFO_FLUSH_B);
514}
515
516static int bcm5301x_xfer_msg(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
517{
518	int rc = bcm5301x_check_before(pdata, pmsg);
519	if (rc) {
520		return rc;
521	}
522
523	pdata->consumed = 0;
524	pdata->pmsg = pmsg;
525
526	if (bcm5301x_i2c_read(pmsg)) {
527		bcm5301x_rx_start(pdata, pmsg);
528	} else {
529		bcm5301x_tx_start(pdata, pmsg);
530	}
531
532	if (!wait_for_completion_timeout(&pdata->done, BCM5301X_CFG_TIMEOUT(pmsg->len))) {
533		BCM5301X_MSG_DBG("waiting timed out js %lu status 0x%x",
534			jiffies, R_REG(SI_OSH, &pdata->ccb->smbus_event_status));
535		rc = -ETIMEDOUT;
536	} else {
537		rc = bcm5301x_check_after(pdata, pmsg);
538	}
539
540	return rc;
541}
542
543static int bcm5301x_xfer_hw(struct bcm5301x_i2c_data *pdata, struct i2c_msg *pmsg)
544{
545	unsigned long ts = jiffies + max(1UL, msecs_to_jiffies(BCM5301X_CFG_MIN_RETRY_MS));
546	int i = 0;
547	int rc;
548
549	bcm5301x_dump_before(pmsg);
550
551	while (1) {
552		rc = bcm5301x_xfer_msg(pdata, pmsg);
553		if (!rc) {
554			bcm5301x_xfer_cleanup(pdata);
555			break;
556		} else if (rc != -EAGAIN) {
557			break;
558		} else if ((++i >= BCM5301X_CFG_MIN_RETRY_CNT) && (time_after(jiffies, ts))) {
559			BCM5301X_MSG_DBG("%s give up on #%d retry", bcm5301x_i2c_dirstr(pmsg), i);
560			rc = -EIO;
561			break;
562		} else {
563			BCM5301X_MSG_DBG("%s retry #%d", bcm5301x_i2c_dirstr(pmsg), i);
564			bcm5301x_xfer_cleanup(pdata);
565			yield();
566		}
567	}
568
569	bcm5301x_dump_after(pmsg, rc);
570
571	if (rc) {
572		bcm5301x_reset_and_en(pdata);
573	} else {
574		rc = 1;
575	}
576
577	return rc;
578}
579
580static bool bcm5301x_xfer_hw_supp(struct i2c_msg *pmsg_arr, int num)
581{
582	struct i2c_msg *pmsg = &pmsg_arr[0];
583
584	if (num > 1) {
585		/* Support only single message as can't make no STOP between them */
586		return false;
587	}
588
589	if ((pmsg->flags & ~I2C_M_RD) != 0) {
590		/* Support only simple read and write */
591		return false;
592	}
593
594	if ((pmsg->flags & I2C_M_RD) && (pmsg->len > BCM5301X_SMBUS_RX_MAX_CNT)) {
595		/* Read size is limited */
596		return false;
597	}
598
599	return true;
600}
601
602static int bcm5301x_xfer_bb(struct i2c_adapter *adap, struct i2c_msg *pmsg_arr, int num)
603{
604	int rc;
605	int i;
606
607	for (i = 0; i < num; ++i) {
608		bcm5301x_dump_before(&pmsg_arr[i]);
609	}
610
611	rc = adap->algo->master_xfer(adap, pmsg_arr, num);
612
613	for (i = 0; i < num; ++i) {
614		bcm5301x_dump_after(&pmsg_arr[i], rc);
615	}
616
617	return rc;
618}
619
620static int bcm5301x_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg_arr, int num)
621{
622	struct bcm5301x_i2c_data *pdata = adap->algo_data;
623	struct i2c_msg *pmsg = &pmsg_arr[0];
624	int rc = -ENOSYS;
625
626	if (num < 1) {
627		return -EINVAL;
628	}
629
630	i2c_lock_adapter(&pdata->bb_adap);
631
632	if (bcm5301x_xfer_hw_supp(pmsg_arr, num)) {
633		rc = bcm5301x_xfer_hw(pdata, pmsg);
634	}
635
636	if (rc < 0) {
637		rc = bcm5301x_xfer_bb(&pdata->bb_adap, pmsg_arr, num);
638	}
639
640	i2c_unlock_adapter(&pdata->bb_adap);
641
642	return rc;
643}
644
645static u32 bcm5301x_func(struct i2c_adapter *adapter)
646{
647	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
648}
649
650static irqreturn_t bcm5301x_i2c_irq(int irqno, void *dev_id)
651{
652	struct bcm5301x_i2c_data *pdata = dev_id;
653	chipcommonbregs_t *ccb = pdata->ccb;
654	uint32 status = R_REG(SI_OSH, &ccb->smbus_event_status);
655
656	BCM5301X_MSG_DBG("enter irq %d status 0x%x js %lu consumed %d",
657		irqno, status, jiffies, pdata->consumed);
658
659	W_REG(SI_OSH, &ccb->smbus_event_status, status);
660
661	if (status & BCM5301X_SMBUS_RX_STATUS_MASK) {
662		bcm5301x_rx_data(pdata);
663	}
664	if (status & BCM5301X_SMBUS_TX_STATUS_MASK) {
665		bcm5301x_tx_data(pdata, BCM5301X_SMBUS_FIFO_DEPTH);
666	}
667	if (status & BCM5301X_SMBUS_EVENT_STATUS_MASTER_START_BUSY_B) {
668		complete(&pdata->done);
669	}
670
671	BCM5301X_MSG_DBG("leave irq %d status 0x%x js %lu consumed %d",
672		irqno, status, jiffies, pdata->consumed);
673
674	return IRQ_HANDLED;
675}
676
677static int __devinit bcm5301x_hwinit(struct bcm5301x_i2c_data *pdata)
678{
679	si_t *sih;
680	chipcommonbregs_t *ccb;
681
682	sih = si_kattach(SI_OSH);
683	if (!sih) {
684		BCM5301X_MSG_ERR("can't get sih");
685		return -ENXIO;
686	}
687
688	ccb = si_setcore(sih, NS_CCB_CORE_ID, 0);
689	if (!ccb) {
690		BCM5301X_MSG_ERR("can't get ccb");
691		return -ENXIO;
692	}
693	pdata->ccb = ccb;
694
695	bcm5301x_reset_and_en(pdata);
696
697	return 0;
698}
699
700static struct i2c_algorithm bcm5301x_algorithm = {
701	.master_xfer	= bcm5301x_xfer,
702	.functionality	= bcm5301x_func,
703};
704
705static int __devinit bcm5301x_i2c_probe(struct platform_device *pdev)
706{
707	struct bcm5301x_i2c_data *pdata;
708	struct i2c_adapter *adap;
709	struct resource *res;
710	int irq;
711	bool fast;
712	int rc;
713
714	BCM5301X_MSG_INFO("probe");
715
716	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
717	if (!res) {
718		BCM5301X_MSG_ERR("no resources");
719		rc = -EINVAL;
720		goto fail_get_res;
721	}
722	irq = res->start;
723	fast = res->end;
724	if (irq <= 0) {
725		BCM5301X_MSG_ERR("bad irqno %d", irq);
726		rc = -EINVAL;
727		goto fail_get_res;
728	}
729	BCM5301X_MSG_INFO("irqno %d fast %d", irq, fast);
730
731	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
732	if (pdata == NULL) {
733		BCM5301X_MSG_ERR("failed to allocate data");
734		rc = -ENOMEM;
735		goto fail_alloc;
736	}
737	pdata->irq = irq;
738	pdata->fast = fast;
739	init_completion(&pdata->done);
740	adap = &pdata->adap;
741	snprintf(adap->name, sizeof(adap->name), BCM5301X_CFG_DRV_NAME);
742	adap->algo = &bcm5301x_algorithm;
743	adap->algo_data = pdata;
744	adap->dev.parent = &pdev->dev;
745	adap->nr = pdev->id;
746	platform_set_drvdata(pdev, pdata);
747
748	rc = bcm5301x_hwinit(pdata);
749	if (rc) {
750		BCM5301X_MSG_ERR("hw init failed");
751		goto fail_hwinit;
752	}
753
754	rc = request_irq(irq, bcm5301x_i2c_irq, 0, BCM5301X_CFG_DRV_NAME, pdata);
755	if (rc) {
756		BCM5301X_MSG_ERR("failed to request irqno %d", irq);
757		goto fail_request_irq;
758	}
759
760	rc = i2c_add_numbered_adapter(adap);
761	if (rc) {
762		BCM5301X_MSG_ERR("adapter registration failed");
763		goto fail_add_adapter;
764	}
765
766	rc = bcm5301x_bb_init(pdev, pdata);
767	if (rc) {
768		BCM5301X_MSG_ERR("bb init failed");
769		goto fail_bb_init;
770	}
771
772	printk(KERN_INFO"%s : adapter %d created\n", BCM5301X_CFG_DRV_NAME, adap->id);
773
774	return 0;
775
776fail_bb_init:
777	i2c_del_adapter(adap);
778fail_add_adapter:
779	free_irq(irq, pdata);
780fail_request_irq:
781fail_hwinit:
782	platform_set_drvdata(pdev, NULL);
783	kfree(pdata);
784fail_alloc:
785fail_get_res:
786	return rc;
787}
788
789static int __devexit bcm5301x_i2c_remove(struct platform_device *pdev)
790{
791	struct bcm5301x_i2c_data *pdata = platform_get_drvdata(pdev);
792
793	BCM5301X_MSG_INFO("remove");
794
795	i2c_del_adapter(&pdata->adap);
796	i2c_del_adapter(&pdata->bb_adap);
797
798	bcm5301x_reset(pdata);
799
800	free_irq(pdata->irq, pdata);
801
802	platform_set_drvdata(pdev, NULL);
803	kfree(pdata);
804
805	return 0;
806}
807
808static struct platform_driver bcm5301x_i2c_driver = {
809	.probe		= bcm5301x_i2c_probe,
810	.remove		= __devexit_p(bcm5301x_i2c_remove),
811	.driver		= {
812		.name	= BCM5301X_CFG_DRV_NAME,
813		.owner	= THIS_MODULE,
814	},
815};
816
817static int __init bcm5301x_i2c_init(void)
818{
819	return platform_driver_register(&bcm5301x_i2c_driver);
820}
821
822static void __exit bcm5301x_i2c_exit(void)
823{
824	platform_driver_unregister(&bcm5301x_i2c_driver);
825}
826
827module_init(bcm5301x_i2c_init);
828module_exit(bcm5301x_i2c_exit);
829