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