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