xref: /arm-trusted-firmware/drivers/brcm/i2c/i2c.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2016 - 2021, Broadcom
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <common/debug.h>
8*91f16700Schasinglulu #include <drivers/delay_timer.h>
9*91f16700Schasinglulu #include <i2c.h>
10*91f16700Schasinglulu #include <i2c_regs.h>
11*91f16700Schasinglulu #include <lib/mmio.h>
12*91f16700Schasinglulu 
13*91f16700Schasinglulu #include <platform_def.h>
14*91f16700Schasinglulu 
15*91f16700Schasinglulu /* Max instances */
16*91f16700Schasinglulu #define MAX_I2C					2U
17*91f16700Schasinglulu 
18*91f16700Schasinglulu /* Transaction error codes defined in Master command register (0x30) */
19*91f16700Schasinglulu #define MSTR_STS_XACT_SUCCESS			0U
20*91f16700Schasinglulu #define MSTR_STS_LOST_ARB			1U
21*91f16700Schasinglulu #define MSTR_STS_NACK_FIRST_BYTE		2U
22*91f16700Schasinglulu  /* NACK on a byte other than the first byte */
23*91f16700Schasinglulu #define MSTR_STS_NACK_NON_FIRST_BYTE		3U
24*91f16700Schasinglulu 
25*91f16700Schasinglulu #define MSTR_STS_TTIMEOUT_EXCEEDED		4U
26*91f16700Schasinglulu #define MSTR_STS_TX_TLOW_MEXT_EXCEEDED		5U
27*91f16700Schasinglulu #define MSTR_STS_RX_TLOW_MEXT_EXCEEDED		6U
28*91f16700Schasinglulu 
29*91f16700Schasinglulu /* SMBUS protocol values defined in register 0x30 */
30*91f16700Schasinglulu #define SMBUS_PROT_QUICK_CMD			0U
31*91f16700Schasinglulu #define SMBUS_PROT_SEND_BYTE			1U
32*91f16700Schasinglulu #define SMBUS_PROT_RECV_BYTE			2U
33*91f16700Schasinglulu #define SMBUS_PROT_WR_BYTE			3U
34*91f16700Schasinglulu #define SMBUS_PROT_RD_BYTE			4U
35*91f16700Schasinglulu #define SMBUS_PROT_WR_WORD			5U
36*91f16700Schasinglulu #define SMBUS_PROT_RD_WORD			6U
37*91f16700Schasinglulu #define SMBUS_PROT_BLK_WR			7U
38*91f16700Schasinglulu #define SMBUS_PROT_BLK_RD			8U
39*91f16700Schasinglulu #define SMBUS_PROT_PROC_CALL			9U
40*91f16700Schasinglulu #define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL	10U
41*91f16700Schasinglulu 
42*91f16700Schasinglulu /* Number can be changed later */
43*91f16700Schasinglulu #define BUS_BUSY_COUNT				100000U
44*91f16700Schasinglulu 
45*91f16700Schasinglulu #define IPROC_I2C_INVALID_ADDR			0xFFU
46*91f16700Schasinglulu 
47*91f16700Schasinglulu #define I2C_SMBUS_BLOCK_MAX			32U
48*91f16700Schasinglulu 
49*91f16700Schasinglulu /*
50*91f16700Schasinglulu  * Enum to specify clock speed. The user will provide it during initialization.
51*91f16700Schasinglulu  * If needed, it can be changed dynamically
52*91f16700Schasinglulu  */
53*91f16700Schasinglulu typedef enum iproc_smb_clk_freq {
54*91f16700Schasinglulu 	IPROC_SMB_SPEED_100KHz = 0,
55*91f16700Schasinglulu 	IPROC_SMB_SPEED_400KHz = 1,
56*91f16700Schasinglulu 	IPROC_SMB_SPEED_INVALID = 255
57*91f16700Schasinglulu } smb_clk_freq_t;
58*91f16700Schasinglulu 
59*91f16700Schasinglulu /* Structure used to pass information to read/write functions. */
60*91f16700Schasinglulu struct iproc_xact_info {
61*91f16700Schasinglulu 	/* Bus Identifier */
62*91f16700Schasinglulu 	uint32_t bus_id;
63*91f16700Schasinglulu 	/* Device Address */
64*91f16700Schasinglulu 	uint8_t devaddr;
65*91f16700Schasinglulu 	/* Passed by caller to send SMBus command cod e*/
66*91f16700Schasinglulu 	uint8_t command;
67*91f16700Schasinglulu 	/* actual data passed by the caller */
68*91f16700Schasinglulu 	uint8_t *data;
69*91f16700Schasinglulu 	/* Size of data buffer passed */
70*91f16700Schasinglulu 	uint32_t size;
71*91f16700Schasinglulu 	/* Sent by caller specifying PEC, 10-bit addresses */
72*91f16700Schasinglulu 	uint16_t flags;
73*91f16700Schasinglulu 	/* SMBus protocol to use to perform transaction */
74*91f16700Schasinglulu 	uint8_t smb_proto;
75*91f16700Schasinglulu 	/* true if command field below is valid. Otherwise, false */
76*91f16700Schasinglulu 	uint32_t cmd_valid;
77*91f16700Schasinglulu };
78*91f16700Schasinglulu 
79*91f16700Schasinglulu static const uintptr_t smbus_base_reg_addr[MAX_I2C] = {
80*91f16700Schasinglulu 	SMBUS0_REGS_BASE,
81*91f16700Schasinglulu 	SMBUS1_REGS_BASE
82*91f16700Schasinglulu };
83*91f16700Schasinglulu 
84*91f16700Schasinglulu /* Function to read a value from specified register. */
85*91f16700Schasinglulu static uint32_t iproc_i2c_reg_read(uint32_t bus_id, unsigned long reg_addr)
86*91f16700Schasinglulu {
87*91f16700Schasinglulu 	uint32_t val;
88*91f16700Schasinglulu 	uintptr_t smbus;
89*91f16700Schasinglulu 
90*91f16700Schasinglulu 	smbus = smbus_base_reg_addr[bus_id];
91*91f16700Schasinglulu 
92*91f16700Schasinglulu 	val = mmio_read_32(smbus + reg_addr);
93*91f16700Schasinglulu 	VERBOSE("i2c %u: reg %p read 0x%x\n", bus_id,
94*91f16700Schasinglulu 		(void *)(smbus + reg_addr), val);
95*91f16700Schasinglulu 	return val;
96*91f16700Schasinglulu }
97*91f16700Schasinglulu 
98*91f16700Schasinglulu /* Function to write a value ('val') in to a specified register. */
99*91f16700Schasinglulu static void iproc_i2c_reg_write(uint32_t bus_id,
100*91f16700Schasinglulu 				unsigned long reg_addr,
101*91f16700Schasinglulu 				uint32_t val)
102*91f16700Schasinglulu {
103*91f16700Schasinglulu 	uintptr_t smbus;
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 	smbus = smbus_base_reg_addr[bus_id];
106*91f16700Schasinglulu 
107*91f16700Schasinglulu 	mmio_write_32((smbus + reg_addr), val);
108*91f16700Schasinglulu 	VERBOSE("i2c %u: reg %p wrote 0x%x\n", bus_id,
109*91f16700Schasinglulu 		(void *)(smbus + reg_addr), val);
110*91f16700Schasinglulu }
111*91f16700Schasinglulu 
112*91f16700Schasinglulu /* Function to clear and set bits in a specified register. */
113*91f16700Schasinglulu static void iproc_i2c_reg_clearset(uint32_t bus_id,
114*91f16700Schasinglulu 				   unsigned long reg_addr,
115*91f16700Schasinglulu 				   uint32_t clear,
116*91f16700Schasinglulu 				   uint32_t set)
117*91f16700Schasinglulu {
118*91f16700Schasinglulu 	uintptr_t smbus;
119*91f16700Schasinglulu 
120*91f16700Schasinglulu 	smbus = smbus_base_reg_addr[bus_id];
121*91f16700Schasinglulu 
122*91f16700Schasinglulu 	mmio_clrsetbits_32((smbus + reg_addr), clear, set);
123*91f16700Schasinglulu 	VERBOSE("i2c %u: reg %p clear 0x%x, set 0x%x\n", bus_id,
124*91f16700Schasinglulu 		(void *)(smbus + reg_addr), clear, set);
125*91f16700Schasinglulu }
126*91f16700Schasinglulu 
127*91f16700Schasinglulu /* Function to dump all SMBUS register */
128*91f16700Schasinglulu #ifdef BCM_I2C_DEBUG
129*91f16700Schasinglulu static int iproc_dump_i2c_regs(uint32_t bus_id)
130*91f16700Schasinglulu {
131*91f16700Schasinglulu 	uint32_t regval;
132*91f16700Schasinglulu 
133*91f16700Schasinglulu 	if (bus_id > MAX_I2C) {
134*91f16700Schasinglulu 		return -1;
135*91f16700Schasinglulu 	}
136*91f16700Schasinglulu 
137*91f16700Schasinglulu 	INFO("----------------------------------------------\n");
138*91f16700Schasinglulu 	INFO("%s: Dumping SMBus %u registers...\n", __func__, bus_id);
139*91f16700Schasinglulu 
140*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
141*91f16700Schasinglulu 	INFO("SMB_CFG_REG=0x%x\n", regval);
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
144*91f16700Schasinglulu 	INFO("SMB_TIMGCFG_REG=0x%x\n", regval);
145*91f16700Schasinglulu 
146*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_ADDR_REG);
147*91f16700Schasinglulu 	INFO("SMB_ADDR_REG=0x%x\n", regval);
148*91f16700Schasinglulu 
149*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRFIFOCTL_REG);
150*91f16700Schasinglulu 	INFO("SMB_MSTRFIFOCTL_REG=0x%x\n", regval);
151*91f16700Schasinglulu 
152*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVFIFOCTL_REG);
153*91f16700Schasinglulu 	INFO("SMB_SLVFIFOCTL_REG=0x%x\n", regval);
154*91f16700Schasinglulu 
155*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_BITBANGCTL_REG);
156*91f16700Schasinglulu 	INFO("SMB_BITBANGCTL_REG=0x%x\n", regval);
157*91f16700Schasinglulu 
158*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
159*91f16700Schasinglulu 	INFO("SMB_MSTRCMD_REG=0x%x\n", regval);
160*91f16700Schasinglulu 
161*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVCMD_REG);
162*91f16700Schasinglulu 	INFO("SMB_SLVCMD_REG=0x%x\n", regval);
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTEN_REG);
165*91f16700Schasinglulu 	INFO("SMB_EVTEN_REG=0x%x\n", regval);
166*91f16700Schasinglulu 
167*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
168*91f16700Schasinglulu 	INFO("SMB_EVTSTS_REG=0x%x\n", regval);
169*91f16700Schasinglulu 
170*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATAWR_REG);
171*91f16700Schasinglulu 	INFO("SMB_MSTRDATAWR_REG=0x%x\n", regval);
172*91f16700Schasinglulu 
173*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATARD_REG);
174*91f16700Schasinglulu 	INFO("SMB_MSTRDATARD_REG=0x%x\n", regval);
175*91f16700Schasinglulu 
176*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATAWR_REG);
177*91f16700Schasinglulu 	INFO("SMB_SLVDATAWR_REG=0x%x\n", regval);
178*91f16700Schasinglulu 
179*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATARD_REG);
180*91f16700Schasinglulu 	INFO("SMB_SLVDATARD_REG=0x%x\n", regval);
181*91f16700Schasinglulu 
182*91f16700Schasinglulu 	INFO("----------------------------------------------\n");
183*91f16700Schasinglulu 	return 0;
184*91f16700Schasinglulu }
185*91f16700Schasinglulu #endif
186*91f16700Schasinglulu 
187*91f16700Schasinglulu /*
188*91f16700Schasinglulu  * Function to ensure that the previous transaction was completed before
189*91f16700Schasinglulu  * initiating a new transaction. It can also be used in polling mode to
190*91f16700Schasinglulu  * check status of completion of a command
191*91f16700Schasinglulu  */
192*91f16700Schasinglulu static int iproc_i2c_startbusy_wait(uint32_t bus_id)
193*91f16700Schasinglulu {
194*91f16700Schasinglulu 	uint32_t regval;
195*91f16700Schasinglulu 	uint32_t retry = 0U;
196*91f16700Schasinglulu 
197*91f16700Schasinglulu 	/*
198*91f16700Schasinglulu 	 * Check if an operation is in progress. During probe it won't be.
199*91f16700Schasinglulu 	 * Want to make sure that the transaction in progress is completed.
200*91f16700Schasinglulu 	 */
201*91f16700Schasinglulu 	do {
202*91f16700Schasinglulu 		udelay(1U);
203*91f16700Schasinglulu 		regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
204*91f16700Schasinglulu 		regval &= SMB_MSTRSTARTBUSYCMD_MASK;
205*91f16700Schasinglulu 		if (retry++ > BUS_BUSY_COUNT) {
206*91f16700Schasinglulu 			ERROR("%s: START_BUSY bit didn't clear, exiting\n",
207*91f16700Schasinglulu 			      __func__);
208*91f16700Schasinglulu 			return -1;
209*91f16700Schasinglulu 		}
210*91f16700Schasinglulu 
211*91f16700Schasinglulu 	} while (regval != 0U);
212*91f16700Schasinglulu 
213*91f16700Schasinglulu 	return 0;
214*91f16700Schasinglulu }
215*91f16700Schasinglulu 
216*91f16700Schasinglulu /*
217*91f16700Schasinglulu  * This function copies data to SMBus's Tx FIFO. Valid for write transactions
218*91f16700Schasinglulu  * info: Data to copy in to Tx FIFO. For read commands, the size should be
219*91f16700Schasinglulu  * set to zero by the caller
220*91f16700Schasinglulu  */
221*91f16700Schasinglulu static void iproc_i2c_write_trans_data(struct iproc_xact_info *info)
222*91f16700Schasinglulu {
223*91f16700Schasinglulu 	uint32_t regval;
224*91f16700Schasinglulu 	uint8_t devaddr;
225*91f16700Schasinglulu 	uint32_t i;
226*91f16700Schasinglulu 	uint32_t num_data_bytes = 0U;
227*91f16700Schasinglulu 
228*91f16700Schasinglulu #ifdef BCM_I2C_DEBUG
229*91f16700Schasinglulu 	INFO("%s:dev_addr=0x%x,cmd_valid=%d, cmd=0x%x, size=%u proto=%d\n",
230*91f16700Schasinglulu 	     __func__, info->devaddr, info->cmd_valid, info->command,
231*91f16700Schasinglulu 	     info->size, info->smb_proto);
232*91f16700Schasinglulu #endif
233*91f16700Schasinglulu 	/* Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n */
234*91f16700Schasinglulu 	devaddr = (info->devaddr << 1);
235*91f16700Schasinglulu 
236*91f16700Schasinglulu 	/*
237*91f16700Schasinglulu 	 * Depending on the SMBus protocol, we need to write additional
238*91f16700Schasinglulu 	 * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus spec
239*91f16700Schasinglulu 	 * for sequence for a transaction
240*91f16700Schasinglulu 	 */
241*91f16700Schasinglulu 	switch (info->smb_proto) {
242*91f16700Schasinglulu 	case SMBUS_PROT_RECV_BYTE:
243*91f16700Schasinglulu 		/* No additional data to be written */
244*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
245*91f16700Schasinglulu 				    devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
246*91f16700Schasinglulu 		break;
247*91f16700Schasinglulu 	case SMBUS_PROT_SEND_BYTE:
248*91f16700Schasinglulu 		num_data_bytes = info->size;
249*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
250*91f16700Schasinglulu 				    devaddr);
251*91f16700Schasinglulu 		break;
252*91f16700Schasinglulu 	case SMBUS_PROT_RD_BYTE:
253*91f16700Schasinglulu 	case SMBUS_PROT_RD_WORD:
254*91f16700Schasinglulu 	case SMBUS_PROT_BLK_RD:
255*91f16700Schasinglulu 		/* Write slave address with R/W~ set (bit #0) */
256*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
257*91f16700Schasinglulu 				    devaddr | 0x1U);
258*91f16700Schasinglulu 		break;
259*91f16700Schasinglulu 	case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL:
260*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
261*91f16700Schasinglulu 				    devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
262*91f16700Schasinglulu 		break;
263*91f16700Schasinglulu 	case SMBUS_PROT_WR_BYTE:
264*91f16700Schasinglulu 	case SMBUS_PROT_WR_WORD:
265*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
266*91f16700Schasinglulu 				    devaddr);
267*91f16700Schasinglulu 		/*
268*91f16700Schasinglulu 		 * No additional bytes to be written. Data portion is written
269*91f16700Schasinglulu 		 * in the 'for' loop below
270*91f16700Schasinglulu 		 */
271*91f16700Schasinglulu 		num_data_bytes = info->size;
272*91f16700Schasinglulu 		break;
273*91f16700Schasinglulu 	case SMBUS_PROT_BLK_WR:
274*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
275*91f16700Schasinglulu 				    devaddr);
276*91f16700Schasinglulu 		/* 3rd byte is byte count */
277*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
278*91f16700Schasinglulu 				    info->size);
279*91f16700Schasinglulu 		num_data_bytes = info->size;
280*91f16700Schasinglulu 		break;
281*91f16700Schasinglulu 	default:
282*91f16700Schasinglulu 		return;
283*91f16700Schasinglulu 	}
284*91f16700Schasinglulu 
285*91f16700Schasinglulu 	/* If the protocol needs command code, copy it */
286*91f16700Schasinglulu 	if (info->cmd_valid) {
287*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
288*91f16700Schasinglulu 				    info->command);
289*91f16700Schasinglulu 	}
290*91f16700Schasinglulu 
291*91f16700Schasinglulu 	/*
292*91f16700Schasinglulu 	 * Copy actual data from caller. In general, for reads,
293*91f16700Schasinglulu 	 * no data is copied.
294*91f16700Schasinglulu 	 */
295*91f16700Schasinglulu 	for (i = 0U; num_data_bytes; --num_data_bytes, i++) {
296*91f16700Schasinglulu 		/* For the last byte, set MASTER_WR_STATUS bit */
297*91f16700Schasinglulu 		regval = (num_data_bytes == 1U) ?
298*91f16700Schasinglulu 			 info->data[i] | SMB_MSTRWRSTS_MASK : info->data[i];
299*91f16700Schasinglulu 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
300*91f16700Schasinglulu 				    regval);
301*91f16700Schasinglulu 	}
302*91f16700Schasinglulu }
303*91f16700Schasinglulu 
304*91f16700Schasinglulu /*
305*91f16700Schasinglulu  * This function writes to the master command register and
306*91f16700Schasinglulu  * then polls for completion
307*91f16700Schasinglulu  */
308*91f16700Schasinglulu static int iproc_i2c_write_master_command(uint32_t mastercmd,
309*91f16700Schasinglulu 					  struct iproc_xact_info *info)
310*91f16700Schasinglulu {
311*91f16700Schasinglulu 	uint32_t retry = 0U;
312*91f16700Schasinglulu 	uint32_t regval;
313*91f16700Schasinglulu 
314*91f16700Schasinglulu 	iproc_i2c_reg_write(info->bus_id, SMB_MSTRCMD_REG, mastercmd);
315*91f16700Schasinglulu 
316*91f16700Schasinglulu 	/* Check for Master Busy status */
317*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
318*91f16700Schasinglulu 	while ((regval & SMB_MSTRSTARTBUSYCMD_MASK) != 0U) {
319*91f16700Schasinglulu 		udelay(1U);
320*91f16700Schasinglulu 		if (retry++ > BUS_BUSY_COUNT) {
321*91f16700Schasinglulu 			ERROR("%s: START_BUSY bit didn't clear, exiting\n",
322*91f16700Schasinglulu 				__func__);
323*91f16700Schasinglulu 			return -1;
324*91f16700Schasinglulu 		}
325*91f16700Schasinglulu 		regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
326*91f16700Schasinglulu 	}
327*91f16700Schasinglulu 
328*91f16700Schasinglulu 	/* If start_busy bit cleared, check if there are any errors */
329*91f16700Schasinglulu 	if (!(regval & SMB_MSTRSTARTBUSYCMD_MASK)) {
330*91f16700Schasinglulu 		/* start_busy bit cleared, check master_status field now */
331*91f16700Schasinglulu 		regval &= SMB_MSTRSTS_MASK;
332*91f16700Schasinglulu 		regval >>= SMB_MSTRSTS_SHIFT;
333*91f16700Schasinglulu 		if (regval != MSTR_STS_XACT_SUCCESS) {
334*91f16700Schasinglulu 			/* Error We can flush Tx FIFO here */
335*91f16700Schasinglulu 			ERROR("%s: ERROR: %u exiting\n", __func__, regval);
336*91f16700Schasinglulu 			return -1;
337*91f16700Schasinglulu 		}
338*91f16700Schasinglulu 	}
339*91f16700Schasinglulu 	return 0;
340*91f16700Schasinglulu 
341*91f16700Schasinglulu }
342*91f16700Schasinglulu /* Function to initiate data send and verify completion status */
343*91f16700Schasinglulu static int iproc_i2c_data_send(struct iproc_xact_info *info)
344*91f16700Schasinglulu {
345*91f16700Schasinglulu 	int rc;
346*91f16700Schasinglulu 	uint32_t mastercmd;
347*91f16700Schasinglulu 
348*91f16700Schasinglulu 	/* Make sure the previous transaction completed */
349*91f16700Schasinglulu 	rc = iproc_i2c_startbusy_wait(info->bus_id);
350*91f16700Schasinglulu 
351*91f16700Schasinglulu 	if (rc < 0) {
352*91f16700Schasinglulu 		WARN("%s: Send: bus is busy, exiting\n", __func__);
353*91f16700Schasinglulu 		return rc;
354*91f16700Schasinglulu 	}
355*91f16700Schasinglulu 	/* Write transaction bytes to Tx FIFO */
356*91f16700Schasinglulu 	iproc_i2c_write_trans_data(info);
357*91f16700Schasinglulu 
358*91f16700Schasinglulu 	/*
359*91f16700Schasinglulu 	 * Program master command register (0x30) with protocol type and set
360*91f16700Schasinglulu 	 * start_busy_command bit to initiate the write transaction
361*91f16700Schasinglulu 	 */
362*91f16700Schasinglulu 	mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
363*91f16700Schasinglulu 	    SMB_MSTRSTARTBUSYCMD_MASK;
364*91f16700Schasinglulu 
365*91f16700Schasinglulu 	if (iproc_i2c_write_master_command(mastercmd, info)) {
366*91f16700Schasinglulu 		return -1;
367*91f16700Schasinglulu 	}
368*91f16700Schasinglulu 
369*91f16700Schasinglulu 	return 0;
370*91f16700Schasinglulu }
371*91f16700Schasinglulu 
372*91f16700Schasinglulu /*
373*91f16700Schasinglulu  * Function to initiate data receive, verify completion status,
374*91f16700Schasinglulu  * and read from SMBUS Read FIFO
375*91f16700Schasinglulu  */
376*91f16700Schasinglulu static int iproc_i2c_data_recv(struct iproc_xact_info *info,
377*91f16700Schasinglulu 			       uint32_t *num_bytes_read)
378*91f16700Schasinglulu {
379*91f16700Schasinglulu 	int rc;
380*91f16700Schasinglulu 	uint32_t mastercmd;
381*91f16700Schasinglulu 	uint32_t regval;
382*91f16700Schasinglulu 
383*91f16700Schasinglulu 	/* Make sure the previous transaction completed */
384*91f16700Schasinglulu 	rc = iproc_i2c_startbusy_wait(info->bus_id);
385*91f16700Schasinglulu 
386*91f16700Schasinglulu 	if (rc < 0) {
387*91f16700Schasinglulu 		WARN("%s: Receive: Bus is busy, exiting\n", __func__);
388*91f16700Schasinglulu 		return rc;
389*91f16700Schasinglulu 	}
390*91f16700Schasinglulu 
391*91f16700Schasinglulu 	/* Program all transaction bytes into master Tx FIFO */
392*91f16700Schasinglulu 	iproc_i2c_write_trans_data(info);
393*91f16700Schasinglulu 
394*91f16700Schasinglulu 	/*
395*91f16700Schasinglulu 	 * Program master command register (0x30) with protocol type and set
396*91f16700Schasinglulu 	 * start_busy_command bit to initiate the write transaction
397*91f16700Schasinglulu 	 */
398*91f16700Schasinglulu 	mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
399*91f16700Schasinglulu 		     SMB_MSTRSTARTBUSYCMD_MASK | info->size;
400*91f16700Schasinglulu 
401*91f16700Schasinglulu 	if (iproc_i2c_write_master_command(mastercmd, info)) {
402*91f16700Schasinglulu 		return -1;
403*91f16700Schasinglulu 	}
404*91f16700Schasinglulu 
405*91f16700Schasinglulu 	/* Read received byte(s), after TX out address etc */
406*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRDATARD_REG);
407*91f16700Schasinglulu 
408*91f16700Schasinglulu 	/* For block read, protocol (hw) returns byte count,as the first byte */
409*91f16700Schasinglulu 	if (info->smb_proto == SMBUS_PROT_BLK_RD) {
410*91f16700Schasinglulu 		uint32_t i;
411*91f16700Schasinglulu 
412*91f16700Schasinglulu 		*num_bytes_read = regval & SMB_MSTRRDDATA_MASK;
413*91f16700Schasinglulu 		/*
414*91f16700Schasinglulu 		 * Limit to reading a max of 32 bytes only; just a safeguard.
415*91f16700Schasinglulu 		 * If # bytes read is a number > 32, check transaction set up,
416*91f16700Schasinglulu 		 * and contact hw engg.
417*91f16700Schasinglulu 		 * Assumption: PEC is disabled
418*91f16700Schasinglulu 		 */
419*91f16700Schasinglulu 		for (i = 0U; (i < *num_bytes_read) &&
420*91f16700Schasinglulu 		     (i < I2C_SMBUS_BLOCK_MAX); i++) {
421*91f16700Schasinglulu 			/* Read Rx FIFO for data bytes */
422*91f16700Schasinglulu 			regval = iproc_i2c_reg_read(info->bus_id,
423*91f16700Schasinglulu 						    SMB_MSTRDATARD_REG);
424*91f16700Schasinglulu 			info->data[i] = regval & SMB_MSTRRDDATA_MASK;
425*91f16700Schasinglulu 		}
426*91f16700Schasinglulu 	} else {
427*91f16700Schasinglulu 		/* 1 Byte data */
428*91f16700Schasinglulu 		*info->data = regval & SMB_MSTRRDDATA_MASK;
429*91f16700Schasinglulu 		*num_bytes_read = 1U;
430*91f16700Schasinglulu 	}
431*91f16700Schasinglulu 
432*91f16700Schasinglulu 	return 0;
433*91f16700Schasinglulu }
434*91f16700Schasinglulu 
435*91f16700Schasinglulu /*
436*91f16700Schasinglulu  * This function set clock frequency for SMBus block. As per hardware
437*91f16700Schasinglulu  * engineering, the clock frequency can be changed dynamically.
438*91f16700Schasinglulu  */
439*91f16700Schasinglulu static int iproc_i2c_set_clk_freq(uint32_t bus_id, smb_clk_freq_t freq)
440*91f16700Schasinglulu {
441*91f16700Schasinglulu 	uint32_t val;
442*91f16700Schasinglulu 
443*91f16700Schasinglulu 	switch (freq) {
444*91f16700Schasinglulu 	case IPROC_SMB_SPEED_100KHz:
445*91f16700Schasinglulu 		val = 0U;
446*91f16700Schasinglulu 		break;
447*91f16700Schasinglulu 	case IPROC_SMB_SPEED_400KHz:
448*91f16700Schasinglulu 		val = 1U;
449*91f16700Schasinglulu 		break;
450*91f16700Schasinglulu 	default:
451*91f16700Schasinglulu 		return -1;
452*91f16700Schasinglulu 	}
453*91f16700Schasinglulu 
454*91f16700Schasinglulu 	iproc_i2c_reg_clearset(bus_id, SMB_TIMGCFG_REG,
455*91f16700Schasinglulu 			       SMB_TIMGCFG_MODE400_MASK,
456*91f16700Schasinglulu 			       val << SMB_TIMGCFG_MODE400_SHIFT);
457*91f16700Schasinglulu 
458*91f16700Schasinglulu 	return 0;
459*91f16700Schasinglulu }
460*91f16700Schasinglulu 
461*91f16700Schasinglulu /* Helper function to fill the iproc_xact_info structure */
462*91f16700Schasinglulu static void iproc_i2c_fill_info(struct iproc_xact_info *info, uint32_t bus_id,
463*91f16700Schasinglulu 				uint8_t devaddr, uint8_t cmd, uint8_t *value,
464*91f16700Schasinglulu 				uint8_t smb_proto, uint32_t cmd_valid)
465*91f16700Schasinglulu {
466*91f16700Schasinglulu 	info->bus_id = bus_id;
467*91f16700Schasinglulu 	info->devaddr = devaddr;
468*91f16700Schasinglulu 	info->command = (uint8_t)cmd;
469*91f16700Schasinglulu 	info->smb_proto = smb_proto;
470*91f16700Schasinglulu 	info->data = value;
471*91f16700Schasinglulu 	info->size = 1U;
472*91f16700Schasinglulu 	info->flags = 0U;
473*91f16700Schasinglulu 	info->cmd_valid = cmd_valid;
474*91f16700Schasinglulu }
475*91f16700Schasinglulu 
476*91f16700Schasinglulu /* This function initializes the SMBUS */
477*91f16700Schasinglulu static void iproc_i2c_init(uint32_t bus_id, int speed)
478*91f16700Schasinglulu {
479*91f16700Schasinglulu 	uint32_t regval;
480*91f16700Schasinglulu 
481*91f16700Schasinglulu #ifdef BCM_I2C_DEBUG
482*91f16700Schasinglulu 	INFO("%s: Enter Init\n", __func__);
483*91f16700Schasinglulu #endif
484*91f16700Schasinglulu 
485*91f16700Schasinglulu 	/* Put controller in reset */
486*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
487*91f16700Schasinglulu 	regval |= BIT(SMB_CFG_RST_SHIFT);
488*91f16700Schasinglulu 	regval &= ~(BIT(SMB_CFG_SMBEN_SHIFT));
489*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
490*91f16700Schasinglulu 
491*91f16700Schasinglulu 	/* Wait 100 usec per spec */
492*91f16700Schasinglulu 	udelay(100U);
493*91f16700Schasinglulu 
494*91f16700Schasinglulu 	/* Bring controller out of reset */
495*91f16700Schasinglulu 	regval &= ~(BIT(SMB_CFG_RST_SHIFT));
496*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
497*91f16700Schasinglulu 
498*91f16700Schasinglulu 	/*
499*91f16700Schasinglulu 	 * Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0.
500*91f16700Schasinglulu 	 * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts
501*91f16700Schasinglulu 	 */
502*91f16700Schasinglulu 	regval = SMB_MSTRRXFIFOFLSH_MASK | SMB_MSTRTXFIFOFLSH_MASK;
503*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_MSTRFIFOCTL_REG, regval);
504*91f16700Schasinglulu 
505*91f16700Schasinglulu 	/*
506*91f16700Schasinglulu 	 * Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero
507*91f16700Schasinglulu 	 * since there will be only one master
508*91f16700Schasinglulu 	 */
509*91f16700Schasinglulu 
510*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
511*91f16700Schasinglulu 	regval |= SMB_CFG_SMBEN_MASK;
512*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
513*91f16700Schasinglulu 	/* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */
514*91f16700Schasinglulu 	mdelay(10U);
515*91f16700Schasinglulu 
516*91f16700Schasinglulu 	/* If error then set default speed */
517*91f16700Schasinglulu 	if (i2c_set_bus_speed(bus_id, speed)) {
518*91f16700Schasinglulu 		i2c_set_bus_speed(bus_id, I2C_SPEED_DEFAULT);
519*91f16700Schasinglulu 	}
520*91f16700Schasinglulu 
521*91f16700Schasinglulu 	/* Disable intrs */
522*91f16700Schasinglulu 	regval = 0x0U;
523*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_EVTEN_REG, regval);
524*91f16700Schasinglulu 
525*91f16700Schasinglulu 	/* Clear intrs (W1TC) */
526*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
527*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_EVTSTS_REG, regval);
528*91f16700Schasinglulu 
529*91f16700Schasinglulu #ifdef BCM_I2C_DEBUG
530*91f16700Schasinglulu 	iproc_dump_i2c_regs(bus_id);
531*91f16700Schasinglulu 
532*91f16700Schasinglulu 	INFO("%s: Exit Init Successfully\n", __func__);
533*91f16700Schasinglulu #endif
534*91f16700Schasinglulu }
535*91f16700Schasinglulu 
536*91f16700Schasinglulu /*
537*91f16700Schasinglulu  * Function Name:    i2c_init
538*91f16700Schasinglulu  *
539*91f16700Schasinglulu  * Description:
540*91f16700Schasinglulu  *	This function initializes the SMBUS.
541*91f16700Schasinglulu  *
542*91f16700Schasinglulu  * Parameters:
543*91f16700Schasinglulu  *	bus_id - I2C bus ID
544*91f16700Schasinglulu  *	speed  - I2C bus speed in Hz
545*91f16700Schasinglulu  *
546*91f16700Schasinglulu  * Return:
547*91f16700Schasinglulu  *	0 on success, or -1 on failure.
548*91f16700Schasinglulu  */
549*91f16700Schasinglulu int i2c_init(uint32_t bus_id, int speed)
550*91f16700Schasinglulu {
551*91f16700Schasinglulu 	if (bus_id > MAX_I2C) {
552*91f16700Schasinglulu 		WARN("%s: Invalid Bus %u\n", __func__, bus_id);
553*91f16700Schasinglulu 		return -1;
554*91f16700Schasinglulu 	}
555*91f16700Schasinglulu 
556*91f16700Schasinglulu 	iproc_i2c_init(bus_id, speed);
557*91f16700Schasinglulu 	return 0U;
558*91f16700Schasinglulu }
559*91f16700Schasinglulu 
560*91f16700Schasinglulu /*
561*91f16700Schasinglulu  * Function Name:    i2c_probe
562*91f16700Schasinglulu  *
563*91f16700Schasinglulu  * Description:
564*91f16700Schasinglulu  *	This function probes the I2C bus for the existence of the specified
565*91f16700Schasinglulu  *	device.
566*91f16700Schasinglulu  *
567*91f16700Schasinglulu  * Parameters:
568*91f16700Schasinglulu  *	bus_id  - I2C bus ID
569*91f16700Schasinglulu  *	devaddr - Device Address
570*91f16700Schasinglulu  *
571*91f16700Schasinglulu  * Return:
572*91f16700Schasinglulu  *	0 on success, or -1 on failure.
573*91f16700Schasinglulu  */
574*91f16700Schasinglulu int i2c_probe(uint32_t bus_id, uint8_t devaddr)
575*91f16700Schasinglulu {
576*91f16700Schasinglulu 	uint32_t regval;
577*91f16700Schasinglulu 	int rc;
578*91f16700Schasinglulu 
579*91f16700Schasinglulu 	/*
580*91f16700Schasinglulu 	 * i2c_init() Initializes internal regs, disable intrs (and then clear intrs),
581*91f16700Schasinglulu 	 * set fifo thresholds, etc.
582*91f16700Schasinglulu 	 * Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n
583*91f16700Schasinglulu 	 */
584*91f16700Schasinglulu 	regval = (devaddr << 1U);
585*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_MSTRDATAWR_REG, regval);
586*91f16700Schasinglulu 
587*91f16700Schasinglulu 	regval = ((SMBUS_PROT_QUICK_CMD << SMB_MSTRSMBUSPROTO_SHIFT) |
588*91f16700Schasinglulu 		  SMB_MSTRSTARTBUSYCMD_MASK);
589*91f16700Schasinglulu 	iproc_i2c_reg_write(bus_id, SMB_MSTRCMD_REG, regval);
590*91f16700Schasinglulu 
591*91f16700Schasinglulu 	rc = iproc_i2c_startbusy_wait(bus_id);
592*91f16700Schasinglulu 
593*91f16700Schasinglulu 	if (rc < 0) {
594*91f16700Schasinglulu 		WARN("%s: Probe: bus is busy, exiting\n", __func__);
595*91f16700Schasinglulu 		return rc;
596*91f16700Schasinglulu 	}
597*91f16700Schasinglulu 
598*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
599*91f16700Schasinglulu 	if (((regval & SMB_MSTRSTS_MASK) >> SMB_MSTRSTS_SHIFT) == 0)
600*91f16700Schasinglulu 		VERBOSE("i2c device address: 0x%x\n", devaddr);
601*91f16700Schasinglulu 	else
602*91f16700Schasinglulu 		return -1;
603*91f16700Schasinglulu 
604*91f16700Schasinglulu #ifdef BCM_I2C_DEBUG
605*91f16700Schasinglulu 	iproc_dump_i2c_regs(bus_id);
606*91f16700Schasinglulu #endif
607*91f16700Schasinglulu 	return 0;
608*91f16700Schasinglulu }
609*91f16700Schasinglulu 
610*91f16700Schasinglulu /*
611*91f16700Schasinglulu  * Function Name:    i2c_recv_byte
612*91f16700Schasinglulu  *
613*91f16700Schasinglulu  * Description:
614*91f16700Schasinglulu  *	This function reads I2C data from a device without specifying
615*91f16700Schasinglulu  *	a command register.
616*91f16700Schasinglulu  *
617*91f16700Schasinglulu  * Parameters:
618*91f16700Schasinglulu  *	bus_id  - I2C bus ID
619*91f16700Schasinglulu  *	devaddr - Device Address
620*91f16700Schasinglulu  *	value   - Data Read
621*91f16700Schasinglulu  *
622*91f16700Schasinglulu  * Return:
623*91f16700Schasinglulu  *	0 on success, or -1 on failure.
624*91f16700Schasinglulu  */
625*91f16700Schasinglulu int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value)
626*91f16700Schasinglulu {
627*91f16700Schasinglulu 	int rc;
628*91f16700Schasinglulu 	struct iproc_xact_info info;
629*91f16700Schasinglulu 	uint32_t num_bytes_read = 0;
630*91f16700Schasinglulu 
631*91f16700Schasinglulu 	iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, value,
632*91f16700Schasinglulu 			    SMBUS_PROT_RECV_BYTE, 0U);
633*91f16700Schasinglulu 
634*91f16700Schasinglulu 	/* Refer to i2c_smbus_read_byte for params passed. */
635*91f16700Schasinglulu 	rc = iproc_i2c_data_recv(&info, &num_bytes_read);
636*91f16700Schasinglulu 
637*91f16700Schasinglulu 	if (rc < 0) {
638*91f16700Schasinglulu 		printf("%s: %s error accessing device 0x%x\n",
639*91f16700Schasinglulu 		__func__, "Read", devaddr);
640*91f16700Schasinglulu 	}
641*91f16700Schasinglulu 
642*91f16700Schasinglulu 	return rc;
643*91f16700Schasinglulu }
644*91f16700Schasinglulu 
645*91f16700Schasinglulu /*
646*91f16700Schasinglulu  * Function Name:    i2c_send_byte
647*91f16700Schasinglulu  *
648*91f16700Schasinglulu  * Description:
649*91f16700Schasinglulu  *	This function send I2C data to a device without specifying
650*91f16700Schasinglulu  *	a command register.
651*91f16700Schasinglulu  *
652*91f16700Schasinglulu  * Parameters:
653*91f16700Schasinglulu  *	bus_id  - I2C bus ID
654*91f16700Schasinglulu  *	devaddr - Device Address
655*91f16700Schasinglulu  *	value   - Data Send
656*91f16700Schasinglulu  *
657*91f16700Schasinglulu  * Return:
658*91f16700Schasinglulu  *	0 on success, or -1 on failure.
659*91f16700Schasinglulu  */
660*91f16700Schasinglulu int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value)
661*91f16700Schasinglulu {
662*91f16700Schasinglulu 	int rc;
663*91f16700Schasinglulu 	struct iproc_xact_info info;
664*91f16700Schasinglulu 
665*91f16700Schasinglulu 	iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, &value,
666*91f16700Schasinglulu 			    SMBUS_PROT_SEND_BYTE, 0U);
667*91f16700Schasinglulu 
668*91f16700Schasinglulu 	/* Refer to i2c_smbus_write_byte params passed. */
669*91f16700Schasinglulu 	rc = iproc_i2c_data_send(&info);
670*91f16700Schasinglulu 
671*91f16700Schasinglulu 	if (rc < 0) {
672*91f16700Schasinglulu 		ERROR("%s: %s error accessing device 0x%x\n",
673*91f16700Schasinglulu 		__func__, "Write", devaddr);
674*91f16700Schasinglulu 	}
675*91f16700Schasinglulu 
676*91f16700Schasinglulu 	return rc;
677*91f16700Schasinglulu }
678*91f16700Schasinglulu 
679*91f16700Schasinglulu /* Helper function to read a single byte */
680*91f16700Schasinglulu static int i2c_read_byte(uint32_t bus_id,
681*91f16700Schasinglulu 			 uint8_t devaddr,
682*91f16700Schasinglulu 			 uint8_t regoffset,
683*91f16700Schasinglulu 			 uint8_t *value)
684*91f16700Schasinglulu {
685*91f16700Schasinglulu 	int rc;
686*91f16700Schasinglulu 	struct iproc_xact_info info;
687*91f16700Schasinglulu 	uint32_t num_bytes_read = 0U;
688*91f16700Schasinglulu 
689*91f16700Schasinglulu 	iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, value,
690*91f16700Schasinglulu 			    SMBUS_PROT_RD_BYTE, 1U);
691*91f16700Schasinglulu 
692*91f16700Schasinglulu 	/* Refer to i2c_smbus_read_byte for params passed. */
693*91f16700Schasinglulu 	rc = iproc_i2c_data_recv(&info, &num_bytes_read);
694*91f16700Schasinglulu 
695*91f16700Schasinglulu 	if (rc < 0) {
696*91f16700Schasinglulu 		ERROR("%s: %s error accessing device 0x%x\n",
697*91f16700Schasinglulu 		       __func__, "Read", devaddr);
698*91f16700Schasinglulu 	}
699*91f16700Schasinglulu 	return rc;
700*91f16700Schasinglulu }
701*91f16700Schasinglulu 
702*91f16700Schasinglulu /*
703*91f16700Schasinglulu  * Function Name:    i2c_read
704*91f16700Schasinglulu  *
705*91f16700Schasinglulu  * Description:
706*91f16700Schasinglulu  *	This function reads I2C data from a device with a designated
707*91f16700Schasinglulu  *	command register
708*91f16700Schasinglulu  *
709*91f16700Schasinglulu  * Parameters:
710*91f16700Schasinglulu  *	bus_id  - I2C bus ID
711*91f16700Schasinglulu  *	devaddr - Device Address
712*91f16700Schasinglulu  *	addr    - Register Offset
713*91f16700Schasinglulu  *	alen    - Address Length, 1 for byte, 2 for word (not supported)
714*91f16700Schasinglulu  *	buffer  - Data Buffer
715*91f16700Schasinglulu  *	len     - Data Length in bytes
716*91f16700Schasinglulu  *
717*91f16700Schasinglulu  * Return:
718*91f16700Schasinglulu  *	0 on success, or -1 on failure.
719*91f16700Schasinglulu  */
720*91f16700Schasinglulu int i2c_read(uint32_t bus_id,
721*91f16700Schasinglulu 	     uint8_t devaddr,
722*91f16700Schasinglulu 	     uint32_t addr,
723*91f16700Schasinglulu 	     int alen,
724*91f16700Schasinglulu 	     uint8_t *buffer,
725*91f16700Schasinglulu 	     int len)
726*91f16700Schasinglulu {
727*91f16700Schasinglulu 	uint32_t i;
728*91f16700Schasinglulu 
729*91f16700Schasinglulu 	if (alen > 1) {
730*91f16700Schasinglulu 		WARN("I2C read: addr len %d not supported\n", alen);
731*91f16700Schasinglulu 		return -1;
732*91f16700Schasinglulu 	}
733*91f16700Schasinglulu 
734*91f16700Schasinglulu 	if (addr + len > 256) {
735*91f16700Schasinglulu 		WARN("I2C read: address out of range\n");
736*91f16700Schasinglulu 		return -1;
737*91f16700Schasinglulu 	}
738*91f16700Schasinglulu 
739*91f16700Schasinglulu 	for (i = 0U; i < len; i++) {
740*91f16700Schasinglulu 		if (i2c_read_byte(bus_id, devaddr, addr + i, &buffer[i])) {
741*91f16700Schasinglulu 			ERROR("I2C read: I/O error\n");
742*91f16700Schasinglulu 			iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
743*91f16700Schasinglulu 			return -1;
744*91f16700Schasinglulu 		}
745*91f16700Schasinglulu 	}
746*91f16700Schasinglulu 
747*91f16700Schasinglulu 	return 0;
748*91f16700Schasinglulu }
749*91f16700Schasinglulu 
750*91f16700Schasinglulu /* Helper function to write a single byte */
751*91f16700Schasinglulu static int i2c_write_byte(uint32_t bus_id,
752*91f16700Schasinglulu 			  uint8_t devaddr,
753*91f16700Schasinglulu 			  uint8_t regoffset,
754*91f16700Schasinglulu 			  uint8_t value)
755*91f16700Schasinglulu {
756*91f16700Schasinglulu 	int rc;
757*91f16700Schasinglulu 	struct iproc_xact_info info;
758*91f16700Schasinglulu 
759*91f16700Schasinglulu 	iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, &value,
760*91f16700Schasinglulu 			    SMBUS_PROT_WR_BYTE, 1U);
761*91f16700Schasinglulu 
762*91f16700Schasinglulu 	/* Refer to i2c_smbus_write_byte params passed. */
763*91f16700Schasinglulu 	rc = iproc_i2c_data_send(&info);
764*91f16700Schasinglulu 
765*91f16700Schasinglulu 	if (rc < 0) {
766*91f16700Schasinglulu 		ERROR("%s: %s error accessing device 0x%x\n",
767*91f16700Schasinglulu 		       __func__, "Write", devaddr);
768*91f16700Schasinglulu 		return -1;
769*91f16700Schasinglulu 	}
770*91f16700Schasinglulu 
771*91f16700Schasinglulu 	return 0;
772*91f16700Schasinglulu }
773*91f16700Schasinglulu 
774*91f16700Schasinglulu /*
775*91f16700Schasinglulu  * Function Name:    i2c_write
776*91f16700Schasinglulu  *
777*91f16700Schasinglulu  * Description:
778*91f16700Schasinglulu  *	This function write I2C data to a device with a designated
779*91f16700Schasinglulu  *	command register
780*91f16700Schasinglulu  *
781*91f16700Schasinglulu  * Parameters:
782*91f16700Schasinglulu  *	bus_id  - I2C bus ID
783*91f16700Schasinglulu  *	devaddr - Device Address
784*91f16700Schasinglulu  *	addr    - Register Offset
785*91f16700Schasinglulu  *	alen    - Address Length, 1 for byte, 2 for word (not supported)
786*91f16700Schasinglulu  *	buffer  - Data Buffer
787*91f16700Schasinglulu  *	len     - Data Length in bytes
788*91f16700Schasinglulu  *
789*91f16700Schasinglulu  * Return:
790*91f16700Schasinglulu  *	0 on success, or -1 on failure.
791*91f16700Schasinglulu  */
792*91f16700Schasinglulu int i2c_write(uint32_t bus_id,
793*91f16700Schasinglulu 	      uint8_t devaddr,
794*91f16700Schasinglulu 	      uint32_t addr,
795*91f16700Schasinglulu 	      int alen,
796*91f16700Schasinglulu 	      uint8_t *buffer,
797*91f16700Schasinglulu 	      int len)
798*91f16700Schasinglulu {
799*91f16700Schasinglulu 	uint32_t i;
800*91f16700Schasinglulu 
801*91f16700Schasinglulu 	if (alen > 1) {
802*91f16700Schasinglulu 		WARN("I2C write: addr len %d not supported\n", alen);
803*91f16700Schasinglulu 		return -1;
804*91f16700Schasinglulu 	}
805*91f16700Schasinglulu 
806*91f16700Schasinglulu 	if (addr + len > 256U) {
807*91f16700Schasinglulu 		WARN("I2C write: address out of range\n");
808*91f16700Schasinglulu 		return -1;
809*91f16700Schasinglulu 	}
810*91f16700Schasinglulu 
811*91f16700Schasinglulu 	for (i = 0U; i < len; i++) {
812*91f16700Schasinglulu 		if (i2c_write_byte(bus_id, devaddr, addr + i, buffer[i])) {
813*91f16700Schasinglulu 			ERROR("I2C write: I/O error\n");
814*91f16700Schasinglulu 			iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
815*91f16700Schasinglulu 			return -1;
816*91f16700Schasinglulu 		}
817*91f16700Schasinglulu 	}
818*91f16700Schasinglulu 	return 0;
819*91f16700Schasinglulu }
820*91f16700Schasinglulu 
821*91f16700Schasinglulu /*
822*91f16700Schasinglulu  * Function Name:    i2c_set_bus_speed
823*91f16700Schasinglulu  *
824*91f16700Schasinglulu  * Description:
825*91f16700Schasinglulu  *	This function configures the SMBUS speed
826*91f16700Schasinglulu  *
827*91f16700Schasinglulu  * Parameters:
828*91f16700Schasinglulu  *	bus_id - I2C bus ID
829*91f16700Schasinglulu  *	speed  - I2C bus speed in Hz
830*91f16700Schasinglulu  *
831*91f16700Schasinglulu  * Return:
832*91f16700Schasinglulu  *	0 on success, or -1 on failure.
833*91f16700Schasinglulu  */
834*91f16700Schasinglulu int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed)
835*91f16700Schasinglulu {
836*91f16700Schasinglulu 	switch (speed) {
837*91f16700Schasinglulu 	case I2C_SPEED_100KHz:
838*91f16700Schasinglulu 		iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_100KHz);
839*91f16700Schasinglulu 		break;
840*91f16700Schasinglulu 
841*91f16700Schasinglulu 	case I2C_SPEED_400KHz:
842*91f16700Schasinglulu 		iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_400KHz);
843*91f16700Schasinglulu 		break;
844*91f16700Schasinglulu 
845*91f16700Schasinglulu 	default:
846*91f16700Schasinglulu 		return -1;
847*91f16700Schasinglulu 	}
848*91f16700Schasinglulu 	return 0;
849*91f16700Schasinglulu }
850*91f16700Schasinglulu 
851*91f16700Schasinglulu /*
852*91f16700Schasinglulu  * Function Name:    i2c_get_bus_speed
853*91f16700Schasinglulu  *
854*91f16700Schasinglulu  * Description:
855*91f16700Schasinglulu  *	This function returns the SMBUS speed.
856*91f16700Schasinglulu  *
857*91f16700Schasinglulu  * Parameters:
858*91f16700Schasinglulu  *	bus_id - I2C bus ID
859*91f16700Schasinglulu  *
860*91f16700Schasinglulu  * Return:
861*91f16700Schasinglulu  *	Bus speed in Hz, 0 on failure
862*91f16700Schasinglulu  */
863*91f16700Schasinglulu uint32_t i2c_get_bus_speed(uint32_t bus_id)
864*91f16700Schasinglulu {
865*91f16700Schasinglulu 	uint32_t regval;
866*91f16700Schasinglulu 	uint32_t retval = 0U;
867*91f16700Schasinglulu 
868*91f16700Schasinglulu 	regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
869*91f16700Schasinglulu 	regval &= SMB_TIMGCFG_MODE400_MASK;
870*91f16700Schasinglulu 	regval >>= SMB_TIMGCFG_MODE400_SHIFT;
871*91f16700Schasinglulu 
872*91f16700Schasinglulu 	switch (regval) {
873*91f16700Schasinglulu 	case IPROC_SMB_SPEED_100KHz:
874*91f16700Schasinglulu 		retval = I2C_SPEED_100KHz;
875*91f16700Schasinglulu 		break;
876*91f16700Schasinglulu 
877*91f16700Schasinglulu 	case IPROC_SMB_SPEED_400KHz:
878*91f16700Schasinglulu 		retval = I2C_SPEED_400KHz;
879*91f16700Schasinglulu 		break;
880*91f16700Schasinglulu 
881*91f16700Schasinglulu 	default:
882*91f16700Schasinglulu 		break;
883*91f16700Schasinglulu 	}
884*91f16700Schasinglulu 	return retval;
885*91f16700Schasinglulu }
886*91f16700Schasinglulu 
887