xref: /rk3399_ARM-atf/drivers/brcm/i2c/i2c.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
148c6a6b6SBharat Gooty /*
248c6a6b6SBharat Gooty  * Copyright (c) 2016 - 2021, Broadcom
348c6a6b6SBharat Gooty  *
448c6a6b6SBharat Gooty  * SPDX-License-Identifier: BSD-3-Clause
548c6a6b6SBharat Gooty  */
648c6a6b6SBharat Gooty 
748c6a6b6SBharat Gooty #include <common/debug.h>
848c6a6b6SBharat Gooty #include <drivers/delay_timer.h>
948c6a6b6SBharat Gooty #include <i2c.h>
1048c6a6b6SBharat Gooty #include <i2c_regs.h>
1148c6a6b6SBharat Gooty #include <lib/mmio.h>
1248c6a6b6SBharat Gooty 
1348c6a6b6SBharat Gooty #include <platform_def.h>
1448c6a6b6SBharat Gooty 
1548c6a6b6SBharat Gooty /* Max instances */
1648c6a6b6SBharat Gooty #define MAX_I2C					2U
1748c6a6b6SBharat Gooty 
1848c6a6b6SBharat Gooty /* Transaction error codes defined in Master command register (0x30) */
1948c6a6b6SBharat Gooty #define MSTR_STS_XACT_SUCCESS			0U
2048c6a6b6SBharat Gooty #define MSTR_STS_LOST_ARB			1U
2148c6a6b6SBharat Gooty #define MSTR_STS_NACK_FIRST_BYTE		2U
2248c6a6b6SBharat Gooty  /* NACK on a byte other than the first byte */
2348c6a6b6SBharat Gooty #define MSTR_STS_NACK_NON_FIRST_BYTE		3U
2448c6a6b6SBharat Gooty 
2548c6a6b6SBharat Gooty #define MSTR_STS_TTIMEOUT_EXCEEDED		4U
2648c6a6b6SBharat Gooty #define MSTR_STS_TX_TLOW_MEXT_EXCEEDED		5U
2748c6a6b6SBharat Gooty #define MSTR_STS_RX_TLOW_MEXT_EXCEEDED		6U
2848c6a6b6SBharat Gooty 
2948c6a6b6SBharat Gooty /* SMBUS protocol values defined in register 0x30 */
3048c6a6b6SBharat Gooty #define SMBUS_PROT_QUICK_CMD			0U
3148c6a6b6SBharat Gooty #define SMBUS_PROT_SEND_BYTE			1U
3248c6a6b6SBharat Gooty #define SMBUS_PROT_RECV_BYTE			2U
3348c6a6b6SBharat Gooty #define SMBUS_PROT_WR_BYTE			3U
3448c6a6b6SBharat Gooty #define SMBUS_PROT_RD_BYTE			4U
3548c6a6b6SBharat Gooty #define SMBUS_PROT_WR_WORD			5U
3648c6a6b6SBharat Gooty #define SMBUS_PROT_RD_WORD			6U
3748c6a6b6SBharat Gooty #define SMBUS_PROT_BLK_WR			7U
3848c6a6b6SBharat Gooty #define SMBUS_PROT_BLK_RD			8U
3948c6a6b6SBharat Gooty #define SMBUS_PROT_PROC_CALL			9U
4048c6a6b6SBharat Gooty #define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL	10U
4148c6a6b6SBharat Gooty 
4248c6a6b6SBharat Gooty /* Number can be changed later */
4348c6a6b6SBharat Gooty #define BUS_BUSY_COUNT				100000U
4448c6a6b6SBharat Gooty 
4548c6a6b6SBharat Gooty #define IPROC_I2C_INVALID_ADDR			0xFFU
4648c6a6b6SBharat Gooty 
4748c6a6b6SBharat Gooty #define I2C_SMBUS_BLOCK_MAX			32U
4848c6a6b6SBharat Gooty 
4948c6a6b6SBharat Gooty /*
5048c6a6b6SBharat Gooty  * Enum to specify clock speed. The user will provide it during initialization.
5148c6a6b6SBharat Gooty  * If needed, it can be changed dynamically
5248c6a6b6SBharat Gooty  */
5348c6a6b6SBharat Gooty typedef enum iproc_smb_clk_freq {
5448c6a6b6SBharat Gooty 	IPROC_SMB_SPEED_100KHz = 0,
5548c6a6b6SBharat Gooty 	IPROC_SMB_SPEED_400KHz = 1,
5648c6a6b6SBharat Gooty 	IPROC_SMB_SPEED_INVALID = 255
5748c6a6b6SBharat Gooty } smb_clk_freq_t;
5848c6a6b6SBharat Gooty 
5948c6a6b6SBharat Gooty /* Structure used to pass information to read/write functions. */
6048c6a6b6SBharat Gooty struct iproc_xact_info {
6148c6a6b6SBharat Gooty 	/* Bus Identifier */
6248c6a6b6SBharat Gooty 	uint32_t bus_id;
6348c6a6b6SBharat Gooty 	/* Device Address */
6448c6a6b6SBharat Gooty 	uint8_t devaddr;
6548c6a6b6SBharat Gooty 	/* Passed by caller to send SMBus command cod e*/
6648c6a6b6SBharat Gooty 	uint8_t command;
6748c6a6b6SBharat Gooty 	/* actual data passed by the caller */
6848c6a6b6SBharat Gooty 	uint8_t *data;
6948c6a6b6SBharat Gooty 	/* Size of data buffer passed */
7048c6a6b6SBharat Gooty 	uint32_t size;
7148c6a6b6SBharat Gooty 	/* Sent by caller specifying PEC, 10-bit addresses */
7248c6a6b6SBharat Gooty 	uint16_t flags;
7348c6a6b6SBharat Gooty 	/* SMBus protocol to use to perform transaction */
7448c6a6b6SBharat Gooty 	uint8_t smb_proto;
7548c6a6b6SBharat Gooty 	/* true if command field below is valid. Otherwise, false */
7648c6a6b6SBharat Gooty 	uint32_t cmd_valid;
7748c6a6b6SBharat Gooty };
7848c6a6b6SBharat Gooty 
7948c6a6b6SBharat Gooty static const uintptr_t smbus_base_reg_addr[MAX_I2C] = {
8048c6a6b6SBharat Gooty 	SMBUS0_REGS_BASE,
8148c6a6b6SBharat Gooty 	SMBUS1_REGS_BASE
8248c6a6b6SBharat Gooty };
8348c6a6b6SBharat Gooty 
8448c6a6b6SBharat Gooty /* Function to read a value from specified register. */
iproc_i2c_reg_read(uint32_t bus_id,unsigned long reg_addr)8548c6a6b6SBharat Gooty static uint32_t iproc_i2c_reg_read(uint32_t bus_id, unsigned long reg_addr)
8648c6a6b6SBharat Gooty {
8748c6a6b6SBharat Gooty 	uint32_t val;
8848c6a6b6SBharat Gooty 	uintptr_t smbus;
8948c6a6b6SBharat Gooty 
9048c6a6b6SBharat Gooty 	smbus = smbus_base_reg_addr[bus_id];
9148c6a6b6SBharat Gooty 
9248c6a6b6SBharat Gooty 	val = mmio_read_32(smbus + reg_addr);
9348c6a6b6SBharat Gooty 	VERBOSE("i2c %u: reg %p read 0x%x\n", bus_id,
9448c6a6b6SBharat Gooty 		(void *)(smbus + reg_addr), val);
9548c6a6b6SBharat Gooty 	return val;
9648c6a6b6SBharat Gooty }
9748c6a6b6SBharat Gooty 
9848c6a6b6SBharat Gooty /* 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)9948c6a6b6SBharat Gooty static void iproc_i2c_reg_write(uint32_t bus_id,
10048c6a6b6SBharat Gooty 				unsigned long reg_addr,
10148c6a6b6SBharat Gooty 				uint32_t val)
10248c6a6b6SBharat Gooty {
10348c6a6b6SBharat Gooty 	uintptr_t smbus;
10448c6a6b6SBharat Gooty 
10548c6a6b6SBharat Gooty 	smbus = smbus_base_reg_addr[bus_id];
10648c6a6b6SBharat Gooty 
10748c6a6b6SBharat Gooty 	mmio_write_32((smbus + reg_addr), val);
10848c6a6b6SBharat Gooty 	VERBOSE("i2c %u: reg %p wrote 0x%x\n", bus_id,
10948c6a6b6SBharat Gooty 		(void *)(smbus + reg_addr), val);
11048c6a6b6SBharat Gooty }
11148c6a6b6SBharat Gooty 
11248c6a6b6SBharat Gooty /* 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)11348c6a6b6SBharat Gooty static void iproc_i2c_reg_clearset(uint32_t bus_id,
11448c6a6b6SBharat Gooty 				   unsigned long reg_addr,
11548c6a6b6SBharat Gooty 				   uint32_t clear,
11648c6a6b6SBharat Gooty 				   uint32_t set)
11748c6a6b6SBharat Gooty {
11848c6a6b6SBharat Gooty 	uintptr_t smbus;
11948c6a6b6SBharat Gooty 
12048c6a6b6SBharat Gooty 	smbus = smbus_base_reg_addr[bus_id];
12148c6a6b6SBharat Gooty 
12248c6a6b6SBharat Gooty 	mmio_clrsetbits_32((smbus + reg_addr), clear, set);
12348c6a6b6SBharat Gooty 	VERBOSE("i2c %u: reg %p clear 0x%x, set 0x%x\n", bus_id,
12448c6a6b6SBharat Gooty 		(void *)(smbus + reg_addr), clear, set);
12548c6a6b6SBharat Gooty }
12648c6a6b6SBharat Gooty 
12748c6a6b6SBharat Gooty /* Function to dump all SMBUS register */
12848c6a6b6SBharat Gooty #ifdef BCM_I2C_DEBUG
iproc_dump_i2c_regs(uint32_t bus_id)12948c6a6b6SBharat Gooty static int iproc_dump_i2c_regs(uint32_t bus_id)
13048c6a6b6SBharat Gooty {
13148c6a6b6SBharat Gooty 	uint32_t regval;
13248c6a6b6SBharat Gooty 
13348c6a6b6SBharat Gooty 	if (bus_id > MAX_I2C) {
13448c6a6b6SBharat Gooty 		return -1;
13548c6a6b6SBharat Gooty 	}
13648c6a6b6SBharat Gooty 
13748c6a6b6SBharat Gooty 	INFO("----------------------------------------------\n");
13848c6a6b6SBharat Gooty 	INFO("%s: Dumping SMBus %u registers...\n", __func__, bus_id);
13948c6a6b6SBharat Gooty 
14048c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
14148c6a6b6SBharat Gooty 	INFO("SMB_CFG_REG=0x%x\n", regval);
14248c6a6b6SBharat Gooty 
14348c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
14448c6a6b6SBharat Gooty 	INFO("SMB_TIMGCFG_REG=0x%x\n", regval);
14548c6a6b6SBharat Gooty 
14648c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_ADDR_REG);
14748c6a6b6SBharat Gooty 	INFO("SMB_ADDR_REG=0x%x\n", regval);
14848c6a6b6SBharat Gooty 
14948c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRFIFOCTL_REG);
15048c6a6b6SBharat Gooty 	INFO("SMB_MSTRFIFOCTL_REG=0x%x\n", regval);
15148c6a6b6SBharat Gooty 
15248c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVFIFOCTL_REG);
15348c6a6b6SBharat Gooty 	INFO("SMB_SLVFIFOCTL_REG=0x%x\n", regval);
15448c6a6b6SBharat Gooty 
15548c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_BITBANGCTL_REG);
15648c6a6b6SBharat Gooty 	INFO("SMB_BITBANGCTL_REG=0x%x\n", regval);
15748c6a6b6SBharat Gooty 
15848c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
15948c6a6b6SBharat Gooty 	INFO("SMB_MSTRCMD_REG=0x%x\n", regval);
16048c6a6b6SBharat Gooty 
16148c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVCMD_REG);
16248c6a6b6SBharat Gooty 	INFO("SMB_SLVCMD_REG=0x%x\n", regval);
16348c6a6b6SBharat Gooty 
16448c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTEN_REG);
16548c6a6b6SBharat Gooty 	INFO("SMB_EVTEN_REG=0x%x\n", regval);
16648c6a6b6SBharat Gooty 
16748c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
16848c6a6b6SBharat Gooty 	INFO("SMB_EVTSTS_REG=0x%x\n", regval);
16948c6a6b6SBharat Gooty 
17048c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATAWR_REG);
17148c6a6b6SBharat Gooty 	INFO("SMB_MSTRDATAWR_REG=0x%x\n", regval);
17248c6a6b6SBharat Gooty 
17348c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATARD_REG);
17448c6a6b6SBharat Gooty 	INFO("SMB_MSTRDATARD_REG=0x%x\n", regval);
17548c6a6b6SBharat Gooty 
17648c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATAWR_REG);
17748c6a6b6SBharat Gooty 	INFO("SMB_SLVDATAWR_REG=0x%x\n", regval);
17848c6a6b6SBharat Gooty 
17948c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATARD_REG);
18048c6a6b6SBharat Gooty 	INFO("SMB_SLVDATARD_REG=0x%x\n", regval);
18148c6a6b6SBharat Gooty 
18248c6a6b6SBharat Gooty 	INFO("----------------------------------------------\n");
18348c6a6b6SBharat Gooty 	return 0;
18448c6a6b6SBharat Gooty }
18548c6a6b6SBharat Gooty #endif
18648c6a6b6SBharat Gooty 
18748c6a6b6SBharat Gooty /*
18848c6a6b6SBharat Gooty  * Function to ensure that the previous transaction was completed before
18948c6a6b6SBharat Gooty  * initiating a new transaction. It can also be used in polling mode to
19048c6a6b6SBharat Gooty  * check status of completion of a command
19148c6a6b6SBharat Gooty  */
iproc_i2c_startbusy_wait(uint32_t bus_id)19248c6a6b6SBharat Gooty static int iproc_i2c_startbusy_wait(uint32_t bus_id)
19348c6a6b6SBharat Gooty {
19448c6a6b6SBharat Gooty 	uint32_t regval;
19548c6a6b6SBharat Gooty 	uint32_t retry = 0U;
19648c6a6b6SBharat Gooty 
19748c6a6b6SBharat Gooty 	/*
19848c6a6b6SBharat Gooty 	 * Check if an operation is in progress. During probe it won't be.
19948c6a6b6SBharat Gooty 	 * Want to make sure that the transaction in progress is completed.
20048c6a6b6SBharat Gooty 	 */
20148c6a6b6SBharat Gooty 	do {
20248c6a6b6SBharat Gooty 		udelay(1U);
20348c6a6b6SBharat Gooty 		regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
20448c6a6b6SBharat Gooty 		regval &= SMB_MSTRSTARTBUSYCMD_MASK;
20548c6a6b6SBharat Gooty 		if (retry++ > BUS_BUSY_COUNT) {
20648c6a6b6SBharat Gooty 			ERROR("%s: START_BUSY bit didn't clear, exiting\n",
20748c6a6b6SBharat Gooty 			      __func__);
20848c6a6b6SBharat Gooty 			return -1;
20948c6a6b6SBharat Gooty 		}
21048c6a6b6SBharat Gooty 
21148c6a6b6SBharat Gooty 	} while (regval != 0U);
21248c6a6b6SBharat Gooty 
21348c6a6b6SBharat Gooty 	return 0;
21448c6a6b6SBharat Gooty }
21548c6a6b6SBharat Gooty 
21648c6a6b6SBharat Gooty /*
21748c6a6b6SBharat Gooty  * This function copies data to SMBus's Tx FIFO. Valid for write transactions
21848c6a6b6SBharat Gooty  * info: Data to copy in to Tx FIFO. For read commands, the size should be
21948c6a6b6SBharat Gooty  * set to zero by the caller
22048c6a6b6SBharat Gooty  */
iproc_i2c_write_trans_data(struct iproc_xact_info * info)22148c6a6b6SBharat Gooty static void iproc_i2c_write_trans_data(struct iproc_xact_info *info)
22248c6a6b6SBharat Gooty {
22348c6a6b6SBharat Gooty 	uint32_t regval;
22448c6a6b6SBharat Gooty 	uint8_t devaddr;
22548c6a6b6SBharat Gooty 	uint32_t i;
22648c6a6b6SBharat Gooty 	uint32_t num_data_bytes = 0U;
22748c6a6b6SBharat Gooty 
22848c6a6b6SBharat Gooty #ifdef BCM_I2C_DEBUG
22948c6a6b6SBharat Gooty 	INFO("%s:dev_addr=0x%x,cmd_valid=%d, cmd=0x%x, size=%u proto=%d\n",
23048c6a6b6SBharat Gooty 	     __func__, info->devaddr, info->cmd_valid, info->command,
23148c6a6b6SBharat Gooty 	     info->size, info->smb_proto);
23248c6a6b6SBharat Gooty #endif
23348c6a6b6SBharat Gooty 	/* Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n */
23448c6a6b6SBharat Gooty 	devaddr = (info->devaddr << 1);
23548c6a6b6SBharat Gooty 
23648c6a6b6SBharat Gooty 	/*
23748c6a6b6SBharat Gooty 	 * Depending on the SMBus protocol, we need to write additional
23848c6a6b6SBharat Gooty 	 * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus spec
23948c6a6b6SBharat Gooty 	 * for sequence for a transaction
24048c6a6b6SBharat Gooty 	 */
24148c6a6b6SBharat Gooty 	switch (info->smb_proto) {
24248c6a6b6SBharat Gooty 	case SMBUS_PROT_RECV_BYTE:
24348c6a6b6SBharat Gooty 		/* No additional data to be written */
24448c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
24548c6a6b6SBharat Gooty 				    devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
24648c6a6b6SBharat Gooty 		break;
24748c6a6b6SBharat Gooty 	case SMBUS_PROT_SEND_BYTE:
24848c6a6b6SBharat Gooty 		num_data_bytes = info->size;
24948c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
25048c6a6b6SBharat Gooty 				    devaddr);
25148c6a6b6SBharat Gooty 		break;
25248c6a6b6SBharat Gooty 	case SMBUS_PROT_RD_BYTE:
25348c6a6b6SBharat Gooty 	case SMBUS_PROT_RD_WORD:
25448c6a6b6SBharat Gooty 	case SMBUS_PROT_BLK_RD:
25548c6a6b6SBharat Gooty 		/* Write slave address with R/W~ set (bit #0) */
25648c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
25748c6a6b6SBharat Gooty 				    devaddr | 0x1U);
25848c6a6b6SBharat Gooty 		break;
25948c6a6b6SBharat Gooty 	case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL:
26048c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
26148c6a6b6SBharat Gooty 				    devaddr | 0x1U | SMB_MSTRWRSTS_MASK);
26248c6a6b6SBharat Gooty 		break;
26348c6a6b6SBharat Gooty 	case SMBUS_PROT_WR_BYTE:
26448c6a6b6SBharat Gooty 	case SMBUS_PROT_WR_WORD:
26548c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
26648c6a6b6SBharat Gooty 				    devaddr);
26748c6a6b6SBharat Gooty 		/*
26848c6a6b6SBharat Gooty 		 * No additional bytes to be written. Data portion is written
26948c6a6b6SBharat Gooty 		 * in the 'for' loop below
27048c6a6b6SBharat Gooty 		 */
27148c6a6b6SBharat Gooty 		num_data_bytes = info->size;
27248c6a6b6SBharat Gooty 		break;
27348c6a6b6SBharat Gooty 	case SMBUS_PROT_BLK_WR:
27448c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
27548c6a6b6SBharat Gooty 				    devaddr);
27648c6a6b6SBharat Gooty 		/* 3rd byte is byte count */
27748c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
27848c6a6b6SBharat Gooty 				    info->size);
27948c6a6b6SBharat Gooty 		num_data_bytes = info->size;
28048c6a6b6SBharat Gooty 		break;
28148c6a6b6SBharat Gooty 	default:
28248c6a6b6SBharat Gooty 		return;
28348c6a6b6SBharat Gooty 	}
28448c6a6b6SBharat Gooty 
28548c6a6b6SBharat Gooty 	/* If the protocol needs command code, copy it */
28648c6a6b6SBharat Gooty 	if (info->cmd_valid) {
28748c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
28848c6a6b6SBharat Gooty 				    info->command);
28948c6a6b6SBharat Gooty 	}
29048c6a6b6SBharat Gooty 
29148c6a6b6SBharat Gooty 	/*
29248c6a6b6SBharat Gooty 	 * Copy actual data from caller. In general, for reads,
29348c6a6b6SBharat Gooty 	 * no data is copied.
29448c6a6b6SBharat Gooty 	 */
29548c6a6b6SBharat Gooty 	for (i = 0U; num_data_bytes; --num_data_bytes, i++) {
29648c6a6b6SBharat Gooty 		/* For the last byte, set MASTER_WR_STATUS bit */
29748c6a6b6SBharat Gooty 		regval = (num_data_bytes == 1U) ?
29848c6a6b6SBharat Gooty 			 info->data[i] | SMB_MSTRWRSTS_MASK : info->data[i];
29948c6a6b6SBharat Gooty 		iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG,
30048c6a6b6SBharat Gooty 				    regval);
30148c6a6b6SBharat Gooty 	}
30248c6a6b6SBharat Gooty }
30348c6a6b6SBharat Gooty 
30448c6a6b6SBharat Gooty /*
30548c6a6b6SBharat Gooty  * This function writes to the master command register and
30648c6a6b6SBharat Gooty  * then polls for completion
30748c6a6b6SBharat Gooty  */
iproc_i2c_write_master_command(uint32_t mastercmd,struct iproc_xact_info * info)30848c6a6b6SBharat Gooty static int iproc_i2c_write_master_command(uint32_t mastercmd,
30948c6a6b6SBharat Gooty 					  struct iproc_xact_info *info)
31048c6a6b6SBharat Gooty {
31148c6a6b6SBharat Gooty 	uint32_t retry = 0U;
31248c6a6b6SBharat Gooty 	uint32_t regval;
31348c6a6b6SBharat Gooty 
31448c6a6b6SBharat Gooty 	iproc_i2c_reg_write(info->bus_id, SMB_MSTRCMD_REG, mastercmd);
31548c6a6b6SBharat Gooty 
31648c6a6b6SBharat Gooty 	/* Check for Master Busy status */
31748c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
31848c6a6b6SBharat Gooty 	while ((regval & SMB_MSTRSTARTBUSYCMD_MASK) != 0U) {
31948c6a6b6SBharat Gooty 		udelay(1U);
32048c6a6b6SBharat Gooty 		if (retry++ > BUS_BUSY_COUNT) {
32148c6a6b6SBharat Gooty 			ERROR("%s: START_BUSY bit didn't clear, exiting\n",
32248c6a6b6SBharat Gooty 				__func__);
32348c6a6b6SBharat Gooty 			return -1;
32448c6a6b6SBharat Gooty 		}
32548c6a6b6SBharat Gooty 		regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG);
32648c6a6b6SBharat Gooty 	}
32748c6a6b6SBharat Gooty 
32848c6a6b6SBharat Gooty 	/* If start_busy bit cleared, check if there are any errors */
32948c6a6b6SBharat Gooty 	if (!(regval & SMB_MSTRSTARTBUSYCMD_MASK)) {
33048c6a6b6SBharat Gooty 		/* start_busy bit cleared, check master_status field now */
33148c6a6b6SBharat Gooty 		regval &= SMB_MSTRSTS_MASK;
33248c6a6b6SBharat Gooty 		regval >>= SMB_MSTRSTS_SHIFT;
33348c6a6b6SBharat Gooty 		if (regval != MSTR_STS_XACT_SUCCESS) {
33448c6a6b6SBharat Gooty 			/* Error We can flush Tx FIFO here */
33548c6a6b6SBharat Gooty 			ERROR("%s: ERROR: %u exiting\n", __func__, regval);
33648c6a6b6SBharat Gooty 			return -1;
33748c6a6b6SBharat Gooty 		}
33848c6a6b6SBharat Gooty 	}
33948c6a6b6SBharat Gooty 	return 0;
34048c6a6b6SBharat Gooty 
34148c6a6b6SBharat Gooty }
34248c6a6b6SBharat Gooty /* Function to initiate data send and verify completion status */
iproc_i2c_data_send(struct iproc_xact_info * info)34348c6a6b6SBharat Gooty static int iproc_i2c_data_send(struct iproc_xact_info *info)
34448c6a6b6SBharat Gooty {
34548c6a6b6SBharat Gooty 	int rc;
34648c6a6b6SBharat Gooty 	uint32_t mastercmd;
34748c6a6b6SBharat Gooty 
34848c6a6b6SBharat Gooty 	/* Make sure the previous transaction completed */
34948c6a6b6SBharat Gooty 	rc = iproc_i2c_startbusy_wait(info->bus_id);
35048c6a6b6SBharat Gooty 
35148c6a6b6SBharat Gooty 	if (rc < 0) {
35248c6a6b6SBharat Gooty 		WARN("%s: Send: bus is busy, exiting\n", __func__);
35348c6a6b6SBharat Gooty 		return rc;
35448c6a6b6SBharat Gooty 	}
35548c6a6b6SBharat Gooty 	/* Write transaction bytes to Tx FIFO */
35648c6a6b6SBharat Gooty 	iproc_i2c_write_trans_data(info);
35748c6a6b6SBharat Gooty 
35848c6a6b6SBharat Gooty 	/*
35948c6a6b6SBharat Gooty 	 * Program master command register (0x30) with protocol type and set
36048c6a6b6SBharat Gooty 	 * start_busy_command bit to initiate the write transaction
36148c6a6b6SBharat Gooty 	 */
36248c6a6b6SBharat Gooty 	mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
36348c6a6b6SBharat Gooty 	    SMB_MSTRSTARTBUSYCMD_MASK;
36448c6a6b6SBharat Gooty 
36548c6a6b6SBharat Gooty 	if (iproc_i2c_write_master_command(mastercmd, info)) {
36648c6a6b6SBharat Gooty 		return -1;
36748c6a6b6SBharat Gooty 	}
36848c6a6b6SBharat Gooty 
36948c6a6b6SBharat Gooty 	return 0;
37048c6a6b6SBharat Gooty }
37148c6a6b6SBharat Gooty 
37248c6a6b6SBharat Gooty /*
37348c6a6b6SBharat Gooty  * Function to initiate data receive, verify completion status,
37448c6a6b6SBharat Gooty  * and read from SMBUS Read FIFO
37548c6a6b6SBharat Gooty  */
iproc_i2c_data_recv(struct iproc_xact_info * info,uint32_t * num_bytes_read)37648c6a6b6SBharat Gooty static int iproc_i2c_data_recv(struct iproc_xact_info *info,
37748c6a6b6SBharat Gooty 			       uint32_t *num_bytes_read)
37848c6a6b6SBharat Gooty {
37948c6a6b6SBharat Gooty 	int rc;
38048c6a6b6SBharat Gooty 	uint32_t mastercmd;
38148c6a6b6SBharat Gooty 	uint32_t regval;
38248c6a6b6SBharat Gooty 
38348c6a6b6SBharat Gooty 	/* Make sure the previous transaction completed */
38448c6a6b6SBharat Gooty 	rc = iproc_i2c_startbusy_wait(info->bus_id);
38548c6a6b6SBharat Gooty 
38648c6a6b6SBharat Gooty 	if (rc < 0) {
38748c6a6b6SBharat Gooty 		WARN("%s: Receive: Bus is busy, exiting\n", __func__);
38848c6a6b6SBharat Gooty 		return rc;
38948c6a6b6SBharat Gooty 	}
39048c6a6b6SBharat Gooty 
39148c6a6b6SBharat Gooty 	/* Program all transaction bytes into master Tx FIFO */
39248c6a6b6SBharat Gooty 	iproc_i2c_write_trans_data(info);
39348c6a6b6SBharat Gooty 
39448c6a6b6SBharat Gooty 	/*
39548c6a6b6SBharat Gooty 	 * Program master command register (0x30) with protocol type and set
39648c6a6b6SBharat Gooty 	 * start_busy_command bit to initiate the write transaction
39748c6a6b6SBharat Gooty 	 */
39848c6a6b6SBharat Gooty 	mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) |
39948c6a6b6SBharat Gooty 		     SMB_MSTRSTARTBUSYCMD_MASK | info->size;
40048c6a6b6SBharat Gooty 
40148c6a6b6SBharat Gooty 	if (iproc_i2c_write_master_command(mastercmd, info)) {
40248c6a6b6SBharat Gooty 		return -1;
40348c6a6b6SBharat Gooty 	}
40448c6a6b6SBharat Gooty 
40548c6a6b6SBharat Gooty 	/* Read received byte(s), after TX out address etc */
40648c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRDATARD_REG);
40748c6a6b6SBharat Gooty 
40848c6a6b6SBharat Gooty 	/* For block read, protocol (hw) returns byte count,as the first byte */
40948c6a6b6SBharat Gooty 	if (info->smb_proto == SMBUS_PROT_BLK_RD) {
41048c6a6b6SBharat Gooty 		uint32_t i;
41148c6a6b6SBharat Gooty 
41248c6a6b6SBharat Gooty 		*num_bytes_read = regval & SMB_MSTRRDDATA_MASK;
41348c6a6b6SBharat Gooty 		/*
41448c6a6b6SBharat Gooty 		 * Limit to reading a max of 32 bytes only; just a safeguard.
41548c6a6b6SBharat Gooty 		 * If # bytes read is a number > 32, check transaction set up,
41648c6a6b6SBharat Gooty 		 * and contact hw engg.
41748c6a6b6SBharat Gooty 		 * Assumption: PEC is disabled
41848c6a6b6SBharat Gooty 		 */
41948c6a6b6SBharat Gooty 		for (i = 0U; (i < *num_bytes_read) &&
42048c6a6b6SBharat Gooty 		     (i < I2C_SMBUS_BLOCK_MAX); i++) {
42148c6a6b6SBharat Gooty 			/* Read Rx FIFO for data bytes */
42248c6a6b6SBharat Gooty 			regval = iproc_i2c_reg_read(info->bus_id,
42348c6a6b6SBharat Gooty 						    SMB_MSTRDATARD_REG);
42448c6a6b6SBharat Gooty 			info->data[i] = regval & SMB_MSTRRDDATA_MASK;
42548c6a6b6SBharat Gooty 		}
42648c6a6b6SBharat Gooty 	} else {
42748c6a6b6SBharat Gooty 		/* 1 Byte data */
42848c6a6b6SBharat Gooty 		*info->data = regval & SMB_MSTRRDDATA_MASK;
42948c6a6b6SBharat Gooty 		*num_bytes_read = 1U;
43048c6a6b6SBharat Gooty 	}
43148c6a6b6SBharat Gooty 
43248c6a6b6SBharat Gooty 	return 0;
43348c6a6b6SBharat Gooty }
43448c6a6b6SBharat Gooty 
43548c6a6b6SBharat Gooty /*
43648c6a6b6SBharat Gooty  * This function set clock frequency for SMBus block. As per hardware
43748c6a6b6SBharat Gooty  * engineering, the clock frequency can be changed dynamically.
43848c6a6b6SBharat Gooty  */
iproc_i2c_set_clk_freq(uint32_t bus_id,smb_clk_freq_t freq)43948c6a6b6SBharat Gooty static int iproc_i2c_set_clk_freq(uint32_t bus_id, smb_clk_freq_t freq)
44048c6a6b6SBharat Gooty {
44148c6a6b6SBharat Gooty 	uint32_t val;
44248c6a6b6SBharat Gooty 
44348c6a6b6SBharat Gooty 	switch (freq) {
44448c6a6b6SBharat Gooty 	case IPROC_SMB_SPEED_100KHz:
44548c6a6b6SBharat Gooty 		val = 0U;
44648c6a6b6SBharat Gooty 		break;
44748c6a6b6SBharat Gooty 	case IPROC_SMB_SPEED_400KHz:
44848c6a6b6SBharat Gooty 		val = 1U;
44948c6a6b6SBharat Gooty 		break;
45048c6a6b6SBharat Gooty 	default:
45148c6a6b6SBharat Gooty 		return -1;
45248c6a6b6SBharat Gooty 	}
45348c6a6b6SBharat Gooty 
45448c6a6b6SBharat Gooty 	iproc_i2c_reg_clearset(bus_id, SMB_TIMGCFG_REG,
45548c6a6b6SBharat Gooty 			       SMB_TIMGCFG_MODE400_MASK,
45648c6a6b6SBharat Gooty 			       val << SMB_TIMGCFG_MODE400_SHIFT);
45748c6a6b6SBharat Gooty 
45848c6a6b6SBharat Gooty 	return 0;
45948c6a6b6SBharat Gooty }
46048c6a6b6SBharat Gooty 
46148c6a6b6SBharat Gooty /* 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)46248c6a6b6SBharat Gooty static void iproc_i2c_fill_info(struct iproc_xact_info *info, uint32_t bus_id,
46348c6a6b6SBharat Gooty 				uint8_t devaddr, uint8_t cmd, uint8_t *value,
46448c6a6b6SBharat Gooty 				uint8_t smb_proto, uint32_t cmd_valid)
46548c6a6b6SBharat Gooty {
46648c6a6b6SBharat Gooty 	info->bus_id = bus_id;
46748c6a6b6SBharat Gooty 	info->devaddr = devaddr;
46848c6a6b6SBharat Gooty 	info->command = (uint8_t)cmd;
46948c6a6b6SBharat Gooty 	info->smb_proto = smb_proto;
47048c6a6b6SBharat Gooty 	info->data = value;
47148c6a6b6SBharat Gooty 	info->size = 1U;
47248c6a6b6SBharat Gooty 	info->flags = 0U;
47348c6a6b6SBharat Gooty 	info->cmd_valid = cmd_valid;
47448c6a6b6SBharat Gooty }
47548c6a6b6SBharat Gooty 
47648c6a6b6SBharat Gooty /* This function initializes the SMBUS */
iproc_i2c_init(uint32_t bus_id,int speed)47748c6a6b6SBharat Gooty static void iproc_i2c_init(uint32_t bus_id, int speed)
47848c6a6b6SBharat Gooty {
47948c6a6b6SBharat Gooty 	uint32_t regval;
48048c6a6b6SBharat Gooty 
48148c6a6b6SBharat Gooty #ifdef BCM_I2C_DEBUG
48248c6a6b6SBharat Gooty 	INFO("%s: Enter Init\n", __func__);
48348c6a6b6SBharat Gooty #endif
48448c6a6b6SBharat Gooty 
48548c6a6b6SBharat Gooty 	/* Put controller in reset */
48648c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
48748c6a6b6SBharat Gooty 	regval |= BIT(SMB_CFG_RST_SHIFT);
48848c6a6b6SBharat Gooty 	regval &= ~(BIT(SMB_CFG_SMBEN_SHIFT));
48948c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
49048c6a6b6SBharat Gooty 
49148c6a6b6SBharat Gooty 	/* Wait 100 usec per spec */
49248c6a6b6SBharat Gooty 	udelay(100U);
49348c6a6b6SBharat Gooty 
49448c6a6b6SBharat Gooty 	/* Bring controller out of reset */
49548c6a6b6SBharat Gooty 	regval &= ~(BIT(SMB_CFG_RST_SHIFT));
49648c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
49748c6a6b6SBharat Gooty 
49848c6a6b6SBharat Gooty 	/*
49948c6a6b6SBharat Gooty 	 * Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0.
50048c6a6b6SBharat Gooty 	 * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts
50148c6a6b6SBharat Gooty 	 */
50248c6a6b6SBharat Gooty 	regval = SMB_MSTRRXFIFOFLSH_MASK | SMB_MSTRTXFIFOFLSH_MASK;
50348c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_MSTRFIFOCTL_REG, regval);
50448c6a6b6SBharat Gooty 
50548c6a6b6SBharat Gooty 	/*
50648c6a6b6SBharat Gooty 	 * Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero
50748c6a6b6SBharat Gooty 	 * since there will be only one master
50848c6a6b6SBharat Gooty 	 */
50948c6a6b6SBharat Gooty 
51048c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG);
51148c6a6b6SBharat Gooty 	regval |= SMB_CFG_SMBEN_MASK;
51248c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval);
51348c6a6b6SBharat Gooty 	/* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */
51448c6a6b6SBharat Gooty 	mdelay(10U);
51548c6a6b6SBharat Gooty 
51648c6a6b6SBharat Gooty 	/* If error then set default speed */
51748c6a6b6SBharat Gooty 	if (i2c_set_bus_speed(bus_id, speed)) {
51848c6a6b6SBharat Gooty 		i2c_set_bus_speed(bus_id, I2C_SPEED_DEFAULT);
51948c6a6b6SBharat Gooty 	}
52048c6a6b6SBharat Gooty 
52148c6a6b6SBharat Gooty 	/* Disable intrs */
52248c6a6b6SBharat Gooty 	regval = 0x0U;
52348c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_EVTEN_REG, regval);
52448c6a6b6SBharat Gooty 
52548c6a6b6SBharat Gooty 	/* Clear intrs (W1TC) */
52648c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG);
52748c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_EVTSTS_REG, regval);
52848c6a6b6SBharat Gooty 
52948c6a6b6SBharat Gooty #ifdef BCM_I2C_DEBUG
53048c6a6b6SBharat Gooty 	iproc_dump_i2c_regs(bus_id);
53148c6a6b6SBharat Gooty 
53248c6a6b6SBharat Gooty 	INFO("%s: Exit Init Successfully\n", __func__);
53348c6a6b6SBharat Gooty #endif
53448c6a6b6SBharat Gooty }
53548c6a6b6SBharat Gooty 
53648c6a6b6SBharat Gooty /*
53748c6a6b6SBharat Gooty  * Function Name:    i2c_init
53848c6a6b6SBharat Gooty  *
53948c6a6b6SBharat Gooty  * Description:
54048c6a6b6SBharat Gooty  *	This function initializes the SMBUS.
54148c6a6b6SBharat Gooty  *
54248c6a6b6SBharat Gooty  * Parameters:
54348c6a6b6SBharat Gooty  *	bus_id - I2C bus ID
54448c6a6b6SBharat Gooty  *	speed  - I2C bus speed in Hz
54548c6a6b6SBharat Gooty  *
54648c6a6b6SBharat Gooty  * Return:
54748c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
54848c6a6b6SBharat Gooty  */
i2c_init(uint32_t bus_id,int speed)54948c6a6b6SBharat Gooty int i2c_init(uint32_t bus_id, int speed)
55048c6a6b6SBharat Gooty {
55148c6a6b6SBharat Gooty 	if (bus_id > MAX_I2C) {
55248c6a6b6SBharat Gooty 		WARN("%s: Invalid Bus %u\n", __func__, bus_id);
55348c6a6b6SBharat Gooty 		return -1;
55448c6a6b6SBharat Gooty 	}
55548c6a6b6SBharat Gooty 
55648c6a6b6SBharat Gooty 	iproc_i2c_init(bus_id, speed);
55748c6a6b6SBharat Gooty 	return 0U;
55848c6a6b6SBharat Gooty }
55948c6a6b6SBharat Gooty 
56048c6a6b6SBharat Gooty /*
56148c6a6b6SBharat Gooty  * Function Name:    i2c_probe
56248c6a6b6SBharat Gooty  *
56348c6a6b6SBharat Gooty  * Description:
56448c6a6b6SBharat Gooty  *	This function probes the I2C bus for the existence of the specified
56548c6a6b6SBharat Gooty  *	device.
56648c6a6b6SBharat Gooty  *
56748c6a6b6SBharat Gooty  * Parameters:
56848c6a6b6SBharat Gooty  *	bus_id  - I2C bus ID
56948c6a6b6SBharat Gooty  *	devaddr - Device Address
57048c6a6b6SBharat Gooty  *
57148c6a6b6SBharat Gooty  * Return:
57248c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
57348c6a6b6SBharat Gooty  */
i2c_probe(uint32_t bus_id,uint8_t devaddr)57448c6a6b6SBharat Gooty int i2c_probe(uint32_t bus_id, uint8_t devaddr)
57548c6a6b6SBharat Gooty {
57648c6a6b6SBharat Gooty 	uint32_t regval;
57748c6a6b6SBharat Gooty 	int rc;
57848c6a6b6SBharat Gooty 
57948c6a6b6SBharat Gooty 	/*
58048c6a6b6SBharat Gooty 	 * i2c_init() Initializes internal regs, disable intrs (and then clear intrs),
58148c6a6b6SBharat Gooty 	 * set fifo thresholds, etc.
58248c6a6b6SBharat Gooty 	 * Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n
58348c6a6b6SBharat Gooty 	 */
58448c6a6b6SBharat Gooty 	regval = (devaddr << 1U);
58548c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_MSTRDATAWR_REG, regval);
58648c6a6b6SBharat Gooty 
58748c6a6b6SBharat Gooty 	regval = ((SMBUS_PROT_QUICK_CMD << SMB_MSTRSMBUSPROTO_SHIFT) |
58848c6a6b6SBharat Gooty 		  SMB_MSTRSTARTBUSYCMD_MASK);
58948c6a6b6SBharat Gooty 	iproc_i2c_reg_write(bus_id, SMB_MSTRCMD_REG, regval);
59048c6a6b6SBharat Gooty 
59148c6a6b6SBharat Gooty 	rc = iproc_i2c_startbusy_wait(bus_id);
59248c6a6b6SBharat Gooty 
59348c6a6b6SBharat Gooty 	if (rc < 0) {
59448c6a6b6SBharat Gooty 		WARN("%s: Probe: bus is busy, exiting\n", __func__);
59548c6a6b6SBharat Gooty 		return rc;
59648c6a6b6SBharat Gooty 	}
59748c6a6b6SBharat Gooty 
59848c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG);
59948c6a6b6SBharat Gooty 	if (((regval & SMB_MSTRSTS_MASK) >> SMB_MSTRSTS_SHIFT) == 0)
60048c6a6b6SBharat Gooty 		VERBOSE("i2c device address: 0x%x\n", devaddr);
60148c6a6b6SBharat Gooty 	else
60248c6a6b6SBharat Gooty 		return -1;
60348c6a6b6SBharat Gooty 
60448c6a6b6SBharat Gooty #ifdef BCM_I2C_DEBUG
60548c6a6b6SBharat Gooty 	iproc_dump_i2c_regs(bus_id);
60648c6a6b6SBharat Gooty #endif
60748c6a6b6SBharat Gooty 	return 0;
60848c6a6b6SBharat Gooty }
60948c6a6b6SBharat Gooty 
61048c6a6b6SBharat Gooty /*
61148c6a6b6SBharat Gooty  * Function Name:    i2c_recv_byte
61248c6a6b6SBharat Gooty  *
61348c6a6b6SBharat Gooty  * Description:
61448c6a6b6SBharat Gooty  *	This function reads I2C data from a device without specifying
615*1b491eeaSElyes Haouas  *	a command register.
61648c6a6b6SBharat Gooty  *
61748c6a6b6SBharat Gooty  * Parameters:
61848c6a6b6SBharat Gooty  *	bus_id  - I2C bus ID
61948c6a6b6SBharat Gooty  *	devaddr - Device Address
62048c6a6b6SBharat Gooty  *	value   - Data Read
62148c6a6b6SBharat Gooty  *
62248c6a6b6SBharat Gooty  * Return:
62348c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
62448c6a6b6SBharat Gooty  */
i2c_recv_byte(uint32_t bus_id,uint8_t devaddr,uint8_t * value)62548c6a6b6SBharat Gooty int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value)
62648c6a6b6SBharat Gooty {
62748c6a6b6SBharat Gooty 	int rc;
62848c6a6b6SBharat Gooty 	struct iproc_xact_info info;
62948c6a6b6SBharat Gooty 	uint32_t num_bytes_read = 0;
63048c6a6b6SBharat Gooty 
63148c6a6b6SBharat Gooty 	iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, value,
63248c6a6b6SBharat Gooty 			    SMBUS_PROT_RECV_BYTE, 0U);
63348c6a6b6SBharat Gooty 
63448c6a6b6SBharat Gooty 	/* Refer to i2c_smbus_read_byte for params passed. */
63548c6a6b6SBharat Gooty 	rc = iproc_i2c_data_recv(&info, &num_bytes_read);
63648c6a6b6SBharat Gooty 
63748c6a6b6SBharat Gooty 	if (rc < 0) {
63848c6a6b6SBharat Gooty 		printf("%s: %s error accessing device 0x%x\n",
63948c6a6b6SBharat Gooty 		__func__, "Read", devaddr);
64048c6a6b6SBharat Gooty 	}
64148c6a6b6SBharat Gooty 
64248c6a6b6SBharat Gooty 	return rc;
64348c6a6b6SBharat Gooty }
64448c6a6b6SBharat Gooty 
64548c6a6b6SBharat Gooty /*
64648c6a6b6SBharat Gooty  * Function Name:    i2c_send_byte
64748c6a6b6SBharat Gooty  *
64848c6a6b6SBharat Gooty  * Description:
64948c6a6b6SBharat Gooty  *	This function send I2C data to a device without specifying
650*1b491eeaSElyes Haouas  *	a command register.
65148c6a6b6SBharat Gooty  *
65248c6a6b6SBharat Gooty  * Parameters:
65348c6a6b6SBharat Gooty  *	bus_id  - I2C bus ID
65448c6a6b6SBharat Gooty  *	devaddr - Device Address
65548c6a6b6SBharat Gooty  *	value   - Data Send
65648c6a6b6SBharat Gooty  *
65748c6a6b6SBharat Gooty  * Return:
65848c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
65948c6a6b6SBharat Gooty  */
i2c_send_byte(uint32_t bus_id,uint8_t devaddr,uint8_t value)66048c6a6b6SBharat Gooty int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value)
66148c6a6b6SBharat Gooty {
66248c6a6b6SBharat Gooty 	int rc;
66348c6a6b6SBharat Gooty 	struct iproc_xact_info info;
66448c6a6b6SBharat Gooty 
66548c6a6b6SBharat Gooty 	iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, &value,
66648c6a6b6SBharat Gooty 			    SMBUS_PROT_SEND_BYTE, 0U);
66748c6a6b6SBharat Gooty 
66848c6a6b6SBharat Gooty 	/* Refer to i2c_smbus_write_byte params passed. */
66948c6a6b6SBharat Gooty 	rc = iproc_i2c_data_send(&info);
67048c6a6b6SBharat Gooty 
67148c6a6b6SBharat Gooty 	if (rc < 0) {
67248c6a6b6SBharat Gooty 		ERROR("%s: %s error accessing device 0x%x\n",
67348c6a6b6SBharat Gooty 		__func__, "Write", devaddr);
67448c6a6b6SBharat Gooty 	}
67548c6a6b6SBharat Gooty 
67648c6a6b6SBharat Gooty 	return rc;
67748c6a6b6SBharat Gooty }
67848c6a6b6SBharat Gooty 
67948c6a6b6SBharat Gooty /* Helper function to read a single byte */
i2c_read_byte(uint32_t bus_id,uint8_t devaddr,uint8_t regoffset,uint8_t * value)68048c6a6b6SBharat Gooty static int i2c_read_byte(uint32_t bus_id,
68148c6a6b6SBharat Gooty 			 uint8_t devaddr,
68248c6a6b6SBharat Gooty 			 uint8_t regoffset,
68348c6a6b6SBharat Gooty 			 uint8_t *value)
68448c6a6b6SBharat Gooty {
68548c6a6b6SBharat Gooty 	int rc;
68648c6a6b6SBharat Gooty 	struct iproc_xact_info info;
68748c6a6b6SBharat Gooty 	uint32_t num_bytes_read = 0U;
68848c6a6b6SBharat Gooty 
68948c6a6b6SBharat Gooty 	iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, value,
69048c6a6b6SBharat Gooty 			    SMBUS_PROT_RD_BYTE, 1U);
69148c6a6b6SBharat Gooty 
69248c6a6b6SBharat Gooty 	/* Refer to i2c_smbus_read_byte for params passed. */
69348c6a6b6SBharat Gooty 	rc = iproc_i2c_data_recv(&info, &num_bytes_read);
69448c6a6b6SBharat Gooty 
69548c6a6b6SBharat Gooty 	if (rc < 0) {
69648c6a6b6SBharat Gooty 		ERROR("%s: %s error accessing device 0x%x\n",
69748c6a6b6SBharat Gooty 		       __func__, "Read", devaddr);
69848c6a6b6SBharat Gooty 	}
69948c6a6b6SBharat Gooty 	return rc;
70048c6a6b6SBharat Gooty }
70148c6a6b6SBharat Gooty 
70248c6a6b6SBharat Gooty /*
70348c6a6b6SBharat Gooty  * Function Name:    i2c_read
70448c6a6b6SBharat Gooty  *
70548c6a6b6SBharat Gooty  * Description:
70648c6a6b6SBharat Gooty  *	This function reads I2C data from a device with a designated
70748c6a6b6SBharat Gooty  *	command register
70848c6a6b6SBharat Gooty  *
70948c6a6b6SBharat Gooty  * Parameters:
71048c6a6b6SBharat Gooty  *	bus_id  - I2C bus ID
71148c6a6b6SBharat Gooty  *	devaddr - Device Address
71248c6a6b6SBharat Gooty  *	addr    - Register Offset
71348c6a6b6SBharat Gooty  *	alen    - Address Length, 1 for byte, 2 for word (not supported)
71448c6a6b6SBharat Gooty  *	buffer  - Data Buffer
71548c6a6b6SBharat Gooty  *	len     - Data Length in bytes
71648c6a6b6SBharat Gooty  *
71748c6a6b6SBharat Gooty  * Return:
71848c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
71948c6a6b6SBharat Gooty  */
i2c_read(uint32_t bus_id,uint8_t devaddr,uint32_t addr,int alen,uint8_t * buffer,int len)72048c6a6b6SBharat Gooty int i2c_read(uint32_t bus_id,
72148c6a6b6SBharat Gooty 	     uint8_t devaddr,
72248c6a6b6SBharat Gooty 	     uint32_t addr,
72348c6a6b6SBharat Gooty 	     int alen,
72448c6a6b6SBharat Gooty 	     uint8_t *buffer,
72548c6a6b6SBharat Gooty 	     int len)
72648c6a6b6SBharat Gooty {
72748c6a6b6SBharat Gooty 	uint32_t i;
72848c6a6b6SBharat Gooty 
72948c6a6b6SBharat Gooty 	if (alen > 1) {
73048c6a6b6SBharat Gooty 		WARN("I2C read: addr len %d not supported\n", alen);
73148c6a6b6SBharat Gooty 		return -1;
73248c6a6b6SBharat Gooty 	}
73348c6a6b6SBharat Gooty 
73448c6a6b6SBharat Gooty 	if (addr + len > 256) {
73548c6a6b6SBharat Gooty 		WARN("I2C read: address out of range\n");
73648c6a6b6SBharat Gooty 		return -1;
73748c6a6b6SBharat Gooty 	}
73848c6a6b6SBharat Gooty 
73948c6a6b6SBharat Gooty 	for (i = 0U; i < len; i++) {
74048c6a6b6SBharat Gooty 		if (i2c_read_byte(bus_id, devaddr, addr + i, &buffer[i])) {
74148c6a6b6SBharat Gooty 			ERROR("I2C read: I/O error\n");
74248c6a6b6SBharat Gooty 			iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
74348c6a6b6SBharat Gooty 			return -1;
74448c6a6b6SBharat Gooty 		}
74548c6a6b6SBharat Gooty 	}
74648c6a6b6SBharat Gooty 
74748c6a6b6SBharat Gooty 	return 0;
74848c6a6b6SBharat Gooty }
74948c6a6b6SBharat Gooty 
75048c6a6b6SBharat Gooty /* Helper function to write a single byte */
i2c_write_byte(uint32_t bus_id,uint8_t devaddr,uint8_t regoffset,uint8_t value)75148c6a6b6SBharat Gooty static int i2c_write_byte(uint32_t bus_id,
75248c6a6b6SBharat Gooty 			  uint8_t devaddr,
75348c6a6b6SBharat Gooty 			  uint8_t regoffset,
75448c6a6b6SBharat Gooty 			  uint8_t value)
75548c6a6b6SBharat Gooty {
75648c6a6b6SBharat Gooty 	int rc;
75748c6a6b6SBharat Gooty 	struct iproc_xact_info info;
75848c6a6b6SBharat Gooty 
75948c6a6b6SBharat Gooty 	iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, &value,
76048c6a6b6SBharat Gooty 			    SMBUS_PROT_WR_BYTE, 1U);
76148c6a6b6SBharat Gooty 
76248c6a6b6SBharat Gooty 	/* Refer to i2c_smbus_write_byte params passed. */
76348c6a6b6SBharat Gooty 	rc = iproc_i2c_data_send(&info);
76448c6a6b6SBharat Gooty 
76548c6a6b6SBharat Gooty 	if (rc < 0) {
76648c6a6b6SBharat Gooty 		ERROR("%s: %s error accessing device 0x%x\n",
76748c6a6b6SBharat Gooty 		       __func__, "Write", devaddr);
76848c6a6b6SBharat Gooty 		return -1;
76948c6a6b6SBharat Gooty 	}
77048c6a6b6SBharat Gooty 
77148c6a6b6SBharat Gooty 	return 0;
77248c6a6b6SBharat Gooty }
77348c6a6b6SBharat Gooty 
77448c6a6b6SBharat Gooty /*
77548c6a6b6SBharat Gooty  * Function Name:    i2c_write
77648c6a6b6SBharat Gooty  *
77748c6a6b6SBharat Gooty  * Description:
77848c6a6b6SBharat Gooty  *	This function write I2C data to a device with a designated
77948c6a6b6SBharat Gooty  *	command register
78048c6a6b6SBharat Gooty  *
78148c6a6b6SBharat Gooty  * Parameters:
78248c6a6b6SBharat Gooty  *	bus_id  - I2C bus ID
78348c6a6b6SBharat Gooty  *	devaddr - Device Address
78448c6a6b6SBharat Gooty  *	addr    - Register Offset
78548c6a6b6SBharat Gooty  *	alen    - Address Length, 1 for byte, 2 for word (not supported)
78648c6a6b6SBharat Gooty  *	buffer  - Data Buffer
78748c6a6b6SBharat Gooty  *	len     - Data Length in bytes
78848c6a6b6SBharat Gooty  *
78948c6a6b6SBharat Gooty  * Return:
79048c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
79148c6a6b6SBharat Gooty  */
i2c_write(uint32_t bus_id,uint8_t devaddr,uint32_t addr,int alen,uint8_t * buffer,int len)79248c6a6b6SBharat Gooty int i2c_write(uint32_t bus_id,
79348c6a6b6SBharat Gooty 	      uint8_t devaddr,
79448c6a6b6SBharat Gooty 	      uint32_t addr,
79548c6a6b6SBharat Gooty 	      int alen,
79648c6a6b6SBharat Gooty 	      uint8_t *buffer,
79748c6a6b6SBharat Gooty 	      int len)
79848c6a6b6SBharat Gooty {
79948c6a6b6SBharat Gooty 	uint32_t i;
80048c6a6b6SBharat Gooty 
80148c6a6b6SBharat Gooty 	if (alen > 1) {
80248c6a6b6SBharat Gooty 		WARN("I2C write: addr len %d not supported\n", alen);
80348c6a6b6SBharat Gooty 		return -1;
80448c6a6b6SBharat Gooty 	}
80548c6a6b6SBharat Gooty 
80648c6a6b6SBharat Gooty 	if (addr + len > 256U) {
80748c6a6b6SBharat Gooty 		WARN("I2C write: address out of range\n");
80848c6a6b6SBharat Gooty 		return -1;
80948c6a6b6SBharat Gooty 	}
81048c6a6b6SBharat Gooty 
81148c6a6b6SBharat Gooty 	for (i = 0U; i < len; i++) {
81248c6a6b6SBharat Gooty 		if (i2c_write_byte(bus_id, devaddr, addr + i, buffer[i])) {
81348c6a6b6SBharat Gooty 			ERROR("I2C write: I/O error\n");
81448c6a6b6SBharat Gooty 			iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id));
81548c6a6b6SBharat Gooty 			return -1;
81648c6a6b6SBharat Gooty 		}
81748c6a6b6SBharat Gooty 	}
81848c6a6b6SBharat Gooty 	return 0;
81948c6a6b6SBharat Gooty }
82048c6a6b6SBharat Gooty 
82148c6a6b6SBharat Gooty /*
82248c6a6b6SBharat Gooty  * Function Name:    i2c_set_bus_speed
82348c6a6b6SBharat Gooty  *
82448c6a6b6SBharat Gooty  * Description:
82548c6a6b6SBharat Gooty  *	This function configures the SMBUS speed
82648c6a6b6SBharat Gooty  *
82748c6a6b6SBharat Gooty  * Parameters:
82848c6a6b6SBharat Gooty  *	bus_id - I2C bus ID
82948c6a6b6SBharat Gooty  *	speed  - I2C bus speed in Hz
83048c6a6b6SBharat Gooty  *
83148c6a6b6SBharat Gooty  * Return:
83248c6a6b6SBharat Gooty  *	0 on success, or -1 on failure.
83348c6a6b6SBharat Gooty  */
i2c_set_bus_speed(uint32_t bus_id,uint32_t speed)83448c6a6b6SBharat Gooty int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed)
83548c6a6b6SBharat Gooty {
83648c6a6b6SBharat Gooty 	switch (speed) {
83748c6a6b6SBharat Gooty 	case I2C_SPEED_100KHz:
83848c6a6b6SBharat Gooty 		iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_100KHz);
83948c6a6b6SBharat Gooty 		break;
84048c6a6b6SBharat Gooty 
84148c6a6b6SBharat Gooty 	case I2C_SPEED_400KHz:
84248c6a6b6SBharat Gooty 		iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_400KHz);
84348c6a6b6SBharat Gooty 		break;
84448c6a6b6SBharat Gooty 
84548c6a6b6SBharat Gooty 	default:
84648c6a6b6SBharat Gooty 		return -1;
84748c6a6b6SBharat Gooty 	}
84848c6a6b6SBharat Gooty 	return 0;
84948c6a6b6SBharat Gooty }
85048c6a6b6SBharat Gooty 
85148c6a6b6SBharat Gooty /*
85248c6a6b6SBharat Gooty  * Function Name:    i2c_get_bus_speed
85348c6a6b6SBharat Gooty  *
85448c6a6b6SBharat Gooty  * Description:
85548c6a6b6SBharat Gooty  *	This function returns the SMBUS speed.
85648c6a6b6SBharat Gooty  *
85748c6a6b6SBharat Gooty  * Parameters:
85848c6a6b6SBharat Gooty  *	bus_id - I2C bus ID
85948c6a6b6SBharat Gooty  *
86048c6a6b6SBharat Gooty  * Return:
86148c6a6b6SBharat Gooty  *	Bus speed in Hz, 0 on failure
86248c6a6b6SBharat Gooty  */
i2c_get_bus_speed(uint32_t bus_id)86348c6a6b6SBharat Gooty uint32_t i2c_get_bus_speed(uint32_t bus_id)
86448c6a6b6SBharat Gooty {
86548c6a6b6SBharat Gooty 	uint32_t regval;
86648c6a6b6SBharat Gooty 	uint32_t retval = 0U;
86748c6a6b6SBharat Gooty 
86848c6a6b6SBharat Gooty 	regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG);
86948c6a6b6SBharat Gooty 	regval &= SMB_TIMGCFG_MODE400_MASK;
87048c6a6b6SBharat Gooty 	regval >>= SMB_TIMGCFG_MODE400_SHIFT;
87148c6a6b6SBharat Gooty 
87248c6a6b6SBharat Gooty 	switch (regval) {
87348c6a6b6SBharat Gooty 	case IPROC_SMB_SPEED_100KHz:
87448c6a6b6SBharat Gooty 		retval = I2C_SPEED_100KHz;
87548c6a6b6SBharat Gooty 		break;
87648c6a6b6SBharat Gooty 
87748c6a6b6SBharat Gooty 	case IPROC_SMB_SPEED_400KHz:
87848c6a6b6SBharat Gooty 		retval = I2C_SPEED_400KHz;
87948c6a6b6SBharat Gooty 		break;
88048c6a6b6SBharat Gooty 
88148c6a6b6SBharat Gooty 	default:
88248c6a6b6SBharat Gooty 		break;
88348c6a6b6SBharat Gooty 	}
88448c6a6b6SBharat Gooty 	return retval;
88548c6a6b6SBharat Gooty }
88648c6a6b6SBharat Gooty 
887