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