From: fengsheng <fengsheng5(a)huawei.com>
driver inclusion
category: feature
bugzilla: NA
CVE: NA
1. add interface: sysctl_pmbus_write_common
2. add interface: sysctl_pmbus_read_common
Signed-off-by: fengsheng <fengsheng5(a)huawei.com>
Reviewed-by: wuyang <wuyang7(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
---
drivers/soc/hisilicon/sysctl/sysctl_drv.c | 2 +-
drivers/soc/hisilicon/sysctl/sysctl_pmbus.c | 113 ++++++++++++++++++++++------
drivers/soc/hisilicon/sysctl/sysctl_pmbus.h | 16 ++++
3 files changed, 108 insertions(+), 23 deletions(-)
diff --git a/drivers/soc/hisilicon/sysctl/sysctl_drv.c b/drivers/soc/hisilicon/sysctl/sysctl_drv.c
index 3899fac..c4cb157 100644
--- a/drivers/soc/hisilicon/sysctl/sysctl_drv.c
+++ b/drivers/soc/hisilicon/sysctl/sysctl_drv.c
@@ -48,7 +48,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define DEBUG
-#define SYSCTL_DRIVER_VERSION "1.9.39.1"
+#define SYSCTL_DRIVER_VERSION "1.9.60.0"
unsigned int g_sysctrl_debug;
diff --git a/drivers/soc/hisilicon/sysctl/sysctl_pmbus.c b/drivers/soc/hisilicon/sysctl/sysctl_pmbus.c
index 74d06a8..92eeba6 100644
--- a/drivers/soc/hisilicon/sysctl/sysctl_pmbus.c
+++ b/drivers/soc/hisilicon/sysctl/sysctl_pmbus.c
@@ -190,6 +190,9 @@ int InitPmbus(u8 chip_id)
his_sysctrl_reg_wr(base, I2C_SS_SCL_HCNT_OFFSET, I2C_SS_SCLHCNT);
/* ulSclLow > 1.5us */
his_sysctrl_reg_wr(base, I2C_SS_SCL_LCNT_OFFSET, I2C_SS_SCLLCNT);
+ /* set sda_hold_fs 1us > 250ns */
+ his_sysctrl_reg_wr(base, I2C_SDA_HOLD_OFFSET, I2C_SS_SDA_HOLD_FS);
+
his_sysctrl_reg_wr(base, I2C_ENABLE_OFFSET, 0x1);
debug_sysctrl_print("Initialize Pmbus end\n");
@@ -233,35 +236,36 @@ int sysctl_pmbus_cfg(u8 chip_id, u8 addr, u8 page, u32 slave_addr)
return 0;
}
-int sysctl_pmbus_write(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 buf)
+int sysctl_pmbus_write_common(u8 chip_id, u32 slave_addr, u32 data_len, u8 *buf)
{
u32 i = 0;
u32 temp = 0;
u32 loop = 0x1000;
- u32 temp_data = addr;
+ u32 temp_data;
void __iomem *base = NULL;
if ((chip_id >= CHIP_ID_NUM_MAX) ||
- (data_len > DATA_NUM_MAX) ||
- (slave_addr >= SLAVE_ADDR_MAX)) {
+ (slave_addr >= SLAVE_ADDR_MAX) ||
+ (!data_len) || (data_len > PMBUS_WRITE_LEN_MAX) ||
+ (!buf)) {
pr_err("[sysctl pmbus] write param err,chipid=0x%x,data_len=0x%x,slave_addr=0x%x!\n",
chip_id, data_len, slave_addr);
return SYSCTL_ERR_PARAM;
}
+ /* clear all interrupt */
base = g_sysctl_pmbus_base[chip_id];
-
his_sysctrl_reg_wr(base, I2C_INTR_RAW_OFFSET, 0x3ffff);
+ /* send: slave_addr[7bit] + write[1bit] */
his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x2 << 0x8) | slave_addr);
- if (data_len != 0) {
- his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, addr);
- for (i = 0; i < data_len - 1; i++)
- his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, 0xff & (buf >> (i * 0x8)));
+ /* write data */
+ for (i = 0; i < data_len - 1; i++)
+ his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, buf[i]);
- temp_data = (0xff & (buf >> (i * 0x8)));
- }
+ /* last data should send stop */
+ temp_data = buf[i];
his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x4 << 0x8) | temp_data);
/* poll until send done */
@@ -273,14 +277,15 @@ int sysctl_pmbus_write(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 bu
/* send data failed */
if (temp & I2C_TX_ABRT) {
his_sysctrl_reg_rd(base, I2C_TX_ABRT_SRC_REG, &temp);
- pr_err("[sysctl pmbus]write data fail, chip_id:0x%x,slave_addr:0x%x, addr:0x%x!\r\n",
- chip_id, slave_addr, addr);
+ pr_err("[sysctl pmbus]write data fail, chip_id:0x%x,slave_addr:0x%x\r\n",
+ chip_id, slave_addr);
his_sysctrl_reg_rd(base, I2C_CLR_TX_ABRT_REG, &temp);
return SYSCTL_ERR_FAILED;
}
his_sysctrl_reg_rd(base, I2C_STATUS_REG, &temp);
+ /* send done */
if (temp & I2C_TX_FIFO_EMPTY) {
his_sysctrl_reg_rd(base, I2C_TX_FIFO_DATA_NUM_REG, &temp);
if (temp == 0)
@@ -289,8 +294,8 @@ int sysctl_pmbus_write(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 bu
loop--;
if (loop == 0) {
- pr_err("[sysctl pmbus]write data retry fail, chip_id:0x%x,slave_addr:0x%x, addr:0x%x!\r\n",
- chip_id, slave_addr, addr);
+ pr_err("[sysctl pmbus]write data retry fail, chip_id:0x%x,slave_addr:0x%x\r\n",
+ chip_id, slave_addr);
return SYSCTL_ERR_FAILED;
}
}
@@ -298,7 +303,25 @@ int sysctl_pmbus_write(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 bu
return SYSCTL_ERR_OK;
}
-static int sysctl_pmbus_read_pre(void __iomem *base, u8 addr, u32 slave_addr, u32 data_len)
+int sysctl_pmbus_write(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 buf)
+{
+#define TMP_LEN_MAX 5
+ u8 i;
+ u8 tmp[TMP_LEN_MAX] = {0};
+
+ if (data_len > DATA_NUM_MAX) {
+ pr_err("[sysctl pmbus] write param err,data_len=0x%x!\n", data_len);
+ return SYSCTL_ERR_PARAM;
+ }
+
+ tmp[0] = addr;
+ for (i = 0; i < data_len; i++)
+ tmp[i + 1] = (buf >> (i * 0x8)) & 0xff;
+
+ return sysctl_pmbus_write_common(chip_id, slave_addr, data_len + sizeof(addr), &tmp[0]);
+}
+
+static int sysctl_pmbus_read_pre(void __iomem *base, u32 cmd_len, u8 *cmd, u32 slave_addr, u32 data_len)
{
u32 i = 0;
u32 fifo_num = 0;
@@ -309,22 +332,29 @@ static int sysctl_pmbus_read_pre(void __iomem *base, u8 addr, u32 slave_addr, u3
return SYSCTL_ERR_PARAM;
}
+ /* clear all interrupt */
his_sysctrl_reg_wr(base, I2C_INTR_RAW_OFFSET, 0x3ffff);
+ /* clear rx fifo */
his_sysctrl_reg_rd(base, I2C_RXFLR_OFFSET, &fifo_num);
- debug_sysctrl_print("[sysctl_pmbus_read_byte]read pmbus , read empty rx fifo num:%d\r\n", fifo_num);
for (i = 0; i < fifo_num; i++)
his_sysctrl_reg_rd(base, I2C_DATA_CMD_OFFSET, &temp_byte);
- his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x2 << 0x8) | slave_addr);
- his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, addr);
- his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x3 << 0x8) | slave_addr);
+ /* send cmd */
+ if (cmd_len) {
+ his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x2 << 0x8) | slave_addr);
+ for (i = 0; i < cmd_len; i++)
+ his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, cmd[i]);
+ }
+ /* read data */
+ his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, (0x3 << 0x8) | slave_addr);
i = data_len;
while ((i - 1) > 0) {
his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, 0x100);
i--;
}
+ /* last data should send stop */
his_sysctrl_reg_wr(base, I2C_DATA_CMD_OFFSET, 0x500);
return 0;
@@ -366,6 +396,43 @@ static int sysctl_pmbus_wait_data(void __iomem *base, u32 data_len)
return SYSCTL_ERR_OK;
}
+int sysctl_pmbus_read_common(u8 chip_id, struct pmbus_read_op *op)
+{
+ u32 ret;
+ u32 i = 0;
+ u32 temp_byte = 0;
+ void __iomem *base = NULL;
+
+ if ((chip_id >= CHIP_ID_NUM_MAX) || (!op)) {
+ pr_err("[sysctl pmbus]read param err,chipid=0x%x!\n", chip_id);
+ return SYSCTL_ERR_PARAM;
+ }
+
+ if ((op->slave_addr >= SLAVE_ADDR_MAX) ||
+ (!op->data_len) || ((op->cmd_len + op->data_len) > PMBUS_READ_LEN_MAX) ||
+ (!op->data) || ((op->cmd_len) && (!op->cmd))) {
+ pr_err("[sysctl pmbus]read param err,data_len=0x%x,cmd_len=0x%x,slave_addr=0x%x\n",
+ op->data_len, op->cmd_len, op->slave_addr);
+ return SYSCTL_ERR_PARAM;
+ }
+
+ base = g_sysctl_pmbus_base[chip_id];
+ ret = sysctl_pmbus_read_pre(base, op->cmd_len, op->cmd, op->slave_addr, op->data_len);
+ if (ret != SYSCTL_ERR_OK)
+ return ret;
+
+ ret = sysctl_pmbus_wait_data(base, op->data_len);
+ if (ret != SYSCTL_ERR_OK)
+ return ret;
+
+ for (i = 0; i < op->data_len; i++) {
+ his_sysctrl_reg_rd(base, I2C_DATA_CMD_OFFSET, &temp_byte);
+ op->data[i] = temp_byte & 0xff;
+ }
+
+ return SYSCTL_ERR_OK;
+}
+
int sysctl_pmbus_read(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 *buf)
{
u32 ret;
@@ -385,7 +452,7 @@ int sysctl_pmbus_read(u8 chip_id, u8 addr, u32 slave_addr, u32 data_len, u32 *bu
base = g_sysctl_pmbus_base[chip_id];
- ret = sysctl_pmbus_read_pre(base, addr, slave_addr, data_len);
+ ret = sysctl_pmbus_read_pre(base, sizeof(addr), &addr, slave_addr, data_len);
if (ret != SYSCTL_ERR_OK)
return ret;
@@ -566,7 +633,7 @@ static int sysctl_cpu_convert_vol_to_vid(u32 vid_table, u32 value, u32 *vid)
return SYSCTL_ERR_OK;
}
-int sysctl_cpu_voltage_adjust (u8 chip_id, u8 loop, u32 slave_addr, u32 value)
+int sysctl_cpu_voltage_adjust(u8 chip_id, u8 loop, u32 slave_addr, u32 value)
{
u32 ret;
u32 vid;
@@ -647,5 +714,7 @@ void hip_sysctl_pmbus_exit(void)
EXPORT_SYMBOL(sysctl_cpu_voltage_adjust);
EXPORT_SYMBOL(sysctl_pmbus_write);
EXPORT_SYMBOL(sysctl_pmbus_read);
+EXPORT_SYMBOL(sysctl_pmbus_write_common);
+EXPORT_SYMBOL(sysctl_pmbus_read_common);
EXPORT_SYMBOL(InitPmbus);
EXPORT_SYMBOL(DeInitPmbus);
diff --git a/drivers/soc/hisilicon/sysctl/sysctl_pmbus.h b/drivers/soc/hisilicon/sysctl/sysctl_pmbus.h
index e1a4742..ce1d83d 100644
--- a/drivers/soc/hisilicon/sysctl/sysctl_pmbus.h
+++ b/drivers/soc/hisilicon/sysctl/sysctl_pmbus.h
@@ -20,6 +20,13 @@
#define PAGE_NUM_MAX (0x6f)
#define DATA_NUM_MAX (0x4)
+#define I2C_FIFO_DEPTH (256)
+
+/* slave_addr use 1 fifo */
+#define PMBUS_READ_LEN_MAX (I2C_FIFO_DEPTH - 1)
+/* slave_addr use 2 fifo */
+#define PMBUS_WRITE_LEN_MAX (I2C_FIFO_DEPTH - 2)
+
#define I2C_TX_ABRT (0x040)
#define I2C_TX_ABRT_SRC_REG (0x0880)
#define I2C_CLR_TX_ABRT_REG (0x0854)
@@ -29,6 +36,7 @@
#define I2C_SS_SCLHCNT 0x3db
#define I2C_SS_SCLLCNT 0x3e6
+#define I2C_SS_SDA_HOLD_FS 0xfa
/* AVS_REG_GEN */
#define AVS_WR_OPEN_OFFSET 0x0004
@@ -77,6 +85,14 @@
#define STATUS_RPT_OFFSET 0x0AA4
#define STATUS_ERR_RPT_OFFSET 0x0AA8
+struct pmbus_read_op {
+ u32 slave_addr;
+ u32 cmd_len;
+ u32 data_len;
+ u8 *cmd;
+ u8 *data;
+};
+
/* Define the union pmbus_vout_mode */
typedef union {
/* Define the struct bits */
--
1.8.3