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. */ 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. */ 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. */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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