From 70f59c90c8199e888b306edb16e20f651a1fce55 Mon Sep 17 00:00:00 2001 From: Mayulong Date: Mon, 17 Aug 2020 09:10:20 +0200 Subject: staging: spmi: add Hikey 970 SPMI controller driver Add the SPMI controller code required to use the Kirin 970 SPMI bus. [mchehab+huawei@kernel.org: added just the SPMI controller on this patch] The complete patch is at: https://github.com/96boards-hikey/linux/commit/08464419fba2 Signed-off-by: Mayulong Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/b4810f476e41e7de4efdf28b42472ae4ffe7defe.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 390 ++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c new file mode 100644 index 000000000000..987526c8b49f --- /dev/null +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -0,0 +1,390 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPMI_CONTROLLER_NAME "spmi_controller" + +/* + * SPMI register addr + */ +#define SPMI_CHANNEL_OFFSET 0x0300 +#define SPMI_SLAVE_OFFSET 0x20 + +#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100 +/*lint -e750 -esym(750,*)*/ +#define SPMI_APB_SPMI_WDATA0_BASE_ADDR 0x0104 +#define SPMI_APB_SPMI_WDATA1_BASE_ADDR 0x0108 +#define SPMI_APB_SPMI_WDATA2_BASE_ADDR 0x010c +#define SPMI_APB_SPMI_WDATA3_BASE_ADDR 0x0110 + +#define SPMI_APB_SPMI_STATUS_BASE_ADDR 0x0200 + +#define SPMI_APB_SPMI_RDATA0_BASE_ADDR 0x0204 +#define SPMI_APB_SPMI_RDATA1_BASE_ADDR 0x0208 +#define SPMI_APB_SPMI_RDATA2_BASE_ADDR 0x020c +#define SPMI_APB_SPMI_RDATA3_BASE_ADDR 0x0210 +/*lint +e750 -esym(750,*)*/ + +#define SPMI_PER_DATAREG_BYTE 4 +/* + * SPMI cmd register + */ +#define SPMI_APB_SPMI_CMD_EN (1 << 31) +#define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24 +#define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20 +#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 +#define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 + +#define Tranverse32(X) ((((u32)(X) & 0xff000000) >> 24) | \ + (((u32)(X) & 0x00ff0000) >> 8) | \ + (((u32)(X) & 0x0000ff00) << 8) | \ + (((u32)(X) & 0x000000ff) << 24)) + +/* Command Opcodes */ +/*lint -e749 -esym(749,*)*/ +enum spmi_controller_cmd_op_code { + SPMI_CMD_REG_ZERO_WRITE = 0, + SPMI_CMD_REG_WRITE = 1, + SPMI_CMD_REG_READ = 2, + SPMI_CMD_EXT_REG_WRITE = 3, + SPMI_CMD_EXT_REG_READ = 4, + SPMI_CMD_EXT_REG_WRITE_L = 5, + SPMI_CMD_EXT_REG_READ_L = 6, + SPMI_CMD_REG_RESET = 7, + SPMI_CMD_REG_SLEEP = 8, + SPMI_CMD_REG_SHUTDOWN = 9, + SPMI_CMD_REG_WAKEUP = 10, +}; +/*lint +e749 -esym(749,*)*/ + +/* + * SPMI status register + */ +#define SPMI_APB_TRANS_DONE (1 << 0) +#define SPMI_APB_TRANS_FAIL (1 << 2) + +/* Command register fields */ +#define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT 16 + +/* Maximum number of support PMIC peripherals */ +#define SPMI_CONTROLLER_TIMEOUT_US 1000 +#define SPMI_CONTROLLER_MAX_TRANS_BYTES (16) + +#define SPMI_WRITEL( dev, reg, addr ) \ + do { \ + writel( ( reg ), ( addr ) ); \ + } while (0) + +#define SPMI_READL( dev, reg, addr ) \ + do { \ + reg = readl( addr ); \ + } while (0) + +/* + * @base base address of the PMIC Arbiter core registers. + * @rdbase, @wrbase base address of the PMIC Arbiter read core registers. + * For HW-v1 these are equal to base. + * For HW-v2, the value is the same in eeraly probing, in order to read + * PMIC_ARB_CORE registers, then chnls, and obsrvr are set to + * PMIC_ARB_CORE_REGISTERS and PMIC_ARB_CORE_REGISTERS_OBS respectivly. + * @intr base address of the SPMI interrupt control registers + * @ppid_2_chnl_tbl lookup table f(SID, Periph-ID) -> channel num + * entry is only valid if corresponding bit is set in valid_ppid_bitmap. + * @valid_ppid_bitmap bit is set only for valid ppids. + * @fmt_cmd formats a command to be set into PMIC_ARBq_CHNLn_CMD + * @chnl_ofst calculates offset of the base of a channel reg space + * @ee execution environment id + * @irq_acc0_init_val initial value of the interrupt accumulator at probe time. + * Use for an HW workaround. On handling interrupts, the first accumulator + * register will be compared against this value, and bits which are set at + * boot will be ignored. + * @reserved_chnl entry of ppid_2_chnl_tbl that this driver should never touch. + * value is positive channel number or negative to mark it unused. + */ +struct spmi_controller_dev { + struct spmi_controller *controller; + struct device *dev; + void __iomem *base; + spinlock_t lock; + u32 channel; +}; + +static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, + void __iomem *base, u8 sid, u16 addr) +{ + u32 status = 0; + u32 timeout = SPMI_CONTROLLER_TIMEOUT_US; + u32 offset = SPMI_APB_SPMI_STATUS_BASE_ADDR + SPMI_CHANNEL_OFFSET * ctrl_dev->channel + + SPMI_SLAVE_OFFSET * sid; + + while (timeout--) { + SPMI_READL(ctrl_dev->dev, status, base + offset);/*lint !e732 */ + + if (status & SPMI_APB_TRANS_DONE) { + if (status & SPMI_APB_TRANS_FAIL) { + dev_err(ctrl_dev->dev, + "%s: transaction failed (0x%x)\n", + __func__, status); + return -EIO; + } + return 0; + } + udelay(1);/*lint !e778 !e774 !e747*/ + } + + dev_err(ctrl_dev->dev, + "%s: timeout, status 0x%x\n", + __func__, status); + return -ETIMEDOUT;/*lint !e438*/ +}/*lint !e715 !e529*/ + +static int spmi_read_cmd(struct spmi_controller *ctrl, + u8 opc, u8 sid, u16 addr, u8 *buf, size_t bc) +{ + struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); + unsigned long flags; + u32 cmd, data; + int rc; + u32 chnl_ofst = SPMI_CHANNEL_OFFSET*spmi_controller->channel; + u8 op_code, i; + + if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { + dev_err(spmi_controller->dev + , "spmi_controller supports 1..%d bytes per trans, but:%ld requested" + , SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); + return -EINVAL; + } + + /* Check the opcode */ + if (SPMI_CMD_READ == opc) + op_code = SPMI_CMD_REG_READ; + else if (SPMI_CMD_EXT_READ == opc) + op_code = SPMI_CMD_EXT_REG_READ; + else if (SPMI_CMD_EXT_READL == opc) + op_code = SPMI_CMD_EXT_REG_READ_L; + else { + dev_err(spmi_controller->dev, "invalid read cmd 0x%x", opc); + return -EINVAL; + } + + cmd = SPMI_APB_SPMI_CMD_EN |/*lint !e648 !e701 */ /* cmd_en */ + (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |/*lint !e648 !e701 */ /* cmd_type */ + ((bc-1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |/*lint !e648 !e701 */ /* byte_cnt */ + ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ + ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ + + spin_lock_irqsave(&spmi_controller->lock, flags);/*lint !e550 */ + + SPMI_WRITEL(spmi_controller->dev, cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); + + + rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); + if (rc) + goto done; + + i = 0; + do { + SPMI_READL(spmi_controller->dev, data, spmi_controller->base + chnl_ofst + SPMI_SLAVE_OFFSET*sid + SPMI_APB_SPMI_RDATA0_BASE_ADDR + i*SPMI_PER_DATAREG_BYTE);/*lint !e732 */ + data = Tranverse32(data); + if ((bc - i*SPMI_PER_DATAREG_BYTE ) >> 2) {/*lint !e702 */ + memcpy(buf, &data, sizeof(data)); + buf += sizeof(data); + } else { + memcpy(buf, &data, bc%SPMI_PER_DATAREG_BYTE);/*lint !e747 */ + buf += (bc%SPMI_PER_DATAREG_BYTE); + } + i++; + } while (bc > i*SPMI_PER_DATAREG_BYTE); + +done: + spin_unlock_irqrestore(&spmi_controller->lock, flags); + if (rc) + dev_err(spmi_controller->dev, "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", + opc, sid, addr, bc + 1); + return rc; +}/*lint !e550 !e529*/ + +/*lint -e438 -esym(438,*)*/ +static int spmi_write_cmd(struct spmi_controller *ctrl, + u8 opc, u8 sid, u16 addr, const u8 *buf, size_t bc) +{ + struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); + unsigned long flags; + u32 cmd; + u32 data = 0; + int rc; + u32 chnl_ofst = SPMI_CHANNEL_OFFSET*spmi_controller->channel; + u8 op_code, i; + + + if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { + dev_err(spmi_controller->dev + , "spmi_controller supports 1..%d bytes per trans, but:%ld requested" + , SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); + return -EINVAL; + } + + /* Check the opcode */ + if (SPMI_CMD_WRITE == opc) + op_code = SPMI_CMD_REG_WRITE; + else if (SPMI_CMD_EXT_WRITE == opc) + op_code = SPMI_CMD_EXT_REG_WRITE; + else if (SPMI_CMD_EXT_WRITEL == opc) + op_code = SPMI_CMD_EXT_REG_WRITE_L; + else { + dev_err(spmi_controller->dev, "invalid write cmd 0x%x", opc); + return -EINVAL; + } + + cmd = SPMI_APB_SPMI_CMD_EN |/*lint !e648 !e701 */ /* cmd_en */ + (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |/*lint !e648 !e701 */ /* cmd_type */ + ((bc-1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |/*lint !e648 !e701 */ /* byte_cnt */ + ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ + ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ + + /* Write data to FIFOs */ + spin_lock_irqsave(&spmi_controller->lock, flags);/*lint !e550 */ + + i = 0; + do { + memset(&data, 0, sizeof(data)); + if ((bc - i*SPMI_PER_DATAREG_BYTE ) >> 2) {/*lint !e702 */ + memcpy(&data, buf, sizeof(data)); + buf +=sizeof(data); + } else { + memcpy(&data, buf, bc%SPMI_PER_DATAREG_BYTE);/*lint !e747 */ + buf +=(bc%SPMI_PER_DATAREG_BYTE); + } + + data = Tranverse32(data); + SPMI_WRITEL(spmi_controller->dev, data, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR+SPMI_PER_DATAREG_BYTE*i); + i++; + } while (bc > i*SPMI_PER_DATAREG_BYTE); + + /* Start the transaction */ + SPMI_WRITEL(spmi_controller->dev, cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); + + rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); + spin_unlock_irqrestore(&spmi_controller->lock, flags); + + if (rc) + dev_err(spmi_controller->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", + opc, sid, addr, bc); + + return rc; +}/*lint !e438 !e550 !e529*/ +/*lint +e438 -esym(438,*)*/ +static int spmi_controller_probe(struct platform_device *pdev) +{ + struct spmi_controller_dev *spmi_controller; + struct spmi_controller *ctrl; + struct resource *iores; + int ret = 0; + + printk(KERN_INFO "HISI SPMI probe\n"); + ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller)); + if (!ctrl) { + dev_err(&pdev->dev, "can not allocate spmi_controller data\n"); + return -ENOMEM; /*lint !e429*/ + } + spmi_controller = spmi_controller_get_drvdata(ctrl); + spmi_controller->controller = ctrl; + + /* NOTE: driver uses the static register mapping */ + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iores) { + dev_err(&pdev->dev, "can not get resource! \n"); + return -EINVAL; /*lint !e429*/ + } + + spmi_controller->base = ioremap(iores->start, resource_size(iores)); + if (!spmi_controller->base) { + dev_err(&pdev->dev, "can not remap base addr! \n"); + return -EADDRNOTAVAIL; /*lint !e429*/ + } + dev_dbg(&pdev->dev, "spmi_add_controller base addr=0x%lx!\n", (long unsigned int)spmi_controller->base);/*lint !e774*/ + + /* Get properties from the device tree */ + ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", + &spmi_controller->channel);/*lint !e838*/ + if (ret) { + dev_err(&pdev->dev, "can not get chanel \n"); + return -ENODEV; /*lint !e429*/ + } + + platform_set_drvdata(pdev, spmi_controller); + dev_set_drvdata(&ctrl->dev, spmi_controller); + + spin_lock_init(&spmi_controller->lock); + + ctrl->nr = spmi_controller->channel; + ctrl->dev.parent = pdev->dev.parent; + ctrl->dev.of_node = of_node_get(pdev->dev.of_node); + + /* Callbacks */ + ctrl->read_cmd = spmi_read_cmd; + ctrl->write_cmd = spmi_write_cmd; + + ret = spmi_controller_add(ctrl); + if (ret) { + dev_err(&pdev->dev, "spmi_add_controller failed!\n"); + goto err_add_controller; + } +err_add_controller: + platform_set_drvdata(pdev, NULL); + return ret; /*lint !e429*/ +} + +static int spmi_del_controller(struct platform_device *pdev) +{ + struct spmi_controller *ctrl = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + spmi_controller_remove(ctrl); + return 0; +} + +static struct of_device_id spmi_controller_match_table[] = { + { .compatible = "hisilicon,spmi-controller", + },/*lint !e785*/ + {}/*lint !e785*/ +}; + +static struct platform_driver spmi_controller_driver = { + .probe = spmi_controller_probe, + .remove = spmi_del_controller, + .driver = { + .name = SPMI_CONTROLLER_NAME, + .owner = THIS_MODULE,/*lint !e64*/ + .of_match_table = spmi_controller_match_table, + },/*lint !e785*/ +};/*lint !e785*/ +/*lint -e528 -esym(528,*)*/ +static int __init spmi_controller_init(void) +{ + return platform_driver_register(&spmi_controller_driver);/*lint !e64*/ +} +postcore_initcall(spmi_controller_init); + +static void __exit spmi_controller_exit(void) +{ + platform_driver_unregister(&spmi_controller_driver); +} +module_exit(spmi_controller_exit); +/*lint -e753 -esym(753,*)*/ +MODULE_LICENSE("GPL v2"); +MODULE_VERSION("1.0");/*lint !e785 !e64 !e528*/ +MODULE_ALIAS("platform:spmi_controlller"); +/*lint -e753 +esym(753,*)*/ +/*lint -e528 +esym(528,*)*/ + -- cgit v1.2.3 From 2ea3f6a03b155f4df0cb9ee03557e7835928b646 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:21 +0200 Subject: staging: spmi: hisi-spmi-controller: coding style fixup In order to prepare for upstream, fix most coding style issues. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/3cd60dd31e481a4f824f7085d70fc243ecbbb94f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 179 +++++++++++------------- 1 file changed, 82 insertions(+), 97 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 987526c8b49f..3af0bd1b379f 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 #include #include @@ -21,7 +22,7 @@ #define SPMI_SLAVE_OFFSET 0x20 #define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100 -/*lint -e750 -esym(750,*)*/ + #define SPMI_APB_SPMI_WDATA0_BASE_ADDR 0x0104 #define SPMI_APB_SPMI_WDATA1_BASE_ADDR 0x0108 #define SPMI_APB_SPMI_WDATA2_BASE_ADDR 0x010c @@ -33,25 +34,25 @@ #define SPMI_APB_SPMI_RDATA1_BASE_ADDR 0x0208 #define SPMI_APB_SPMI_RDATA2_BASE_ADDR 0x020c #define SPMI_APB_SPMI_RDATA3_BASE_ADDR 0x0210 -/*lint +e750 -esym(750,*)*/ #define SPMI_PER_DATAREG_BYTE 4 /* * SPMI cmd register */ -#define SPMI_APB_SPMI_CMD_EN (1 << 31) +#define SPMI_APB_SPMI_CMD_EN BIT(31) #define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24 #define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20 #define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 #define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 -#define Tranverse32(X) ((((u32)(X) & 0xff000000) >> 24) | \ - (((u32)(X) & 0x00ff0000) >> 8) | \ - (((u32)(X) & 0x0000ff00) << 8) | \ - (((u32)(X) & 0x000000ff) << 24)) +#define bswap_32(X) \ + ((((u32)(X) & 0xff000000) >> 24) | \ + (((u32)(X) & 0x00ff0000) >> 8) | \ + (((u32)(X) & 0x0000ff00) << 8) | \ + (((u32)(X) & 0x000000ff) << 24)) /* Command Opcodes */ -/*lint -e749 -esym(749,*)*/ + enum spmi_controller_cmd_op_code { SPMI_CMD_REG_ZERO_WRITE = 0, SPMI_CMD_REG_WRITE = 1, @@ -65,13 +66,12 @@ enum spmi_controller_cmd_op_code { SPMI_CMD_REG_SHUTDOWN = 9, SPMI_CMD_REG_WAKEUP = 10, }; -/*lint +e749 -esym(749,*)*/ /* * SPMI status register */ -#define SPMI_APB_TRANS_DONE (1 << 0) -#define SPMI_APB_TRANS_FAIL (1 << 2) +#define SPMI_APB_TRANS_DONE BIT(0) +#define SPMI_APB_TRANS_FAIL BIT(2) /* Command register fields */ #define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT 16 @@ -80,16 +80,6 @@ enum spmi_controller_cmd_op_code { #define SPMI_CONTROLLER_TIMEOUT_US 1000 #define SPMI_CONTROLLER_MAX_TRANS_BYTES (16) -#define SPMI_WRITEL( dev, reg, addr ) \ - do { \ - writel( ( reg ), ( addr ) ); \ - } while (0) - -#define SPMI_READL( dev, reg, addr ) \ - do { \ - reg = readl( addr ); \ - } while (0) - /* * @base base address of the PMIC Arbiter core registers. * @rdbase, @wrbase base address of the PMIC Arbiter read core registers. @@ -120,7 +110,7 @@ struct spmi_controller_dev { }; static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, - void __iomem *base, u8 sid, u16 addr) + void __iomem *base, u8 sid, u16 addr) { u32 status = 0; u32 timeout = SPMI_CONTROLLER_TIMEOUT_US; @@ -128,7 +118,7 @@ static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, + SPMI_SLAVE_OFFSET * sid; while (timeout--) { - SPMI_READL(ctrl_dev->dev, status, base + offset);/*lint !e732 */ + status = readl(base + offset); if (status & SPMI_APB_TRANS_DONE) { if (status & SPMI_APB_TRANS_FAIL) { @@ -139,23 +129,23 @@ static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, } return 0; } - udelay(1);/*lint !e778 !e774 !e747*/ + udelay(1); } dev_err(ctrl_dev->dev, "%s: timeout, status 0x%x\n", __func__, status); - return -ETIMEDOUT;/*lint !e438*/ -}/*lint !e715 !e529*/ + return -ETIMEDOUT; +} static int spmi_read_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, u8 *buf, size_t bc) + u8 opc, u8 sid, u16 addr, u8 *buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); unsigned long flags; u32 cmd, data; int rc; - u32 chnl_ofst = SPMI_CHANNEL_OFFSET*spmi_controller->channel; + u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; u8 op_code, i; if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { @@ -166,27 +156,26 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, } /* Check the opcode */ - if (SPMI_CMD_READ == opc) + if (opc == SPMI_CMD_READ) { op_code = SPMI_CMD_REG_READ; - else if (SPMI_CMD_EXT_READ == opc) + } else if (opc == SPMI_CMD_EXT_READ) { op_code = SPMI_CMD_EXT_REG_READ; - else if (SPMI_CMD_EXT_READL == opc) + } else if (opc == SPMI_CMD_EXT_READL) { op_code = SPMI_CMD_EXT_REG_READ_L; - else { + } else { dev_err(spmi_controller->dev, "invalid read cmd 0x%x", opc); return -EINVAL; } - cmd = SPMI_APB_SPMI_CMD_EN |/*lint !e648 !e701 */ /* cmd_en */ - (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |/*lint !e648 !e701 */ /* cmd_type */ - ((bc-1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |/*lint !e648 !e701 */ /* byte_cnt */ - ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ - ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ - - spin_lock_irqsave(&spmi_controller->lock, flags);/*lint !e550 */ + cmd = SPMI_APB_SPMI_CMD_EN | + (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) | + ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) | + ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ + ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ - SPMI_WRITEL(spmi_controller->dev, cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); + spin_lock_irqsave(&spmi_controller->lock, flags); + writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); if (rc) @@ -194,39 +183,37 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, i = 0; do { - SPMI_READL(spmi_controller->dev, data, spmi_controller->base + chnl_ofst + SPMI_SLAVE_OFFSET*sid + SPMI_APB_SPMI_RDATA0_BASE_ADDR + i*SPMI_PER_DATAREG_BYTE);/*lint !e732 */ - data = Tranverse32(data); - if ((bc - i*SPMI_PER_DATAREG_BYTE ) >> 2) {/*lint !e702 */ + data = readl(spmi_controller->base + chnl_ofst + SPMI_SLAVE_OFFSET * sid + SPMI_APB_SPMI_RDATA0_BASE_ADDR + i * SPMI_PER_DATAREG_BYTE); + data = bswap_32(data); + if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(buf, &data, sizeof(data)); buf += sizeof(data); } else { - memcpy(buf, &data, bc%SPMI_PER_DATAREG_BYTE);/*lint !e747 */ - buf += (bc%SPMI_PER_DATAREG_BYTE); + memcpy(buf, &data, bc % SPMI_PER_DATAREG_BYTE); + buf += (bc % SPMI_PER_DATAREG_BYTE); } i++; - } while (bc > i*SPMI_PER_DATAREG_BYTE); + } while (bc > i * SPMI_PER_DATAREG_BYTE); done: spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) dev_err(spmi_controller->dev, "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", - opc, sid, addr, bc + 1); + opc, sid, addr, bc + 1); return rc; -}/*lint !e550 !e529*/ +} -/*lint -e438 -esym(438,*)*/ static int spmi_write_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, const u8 *buf, size_t bc) + u8 opc, u8 sid, u16 addr, const u8 *buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); unsigned long flags; u32 cmd; u32 data = 0; int rc; - u32 chnl_ofst = SPMI_CHANNEL_OFFSET*spmi_controller->channel; + u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; u8 op_code, i; - if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { dev_err(spmi_controller->dev , "spmi_controller supports 1..%d bytes per trans, but:%ld requested" @@ -235,55 +222,55 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, } /* Check the opcode */ - if (SPMI_CMD_WRITE == opc) + if (opc == SPMI_CMD_WRITE) { op_code = SPMI_CMD_REG_WRITE; - else if (SPMI_CMD_EXT_WRITE == opc) + } else if (opc == SPMI_CMD_EXT_WRITE) { op_code = SPMI_CMD_EXT_REG_WRITE; - else if (SPMI_CMD_EXT_WRITEL == opc) + } else if (opc == SPMI_CMD_EXT_WRITEL) { op_code = SPMI_CMD_EXT_REG_WRITE_L; - else { + } else { dev_err(spmi_controller->dev, "invalid write cmd 0x%x", opc); return -EINVAL; } - cmd = SPMI_APB_SPMI_CMD_EN |/*lint !e648 !e701 */ /* cmd_en */ - (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) |/*lint !e648 !e701 */ /* cmd_type */ - ((bc-1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) |/*lint !e648 !e701 */ /* byte_cnt */ - ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ - ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ + cmd = SPMI_APB_SPMI_CMD_EN | + (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) | + ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) | + ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ + ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ /* Write data to FIFOs */ - spin_lock_irqsave(&spmi_controller->lock, flags);/*lint !e550 */ + spin_lock_irqsave(&spmi_controller->lock, flags); i = 0; do { memset(&data, 0, sizeof(data)); - if ((bc - i*SPMI_PER_DATAREG_BYTE ) >> 2) {/*lint !e702 */ + if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(&data, buf, sizeof(data)); - buf +=sizeof(data); + buf += sizeof(data); } else { - memcpy(&data, buf, bc%SPMI_PER_DATAREG_BYTE);/*lint !e747 */ - buf +=(bc%SPMI_PER_DATAREG_BYTE); + memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE); + buf += (bc % SPMI_PER_DATAREG_BYTE); } - data = Tranverse32(data); - SPMI_WRITEL(spmi_controller->dev, data, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR+SPMI_PER_DATAREG_BYTE*i); + data = bswap_32(data); + writel(data, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR + SPMI_PER_DATAREG_BYTE * i); i++; - } while (bc > i*SPMI_PER_DATAREG_BYTE); + } while (bc > i * SPMI_PER_DATAREG_BYTE); /* Start the transaction */ - SPMI_WRITEL(spmi_controller->dev, cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); + writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) dev_err(spmi_controller->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", - opc, sid, addr, bc); + opc, sid, addr, bc); return rc; -}/*lint !e438 !e550 !e529*/ -/*lint +e438 -esym(438,*)*/ +} + static int spmi_controller_probe(struct platform_device *pdev) { struct spmi_controller_dev *spmi_controller; @@ -291,11 +278,11 @@ static int spmi_controller_probe(struct platform_device *pdev) struct resource *iores; int ret = 0; - printk(KERN_INFO "HISI SPMI probe\n"); + dev_info(&pdev->dev, "HISI SPMI probe\n"); ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller)); if (!ctrl) { dev_err(&pdev->dev, "can not allocate spmi_controller data\n"); - return -ENOMEM; /*lint !e429*/ + return -ENOMEM; } spmi_controller = spmi_controller_get_drvdata(ctrl); spmi_controller->controller = ctrl; @@ -303,23 +290,24 @@ static int spmi_controller_probe(struct platform_device *pdev) /* NOTE: driver uses the static register mapping */ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iores) { - dev_err(&pdev->dev, "can not get resource! \n"); - return -EINVAL; /*lint !e429*/ + dev_err(&pdev->dev, "can not get resource!\n"); + return -EINVAL; } spmi_controller->base = ioremap(iores->start, resource_size(iores)); if (!spmi_controller->base) { - dev_err(&pdev->dev, "can not remap base addr! \n"); - return -EADDRNOTAVAIL; /*lint !e429*/ + dev_err(&pdev->dev, "can not remap base addr!\n"); + return -EADDRNOTAVAIL; } - dev_dbg(&pdev->dev, "spmi_add_controller base addr=0x%lx!\n", (long unsigned int)spmi_controller->base);/*lint !e774*/ + dev_dbg(&pdev->dev, "spmi_add_controller base addr=0x%lx!\n", + (unsigned long)spmi_controller->base); /* Get properties from the device tree */ ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", - &spmi_controller->channel);/*lint !e838*/ + &spmi_controller->channel); if (ret) { - dev_err(&pdev->dev, "can not get chanel \n"); - return -ENODEV; /*lint !e429*/ + dev_err(&pdev->dev, "can not get chanel\n"); + return -ENODEV; } platform_set_drvdata(pdev, spmi_controller); @@ -342,7 +330,7 @@ static int spmi_controller_probe(struct platform_device *pdev) } err_add_controller: platform_set_drvdata(pdev, NULL); - return ret; /*lint !e429*/ + return ret; } static int spmi_del_controller(struct platform_device *pdev) @@ -354,10 +342,10 @@ static int spmi_del_controller(struct platform_device *pdev) return 0; } -static struct of_device_id spmi_controller_match_table[] = { +static const struct of_device_id spmi_controller_match_table[] = { { .compatible = "hisilicon,spmi-controller", - },/*lint !e785*/ - {}/*lint !e785*/ + }, + {} }; static struct platform_driver spmi_controller_driver = { @@ -365,14 +353,14 @@ static struct platform_driver spmi_controller_driver = { .remove = spmi_del_controller, .driver = { .name = SPMI_CONTROLLER_NAME, - .owner = THIS_MODULE,/*lint !e64*/ + .owner = THIS_MODULE, .of_match_table = spmi_controller_match_table, - },/*lint !e785*/ -};/*lint !e785*/ -/*lint -e528 -esym(528,*)*/ + }, +}; + static int __init spmi_controller_init(void) { - return platform_driver_register(&spmi_controller_driver);/*lint !e64*/ + return platform_driver_register(&spmi_controller_driver); } postcore_initcall(spmi_controller_init); @@ -381,10 +369,7 @@ static void __exit spmi_controller_exit(void) platform_driver_unregister(&spmi_controller_driver); } module_exit(spmi_controller_exit); -/*lint -e753 -esym(753,*)*/ + MODULE_LICENSE("GPL v2"); -MODULE_VERSION("1.0");/*lint !e785 !e64 !e528*/ +MODULE_VERSION("1.0"); MODULE_ALIAS("platform:spmi_controlller"); -/*lint -e753 +esym(753,*)*/ -/*lint -e528 +esym(528,*)*/ - -- cgit v1.2.3 From 85eb5344f2c91502229ebb79f2af9eb37130ceac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:22 +0200 Subject: staging: spmi: hisi-spmi-controller: fix it to probe successfully Add a MODULE_DEVICE_TABLE() to the driver. Also, the current logic calls platform_set_drvdata(pdev, NULL) if the driver succeeds loading. While here, remove the .owner, as it is not needed upstream anymore. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/122bd1c02f325094f4830ac79a86430fbe01e3d5.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 3af0bd1b379f..bc6847f9a5e7 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -324,11 +324,14 @@ static int spmi_controller_probe(struct platform_device *pdev) ctrl->write_cmd = spmi_write_cmd; ret = spmi_controller_add(ctrl); - if (ret) { - dev_err(&pdev->dev, "spmi_add_controller failed!\n"); + if (ret) goto err_add_controller; - } + + dev_info(&pdev->dev, "spmi_add_controller initialized\n"); + return 0; + err_add_controller: + dev_err(&pdev->dev, "spmi_add_controller failed!\n"); platform_set_drvdata(pdev, NULL); return ret; } @@ -347,13 +350,13 @@ static const struct of_device_id spmi_controller_match_table[] = { }, {} }; +MODULE_DEVICE_TABLE(of, spmi_controller_match_table); static struct platform_driver spmi_controller_driver = { .probe = spmi_controller_probe, .remove = spmi_del_controller, .driver = { .name = SPMI_CONTROLLER_NAME, - .owner = THIS_MODULE, .of_match_table = spmi_controller_match_table, }, }; -- cgit v1.2.3 From 6196331e79f361b9c395b45588fbbb9e8de8a990 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:23 +0200 Subject: staging: spmi: hisi-spmi-controller: fix a typo chanel -> channel Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/49798ac555d498c0fd489567643c619c625360f5.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index bc6847f9a5e7..99cf757d76fe 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -306,7 +306,7 @@ static int spmi_controller_probe(struct platform_device *pdev) ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", &spmi_controller->channel); if (ret) { - dev_err(&pdev->dev, "can not get chanel\n"); + dev_err(&pdev->dev, "can not get channel\n"); return -ENODEV; } -- cgit v1.2.3 From 974e3bdc187e68b5652ad57c8d1844e24884cb89 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:24 +0200 Subject: staging: spmi: hisi-spmi-controller: adjust whitespaces at defines Some defines are not aligned with tab=8, which is the style defined on Linux. Adjust them. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/4a3799b40379dbc3abcbd08827977247ccc26dcb.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 99cf757d76fe..7fae267a6062 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -18,10 +18,10 @@ /* * SPMI register addr */ -#define SPMI_CHANNEL_OFFSET 0x0300 -#define SPMI_SLAVE_OFFSET 0x20 +#define SPMI_CHANNEL_OFFSET 0x0300 +#define SPMI_SLAVE_OFFSET 0x20 -#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100 +#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100 #define SPMI_APB_SPMI_WDATA0_BASE_ADDR 0x0104 #define SPMI_APB_SPMI_WDATA1_BASE_ADDR 0x0108 @@ -35,21 +35,21 @@ #define SPMI_APB_SPMI_RDATA2_BASE_ADDR 0x020c #define SPMI_APB_SPMI_RDATA3_BASE_ADDR 0x0210 -#define SPMI_PER_DATAREG_BYTE 4 +#define SPMI_PER_DATAREG_BYTE 4 /* * SPMI cmd register */ -#define SPMI_APB_SPMI_CMD_EN BIT(31) +#define SPMI_APB_SPMI_CMD_EN BIT(31) #define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24 #define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20 -#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 -#define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 #define bswap_32(X) \ ((((u32)(X) & 0xff000000) >> 24) | \ (((u32)(X) & 0x00ff0000) >> 8) | \ (((u32)(X) & 0x0000ff00) << 8) | \ (((u32)(X) & 0x000000ff) << 24)) +#define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 +#define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 /* Command Opcodes */ @@ -70,15 +70,15 @@ enum spmi_controller_cmd_op_code { /* * SPMI status register */ -#define SPMI_APB_TRANS_DONE BIT(0) -#define SPMI_APB_TRANS_FAIL BIT(2) +#define SPMI_APB_TRANS_DONE BIT(0) +#define SPMI_APB_TRANS_FAIL BIT(2) /* Command register fields */ #define SPMI_CONTROLLER_CMD_MAX_BYTE_COUNT 16 /* Maximum number of support PMIC peripherals */ #define SPMI_CONTROLLER_TIMEOUT_US 1000 -#define SPMI_CONTROLLER_MAX_TRANS_BYTES (16) +#define SPMI_CONTROLLER_MAX_TRANS_BYTES 16 /* * @base base address of the PMIC Arbiter core registers. @@ -114,8 +114,10 @@ static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, { u32 status = 0; u32 timeout = SPMI_CONTROLLER_TIMEOUT_US; - u32 offset = SPMI_APB_SPMI_STATUS_BASE_ADDR + SPMI_CHANNEL_OFFSET * ctrl_dev->channel - + SPMI_SLAVE_OFFSET * sid; + u32 offset; + + offset = SPMI_APB_SPMI_STATUS_BASE_ADDR; + offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid; while (timeout--) { status = readl(base + offset); -- cgit v1.2.3 From 8788a30c12c78846c153bea06125296111f53ece Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:25 +0200 Subject: staging: spmi: hisi-spmi-controller: use le32 macros where needed Instead of manually using bswap_32(), just use the le32 macros. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/927ac4f981649318dba399e46a1aa429c428cfa3.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 7fae267a6062..cacd28150b49 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -11,7 +11,6 @@ #include #include #include -#include #define SPMI_CONTROLLER_NAME "spmi_controller" @@ -43,11 +42,6 @@ #define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24 #define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20 -#define bswap_32(X) \ - ((((u32)(X) & 0xff000000) >> 24) | \ - (((u32)(X) & 0x00ff0000) >> 8) | \ - (((u32)(X) & 0x0000ff00) << 8) | \ - (((u32)(X) & 0x000000ff) << 24)) #define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 #define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 @@ -179,14 +173,15 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); - rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); + rc = spmi_controller_wait_for_done(spmi_controller, + spmi_controller->base, sid, addr); if (rc) goto done; i = 0; do { data = readl(spmi_controller->base + chnl_ofst + SPMI_SLAVE_OFFSET * sid + SPMI_APB_SPMI_RDATA0_BASE_ADDR + i * SPMI_PER_DATAREG_BYTE); - data = bswap_32(data); + data = be32_to_cpu((__be32)data); if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(buf, &data, sizeof(data)); buf += sizeof(data); @@ -210,8 +205,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); unsigned long flags; - u32 cmd; - u32 data = 0; + u32 cmd, data; int rc; u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; u8 op_code, i; @@ -246,7 +240,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, i = 0; do { - memset(&data, 0, sizeof(data)); + data = 0; if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(&data, buf, sizeof(data)); buf += sizeof(data); @@ -255,8 +249,8 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, buf += (bc % SPMI_PER_DATAREG_BYTE); } - data = bswap_32(data); - writel(data, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR + SPMI_PER_DATAREG_BYTE * i); + writel((u32)cpu_to_be32(data), + spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR + SPMI_PER_DATAREG_BYTE * i); i++; } while (bc > i * SPMI_PER_DATAREG_BYTE); -- cgit v1.2.3 From 6af364501949d9978252a5c0d4f2363f1cf45dcc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:26 +0200 Subject: staging: spmi: hisi-spmi-controller: add debug when values are read/write It is interesting to be able to check if the driver is doing the right thing. So, add some debug macros to allow checking it. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/11dc4583c41a9c5e2804114d6a7a87374d2a23b4.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index cacd28150b49..e996114bc717 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -41,7 +41,6 @@ #define SPMI_APB_SPMI_CMD_EN BIT(31) #define SPMI_APB_SPMI_CMD_TYPE_OFFSET 24 #define SPMI_APB_SPMI_CMD_LENGTH_OFFSET 20 - #define SPMI_APB_SPMI_CMD_SLAVEID_OFFSET 16 #define SPMI_APB_SPMI_CMD_ADDR_OFFSET 0 @@ -135,10 +134,11 @@ static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, } static int spmi_read_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, u8 *buf, size_t bc) + u8 opc, u8 sid, u16 addr, u8 *__buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); unsigned long flags; + u8 *buf = __buf; u32 cmd, data; int rc; u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; @@ -197,13 +197,18 @@ done: if (rc) dev_err(spmi_controller->dev, "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", opc, sid, addr, bc + 1); + else + dev_dbg(spmi_controller->dev, "%s: id:%d addr:0x%x, read value: %*ph\n", + __func__, sid, addr, (int)bc, __buf); + return rc; } static int spmi_write_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, const u8 *buf, size_t bc) + u8 opc, u8 sid, u16 addr, const u8 *__buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); + const u8 *buf = __buf; unsigned long flags; u32 cmd, data; int rc; @@ -263,6 +268,9 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, if (rc) dev_err(spmi_controller->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", opc, sid, addr, bc); + else + dev_dbg(spmi_controller->dev, "%s: id:%d addr:0x%x, wrote value: %*ph\n", + __func__, sid, addr, (int)bc, __buf); return rc; } @@ -275,6 +283,7 @@ static int spmi_controller_probe(struct platform_device *pdev) int ret = 0; dev_info(&pdev->dev, "HISI SPMI probe\n"); + ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller)); if (!ctrl) { dev_err(&pdev->dev, "can not allocate spmi_controller data\n"); -- cgit v1.2.3 From 4d914a8c480c31280505304611030612fa5c2645 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:27 +0200 Subject: staging: spmi: hisi-spmi-controller: fix the dev_foo() logic Right now, driver is printing some messages as: [ 33.833026] (NULL device *): spmi_read_cmd: id:0 addr:0x17, read value: 00 This is because dev_foo() are not using a device with a name set. Change the logic for it to print it right. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/f647600d6e709f3dc3f92a64f1788f739c924330.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 41 +++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index e996114bc717..153bcdb0cde4 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -102,7 +102,8 @@ struct spmi_controller_dev { u32 channel; }; -static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, +static int spmi_controller_wait_for_done(struct device *dev, + struct spmi_controller_dev *ctrl_dev, void __iomem *base, u8 sid, u16 addr) { u32 status = 0; @@ -117,19 +118,17 @@ static int spmi_controller_wait_for_done(struct spmi_controller_dev *ctrl_dev, if (status & SPMI_APB_TRANS_DONE) { if (status & SPMI_APB_TRANS_FAIL) { - dev_err(ctrl_dev->dev, - "%s: transaction failed (0x%x)\n", + dev_err(dev, "%s: transaction failed (0x%x)\n", __func__, status); return -EIO; } + dev_dbg(dev, "%s: status 0x%x\n", __func__, status); return 0; } udelay(1); } - dev_err(ctrl_dev->dev, - "%s: timeout, status 0x%x\n", - __func__, status); + dev_err(dev, "%s: timeout, status 0x%x\n", __func__, status); return -ETIMEDOUT; } @@ -145,9 +144,9 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, u8 op_code, i; if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { - dev_err(spmi_controller->dev - , "spmi_controller supports 1..%d bytes per trans, but:%ld requested" - , SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); + dev_err(&ctrl->dev, + "spmi_controller supports 1..%d bytes per trans, but:%ld requested", + SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } @@ -159,7 +158,7 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, } else if (opc == SPMI_CMD_EXT_READL) { op_code = SPMI_CMD_EXT_REG_READ_L; } else { - dev_err(spmi_controller->dev, "invalid read cmd 0x%x", opc); + dev_err(&ctrl->dev, "invalid read cmd 0x%x", opc); return -EINVAL; } @@ -173,7 +172,7 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); - rc = spmi_controller_wait_for_done(spmi_controller, + rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller, spmi_controller->base, sid, addr); if (rc) goto done; @@ -195,10 +194,11 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, done: spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) - dev_err(spmi_controller->dev, "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", + dev_err(&ctrl->dev, + "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", opc, sid, addr, bc + 1); else - dev_dbg(spmi_controller->dev, "%s: id:%d addr:0x%x, read value: %*ph\n", + dev_dbg(&ctrl->dev, "%s: id:%d addr:0x%x, read value: %*ph\n", __func__, sid, addr, (int)bc, __buf); return rc; @@ -216,9 +216,9 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, u8 op_code, i; if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { - dev_err(spmi_controller->dev - , "spmi_controller supports 1..%d bytes per trans, but:%ld requested" - , SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); + dev_err(&ctrl->dev, + "spmi_controller supports 1..%d bytes per trans, but:%ld requested", + SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } @@ -230,7 +230,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, } else if (opc == SPMI_CMD_EXT_WRITEL) { op_code = SPMI_CMD_EXT_REG_WRITE_L; } else { - dev_err(spmi_controller->dev, "invalid write cmd 0x%x", opc); + dev_err(&ctrl->dev, "invalid write cmd 0x%x", opc); return -EINVAL; } @@ -262,14 +262,15 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, /* Start the transaction */ writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); - rc = spmi_controller_wait_for_done(spmi_controller, spmi_controller->base, sid, addr); + rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller, + spmi_controller->base, sid, addr); spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) - dev_err(spmi_controller->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", + dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", opc, sid, addr, bc); else - dev_dbg(spmi_controller->dev, "%s: id:%d addr:0x%x, wrote value: %*ph\n", + dev_dbg(&ctrl->dev, "%s: id:%d addr:0x%x, wrote value: %*ph\n", __func__, sid, addr, (int)bc, __buf); return rc; -- cgit v1.2.3 From 1747938a37d1dfa9faa397507f88627158b3d806 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:28 +0200 Subject: staging: spmi: hisi-spmi-controller: add it to the building system Now that the driver was ported to upstream, add it as a SPMI controller. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5315331cf048cc72844080e5e8668c0dbac48f1f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + drivers/staging/hikey9xx/Kconfig | 10 ++++++++++ drivers/staging/hikey9xx/Makefile | 3 +++ 4 files changed, 16 insertions(+) create mode 100644 drivers/staging/hikey9xx/Kconfig create mode 100644 drivers/staging/hikey9xx/Makefile (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index e6c831c6cccc..2d0310448eba 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -116,4 +116,6 @@ source "drivers/staging/qlge/Kconfig" source "drivers/staging/wfx/Kconfig" +source "drivers/staging/hikey9xx/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a3b1fd0622f9..757a892ab5b9 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -48,3 +48,4 @@ obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/ obj-$(CONFIG_KPC2000) += kpc2000/ obj-$(CONFIG_QLGE) += qlge/ obj-$(CONFIG_WFX) += wfx/ +obj-y += hikey9xx/ diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig new file mode 100644 index 000000000000..31eb01b5ef2b --- /dev/null +++ b/drivers/staging/hikey9xx/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 + +config SPMI_HISI3670 + tristate "Hisilicon 3670 SPMI Controller" + select IRQ_DOMAIN_HIERARCHY + depends on HAS_IOMEM + help + If you say yes to this option, support will be included for the + built-in SPMI PMIC Arbiter interface on Hisilicon 3670 + processors. diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile new file mode 100644 index 000000000000..e8085abce444 --- /dev/null +++ b/drivers/staging/hikey9xx/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o -- cgit v1.2.3 From 7f3ac6c502fd7ff301dbf21011d9db9deaf94f76 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:29 +0200 Subject: staging: spmi: hisi-spmi-controller: do some code cleanups There are several minor things that can be cleanup in order to make this driver more prepared for leaving staging. Suggested-by: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/1fa33567e21f95942d901a299d92e434d4a24b8f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 150 ++++++++++-------------- 1 file changed, 61 insertions(+), 89 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 153bcdb0cde4..513d962b8bce 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -2,18 +2,16 @@ #include #include +#include #include #include -#include -#include -#include -#include #include +#include +#include #include +#include #include -#define SPMI_CONTROLLER_NAME "spmi_controller" - /* * SPMI register addr */ @@ -73,27 +71,6 @@ enum spmi_controller_cmd_op_code { #define SPMI_CONTROLLER_TIMEOUT_US 1000 #define SPMI_CONTROLLER_MAX_TRANS_BYTES 16 -/* - * @base base address of the PMIC Arbiter core registers. - * @rdbase, @wrbase base address of the PMIC Arbiter read core registers. - * For HW-v1 these are equal to base. - * For HW-v2, the value is the same in eeraly probing, in order to read - * PMIC_ARB_CORE registers, then chnls, and obsrvr are set to - * PMIC_ARB_CORE_REGISTERS and PMIC_ARB_CORE_REGISTERS_OBS respectivly. - * @intr base address of the SPMI interrupt control registers - * @ppid_2_chnl_tbl lookup table f(SID, Periph-ID) -> channel num - * entry is only valid if corresponding bit is set in valid_ppid_bitmap. - * @valid_ppid_bitmap bit is set only for valid ppids. - * @fmt_cmd formats a command to be set into PMIC_ARBq_CHNLn_CMD - * @chnl_ofst calculates offset of the base of a channel reg space - * @ee execution environment id - * @irq_acc0_init_val initial value of the interrupt accumulator at probe time. - * Use for an HW workaround. On handling interrupts, the first accumulator - * register will be compared against this value, and bits which are set at - * boot will be ignored. - * @reserved_chnl entry of ppid_2_chnl_tbl that this driver should never touch. - * value is positive channel number or negative to mark it unused. - */ struct spmi_controller_dev { struct spmi_controller *controller; struct device *dev; @@ -106,14 +83,13 @@ static int spmi_controller_wait_for_done(struct device *dev, struct spmi_controller_dev *ctrl_dev, void __iomem *base, u8 sid, u16 addr) { - u32 status = 0; u32 timeout = SPMI_CONTROLLER_TIMEOUT_US; - u32 offset; + u32 status, offset; offset = SPMI_APB_SPMI_STATUS_BASE_ADDR; offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid; - while (timeout--) { + do { status = readl(base + offset); if (status & SPMI_APB_TRANS_DONE) { @@ -126,60 +102,65 @@ static int spmi_controller_wait_for_done(struct device *dev, return 0; } udelay(1); - } + } while (timeout--); dev_err(dev, "%s: timeout, status 0x%x\n", __func__, status); return -ETIMEDOUT; } static int spmi_read_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, u8 *__buf, size_t bc) + u8 opc, u8 slave_id, u16 slave_addr, u8 *__buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); + u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; unsigned long flags; u8 *buf = __buf; u32 cmd, data; int rc; - u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; u8 op_code, i; if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, - "spmi_controller supports 1..%d bytes per trans, but:%ld requested", + "spmi_controller supports 1..%d bytes per trans, but:%ld requested\n", SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } - /* Check the opcode */ - if (opc == SPMI_CMD_READ) { + switch (opc) { + case SPMI_CMD_READ: op_code = SPMI_CMD_REG_READ; - } else if (opc == SPMI_CMD_EXT_READ) { + break; + case SPMI_CMD_EXT_READ: op_code = SPMI_CMD_EXT_REG_READ; - } else if (opc == SPMI_CMD_EXT_READL) { + break; + case SPMI_CMD_EXT_READL: op_code = SPMI_CMD_EXT_REG_READ_L; - } else { - dev_err(&ctrl->dev, "invalid read cmd 0x%x", opc); + break; + default: + dev_err(&ctrl->dev, "invalid read cmd 0x%x\n", opc); return -EINVAL; } cmd = SPMI_APB_SPMI_CMD_EN | (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) | ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) | - ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ - ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ + ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ + ((slave_addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ spin_lock_irqsave(&spmi_controller->lock, flags); writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller, - spmi_controller->base, sid, addr); + spmi_controller->base, slave_id, slave_addr); if (rc) goto done; - i = 0; - do { - data = readl(spmi_controller->base + chnl_ofst + SPMI_SLAVE_OFFSET * sid + SPMI_APB_SPMI_RDATA0_BASE_ADDR + i * SPMI_PER_DATAREG_BYTE); + for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) { + data = readl(spmi_controller->base + chnl_ofst + + SPMI_SLAVE_OFFSET * slave_id + + SPMI_APB_SPMI_RDATA0_BASE_ADDR + + i * SPMI_PER_DATAREG_BYTE); data = be32_to_cpu((__be32)data); if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(buf, &data, sizeof(data)); @@ -188,63 +169,64 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, memcpy(buf, &data, bc % SPMI_PER_DATAREG_BYTE); buf += (bc % SPMI_PER_DATAREG_BYTE); } - i++; - } while (bc > i * SPMI_PER_DATAREG_BYTE); + } done: spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) dev_err(&ctrl->dev, - "spmi read wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", - opc, sid, addr, bc + 1); + "spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%ld\n", + opc, slave_id, slave_addr, bc + 1); else - dev_dbg(&ctrl->dev, "%s: id:%d addr:0x%x, read value: %*ph\n", - __func__, sid, addr, (int)bc, __buf); + dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, read value: %*ph\n", + __func__, slave_id, slave_addr, (int)bc, __buf); return rc; } static int spmi_write_cmd(struct spmi_controller *ctrl, - u8 opc, u8 sid, u16 addr, const u8 *__buf, size_t bc) + u8 opc, u8 slave_id, u16 slave_addr, const u8 *__buf, size_t bc) { struct spmi_controller_dev *spmi_controller = dev_get_drvdata(&ctrl->dev); + u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; const u8 *buf = __buf; unsigned long flags; u32 cmd, data; int rc; - u32 chnl_ofst = SPMI_CHANNEL_OFFSET * spmi_controller->channel; u8 op_code, i; if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, - "spmi_controller supports 1..%d bytes per trans, but:%ld requested", + "spmi_controller supports 1..%d bytes per trans, but:%ld requested\n", SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } - /* Check the opcode */ - if (opc == SPMI_CMD_WRITE) { + switch (opc) { + case SPMI_CMD_WRITE: op_code = SPMI_CMD_REG_WRITE; - } else if (opc == SPMI_CMD_EXT_WRITE) { + break; + case SPMI_CMD_EXT_WRITE: op_code = SPMI_CMD_EXT_REG_WRITE; - } else if (opc == SPMI_CMD_EXT_WRITEL) { + break; + case SPMI_CMD_EXT_WRITEL: op_code = SPMI_CMD_EXT_REG_WRITE_L; - } else { - dev_err(&ctrl->dev, "invalid write cmd 0x%x", opc); + break; + default: + dev_err(&ctrl->dev, "invalid write cmd 0x%x\n", opc); return -EINVAL; } cmd = SPMI_APB_SPMI_CMD_EN | (op_code << SPMI_APB_SPMI_CMD_TYPE_OFFSET) | ((bc - 1) << SPMI_APB_SPMI_CMD_LENGTH_OFFSET) | - ((sid & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | /* slvid */ - ((addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* slave_addr */ + ((slave_id & 0xf) << SPMI_APB_SPMI_CMD_SLAVEID_OFFSET) | + ((slave_addr & 0xffff) << SPMI_APB_SPMI_CMD_ADDR_OFFSET); /* Write data to FIFOs */ spin_lock_irqsave(&spmi_controller->lock, flags); - i = 0; - do { + for (i = 0; bc > i * SPMI_PER_DATAREG_BYTE; i++) { data = 0; if ((bc - i * SPMI_PER_DATAREG_BYTE) >> 2) { memcpy(&data, buf, sizeof(data)); @@ -255,23 +237,25 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, } writel((u32)cpu_to_be32(data), - spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_WDATA0_BASE_ADDR + SPMI_PER_DATAREG_BYTE * i); - i++; - } while (bc > i * SPMI_PER_DATAREG_BYTE); + spmi_controller->base + chnl_ofst + + SPMI_APB_SPMI_WDATA0_BASE_ADDR + + SPMI_PER_DATAREG_BYTE * i); + } /* Start the transaction */ writel(cmd, spmi_controller->base + chnl_ofst + SPMI_APB_SPMI_CMD_BASE_ADDR); rc = spmi_controller_wait_for_done(&ctrl->dev, spmi_controller, - spmi_controller->base, sid, addr); + spmi_controller->base, slave_id, + slave_addr); spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) - dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x sid:%d addr:0x%x bc:%ld\n", - opc, sid, addr, bc); + dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%ld\n", + opc, slave_id, slave_addr, bc); else - dev_dbg(&ctrl->dev, "%s: id:%d addr:0x%x, wrote value: %*ph\n", - __func__, sid, addr, (int)bc, __buf); + dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n", + __func__, slave_id, slave_addr, (int)bc, __buf); return rc; } @@ -281,9 +265,7 @@ static int spmi_controller_probe(struct platform_device *pdev) struct spmi_controller_dev *spmi_controller; struct spmi_controller *ctrl; struct resource *iores; - int ret = 0; - - dev_info(&pdev->dev, "HISI SPMI probe\n"); + int ret; ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller)); if (!ctrl) { @@ -293,7 +275,6 @@ static int spmi_controller_probe(struct platform_device *pdev) spmi_controller = spmi_controller_get_drvdata(ctrl); spmi_controller->controller = ctrl; - /* NOTE: driver uses the static register mapping */ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!iores) { dev_err(&pdev->dev, "can not get resource!\n"); @@ -305,10 +286,7 @@ static int spmi_controller_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can not remap base addr!\n"); return -EADDRNOTAVAIL; } - dev_dbg(&pdev->dev, "spmi_add_controller base addr=0x%lx!\n", - (unsigned long)spmi_controller->base); - /* Get properties from the device tree */ ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel", &spmi_controller->channel); if (ret) { @@ -331,14 +309,8 @@ static int spmi_controller_probe(struct platform_device *pdev) ret = spmi_controller_add(ctrl); if (ret) - goto err_add_controller; - - dev_info(&pdev->dev, "spmi_add_controller initialized\n"); - return 0; + dev_err(&pdev->dev, "spmi_add_controller failed with error %d!\n", ret); -err_add_controller: - dev_err(&pdev->dev, "spmi_add_controller failed!\n"); - platform_set_drvdata(pdev, NULL); return ret; } @@ -346,8 +318,8 @@ static int spmi_del_controller(struct platform_device *pdev) { struct spmi_controller *ctrl = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); spmi_controller_remove(ctrl); + kfree(ctrl); return 0; } @@ -362,7 +334,7 @@ static struct platform_driver spmi_controller_driver = { .probe = spmi_controller_probe, .remove = spmi_del_controller, .driver = { - .name = SPMI_CONTROLLER_NAME, + .name = "hisi_spmi_controller", .of_match_table = spmi_controller_match_table, }, }; -- cgit v1.2.3 From 4524ac56cdcabf77b734ec8021089cba59cac1ac Mon Sep 17 00:00:00 2001 From: Mayulong Date: Mon, 17 Aug 2020 09:10:30 +0200 Subject: staging: mfd: add a PMIC driver for HiSilicon 6421 SPMI version Add the PMIC SPMI driver for the HiSilicon 6421v600. [mchehab+huawei@kernel.org: keep just the MFD driver on this patch, and renamed filenames to better match other upstream drivers] The compete patch is at: https://github.com/96boards-hikey/linux/commit/08464419fba2 Signed-off-by: Mayulong Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/4ffb2694244baa47387e39e2c5d71243242c1fc1.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 759 ++++++++++++++++++++++++++++ include/linux/mfd/hi6421-spmi-pmic.h | 165 ++++++ 2 files changed, 924 insertions(+) create mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c create mode 100644 include/linux/mfd/hi6421-spmi-pmic.h (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c new file mode 100644 index 000000000000..6bb0bc4b203b --- /dev/null +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -0,0 +1,759 @@ +/* + * Device driver for regulators in HISI PMIC IC + * + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2011 Hisilicon. + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef NO_IRQ +#define NO_IRQ 0 +#endif + +/* 8-bit register offset in PMIC */ +#define HISI_MASK_STATE 0xff + +#define HISI_IRQ_KEY_NUM 0 +#define HISI_IRQ_KEY_VALUE 0xc0 +#define HISI_IRQ_KEY_DOWN 7 +#define HISI_IRQ_KEY_UP 6 + +/*#define HISI_NR_IRQ 25*/ +#define HISI_MASK_FIELD 0xFF +#define HISI_BITS 8 +#define PMIC_FPGA_FLAG 1 + +/*define the first group interrupt register number*/ +#define HISI_PMIC_FIRST_GROUP_INT_NUM 2 + +static struct bit_info g_pmic_vbus = {0}; +#ifndef BIT +#define BIT(x) (0x1U << (x)) +#endif + +static struct hisi_pmic *g_pmic; +static unsigned int g_extinterrupt_flag = 0; +static struct of_device_id of_hisi_pmic_match_tbl[] = { + { + .compatible = "hisilicon-hisi-pmic-spmi", + }, + { /* end */ } +}; + +/* + * The PMIC register is only 8-bit. + * Hisilicon SoC use hardware to map PMIC register into SoC mapping. + * At here, we are accessing SoC register with 32-bit. + */ +u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) +{ + u32 ret; + u8 read_value = 0; + struct spmi_device *pdev; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return 0; + } + + pdev = to_spmi_device(g_pmic->dev); + if (NULL == pdev) { + pr_err("%s:pdev get failed!\n", __func__); + return 0; + } + + ret = spmi_ext_register_readl(pdev, reg, (unsigned char*)&read_value, 1);/*lint !e734 !e732 */ + if (ret) { + pr_err("%s:spmi_ext_register_readl failed!\n", __func__); + return ret; + } + return (u32)read_value; +} +EXPORT_SYMBOL(hisi_pmic_read); + +void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) +{ + u32 ret; + struct spmi_device *pdev; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + pdev = to_spmi_device(g_pmic->dev); + if (NULL == pdev) { + pr_err("%s:pdev get failed!\n", __func__); + return; + } + + ret = spmi_ext_register_writel(pdev, reg, (unsigned char*)&val, 1);/*lint !e734 !e732 */ + if (ret) { + pr_err("%s:spmi_ext_register_writel failed!\n", __func__); + return ; + } +} +EXPORT_SYMBOL(hisi_pmic_write); + +#ifdef CONFIG_HISI_DIEID +u32 hisi_pmic_read_sub_pmu(u8 sid, int reg) +{ + u32 ret; + u8 read_value = 0; + struct spmi_device *pdev; + + if(strstr(saved_command_line, "androidboot.swtype=factory")) + { + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return -1;/*lint !e570 */ + } + + pdev = to_spmi_device(g_pmic->dev); + if (NULL == pdev) { + pr_err("%s:pdev get failed!\n", __func__); + return -1;/*lint !e570 */ + } + + ret = spmi_ext_register_readl(pdev->ctrl, sid, reg, (unsigned char*)&read_value, 1);/*lint !e734 !e732 */ + if (ret) { + pr_err("%s:spmi_ext_register_readl failed!\n", __func__); + return ret; + } + return (u32)read_value; + } + return 0; +} +EXPORT_SYMBOL(hisi_pmic_read_sub_pmu); + +void hisi_pmic_write_sub_pmu(u8 sid, int reg, u32 val) +{ + u32 ret; + struct spmi_device *pdev; + if(strstr(saved_command_line, "androidboot.swtype=factory")) + { + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + pdev = to_spmi_device(g_pmic->dev); + if (NULL == pdev) { + pr_err("%s:pdev get failed!\n", __func__); + return; + } + + ret = spmi_ext_register_writel(pdev->ctrl, sid, reg, (unsigned char*)&val, 1);/*lint !e734 !e732 */ + if (ret) { + pr_err("%s:spmi_ext_register_writel failed!\n", __func__); + return ; + } + } + + return ; +} +EXPORT_SYMBOL(hisi_pmic_write_sub_pmu); +#endif + +void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, + u32 mask, u32 bits) +{ + u32 data; + unsigned long flags; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + spin_lock_irqsave(&g_pmic->lock, flags); + data = hisi_pmic_read(pmic, reg) & ~mask; + data |= mask & bits; + hisi_pmic_write(pmic, reg, data); + spin_unlock_irqrestore(&g_pmic->lock, flags); +} +EXPORT_SYMBOL(hisi_pmic_rmw); + +unsigned int hisi_pmic_reg_read(int addr) +{ + return (unsigned int)hisi_pmic_read(g_pmic, addr); +} +EXPORT_SYMBOL(hisi_pmic_reg_read); + +void hisi_pmic_reg_write(int addr, int val) +{ + hisi_pmic_write(g_pmic, addr, val); +} +EXPORT_SYMBOL(hisi_pmic_reg_write); + +void hisi_pmic_reg_write_lock(int addr, int val) +{ + unsigned long flags; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + spin_lock_irqsave(&g_pmic->lock, flags); + hisi_pmic_write(g_pmic, g_pmic->normal_lock.addr, g_pmic->normal_lock.val); + hisi_pmic_write(g_pmic, g_pmic->debug_lock.addr, g_pmic->debug_lock.val); + hisi_pmic_write(g_pmic, addr, val); + hisi_pmic_write(g_pmic, g_pmic->normal_lock.addr, 0); + hisi_pmic_write(g_pmic, g_pmic->debug_lock.addr, 0); + spin_unlock_irqrestore(&g_pmic->lock, flags); +} + +int hisi_pmic_array_read(int addr, char *buff, unsigned int len) +{ + unsigned int i; + + if ((len > 32) || (NULL == buff)) { + return -EINVAL; + } + + /* + * Here is a bug in the pmu die. + * the coul driver will read 4 bytes, + * but the ssi bus only read 1 byte, and the pmu die + * will make sampling 1/10669us about vol cur,so the driver + * read the data is not the same sampling + */ + for (i = 0; i < len; i++) + { + *(buff + i) = hisi_pmic_reg_read(addr+i); + } + + return 0; +} + +int hisi_pmic_array_write(int addr, char *buff, unsigned int len) +{ + unsigned int i; + + if ((len > 32) || (NULL == buff)) { + return -EINVAL; + } + + for (i = 0; i < len; i++) + { + hisi_pmic_reg_write(addr+i, *(buff + i)); + } + + return 0; +} + +static irqreturn_t hisi_irq_handler(int irq, void *data) +{ + struct hisi_pmic *pmic = (struct hisi_pmic *)data; + unsigned long pending; + int i, offset; + + for (i = 0; i < pmic->irqarray; i++) { + pending = hisi_pmic_reg_read((i + pmic->irq_addr.start_addr)); + pending &= HISI_MASK_FIELD; + if (pending != 0) { + pr_info("pending[%d]=0x%lx\n\r", i, pending); + } + + hisi_pmic_reg_write((i + pmic->irq_addr.start_addr), pending); + + /*solve powerkey order*/ + if ((HISI_IRQ_KEY_NUM == i) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { + generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]); + generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]); + pending &= (~HISI_IRQ_KEY_VALUE); + } + + if (pending) { + for_each_set_bit(offset, &pending, HISI_BITS) + generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]);/*lint !e679 */ + } + } + + /*Handle the second group irq if analysis the second group irq from dtsi*/ + if (1 == g_extinterrupt_flag){ + for (i = 0; i < pmic->irqarray1; i++) { + pending = hisi_pmic_reg_read((i + pmic->irq_addr1.start_addr)); + pending &= HISI_MASK_FIELD; + if (pending != 0) { + pr_info("pending[%d]=0x%lx\n\r", i, pending); + } + + hisi_pmic_reg_write((i + pmic->irq_addr1.start_addr), pending); + + if (pending) { + for_each_set_bit(offset, &pending, HISI_BITS) + generic_handle_irq(pmic->irqs[offset + (i+HISI_PMIC_FIRST_GROUP_INT_NUM) * HISI_BITS]);/*lint !e679 */ + } + } + } + + return IRQ_HANDLED; +} + +static void hisi_irq_mask(struct irq_data *d) +{ + struct hisi_pmic *pmic = irq_data_get_irq_chip_data(d); + u32 data, offset; + unsigned long flags; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + offset = (irqd_to_hwirq(d) >> 3); + if (1==g_extinterrupt_flag){ + if ( offset < HISI_PMIC_FIRST_GROUP_INT_NUM) + offset += pmic->irq_mask_addr.start_addr; + else/*Change addr when irq num larger than 16 because interrupt addr is nonsequence*/ + offset = offset+(pmic->irq_mask_addr1.start_addr)-HISI_PMIC_FIRST_GROUP_INT_NUM; + }else{ + offset += pmic->irq_mask_addr.start_addr; + } + spin_lock_irqsave(&g_pmic->lock, flags); + data = hisi_pmic_reg_read(offset); + data |= (1 << (irqd_to_hwirq(d) & 0x07)); + hisi_pmic_reg_write(offset, data); + spin_unlock_irqrestore(&g_pmic->lock, flags); +} + +static void hisi_irq_unmask(struct irq_data *d) +{ + struct hisi_pmic *pmic = irq_data_get_irq_chip_data(d); + u32 data, offset; + unsigned long flags; + + if (NULL == g_pmic) { + pr_err(" g_pmic is NULL\n"); + return; + } + + offset = (irqd_to_hwirq(d) >> 3); + if (1==g_extinterrupt_flag){ + if ( offset < HISI_PMIC_FIRST_GROUP_INT_NUM) + offset += pmic->irq_mask_addr.start_addr; + else + offset = offset+(pmic->irq_mask_addr1.start_addr)-HISI_PMIC_FIRST_GROUP_INT_NUM; + }else{ + offset += pmic->irq_mask_addr.start_addr; + } + spin_lock_irqsave(&g_pmic->lock, flags); + data = hisi_pmic_reg_read(offset); + data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); /*lint !e502 */ + hisi_pmic_reg_write(offset, data); + spin_unlock_irqrestore(&g_pmic->lock, flags); +} + +static struct irq_chip hisi_pmu_irqchip = { + .name = "hisi-irq", + .irq_mask = hisi_irq_mask, + .irq_unmask = hisi_irq_unmask, + .irq_disable = hisi_irq_mask, + .irq_enable = hisi_irq_unmask, +}; + +static int hisi_irq_map(struct irq_domain *d, unsigned int virq, + irq_hw_number_t hw) +{ + struct hisi_pmic *pmic = d->host_data; + + irq_set_chip_and_handler_name(virq, &hisi_pmu_irqchip, + handle_simple_irq, "hisi"); + irq_set_chip_data(virq, pmic); + irq_set_irq_type(virq, IRQ_TYPE_NONE); + + return 0; +} + +static struct irq_domain_ops hisi_domain_ops = { + .map = hisi_irq_map, + .xlate = irq_domain_xlate_twocell, +}; + +/*lint -e570 -e64*/ +static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *pmic) +{ + int ret = 0; + + /*get pmic irq num*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num", + &(pmic->irqnum), 1); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-num property set\n"); + ret = -ENODEV; + return ret; + } + + /*get pmic irq array number*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array", + &(pmic->irqarray), 1); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-array property set\n"); + ret = -ENODEV; + return ret; + } + + /*SOC_PMIC_IRQ_MASK_0_ADDR*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr", + (int *)&pmic->irq_mask_addr, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-mask-addr property set\n"); + ret = -ENODEV; + return ret; + } + + /*SOC_PMIC_IRQ0_ADDR*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr", + (int *)&pmic->irq_addr, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-addr property set\n"); + ret = -ENODEV; + return ret; + } + + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-vbus", + (u32 *)&g_pmic_vbus, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-vbus property\n"); + ret = -ENODEV; + return ret; + } + + /*pmic lock*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-lock", + (int *)&pmic->normal_lock, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-lock property set\n"); + ret = -ENODEV; + return ret; + } + + /*pmic debug lock*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-debug-lock", + (int *)&pmic->debug_lock, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-debug-lock property set\n"); + ret = -ENODEV; + return ret; + } + + return ret; +}/*lint -restore*/ + + +/*lint -e570 -e64*/ +static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic *pmic) +{ + int ret = 0; + + /*get pmic irq num*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num1", + &(pmic->irqnum1), 1); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-num1 property set\n"); + ret = -ENODEV; + pmic->irqnum1 = 0; + return ret; + } + + /*get pmic irq array number*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array1", + &(pmic->irqarray1), 1); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-array1 property set\n"); + ret = -ENODEV; + return ret; + } + + /*SOC_PMIC_IRQ_MASK_0_ADDR*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr1", + (int *)&pmic->irq_mask_addr1, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-mask-addr1 property set\n"); + ret = -ENODEV; + return ret; + } + + /*SOC_PMIC_IRQ0_ADDR*/ + ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr1", + (int *)&pmic->irq_addr1, 2); + if (ret) { + pr_err("no hisilicon,hisi-pmic-irq-addr1 property set\n"); + ret = -ENODEV; + return ret; + } + + g_extinterrupt_flag = 1; + return ret; +}/*lint -restore*/ + +int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list) +{ + if ( NULL == g_pmic ) { + pr_err("[%s]g_pmic is NULL\n", __func__); + return -1; + } + + if (pmic_irq_list > (unsigned int)g_pmic->irqnum) { + pr_err("[%s]input pmic irq number is error.\n", __func__); + return -1; + } + pr_info("%s:g_pmic->irqs[%d]=%d\n", __func__, pmic_irq_list, g_pmic->irqs[pmic_irq_list]); + return (int)g_pmic->irqs[pmic_irq_list]; +} +EXPORT_SYMBOL(hisi_get_pmic_irq_byname); + +int hisi_pmic_get_vbus_status(void) +{ + if (0 == g_pmic_vbus.addr) + return -1; + + if (hisi_pmic_reg_read(g_pmic_vbus.addr) & BIT(g_pmic_vbus.bit)) + return 1; + + return 0; +} +EXPORT_SYMBOL(hisi_pmic_get_vbus_status); + +static void hisi_pmic_irq_prc(struct hisi_pmic *pmic) +{ + int i; + for (i = 0 ; i < pmic->irq_mask_addr.array; i++) { + hisi_pmic_write(pmic, pmic->irq_mask_addr.start_addr + i, HISI_MASK_STATE); + } + + for (i = 0 ; i < pmic->irq_addr.array; i++) { + unsigned int pending = hisi_pmic_read(pmic, pmic->irq_addr.start_addr + i); + pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", pmic->irq_addr.start_addr + i, pending); + hisi_pmic_write(pmic, pmic->irq_addr.start_addr + i, HISI_MASK_STATE); + } + +} + +static void hisi_pmic_irq1_prc(struct hisi_pmic *pmic) +{ + int i; + if(1 == g_extinterrupt_flag){ + for (i = 0 ; i < pmic->irq_mask_addr1.array; i++) { + hisi_pmic_write(pmic, pmic->irq_mask_addr1.start_addr + i, HISI_MASK_STATE); + } + + for (i = 0 ; i < pmic->irq_addr1.array; i++) { + unsigned int pending1 = hisi_pmic_read(pmic, pmic->irq_addr1.start_addr + i); + pr_debug("PMU IRQ address1 value:irq[0x%x] = 0x%x\n", pmic->irq_addr1.start_addr + i, pending1); + hisi_pmic_write(pmic, pmic->irq_addr1.start_addr + i, HISI_MASK_STATE); + } + } +} + +static int hisi_pmic_probe(struct spmi_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct hisi_pmic *pmic = NULL; + enum of_gpio_flags flags; + int ret = 0; + int i; + unsigned int fpga_flag = 0; + unsigned int virq; + + pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); + if (!pmic) { + dev_err(dev, "cannot allocate hisi_pmic device info\n"); + return -ENOMEM; + } + + /*TODO: get pmic dts info*/ + ret = get_pmic_device_tree_data(np, pmic); + if (ret) { + dev_err(&pdev->dev, "Error reading hisi pmic dts \n"); + return ret; + } + + /*get pmic dts the second group irq*/ + ret = get_pmic_device_tree_data1(np, pmic); + if (ret) { + dev_err(&pdev->dev, "the platform don't support ext-interrupt.\n"); + } + + /* TODO: get and enable clk request */ + spin_lock_init(&pmic->lock); + + pmic->dev = dev; + g_pmic = pmic; + ret = of_property_read_u32_array(np, "hisilicon,pmic_fpga_flag", &fpga_flag, 1); + if (ret) { + pr_err("no hisilicon,pmic_fpga_flag property set\n"); + } + if (PMIC_FPGA_FLAG == fpga_flag) { + goto after_irq_register; + } + + pmic->gpio = of_get_gpio_flags(np, 0, &flags); + if (pmic->gpio < 0) + return pmic->gpio; + + if (!gpio_is_valid(pmic->gpio)) + return -EINVAL; + + ret = gpio_request_one(pmic->gpio, GPIOF_IN, "pmic"); + if (ret < 0) { + dev_err(dev, "failed to request gpio%d\n", pmic->gpio); + return ret; + } + + pmic->irq = gpio_to_irq(pmic->gpio); + + /* mask && clear IRQ status */ + hisi_pmic_irq_prc(pmic); + /*clear && mask the new adding irq*/ + hisi_pmic_irq1_prc(pmic); + + pmic->irqnum += pmic->irqnum1; + + pmic->irqs = (unsigned int *)devm_kmalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); + if (!pmic->irqs) { + pr_err("%s:Failed to alloc memory for pmic irq number!\n", __func__); + goto irq_malloc; + } + memset(pmic->irqs, 0, pmic->irqnum); + + pmic->domain = irq_domain_add_simple(np, pmic->irqnum, 0, + &hisi_domain_ops, pmic); + if (!pmic->domain) { + dev_err(dev, "failed irq domain add simple!\n"); + ret = -ENODEV; + goto irq_domain; + } + + for (i = 0; i < pmic->irqnum; i++) { + virq = irq_create_mapping(pmic->domain, i); + if (virq == NO_IRQ) { + pr_debug("Failed mapping hwirq\n"); + ret = -ENOSPC; + goto irq_create_mapping; + } + pmic->irqs[i] = virq; + pr_info("[%s]. pmic->irqs[%d] = %d\n", __func__, i, pmic->irqs[i]); + } + + ret = request_threaded_irq(pmic->irq, hisi_irq_handler, NULL, + IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, + "pmic", pmic); + if (ret < 0) { + dev_err(dev, "could not claim pmic %d\n", ret); + ret = -ENODEV; + goto request_theaded_irq; + } + +after_irq_register: + return 0; + + +request_theaded_irq: +irq_create_mapping: +irq_domain: +irq_malloc: + gpio_free(pmic->gpio); + g_pmic = NULL; + return ret; +} + +static void hisi_pmic_remove(struct spmi_device *pdev) +{ + + struct hisi_pmic *pmic = dev_get_drvdata(&pdev->dev); + + free_irq(pmic->irq, pmic); + gpio_free(pmic->gpio); + devm_kfree(&pdev->dev, pmic); + +} +static int hisi_pmic_suspend(struct device *dev, pm_message_t state) +{ + struct hisi_pmic *pmic = dev_get_drvdata(dev); + + if (NULL == pmic) { + pr_err("%s:pmic is NULL\n", __func__); + return -ENOMEM; + } + + pr_info("%s:+\n", __func__); + pr_info("%s:-\n", __func__); + + return 0; +}/*lint !e715 */ + +static int hisi_pmic_resume(struct device *dev) +{ + struct hisi_pmic *pmic = dev_get_drvdata(dev); + + if (NULL == pmic) { + pr_err("%s:pmic is NULL\n", __func__); + return -ENOMEM; + } + + pr_info("%s:+\n", __func__); + pr_info("%s:-\n", __func__); + + return 0; +} + +MODULE_DEVICE_TABLE(spmi, pmic_spmi_id); +static struct spmi_driver hisi_pmic_driver = { + .driver = { + .name = "hisi_pmic", + .owner = THIS_MODULE, + .of_match_table = of_hisi_pmic_match_tbl, + .suspend = hisi_pmic_suspend, + .resume = hisi_pmic_resume, + }, + .probe = hisi_pmic_probe, + .remove = hisi_pmic_remove, +}; + +static int __init hisi_pmic_init(void) +{ + return spmi_driver_register(&hisi_pmic_driver); +} + +static void __exit hisi_pmic_exit(void) +{ + spmi_driver_unregister(&hisi_pmic_driver); +} + + +subsys_initcall_sync(hisi_pmic_init); +module_exit(hisi_pmic_exit); + +MODULE_DESCRIPTION("PMIC driver"); +MODULE_LICENSE("GPL v2"); + diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h new file mode 100644 index 000000000000..939b36f617c1 --- /dev/null +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -0,0 +1,165 @@ +/* + * Header file for device driver Hi6421 PMIC + * + * Copyright (c) 2013 Linaro Ltd. + * Copyright (C) 2011 Hisilicon. + * + * Guodong Xu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __HISI_PMIC_H +#define __HISI_PMIC_H + +#include + +#define HISI_REGS_ENA_PROTECT_TIME (0) /* in microseconds */ +#define HISI_ECO_MODE_ENABLE (1) +#define HISI_ECO_MODE_DISABLE (0) + +typedef int (*pmic_ocp_callback)(char *); +extern int hisi_pmic_special_ocp_register(char *power_name, pmic_ocp_callback handler); + +struct irq_mask_info { + int start_addr; + int array; +}; + +struct irq_info { + int start_addr; + int array; +}; + +struct bit_info { + int addr; + int bit; +}; + +struct write_lock { + int addr; + int val; +}; + +struct hisi_pmic { + struct resource *res; + struct device *dev; + void __iomem *regs; + spinlock_t lock; + struct irq_domain *domain; + int irq; + int gpio; + unsigned int *irqs; + int irqnum; + int irqarray; + struct irq_mask_info irq_mask_addr; + struct irq_info irq_addr; + int irqnum1; + int irqarray1; + struct irq_mask_info irq_mask_addr1; + struct irq_info irq_addr1; + struct write_lock normal_lock; + struct write_lock debug_lock; +}; + +/* 0:disable; 1:enable */ +unsigned int get_uv_mntn_status(void); +void clear_uv_mntn_resered_reg_bit(void); +void set_uv_mntn_resered_reg_bit(void); + +#if defined(CONFIG_HISI_PMIC) || defined(CONFIG_HISI_PMIC_PMU_SPMI) +/* Register Access Helpers */ +u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg); +void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val); +void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits); +unsigned int hisi_pmic_reg_read(int addr); +void hisi_pmic_reg_write(int addr, int val); +void hisi_pmic_reg_write_lock(int addr, int val); +int hisi_pmic_array_read(int addr, char *buff, unsigned int len); +int hisi_pmic_array_write(int addr, char *buff, unsigned int len); +extern int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list); +extern int hisi_pmic_get_vbus_status(void); +#if defined(CONFIG_HISI_DIEID) +u32 hisi_pmic_read_sub_pmu(u8 sid ,int reg); +void hisi_pmic_write_sub_pmu(u8 sid ,int reg, u32 val); +#endif +#else +static inline u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) { return 0; } +static inline void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) {} +static inline void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) {} +static inline unsigned int hisi_pmic_reg_read(int addr) { return 0; } +static inline void hisi_pmic_reg_write(int addr, int val) {} +static inline void hisi_pmic_reg_write_lock(int addr, int val) {} +static inline int hisi_pmic_array_read(int addr, char *buff, unsigned int len) { return 0; } +static inline int hisi_pmic_array_write(int addr, char *buff, unsigned int len) { return 0; } +static inline int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list) { return -1; } +static inline int hisi_pmic_get_vbus_status(void) { return 1; } +static inline u32 hisi_pmic_read_sub_pmu(u8 sid ,int reg) { return 0; } +static inline void hisi_pmic_write_sub_pmu(u8 sid ,int reg, u32 val) {} +#endif + +#ifdef CONFIG_HISI_HI6421V500_PMU +enum pmic_irq_list { + POR_D45MR = 0, + VBUS_CONNECT, + VBUS_DISCONNECT, + ALARMON_R, + HOLD_6S, + HOLD_1S, + POWERKEY_UP, + POWERKEY_DOWN, + OCP_SCP_R, + COUL_R, + VSYS_OV, + VSYS_UV, + VSYS_PWROFF_ABS, + VSYS_PWROFF_DEB, + THSD_OTMP140, + THSD_OTMP125, + HRESETN, + SIM0_HPD_R = 24, + SIM0_HPD_F, + SIM0_HPD_H, + SIM0_HPD_L, + SIM1_HPD_R, + SIM1_HPD_F, + SIM1_HPD_H, + SIM1_HPD_L, + PMIC_IRQ_LIST_MAX, +}; +#else +enum pmic_irq_list { + OTMP = 0, + VBUS_CONNECT, + VBUS_DISCONNECT, + ALARMON_R, + HOLD_6S, + HOLD_1S, + POWERKEY_UP, + POWERKEY_DOWN, + OCP_SCP_R, + COUL_R, + SIM0_HPD_R, + SIM0_HPD_F, + SIM1_HPD_R, + SIM1_HPD_F, + PMIC_IRQ_LIST_MAX, +}; +#endif + +#ifdef CONFIG_HISI_SR_DEBUG +extern void get_ip_regulator_state(void); +#endif +#endif /* __HISI_PMIC_H */ + -- cgit v1.2.3 From 489b1a36b111b6a3a4ac1acf29de5cf154810887 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:31 +0200 Subject: staging: mfd: hi6421-spmi-pmic: get rid of unused code There are some checks there which could make sense for downstream builds, but doesn't make much sense for upstream ones. They came from the official Hikey970 tree from Linaro, but even there, the commented-out code is not set via other Kconfig vars. So, let's just get rid of that. If needed later, this patch can be (partially?) reversed. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/ecbef801f6c32ba0850ad9e5c534a4304807df3b.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 63 ----------------------------- include/linux/mfd/hi6421-spmi-pmic.h | 42 ------------------- 2 files changed, 105 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 6bb0bc4b203b..809381eb6043 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -53,10 +53,6 @@ #define HISI_PMIC_FIRST_GROUP_INT_NUM 2 static struct bit_info g_pmic_vbus = {0}; -#ifndef BIT -#define BIT(x) (0x1U << (x)) -#endif - static struct hisi_pmic *g_pmic; static unsigned int g_extinterrupt_flag = 0; static struct of_device_id of_hisi_pmic_match_tbl[] = { @@ -121,65 +117,6 @@ void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) } EXPORT_SYMBOL(hisi_pmic_write); -#ifdef CONFIG_HISI_DIEID -u32 hisi_pmic_read_sub_pmu(u8 sid, int reg) -{ - u32 ret; - u8 read_value = 0; - struct spmi_device *pdev; - - if(strstr(saved_command_line, "androidboot.swtype=factory")) - { - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); - return -1;/*lint !e570 */ - } - - pdev = to_spmi_device(g_pmic->dev); - if (NULL == pdev) { - pr_err("%s:pdev get failed!\n", __func__); - return -1;/*lint !e570 */ - } - - ret = spmi_ext_register_readl(pdev->ctrl, sid, reg, (unsigned char*)&read_value, 1);/*lint !e734 !e732 */ - if (ret) { - pr_err("%s:spmi_ext_register_readl failed!\n", __func__); - return ret; - } - return (u32)read_value; - } - return 0; -} -EXPORT_SYMBOL(hisi_pmic_read_sub_pmu); - -void hisi_pmic_write_sub_pmu(u8 sid, int reg, u32 val) -{ - u32 ret; - struct spmi_device *pdev; - if(strstr(saved_command_line, "androidboot.swtype=factory")) - { - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); - return; - } - - pdev = to_spmi_device(g_pmic->dev); - if (NULL == pdev) { - pr_err("%s:pdev get failed!\n", __func__); - return; - } - - ret = spmi_ext_register_writel(pdev->ctrl, sid, reg, (unsigned char*)&val, 1);/*lint !e734 !e732 */ - if (ret) { - pr_err("%s:spmi_ext_register_writel failed!\n", __func__); - return ; - } - } - - return ; -} -EXPORT_SYMBOL(hisi_pmic_write_sub_pmu); -#endif void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index 939b36f617c1..5be9b4d3f207 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -78,7 +78,6 @@ unsigned int get_uv_mntn_status(void); void clear_uv_mntn_resered_reg_bit(void); void set_uv_mntn_resered_reg_bit(void); -#if defined(CONFIG_HISI_PMIC) || defined(CONFIG_HISI_PMIC_PMU_SPMI) /* Register Access Helpers */ u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg); void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val); @@ -90,11 +89,6 @@ int hisi_pmic_array_read(int addr, char *buff, unsigned int len); int hisi_pmic_array_write(int addr, char *buff, unsigned int len); extern int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list); extern int hisi_pmic_get_vbus_status(void); -#if defined(CONFIG_HISI_DIEID) -u32 hisi_pmic_read_sub_pmu(u8 sid ,int reg); -void hisi_pmic_write_sub_pmu(u8 sid ,int reg, u32 val); -#endif -#else static inline u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) { return 0; } static inline void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) {} static inline void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) {} @@ -107,38 +101,7 @@ static inline int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list) { return static inline int hisi_pmic_get_vbus_status(void) { return 1; } static inline u32 hisi_pmic_read_sub_pmu(u8 sid ,int reg) { return 0; } static inline void hisi_pmic_write_sub_pmu(u8 sid ,int reg, u32 val) {} -#endif -#ifdef CONFIG_HISI_HI6421V500_PMU -enum pmic_irq_list { - POR_D45MR = 0, - VBUS_CONNECT, - VBUS_DISCONNECT, - ALARMON_R, - HOLD_6S, - HOLD_1S, - POWERKEY_UP, - POWERKEY_DOWN, - OCP_SCP_R, - COUL_R, - VSYS_OV, - VSYS_UV, - VSYS_PWROFF_ABS, - VSYS_PWROFF_DEB, - THSD_OTMP140, - THSD_OTMP125, - HRESETN, - SIM0_HPD_R = 24, - SIM0_HPD_F, - SIM0_HPD_H, - SIM0_HPD_L, - SIM1_HPD_R, - SIM1_HPD_F, - SIM1_HPD_H, - SIM1_HPD_L, - PMIC_IRQ_LIST_MAX, -}; -#else enum pmic_irq_list { OTMP = 0, VBUS_CONNECT, @@ -156,10 +119,5 @@ enum pmic_irq_list { SIM1_HPD_F, PMIC_IRQ_LIST_MAX, }; -#endif - -#ifdef CONFIG_HISI_SR_DEBUG -extern void get_ip_regulator_state(void); -#endif #endif /* __HISI_PMIC_H */ -- cgit v1.2.3 From 02a9bd4f3e03ab335101233bf1b1362aef11f907 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:32 +0200 Subject: staging: mfd: hi6421-spmi-pmic: deal with non-static functions Several functions aren't used outside the mfd driver. So, either remove or make them static. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/d26323ab7be5b4efb73b1950b4daaa5959277449.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 147 +++++----------------------- 1 file changed, 24 insertions(+), 123 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 809381eb6043..8b87d48b88b5 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -73,21 +73,21 @@ u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) u8 read_value = 0; struct spmi_device *pdev; - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); + if (!g_pmic) { + pr_err("%s: g_pmic is NULL\n", __func__); return 0; } pdev = to_spmi_device(g_pmic->dev); - if (NULL == pdev) { - pr_err("%s:pdev get failed!\n", __func__); + if (!pdev) { + pr_err("%s: pdev get failed!\n", __func__); return 0; } ret = spmi_ext_register_readl(pdev, reg, (unsigned char*)&read_value, 1);/*lint !e734 !e732 */ if (ret) { - pr_err("%s:spmi_ext_register_readl failed!\n", __func__); - return ret; + pr_err("%s: spmi_ext_register_readl failed!\n", __func__); + return 0; } return (u32)read_value; } @@ -98,34 +98,32 @@ void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) u32 ret; struct spmi_device *pdev; - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); + if (!g_pmic) { + pr_err("%s: g_pmic is NULL\n", __func__); return; } pdev = to_spmi_device(g_pmic->dev); - if (NULL == pdev) { - pr_err("%s:pdev get failed!\n", __func__); + if (!pdev) { + pr_err("%s: pdev get failed!\n", __func__); return; } ret = spmi_ext_register_writel(pdev, reg, (unsigned char*)&val, 1);/*lint !e734 !e732 */ if (ret) { - pr_err("%s:spmi_ext_register_writel failed!\n", __func__); - return ; + pr_err("%s: spmi_ext_register_writel failed!\n", __func__); + return; } } EXPORT_SYMBOL(hisi_pmic_write); - -void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, - u32 mask, u32 bits) +void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) { u32 data; unsigned long flags; - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); + if (!g_pmic) { + pr_err("%s: g_pmic is NULL\n", __func__); return; } @@ -137,75 +135,6 @@ void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, } EXPORT_SYMBOL(hisi_pmic_rmw); -unsigned int hisi_pmic_reg_read(int addr) -{ - return (unsigned int)hisi_pmic_read(g_pmic, addr); -} -EXPORT_SYMBOL(hisi_pmic_reg_read); - -void hisi_pmic_reg_write(int addr, int val) -{ - hisi_pmic_write(g_pmic, addr, val); -} -EXPORT_SYMBOL(hisi_pmic_reg_write); - -void hisi_pmic_reg_write_lock(int addr, int val) -{ - unsigned long flags; - - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); - return; - } - - spin_lock_irqsave(&g_pmic->lock, flags); - hisi_pmic_write(g_pmic, g_pmic->normal_lock.addr, g_pmic->normal_lock.val); - hisi_pmic_write(g_pmic, g_pmic->debug_lock.addr, g_pmic->debug_lock.val); - hisi_pmic_write(g_pmic, addr, val); - hisi_pmic_write(g_pmic, g_pmic->normal_lock.addr, 0); - hisi_pmic_write(g_pmic, g_pmic->debug_lock.addr, 0); - spin_unlock_irqrestore(&g_pmic->lock, flags); -} - -int hisi_pmic_array_read(int addr, char *buff, unsigned int len) -{ - unsigned int i; - - if ((len > 32) || (NULL == buff)) { - return -EINVAL; - } - - /* - * Here is a bug in the pmu die. - * the coul driver will read 4 bytes, - * but the ssi bus only read 1 byte, and the pmu die - * will make sampling 1/10669us about vol cur,so the driver - * read the data is not the same sampling - */ - for (i = 0; i < len; i++) - { - *(buff + i) = hisi_pmic_reg_read(addr+i); - } - - return 0; -} - -int hisi_pmic_array_write(int addr, char *buff, unsigned int len) -{ - unsigned int i; - - if ((len > 32) || (NULL == buff)) { - return -EINVAL; - } - - for (i = 0; i < len; i++) - { - hisi_pmic_reg_write(addr+i, *(buff + i)); - } - - return 0; -} - static irqreturn_t hisi_irq_handler(int irq, void *data) { struct hisi_pmic *pmic = (struct hisi_pmic *)data; @@ -213,13 +142,13 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) int i, offset; for (i = 0; i < pmic->irqarray; i++) { - pending = hisi_pmic_reg_read((i + pmic->irq_addr.start_addr)); + pending = hisi_pmic_read(g_pmic, (i + pmic->irq_addr.start_addr)); pending &= HISI_MASK_FIELD; if (pending != 0) { pr_info("pending[%d]=0x%lx\n\r", i, pending); } - hisi_pmic_reg_write((i + pmic->irq_addr.start_addr), pending); + hisi_pmic_write(g_pmic, (i + pmic->irq_addr.start_addr), pending); /*solve powerkey order*/ if ((HISI_IRQ_KEY_NUM == i) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { @@ -237,13 +166,13 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) /*Handle the second group irq if analysis the second group irq from dtsi*/ if (1 == g_extinterrupt_flag){ for (i = 0; i < pmic->irqarray1; i++) { - pending = hisi_pmic_reg_read((i + pmic->irq_addr1.start_addr)); + pending = hisi_pmic_read(g_pmic, (i + pmic->irq_addr1.start_addr)); pending &= HISI_MASK_FIELD; if (pending != 0) { pr_info("pending[%d]=0x%lx\n\r", i, pending); } - hisi_pmic_reg_write((i + pmic->irq_addr1.start_addr), pending); + hisi_pmic_write(g_pmic, (i + pmic->irq_addr1.start_addr), pending); if (pending) { for_each_set_bit(offset, &pending, HISI_BITS) @@ -276,9 +205,9 @@ static void hisi_irq_mask(struct irq_data *d) offset += pmic->irq_mask_addr.start_addr; } spin_lock_irqsave(&g_pmic->lock, flags); - data = hisi_pmic_reg_read(offset); + data = hisi_pmic_read(g_pmic, offset); data |= (1 << (irqd_to_hwirq(d) & 0x07)); - hisi_pmic_reg_write(offset, data); + hisi_pmic_write(g_pmic, offset, data); spin_unlock_irqrestore(&g_pmic->lock, flags); } @@ -303,9 +232,9 @@ static void hisi_irq_unmask(struct irq_data *d) offset += pmic->irq_mask_addr.start_addr; } spin_lock_irqsave(&g_pmic->lock, flags); - data = hisi_pmic_reg_read(offset); - data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); /*lint !e502 */ - hisi_pmic_reg_write(offset, data); + data = hisi_pmic_read(g_pmic, offset); + data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); + hisi_pmic_write(g_pmic, offset, data); spin_unlock_irqrestore(&g_pmic->lock, flags); } @@ -452,34 +381,6 @@ static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic * return ret; }/*lint -restore*/ -int hisi_get_pmic_irq_byname(unsigned int pmic_irq_list) -{ - if ( NULL == g_pmic ) { - pr_err("[%s]g_pmic is NULL\n", __func__); - return -1; - } - - if (pmic_irq_list > (unsigned int)g_pmic->irqnum) { - pr_err("[%s]input pmic irq number is error.\n", __func__); - return -1; - } - pr_info("%s:g_pmic->irqs[%d]=%d\n", __func__, pmic_irq_list, g_pmic->irqs[pmic_irq_list]); - return (int)g_pmic->irqs[pmic_irq_list]; -} -EXPORT_SYMBOL(hisi_get_pmic_irq_byname); - -int hisi_pmic_get_vbus_status(void) -{ - if (0 == g_pmic_vbus.addr) - return -1; - - if (hisi_pmic_reg_read(g_pmic_vbus.addr) & BIT(g_pmic_vbus.bit)) - return 1; - - return 0; -} -EXPORT_SYMBOL(hisi_pmic_get_vbus_status); - static void hisi_pmic_irq_prc(struct hisi_pmic *pmic) { int i; -- cgit v1.2.3 From 4b5e9b39e7dd9e6b980ad588f1f7a36fe7cda044 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:33 +0200 Subject: staging: mfd: hi6421-spmi-pmic: get rid of the static vars There are several static vars inside this driver. Get rid of them. While here, add a SPDX header file. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/19c497fc2bb1d3a95863d92cac89869d5abe3f2e.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 224 ++++++++++++---------------- include/linux/mfd/hi6421-spmi-pmic.h | 20 +-- 2 files changed, 97 insertions(+), 147 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 8b87d48b88b5..be42fed16bd2 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Device driver for regulators in HISI PMIC IC * @@ -52,10 +53,7 @@ /*define the first group interrupt register number*/ #define HISI_PMIC_FIRST_GROUP_INT_NUM 2 -static struct bit_info g_pmic_vbus = {0}; -static struct hisi_pmic *g_pmic; -static unsigned int g_extinterrupt_flag = 0; -static struct of_device_id of_hisi_pmic_match_tbl[] = { +static const struct of_device_id of_hisi_pmic_match_tbl[] = { { .compatible = "hisilicon-hisi-pmic-spmi", }, @@ -73,18 +71,14 @@ u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) u8 read_value = 0; struct spmi_device *pdev; - if (!g_pmic) { - pr_err("%s: g_pmic is NULL\n", __func__); - return 0; - } - - pdev = to_spmi_device(g_pmic->dev); + pdev = to_spmi_device(pmic->dev); if (!pdev) { pr_err("%s: pdev get failed!\n", __func__); return 0; } - ret = spmi_ext_register_readl(pdev, reg, (unsigned char*)&read_value, 1);/*lint !e734 !e732 */ + ret = spmi_ext_register_readl(pdev, reg, + (unsigned char *)&read_value, 1); if (ret) { pr_err("%s: spmi_ext_register_readl failed!\n", __func__); return 0; @@ -98,18 +92,13 @@ void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) u32 ret; struct spmi_device *pdev; - if (!g_pmic) { - pr_err("%s: g_pmic is NULL\n", __func__); - return; - } - - pdev = to_spmi_device(g_pmic->dev); + pdev = to_spmi_device(pmic->dev); if (!pdev) { pr_err("%s: pdev get failed!\n", __func__); return; } - ret = spmi_ext_register_writel(pdev, reg, (unsigned char*)&val, 1);/*lint !e734 !e732 */ + ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1); if (ret) { pr_err("%s: spmi_ext_register_writel failed!\n", __func__); return; @@ -122,16 +111,11 @@ void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) u32 data; unsigned long flags; - if (!g_pmic) { - pr_err("%s: g_pmic is NULL\n", __func__); - return; - } - - spin_lock_irqsave(&g_pmic->lock, flags); + spin_lock_irqsave(&pmic->lock, flags); data = hisi_pmic_read(pmic, reg) & ~mask; data |= mask & bits; hisi_pmic_write(pmic, reg, data); - spin_unlock_irqrestore(&g_pmic->lock, flags); + spin_unlock_irqrestore(&pmic->lock, flags); } EXPORT_SYMBOL(hisi_pmic_rmw); @@ -142,16 +126,15 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) int i, offset; for (i = 0; i < pmic->irqarray; i++) { - pending = hisi_pmic_read(g_pmic, (i + pmic->irq_addr.start_addr)); + pending = hisi_pmic_read(pmic, (i + pmic->irq_addr.start_addr)); pending &= HISI_MASK_FIELD; - if (pending != 0) { - pr_info("pending[%d]=0x%lx\n\r", i, pending); - } + if (pending != 0) + pr_debug("pending[%d]=0x%lx\n\r", i, pending); - hisi_pmic_write(g_pmic, (i + pmic->irq_addr.start_addr), pending); + hisi_pmic_write(pmic, (i + pmic->irq_addr.start_addr), pending); - /*solve powerkey order*/ - if ((HISI_IRQ_KEY_NUM == i) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { + /* solve powerkey order */ + if ((i == HISI_IRQ_KEY_NUM) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]); generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]); pending &= (~HISI_IRQ_KEY_VALUE); @@ -159,25 +142,25 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) if (pending) { for_each_set_bit(offset, &pending, HISI_BITS) - generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]);/*lint !e679 */ + generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]); } } /*Handle the second group irq if analysis the second group irq from dtsi*/ - if (1 == g_extinterrupt_flag){ + if (pmic->g_extinterrupt_flag == 1) { for (i = 0; i < pmic->irqarray1; i++) { - pending = hisi_pmic_read(g_pmic, (i + pmic->irq_addr1.start_addr)); + pending = hisi_pmic_read(pmic, (i + pmic->irq_addr1.start_addr)); pending &= HISI_MASK_FIELD; - if (pending != 0) { - pr_info("pending[%d]=0x%lx\n\r", i, pending); - } + if (pending != 0) + pr_debug("pending[%d]=0x%lx\n\r", i, pending); + + hisi_pmic_write(pmic, (i + pmic->irq_addr1.start_addr), pending); - hisi_pmic_write(g_pmic, (i + pmic->irq_addr1.start_addr), pending); + if (!pending) + continue; - if (pending) { - for_each_set_bit(offset, &pending, HISI_BITS) - generic_handle_irq(pmic->irqs[offset + (i+HISI_PMIC_FIRST_GROUP_INT_NUM) * HISI_BITS]);/*lint !e679 */ - } + for_each_set_bit(offset, &pending, HISI_BITS) + generic_handle_irq(pmic->irqs[offset + (i + HISI_PMIC_FIRST_GROUP_INT_NUM) * HISI_BITS]); } } @@ -190,25 +173,25 @@ static void hisi_irq_mask(struct irq_data *d) u32 data, offset; unsigned long flags; - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); - return; - } - offset = (irqd_to_hwirq(d) >> 3); - if (1==g_extinterrupt_flag){ - if ( offset < HISI_PMIC_FIRST_GROUP_INT_NUM) + if (pmic->g_extinterrupt_flag == 1) { + if (offset < HISI_PMIC_FIRST_GROUP_INT_NUM) { offset += pmic->irq_mask_addr.start_addr; - else/*Change addr when irq num larger than 16 because interrupt addr is nonsequence*/ - offset = offset+(pmic->irq_mask_addr1.start_addr)-HISI_PMIC_FIRST_GROUP_INT_NUM; - }else{ + } else { + /* + * Change addr when irq num larger than 16 because + * interrupt addr is nonsequence + */ + offset = offset + (pmic->irq_mask_addr1.start_addr) - HISI_PMIC_FIRST_GROUP_INT_NUM; + } + } else { offset += pmic->irq_mask_addr.start_addr; } - spin_lock_irqsave(&g_pmic->lock, flags); - data = hisi_pmic_read(g_pmic, offset); + spin_lock_irqsave(&pmic->lock, flags); + data = hisi_pmic_read(pmic, offset); data |= (1 << (irqd_to_hwirq(d) & 0x07)); - hisi_pmic_write(g_pmic, offset, data); - spin_unlock_irqrestore(&g_pmic->lock, flags); + hisi_pmic_write(pmic, offset, data); + spin_unlock_irqrestore(&pmic->lock, flags); } static void hisi_irq_unmask(struct irq_data *d) @@ -217,25 +200,20 @@ static void hisi_irq_unmask(struct irq_data *d) u32 data, offset; unsigned long flags; - if (NULL == g_pmic) { - pr_err(" g_pmic is NULL\n"); - return; - } - offset = (irqd_to_hwirq(d) >> 3); - if (1==g_extinterrupt_flag){ - if ( offset < HISI_PMIC_FIRST_GROUP_INT_NUM) + if (pmic->g_extinterrupt_flag == 1) { + if (offset < HISI_PMIC_FIRST_GROUP_INT_NUM) offset += pmic->irq_mask_addr.start_addr; else - offset = offset+(pmic->irq_mask_addr1.start_addr)-HISI_PMIC_FIRST_GROUP_INT_NUM; - }else{ + offset = offset + (pmic->irq_mask_addr1.start_addr) - HISI_PMIC_FIRST_GROUP_INT_NUM; + } else { offset += pmic->irq_mask_addr.start_addr; } - spin_lock_irqsave(&g_pmic->lock, flags); - data = hisi_pmic_read(g_pmic, offset); + spin_lock_irqsave(&pmic->lock, flags); + data = hisi_pmic_read(pmic, offset); data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); - hisi_pmic_write(g_pmic, offset, data); - spin_unlock_irqrestore(&g_pmic->lock, flags); + hisi_pmic_write(pmic, offset, data); + spin_unlock_irqrestore(&pmic->lock, flags); } static struct irq_chip hisi_pmu_irqchip = { @@ -247,7 +225,7 @@ static struct irq_chip hisi_pmu_irqchip = { }; static int hisi_irq_map(struct irq_domain *d, unsigned int virq, - irq_hw_number_t hw) + irq_hw_number_t hw) { struct hisi_pmic *pmic = d->host_data; @@ -259,19 +237,18 @@ static int hisi_irq_map(struct irq_domain *d, unsigned int virq, return 0; } -static struct irq_domain_ops hisi_domain_ops = { +static const struct irq_domain_ops hisi_domain_ops = { .map = hisi_irq_map, .xlate = irq_domain_xlate_twocell, }; -/*lint -e570 -e64*/ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *pmic) { int ret = 0; /*get pmic irq num*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num", - &(pmic->irqnum), 1); + &pmic->irqnum, 1); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-num property set\n"); ret = -ENODEV; @@ -280,7 +257,7 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p /*get pmic irq array number*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array", - &(pmic->irqarray), 1); + &pmic->irqarray, 1); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-array property set\n"); ret = -ENODEV; @@ -289,7 +266,7 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p /*SOC_PMIC_IRQ_MASK_0_ADDR*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr", - (int *)&pmic->irq_mask_addr, 2); + (int *)&pmic->irq_mask_addr, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-mask-addr property set\n"); ret = -ENODEV; @@ -298,24 +275,16 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p /*SOC_PMIC_IRQ0_ADDR*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr", - (int *)&pmic->irq_addr, 2); + (int *)&pmic->irq_addr, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-addr property set\n"); ret = -ENODEV; return ret; } - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-vbus", - (u32 *)&g_pmic_vbus, 2); - if (ret) { - pr_err("no hisilicon,hisi-pmic-vbus property\n"); - ret = -ENODEV; - return ret; - } - /*pmic lock*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-lock", - (int *)&pmic->normal_lock, 2); + (int *)&pmic->normal_lock, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-lock property set\n"); ret = -ENODEV; @@ -324,7 +293,7 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p /*pmic debug lock*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-debug-lock", - (int *)&pmic->debug_lock, 2); + (int *)&pmic->debug_lock, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-debug-lock property set\n"); ret = -ENODEV; @@ -332,17 +301,15 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p } return ret; -}/*lint -restore*/ - +} -/*lint -e570 -e64*/ static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic *pmic) { int ret = 0; /*get pmic irq num*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num1", - &(pmic->irqnum1), 1); + &pmic->irqnum1, 1); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-num1 property set\n"); ret = -ENODEV; @@ -352,7 +319,7 @@ static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic * /*get pmic irq array number*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array1", - &(pmic->irqarray1), 1); + &pmic->irqarray1, 1); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-array1 property set\n"); ret = -ENODEV; @@ -361,7 +328,7 @@ static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic * /*SOC_PMIC_IRQ_MASK_0_ADDR*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr1", - (int *)&pmic->irq_mask_addr1, 2); + (int *)&pmic->irq_mask_addr1, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-mask-addr1 property set\n"); ret = -ENODEV; @@ -370,43 +337,48 @@ static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic * /*SOC_PMIC_IRQ0_ADDR*/ ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr1", - (int *)&pmic->irq_addr1, 2); + (int *)&pmic->irq_addr1, 2); if (ret) { pr_err("no hisilicon,hisi-pmic-irq-addr1 property set\n"); ret = -ENODEV; return ret; } - g_extinterrupt_flag = 1; + pmic->g_extinterrupt_flag = 1; return ret; -}/*lint -restore*/ +} static void hisi_pmic_irq_prc(struct hisi_pmic *pmic) { int i; - for (i = 0 ; i < pmic->irq_mask_addr.array; i++) { + + for (i = 0 ; i < pmic->irq_mask_addr.array; i++) hisi_pmic_write(pmic, pmic->irq_mask_addr.start_addr + i, HISI_MASK_STATE); - } for (i = 0 ; i < pmic->irq_addr.array; i++) { unsigned int pending = hisi_pmic_read(pmic, pmic->irq_addr.start_addr + i); - pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", pmic->irq_addr.start_addr + i, pending); + + pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", + pmic->irq_addr.start_addr + i, pending); hisi_pmic_write(pmic, pmic->irq_addr.start_addr + i, HISI_MASK_STATE); } - } static void hisi_pmic_irq1_prc(struct hisi_pmic *pmic) { int i; - if(1 == g_extinterrupt_flag){ - for (i = 0 ; i < pmic->irq_mask_addr1.array; i++) { + unsigned int pending1; + + if (pmic->g_extinterrupt_flag == 1) { + for (i = 0 ; i < pmic->irq_mask_addr1.array; i++) hisi_pmic_write(pmic, pmic->irq_mask_addr1.start_addr + i, HISI_MASK_STATE); - } for (i = 0 ; i < pmic->irq_addr1.array; i++) { - unsigned int pending1 = hisi_pmic_read(pmic, pmic->irq_addr1.start_addr + i); - pr_debug("PMU IRQ address1 value:irq[0x%x] = 0x%x\n", pmic->irq_addr1.start_addr + i, pending1); + pending1 = hisi_pmic_read(pmic, pmic->irq_addr1.start_addr + i); + + pr_debug("PMU IRQ address1 value:irq[0x%x] = 0x%x\n", + pmic->irq_addr1.start_addr + i, pending1); + hisi_pmic_write(pmic, pmic->irq_addr1.start_addr + i, HISI_MASK_STATE); } } @@ -424,36 +396,32 @@ static int hisi_pmic_probe(struct spmi_device *pdev) unsigned int virq; pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); - if (!pmic) { - dev_err(dev, "cannot allocate hisi_pmic device info\n"); + if (!pmic) return -ENOMEM; - } /*TODO: get pmic dts info*/ ret = get_pmic_device_tree_data(np, pmic); if (ret) { - dev_err(&pdev->dev, "Error reading hisi pmic dts \n"); + dev_err(&pdev->dev, "Error reading hisi pmic dts\n"); return ret; } /*get pmic dts the second group irq*/ ret = get_pmic_device_tree_data1(np, pmic); - if (ret) { + if (ret) dev_err(&pdev->dev, "the platform don't support ext-interrupt.\n"); - } /* TODO: get and enable clk request */ spin_lock_init(&pmic->lock); pmic->dev = dev; - g_pmic = pmic; - ret = of_property_read_u32_array(np, "hisilicon,pmic_fpga_flag", &fpga_flag, 1); - if (ret) { + ret = of_property_read_u32_array(np, "hisilicon,pmic_fpga_flag", + &fpga_flag, 1); + if (ret) pr_err("no hisilicon,pmic_fpga_flag property set\n"); - } - if (PMIC_FPGA_FLAG == fpga_flag) { + + if (fpga_flag == PMIC_FPGA_FLAG) goto after_irq_register; - } pmic->gpio = of_get_gpio_flags(np, 0, &flags); if (pmic->gpio < 0) @@ -477,12 +445,9 @@ static int hisi_pmic_probe(struct spmi_device *pdev) pmic->irqnum += pmic->irqnum1; - pmic->irqs = (unsigned int *)devm_kmalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); - if (!pmic->irqs) { - pr_err("%s:Failed to alloc memory for pmic irq number!\n", __func__); + pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); + if (!pmic->irqs) goto irq_malloc; - } - memset(pmic->irqs, 0, pmic->irqnum); pmic->domain = irq_domain_add_simple(np, pmic->irqnum, 0, &hisi_domain_ops, pmic); @@ -504,7 +469,7 @@ static int hisi_pmic_probe(struct spmi_device *pdev) } ret = request_threaded_irq(pmic->irq, hisi_irq_handler, NULL, - IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, + IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, "pmic", pmic); if (ret < 0) { dev_err(dev, "could not claim pmic %d\n", ret); @@ -515,31 +480,28 @@ static int hisi_pmic_probe(struct spmi_device *pdev) after_irq_register: return 0; - request_theaded_irq: irq_create_mapping: irq_domain: irq_malloc: gpio_free(pmic->gpio); - g_pmic = NULL; return ret; } static void hisi_pmic_remove(struct spmi_device *pdev) { - struct hisi_pmic *pmic = dev_get_drvdata(&pdev->dev); free_irq(pmic->irq, pmic); gpio_free(pmic->gpio); devm_kfree(&pdev->dev, pmic); - } + static int hisi_pmic_suspend(struct device *dev, pm_message_t state) { struct hisi_pmic *pmic = dev_get_drvdata(dev); - if (NULL == pmic) { + if (!pmic) { pr_err("%s:pmic is NULL\n", __func__); return -ENOMEM; } @@ -548,13 +510,13 @@ static int hisi_pmic_suspend(struct device *dev, pm_message_t state) pr_info("%s:-\n", __func__); return 0; -}/*lint !e715 */ +} static int hisi_pmic_resume(struct device *dev) { struct hisi_pmic *pmic = dev_get_drvdata(dev); - if (NULL == pmic) { + if (!pmic) { pr_err("%s:pmic is NULL\n", __func__); return -ENOMEM; } @@ -588,10 +550,8 @@ static void __exit hisi_pmic_exit(void) spmi_driver_unregister(&hisi_pmic_driver); } - subsys_initcall_sync(hisi_pmic_init); module_exit(hisi_pmic_exit); MODULE_DESCRIPTION("PMIC driver"); MODULE_LICENSE("GPL v2"); - diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index 5be9b4d3f207..e0a8b50f95fc 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Header file for device driver Hi6421 PMIC * @@ -5,19 +6,6 @@ * Copyright (C) 2011 Hisilicon. * * Guodong Xu - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __HISI_PMIC_H @@ -25,12 +13,12 @@ #include -#define HISI_REGS_ENA_PROTECT_TIME (0) /* in microseconds */ +#define HISI_REGS_ENA_PROTECT_TIME (0) /* in microseconds */ #define HISI_ECO_MODE_ENABLE (1) #define HISI_ECO_MODE_DISABLE (0) typedef int (*pmic_ocp_callback)(char *); -extern int hisi_pmic_special_ocp_register(char *power_name, pmic_ocp_callback handler); +int hisi_pmic_special_ocp_register(char *power_name, pmic_ocp_callback handler); struct irq_mask_info { int start_addr; @@ -71,6 +59,8 @@ struct hisi_pmic { struct irq_info irq_addr1; struct write_lock normal_lock; struct write_lock debug_lock; + + unsigned int g_extinterrupt_flag; }; /* 0:disable; 1:enable */ -- cgit v1.2.3 From cf0f27b7b20b5ff19bc2ef488f19720a9d14356b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:35 +0200 Subject: staging: mfd: hi6421-spmi-pmic: change the binding logic Change the binding logic to ensure that the MFD driver will be load after having the SPMI controller registered. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/eb50392ce68bb30f64c603572cdb9c91f93ea47b.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 84 ++++++++++------------------- 1 file changed, 29 insertions(+), 55 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index be42fed16bd2..939f7bd5d8ba 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -24,13 +24,14 @@ #include #include #include +#include #include #include #include #include #include #include -#include +#include #include #include #ifndef NO_IRQ @@ -53,11 +54,8 @@ /*define the first group interrupt register number*/ #define HISI_PMIC_FIRST_GROUP_INT_NUM 2 -static const struct of_device_id of_hisi_pmic_match_tbl[] = { - { - .compatible = "hisilicon-hisi-pmic-spmi", - }, - { /* end */ } +static const struct mfd_cell hi6421v600_devs[] = { + { .name = "hi6421v600-regulator", }, }; /* @@ -477,6 +475,22 @@ static int hisi_pmic_probe(struct spmi_device *pdev) goto request_theaded_irq; } + dev_set_drvdata(&pdev->dev, pmic); + + /* + * The logic below will rely that the pmic is already stored at + * drvdata. + */ + dev_dbg(&pdev->dev, "SPMI-PMIC: adding childs for %pOF\n", + pdev->dev.of_node); + ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, + hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs), + NULL, 0, NULL); + if (ret) { + dev_err(&pdev->dev, "Failed to add child devices: %d\n", ret); + return ret; + } + after_irq_register: return 0; @@ -497,61 +511,21 @@ static void hisi_pmic_remove(struct spmi_device *pdev) devm_kfree(&pdev->dev, pmic); } -static int hisi_pmic_suspend(struct device *dev, pm_message_t state) -{ - struct hisi_pmic *pmic = dev_get_drvdata(dev); - - if (!pmic) { - pr_err("%s:pmic is NULL\n", __func__); - return -ENOMEM; - } - - pr_info("%s:+\n", __func__); - pr_info("%s:-\n", __func__); - - return 0; -} - -static int hisi_pmic_resume(struct device *dev) -{ - struct hisi_pmic *pmic = dev_get_drvdata(dev); - - if (!pmic) { - pr_err("%s:pmic is NULL\n", __func__); - return -ENOMEM; - } - - pr_info("%s:+\n", __func__); - pr_info("%s:-\n", __func__); - - return 0; -} +static const struct of_device_id pmic_spmi_id_table[] = { + { .compatible = "hisilicon,hi6421-spmi-pmic" }, + { } +}; +MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); -MODULE_DEVICE_TABLE(spmi, pmic_spmi_id); static struct spmi_driver hisi_pmic_driver = { .driver = { - .name = "hisi_pmic", - .owner = THIS_MODULE, - .of_match_table = of_hisi_pmic_match_tbl, - .suspend = hisi_pmic_suspend, - .resume = hisi_pmic_resume, + .name = "hi6421-spmi-pmic", + .of_match_table = pmic_spmi_id_table, }, .probe = hisi_pmic_probe, .remove = hisi_pmic_remove, }; +module_spmi_driver(hisi_pmic_driver); -static int __init hisi_pmic_init(void) -{ - return spmi_driver_register(&hisi_pmic_driver); -} - -static void __exit hisi_pmic_exit(void) -{ - spmi_driver_unregister(&hisi_pmic_driver); -} - -subsys_initcall_sync(hisi_pmic_init); -module_exit(hisi_pmic_exit); - -MODULE_DESCRIPTION("PMIC driver"); +MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From bd07d62a47290ca3ceee58f373fa05464edc6eb5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:36 +0200 Subject: staging: mfd: hi6421-spmi-pmic: get rid of unused OF properties There are several OF properties that aren't used by Hikey 970, and some are not even used inside the driver. So, drop them, as as this makes easier to document what's actually used. If latter needed, those could be re-added later. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/332f96c178b81bf1e9908a1da2127f043909ae0c.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 145 +--------------------------- include/linux/mfd/hi6421-spmi-pmic.h | 14 +-- 2 files changed, 7 insertions(+), 152 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 939f7bd5d8ba..f523b2d844b9 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -49,7 +49,6 @@ /*#define HISI_NR_IRQ 25*/ #define HISI_MASK_FIELD 0xFF #define HISI_BITS 8 -#define PMIC_FPGA_FLAG 1 /*define the first group interrupt register number*/ #define HISI_PMIC_FIRST_GROUP_INT_NUM 2 @@ -144,24 +143,6 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) } } - /*Handle the second group irq if analysis the second group irq from dtsi*/ - if (pmic->g_extinterrupt_flag == 1) { - for (i = 0; i < pmic->irqarray1; i++) { - pending = hisi_pmic_read(pmic, (i + pmic->irq_addr1.start_addr)); - pending &= HISI_MASK_FIELD; - if (pending != 0) - pr_debug("pending[%d]=0x%lx\n\r", i, pending); - - hisi_pmic_write(pmic, (i + pmic->irq_addr1.start_addr), pending); - - if (!pending) - continue; - - for_each_set_bit(offset, &pending, HISI_BITS) - generic_handle_irq(pmic->irqs[offset + (i + HISI_PMIC_FIRST_GROUP_INT_NUM) * HISI_BITS]); - } - } - return IRQ_HANDLED; } @@ -172,19 +153,8 @@ static void hisi_irq_mask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - if (pmic->g_extinterrupt_flag == 1) { - if (offset < HISI_PMIC_FIRST_GROUP_INT_NUM) { - offset += pmic->irq_mask_addr.start_addr; - } else { - /* - * Change addr when irq num larger than 16 because - * interrupt addr is nonsequence - */ - offset = offset + (pmic->irq_mask_addr1.start_addr) - HISI_PMIC_FIRST_GROUP_INT_NUM; - } - } else { - offset += pmic->irq_mask_addr.start_addr; - } + offset += pmic->irq_mask_addr.start_addr; + spin_lock_irqsave(&pmic->lock, flags); data = hisi_pmic_read(pmic, offset); data |= (1 << (irqd_to_hwirq(d) & 0x07)); @@ -199,14 +169,8 @@ static void hisi_irq_unmask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - if (pmic->g_extinterrupt_flag == 1) { - if (offset < HISI_PMIC_FIRST_GROUP_INT_NUM) - offset += pmic->irq_mask_addr.start_addr; - else - offset = offset + (pmic->irq_mask_addr1.start_addr) - HISI_PMIC_FIRST_GROUP_INT_NUM; - } else { - offset += pmic->irq_mask_addr.start_addr; - } + offset += pmic->irq_mask_addr.start_addr; + spin_lock_irqsave(&pmic->lock, flags); data = hisi_pmic_read(pmic, offset); data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); @@ -280,69 +244,6 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p return ret; } - /*pmic lock*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-lock", - (int *)&pmic->normal_lock, 2); - if (ret) { - pr_err("no hisilicon,hisi-pmic-lock property set\n"); - ret = -ENODEV; - return ret; - } - - /*pmic debug lock*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-debug-lock", - (int *)&pmic->debug_lock, 2); - if (ret) { - pr_err("no hisilicon,hisi-pmic-debug-lock property set\n"); - ret = -ENODEV; - return ret; - } - - return ret; -} - -static int get_pmic_device_tree_data1(struct device_node *np, struct hisi_pmic *pmic) -{ - int ret = 0; - - /*get pmic irq num*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num1", - &pmic->irqnum1, 1); - if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-num1 property set\n"); - ret = -ENODEV; - pmic->irqnum1 = 0; - return ret; - } - - /*get pmic irq array number*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array1", - &pmic->irqarray1, 1); - if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-array1 property set\n"); - ret = -ENODEV; - return ret; - } - - /*SOC_PMIC_IRQ_MASK_0_ADDR*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr1", - (int *)&pmic->irq_mask_addr1, 2); - if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-mask-addr1 property set\n"); - ret = -ENODEV; - return ret; - } - - /*SOC_PMIC_IRQ0_ADDR*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr1", - (int *)&pmic->irq_addr1, 2); - if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-addr1 property set\n"); - ret = -ENODEV; - return ret; - } - - pmic->g_extinterrupt_flag = 1; return ret; } @@ -362,26 +263,6 @@ static void hisi_pmic_irq_prc(struct hisi_pmic *pmic) } } -static void hisi_pmic_irq1_prc(struct hisi_pmic *pmic) -{ - int i; - unsigned int pending1; - - if (pmic->g_extinterrupt_flag == 1) { - for (i = 0 ; i < pmic->irq_mask_addr1.array; i++) - hisi_pmic_write(pmic, pmic->irq_mask_addr1.start_addr + i, HISI_MASK_STATE); - - for (i = 0 ; i < pmic->irq_addr1.array; i++) { - pending1 = hisi_pmic_read(pmic, pmic->irq_addr1.start_addr + i); - - pr_debug("PMU IRQ address1 value:irq[0x%x] = 0x%x\n", - pmic->irq_addr1.start_addr + i, pending1); - - hisi_pmic_write(pmic, pmic->irq_addr1.start_addr + i, HISI_MASK_STATE); - } - } -} - static int hisi_pmic_probe(struct spmi_device *pdev) { struct device *dev = &pdev->dev; @@ -390,7 +271,6 @@ static int hisi_pmic_probe(struct spmi_device *pdev) enum of_gpio_flags flags; int ret = 0; int i; - unsigned int fpga_flag = 0; unsigned int virq; pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); @@ -404,22 +284,10 @@ static int hisi_pmic_probe(struct spmi_device *pdev) return ret; } - /*get pmic dts the second group irq*/ - ret = get_pmic_device_tree_data1(np, pmic); - if (ret) - dev_err(&pdev->dev, "the platform don't support ext-interrupt.\n"); - /* TODO: get and enable clk request */ spin_lock_init(&pmic->lock); pmic->dev = dev; - ret = of_property_read_u32_array(np, "hisilicon,pmic_fpga_flag", - &fpga_flag, 1); - if (ret) - pr_err("no hisilicon,pmic_fpga_flag property set\n"); - - if (fpga_flag == PMIC_FPGA_FLAG) - goto after_irq_register; pmic->gpio = of_get_gpio_flags(np, 0, &flags); if (pmic->gpio < 0) @@ -438,10 +306,6 @@ static int hisi_pmic_probe(struct spmi_device *pdev) /* mask && clear IRQ status */ hisi_pmic_irq_prc(pmic); - /*clear && mask the new adding irq*/ - hisi_pmic_irq1_prc(pmic); - - pmic->irqnum += pmic->irqnum1; pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); if (!pmic->irqs) @@ -491,7 +355,6 @@ static int hisi_pmic_probe(struct spmi_device *pdev) return ret; } -after_irq_register: return 0; request_theaded_irq: diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index 1f986dd5f31c..41b61de48259 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -48,19 +48,11 @@ struct hisi_pmic { struct irq_domain *domain; int irq; int gpio; - unsigned int *irqs; + unsigned int *irqs; int irqnum; int irqarray; - struct irq_mask_info irq_mask_addr; - struct irq_info irq_addr; - int irqnum1; - int irqarray1; - struct irq_mask_info irq_mask_addr1; - struct irq_info irq_addr1; - struct write_lock normal_lock; - struct write_lock debug_lock; - - unsigned int g_extinterrupt_flag; + struct irq_mask_info irq_mask_addr; + struct irq_info irq_addr; }; u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg); -- cgit v1.2.3 From 4e15eadc8524cf4148596ed352e33fa6b5734ee3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:37 +0200 Subject: staging: mfd: hi6421-spmi-pmic: cleanup OF properties Simplify the names of the DT properties and do some cleanups, in order to better document them. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/24ffcd28a17ee7b0940d8aabef556d172d5feddf.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index f523b2d844b9..aed2d3ec2227 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -209,37 +209,37 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p int ret = 0; /*get pmic irq num*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-num", + ret = of_property_read_u32_array(np, "irq-num", &pmic->irqnum, 1); if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-num property set\n"); + pr_err("no irq-num property set\n"); ret = -ENODEV; return ret; } /*get pmic irq array number*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-array", + ret = of_property_read_u32_array(np, "irq-array", &pmic->irqarray, 1); if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-array property set\n"); + pr_err("no irq-array property set\n"); ret = -ENODEV; return ret; } /*SOC_PMIC_IRQ_MASK_0_ADDR*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-mask-addr", + ret = of_property_read_u32_array(np, "irq-mask-addr", (int *)&pmic->irq_mask_addr, 2); if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-mask-addr property set\n"); + pr_err("no irq-mask-addr property set\n"); ret = -ENODEV; return ret; } /*SOC_PMIC_IRQ0_ADDR*/ - ret = of_property_read_u32_array(np, "hisilicon,hisi-pmic-irq-addr", + ret = of_property_read_u32_array(np, "irq-addr", (int *)&pmic->irq_addr, 2); if (ret) { - pr_err("no hisilicon,hisi-pmic-irq-addr property set\n"); + pr_err("no irq-addr property set\n"); ret = -ENODEV; return ret; } -- cgit v1.2.3 From 1eb2784a90925d48500f6baac1fa1870085c4121 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:38 +0200 Subject: staging: mfd: hi6421-spmi-pmic: change namespace on its functions Rename the functions used internally inside the driver in order for them to follow the driver's name. While here, get rid of some unused definitions at the header file. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/bfa8bf33f71612b1511d73269ca242d0d4e70940.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 97 +++++++++++++++-------------- include/linux/mfd/hi6421-spmi-pmic.h | 51 ++++++--------- 2 files changed, 70 insertions(+), 78 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index aed2d3ec2227..09cedfa1e4bb 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -62,7 +62,7 @@ static const struct mfd_cell hi6421v600_devs[] = { * Hisilicon SoC use hardware to map PMIC register into SoC mapping. * At here, we are accessing SoC register with 32-bit. */ -u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) +u32 hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg) { u32 ret; u8 read_value = 0; @@ -82,9 +82,9 @@ u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg) } return (u32)read_value; } -EXPORT_SYMBOL(hisi_pmic_read); +EXPORT_SYMBOL(hi6421_spmi_pmic_read); -void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) +void hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val) { u32 ret; struct spmi_device *pdev; @@ -101,34 +101,36 @@ void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val) return; } } -EXPORT_SYMBOL(hisi_pmic_write); +EXPORT_SYMBOL(hi6421_spmi_pmic_write); -void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits) +void hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, + u32 mask, u32 bits) { u32 data; unsigned long flags; spin_lock_irqsave(&pmic->lock, flags); - data = hisi_pmic_read(pmic, reg) & ~mask; + data = hi6421_spmi_pmic_read(pmic, reg) & ~mask; data |= mask & bits; - hisi_pmic_write(pmic, reg, data); + hi6421_spmi_pmic_write(pmic, reg, data); spin_unlock_irqrestore(&pmic->lock, flags); } -EXPORT_SYMBOL(hisi_pmic_rmw); +EXPORT_SYMBOL(hi6421_spmi_pmic_rmw); -static irqreturn_t hisi_irq_handler(int irq, void *data) +static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data) { - struct hisi_pmic *pmic = (struct hisi_pmic *)data; + struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data; unsigned long pending; int i, offset; for (i = 0; i < pmic->irqarray; i++) { - pending = hisi_pmic_read(pmic, (i + pmic->irq_addr.start_addr)); + pending = hi6421_spmi_pmic_read(pmic, (i + pmic->irq_addr.start_addr)); pending &= HISI_MASK_FIELD; if (pending != 0) pr_debug("pending[%d]=0x%lx\n\r", i, pending); - hisi_pmic_write(pmic, (i + pmic->irq_addr.start_addr), pending); + hi6421_spmi_pmic_write(pmic, (i + pmic->irq_addr.start_addr), + pending); /* solve powerkey order */ if ((i == HISI_IRQ_KEY_NUM) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { @@ -146,9 +148,9 @@ static irqreturn_t hisi_irq_handler(int irq, void *data) return IRQ_HANDLED; } -static void hisi_irq_mask(struct irq_data *d) +static void hi6421_spmi_irq_mask(struct irq_data *d) { - struct hisi_pmic *pmic = irq_data_get_irq_chip_data(d); + struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d); u32 data, offset; unsigned long flags; @@ -156,15 +158,15 @@ static void hisi_irq_mask(struct irq_data *d) offset += pmic->irq_mask_addr.start_addr; spin_lock_irqsave(&pmic->lock, flags); - data = hisi_pmic_read(pmic, offset); + data = hi6421_spmi_pmic_read(pmic, offset); data |= (1 << (irqd_to_hwirq(d) & 0x07)); - hisi_pmic_write(pmic, offset, data); + hi6421_spmi_pmic_write(pmic, offset, data); spin_unlock_irqrestore(&pmic->lock, flags); } -static void hisi_irq_unmask(struct irq_data *d) +static void hi6421_spmi_irq_unmask(struct irq_data *d) { - struct hisi_pmic *pmic = irq_data_get_irq_chip_data(d); + struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d); u32 data, offset; unsigned long flags; @@ -172,26 +174,26 @@ static void hisi_irq_unmask(struct irq_data *d) offset += pmic->irq_mask_addr.start_addr; spin_lock_irqsave(&pmic->lock, flags); - data = hisi_pmic_read(pmic, offset); + data = hi6421_spmi_pmic_read(pmic, offset); data &= ~(1 << (irqd_to_hwirq(d) & 0x07)); - hisi_pmic_write(pmic, offset, data); + hi6421_spmi_pmic_write(pmic, offset, data); spin_unlock_irqrestore(&pmic->lock, flags); } -static struct irq_chip hisi_pmu_irqchip = { +static struct irq_chip hi6421_spmi_pmu_irqchip = { .name = "hisi-irq", - .irq_mask = hisi_irq_mask, - .irq_unmask = hisi_irq_unmask, - .irq_disable = hisi_irq_mask, - .irq_enable = hisi_irq_unmask, + .irq_mask = hi6421_spmi_irq_mask, + .irq_unmask = hi6421_spmi_irq_unmask, + .irq_disable = hi6421_spmi_irq_mask, + .irq_enable = hi6421_spmi_irq_unmask, }; -static int hisi_irq_map(struct irq_domain *d, unsigned int virq, +static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw) { - struct hisi_pmic *pmic = d->host_data; + struct hi6421_spmi_pmic *pmic = d->host_data; - irq_set_chip_and_handler_name(virq, &hisi_pmu_irqchip, + irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip, handle_simple_irq, "hisi"); irq_set_chip_data(virq, pmic); irq_set_irq_type(virq, IRQ_TYPE_NONE); @@ -199,12 +201,13 @@ static int hisi_irq_map(struct irq_domain *d, unsigned int virq, return 0; } -static const struct irq_domain_ops hisi_domain_ops = { - .map = hisi_irq_map, +static const struct irq_domain_ops hi6421_spmi_domain_ops = { + .map = hi6421_spmi_irq_map, .xlate = irq_domain_xlate_twocell, }; -static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *pmic) +static int get_pmic_device_tree_data(struct device_node *np, + struct hi6421_spmi_pmic *pmic) { int ret = 0; @@ -247,27 +250,29 @@ static int get_pmic_device_tree_data(struct device_node *np, struct hisi_pmic *p return ret; } -static void hisi_pmic_irq_prc(struct hisi_pmic *pmic) +static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic) { int i; for (i = 0 ; i < pmic->irq_mask_addr.array; i++) - hisi_pmic_write(pmic, pmic->irq_mask_addr.start_addr + i, HISI_MASK_STATE); + hi6421_spmi_pmic_write(pmic, pmic->irq_mask_addr.start_addr + i, + HISI_MASK_STATE); for (i = 0 ; i < pmic->irq_addr.array; i++) { - unsigned int pending = hisi_pmic_read(pmic, pmic->irq_addr.start_addr + i); + unsigned int pending = hi6421_spmi_pmic_read(pmic, pmic->irq_addr.start_addr + i); pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", pmic->irq_addr.start_addr + i, pending); - hisi_pmic_write(pmic, pmic->irq_addr.start_addr + i, HISI_MASK_STATE); + hi6421_spmi_pmic_write(pmic, pmic->irq_addr.start_addr + i, + HISI_MASK_STATE); } } -static int hisi_pmic_probe(struct spmi_device *pdev) +static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct hisi_pmic *pmic = NULL; + struct hi6421_spmi_pmic *pmic = NULL; enum of_gpio_flags flags; int ret = 0; int i; @@ -305,14 +310,14 @@ static int hisi_pmic_probe(struct spmi_device *pdev) pmic->irq = gpio_to_irq(pmic->gpio); /* mask && clear IRQ status */ - hisi_pmic_irq_prc(pmic); + hi6421_spmi_pmic_irq_prc(pmic); pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); if (!pmic->irqs) goto irq_malloc; pmic->domain = irq_domain_add_simple(np, pmic->irqnum, 0, - &hisi_domain_ops, pmic); + &hi6421_spmi_domain_ops, pmic); if (!pmic->domain) { dev_err(dev, "failed irq domain add simple!\n"); ret = -ENODEV; @@ -330,7 +335,7 @@ static int hisi_pmic_probe(struct spmi_device *pdev) pr_info("[%s]. pmic->irqs[%d] = %d\n", __func__, i, pmic->irqs[i]); } - ret = request_threaded_irq(pmic->irq, hisi_irq_handler, NULL, + ret = request_threaded_irq(pmic->irq, hi6421_spmi_irq_handler, NULL, IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, "pmic", pmic); if (ret < 0) { @@ -365,9 +370,9 @@ irq_malloc: return ret; } -static void hisi_pmic_remove(struct spmi_device *pdev) +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev) { - struct hisi_pmic *pmic = dev_get_drvdata(&pdev->dev); + struct hi6421_spmi_pmic *pmic = dev_get_drvdata(&pdev->dev); free_irq(pmic->irq, pmic); gpio_free(pmic->gpio); @@ -380,15 +385,15 @@ static const struct of_device_id pmic_spmi_id_table[] = { }; MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); -static struct spmi_driver hisi_pmic_driver = { +static struct spmi_driver hi6421_spmi_pmic_driver = { .driver = { .name = "hi6421-spmi-pmic", .of_match_table = pmic_spmi_id_table, }, - .probe = hisi_pmic_probe, - .remove = hisi_pmic_remove, + .probe = hi6421_spmi_pmic_probe, + .remove = hi6421_spmi_pmic_remove, }; -module_spmi_driver(hisi_pmic_driver); +module_spmi_driver(hi6421_spmi_pmic_driver); MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver"); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index 41b61de48259..d12ad7484018 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -17,49 +17,36 @@ #define HISI_ECO_MODE_ENABLE (1) #define HISI_ECO_MODE_DISABLE (0) -typedef int (*pmic_ocp_callback)(char *); -int hisi_pmic_special_ocp_register(char *power_name, pmic_ocp_callback handler); - -struct irq_mask_info { +struct hi6421_spmi_irq_mask_info { int start_addr; int array; }; -struct irq_info { +struct hi6421_spmi_irq_info { int start_addr; int array; }; -struct bit_info { - int addr; - int bit; -}; - -struct write_lock { - int addr; - int val; -}; - -struct hisi_pmic { - struct resource *res; - struct device *dev; - void __iomem *regs; - spinlock_t lock; - struct irq_domain *domain; - int irq; - int gpio; - unsigned int *irqs; - int irqnum; - int irqarray; - struct irq_mask_info irq_mask_addr; - struct irq_info irq_addr; +struct hi6421_spmi_pmic { + struct resource *res; + struct device *dev; + void __iomem *regs; + spinlock_t lock; + struct irq_domain *domain; + int irq; + int gpio; + unsigned int *irqs; + int irqnum; + int irqarray; + struct hi6421_spmi_irq_mask_info irq_mask_addr; + struct hi6421_spmi_irq_info irq_addr; }; -u32 hisi_pmic_read(struct hisi_pmic *pmic, int reg); -void hisi_pmic_write(struct hisi_pmic *pmic, int reg, u32 val); -void hisi_pmic_rmw(struct hisi_pmic *pmic, int reg, u32 mask, u32 bits); +u32 hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg); +void hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val); +void hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, u32 mask, u32 bits); -enum pmic_irq_list { +enum hi6421_spmi_pmic_irq_list { OTMP = 0, VBUS_CONNECT, VBUS_DISCONNECT, -- cgit v1.2.3 From 4d70881afdeb261ee318447ed0232b96946ecabc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:39 +0200 Subject: staging: mfd: hi6421-spmi-pmic: fix some coding style issues Checkpatch complains about some minor issues inside this driver that were not addressed by the previous patch. Address them. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/84b53d20632c84cc60b8dadfe937f3c54b355cef.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 4 ++-- include/linux/mfd/hi6421-spmi-pmic.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 09cedfa1e4bb..d8b84d64041e 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -189,7 +189,7 @@ static struct irq_chip hi6421_spmi_pmu_irqchip = { }; static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq, - irq_hw_number_t hw) + irq_hw_number_t hw) { struct hi6421_spmi_pmic *pmic = d->host_data; @@ -350,7 +350,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) * The logic below will rely that the pmic is already stored at * drvdata. */ - dev_dbg(&pdev->dev, "SPMI-PMIC: adding childs for %pOF\n", + dev_dbg(&pdev->dev, "SPMI-PMIC: adding children for %pOF\n", pdev->dev.of_node); ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs), diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index d12ad7484018..403fd8bb45fa 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -38,7 +38,7 @@ struct hi6421_spmi_pmic { unsigned int *irqs; int irqnum; int irqarray; - struct hi6421_spmi_irq_mask_info irq_mask_addr; + struct hi6421_spmi_irq_mask_info irq_mask_addr; struct hi6421_spmi_irq_info irq_addr; }; -- cgit v1.2.3 From 926648d4791226ad5867abeefef10365e065a697 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:40 +0200 Subject: staging: mfd: hi6421-spmi-pmic: add it to the building system Now that the driver is ready, place it at the build system. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/952e11ea1a33beaf67d6dc355d5c0f99ab4fb964.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/Kconfig | 17 +++++++++++++++++ drivers/staging/hikey9xx/Makefile | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index 31eb01b5ef2b..7ca083b7e94d 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +# to be placed at drivers/spmi config SPMI_HISI3670 tristate "Hisilicon 3670 SPMI Controller" select IRQ_DOMAIN_HIERARCHY @@ -8,3 +9,19 @@ config SPMI_HISI3670 If you say yes to this option, support will be included for the built-in SPMI PMIC Arbiter interface on Hisilicon 3670 processors. + +# to be placed at drivers/mfd +config MFD_HI6421_SPMI + tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" + depends on OF + select MFD_CORE + select REGMAP_MMIO + help + Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes + multi-functions, such as regulators, RTC, codec, Coulomb counter, + etc. + + This driver includes core APIs _only_. You have to select + individual components like voltage regulators under corresponding + menus in order to enable them. + We communicate with the Hi6421v600 via a SPMI bus. diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile index e8085abce444..79de37da7a8f 100644 --- a/drivers/staging/hikey9xx/Makefile +++ b/drivers/staging/hikey9xx/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o +obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o +obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o -- cgit v1.2.3 From 6b946699252c68b0c792896eded217269c9aa286 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:41 +0200 Subject: staging: mfd: hi6421-spmi-pmic: cleanup the code There are several small cleanups that can be done in order to make the code more prepared to be upstreamed. Suggested-by: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/823792ba2f69e613629ab52a33e5728d54e2288b.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 151 ++++++++++++---------------- include/linux/mfd/hi6421-spmi-pmic.h | 12 ++- 2 files changed, 74 insertions(+), 89 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index d8b84d64041e..9d73458ca65a 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -17,26 +17,23 @@ * */ -#include #include #include -#include #include #include #include +#include #include -#include -#include +#include +#include #include #include #include +#include #include -#include -#include +#include +#include #include -#ifndef NO_IRQ -#define NO_IRQ 0 -#endif /* 8-bit register offset in PMIC */ #define HISI_MASK_STATE 0xff @@ -46,12 +43,11 @@ #define HISI_IRQ_KEY_DOWN 7 #define HISI_IRQ_KEY_UP 6 -/*#define HISI_NR_IRQ 25*/ -#define HISI_MASK_FIELD 0xFF +#define HISI_MASK_FIELD 0xFF #define HISI_BITS 8 /*define the first group interrupt register number*/ -#define HISI_PMIC_FIRST_GROUP_INT_NUM 2 +#define HISI_PMIC_FIRST_GROUP_INT_NUM 2 static const struct mfd_cell hi6421v600_devs[] = { { .name = "hi6421v600-regulator", }, @@ -62,58 +58,60 @@ static const struct mfd_cell hi6421v600_devs[] = { * Hisilicon SoC use hardware to map PMIC register into SoC mapping. * At here, we are accessing SoC register with 32-bit. */ -u32 hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg) +int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg) { - u32 ret; - u8 read_value = 0; struct spmi_device *pdev; + u8 read_value = 0; + u32 ret; pdev = to_spmi_device(pmic->dev); if (!pdev) { pr_err("%s: pdev get failed!\n", __func__); - return 0; + return -ENODEV; } - ret = spmi_ext_register_readl(pdev, reg, - (unsigned char *)&read_value, 1); + ret = spmi_ext_register_readl(pdev, reg, &read_value, 1); if (ret) { pr_err("%s: spmi_ext_register_readl failed!\n", __func__); - return 0; + return ret; } - return (u32)read_value; + return read_value; } EXPORT_SYMBOL(hi6421_spmi_pmic_read); -void hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val) +int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val) { - u32 ret; struct spmi_device *pdev; + u32 ret; pdev = to_spmi_device(pmic->dev); if (!pdev) { pr_err("%s: pdev get failed!\n", __func__); - return; + return -ENODEV; } ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1); - if (ret) { + if (ret) pr_err("%s: spmi_ext_register_writel failed!\n", __func__); - return; - } + + return ret; } EXPORT_SYMBOL(hi6421_spmi_pmic_write); -void hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, - u32 mask, u32 bits) +int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, + u32 mask, u32 bits) { - u32 data; unsigned long flags; + u32 data; + int ret; spin_lock_irqsave(&pmic->lock, flags); data = hi6421_spmi_pmic_read(pmic, reg) & ~mask; data |= mask & bits; - hi6421_spmi_pmic_write(pmic, reg, data); + ret = hi6421_spmi_pmic_write(pmic, reg, data); spin_unlock_irqrestore(&pmic->lock, flags); + + return ret; } EXPORT_SYMBOL(hi6421_spmi_pmic_rmw); @@ -124,16 +122,16 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data) int i, offset; for (i = 0; i < pmic->irqarray; i++) { - pending = hi6421_spmi_pmic_read(pmic, (i + pmic->irq_addr.start_addr)); + pending = hi6421_spmi_pmic_read(pmic, (i + pmic->irq_addr)); pending &= HISI_MASK_FIELD; if (pending != 0) pr_debug("pending[%d]=0x%lx\n\r", i, pending); - hi6421_spmi_pmic_write(pmic, (i + pmic->irq_addr.start_addr), - pending); + hi6421_spmi_pmic_write(pmic, (i + pmic->irq_addr), pending); /* solve powerkey order */ - if ((i == HISI_IRQ_KEY_NUM) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { + if ((i == HISI_IRQ_KEY_NUM) && + ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]); generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]); pending &= (~HISI_IRQ_KEY_VALUE); @@ -155,7 +153,7 @@ static void hi6421_spmi_irq_mask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - offset += pmic->irq_mask_addr.start_addr; + offset += pmic->irq_mask_addr; spin_lock_irqsave(&pmic->lock, flags); data = hi6421_spmi_pmic_read(pmic, offset); @@ -171,7 +169,7 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - offset += pmic->irq_mask_addr.start_addr; + offset += pmic->irq_mask_addr; spin_lock_irqsave(&pmic->lock, flags); data = hi6421_spmi_pmic_read(pmic, offset); @@ -211,36 +209,32 @@ static int get_pmic_device_tree_data(struct device_node *np, { int ret = 0; - /*get pmic irq num*/ - ret = of_property_read_u32_array(np, "irq-num", - &pmic->irqnum, 1); + /* IRQ number */ + ret = of_property_read_u32(np, "irq-num", &pmic->irqnum); if (ret) { pr_err("no irq-num property set\n"); ret = -ENODEV; return ret; } - /*get pmic irq array number*/ - ret = of_property_read_u32_array(np, "irq-array", - &pmic->irqarray, 1); + /* Size of IRQ array */ + ret = of_property_read_u32(np, "irq-array", &pmic->irqarray); if (ret) { pr_err("no irq-array property set\n"); ret = -ENODEV; return ret; } - /*SOC_PMIC_IRQ_MASK_0_ADDR*/ - ret = of_property_read_u32_array(np, "irq-mask-addr", - (int *)&pmic->irq_mask_addr, 2); + /* SOC_PMIC_IRQ_MASK_0_ADDR */ + ret = of_property_read_u32(np, "irq-mask-addr", &pmic->irq_mask_addr); if (ret) { pr_err("no irq-mask-addr property set\n"); ret = -ENODEV; return ret; } - /*SOC_PMIC_IRQ0_ADDR*/ - ret = of_property_read_u32_array(np, "irq-addr", - (int *)&pmic->irq_addr, 2); + /* SOC_PMIC_IRQ0_ADDR */ + ret = of_property_read_u32(np, "irq-addr", &pmic->irq_addr); if (ret) { pr_err("no irq-addr property set\n"); ret = -ENODEV; @@ -252,18 +246,18 @@ static int get_pmic_device_tree_data(struct device_node *np, static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic) { - int i; + int i, pending; - for (i = 0 ; i < pmic->irq_mask_addr.array; i++) - hi6421_spmi_pmic_write(pmic, pmic->irq_mask_addr.start_addr + i, + for (i = 0 ; i < pmic->irqarray; i++) + hi6421_spmi_pmic_write(pmic, pmic->irq_mask_addr + i, HISI_MASK_STATE); - for (i = 0 ; i < pmic->irq_addr.array; i++) { - unsigned int pending = hi6421_spmi_pmic_read(pmic, pmic->irq_addr.start_addr + i); + for (i = 0 ; i < pmic->irqarray; i++) { + pending = hi6421_spmi_pmic_read(pmic, pmic->irq_addr + i); pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", - pmic->irq_addr.start_addr + i, pending); - hi6421_spmi_pmic_write(pmic, pmic->irq_addr.start_addr + i, + pmic->irq_addr + i, pending); + hi6421_spmi_pmic_write(pmic, pmic->irq_addr + i, HISI_MASK_STATE); } } @@ -272,36 +266,32 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct hi6421_spmi_pmic *pmic = NULL; - enum of_gpio_flags flags; - int ret = 0; - int i; + struct hi6421_spmi_pmic *pmic; unsigned int virq; + int ret, i; pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL); if (!pmic) return -ENOMEM; - /*TODO: get pmic dts info*/ ret = get_pmic_device_tree_data(np, pmic); if (ret) { - dev_err(&pdev->dev, "Error reading hisi pmic dts\n"); + dev_err(dev, "Error reading hisi pmic dts\n"); return ret; } - /* TODO: get and enable clk request */ spin_lock_init(&pmic->lock); pmic->dev = dev; - pmic->gpio = of_get_gpio_flags(np, 0, &flags); + pmic->gpio = of_get_gpio(np, 0); if (pmic->gpio < 0) return pmic->gpio; if (!gpio_is_valid(pmic->gpio)) return -EINVAL; - ret = gpio_request_one(pmic->gpio, GPIOF_IN, "pmic"); + ret = devm_gpio_request_one(dev, pmic->gpio, GPIOF_IN, "pmic"); if (ret < 0) { dev_err(dev, "failed to request gpio%d\n", pmic->gpio); return ret; @@ -309,7 +299,6 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) pmic->irq = gpio_to_irq(pmic->gpio); - /* mask && clear IRQ status */ hi6421_spmi_pmic_irq_prc(pmic); pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); @@ -321,27 +310,27 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) if (!pmic->domain) { dev_err(dev, "failed irq domain add simple!\n"); ret = -ENODEV; - goto irq_domain; + goto irq_malloc; } for (i = 0; i < pmic->irqnum; i++) { virq = irq_create_mapping(pmic->domain, i); - if (virq == NO_IRQ) { - pr_debug("Failed mapping hwirq\n"); + if (!virq) { + dev_err(dev, "Failed mapping hwirq\n"); ret = -ENOSPC; - goto irq_create_mapping; + goto irq_malloc; } pmic->irqs[i] = virq; - pr_info("[%s]. pmic->irqs[%d] = %d\n", __func__, i, pmic->irqs[i]); + dev_dbg(dev, "%s: pmic->irqs[%d] = %d\n", + __func__, i, pmic->irqs[i]); } ret = request_threaded_irq(pmic->irq, hi6421_spmi_irq_handler, NULL, IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND, "pmic", pmic); if (ret < 0) { - dev_err(dev, "could not claim pmic %d\n", ret); - ret = -ENODEV; - goto request_theaded_irq; + dev_err(dev, "could not claim pmic IRQ: error %d\n", ret); + goto irq_malloc; } dev_set_drvdata(&pdev->dev, pmic); @@ -355,18 +344,14 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs), NULL, 0, NULL); - if (ret) { - dev_err(&pdev->dev, "Failed to add child devices: %d\n", ret); - return ret; - } + if (!ret) + return 0; - return 0; + dev_err(dev, "Failed to add child devices: %d\n", ret); -request_theaded_irq: -irq_create_mapping: -irq_domain: irq_malloc: - gpio_free(pmic->gpio); + free_irq(pmic->irq, pmic); + return ret; } @@ -375,8 +360,6 @@ static void hi6421_spmi_pmic_remove(struct spmi_device *pdev) struct hi6421_spmi_pmic *pmic = dev_get_drvdata(&pdev->dev); free_irq(pmic->irq, pmic); - gpio_free(pmic->gpio); - devm_kfree(&pdev->dev, pmic); } static const struct of_device_id pmic_spmi_id_table[] = { diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index 403fd8bb45fa..ff3adfa7b3ec 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -36,15 +36,17 @@ struct hi6421_spmi_pmic { int irq; int gpio; unsigned int *irqs; + int irqnum; int irqarray; - struct hi6421_spmi_irq_mask_info irq_mask_addr; - struct hi6421_spmi_irq_info irq_addr; + int irq_mask_addr; + int irq_addr; }; -u32 hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg); -void hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val); -void hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, u32 mask, u32 bits); +int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg); +int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val); +int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg, + u32 mask, u32 bits); enum hi6421_spmi_pmic_irq_list { OTMP = 0, -- cgit v1.2.3 From 42f24d9d446a74fe59b08cf54191b10219526c0a Mon Sep 17 00:00:00 2001 From: Mayulong Date: Mon, 17 Aug 2020 09:10:42 +0200 Subject: staging: regulator: add a regulator driver for HiSilicon 6421v600 SPMI PMIC Add the regulator driver for the LDO lines provided by the HiSilicon 6421v600 SPMI PMIC device. [mchehab+huawei@kernel.org: keep just the regulator driver on this patch, renaming it to better fit at upstream namespace] The compete patch is at: https://github.com/96boards-hikey/linux/commit/08464419fba2 Signed-off-by: Mayulong Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/6e5f6a811edf77575ddaa84ab6542cc646024423.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 741 ++++++++++++++++++++++++ 1 file changed, 741 insertions(+) create mode 100644 drivers/staging/hikey9xx/hi6421v600-regulator.c (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c new file mode 100644 index 000000000000..941bfe32bf5b --- /dev/null +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -0,0 +1,741 @@ +/* + * Device driver for regulators in Hisi IC + * + * Copyright (c) 2013 Linaro Ltd. + * Copyright (c) 2011 Hisilicon. + * + * Guodong Xu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HISI_PMIC_DEBUG +#include +#endif +#include +#include +#include + +#if 1 +#define BRAND_DEBUG(args...) pr_debug(args); +#else +#define BRAND_DEBUG(args...) +#endif + +struct hisi_regulator_register_info { + u32 ctrl_reg; + u32 enable_mask; + u32 eco_mode_mask; + u32 vset_reg; + u32 vset_mask; +}; + +struct hisi_regulator { + const char *name; + struct hisi_regulator_register_info register_info; + struct timeval last_off_time; + u32 off_on_delay; + u32 eco_uA; + struct regulator_desc rdesc; + int (*dt_parse)(struct hisi_regulator *, struct spmi_device *); +}; + +static DEFINE_MUTEX(enable_mutex); +struct timeval last_enabled; + + +static inline struct hisi_pmic *rdev_to_pmic(struct regulator_dev *dev) +{ + /* regulator_dev parent to-> + * hisi regulator platform device_dev parent to-> + * hisi pmic platform device_dev + */ + return dev_get_drvdata(rdev_get_dev(dev)->parent->parent); +} + +/* helper function to ensure when it returns it is at least 'delay_us' + * microseconds after 'since'. + */ +static void ensured_time_after(struct timeval since, u32 delay_us) +{ + struct timeval now; + u64 elapsed_ns64, delay_ns64; + u32 actual_us32; + + delay_ns64 = delay_us * NSEC_PER_USEC; + do_gettimeofday(&now); + elapsed_ns64 = timeval_to_ns(&now) - timeval_to_ns(&since); + if (delay_ns64 > elapsed_ns64) { + actual_us32 = ((u32)(delay_ns64 - elapsed_ns64) / + NSEC_PER_USEC); + if (actual_us32 >= 1000) { + mdelay(actual_us32 / 1000); /*lint !e647 */ + udelay(actual_us32 % 1000); + } else if (actual_us32 > 0) { + udelay(actual_us32); + } + } + return; +} + +static int hisi_regulator_is_enabled(struct regulator_dev *dev) +{ + u32 reg_val; + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + + reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); + BRAND_DEBUG("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", __func__, sreg->register_info.ctrl_reg,\ + (reg_val & sreg->register_info.enable_mask)); + + return ((reg_val & sreg->register_info.enable_mask) != 0); +} + +static int hisi_regulator_enable(struct regulator_dev *dev) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + + /* keep a distance of off_on_delay from last time disabled */ + ensured_time_after(sreg->last_off_time, sreg->off_on_delay); + + BRAND_DEBUG("<[%s]: off_on_delay=%dus>\n", __func__, sreg->off_on_delay); + + /* cannot enable more than one regulator at one time */ + mutex_lock(&enable_mutex); + ensured_time_after(last_enabled, HISI_REGS_ENA_PROTECT_TIME); + + /* set enable register */ + hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, + sreg->register_info.enable_mask, + sreg->register_info.enable_mask); + BRAND_DEBUG("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", __func__, sreg->register_info.ctrl_reg,\ + sreg->register_info.enable_mask); + + do_gettimeofday(&last_enabled); + mutex_unlock(&enable_mutex); + + return 0; +} + +static int hisi_regulator_disable(struct regulator_dev *dev) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + + /* set enable register to 0 */ + hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, + sreg->register_info.enable_mask, 0); + + do_gettimeofday(&sreg->last_off_time); + + return 0; +} + +static int hisi_regulator_get_voltage(struct regulator_dev *dev) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + u32 reg_val, selector; + + /* get voltage selector */ + reg_val = hisi_pmic_read(pmic, sreg->register_info.vset_reg); + BRAND_DEBUG("<[%s]: vset_reg=0x%x>\n", __func__, sreg->register_info.vset_reg); + + selector = (reg_val & sreg->register_info.vset_mask) >> + (ffs(sreg->register_info.vset_mask) - 1); + + return sreg->rdesc.ops->list_voltage(dev, selector); +} + +static int hisi_regulator_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, unsigned *selector) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + u32 vsel; + int ret = 0; + + for (vsel = 0; vsel < sreg->rdesc.n_voltages; vsel++) { + int uV = sreg->rdesc.volt_table[vsel]; + /* Break at the first in-range value */ + if (min_uV <= uV && uV <= max_uV) + break; + } + + /* unlikely to happen. sanity test done by regulator core */ + if (unlikely(vsel == sreg->rdesc.n_voltages)) + return -EINVAL; + + *selector = vsel; + /* set voltage selector */ + hisi_pmic_rmw(pmic, sreg->register_info.vset_reg, + sreg->register_info.vset_mask, + vsel << (ffs(sreg->register_info.vset_mask) - 1)); + + BRAND_DEBUG("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", __func__,\ + sreg->register_info.vset_reg,\ + sreg->register_info.vset_mask,\ + vsel << (ffs(sreg->register_info.vset_mask) - 1)\ + ); + + return ret; +} + +static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + u32 reg_val; + + reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); + BRAND_DEBUG("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", __func__, reg_val,\ + sreg->register_info.ctrl_reg,\ + sreg->register_info.eco_mode_mask\ + ); + + if (reg_val & sreg->register_info.eco_mode_mask) + return REGULATOR_MODE_IDLE; + else + return REGULATOR_MODE_NORMAL; +} + +static int hisi_regulator_set_mode(struct regulator_dev *dev, + unsigned int mode) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hisi_pmic *pmic = rdev_to_pmic(dev); + u32 eco_mode; + + switch (mode) { + case REGULATOR_MODE_NORMAL: + eco_mode = HISI_ECO_MODE_DISABLE; + break; + case REGULATOR_MODE_IDLE: + eco_mode = HISI_ECO_MODE_ENABLE; + break; + default: + return -EINVAL; + } + + /* set mode */ + hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, + sreg->register_info.eco_mode_mask, + eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); + + BRAND_DEBUG("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", __func__,\ + sreg->register_info.ctrl_reg,\ + sreg->register_info.eco_mode_mask,\ + eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)\ + ); + return 0; +} + + +unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, + int input_uV, int output_uV, int load_uA) +{ + struct hisi_regulator *sreg = rdev_get_drvdata(dev); + + if ((load_uA == 0) || ((unsigned int)load_uA > sreg->eco_uA)) + return REGULATOR_MODE_NORMAL; + else + return REGULATOR_MODE_IDLE; +} + +static int hisi_dt_parse_common(struct hisi_regulator *sreg, + struct spmi_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct regulator_desc *rdesc = &sreg->rdesc; + unsigned int register_info[3] = {0}; + int ret = 0; + + /* parse .register_info.ctrl_reg */ + ret = of_property_read_u32_array(np, "hisilicon,hisi-ctrl", + register_info, 3); + if (ret) { + dev_err(dev, "no hisilicon,hisi-ctrl property set\n"); + goto dt_parse_common_end; + } + sreg->register_info.ctrl_reg = register_info[0]; + sreg->register_info.enable_mask = register_info[1]; + sreg->register_info.eco_mode_mask = register_info[2]; + + /* parse .register_info.vset_reg */ + ret = of_property_read_u32_array(np, "hisilicon,hisi-vset", + register_info, 2); + if (ret) { + dev_err(dev, "no hisilicon,hisi-vset property set\n"); + goto dt_parse_common_end; + } + sreg->register_info.vset_reg = register_info[0]; + sreg->register_info.vset_mask = register_info[1]; + + /* parse .off-on-delay */ + ret = of_property_read_u32(np, "hisilicon,hisi-off-on-delay-us", + &sreg->off_on_delay); + if (ret) { + dev_err(dev, "no hisilicon,hisi-off-on-delay-us property set\n"); + goto dt_parse_common_end; + } + + /* parse .enable_time */ + ret = of_property_read_u32(np, "hisilicon,hisi-enable-time-us", + &rdesc->enable_time); + if (ret) { + dev_err(dev, "no hisilicon,hisi-enable-time-us property set\n"); + goto dt_parse_common_end; + } + + /* parse .eco_uA */ + ret = of_property_read_u32(np, "hisilicon,hisi-eco-microamp", + &sreg->eco_uA); + if (ret) { + sreg->eco_uA = 0; + ret = 0; + } + +dt_parse_common_end: + return ret; +} + +static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, + struct spmi_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct regulator_desc *rdesc = &sreg->rdesc; + unsigned int *v_table; + int ret = 0; + + /* parse .n_voltages, and .volt_table */ + ret = of_property_read_u32(np, "hisilicon,hisi-n-voltages", + &rdesc->n_voltages); + if (ret) { + dev_err(dev, "no hisilicon,hisi-n-voltages property set\n"); + goto dt_parse_ldo_end; + } + + /* alloc space for .volt_table */ + v_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages, + GFP_KERNEL); + if (unlikely(!v_table)) { + ret = -ENOMEM; + dev_err(dev, "no memory for .volt_table\n"); + goto dt_parse_ldo_end; + } + + ret = of_property_read_u32_array(np, "hisilicon,hisi-vset-table", + v_table, rdesc->n_voltages); + if (ret) { + dev_err(dev, "no hisilicon,hisi-vset-table property set\n"); + goto dt_parse_ldo_end1; + } + rdesc->volt_table = v_table; + + /* parse hisi regulator's dt common part */ + ret = hisi_dt_parse_common(sreg, pdev); + if (ret) { + dev_err(dev, "failure in hisi_dt_parse_common\n"); + goto dt_parse_ldo_end1; + } + + return ret; + +dt_parse_ldo_end1: +dt_parse_ldo_end: + return ret; +} + +static struct regulator_ops hisi_ldo_rops = { + .is_enabled = hisi_regulator_is_enabled, + .enable = hisi_regulator_enable, + .disable = hisi_regulator_disable, + .list_voltage = regulator_list_voltage_table, + .get_voltage = hisi_regulator_get_voltage, + .set_voltage = hisi_regulator_set_voltage, + .get_mode = hisi_regulator_get_mode, + .set_mode = hisi_regulator_set_mode, + .get_optimum_mode = hisi_regulator_get_optimum_mode, +}; + +static const struct hisi_regulator hisi_regulator_ldo = { + .rdesc = { + .ops = &hisi_ldo_rops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + }, + .dt_parse = hisi_dt_parse_ldo, +}; + +static struct of_device_id of_hisi_regulator_match_tbl[] = { + { + .compatible = "hisilicon-hisi-ldo", + .data = &hisi_regulator_ldo, + }, + { /* end */ } +}; + +#ifdef CONFIG_HISI_PMIC_DEBUG +extern void get_current_regulator_dev(struct seq_file *s); +extern void set_regulator_state(char *ldo_name, int value); +extern void get_regulator_state(char *ldo_name); +extern int set_regulator_voltage(char *ldo_name, unsigned int vol_value); + +u32 pmu_atoi(char *s) +{ + char *p = s; + char c; + u64 ret = 0; + if (s == NULL) + return 0; + while ((c = *p++) != '\0') { + if ('0' <= c && c <= '9') { + ret *= 10; + ret += (u64)((unsigned char)c - '0'); + if (ret > U32_MAX) + return 0; + } else { + break; + } + } + return (u32)ret; +} +static int dbg_hisi_regulator_show(struct seq_file *s, void *data) +{ + seq_printf(s, "\n\r"); + seq_printf(s, "%-13s %-15s %-15s %-15s %-15s\n\r", + "LDO_NAME", "ON/OFF", "Use_count", "Open_count", "Always_on"); + seq_printf(s, "-----------------------------------------" + "-----------------------------------------------\n\r"); + get_current_regulator_dev(s); + return 0; +} + +static int dbg_hisi_regulator_open(struct inode *inode, struct file *file) +{ + return single_open(file, dbg_hisi_regulator_show, inode->i_private); +} + +static const struct file_operations debug_regulator_state_fops = { + .open = dbg_hisi_regulator_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int dbg_control_regulator_show(struct seq_file *s, void *data) +{ + printk(" \n\r \ + ---------------------------------------------------------------------------------\n\r \ + |usage: |\n\r \ + | S = state R = read V = voltage |\n\r \ + | set ldo state and voltage |\n\r \ + | get ldo state and current voltage |\n\r \ + |example: |\n\r \ + | echo S ldo16 0 > control_regulator :disable ldo16 |\n\r \ + | echo S ldo16 1 > control_regulator :enable ldo16 |\n\r \ + | echo R ldo16 > control_regulator :get ldo16 state and voltage |\n\r \ + | echo V ldo16 xxx > control_regulator :set ldo16 voltage |\n\r \ + ---------------------------------------------------------------------------------\n\r"); + return 0; +} +static ssize_t dbg_control_regulator_set_value(struct file *filp, const char __user *buffer, + size_t count, loff_t *ppos) +{ + char tmp[128] = {0}; + char ptr[128] = {0}; + char *vol = NULL; + char num = 0; + unsigned int i; + int next_flag = 1; + + if (count >= 128) { + pr_info("error! buffer size big than internal buffer\n"); + return -EFAULT; + } + + if (copy_from_user(tmp, buffer, count)) { + pr_info("error!\n"); + return -EFAULT; + } + + if (tmp[0] == 'R' || tmp[0] == 'r') { + for (i = 2; i < (count - 1); i++) { + ptr[i - 2] = tmp[i]; + } + ptr[i - 2] = '\0'; + get_regulator_state(ptr); + } else if (tmp[0] == 'S' || tmp[0] == 's') { + for (i = 2; i < (count - 1); i++) { + if (tmp[i] == ' ') { + next_flag = 0; + ptr[i - 2] = '\0'; + continue; + } + if (next_flag) { + ptr[i - 2] = tmp[i]; + } else { + num = tmp[i] - 48; + } + } + set_regulator_state(ptr, num); + } else if (tmp[0] == 'V' || tmp[0] == 'v') { + for (i = 2; i < (count - 1); i++) { + if (tmp[i] == ' ') { + next_flag = 0; + ptr[i - 2] = '\0'; + continue; + } + if (next_flag) { + ptr[i - 2] = tmp[i]; + } else { + vol = &tmp[i]; + break; + } + } + set_regulator_voltage(ptr, pmu_atoi(vol)); + } + + *ppos += count; + + return count; +} + +static int dbg_control_regulator_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return single_open(file, dbg_control_regulator_show, &inode->i_private); +} + +static const struct file_operations set_control_regulator_fops = { + .open = dbg_control_regulator_open, + .read = seq_read, + .write = dbg_control_regulator_set_value, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + +static int hisi_regulator_probe(struct spmi_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct regulator_desc *rdesc; + struct regulator_dev *rdev; + struct hisi_regulator *sreg = NULL; + struct regulator_init_data *initdata; + struct regulator_config config = { }; + const struct of_device_id *match; + struct regulation_constraints *constraint; + const char *supplyname = NULL; +#ifdef CONFIG_HISI_PMIC_DEBUG + struct dentry *d; + static int debugfs_flag; +#endif + unsigned int temp_modes; + + const struct hisi_regulator *template = NULL; + int ret = 0; + /* to check which type of regulator this is */ + match = of_match_device(of_hisi_regulator_match_tbl, &pdev->dev); + if (NULL == match) { + pr_err("get hisi regulator fail!\n\r"); + return -EINVAL; + } + + template = match->data; +#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) + initdata = of_get_regulator_init_data(dev, np, NULL); +#else + initdata = of_get_regulator_init_data(dev, np); +#endif + if (NULL == initdata) { + pr_err("get regulator init data error !\n"); + return -EINVAL; + } + + /* hisi regulator supports two modes */ + constraint = &initdata->constraints; + + ret = of_property_read_u32_array(np, "hisilicon,valid-modes-mask", + &(constraint->valid_modes_mask), 1); + if (ret) { + pr_err("no hisilicon,valid-modes-mask property set\n"); + ret = -ENODEV; + return ret; + } + ret = of_property_read_u32_array(np, "hisilicon,valid-idle-mask", + &temp_modes, 1); + if (ret) { + pr_err("no hisilicon,valid-modes-mask property set\n"); + ret = -ENODEV; + return ret; + } + constraint->valid_ops_mask |= temp_modes; + + sreg = kmemdup(template, sizeof(*sreg), GFP_KERNEL); + if (!sreg) { + pr_err("template kememdup is fail. \n"); + return -ENOMEM; + } + sreg->name = initdata->constraints.name; + rdesc = &sreg->rdesc; + rdesc->name = sreg->name; + rdesc->min_uV = initdata->constraints.min_uV; + supplyname = of_get_property(np, "hisilicon,supply_name", NULL); + if (supplyname != NULL) { + initdata->supply_regulator = supplyname; + } + + /* to parse device tree data for regulator specific */ + ret = sreg->dt_parse(sreg, pdev); + if (ret) { + dev_err(dev, "device tree parameter parse error!\n"); + goto hisi_probe_end; + } + + config.dev = &pdev->dev; + config.init_data = initdata; + config.driver_data = sreg; + config.of_node = pdev->dev.of_node; + + /* register regulator */ + rdev = regulator_register(rdesc, &config); + if (IS_ERR(rdev)) { + dev_err(dev, "failed to register %s\n", + rdesc->name); + ret = PTR_ERR(rdev); + goto hisi_probe_end; + } + + BRAND_DEBUG("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", rdesc->name,\ + constraint->valid_modes_mask, constraint->valid_ops_mask); + + dev_set_drvdata(dev, rdev); +#ifdef CONFIG_HISI_PMIC_DEBUG + if (debugfs_flag == 0) { + d = debugfs_create_dir("hisi_regulator_debugfs", NULL); + if (!d) { + dev_err(dev, "failed to create hisi regulator debugfs dir !\n"); + ret = -ENOMEM; + goto hisi_probe_fail; + } + (void) debugfs_create_file("regulator_state", S_IRUSR, + d, NULL, &debug_regulator_state_fops); + + (void) debugfs_create_file("control_regulator", S_IRUSR, + d, NULL, &set_control_regulator_fops); + debugfs_flag = 1; + } +#endif + +#ifdef CONFIG_HISI_PMIC_DEBUG +hisi_probe_fail: + if (ret) + regulator_unregister(rdev); +#endif +hisi_probe_end: + if (ret) + kfree(sreg); + return ret; +} + +static void hisi_regulator_remove(struct spmi_device *pdev) +{ + struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev); + struct hisi_regulator *sreg = rdev_get_drvdata(rdev); + + regulator_unregister(rdev); + + /* TODO: should i worry about that? devm_kzalloc */ + if (sreg->rdesc.volt_table) + devm_kfree(&pdev->dev, (unsigned int *)sreg->rdesc.volt_table); + + kfree(sreg); +} +static int hisi_regulator_suspend(struct device *dev, pm_message_t state) +{ + struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); + + if (NULL == hisi_regulator) { + pr_err("%s:regulator is NULL\n", __func__); + return -ENOMEM; + } + + pr_info("%s:+\n", __func__); + pr_info("%s:-\n", __func__); + + return 0; +}/*lint !e715 */ + +static int hisi_regulator_resume(struct device *dev) +{ + struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); + + if (NULL == hisi_regulator) { + pr_err("%s:regulator is NULL\n", __func__); + return -ENOMEM; + } + + pr_info("%s:+\n", __func__); + pr_info("%s:-\n", __func__); + + return 0; +} + +static struct spmi_driver hisi_pmic_driver = { + .driver = { + .name = "hisi_regulator", + .owner = THIS_MODULE, + .of_match_table = of_hisi_regulator_match_tbl, + .suspend = hisi_regulator_suspend, + .resume = hisi_regulator_resume, + }, + .probe = hisi_regulator_probe, + .remove = hisi_regulator_remove, +}; + +static int __init hisi_regulator_init(void) +{ + return spmi_driver_register(&hisi_pmic_driver); +} + +static void __exit hisi_regulator_exit(void) +{ + spmi_driver_unregister(&hisi_pmic_driver); +} + +fs_initcall(hisi_regulator_init); +module_exit(hisi_regulator_exit); + +MODULE_DESCRIPTION("Hisi regulator driver"); +MODULE_LICENSE("GPL v2"); + -- cgit v1.2.3 From 0e0473c8387b656bce8a3f6fe38fed7e1bb2761d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:43 +0200 Subject: staging: regulator: hi6421v600-regulator: get rid of unused code Get rid of the sysfs code and other parts of the driver which aren't needed upstream. If needed later, this patch can be (partially?) reversed. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/698b2c7bdc92e336d2559bc65415807499b0e3a8.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 196 +----------------------- 1 file changed, 8 insertions(+), 188 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 941bfe32bf5b..7bc0ae27b110 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -34,19 +34,10 @@ #include #include #include -#ifdef CONFIG_HISI_PMIC_DEBUG -#include -#endif #include #include #include -#if 1 -#define BRAND_DEBUG(args...) pr_debug(args); -#else -#define BRAND_DEBUG(args...) -#endif - struct hisi_regulator_register_info { u32 ctrl_reg; u32 enable_mask; @@ -110,7 +101,7 @@ static int hisi_regulator_is_enabled(struct regulator_dev *dev) struct hisi_pmic *pmic = rdev_to_pmic(dev); reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - BRAND_DEBUG("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", __func__, sreg->register_info.ctrl_reg,\ + pr_debug("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", __func__, sreg->register_info.ctrl_reg,\ (reg_val & sreg->register_info.enable_mask)); return ((reg_val & sreg->register_info.enable_mask) != 0); @@ -124,7 +115,7 @@ static int hisi_regulator_enable(struct regulator_dev *dev) /* keep a distance of off_on_delay from last time disabled */ ensured_time_after(sreg->last_off_time, sreg->off_on_delay); - BRAND_DEBUG("<[%s]: off_on_delay=%dus>\n", __func__, sreg->off_on_delay); + pr_debug("<[%s]: off_on_delay=%dus>\n", __func__, sreg->off_on_delay); /* cannot enable more than one regulator at one time */ mutex_lock(&enable_mutex); @@ -134,7 +125,7 @@ static int hisi_regulator_enable(struct regulator_dev *dev) hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, sreg->register_info.enable_mask, sreg->register_info.enable_mask); - BRAND_DEBUG("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", __func__, sreg->register_info.ctrl_reg,\ + pr_debug("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", __func__, sreg->register_info.ctrl_reg,\ sreg->register_info.enable_mask); do_gettimeofday(&last_enabled); @@ -165,7 +156,7 @@ static int hisi_regulator_get_voltage(struct regulator_dev *dev) /* get voltage selector */ reg_val = hisi_pmic_read(pmic, sreg->register_info.vset_reg); - BRAND_DEBUG("<[%s]: vset_reg=0x%x>\n", __func__, sreg->register_info.vset_reg); + pr_debug("<[%s]: vset_reg=0x%x>\n", __func__, sreg->register_info.vset_reg); selector = (reg_val & sreg->register_info.vset_mask) >> (ffs(sreg->register_info.vset_mask) - 1); @@ -198,7 +189,7 @@ static int hisi_regulator_set_voltage(struct regulator_dev *dev, sreg->register_info.vset_mask, vsel << (ffs(sreg->register_info.vset_mask) - 1)); - BRAND_DEBUG("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", __func__,\ + pr_debug("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", __func__,\ sreg->register_info.vset_reg,\ sreg->register_info.vset_mask,\ vsel << (ffs(sreg->register_info.vset_mask) - 1)\ @@ -214,7 +205,7 @@ static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) u32 reg_val; reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - BRAND_DEBUG("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", __func__, reg_val,\ + pr_debug("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", __func__, reg_val,\ sreg->register_info.ctrl_reg,\ sreg->register_info.eco_mode_mask\ ); @@ -248,7 +239,7 @@ static int hisi_regulator_set_mode(struct regulator_dev *dev, sreg->register_info.eco_mode_mask, eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); - BRAND_DEBUG("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", __func__,\ + pr_debug("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", __func__,\ sreg->register_info.ctrl_reg,\ sreg->register_info.eco_mode_mask,\ eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)\ @@ -403,147 +394,6 @@ static struct of_device_id of_hisi_regulator_match_tbl[] = { { /* end */ } }; -#ifdef CONFIG_HISI_PMIC_DEBUG -extern void get_current_regulator_dev(struct seq_file *s); -extern void set_regulator_state(char *ldo_name, int value); -extern void get_regulator_state(char *ldo_name); -extern int set_regulator_voltage(char *ldo_name, unsigned int vol_value); - -u32 pmu_atoi(char *s) -{ - char *p = s; - char c; - u64 ret = 0; - if (s == NULL) - return 0; - while ((c = *p++) != '\0') { - if ('0' <= c && c <= '9') { - ret *= 10; - ret += (u64)((unsigned char)c - '0'); - if (ret > U32_MAX) - return 0; - } else { - break; - } - } - return (u32)ret; -} -static int dbg_hisi_regulator_show(struct seq_file *s, void *data) -{ - seq_printf(s, "\n\r"); - seq_printf(s, "%-13s %-15s %-15s %-15s %-15s\n\r", - "LDO_NAME", "ON/OFF", "Use_count", "Open_count", "Always_on"); - seq_printf(s, "-----------------------------------------" - "-----------------------------------------------\n\r"); - get_current_regulator_dev(s); - return 0; -} - -static int dbg_hisi_regulator_open(struct inode *inode, struct file *file) -{ - return single_open(file, dbg_hisi_regulator_show, inode->i_private); -} - -static const struct file_operations debug_regulator_state_fops = { - .open = dbg_hisi_regulator_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int dbg_control_regulator_show(struct seq_file *s, void *data) -{ - printk(" \n\r \ - ---------------------------------------------------------------------------------\n\r \ - |usage: |\n\r \ - | S = state R = read V = voltage |\n\r \ - | set ldo state and voltage |\n\r \ - | get ldo state and current voltage |\n\r \ - |example: |\n\r \ - | echo S ldo16 0 > control_regulator :disable ldo16 |\n\r \ - | echo S ldo16 1 > control_regulator :enable ldo16 |\n\r \ - | echo R ldo16 > control_regulator :get ldo16 state and voltage |\n\r \ - | echo V ldo16 xxx > control_regulator :set ldo16 voltage |\n\r \ - ---------------------------------------------------------------------------------\n\r"); - return 0; -} -static ssize_t dbg_control_regulator_set_value(struct file *filp, const char __user *buffer, - size_t count, loff_t *ppos) -{ - char tmp[128] = {0}; - char ptr[128] = {0}; - char *vol = NULL; - char num = 0; - unsigned int i; - int next_flag = 1; - - if (count >= 128) { - pr_info("error! buffer size big than internal buffer\n"); - return -EFAULT; - } - - if (copy_from_user(tmp, buffer, count)) { - pr_info("error!\n"); - return -EFAULT; - } - - if (tmp[0] == 'R' || tmp[0] == 'r') { - for (i = 2; i < (count - 1); i++) { - ptr[i - 2] = tmp[i]; - } - ptr[i - 2] = '\0'; - get_regulator_state(ptr); - } else if (tmp[0] == 'S' || tmp[0] == 's') { - for (i = 2; i < (count - 1); i++) { - if (tmp[i] == ' ') { - next_flag = 0; - ptr[i - 2] = '\0'; - continue; - } - if (next_flag) { - ptr[i - 2] = tmp[i]; - } else { - num = tmp[i] - 48; - } - } - set_regulator_state(ptr, num); - } else if (tmp[0] == 'V' || tmp[0] == 'v') { - for (i = 2; i < (count - 1); i++) { - if (tmp[i] == ' ') { - next_flag = 0; - ptr[i - 2] = '\0'; - continue; - } - if (next_flag) { - ptr[i - 2] = tmp[i]; - } else { - vol = &tmp[i]; - break; - } - } - set_regulator_voltage(ptr, pmu_atoi(vol)); - } - - *ppos += count; - - return count; -} - -static int dbg_control_regulator_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return single_open(file, dbg_control_regulator_show, &inode->i_private); -} - -static const struct file_operations set_control_regulator_fops = { - .open = dbg_control_regulator_open, - .read = seq_read, - .write = dbg_control_regulator_set_value, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - static int hisi_regulator_probe(struct spmi_device *pdev) { struct device *dev = &pdev->dev; @@ -556,10 +406,6 @@ static int hisi_regulator_probe(struct spmi_device *pdev) const struct of_device_id *match; struct regulation_constraints *constraint; const char *supplyname = NULL; -#ifdef CONFIG_HISI_PMIC_DEBUG - struct dentry *d; - static int debugfs_flag; -#endif unsigned int temp_modes; const struct hisi_regulator *template = NULL; @@ -572,11 +418,7 @@ static int hisi_regulator_probe(struct spmi_device *pdev) } template = match->data; -#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) initdata = of_get_regulator_init_data(dev, np, NULL); -#else - initdata = of_get_regulator_init_data(dev, np); -#endif if (NULL == initdata) { pr_err("get regulator init data error !\n"); return -EINVAL; @@ -636,32 +478,10 @@ static int hisi_regulator_probe(struct spmi_device *pdev) goto hisi_probe_end; } - BRAND_DEBUG("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", rdesc->name,\ + pr_debug("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", rdesc->name,\ constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); -#ifdef CONFIG_HISI_PMIC_DEBUG - if (debugfs_flag == 0) { - d = debugfs_create_dir("hisi_regulator_debugfs", NULL); - if (!d) { - dev_err(dev, "failed to create hisi regulator debugfs dir !\n"); - ret = -ENOMEM; - goto hisi_probe_fail; - } - (void) debugfs_create_file("regulator_state", S_IRUSR, - d, NULL, &debug_regulator_state_fops); - - (void) debugfs_create_file("control_regulator", S_IRUSR, - d, NULL, &set_control_regulator_fops); - debugfs_flag = 1; - } -#endif - -#ifdef CONFIG_HISI_PMIC_DEBUG -hisi_probe_fail: - if (ret) - regulator_unregister(rdev); -#endif hisi_probe_end: if (ret) kfree(sreg); -- cgit v1.2.3 From 12ca3b20dbd42c9c35b0499754317bdc2fc533d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:44 +0200 Subject: staging: regulator: hi6421v600-regulator: port it to upstream The driver was originally written for Kernel 4.9. It needs to be ported to upstream: - Got rid of timeval; - Removed a bogus dependency; - Did cleanups at the header file. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9e34400d2cc15ef501a8478f69a95c9abc5c4d8d.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 34 ++++--------------------- 1 file changed, 5 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 7bc0ae27b110..904cb64b1dcd 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -49,7 +49,6 @@ struct hisi_regulator_register_info { struct hisi_regulator { const char *name; struct hisi_regulator_register_info register_info; - struct timeval last_off_time; u32 off_on_delay; u32 eco_uA; struct regulator_desc rdesc; @@ -57,8 +56,6 @@ struct hisi_regulator { }; static DEFINE_MUTEX(enable_mutex); -struct timeval last_enabled; - static inline struct hisi_pmic *rdev_to_pmic(struct regulator_dev *dev) { @@ -72,27 +69,6 @@ static inline struct hisi_pmic *rdev_to_pmic(struct regulator_dev *dev) /* helper function to ensure when it returns it is at least 'delay_us' * microseconds after 'since'. */ -static void ensured_time_after(struct timeval since, u32 delay_us) -{ - struct timeval now; - u64 elapsed_ns64, delay_ns64; - u32 actual_us32; - - delay_ns64 = delay_us * NSEC_PER_USEC; - do_gettimeofday(&now); - elapsed_ns64 = timeval_to_ns(&now) - timeval_to_ns(&since); - if (delay_ns64 > elapsed_ns64) { - actual_us32 = ((u32)(delay_ns64 - elapsed_ns64) / - NSEC_PER_USEC); - if (actual_us32 >= 1000) { - mdelay(actual_us32 / 1000); /*lint !e647 */ - udelay(actual_us32 % 1000); - } else if (actual_us32 > 0) { - udelay(actual_us32); - } - } - return; -} static int hisi_regulator_is_enabled(struct regulator_dev *dev) { @@ -113,13 +89,16 @@ static int hisi_regulator_enable(struct regulator_dev *dev) struct hisi_pmic *pmic = rdev_to_pmic(dev); /* keep a distance of off_on_delay from last time disabled */ - ensured_time_after(sreg->last_off_time, sreg->off_on_delay); + usleep_range(sreg->off_on_delay, sreg->off_on_delay + 1000); pr_debug("<[%s]: off_on_delay=%dus>\n", __func__, sreg->off_on_delay); /* cannot enable more than one regulator at one time */ mutex_lock(&enable_mutex); - ensured_time_after(last_enabled, HISI_REGS_ENA_PROTECT_TIME); + usleep_range(HISI_REGS_ENA_PROTECT_TIME, + HISI_REGS_ENA_PROTECT_TIME + 1000); + + /* set enable register */ hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, @@ -128,7 +107,6 @@ static int hisi_regulator_enable(struct regulator_dev *dev) pr_debug("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", __func__, sreg->register_info.ctrl_reg,\ sreg->register_info.enable_mask); - do_gettimeofday(&last_enabled); mutex_unlock(&enable_mutex); return 0; @@ -143,8 +121,6 @@ static int hisi_regulator_disable(struct regulator_dev *dev) hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, sreg->register_info.enable_mask, 0); - do_gettimeofday(&sreg->last_off_time); - return 0; } -- cgit v1.2.3 From b660bf657d3262e6a0d1f1b7e83be11e13228a71 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:45 +0200 Subject: staging: regulator: hi6421v600-regulator: coding style fixups There are several issues on those drivers related to their coding style. Solve most of them. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9ea7fdc004c7c44ae513b6c8f6c4a4493dd1ac61.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 110 ++++++++++++------------ 1 file changed, 56 insertions(+), 54 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 904cb64b1dcd..5f6e4ba4b99e 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Device driver for regulators in Hisi IC * @@ -52,7 +53,7 @@ struct hisi_regulator { u32 off_on_delay; u32 eco_uA; struct regulator_desc rdesc; - int (*dt_parse)(struct hisi_regulator *, struct spmi_device *); + int (*dt_parse)(struct hisi_regulator *reg, struct spmi_device *spmi); }; static DEFINE_MUTEX(enable_mutex); @@ -77,8 +78,9 @@ static int hisi_regulator_is_enabled(struct regulator_dev *dev) struct hisi_pmic *pmic = rdev_to_pmic(dev); reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - pr_debug("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", __func__, sreg->register_info.ctrl_reg,\ - (reg_val & sreg->register_info.enable_mask)); + pr_debug("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", + __func__, sreg->register_info.ctrl_reg, + (reg_val & sreg->register_info.enable_mask)); return ((reg_val & sreg->register_info.enable_mask) != 0); } @@ -98,14 +100,13 @@ static int hisi_regulator_enable(struct regulator_dev *dev) usleep_range(HISI_REGS_ENA_PROTECT_TIME, HISI_REGS_ENA_PROTECT_TIME + 1000); - - /* set enable register */ hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.enable_mask, + sreg->register_info.enable_mask, sreg->register_info.enable_mask); - pr_debug("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", __func__, sreg->register_info.ctrl_reg,\ - sreg->register_info.enable_mask); + pr_debug("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", + __func__, sreg->register_info.ctrl_reg, + sreg->register_info.enable_mask); mutex_unlock(&enable_mutex); @@ -119,7 +120,7 @@ static int hisi_regulator_disable(struct regulator_dev *dev) /* set enable register to 0 */ hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.enable_mask, 0); + sreg->register_info.enable_mask, 0); return 0; } @@ -132,7 +133,8 @@ static int hisi_regulator_get_voltage(struct regulator_dev *dev) /* get voltage selector */ reg_val = hisi_pmic_read(pmic, sreg->register_info.vset_reg); - pr_debug("<[%s]: vset_reg=0x%x>\n", __func__, sreg->register_info.vset_reg); + pr_debug("<[%s]: vset_reg=0x%x>\n", + __func__, sreg->register_info.vset_reg); selector = (reg_val & sreg->register_info.vset_mask) >> (ffs(sreg->register_info.vset_mask) - 1); @@ -141,7 +143,7 @@ static int hisi_regulator_get_voltage(struct regulator_dev *dev) } static int hisi_regulator_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV, unsigned *selector) + int min_uV, int max_uV, unsigned int *selector) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); struct hisi_pmic *pmic = rdev_to_pmic(dev); @@ -162,14 +164,14 @@ static int hisi_regulator_set_voltage(struct regulator_dev *dev, *selector = vsel; /* set voltage selector */ hisi_pmic_rmw(pmic, sreg->register_info.vset_reg, - sreg->register_info.vset_mask, + sreg->register_info.vset_mask, vsel << (ffs(sreg->register_info.vset_mask) - 1)); - pr_debug("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", __func__,\ - sreg->register_info.vset_reg,\ - sreg->register_info.vset_mask,\ - vsel << (ffs(sreg->register_info.vset_mask) - 1)\ - ); + pr_debug("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", + __func__, + sreg->register_info.vset_reg, + sreg->register_info.vset_mask, + vsel << (ffs(sreg->register_info.vset_mask) - 1)); return ret; } @@ -181,10 +183,10 @@ static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) u32 reg_val; reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - pr_debug("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", __func__, reg_val,\ - sreg->register_info.ctrl_reg,\ - sreg->register_info.eco_mode_mask\ - ); + pr_debug("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", + __func__, reg_val, + sreg->register_info.ctrl_reg, + sreg->register_info.eco_mode_mask); if (reg_val & sreg->register_info.eco_mode_mask) return REGULATOR_MODE_IDLE; @@ -193,7 +195,7 @@ static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) } static int hisi_regulator_set_mode(struct regulator_dev *dev, - unsigned int mode) + unsigned int mode) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); struct hisi_pmic *pmic = rdev_to_pmic(dev); @@ -212,31 +214,31 @@ static int hisi_regulator_set_mode(struct regulator_dev *dev, /* set mode */ hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.eco_mode_mask, + sreg->register_info.eco_mode_mask, eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); - pr_debug("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", __func__,\ - sreg->register_info.ctrl_reg,\ - sreg->register_info.eco_mode_mask,\ - eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)\ - ); + pr_debug("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", + __func__, + sreg->register_info.ctrl_reg, + sreg->register_info.eco_mode_mask, + eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); return 0; } - -unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, - int input_uV, int output_uV, int load_uA) +static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, + int input_uV, int output_uV, + int load_uA) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - if ((load_uA == 0) || ((unsigned int)load_uA > sreg->eco_uA)) + if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) return REGULATOR_MODE_NORMAL; else return REGULATOR_MODE_IDLE; } static int hisi_dt_parse_common(struct hisi_regulator *sreg, - struct spmi_device *pdev) + struct spmi_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -246,7 +248,7 @@ static int hisi_dt_parse_common(struct hisi_regulator *sreg, /* parse .register_info.ctrl_reg */ ret = of_property_read_u32_array(np, "hisilicon,hisi-ctrl", - register_info, 3); + register_info, 3); if (ret) { dev_err(dev, "no hisilicon,hisi-ctrl property set\n"); goto dt_parse_common_end; @@ -257,7 +259,7 @@ static int hisi_dt_parse_common(struct hisi_regulator *sreg, /* parse .register_info.vset_reg */ ret = of_property_read_u32_array(np, "hisilicon,hisi-vset", - register_info, 2); + register_info, 2); if (ret) { dev_err(dev, "no hisilicon,hisi-vset property set\n"); goto dt_parse_common_end; @@ -267,7 +269,7 @@ static int hisi_dt_parse_common(struct hisi_regulator *sreg, /* parse .off-on-delay */ ret = of_property_read_u32(np, "hisilicon,hisi-off-on-delay-us", - &sreg->off_on_delay); + &sreg->off_on_delay); if (ret) { dev_err(dev, "no hisilicon,hisi-off-on-delay-us property set\n"); goto dt_parse_common_end; @@ -294,7 +296,7 @@ dt_parse_common_end: } static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, - struct spmi_device *pdev) + struct spmi_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -312,7 +314,7 @@ static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, /* alloc space for .volt_table */ v_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages, - GFP_KERNEL); + GFP_KERNEL); if (unlikely(!v_table)) { ret = -ENOMEM; dev_err(dev, "no memory for .volt_table\n"); @@ -320,7 +322,7 @@ static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, } ret = of_property_read_u32_array(np, "hisilicon,hisi-vset-table", - v_table, rdesc->n_voltages); + v_table, rdesc->n_voltages); if (ret) { dev_err(dev, "no hisilicon,hisi-vset-table property set\n"); goto dt_parse_ldo_end1; @@ -362,7 +364,7 @@ static const struct hisi_regulator hisi_regulator_ldo = { .dt_parse = hisi_dt_parse_ldo, }; -static struct of_device_id of_hisi_regulator_match_tbl[] = { +static const struct of_device_id of_hisi_regulator_match_tbl[] = { { .compatible = "hisilicon-hisi-ldo", .data = &hisi_regulator_ldo, @@ -388,14 +390,14 @@ static int hisi_regulator_probe(struct spmi_device *pdev) int ret = 0; /* to check which type of regulator this is */ match = of_match_device(of_hisi_regulator_match_tbl, &pdev->dev); - if (NULL == match) { + if (!match) { pr_err("get hisi regulator fail!\n\r"); return -EINVAL; } template = match->data; initdata = of_get_regulator_init_data(dev, np, NULL); - if (NULL == initdata) { + if (!initdata) { pr_err("get regulator init data error !\n"); return -EINVAL; } @@ -404,14 +406,14 @@ static int hisi_regulator_probe(struct spmi_device *pdev) constraint = &initdata->constraints; ret = of_property_read_u32_array(np, "hisilicon,valid-modes-mask", - &(constraint->valid_modes_mask), 1); + &constraint->valid_modes_mask, 1); if (ret) { pr_err("no hisilicon,valid-modes-mask property set\n"); ret = -ENODEV; return ret; } ret = of_property_read_u32_array(np, "hisilicon,valid-idle-mask", - &temp_modes, 1); + &temp_modes, 1); if (ret) { pr_err("no hisilicon,valid-modes-mask property set\n"); ret = -ENODEV; @@ -420,18 +422,16 @@ static int hisi_regulator_probe(struct spmi_device *pdev) constraint->valid_ops_mask |= temp_modes; sreg = kmemdup(template, sizeof(*sreg), GFP_KERNEL); - if (!sreg) { - pr_err("template kememdup is fail. \n"); + if (!sreg) return -ENOMEM; - } + sreg->name = initdata->constraints.name; rdesc = &sreg->rdesc; rdesc->name = sreg->name; rdesc->min_uV = initdata->constraints.min_uV; supplyname = of_get_property(np, "hisilicon,supply_name", NULL); - if (supplyname != NULL) { + if (supplyname) initdata->supply_regulator = supplyname; - } /* to parse device tree data for regulator specific */ ret = sreg->dt_parse(sreg, pdev); @@ -454,8 +454,9 @@ static int hisi_regulator_probe(struct spmi_device *pdev) goto hisi_probe_end; } - pr_debug("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", rdesc->name,\ - constraint->valid_modes_mask, constraint->valid_ops_mask); + pr_debug("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", + rdesc->name, + constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); hisi_probe_end: @@ -477,11 +478,12 @@ static void hisi_regulator_remove(struct spmi_device *pdev) kfree(sreg); } + static int hisi_regulator_suspend(struct device *dev, pm_message_t state) { struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); - if (NULL == hisi_regulator) { + if (!hisi_regulator) { pr_err("%s:regulator is NULL\n", __func__); return -ENOMEM; } @@ -490,13 +492,13 @@ static int hisi_regulator_suspend(struct device *dev, pm_message_t state) pr_info("%s:-\n", __func__); return 0; -}/*lint !e715 */ +} static int hisi_regulator_resume(struct device *dev) { struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); - if (NULL == hisi_regulator) { + if (!hisi_regulator) { pr_err("%s:regulator is NULL\n", __func__); return -ENOMEM; } -- cgit v1.2.3 From 75937f8f961e090cd98713f9b1302b6ae6173f80 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:46 +0200 Subject: staging: regulator: hi6421v600-regulator: change the binding logic Change the binding logic to ensure that the PMIC SPMI driver will run before the regulator code and add it to the building system. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/aa40d443dfc6c8e69e4c36fa79d15459762924e4.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 186 ++++++++++++------------ 1 file changed, 91 insertions(+), 95 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 5f6e4ba4b99e..9aaafcbb1a36 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,20 +53,11 @@ struct hisi_regulator { u32 off_on_delay; u32 eco_uA; struct regulator_desc rdesc; - int (*dt_parse)(struct hisi_regulator *reg, struct spmi_device *spmi); + struct hisi_pmic *pmic; }; static DEFINE_MUTEX(enable_mutex); -static inline struct hisi_pmic *rdev_to_pmic(struct regulator_dev *dev) -{ - /* regulator_dev parent to-> - * hisi regulator platform device_dev parent to-> - * hisi pmic platform device_dev - */ - return dev_get_drvdata(rdev_get_dev(dev)->parent->parent); -} - /* helper function to ensure when it returns it is at least 'delay_us' * microseconds after 'since'. */ @@ -75,7 +66,7 @@ static int hisi_regulator_is_enabled(struct regulator_dev *dev) { u32 reg_val; struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); pr_debug("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", @@ -88,7 +79,7 @@ static int hisi_regulator_is_enabled(struct regulator_dev *dev) static int hisi_regulator_enable(struct regulator_dev *dev) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; /* keep a distance of off_on_delay from last time disabled */ usleep_range(sreg->off_on_delay, sreg->off_on_delay + 1000); @@ -116,7 +107,7 @@ static int hisi_regulator_enable(struct regulator_dev *dev) static int hisi_regulator_disable(struct regulator_dev *dev) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; /* set enable register to 0 */ hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, @@ -128,7 +119,7 @@ static int hisi_regulator_disable(struct regulator_dev *dev) static int hisi_regulator_get_voltage(struct regulator_dev *dev) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; u32 reg_val, selector; /* get voltage selector */ @@ -146,7 +137,7 @@ static int hisi_regulator_set_voltage(struct regulator_dev *dev, int min_uV, int max_uV, unsigned int *selector) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; u32 vsel; int ret = 0; @@ -179,7 +170,7 @@ static int hisi_regulator_set_voltage(struct regulator_dev *dev, static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; u32 reg_val; reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); @@ -198,7 +189,7 @@ static int hisi_regulator_set_mode(struct regulator_dev *dev, unsigned int mode) { struct hisi_regulator *sreg = rdev_get_drvdata(dev); - struct hisi_pmic *pmic = rdev_to_pmic(dev); + struct hisi_pmic *pmic = sreg->pmic; u32 eco_mode; switch (mode) { @@ -238,7 +229,7 @@ static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, } static int hisi_dt_parse_common(struct hisi_regulator *sreg, - struct spmi_device *pdev) + struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -296,7 +287,7 @@ dt_parse_common_end: } static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, - struct spmi_device *pdev) + struct platform_device *pdev) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; @@ -355,47 +346,32 @@ static struct regulator_ops hisi_ldo_rops = { .get_optimum_mode = hisi_regulator_get_optimum_mode, }; -static const struct hisi_regulator hisi_regulator_ldo = { - .rdesc = { - .ops = &hisi_ldo_rops, - .type = REGULATOR_VOLTAGE, - .owner = THIS_MODULE, - }, - .dt_parse = hisi_dt_parse_ldo, -}; +/* + * Used only for parsing the DT properties + */ -static const struct of_device_id of_hisi_regulator_match_tbl[] = { +static const struct of_device_id of_hisi_pmic_match_tbl[] = { { - .compatible = "hisilicon-hisi-ldo", - .data = &hisi_regulator_ldo, + .compatible = "hisilicon,hi6421-spmi-pmic-ldo", }, - { /* end */ } + { } }; -static int hisi_regulator_probe(struct spmi_device *pdev) +static int hisi_regulator_probe_ldo(struct platform_device *pdev, + struct device_node *np, + struct hisi_pmic *pmic) { struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; struct regulator_desc *rdesc; struct regulator_dev *rdev; struct hisi_regulator *sreg = NULL; struct regulator_init_data *initdata; struct regulator_config config = { }; - const struct of_device_id *match; struct regulation_constraints *constraint; const char *supplyname = NULL; unsigned int temp_modes; - - const struct hisi_regulator *template = NULL; int ret = 0; - /* to check which type of regulator this is */ - match = of_match_device(of_hisi_regulator_match_tbl, &pdev->dev); - if (!match) { - pr_err("get hisi regulator fail!\n\r"); - return -EINVAL; - } - template = match->data; initdata = of_get_regulator_init_data(dev, np, NULL); if (!initdata) { pr_err("get regulator init data error !\n"); @@ -421,20 +397,25 @@ static int hisi_regulator_probe(struct spmi_device *pdev) } constraint->valid_ops_mask |= temp_modes; - sreg = kmemdup(template, sizeof(*sreg), GFP_KERNEL); + sreg = kzalloc(sizeof(*sreg), GFP_KERNEL); if (!sreg) return -ENOMEM; sreg->name = initdata->constraints.name; + sreg->pmic = pmic; rdesc = &sreg->rdesc; + rdesc->name = sreg->name; + rdesc->ops = &hisi_ldo_rops; + rdesc->type = REGULATOR_VOLTAGE; rdesc->min_uV = initdata->constraints.min_uV; + supplyname = of_get_property(np, "hisilicon,supply_name", NULL); if (supplyname) initdata->supply_regulator = supplyname; - /* to parse device tree data for regulator specific */ - ret = sreg->dt_parse(sreg, pdev); + /* parse device tree data for regulator specific */ + ret = hisi_dt_parse_ldo(sreg, pdev); if (ret) { dev_err(dev, "device tree parameter parse error!\n"); goto hisi_probe_end; @@ -465,75 +446,90 @@ hisi_probe_end: return ret; } -static void hisi_regulator_remove(struct spmi_device *pdev) -{ - struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev); - struct hisi_regulator *sreg = rdev_get_drvdata(rdev); - - regulator_unregister(rdev); - - /* TODO: should i worry about that? devm_kzalloc */ - if (sreg->rdesc.volt_table) - devm_kfree(&pdev->dev, (unsigned int *)sreg->rdesc.volt_table); - - kfree(sreg); -} -static int hisi_regulator_suspend(struct device *dev, pm_message_t state) +static int hisi_regulator_probe(struct platform_device *pdev) { - struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); + struct device *pmic_dev = pdev->dev.parent; + struct device_node *np = pmic_dev->of_node; + struct device_node *regulators, *child; + struct platform_device *new_pdev; + struct hisi_pmic *pmic; + int ret; + + dev_dbg(&pdev->dev, "probing hi6421v600 regulator\n"); + /* + * This driver is meant to be called by hi6421-spmi-core, + * which should first set drvdata. If this doesn't happen, hit + * a warn on and return. + */ + pmic = dev_get_drvdata(pmic_dev); + if (WARN_ON(!pmic)) + return -ENODEV; + + regulators = of_get_child_by_name(np, "regulators"); + if (!regulators) { + dev_err(&pdev->dev, "regulator node not found\n"); + return -ENODEV; + } - if (!hisi_regulator) { - pr_err("%s:regulator is NULL\n", __func__); - return -ENOMEM; + /* + * Parse all LDO regulator nodes + */ + for_each_child_of_node(regulators, child) { + dev_dbg(&pdev->dev, "adding child %pOF\n", child); + + new_pdev = platform_device_alloc(child->name, -1); + new_pdev->dev.parent = pmic_dev; + new_pdev->dev.of_node = of_node_get(child); + + ret = platform_device_add(new_pdev); + if (ret < 0) { + platform_device_put(new_pdev); + continue; + } + + ret = hisi_regulator_probe_ldo(new_pdev, child, pmic); + if (ret < 0) + platform_device_put(new_pdev); } - pr_info("%s:+\n", __func__); - pr_info("%s:-\n", __func__); + of_node_put(regulators); return 0; } -static int hisi_regulator_resume(struct device *dev) +static int hisi_regulator_remove(struct platform_device *pdev) { - struct hisi_regulator *hisi_regulator = dev_get_drvdata(dev); + struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev); + struct hisi_regulator *sreg = rdev_get_drvdata(rdev); - if (!hisi_regulator) { - pr_err("%s:regulator is NULL\n", __func__); - return -ENOMEM; - } + regulator_unregister(rdev); + + /* TODO: should i worry about that? devm_kzalloc */ + if (sreg->rdesc.volt_table) + devm_kfree(&pdev->dev, (unsigned int *)sreg->rdesc.volt_table); - pr_info("%s:+\n", __func__); - pr_info("%s:-\n", __func__); + kfree(sreg); return 0; } -static struct spmi_driver hisi_pmic_driver = { +static const struct platform_device_id hi6421v600_regulator_table[] = { + { .name = "hi6421v600-regulator" }, + {}, +}; +MODULE_DEVICE_TABLE(platform, hi6421v600_regulator_table); + +static struct platform_driver hi6421v600_regulator_driver = { + .id_table = hi6421v600_regulator_table, .driver = { - .name = "hisi_regulator", - .owner = THIS_MODULE, - .of_match_table = of_hisi_regulator_match_tbl, - .suspend = hisi_regulator_suspend, - .resume = hisi_regulator_resume, + .name = "hi6421v600-regulator", }, .probe = hisi_regulator_probe, .remove = hisi_regulator_remove, }; +module_platform_driver(hi6421v600_regulator_driver); -static int __init hisi_regulator_init(void) -{ - return spmi_driver_register(&hisi_pmic_driver); -} - -static void __exit hisi_regulator_exit(void) -{ - spmi_driver_unregister(&hisi_pmic_driver); -} - -fs_initcall(hisi_regulator_init); -module_exit(hisi_regulator_exit); - -MODULE_DESCRIPTION("Hisi regulator driver"); +MODULE_DESCRIPTION("Hi6421v600 regulator driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 32f53804d23cadd1b5ba530c61ddea3db8b1a5a3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:47 +0200 Subject: staging: regulator: hi6421v600-regulator: cleanup struct hisi_regulator There are several fields on this struct that can be removed, as they already exists at struct regulator_desc. Remove them, cleaning up the code in the process. While here, rename it to hi6421v600_regulator_info, in order to better match the driver's name. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/648d48f11368a9869d760c2bd54bfbc3feb4f44c.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 226 ++++++++++-------------- 1 file changed, 92 insertions(+), 134 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 9aaafcbb1a36..7d82d11f4b52 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -39,21 +39,11 @@ #include #include -struct hisi_regulator_register_info { - u32 ctrl_reg; - u32 enable_mask; - u32 eco_mode_mask; - u32 vset_reg; - u32 vset_mask; -}; - -struct hisi_regulator { - const char *name; - struct hisi_regulator_register_info register_info; - u32 off_on_delay; - u32 eco_uA; +struct hi6421v600_regulator { struct regulator_desc rdesc; struct hisi_pmic *pmic; + u8 eco_mode_mask; + u32 eco_uA; }; static DEFINE_MUTEX(enable_mutex); @@ -62,29 +52,29 @@ static DEFINE_MUTEX(enable_mutex); * microseconds after 'since'. */ -static int hisi_regulator_is_enabled(struct regulator_dev *dev) +static int hisi_regulator_is_enabled(struct regulator_dev *rdev) { u32 reg_val; - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; - reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - pr_debug("<[%s]: ctrl_reg=0x%x,enable_state=%d>\n", - __func__, sreg->register_info.ctrl_reg, - (reg_val & sreg->register_info.enable_mask)); + reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); + pr_debug("<[%s]: enable_reg=0x%x,enable_state=%d>\n", + __func__, rdev->desc->enable_reg, + (reg_val & rdev->desc->enable_mask)); - return ((reg_val & sreg->register_info.enable_mask) != 0); + return ((reg_val & rdev->desc->enable_mask) != 0); } -static int hisi_regulator_enable(struct regulator_dev *dev) +static int hisi_regulator_enable(struct regulator_dev *rdev) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; /* keep a distance of off_on_delay from last time disabled */ - usleep_range(sreg->off_on_delay, sreg->off_on_delay + 1000); + usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 1000); - pr_debug("<[%s]: off_on_delay=%dus>\n", __func__, sreg->off_on_delay); + pr_debug("<[%s]: off_on_delay=%dus>\n", __func__, rdev->desc->off_on_delay); /* cannot enable more than one regulator at one time */ mutex_lock(&enable_mutex); @@ -92,103 +82,103 @@ static int hisi_regulator_enable(struct regulator_dev *dev) HISI_REGS_ENA_PROTECT_TIME + 1000); /* set enable register */ - hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.enable_mask, - sreg->register_info.enable_mask); - pr_debug("<[%s]: ctrl_reg=0x%x,enable_mask=0x%x>\n", - __func__, sreg->register_info.ctrl_reg, - sreg->register_info.enable_mask); + hisi_pmic_rmw(pmic, rdev->desc->enable_reg, + rdev->desc->enable_mask, + rdev->desc->enable_mask); + pr_debug("<[%s]: enable_reg=0x%x,enable_mask=0x%x>\n", + __func__, rdev->desc->enable_reg, + rdev->desc->enable_mask); mutex_unlock(&enable_mutex); return 0; } -static int hisi_regulator_disable(struct regulator_dev *dev) +static int hisi_regulator_disable(struct regulator_dev *rdev) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; /* set enable register to 0 */ - hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.enable_mask, 0); + hisi_pmic_rmw(pmic, rdev->desc->enable_reg, + rdev->desc->enable_mask, 0); return 0; } -static int hisi_regulator_get_voltage(struct regulator_dev *dev) +static int hisi_regulator_get_voltage(struct regulator_dev *rdev) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 reg_val, selector; /* get voltage selector */ - reg_val = hisi_pmic_read(pmic, sreg->register_info.vset_reg); - pr_debug("<[%s]: vset_reg=0x%x>\n", - __func__, sreg->register_info.vset_reg); + reg_val = hisi_pmic_read(pmic, rdev->desc->vsel_reg); + pr_debug("<[%s]: vsel_reg=0x%x>\n", + __func__, rdev->desc->vsel_reg); - selector = (reg_val & sreg->register_info.vset_mask) >> - (ffs(sreg->register_info.vset_mask) - 1); + selector = (reg_val & rdev->desc->vsel_mask) >> + (ffs(rdev->desc->vsel_mask) - 1); - return sreg->rdesc.ops->list_voltage(dev, selector); + return rdev->desc->ops->list_voltage(rdev, selector); } -static int hisi_regulator_set_voltage(struct regulator_dev *dev, +static int hisi_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 vsel; int ret = 0; - for (vsel = 0; vsel < sreg->rdesc.n_voltages; vsel++) { - int uV = sreg->rdesc.volt_table[vsel]; + for (vsel = 0; vsel < rdev->desc->n_voltages; vsel++) { + int uV = rdev->desc->volt_table[vsel]; /* Break at the first in-range value */ if (min_uV <= uV && uV <= max_uV) break; } /* unlikely to happen. sanity test done by regulator core */ - if (unlikely(vsel == sreg->rdesc.n_voltages)) + if (unlikely(vsel == rdev->desc->n_voltages)) return -EINVAL; *selector = vsel; /* set voltage selector */ - hisi_pmic_rmw(pmic, sreg->register_info.vset_reg, - sreg->register_info.vset_mask, - vsel << (ffs(sreg->register_info.vset_mask) - 1)); + hisi_pmic_rmw(pmic, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, + vsel << (ffs(rdev->desc->vsel_mask) - 1)); - pr_debug("<[%s]: vset_reg=0x%x, vset_mask=0x%x, value=0x%x>\n", + pr_debug("<[%s]: vsel_reg=0x%x, vsel_mask=0x%x, value=0x%x>\n", __func__, - sreg->register_info.vset_reg, - sreg->register_info.vset_mask, - vsel << (ffs(sreg->register_info.vset_mask) - 1)); + rdev->desc->vsel_reg, + rdev->desc->vsel_mask, + vsel << (ffs(rdev->desc->vsel_mask) - 1)); return ret; } -static unsigned int hisi_regulator_get_mode(struct regulator_dev *dev) +static unsigned int hisi_regulator_get_mode(struct regulator_dev *rdev) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 reg_val; - reg_val = hisi_pmic_read(pmic, sreg->register_info.ctrl_reg); - pr_debug("<[%s]: reg_val=%d, ctrl_reg=0x%x, eco_mode_mask=0x%x>\n", + reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); + pr_debug("<[%s]: reg_val=%d, enable_reg=0x%x, eco_mode_mask=0x%x>\n", __func__, reg_val, - sreg->register_info.ctrl_reg, - sreg->register_info.eco_mode_mask); + rdev->desc->enable_reg, + sreg->eco_mode_mask); - if (reg_val & sreg->register_info.eco_mode_mask) + if (reg_val & sreg->eco_mode_mask) return REGULATOR_MODE_IDLE; else return REGULATOR_MODE_NORMAL; } -static int hisi_regulator_set_mode(struct regulator_dev *dev, +static int hisi_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 eco_mode; @@ -204,23 +194,23 @@ static int hisi_regulator_set_mode(struct regulator_dev *dev, } /* set mode */ - hisi_pmic_rmw(pmic, sreg->register_info.ctrl_reg, - sreg->register_info.eco_mode_mask, - eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); + hisi_pmic_rmw(pmic, rdev->desc->enable_reg, + sreg->eco_mode_mask, + eco_mode << (ffs(sreg->eco_mode_mask) - 1)); - pr_debug("<[%s]: ctrl_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", + pr_debug("<[%s]: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", __func__, - sreg->register_info.ctrl_reg, - sreg->register_info.eco_mode_mask, - eco_mode << (ffs(sreg->register_info.eco_mode_mask) - 1)); + rdev->desc->enable_reg, + sreg->eco_mode_mask, + eco_mode << (ffs(sreg->eco_mode_mask) - 1)); return 0; } -static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, +static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA) { - struct hisi_regulator *sreg = rdev_get_drvdata(dev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) return REGULATOR_MODE_NORMAL; @@ -228,42 +218,43 @@ static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *dev, return REGULATOR_MODE_IDLE; } -static int hisi_dt_parse_common(struct hisi_regulator *sreg, - struct platform_device *pdev) +static int hisi_dt_parse(struct platform_device *pdev, + struct hi6421v600_regulator *sreg, + struct regulator_desc *rdesc) { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - struct regulator_desc *rdesc = &sreg->rdesc; unsigned int register_info[3] = {0}; - int ret = 0; + unsigned int *v_table; + int ret; - /* parse .register_info.ctrl_reg */ + /* parse .register_info.enable_reg */ ret = of_property_read_u32_array(np, "hisilicon,hisi-ctrl", register_info, 3); if (ret) { dev_err(dev, "no hisilicon,hisi-ctrl property set\n"); - goto dt_parse_common_end; + return ret; } - sreg->register_info.ctrl_reg = register_info[0]; - sreg->register_info.enable_mask = register_info[1]; - sreg->register_info.eco_mode_mask = register_info[2]; + rdesc->enable_reg = register_info[0]; + rdesc->enable_mask = register_info[1]; + sreg->eco_mode_mask = register_info[2]; - /* parse .register_info.vset_reg */ + /* parse .register_info.vsel_reg */ ret = of_property_read_u32_array(np, "hisilicon,hisi-vset", register_info, 2); if (ret) { dev_err(dev, "no hisilicon,hisi-vset property set\n"); - goto dt_parse_common_end; + return ret; } - sreg->register_info.vset_reg = register_info[0]; - sreg->register_info.vset_mask = register_info[1]; + rdesc->vsel_reg = register_info[0]; + rdesc->vsel_mask = register_info[1]; /* parse .off-on-delay */ ret = of_property_read_u32(np, "hisilicon,hisi-off-on-delay-us", - &sreg->off_on_delay); + &rdesc->off_on_delay); if (ret) { dev_err(dev, "no hisilicon,hisi-off-on-delay-us property set\n"); - goto dt_parse_common_end; + return ret; } /* parse .enable_time */ @@ -271,7 +262,7 @@ static int hisi_dt_parse_common(struct hisi_regulator *sreg, &rdesc->enable_time); if (ret) { dev_err(dev, "no hisilicon,hisi-enable-time-us property set\n"); - goto dt_parse_common_end; + return ret; } /* parse .eco_uA */ @@ -282,56 +273,24 @@ static int hisi_dt_parse_common(struct hisi_regulator *sreg, ret = 0; } -dt_parse_common_end: - return ret; -} - -static int hisi_dt_parse_ldo(struct hisi_regulator *sreg, - struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct regulator_desc *rdesc = &sreg->rdesc; - unsigned int *v_table; - int ret = 0; + /* parse volt_table */ - /* parse .n_voltages, and .volt_table */ - ret = of_property_read_u32(np, "hisilicon,hisi-n-voltages", - &rdesc->n_voltages); - if (ret) { - dev_err(dev, "no hisilicon,hisi-n-voltages property set\n"); - goto dt_parse_ldo_end; - } + rdesc->n_voltages = of_property_count_u32_elems(np, "hisilicon,hisi-vset-table"); - /* alloc space for .volt_table */ v_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages, GFP_KERNEL); - if (unlikely(!v_table)) { - ret = -ENOMEM; - dev_err(dev, "no memory for .volt_table\n"); - goto dt_parse_ldo_end; - } + if (unlikely(!v_table)) + return -ENOMEM; + rdesc->volt_table = v_table; ret = of_property_read_u32_array(np, "hisilicon,hisi-vset-table", v_table, rdesc->n_voltages); if (ret) { dev_err(dev, "no hisilicon,hisi-vset-table property set\n"); - goto dt_parse_ldo_end1; - } - rdesc->volt_table = v_table; - - /* parse hisi regulator's dt common part */ - ret = hisi_dt_parse_common(sreg, pdev); - if (ret) { - dev_err(dev, "failure in hisi_dt_parse_common\n"); - goto dt_parse_ldo_end1; + return ret; } - return ret; - -dt_parse_ldo_end1: -dt_parse_ldo_end: - return ret; + return 0; } static struct regulator_ops hisi_ldo_rops = { @@ -364,7 +323,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, struct device *dev = &pdev->dev; struct regulator_desc *rdesc; struct regulator_dev *rdev; - struct hisi_regulator *sreg = NULL; + struct hi6421v600_regulator *sreg = NULL; struct regulator_init_data *initdata; struct regulator_config config = { }; struct regulation_constraints *constraint; @@ -401,11 +360,10 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, if (!sreg) return -ENOMEM; - sreg->name = initdata->constraints.name; sreg->pmic = pmic; rdesc = &sreg->rdesc; - rdesc->name = sreg->name; + rdesc->name = initdata->constraints.name; rdesc->ops = &hisi_ldo_rops; rdesc->type = REGULATOR_VOLTAGE; rdesc->min_uV = initdata->constraints.min_uV; @@ -415,7 +373,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, initdata->supply_regulator = supplyname; /* parse device tree data for regulator specific */ - ret = hisi_dt_parse_ldo(sreg, pdev); + ret = hisi_dt_parse(pdev, sreg, rdesc); if (ret) { dev_err(dev, "device tree parameter parse error!\n"); goto hisi_probe_end; @@ -501,13 +459,13 @@ static int hisi_regulator_probe(struct platform_device *pdev) static int hisi_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev); - struct hisi_regulator *sreg = rdev_get_drvdata(rdev); + struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); regulator_unregister(rdev); /* TODO: should i worry about that? devm_kzalloc */ - if (sreg->rdesc.volt_table) - devm_kfree(&pdev->dev, (unsigned int *)sreg->rdesc.volt_table); + if (rdev->desc->volt_table) + devm_kfree(&pdev->dev, (unsigned int *)rdev->desc->volt_table); kfree(sreg); -- cgit v1.2.3 From 9a18329f776b5a18ead0de8b2eb2000f5f1ad6f6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:48 +0200 Subject: staging: regulator: hi6421v600-regulator: cleanup debug messages - use dev_foo() instead of pr_foo(); - cleanup the messages, making them more standard and easier to understand. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/2d17e168031340da73e1bd1c826289ceba2dbe8f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 76 +++++++++++++++---------- 1 file changed, 47 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 7d82d11f4b52..2d1096ecb277 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -59,9 +59,11 @@ static int hisi_regulator_is_enabled(struct regulator_dev *rdev) struct hisi_pmic *pmic = sreg->pmic; reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); - pr_debug("<[%s]: enable_reg=0x%x,enable_state=%d>\n", + + dev_dbg(&rdev->dev, + "%s: enable_reg=0x%x, val= 0x%x, enable_state=%d\n", __func__, rdev->desc->enable_reg, - (reg_val & rdev->desc->enable_mask)); + reg_val, (reg_val & rdev->desc->enable_mask)); return ((reg_val & rdev->desc->enable_mask) != 0); } @@ -74,7 +76,8 @@ static int hisi_regulator_enable(struct regulator_dev *rdev) /* keep a distance of off_on_delay from last time disabled */ usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 1000); - pr_debug("<[%s]: off_on_delay=%dus>\n", __func__, rdev->desc->off_on_delay); + dev_dbg(&rdev->dev, "%s: off_on_delay=%d us\n", + __func__, rdev->desc->off_on_delay); /* cannot enable more than one regulator at one time */ mutex_lock(&enable_mutex); @@ -85,7 +88,7 @@ static int hisi_regulator_enable(struct regulator_dev *rdev) hisi_pmic_rmw(pmic, rdev->desc->enable_reg, rdev->desc->enable_mask, rdev->desc->enable_mask); - pr_debug("<[%s]: enable_reg=0x%x,enable_mask=0x%x>\n", + dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, enable_mask=0x%x\n", __func__, rdev->desc->enable_reg, rdev->desc->enable_mask); @@ -111,16 +114,20 @@ static int hisi_regulator_get_voltage(struct regulator_dev *rdev) struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 reg_val, selector; + int vol; /* get voltage selector */ reg_val = hisi_pmic_read(pmic, rdev->desc->vsel_reg); - pr_debug("<[%s]: vsel_reg=0x%x>\n", - __func__, rdev->desc->vsel_reg); - selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); - return rdev->desc->ops->list_voltage(rdev, selector); + vol = rdev->desc->ops->list_voltage(rdev, selector); + + dev_dbg(&rdev->dev, + "%s: vsel_reg=0x%x, val=0x%x, entry=0x%x, voltage=%d mV\n", + __func__, rdev->desc->vsel_reg, reg_val, selector, vol/ 1000); + + return vol; } static int hisi_regulator_set_voltage(struct regulator_dev *rdev, @@ -129,10 +136,14 @@ static int hisi_regulator_set_voltage(struct regulator_dev *rdev, struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 vsel; - int ret = 0; + int uV, ret = 0; for (vsel = 0; vsel < rdev->desc->n_voltages; vsel++) { - int uV = rdev->desc->volt_table[vsel]; + uV = rdev->desc->volt_table[vsel]; + dev_dbg(&rdev->dev, + "%s: min %d, max %d, value[%u] = %d\n", + __func__, min_uV, max_uV, vsel, uV); + /* Break at the first in-range value */ if (min_uV <= uV && uV <= max_uV) break; @@ -146,13 +157,14 @@ static int hisi_regulator_set_voltage(struct regulator_dev *rdev, /* set voltage selector */ hisi_pmic_rmw(pmic, rdev->desc->vsel_reg, rdev->desc->vsel_mask, - vsel << (ffs(rdev->desc->vsel_mask) - 1)); + vsel << (ffs(rdev->desc->vsel_mask) - 1)); - pr_debug("<[%s]: vsel_reg=0x%x, vsel_mask=0x%x, value=0x%x>\n", + dev_dbg(&rdev->dev, + "%s: vsel_reg=0x%x, vsel_mask=0x%x, value=0x%x, voltage=%d mV\n", __func__, rdev->desc->vsel_reg, rdev->desc->vsel_mask, - vsel << (ffs(rdev->desc->vsel_mask) - 1)); + vsel << (ffs(rdev->desc->vsel_mask) - 1), uV / 1000); return ret; } @@ -162,17 +174,21 @@ static unsigned int hisi_regulator_get_mode(struct regulator_dev *rdev) struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; u32 reg_val; + unsigned int mode; reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); - pr_debug("<[%s]: reg_val=%d, enable_reg=0x%x, eco_mode_mask=0x%x>\n", - __func__, reg_val, - rdev->desc->enable_reg, - sreg->eco_mode_mask); if (reg_val & sreg->eco_mode_mask) - return REGULATOR_MODE_IDLE; + mode = REGULATOR_MODE_IDLE; else - return REGULATOR_MODE_NORMAL; + mode = REGULATOR_MODE_NORMAL; + + dev_dbg(&rdev->dev, + "%s: enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n", + __func__, rdev->desc->enable_reg, sreg->eco_mode_mask, reg_val, + mode == REGULATOR_MODE_IDLE ? "idle" : "normal"); + + return mode; } static int hisi_regulator_set_mode(struct regulator_dev *rdev, @@ -198,7 +214,8 @@ static int hisi_regulator_set_mode(struct regulator_dev *rdev, sreg->eco_mode_mask, eco_mode << (ffs(sreg->eco_mode_mask) - 1)); - pr_debug("<[%s]: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x>\n", + dev_dbg(&rdev->dev, + "%s: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n", __func__, rdev->desc->enable_reg, sreg->eco_mode_mask, @@ -212,10 +229,13 @@ static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *rdev, { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) + if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) { + dev_dbg(&rdev->dev, "%s: normal mode", __func__); return REGULATOR_MODE_NORMAL; - else + } else { + dev_dbg(&rdev->dev, "%s: idle mode", __func__); return REGULATOR_MODE_IDLE; + } } static int hisi_dt_parse(struct platform_device *pdev, @@ -333,7 +353,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, initdata = of_get_regulator_init_data(dev, np, NULL); if (!initdata) { - pr_err("get regulator init data error !\n"); + dev_err(dev, "failed to get regulator data\n"); return -EINVAL; } @@ -343,14 +363,14 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, ret = of_property_read_u32_array(np, "hisilicon,valid-modes-mask", &constraint->valid_modes_mask, 1); if (ret) { - pr_err("no hisilicon,valid-modes-mask property set\n"); + dev_err(dev, "no valid modes mask\n"); ret = -ENODEV; return ret; } ret = of_property_read_u32_array(np, "hisilicon,valid-idle-mask", &temp_modes, 1); if (ret) { - pr_err("no hisilicon,valid-modes-mask property set\n"); + dev_err(dev, "no valid idle mask\n"); ret = -ENODEV; return ret; } @@ -374,10 +394,8 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, /* parse device tree data for regulator specific */ ret = hisi_dt_parse(pdev, sreg, rdesc); - if (ret) { - dev_err(dev, "device tree parameter parse error!\n"); + if (ret) goto hisi_probe_end; - } config.dev = &pdev->dev; config.init_data = initdata; @@ -393,7 +411,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, goto hisi_probe_end; } - pr_debug("[%s]:valid_modes_mask[0x%x], valid_ops_mask[0x%x]\n", + dev_dbg(dev, "%s:valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", rdesc->name, constraint->valid_modes_mask, constraint->valid_ops_mask); -- cgit v1.2.3 From db27f8294cd703bc23f4b1ccc5023d354c6a63d2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:49 +0200 Subject: staging: regulator: hi6421v600-regulator: use shorter names for OF properties Simplify the names of the OF properties, in order to make them similar to other drivers and to make easier to understand what each property means. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/98f66100263940901ba59ec187919e9cf5e64f31.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 52 ++++++++++--------------- 1 file changed, 21 insertions(+), 31 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 2d1096ecb277..e4a64893a7ad 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -196,14 +196,14 @@ static int hisi_regulator_set_mode(struct regulator_dev *rdev, { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hisi_pmic *pmic = sreg->pmic; - u32 eco_mode; + u32 val; switch (mode) { case REGULATOR_MODE_NORMAL: - eco_mode = HISI_ECO_MODE_DISABLE; + val = 0; break; case REGULATOR_MODE_IDLE: - eco_mode = HISI_ECO_MODE_ENABLE; + val = sreg->eco_mode_mask << (ffs(sreg->eco_mode_mask) - 1); break; default: return -EINVAL; @@ -211,15 +211,12 @@ static int hisi_regulator_set_mode(struct regulator_dev *rdev, /* set mode */ hisi_pmic_rmw(pmic, rdev->desc->enable_reg, - sreg->eco_mode_mask, - eco_mode << (ffs(sreg->eco_mode_mask) - 1)); + sreg->eco_mode_mask, val); dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n", - __func__, - rdev->desc->enable_reg, - sreg->eco_mode_mask, - eco_mode << (ffs(sreg->eco_mode_mask) - 1)); + __func__, rdev->desc->enable_reg, sreg->eco_mode_mask, val); + return 0; } @@ -249,10 +246,10 @@ static int hisi_dt_parse(struct platform_device *pdev, int ret; /* parse .register_info.enable_reg */ - ret = of_property_read_u32_array(np, "hisilicon,hisi-ctrl", + ret = of_property_read_u32_array(np, "hi6421-ctrl", register_info, 3); if (ret) { - dev_err(dev, "no hisilicon,hisi-ctrl property set\n"); + dev_err(dev, "no hi6421-ctrl property set\n"); return ret; } rdesc->enable_reg = register_info[0]; @@ -260,33 +257,33 @@ static int hisi_dt_parse(struct platform_device *pdev, sreg->eco_mode_mask = register_info[2]; /* parse .register_info.vsel_reg */ - ret = of_property_read_u32_array(np, "hisilicon,hisi-vset", + ret = of_property_read_u32_array(np, "hi6421-vsel", register_info, 2); if (ret) { - dev_err(dev, "no hisilicon,hisi-vset property set\n"); + dev_err(dev, "no hi6421-vsel property set\n"); return ret; } rdesc->vsel_reg = register_info[0]; rdesc->vsel_mask = register_info[1]; /* parse .off-on-delay */ - ret = of_property_read_u32(np, "hisilicon,hisi-off-on-delay-us", + ret = of_property_read_u32(np, "off-on-delay-us", &rdesc->off_on_delay); if (ret) { - dev_err(dev, "no hisilicon,hisi-off-on-delay-us property set\n"); + dev_err(dev, "no off-on-delay-us property set\n"); return ret; } /* parse .enable_time */ - ret = of_property_read_u32(np, "hisilicon,hisi-enable-time-us", + ret = of_property_read_u32(np, "startup-delay-us", &rdesc->enable_time); if (ret) { - dev_err(dev, "no hisilicon,hisi-enable-time-us property set\n"); + dev_err(dev, "no startup-delay-us property set\n"); return ret; } /* parse .eco_uA */ - ret = of_property_read_u32(np, "hisilicon,hisi-eco-microamp", + ret = of_property_read_u32(np, "eco-microamp", &sreg->eco_uA); if (ret) { sreg->eco_uA = 0; @@ -295,7 +292,7 @@ static int hisi_dt_parse(struct platform_device *pdev, /* parse volt_table */ - rdesc->n_voltages = of_property_count_u32_elems(np, "hisilicon,hisi-vset-table"); + rdesc->n_voltages = of_property_count_u32_elems(np, "voltage-table"); v_table = devm_kzalloc(dev, sizeof(unsigned int) * rdesc->n_voltages, GFP_KERNEL); @@ -303,10 +300,10 @@ static int hisi_dt_parse(struct platform_device *pdev, return -ENOMEM; rdesc->volt_table = v_table; - ret = of_property_read_u32_array(np, "hisilicon,hisi-vset-table", + ret = of_property_read_u32_array(np, "voltage-table", v_table, rdesc->n_voltages); if (ret) { - dev_err(dev, "no hisilicon,hisi-vset-table property set\n"); + dev_err(dev, "no voltage-table property set\n"); return ret; } @@ -329,13 +326,6 @@ static struct regulator_ops hisi_ldo_rops = { * Used only for parsing the DT properties */ -static const struct of_device_id of_hisi_pmic_match_tbl[] = { - { - .compatible = "hisilicon,hi6421-spmi-pmic-ldo", - }, - { } -}; - static int hisi_regulator_probe_ldo(struct platform_device *pdev, struct device_node *np, struct hisi_pmic *pmic) @@ -360,14 +350,14 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, /* hisi regulator supports two modes */ constraint = &initdata->constraints; - ret = of_property_read_u32_array(np, "hisilicon,valid-modes-mask", + ret = of_property_read_u32_array(np, "valid-modes-mask", &constraint->valid_modes_mask, 1); if (ret) { dev_err(dev, "no valid modes mask\n"); ret = -ENODEV; return ret; } - ret = of_property_read_u32_array(np, "hisilicon,valid-idle-mask", + ret = of_property_read_u32_array(np, "valid-idle-mask", &temp_modes, 1); if (ret) { dev_err(dev, "no valid idle mask\n"); @@ -388,7 +378,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, rdesc->type = REGULATOR_VOLTAGE; rdesc->min_uV = initdata->constraints.min_uV; - supplyname = of_get_property(np, "hisilicon,supply_name", NULL); + supplyname = of_get_property(np, "supply_name", NULL); if (supplyname) initdata->supply_regulator = supplyname; -- cgit v1.2.3 From e086a9cd2b9facf9e081af63f4728371645d1a6f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:50 +0200 Subject: staging: regulator: hi6421v600-regulator: better handle modes Instead of implementing a custom set of properties, set valid_modes_mask based on having or not a mask for enabling the eco_mode. This makes the code clearer, and remove some uneeded props from DT. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/0f4ac5a4167bbca428c8507b6992acd8b3ebabd1.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 32 ++++++++----------------- 1 file changed, 10 insertions(+), 22 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index e4a64893a7ad..bde7fa4d7e8f 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -338,7 +338,6 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, struct regulator_config config = { }; struct regulation_constraints *constraint; const char *supplyname = NULL; - unsigned int temp_modes; int ret = 0; initdata = of_get_regulator_init_data(dev, np, NULL); @@ -347,25 +346,6 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, return -EINVAL; } - /* hisi regulator supports two modes */ - constraint = &initdata->constraints; - - ret = of_property_read_u32_array(np, "valid-modes-mask", - &constraint->valid_modes_mask, 1); - if (ret) { - dev_err(dev, "no valid modes mask\n"); - ret = -ENODEV; - return ret; - } - ret = of_property_read_u32_array(np, "valid-idle-mask", - &temp_modes, 1); - if (ret) { - dev_err(dev, "no valid idle mask\n"); - ret = -ENODEV; - return ret; - } - constraint->valid_ops_mask |= temp_modes; - sreg = kzalloc(sizeof(*sreg), GFP_KERNEL); if (!sreg) return -ENOMEM; @@ -387,6 +367,15 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, if (ret) goto hisi_probe_end; + /* hisi regulator supports two modes */ + constraint = &initdata->constraints; + + constraint->valid_modes_mask = REGULATOR_MODE_NORMAL; + if (sreg->eco_mode_mask) { + constraint->valid_modes_mask |= REGULATOR_MODE_IDLE; + constraint->valid_ops_mask |= REGULATOR_CHANGE_MODE; + } + config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = sreg; @@ -401,8 +390,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, goto hisi_probe_end; } - dev_dbg(dev, "%s:valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", - rdesc->name, + dev_dbg(dev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); -- cgit v1.2.3 From c22aeb9412cae7417df72c4d1685a0d8f6f81ff2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:51 +0200 Subject: staging: regulator: hi6421v600-regulator: change namespace Rename the functions used internally inside the driver in order for them to follow the driver's name. While here, get rid of some unused definitions at the header file. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5cda96baef9374a096a7a0c8f76f60491b0084c7.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 94 ++++++++++++------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index bde7fa4d7e8f..f77ecea78597 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -41,7 +41,7 @@ struct hi6421v600_regulator { struct regulator_desc rdesc; - struct hisi_pmic *pmic; + struct hi6421_spmi_pmic *pmic; u8 eco_mode_mask; u32 eco_uA; }; @@ -52,13 +52,13 @@ static DEFINE_MUTEX(enable_mutex); * microseconds after 'since'. */ -static int hisi_regulator_is_enabled(struct regulator_dev *rdev) +static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev) { u32 reg_val; struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; - reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); + reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, val= 0x%x, enable_state=%d\n", @@ -68,10 +68,10 @@ static int hisi_regulator_is_enabled(struct regulator_dev *rdev) return ((reg_val & rdev->desc->enable_mask) != 0); } -static int hisi_regulator_enable(struct regulator_dev *rdev) +static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; /* keep a distance of off_on_delay from last time disabled */ usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 1000); @@ -85,7 +85,7 @@ static int hisi_regulator_enable(struct regulator_dev *rdev) HISI_REGS_ENA_PROTECT_TIME + 1000); /* set enable register */ - hisi_pmic_rmw(pmic, rdev->desc->enable_reg, + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, rdev->desc->enable_mask, rdev->desc->enable_mask); dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, enable_mask=0x%x\n", @@ -97,27 +97,27 @@ static int hisi_regulator_enable(struct regulator_dev *rdev) return 0; } -static int hisi_regulator_disable(struct regulator_dev *rdev) +static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; /* set enable register to 0 */ - hisi_pmic_rmw(pmic, rdev->desc->enable_reg, + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, rdev->desc->enable_mask, 0); return 0; } -static int hisi_regulator_get_voltage(struct regulator_dev *rdev) +static int hi6421_spmi_regulator_get_voltage(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 reg_val, selector; int vol; /* get voltage selector */ - reg_val = hisi_pmic_read(pmic, rdev->desc->vsel_reg); + reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg); selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); @@ -130,11 +130,11 @@ static int hisi_regulator_get_voltage(struct regulator_dev *rdev) return vol; } -static int hisi_regulator_set_voltage(struct regulator_dev *rdev, +static int hi6421_spmi_regulator_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned int *selector) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 vsel; int uV, ret = 0; @@ -155,7 +155,7 @@ static int hisi_regulator_set_voltage(struct regulator_dev *rdev, *selector = vsel; /* set voltage selector */ - hisi_pmic_rmw(pmic, rdev->desc->vsel_reg, + hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg, rdev->desc->vsel_mask, vsel << (ffs(rdev->desc->vsel_mask) - 1)); @@ -169,14 +169,14 @@ static int hisi_regulator_set_voltage(struct regulator_dev *rdev, return ret; } -static unsigned int hisi_regulator_get_mode(struct regulator_dev *rdev) +static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 reg_val; unsigned int mode; - reg_val = hisi_pmic_read(pmic, rdev->desc->enable_reg); + reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); if (reg_val & sreg->eco_mode_mask) mode = REGULATOR_MODE_IDLE; @@ -191,11 +191,11 @@ static unsigned int hisi_regulator_get_mode(struct regulator_dev *rdev) return mode; } -static int hisi_regulator_set_mode(struct regulator_dev *rdev, +static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, unsigned int mode) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - struct hisi_pmic *pmic = sreg->pmic; + struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 val; switch (mode) { @@ -210,8 +210,8 @@ static int hisi_regulator_set_mode(struct regulator_dev *rdev, } /* set mode */ - hisi_pmic_rmw(pmic, rdev->desc->enable_reg, - sreg->eco_mode_mask, val); + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, + sreg->eco_mode_mask, val); dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n", @@ -220,7 +220,7 @@ static int hisi_regulator_set_mode(struct regulator_dev *rdev, return 0; } -static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *rdev, +static unsigned int hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA) { @@ -235,7 +235,7 @@ static unsigned int hisi_regulator_get_optimum_mode(struct regulator_dev *rdev, } } -static int hisi_dt_parse(struct platform_device *pdev, +static int hi6421_spmi_dt_parse(struct platform_device *pdev, struct hi6421v600_regulator *sreg, struct regulator_desc *rdesc) { @@ -310,25 +310,25 @@ static int hisi_dt_parse(struct platform_device *pdev, return 0; } -static struct regulator_ops hisi_ldo_rops = { - .is_enabled = hisi_regulator_is_enabled, - .enable = hisi_regulator_enable, - .disable = hisi_regulator_disable, +static struct regulator_ops hi6421_spmi_ldo_rops = { + .is_enabled = hi6421_spmi_regulator_is_enabled, + .enable = hi6421_spmi_regulator_enable, + .disable = hi6421_spmi_regulator_disable, .list_voltage = regulator_list_voltage_table, - .get_voltage = hisi_regulator_get_voltage, - .set_voltage = hisi_regulator_set_voltage, - .get_mode = hisi_regulator_get_mode, - .set_mode = hisi_regulator_set_mode, - .get_optimum_mode = hisi_regulator_get_optimum_mode, + .get_voltage = hi6421_spmi_regulator_get_voltage, + .set_voltage = hi6421_spmi_regulator_set_voltage, + .get_mode = hi6421_spmi_regulator_get_mode, + .set_mode = hi6421_spmi_regulator_set_mode, + .get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode, }; /* * Used only for parsing the DT properties */ -static int hisi_regulator_probe_ldo(struct platform_device *pdev, +static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, struct device_node *np, - struct hisi_pmic *pmic) + struct hi6421_spmi_pmic *pmic) { struct device *dev = &pdev->dev; struct regulator_desc *rdesc; @@ -354,7 +354,7 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, rdesc = &sreg->rdesc; rdesc->name = initdata->constraints.name; - rdesc->ops = &hisi_ldo_rops; + rdesc->ops = &hi6421_spmi_ldo_rops; rdesc->type = REGULATOR_VOLTAGE; rdesc->min_uV = initdata->constraints.min_uV; @@ -363,9 +363,9 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, initdata->supply_regulator = supplyname; /* parse device tree data for regulator specific */ - ret = hisi_dt_parse(pdev, sreg, rdesc); + ret = hi6421_spmi_dt_parse(pdev, sreg, rdesc); if (ret) - goto hisi_probe_end; + goto probe_end; /* hisi regulator supports two modes */ constraint = &initdata->constraints; @@ -387,27 +387,27 @@ static int hisi_regulator_probe_ldo(struct platform_device *pdev, dev_err(dev, "failed to register %s\n", rdesc->name); ret = PTR_ERR(rdev); - goto hisi_probe_end; + goto probe_end; } dev_dbg(dev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); -hisi_probe_end: +probe_end: if (ret) kfree(sreg); return ret; } -static int hisi_regulator_probe(struct platform_device *pdev) +static int hi6421_spmi_regulator_probe(struct platform_device *pdev) { struct device *pmic_dev = pdev->dev.parent; struct device_node *np = pmic_dev->of_node; struct device_node *regulators, *child; struct platform_device *new_pdev; - struct hisi_pmic *pmic; + struct hi6421_spmi_pmic *pmic; int ret; dev_dbg(&pdev->dev, "probing hi6421v600 regulator\n"); @@ -442,7 +442,7 @@ static int hisi_regulator_probe(struct platform_device *pdev) continue; } - ret = hisi_regulator_probe_ldo(new_pdev, child, pmic); + ret = hi6421_spmi_regulator_probe_ldo(new_pdev, child, pmic); if (ret < 0) platform_device_put(new_pdev); } @@ -452,7 +452,7 @@ static int hisi_regulator_probe(struct platform_device *pdev) return 0; } -static int hisi_regulator_remove(struct platform_device *pdev) +static int hi6421_spmi_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = dev_get_drvdata(&pdev->dev); struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); @@ -479,8 +479,8 @@ static struct platform_driver hi6421v600_regulator_driver = { .driver = { .name = "hi6421v600-regulator", }, - .probe = hisi_regulator_probe, - .remove = hisi_regulator_remove, + .probe = hi6421_spmi_regulator_probe, + .remove = hi6421_spmi_regulator_remove, }; module_platform_driver(hi6421v600_regulator_driver); -- cgit v1.2.3 From 60432176956cf7aaa9b7d45d7b5adeaa443c2752 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:52 +0200 Subject: staging: regulator: hi6421v600-regulator: convert to use get/set voltage_sel As the supported LDOs on this driver are all using a selector, change the implementation to use get_voltage_sel and set_voltage_sel ops. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/1cf4f26540e65ffbb561c7d52e53f6be5bd63ac4.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 58 ++++++++++--------------- 1 file changed, 22 insertions(+), 36 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index f77ecea78597..abd1f43dd5ec 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -86,8 +86,8 @@ static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) /* set enable register */ hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, - rdev->desc->enable_mask, - rdev->desc->enable_mask); + rdev->desc->enable_mask, + rdev->desc->enable_mask); dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, enable_mask=0x%x\n", __func__, rdev->desc->enable_reg, rdev->desc->enable_mask); @@ -109,64 +109,49 @@ static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) return 0; } -static int hi6421_spmi_regulator_get_voltage(struct regulator_dev *rdev) +static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 reg_val, selector; - int vol; /* get voltage selector */ reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg); - selector = (reg_val & rdev->desc->vsel_mask) >> - (ffs(rdev->desc->vsel_mask) - 1); - vol = rdev->desc->ops->list_voltage(rdev, selector); + selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); dev_dbg(&rdev->dev, - "%s: vsel_reg=0x%x, val=0x%x, entry=0x%x, voltage=%d mV\n", - __func__, rdev->desc->vsel_reg, reg_val, selector, vol/ 1000); + "%s: vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n", + __func__, rdev->desc->vsel_reg, reg_val, selector, + rdev->desc->ops->list_voltage(rdev, selector) / 1000); - return vol; + return selector; } -static int hi6421_spmi_regulator_set_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned int *selector) +static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev, + unsigned int selector) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; - u32 vsel; - int uV, ret = 0; - - for (vsel = 0; vsel < rdev->desc->n_voltages; vsel++) { - uV = rdev->desc->volt_table[vsel]; - dev_dbg(&rdev->dev, - "%s: min %d, max %d, value[%u] = %d\n", - __func__, min_uV, max_uV, vsel, uV); - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } + u32 reg_val; /* unlikely to happen. sanity test done by regulator core */ - if (unlikely(vsel == rdev->desc->n_voltages)) + if (unlikely(selector >= rdev->desc->n_voltages)) return -EINVAL; - *selector = vsel; + reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1); + /* set voltage selector */ hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, - vsel << (ffs(rdev->desc->vsel_mask) - 1)); + rdev->desc->vsel_mask, reg_val); dev_dbg(&rdev->dev, - "%s: vsel_reg=0x%x, vsel_mask=0x%x, value=0x%x, voltage=%d mV\n", + "%s: vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n", __func__, - rdev->desc->vsel_reg, - rdev->desc->vsel_mask, - vsel << (ffs(rdev->desc->vsel_mask) - 1), uV / 1000); + rdev->desc->vsel_reg, rdev->desc->vsel_mask, reg_val, + rdev->desc->ops->list_voltage(rdev, selector) / 1000); - return ret; + return 0; } static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) @@ -315,8 +300,9 @@ static struct regulator_ops hi6421_spmi_ldo_rops = { .enable = hi6421_spmi_regulator_enable, .disable = hi6421_spmi_regulator_disable, .list_voltage = regulator_list_voltage_table, - .get_voltage = hi6421_spmi_regulator_get_voltage, - .set_voltage = hi6421_spmi_regulator_set_voltage, + .map_voltage = regulator_map_voltage_iterate, + .get_voltage_sel = hi6421_spmi_regulator_get_voltage_sel, + .set_voltage_sel = hi6421_spmi_regulator_set_voltage_sel, .get_mode = hi6421_spmi_regulator_get_mode, .set_mode = hi6421_spmi_regulator_set_mode, .get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode, -- cgit v1.2.3 From 67a345c7843ee287496a8ae6dce5d54064c60ad3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:53 +0200 Subject: staging: regulator: hi6421v600-regulator: don't use usleep_range for off_on_delay The regulator's core already handles it. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/4f17adca2b04c401e5de5556700638648ce25c0c.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index abd1f43dd5ec..31b8ff19fd31 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -73,9 +73,6 @@ static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; - /* keep a distance of off_on_delay from last time disabled */ - usleep_range(rdev->desc->off_on_delay, rdev->desc->off_on_delay + 1000); - dev_dbg(&rdev->dev, "%s: off_on_delay=%d us\n", __func__, rdev->desc->off_on_delay); -- cgit v1.2.3 From 875a65a05dc4b563ccf6f4d18dcc57eb484f8f1b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:54 +0200 Subject: staging: regulator: hi6421v600-regulator: add a driver-specific debug macro Using dev_dbg() is not too nice, as, instead of printing the name of the regulator, it prints "regulator.", making harder to associate what is happening with each ldo line. So, add a debug-specific macro, which will print the rdev's name, just like the regulator core. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/1690b8531b23910aa915bd2725410b926022c481.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 61 +++++++++++++------------ 1 file changed, 32 insertions(+), 29 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 31b8ff19fd31..5ddaf7f8cacc 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -39,6 +39,9 @@ #include #include +#define rdev_dbg(rdev, fmt, arg...) \ + pr_debug("%s: %s: " fmt, rdev->desc->name, __func__, ##arg) + struct hi6421v600_regulator { struct regulator_desc rdesc; struct hi6421_spmi_pmic *pmic; @@ -60,10 +63,10 @@ static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev) reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); - dev_dbg(&rdev->dev, - "%s: enable_reg=0x%x, val= 0x%x, enable_state=%d\n", - __func__, rdev->desc->enable_reg, - reg_val, (reg_val & rdev->desc->enable_mask)); + rdev_dbg(rdev, + "enable_reg=0x%x, val= 0x%x, enable_state=%d\n", + rdev->desc->enable_reg, + reg_val, (reg_val & rdev->desc->enable_mask)); return ((reg_val & rdev->desc->enable_mask) != 0); } @@ -73,21 +76,20 @@ static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev) struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; - dev_dbg(&rdev->dev, "%s: off_on_delay=%d us\n", - __func__, rdev->desc->off_on_delay); - /* cannot enable more than one regulator at one time */ mutex_lock(&enable_mutex); usleep_range(HISI_REGS_ENA_PROTECT_TIME, HISI_REGS_ENA_PROTECT_TIME + 1000); /* set enable register */ + rdev_dbg(rdev, + "off_on_delay=%d us, enable_reg=0x%x, enable_mask=0x%x\n", + rdev->desc->off_on_delay, rdev->desc->enable_reg, + rdev->desc->enable_mask); + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, rdev->desc->enable_mask, rdev->desc->enable_mask); - dev_dbg(&rdev->dev, "%s: enable_reg=0x%x, enable_mask=0x%x\n", - __func__, rdev->desc->enable_reg, - rdev->desc->enable_mask); mutex_unlock(&enable_mutex); @@ -100,6 +102,9 @@ static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) struct hi6421_spmi_pmic *pmic = sreg->pmic; /* set enable register to 0 */ + rdev_dbg(rdev, "enable_reg=0x%x, enable_mask=0x%x\n", + rdev->desc->enable_reg, rdev->desc->enable_mask); + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, rdev->desc->enable_mask, 0); @@ -117,9 +122,9 @@ static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev) selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); - dev_dbg(&rdev->dev, - "%s: vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n", - __func__, rdev->desc->vsel_reg, reg_val, selector, + rdev_dbg(rdev, + "vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n", + rdev->desc->vsel_reg, reg_val, selector, rdev->desc->ops->list_voltage(rdev, selector) / 1000); return selector; @@ -139,15 +144,14 @@ static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev, reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1); /* set voltage selector */ - hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg, - rdev->desc->vsel_mask, reg_val); - - dev_dbg(&rdev->dev, - "%s: vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n", - __func__, + rdev_dbg(rdev, + "vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n", rdev->desc->vsel_reg, rdev->desc->vsel_mask, reg_val, rdev->desc->ops->list_voltage(rdev, selector) / 1000); + hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg, + rdev->desc->vsel_mask, reg_val); + return 0; } @@ -165,9 +169,9 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) else mode = REGULATOR_MODE_NORMAL; - dev_dbg(&rdev->dev, - "%s: enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n", - __func__, rdev->desc->enable_reg, sreg->eco_mode_mask, reg_val, + rdev_dbg(rdev, + "enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n", + rdev->desc->enable_reg, sreg->eco_mode_mask, reg_val, mode == REGULATOR_MODE_IDLE ? "idle" : "normal"); return mode; @@ -192,13 +196,12 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, } /* set mode */ + rdev_dbg(rdev, "enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n", + rdev->desc->enable_reg, sreg->eco_mode_mask, val); + hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, sreg->eco_mode_mask, val); - dev_dbg(&rdev->dev, - "%s: enable_reg=0x%x, eco_mode_mask=0x%x, value=0x%x\n", - __func__, rdev->desc->enable_reg, sreg->eco_mode_mask, val); - return 0; } @@ -209,10 +212,10 @@ static unsigned int hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) { - dev_dbg(&rdev->dev, "%s: normal mode", __func__); + rdev_dbg(rdev, "normal mode"); return REGULATOR_MODE_NORMAL; } else { - dev_dbg(&rdev->dev, "%s: idle mode", __func__); + rdev_dbg(rdev, "idle mode"); return REGULATOR_MODE_IDLE; } } @@ -373,7 +376,7 @@ static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, goto probe_end; } - dev_dbg(dev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", + rdev_dbg(rdev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); -- cgit v1.2.3 From 6105e9ab64c6dea7337a4c9bc996e0cdde59a799 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:55 +0200 Subject: staging: regulator: hi6421v600-regulator: initialize ramp_delay Without that, the regulator's core complains with: ldo17: ramp_delay not set For now, use the enable time, as we don't have any datasheets from this device. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/67df5456e4f23c88ab4fd9331eb8202c3952e5c5.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 5ddaf7f8cacc..21467fce9980 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -267,6 +267,9 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, return ret; } + /* FIXME: are there a better value for this? */ + rdesc->ramp_delay = rdesc->enable_time; + /* parse .eco_uA */ ret = of_property_read_u32(np, "eco-microamp", &sreg->eco_uA); -- cgit v1.2.3 From 6f9bd6e2621e6bbfd1aa152f97b3030375a5feb2 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:56 +0200 Subject: staging: regulator: hi6421v600-regulator: cleanup DT settings Currently, an array is used to store both vsel and enable settings, mixing registers, masks and bit settings. Change it in order to have one separate property for each. This makes easier to understand the contents of the DT file, and to describe it at the Documentation/. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/fd72215b0a7da55dd727c2d7bd01c047a46cdd2e.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 69 +++++++++++++++---------- 1 file changed, 42 insertions(+), 27 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 21467fce9980..72f51594b5ff 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -45,8 +45,7 @@ struct hi6421v600_regulator { struct regulator_desc rdesc; struct hi6421_spmi_pmic *pmic; - u8 eco_mode_mask; - u32 eco_uA; + u32 eco_mode_mask, eco_uA; }; static DEFINE_MUTEX(enable_mutex); @@ -226,36 +225,49 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, { struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; - unsigned int register_info[3] = {0}; unsigned int *v_table; int ret; - /* parse .register_info.enable_reg */ - ret = of_property_read_u32_array(np, "hi6421-ctrl", - register_info, 3); + ret = of_property_read_u32(np, "reg", &rdesc->enable_reg); if (ret) { - dev_err(dev, "no hi6421-ctrl property set\n"); + dev_err(dev, "missing reg property\nn"); return ret; } - rdesc->enable_reg = register_info[0]; - rdesc->enable_mask = register_info[1]; - sreg->eco_mode_mask = register_info[2]; - /* parse .register_info.vsel_reg */ - ret = of_property_read_u32_array(np, "hi6421-vsel", - register_info, 2); + ret = of_property_read_u32(np, "vsel-reg", &rdesc->vsel_reg); if (ret) { - dev_err(dev, "no hi6421-vsel property set\n"); + dev_err(dev, "missing vsel-reg property\n"); return ret; } - rdesc->vsel_reg = register_info[0]; - rdesc->vsel_mask = register_info[1]; + + ret = of_property_read_u32(np, "enable-mask", &rdesc->enable_mask); + if (ret) { + dev_err(dev, "missing enable-mask property\n"); + return ret; + } + + /* + * Not all regulators work on idle mode + */ + ret = of_property_read_u32(np, "idle-mode-mask", &sreg->eco_mode_mask); + if (ret) { + dev_dbg(dev, "LDO doesn't support economy mode.\n"); + sreg->eco_mode_mask = 0; + sreg->eco_uA = 0; + } else { + ret = of_property_read_u32(np, "eco-microamp", + &sreg->eco_uA); + if (ret) { + dev_err(dev, "missing eco-microamp property\n"); + return ret; + } + } /* parse .off-on-delay */ ret = of_property_read_u32(np, "off-on-delay-us", &rdesc->off_on_delay); if (ret) { - dev_err(dev, "no off-on-delay-us property set\n"); + dev_err(dev, "missing off-on-delay-us property\n"); return ret; } @@ -263,21 +275,13 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, ret = of_property_read_u32(np, "startup-delay-us", &rdesc->enable_time); if (ret) { - dev_err(dev, "no startup-delay-us property set\n"); + dev_err(dev, "missing startup-delay-us property\n"); return ret; } /* FIXME: are there a better value for this? */ rdesc->ramp_delay = rdesc->enable_time; - /* parse .eco_uA */ - ret = of_property_read_u32(np, "eco-microamp", - &sreg->eco_uA); - if (ret) { - sreg->eco_uA = 0; - ret = 0; - } - /* parse volt_table */ rdesc->n_voltages = of_property_count_u32_elems(np, "voltage-table"); @@ -291,10 +295,21 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, ret = of_property_read_u32_array(np, "voltage-table", v_table, rdesc->n_voltages); if (ret) { - dev_err(dev, "no voltage-table property set\n"); + dev_err(dev, "missing voltage-table property\n"); return ret; } + /* + * Instead of explicitly requiring a mask for the voltage selector, + * as they all start from bit zero (at least on the known LDOs), + * just use the number of voltages at the voltage table, getting the + * minimal mask that would pick everything. + */ + rdesc->vsel_mask = (1 << (fls(rdesc->n_voltages) - 1)) - 1; + + dev_dbg(dev, "voltage selector settings: reg: 0x%x, mask: 0x%x", + rdesc->vsel_reg, rdesc->vsel_mask); + return 0; } -- cgit v1.2.3 From 1275f3c3fc8ed97cdc5a45244674328dc6e18f1a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:57 +0200 Subject: staging: regulator: hi6421v600-regulator: fix some coding style issues Fix the remaining issues complained by checkpatch. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/af5101fa2ab1d267ac5ac22603f95c6065ac110f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 72f51594b5ff..c80dfac1e4c3 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -40,7 +40,7 @@ #include #define rdev_dbg(rdev, fmt, arg...) \ - pr_debug("%s: %s: " fmt, rdev->desc->name, __func__, ##arg) + pr_debug("%s: %s: " fmt, (rdev)->desc->name, __func__, ##arg) struct hi6421v600_regulator { struct regulator_desc rdesc; @@ -105,7 +105,7 @@ static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev) rdev->desc->enable_reg, rdev->desc->enable_mask); hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg, - rdev->desc->enable_mask, 0); + rdev->desc->enable_mask, 0); return 0; } @@ -122,7 +122,7 @@ static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev) selector = (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1); rdev_dbg(rdev, - "vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n", + "vsel_reg=0x%x, value=0x%x, entry=0x%x, voltage=%d mV\n", rdev->desc->vsel_reg, reg_val, selector, rdev->desc->ops->list_voltage(rdev, selector) / 1000); @@ -144,7 +144,7 @@ static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev, /* set voltage selector */ rdev_dbg(rdev, - "vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n", + "vsel_reg=0x%x, mask=0x%x, value=0x%x, voltage=%d mV\n", rdev->desc->vsel_reg, rdev->desc->vsel_mask, reg_val, rdev->desc->ops->list_voltage(rdev, selector) / 1000); @@ -169,7 +169,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) mode = REGULATOR_MODE_NORMAL; rdev_dbg(rdev, - "enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n", + "enable_reg=0x%x, eco_mode_mask=0x%x, reg_val=0x%x, %s mode\n", rdev->desc->enable_reg, sreg->eco_mode_mask, reg_val, mode == REGULATOR_MODE_IDLE ? "idle" : "normal"); @@ -177,7 +177,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) } static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, - unsigned int mode) + unsigned int mode) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; @@ -204,9 +204,10 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev, return 0; } -static unsigned int hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, - int input_uV, int output_uV, - int load_uA) +static unsigned int +hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, + int input_uV, int output_uV, + int load_uA) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); @@ -220,7 +221,7 @@ static unsigned int hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev } static int hi6421_spmi_dt_parse(struct platform_device *pdev, - struct hi6421v600_regulator *sreg, + struct hi6421v600_regulator *sreg, struct regulator_desc *rdesc) { struct device *dev = &pdev->dev; @@ -256,7 +257,7 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, sreg->eco_uA = 0; } else { ret = of_property_read_u32(np, "eco-microamp", - &sreg->eco_uA); + &sreg->eco_uA); if (ret) { dev_err(dev, "missing eco-microamp property\n"); return ret; @@ -331,8 +332,8 @@ static struct regulator_ops hi6421_spmi_ldo_rops = { */ static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, - struct device_node *np, - struct hi6421_spmi_pmic *pmic) + struct device_node *np, + struct hi6421_spmi_pmic *pmic) { struct device *dev = &pdev->dev; struct regulator_desc *rdesc; @@ -404,7 +405,6 @@ probe_end: return ret; } - static int hi6421_spmi_regulator_probe(struct platform_device *pdev) { struct device *pmic_dev = pdev->dev.parent; -- cgit v1.2.3 From 88e059e6c428fc7253e09b1ecc8e792533b86647 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:58 +0200 Subject: staging: regulator: hi6421v600-regulator: add it to the building system Change the binding logic to ensure that the PMIC SPMI driver will run before the regulator code and add it to the building system. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/2992dc49945dcfb07c4bd96fa5c288c4e679701a.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/Kconfig | 10 +++++++++- drivers/staging/hikey9xx/Makefile | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index 7ca083b7e94d..76267b9be562 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -15,7 +15,6 @@ config MFD_HI6421_SPMI tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" depends on OF select MFD_CORE - select REGMAP_MMIO help Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes multi-functions, such as regulators, RTC, codec, Coulomb counter, @@ -25,3 +24,12 @@ config MFD_HI6421_SPMI individual components like voltage regulators under corresponding menus in order to enable them. We communicate with the Hi6421v600 via a SPMI bus. + +# to be placed at drivers/regulator +config REGULATOR_HI6421V600 + tristate "HiSilicon Hi6421v600 PMIC voltage regulator support" + depends on MFD_HI6421_PMIC && OF + help + This driver provides support for the voltage regulators on + HiSilicon Hi6421v600 PMU / Codec IC. + This is used on Kirin 3670 boards, like HiKey 970. diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile index 79de37da7a8f..9371dcc3d35b 100644 --- a/drivers/staging/hikey9xx/Makefile +++ b/drivers/staging/hikey9xx/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o -obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o +obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o +obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o +obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o -- cgit v1.2.3 From 2c4fb70d185c7e7080e73bd382f3b4814d89d8c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:10:59 +0200 Subject: staging: regulator: hi6421v600-regulator: code cleanup Do some code cleanup in order to make it cleaner for moving it out of staging in the future. Suggested-by: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/32fadb359c1817992af78052e2d9448b8c5fc61f.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 78 ++++++++++--------------- 1 file changed, 32 insertions(+), 46 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index c80dfac1e4c3..82635ff54a74 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -15,29 +15,28 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ -#include +#include #include -#include #include #include -#include -#include -#include +#include +#include #include +#include +#include +#include #include #include #include #include -#include -#include -#include -#include #include -#include +#include #include +#include +#include +#include #define rdev_dbg(rdev, fmt, arg...) \ pr_debug("%s: %s: " fmt, (rdev)->desc->name, __func__, ##arg) @@ -50,15 +49,16 @@ struct hi6421v600_regulator { static DEFINE_MUTEX(enable_mutex); -/* helper function to ensure when it returns it is at least 'delay_us' +/* + * helper function to ensure when it returns it is at least 'delay_us' * microseconds after 'since'. */ static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev) { - u32 reg_val; struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; + u32 reg_val; reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); @@ -136,7 +136,6 @@ static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev, struct hi6421_spmi_pmic *pmic = sreg->pmic; u32 reg_val; - /* unlikely to happen. sanity test done by regulator core */ if (unlikely(selector >= rdev->desc->n_voltages)) return -EINVAL; @@ -158,8 +157,8 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev) { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); struct hi6421_spmi_pmic *pmic = sreg->pmic; - u32 reg_val; unsigned int mode; + u32 reg_val; reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->enable_reg); @@ -211,13 +210,10 @@ hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev, { struct hi6421v600_regulator *sreg = rdev_get_drvdata(rdev); - if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) { - rdev_dbg(rdev, "normal mode"); + if (load_uA || ((unsigned int)load_uA > sreg->eco_uA)) return REGULATOR_MODE_NORMAL; - } else { - rdev_dbg(rdev, "idle mode"); - return REGULATOR_MODE_IDLE; - } + + return REGULATOR_MODE_IDLE; } static int hi6421_spmi_dt_parse(struct platform_device *pdev, @@ -231,7 +227,7 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, ret = of_property_read_u32(np, "reg", &rdesc->enable_reg); if (ret) { - dev_err(dev, "missing reg property\nn"); + dev_err(dev, "missing reg property\n"); return ret; } @@ -256,8 +252,7 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, sreg->eco_mode_mask = 0; sreg->eco_uA = 0; } else { - ret = of_property_read_u32(np, "eco-microamp", - &sreg->eco_uA); + ret = of_property_read_u32(np, "eco-microamp", &sreg->eco_uA); if (ret) { dev_err(dev, "missing eco-microamp property\n"); return ret; @@ -308,13 +303,13 @@ static int hi6421_spmi_dt_parse(struct platform_device *pdev, */ rdesc->vsel_mask = (1 << (fls(rdesc->n_voltages) - 1)) - 1; - dev_dbg(dev, "voltage selector settings: reg: 0x%x, mask: 0x%x", + dev_dbg(dev, "voltage selector settings: reg: 0x%x, mask: 0x%x\n", rdesc->vsel_reg, rdesc->vsel_mask); return 0; } -static struct regulator_ops hi6421_spmi_ldo_rops = { +static const struct regulator_ops hi6421_spmi_ldo_rops = { .is_enabled = hi6421_spmi_regulator_is_enabled, .enable = hi6421_spmi_regulator_enable, .disable = hi6421_spmi_regulator_disable, @@ -327,23 +322,19 @@ static struct regulator_ops hi6421_spmi_ldo_rops = { .get_optimum_mode = hi6421_spmi_regulator_get_optimum_mode, }; -/* - * Used only for parsing the DT properties - */ - static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, struct device_node *np, struct hi6421_spmi_pmic *pmic) { + struct regulation_constraints *constraint; + struct regulator_init_data *initdata; + struct regulator_config config = { }; + struct hi6421v600_regulator *sreg; struct device *dev = &pdev->dev; struct regulator_desc *rdesc; struct regulator_dev *rdev; - struct hi6421v600_regulator *sreg = NULL; - struct regulator_init_data *initdata; - struct regulator_config config = { }; - struct regulation_constraints *constraint; - const char *supplyname = NULL; - int ret = 0; + const char *supplyname; + int ret; initdata = of_get_regulator_init_data(dev, np, NULL); if (!initdata) { @@ -351,7 +342,7 @@ static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, return -EINVAL; } - sreg = kzalloc(sizeof(*sreg), GFP_KERNEL); + sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); if (!sreg) return -ENOMEM; @@ -370,7 +361,7 @@ static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, /* parse device tree data for regulator specific */ ret = hi6421_spmi_dt_parse(pdev, sreg, rdesc); if (ret) - goto probe_end; + return ret; /* hisi regulator supports two modes */ constraint = &initdata->constraints; @@ -391,18 +382,15 @@ static int hi6421_spmi_regulator_probe_ldo(struct platform_device *pdev, if (IS_ERR(rdev)) { dev_err(dev, "failed to register %s\n", rdesc->name); - ret = PTR_ERR(rdev); - goto probe_end; + return PTR_ERR(rdev); } rdev_dbg(rdev, "valid_modes_mask: 0x%x, valid_ops_mask: 0x%x\n", constraint->valid_modes_mask, constraint->valid_ops_mask); dev_set_drvdata(dev, rdev); -probe_end: - if (ret) - kfree(sreg); - return ret; + + return 0; } static int hi6421_spmi_regulator_probe(struct platform_device *pdev) @@ -414,7 +402,6 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev) struct hi6421_spmi_pmic *pmic; int ret; - dev_dbg(&pdev->dev, "probing hi6421v600 regulator\n"); /* * This driver is meant to be called by hi6421-spmi-core, * which should first set drvdata. If this doesn't happen, hit @@ -463,7 +450,6 @@ static int hi6421_spmi_regulator_remove(struct platform_device *pdev) regulator_unregister(rdev); - /* TODO: should i worry about that? devm_kzalloc */ if (rdev->desc->volt_table) devm_kfree(&pdev->dev, (unsigned int *)rdev->desc->volt_table); -- cgit v1.2.3 From 561e174eb3a153d4e4a3c8da10cabe96c686108b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 17 Aug 2020 09:11:00 +0200 Subject: staging: hikey9xx: add a TODO list Place the things that are needed to be able to move those drivers out of staging. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/bf3ebe32125646e0a87a59280392e8c6fda08488.1597647359.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/TODO | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 drivers/staging/hikey9xx/TODO (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/TODO b/drivers/staging/hikey9xx/TODO new file mode 100644 index 000000000000..65e7996a3066 --- /dev/null +++ b/drivers/staging/hikey9xx/TODO @@ -0,0 +1,5 @@ +ToDo list: + +- Port other drivers needed by Hikey 960/970; +- Test drivers on Hikey 960; +- Validate device tree bindings. -- cgit v1.2.3 From 78dd4243574ffc05c266e5cab7c0d3ebafea51dd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 16:58:53 +0200 Subject: staging: hikey9xx: fix Kconfig dependency chain Both the SPMI controller and the SPMI PMIC driver depends on the SPMI bus support. The dependency for the regulator is also wrong: it should depends on the SPMI version of the HiSilicon 6421, and not on the normal one. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/1b7e23500e7449593393115cc0954af441b0c730.1597762400.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index 76267b9be562..a004839e8fa9 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -5,6 +5,7 @@ config SPMI_HISI3670 tristate "Hisilicon 3670 SPMI Controller" select IRQ_DOMAIN_HIERARCHY depends on HAS_IOMEM + depends on SPMI help If you say yes to this option, support will be included for the built-in SPMI PMIC Arbiter interface on Hisilicon 3670 @@ -14,6 +15,7 @@ config SPMI_HISI3670 config MFD_HI6421_SPMI tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC" depends on OF + depends on SPMI select MFD_CORE help Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes @@ -28,7 +30,7 @@ config MFD_HI6421_SPMI # to be placed at drivers/regulator config REGULATOR_HI6421V600 tristate "HiSilicon Hi6421v600 PMIC voltage regulator support" - depends on MFD_HI6421_PMIC && OF + depends on MFD_HI6421_SPMI && OF help This driver provides support for the voltage regulators on HiSilicon Hi6421v600 PMU / Codec IC. -- cgit v1.2.3 From b240d0143bfbc96f610405f978e4753fd663cbfc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 16:58:54 +0200 Subject: staging: mfd: hi6421-spmi-pmic: get rid of interrupt properties Both irqnum and irqarray properties reflect the same thing: the number of bits and bytes for interrupts at this chipset. E. g.: irqnum = 8 x irqarray This can be seen by the way pending interrupts are handled: /* During probe time */ pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); /* While handling IRQs */ for (i = 0; i < pmic->irqarray; i++) { pending = hi6421_spmi_pmic_read(pmic, (i + pmic->irq_addr)); pending &= 0xff; for_each_set_bit(offset, &pending, 8) generic_handle_irq(pmic->irqs[offset + i * 8]); } Going further, there are some logic at the driver which assumes that irqarray is 2: /* solve powerkey order */ if ((i == HISI_IRQ_KEY_NUM) && ((pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE)) { generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_DOWN]); generic_handle_irq(pmic->irqs[HISI_IRQ_KEY_UP]); pending &= (~HISI_IRQ_KEY_VALUE); } As HISI_IRQ_KEY_DOWN and HISI_IRQ_KEY_UP are fixed values and don't depend on irqnum/irqarray. The IRQ addr and mask addr seem to be also fixed, based on some comments at the OF parsing code. So, get rid of them too, removing the of parsing function completely. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/e231244e42cb5b56240705cac2f987e11a078038.1597762400.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 80 ++++++++--------------------- include/linux/mfd/hi6421-spmi-pmic.h | 15 ------ 2 files changed, 20 insertions(+), 75 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 9d73458ca65a..7817c0637737 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -38,6 +38,12 @@ /* 8-bit register offset in PMIC */ #define HISI_MASK_STATE 0xff +#define HISI_IRQ_ARRAY 2 +#define HISI_IRQ_NUM (HISI_IRQ_ARRAY * 8) + +#define SOC_PMIC_IRQ_MASK_0_ADDR 0x0202 +#define SOC_PMIC_IRQ0_ADDR 0x0212 + #define HISI_IRQ_KEY_NUM 0 #define HISI_IRQ_KEY_VALUE 0xc0 #define HISI_IRQ_KEY_DOWN 7 @@ -121,13 +127,13 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data) unsigned long pending; int i, offset; - for (i = 0; i < pmic->irqarray; i++) { - pending = hi6421_spmi_pmic_read(pmic, (i + pmic->irq_addr)); + for (i = 0; i < HISI_IRQ_ARRAY; i++) { + pending = hi6421_spmi_pmic_read(pmic, (i + SOC_PMIC_IRQ0_ADDR)); pending &= HISI_MASK_FIELD; if (pending != 0) pr_debug("pending[%d]=0x%lx\n\r", i, pending); - hi6421_spmi_pmic_write(pmic, (i + pmic->irq_addr), pending); + hi6421_spmi_pmic_write(pmic, (i + SOC_PMIC_IRQ0_ADDR), pending); /* solve powerkey order */ if ((i == HISI_IRQ_KEY_NUM) && @@ -153,7 +159,7 @@ static void hi6421_spmi_irq_mask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - offset += pmic->irq_mask_addr; + offset += SOC_PMIC_IRQ_MASK_0_ADDR; spin_lock_irqsave(&pmic->lock, flags); data = hi6421_spmi_pmic_read(pmic, offset); @@ -169,7 +175,7 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d) unsigned long flags; offset = (irqd_to_hwirq(d) >> 3); - offset += pmic->irq_mask_addr; + offset += SOC_PMIC_IRQ_MASK_0_ADDR; spin_lock_irqsave(&pmic->lock, flags); data = hi6421_spmi_pmic_read(pmic, offset); @@ -204,60 +210,20 @@ static const struct irq_domain_ops hi6421_spmi_domain_ops = { .xlate = irq_domain_xlate_twocell, }; -static int get_pmic_device_tree_data(struct device_node *np, - struct hi6421_spmi_pmic *pmic) -{ - int ret = 0; - - /* IRQ number */ - ret = of_property_read_u32(np, "irq-num", &pmic->irqnum); - if (ret) { - pr_err("no irq-num property set\n"); - ret = -ENODEV; - return ret; - } - - /* Size of IRQ array */ - ret = of_property_read_u32(np, "irq-array", &pmic->irqarray); - if (ret) { - pr_err("no irq-array property set\n"); - ret = -ENODEV; - return ret; - } - - /* SOC_PMIC_IRQ_MASK_0_ADDR */ - ret = of_property_read_u32(np, "irq-mask-addr", &pmic->irq_mask_addr); - if (ret) { - pr_err("no irq-mask-addr property set\n"); - ret = -ENODEV; - return ret; - } - - /* SOC_PMIC_IRQ0_ADDR */ - ret = of_property_read_u32(np, "irq-addr", &pmic->irq_addr); - if (ret) { - pr_err("no irq-addr property set\n"); - ret = -ENODEV; - return ret; - } - - return ret; -} - static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic) { int i, pending; - for (i = 0 ; i < pmic->irqarray; i++) - hi6421_spmi_pmic_write(pmic, pmic->irq_mask_addr + i, + for (i = 0 ; i < HISI_IRQ_ARRAY; i++) + hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ_MASK_0_ADDR + i, HISI_MASK_STATE); - for (i = 0 ; i < pmic->irqarray; i++) { - pending = hi6421_spmi_pmic_read(pmic, pmic->irq_addr + i); + for (i = 0 ; i < HISI_IRQ_ARRAY; i++) { + pending = hi6421_spmi_pmic_read(pmic, SOC_PMIC_IRQ0_ADDR + i); pr_debug("PMU IRQ address value:irq[0x%x] = 0x%x\n", - pmic->irq_addr + i, pending); - hi6421_spmi_pmic_write(pmic, pmic->irq_addr + i, + SOC_PMIC_IRQ0_ADDR + i, pending); + hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ0_ADDR + i, HISI_MASK_STATE); } } @@ -274,12 +240,6 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) if (!pmic) return -ENOMEM; - ret = get_pmic_device_tree_data(np, pmic); - if (ret) { - dev_err(dev, "Error reading hisi pmic dts\n"); - return ret; - } - spin_lock_init(&pmic->lock); pmic->dev = dev; @@ -301,11 +261,11 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) hi6421_spmi_pmic_irq_prc(pmic); - pmic->irqs = devm_kzalloc(dev, pmic->irqnum * sizeof(int), GFP_KERNEL); + pmic->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL); if (!pmic->irqs) goto irq_malloc; - pmic->domain = irq_domain_add_simple(np, pmic->irqnum, 0, + pmic->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0, &hi6421_spmi_domain_ops, pmic); if (!pmic->domain) { dev_err(dev, "failed irq domain add simple!\n"); @@ -313,7 +273,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev) goto irq_malloc; } - for (i = 0; i < pmic->irqnum; i++) { + for (i = 0; i < HISI_IRQ_NUM; i++) { virq = irq_create_mapping(pmic->domain, i); if (!virq) { dev_err(dev, "Failed mapping hwirq\n"); diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h index ff3adfa7b3ec..2c8896fd852e 100644 --- a/include/linux/mfd/hi6421-spmi-pmic.h +++ b/include/linux/mfd/hi6421-spmi-pmic.h @@ -17,16 +17,6 @@ #define HISI_ECO_MODE_ENABLE (1) #define HISI_ECO_MODE_DISABLE (0) -struct hi6421_spmi_irq_mask_info { - int start_addr; - int array; -}; - -struct hi6421_spmi_irq_info { - int start_addr; - int array; -}; - struct hi6421_spmi_pmic { struct resource *res; struct device *dev; @@ -36,11 +26,6 @@ struct hi6421_spmi_pmic { int irq; int gpio; unsigned int *irqs; - - int irqnum; - int irqarray; - int irq_mask_addr; - int irq_addr; }; int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg); -- cgit v1.2.3 From de1a93b6a49c366b4897fc314c71ac005f765479 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 16:58:55 +0200 Subject: staging: spmi: hisi-spmi-controller: change compatible string Add the chipset name at the compatible string, as other HiSilicon chipsets with SPMI bus might require something different. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/f34062e82b5d5ee49aab4f9055b44e42e5023f0a.1597762400.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 513d962b8bce..66a0b296e06f 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -324,7 +324,8 @@ static int spmi_del_controller(struct platform_device *pdev) } static const struct of_device_id spmi_controller_match_table[] = { - { .compatible = "hisilicon,spmi-controller", + { + .compatible = "hisilicon,kirin970-spmi-controller", }, {} }; -- cgit v1.2.3 From 9f46c3433f99f3901907c8acca29e03415bf1d76 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 16:58:56 +0200 Subject: staging: mfd: hi6421-spmi-pmic: Simplify the compatible string It is clear that this driver is for PMIC. So, get rid of it at the compatible. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/12bdc9b4734e156098408d0d27256abdc91ac283.1597762400.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c index 7817c0637737..64b30d263c8d 100644 --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c @@ -323,7 +323,7 @@ static void hi6421_spmi_pmic_remove(struct spmi_device *pdev) } static const struct of_device_id pmic_spmi_id_table[] = { - { .compatible = "hisilicon,hi6421-spmi-pmic" }, + { .compatible = "hisilicon,hi6421-spmi" }, { } }; MODULE_DEVICE_TABLE(of, pmic_spmi_id_table); -- cgit v1.2.3 From 9e591728854516b0f5623eabe1bf35ad6030aef6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 16:58:57 +0200 Subject: dt: document HiSilicon SPMI controller and mfd/regulator properties Add documentation for the properties needed by the HiSilicon 6421v600 driver, and by the SPMI controller used to access the chipset. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/56c40a260bf31edf7049f50586c63ee0d06e02cb.1597762400.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 159 +++++++++++++++++++++ .../hikey9xx/hisilicon,hisi-spmi-controller.yaml | 62 ++++++++ 2 files changed, 221 insertions(+) create mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml create mode 100644 drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml new file mode 100644 index 000000000000..c76093f320f1 --- /dev/null +++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml @@ -0,0 +1,159 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/hisilicon,hi6421-spmi-pmic.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HiSilicon 6421v600 SPMI PMIC + +maintainers: + - Mauro Carvalho Chehab + +description: | + HiSilicon 6421v600 should be connected inside a MIPI System Power Management + (SPMI) bus. It provides interrupts and power supply. + + The GPIO and interrupt settings are represented as part of the top-level PMIC + node. + + The SPMI controller part is provided by + Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml. + +properties: + $nodename: + pattern: "pmic@[0-9a-f]" + + compatible: + const: hisilicon,hi6421v600-spmi + + reg: + maxItems: 1 + + '#interrupt-cells': + const: 2 + + interrupt-controller: + description: + Identify that the PMIC is capable of behaving as an interrupt controller. + + gpios: + maxItems: 1 + + regulators: + type: object + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + '^ldo[0-9]+@[0-9a-f]$': + type: object + + $ref: "/schemas/regulator/regulator.yaml#" + + properties: + reg: + description: Enable register. + + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + vsel-reg: + description: Voltage selector register. + + enable-mask: + description: Bitmask used to enable the regulator. + + voltage-table: + description: Table with the selector items for the voltage regulator. + minItems: 2 + maxItems: 16 + + off-on-delay-us: + description: Time required for changing state to enabled in microseconds. + + startup-delay-us: + description: Startup time in microseconds. + + idle-mode-mask: + description: Bitmask used to put the regulator on idle mode. + + eco-microamp: + description: Maximum current while on idle mode. + + required: + - reg + - vsel-reg + - enable-mask + - voltage-table + - off-on-delay-us + - startup-delay-us + +required: + - compatible + - reg + - regulators + +examples: + - | + /* pmic properties */ + + pmic: pmic@0 { + compatible = "hisilicon,hi6421-spmi"; + reg = <0 0>; + + #interrupt-cells = <2>; + interrupt-controller; + gpios = <&gpio28 0 0>; + + regulators { + #address-cells = <1>; + #size-cells = <0>; + + ldo3: ldo3@16 { + reg = <0x16>; + vsel-reg = <0x51>; + + regulator-name = "ldo3"; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2000000>; + regulator-boot-on; + + enable-mask = <0x01>; + + voltage-table = <1500000>, <1550000>, <1600000>, <1650000>, + <1700000>, <1725000>, <1750000>, <1775000>, + <1800000>, <1825000>, <1850000>, <1875000>, + <1900000>, <1925000>, <1950000>, <2000000>; + off-on-delay-us = <20000>; + startup-delay-us = <120>; + }; + + ldo4: ldo4@17 { /* 40 PIN */ + reg = <0x17>; + vsel-reg = <0x52>; + + regulator-name = "ldo4"; + regulator-min-microvolt = <1725000>; + regulator-max-microvolt = <1900000>; + regulator-boot-on; + + enable-mask = <0x01>; + idle-mode-mask = <0x10>; + eco-microamp = <10000>; + + hi6421-vsel = <0x52 0x07>; + voltage-table = <1725000>, <1750000>, <1775000>, <1800000>, + <1825000>, <1850000>, <1875000>, <1900000>; + off-on-delay-us = <20000>; + startup-delay-us = <120>; + }; + }; + }; diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml new file mode 100644 index 000000000000..b1cfa9c3aca6 --- /dev/null +++ b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/spmi/hisilicon,hisi-spmi-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: HiSilicon SPMI controller + +maintainers: + - Mauro Carvalho Chehab + +description: | + The HiSilicon SPMI BUS controller is found on some Kirin-based designs. + It is a MIPI System Power Management (SPMI) controller. + + The PMIC part is provided by + Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml. + +properties: + $nodename: + pattern: "spmi@[0-9a-f]" + + compatible: + const: hisilicon,kirin970-spmi-controller + + reg: + maxItems: 1 + + spmi-channel: + description: | + number of the Kirin 970 SPMI channel where the SPMI devices are connected. + +required: + - compatible + - reg + - spmi-channel + +patternProperties: + "^pmic@[0-9a-f]$": + description: | + PMIC properties, which are specific to the used SPMI PMIC device(s). + When used in combination with HiSilicon 6421v600, the properties + are documented at + Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml. + +examples: + - | + bus { + #address-cells = <2>; + #size-cells = <2>; + + spmi: spmi@fff24000 { + compatible = "hisilicon,kirin970-spmi-controller"; + status = "ok"; + reg = <0x0 0xfff24000 0x0 0x1000>; + spmi-channel = <2>; + + pmic@0 { + /* pmic properties */ + }; + }; + }; -- cgit v1.2.3 From bc752d2f345bf55d71b3422a6a24890ea03168dc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 Aug 2020 18:04:48 +0200 Subject: staging: hikey9xx: Kconfig: add regulator dependency The regulator driver needs it, as otherwise it will produce errors when creating vmlinux. Reported-by: Greg Kroah-Hartman Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/a287238bd0141aa68aae7d4cec4c1174a43b3e53.1597766680.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index a004839e8fa9..0e97b5b9a56a 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -31,6 +31,7 @@ config MFD_HI6421_SPMI config REGULATOR_HI6421V600 tristate "HiSilicon Hi6421v600 PMIC voltage regulator support" depends on MFD_HI6421_SPMI && OF + depends on REGULATOR help This driver provides support for the voltage regulators on HiSilicon Hi6421v600 PMU / Codec IC. -- cgit v1.2.3 From e4cebcae751874f46a1cb55eb5e2c1b367de3669 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 20 Aug 2020 08:51:36 +0100 Subject: staging: spmi: hisi-spmi-controller: fix spelling mistake "controlller" -> "controller" There is a spelling mistake in the MODULE_ALIAS, fix it. Signed-off-by: Colin Ian King Reviewed-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/20200820075136.186199-1-colin.king@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 66a0b296e06f..b132b2a5d939 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -354,4 +354,4 @@ module_exit(spmi_controller_exit); MODULE_LICENSE("GPL v2"); MODULE_VERSION("1.0"); -MODULE_ALIAS("platform:spmi_controlller"); +MODULE_ALIAS("platform:spmi_controller"); -- cgit v1.2.3 From e6627a5e82f9d00b95a619aa0a3cbc5809ef1aac Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 26 Aug 2020 11:32:12 +0200 Subject: staging: hikey9xx: update references inside the yaml files The references inside those files were not assuming that they would end at the staging tree. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/809bce085b0a9a9ede74d619d160e1e04723709d.1598434228.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 2 +- drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml index c76093f320f1..80e74c261e05 100644 --- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml +++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml @@ -17,7 +17,7 @@ description: | node. The SPMI controller part is provided by - Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml. + drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml. properties: $nodename: diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml index b1cfa9c3aca6..f2a56fa4e78e 100644 --- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml +++ b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml @@ -14,7 +14,7 @@ description: | It is a MIPI System Power Management (SPMI) controller. The PMIC part is provided by - Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml. + drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml. properties: $nodename: @@ -41,7 +41,7 @@ patternProperties: PMIC properties, which are specific to the used SPMI PMIC device(s). When used in combination with HiSilicon 6421v600, the properties are documented at - Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml. + drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml. examples: - | -- cgit v1.2.3 From 4c6491a343e91a5a2a699b0b545f8ba1ec1e8c65 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Tue, 1 Sep 2020 11:57:22 +0800 Subject: staging: spmi: hisi-spmi-controller: Use proper format in call to dev_err() The correct format string for a size_t argument should be %zu. Signed-off-by: YueHaibing Reviewed-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/20200901035722.9324-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index b132b2a5d939..5ffe79f45d9a 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -121,7 +121,7 @@ static int spmi_read_cmd(struct spmi_controller *ctrl, if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, - "spmi_controller supports 1..%d bytes per trans, but:%ld requested\n", + "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n", SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } @@ -175,7 +175,7 @@ done: spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) dev_err(&ctrl->dev, - "spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%ld\n", + "spmi read wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n", opc, slave_id, slave_addr, bc + 1); else dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, read value: %*ph\n", @@ -197,7 +197,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) { dev_err(&ctrl->dev, - "spmi_controller supports 1..%d bytes per trans, but:%ld requested\n", + "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n", SPMI_CONTROLLER_MAX_TRANS_BYTES, bc); return -EINVAL; } @@ -251,7 +251,7 @@ static int spmi_write_cmd(struct spmi_controller *ctrl, spin_unlock_irqrestore(&spmi_controller->lock, flags); if (rc) - dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%ld\n", + dev_err(&ctrl->dev, "spmi write wait timeout op:0x%x slave_id:%d slave_addr:0x%x bc:%zu\n", opc, slave_id, slave_addr, bc); else dev_dbg(&ctrl->dev, "%s: id:%d slave_addr:0x%x, wrote value: %*ph\n", -- cgit v1.2.3 From 978620cc4f5577c5139da9d8377849aeac46687a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 10 Sep 2020 14:17:56 +0800 Subject: staging: regulator: hi6421v600-regulator: Remove unused including Remove including that don't need it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/20200910061756.40864-1-yuehaibing@huawei.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hi6421v600-regulator.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c index 82635ff54a74..614b03c9ddfb 100644 --- a/drivers/staging/hikey9xx/hi6421v600-regulator.c +++ b/drivers/staging/hikey9xx/hi6421v600-regulator.c @@ -36,7 +36,6 @@ #include #include #include -#include #define rdev_dbg(rdev, fmt, arg...) \ pr_debug("%s: %s: " fmt, (rdev)->desc->name, __func__, ##arg) -- cgit v1.2.3 From 8971a3b880b2fa8086ddc79d83f1fddc6238b3ee Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Thu, 17 Sep 2020 12:42:05 +0200 Subject: staging: hikey9xx: add USB physical layer for Kirin 3670 Add the Hisilicon Kirin 3670 USB phy driver. This driver was imported from Linaro's official Hikey 970 tree, from the original patch, removing the addition of the dwg3-specific parts, and getting the missing SoB from its original author: https://github.com/96boards-hikey/linux/commit/9d168f580c9977f9c7f48b228b72035e2f6e3eba#diff-93bb70bc97bdd7be752cb6722adf2124 [mchehab: moved to staging and dropped Makefile/Kconfig changes] Signed-off-by: Yu Chen Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/0e6b2fa68cabd317511637fdfdeadc574196ea90.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 682 +++++++++++++++++++++++++++ drivers/staging/hikey9xx/phy-hi3670-usb3.txt | 25 + 2 files changed, 707 insertions(+) create mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.c create mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.txt (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c new file mode 100644 index 000000000000..4e04ac97728d --- /dev/null +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -0,0 +1,682 @@ +/* + * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform + * + * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * http://www.huawei.com + * + * Authors: Yu Chen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 of + * the License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define SCTRL_SCDEEPSLEEPED (0x0) +#define USB_CLK_SELECTED BIT(20) + +#define PERI_CRG_PEREN0 (0x00) +#define PERI_CRG_PERDIS0 (0x04) +#define PERI_CRG_PEREN4 (0x40) +#define PERI_CRG_PERDIS4 (0x44) +#define PERI_CRG_PERRSTEN4 (0x90) +#define PERI_CRG_PERRSTDIS4 (0x94) +#define PERI_CRG_ISODIS (0x148) +#define PERI_CRG_PEREN6 (0x410) +#define PERI_CRG_PERDIS6 (0x414) + +#define USB_REFCLK_ISO_EN BIT(25) + +#define GT_CLK_USB2PHY_REF BIT(19) + +#define PCTRL_PERI_CTRL3 (0x10) +#define PCTRL_PERI_CTRL3_MSK_START (16) +#define USB_TCXO_EN BIT(1) + +#define PCTRL_PERI_CTRL24 (0x64) +#define SC_CLK_USB3PHY_3MUX1_SEL BIT(25) + +#define USB3OTG_CTRL0 (0x00) +#define USB3OTG_CTRL3 (0x0C) +#define USB3OTG_CTRL4 (0x10) +#define USB3OTG_CTRL5 (0x14) +#define USB3OTG_CTRL7 (0x1C) +#define USB_MISC_CFG50 (0x50) +#define USB_MISC_CFG54 (0x54) +#define USB_MISC_CFG58 (0x58) +#define USB_MISC_CFG5C (0x5C) +#define USB_MISC_CFGA0 (0xA0) +#define TCA_CLK_RST (0x200) +#define TCA_INTR_EN (0x204) +#define TCA_INTR_STS (0x208) +#define TCA_GCFG (0x210) +#define TCA_TCPC (0x214) +#define TCA_VBUS_CTRL (0x240) + +#define CTRL0_USB3_VBUSVLD BIT(7) +#define CTRL0_USB3_VBUSVLD_SEL BIT(6) + +#define CTRL3_USB2_VBUSVLDEXT0 BIT(6) +#define CTRL3_USB2_VBUSVLDEXTSEL0 BIT(5) + +#define CTRL5_USB2_SIDDQ BIT(0) + +#define CTRL7_USB2_REFCLKSEL_MASK (3 << 3) +#define CTRL7_USB2_REFCLKSEL_ABB (3 << 3) +#define CTRL7_USB2_REFCLKSEL_PAD (2 << 3) + +#define CFG50_USB3_PHY_TEST_POWERDOWN BIT(23) + +#define CFG54_USB31PHY_CR_ADDR_MASK (0xFFFF) +#define CFG54_USB31PHY_CR_ADDR_SHIFT (16) +#define CFG54_USB3PHY_REF_USE_PAD BIT(12) +#define CFG54_PHY0_PMA_PWR_STABLE BIT(11) +#define CFG54_PHY0_PCS_PWR_STABLE BIT(9) +#define CFG54_USB31PHY_CR_ACK BIT(7) +#define CFG54_USB31PHY_CR_WR_EN BIT(5) +#define CFG54_USB31PHY_CR_SEL BIT(4) +#define CFG54_USB31PHY_CR_RD_EN BIT(3) +#define CFG54_USB31PHY_CR_CLK BIT(2) +#define CFG54_USB3_PHY0_ANA_PWR_EN BIT(1) + +#define CFG58_USB31PHY_CR_DATA_MASK (0xFFFF) +#define CFG58_USB31PHY_CR_DATA_RD_START (16) + +#define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN BIT(1) + +#define CFGA0_VAUX_RESET BIT(9) +#define CFGA0_USB31C_RESET BIT(8) +#define CFGA0_USB2PHY_REFCLK_SELECT BIT(4) +#define CFGA0_USB3PHY_RESET BIT(1) +#define CFGA0_USB2PHY_POR BIT(0) + +#define INTR_EN_XA_TIMEOUT_EVT_EN BIT(1) +#define INTR_EN_XA_ACK_EVT_EN BIT(0) + +#define CLK_RST_TCA_REF_CLK_EN BIT(1) +#define CLK_RST_SUSPEND_CLK_EN BIT(0) + +#define GCFG_ROLE_HSTDEV BIT(4) + +#define TCPC_VALID BIT(4) +#define TCPC_LOW_POWER_EN BIT(3) +#define TCPC_MUX_CONTROL_MASK (3 << 0) +#define TCPC_MUX_CONTROL_USB31 (1 << 0) + +#define VBUS_CTRL_POWERPRESENT_OVERRD (3 << 2) +#define VBUS_CTRL_VBUSVALID_OVERRD (3 << 0) + +#define KIRIN970_USB_DEFAULT_PHY_PARAM (0xFDFEE4) +#define KIRIN970_USB_DEFAULT_PHY_VBOOST (0x5) + +#define TX_VBOOST_LVL_REG (0xf) +#define TX_VBOOST_LVL_START (6) +#define TX_VBOOST_LVL_ENABLE BIT(9) + +struct kirin970_priv { + struct device *dev; + struct regmap *peri_crg; + struct regmap *pctrl; + struct regmap *sctrl; + struct regmap *usb31misc; + + u32 eye_diagram_param; + u32 tx_vboost_lvl; + + u32 peri_crg_offset; + u32 pctrl_offset; + u32 usb31misc_offset; +}; + +static int kirin970_phy_cr_clk(struct regmap *usb31misc) +{ + int ret; + + /* Clock up */ + ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK); + if (ret) + return ret; + + /* Clock down */ + ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_CLK, 0); + + return ret; +} + +static int kirin970_phy_cr_set_sel(struct regmap *usb31misc) +{ + return regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL); +} + +static int kirin970_phy_cr_start(struct regmap *usb31misc, int direction) +{ + int ret; + + if (direction) + ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_WR_EN, CFG54_USB31PHY_CR_WR_EN); + else + ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_RD_EN, CFG54_USB31PHY_CR_RD_EN); + + if (ret) + return ret; + + ret = kirin970_phy_cr_clk(usb31misc); + if (ret) + return ret; + + ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, + CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0); + + return ret; +} + +static int kirin970_phy_cr_wait_ack(struct regmap *usb31misc) +{ + u32 reg; + int retry = 100000; + int ret; + + while (retry-- > 0) { + ret = regmap_read(usb31misc, USB_MISC_CFG54, ®); + if (ret) + return ret; + if ((reg & CFG54_USB31PHY_CR_ACK) == CFG54_USB31PHY_CR_ACK) + return 0; + + ret = kirin970_phy_cr_clk(usb31misc); + if (ret) + return ret; + } + + return -ETIMEDOUT; +} + +static int kirin970_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) +{ + u32 reg; + int ret; + + ret = regmap_read(usb31misc, USB_MISC_CFG54, ®); + if (ret) + return ret; + + reg &= ~(CFG54_USB31PHY_CR_ADDR_MASK << CFG54_USB31PHY_CR_ADDR_SHIFT); + reg |= ((addr & CFG54_USB31PHY_CR_ADDR_MASK) << + CFG54_USB31PHY_CR_ADDR_SHIFT); + ret = regmap_write(usb31misc, USB_MISC_CFG54, reg); + + return ret; +} + +static int kirin970_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) +{ + int reg; + int i; + int ret; + + for (i = 0; i < 100; i++) { + ret = kirin970_phy_cr_clk(usb31misc); + if (ret) + return ret; + } + + ret = kirin970_phy_cr_set_sel(usb31misc); + if (ret) + return ret; + + ret = kirin970_phy_cr_set_addr(usb31misc, addr); + if (ret) + return ret; + + ret = kirin970_phy_cr_start(usb31misc, 0); + if (ret) + return ret; + + ret = kirin970_phy_cr_wait_ack(usb31misc); + if (ret) + return ret; + + ret = regmap_read(usb31misc, USB_MISC_CFG58, ®); + if (ret) + return ret; + + *val = (reg >> CFG58_USB31PHY_CR_DATA_RD_START) & + CFG58_USB31PHY_CR_DATA_MASK; + + return 0; +} + +static int kirin970_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) +{ + int i; + int ret; + + for (i = 0; i < 100; i++) { + ret = kirin970_phy_cr_clk(usb31misc); + if (ret) + return ret; + } + + ret = kirin970_phy_cr_set_sel(usb31misc); + if (ret) + return ret; + + ret = kirin970_phy_cr_set_addr(usb31misc, addr); + if (ret) + return ret; + + ret = regmap_write(usb31misc, USB_MISC_CFG58, + val & CFG58_USB31PHY_CR_DATA_MASK); + if (ret) + return ret; + + ret = kirin970_phy_cr_start(usb31misc, 1); + if (ret) + return ret; + + ret = kirin970_phy_cr_wait_ack(usb31misc); + + return ret; +} + +static int kirin970_phy_set_params(struct kirin970_priv *priv) +{ + u32 reg; + int ret; + int retry = 3; + + ret = regmap_write(priv->usb31misc, USB3OTG_CTRL4, + priv->eye_diagram_param); + if (ret) { + dev_err(priv->dev, "set USB3OTG_CTRL4 failed\n"); + return ret; + } + + while (retry-- > 0) { + ret = kirin970_phy_cr_read(priv->usb31misc, + TX_VBOOST_LVL_REG, ®); + if (!ret) + break; + else if (ret != -ETIMEDOUT) { + dev_err(priv->dev, "read TX_VBOOST_LVL_REG failed\n"); + return ret; + } + } + if (ret) + return ret; + + reg |= (TX_VBOOST_LVL_ENABLE | + (priv->tx_vboost_lvl << TX_VBOOST_LVL_START)); + ret = kirin970_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg); + if (ret) + dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n"); + + return ret; +} + +static int kirin970_is_abbclk_seleted(struct kirin970_priv *priv) +{ + u32 reg; + + if (!priv->sctrl) { + dev_err(priv->dev, "priv->sctrl is null!\n"); + return 1; + } + + if (regmap_read(priv->sctrl, SCTRL_SCDEEPSLEEPED, ®)) { + dev_err(priv->dev, "SCTRL_SCDEEPSLEEPED read failed!\n"); + return 1; + } + + if ((reg & USB_CLK_SELECTED) == 0) + return 1; + + return 0; +} + +static int kirin970_config_phy_clock(struct kirin970_priv *priv) +{ + u32 val, mask; + int ret; + + if (kirin970_is_abbclk_seleted(priv)) { + /* usb refclk iso disable */ + ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, + USB_REFCLK_ISO_EN); + if (ret) + goto out; + + /* select usbphy clk from abb */ + mask = SC_CLK_USB3PHY_3MUX1_SEL; + ret = regmap_update_bits(priv->pctrl, + PCTRL_PERI_CTRL24, mask, 0); + if (ret) + goto out; + + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, + CFGA0_USB2PHY_REFCLK_SELECT, 0); + if (ret) + goto out; + + ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val); + if (ret) + goto out; + val &= ~CTRL7_USB2_REFCLKSEL_MASK; + val |= CTRL7_USB2_REFCLKSEL_ABB; + ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val); + if (ret) + goto out; + } else { + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54, + CFG54_USB3PHY_REF_USE_PAD, + CFG54_USB3PHY_REF_USE_PAD); + if (ret) + goto out; + + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, + CFGA0_USB2PHY_REFCLK_SELECT, + CFGA0_USB2PHY_REFCLK_SELECT); + if (ret) + goto out; + + ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val); + if (ret) + goto out; + val &= ~CTRL7_USB2_REFCLKSEL_MASK; + val |= CTRL7_USB2_REFCLKSEL_PAD; + ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val); + if (ret) + goto out; + + ret = regmap_write(priv->peri_crg, + PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF); + if (ret) + goto out; + } + + return 0; +out: + dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret); + return ret; +} + +static int kirin970_config_tca(struct kirin970_priv *priv) +{ + u32 val, mask; + int ret; + + ret = regmap_write(priv->usb31misc, TCA_INTR_STS, 0xffff); + if (ret) + goto out; + + ret = regmap_write(priv->usb31misc, TCA_INTR_EN, + INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN); + if (ret) + goto out; + + mask = CLK_RST_TCA_REF_CLK_EN | CLK_RST_SUSPEND_CLK_EN; + ret = regmap_update_bits(priv->usb31misc, TCA_CLK_RST, mask, 0); + if (ret) + goto out; + + ret = regmap_update_bits(priv->usb31misc, TCA_GCFG, + GCFG_ROLE_HSTDEV, GCFG_ROLE_HSTDEV); + if (ret) + goto out; + + ret = regmap_read(priv->usb31misc, TCA_TCPC, &val); + if (ret) + goto out; + val &= ~(TCPC_VALID | TCPC_LOW_POWER_EN | TCPC_MUX_CONTROL_MASK); + val |= (TCPC_VALID | TCPC_MUX_CONTROL_USB31); + ret = regmap_write(priv->usb31misc, TCA_TCPC, val); + if (ret) + goto out; + + ret = regmap_write(priv->usb31misc, TCA_VBUS_CTRL, + VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD); + if (ret) + goto out; + + return 0; +out: + dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret); + return ret; +} + +static int kirin970_phy_exit(struct phy *phy); + +static int kirin970_phy_init(struct phy *phy) +{ + struct kirin970_priv *priv = phy_get_drvdata(phy); + u32 val; + int ret; + + kirin970_phy_exit(phy); + dev_info(priv->dev, "%s in\n", __func__); + /* assert controller */ + val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0); + if (ret) + goto out; + + ret = kirin970_config_phy_clock(priv); + if (ret) + goto out; + + /* Exit from IDDQ mode */ + ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL5, + CTRL5_USB2_SIDDQ, 0); + if (ret) + goto out; + + /* Release USB31 PHY out of TestPowerDown mode */ + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG50, + CFG50_USB3_PHY_TEST_POWERDOWN, 0); + if (ret) + goto out; + + /* Tell the PHY power is stable */ + val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE | + CFG54_PHY0_PMA_PWR_STABLE; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54, + val, val); + if (ret) + goto out; + + ret = kirin970_config_tca(priv); + if (ret) + goto out; + + /* Enable SSC */ + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG5C, + CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN, + CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN); + if (ret) + goto out; + + /* Deassert phy */ + val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val); + if (ret) + goto out; + + udelay(100); + + /* Deassert controller */ + val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val); + if (ret) + goto out; + + udelay(100); + + /* Set fake vbus valid signal */ + val = CTRL0_USB3_VBUSVLD | CTRL0_USB3_VBUSVLD_SEL; + ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL0, val, val); + if (ret) + goto out; + + val = CTRL3_USB2_VBUSVLDEXT0 | CTRL3_USB2_VBUSVLDEXTSEL0; + ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL3, val, val); + if (ret) + goto out; + + udelay(100); + + ret = kirin970_phy_set_params(priv); + if (ret) + goto out; + + { + ret = regmap_read(priv->peri_crg, 0x4c, + &val); + if (!ret) + dev_info(priv->dev, "peri_crg 0x4c %x\n", val); + ret = regmap_read(priv->peri_crg, 0x404, + &val); + if (!ret) + dev_info(priv->dev, "peri_crg 0x404 %x\n", val); + ret = regmap_read(priv->peri_crg, 0xc, + &val); + if (!ret) + dev_info(priv->dev, "peri_crg 0xc %x\n", val); + ret = regmap_read(priv->peri_crg, 0xac, + &val); + if (!ret) + dev_info(priv->dev, "peri_crg 0xac %x\n", val); + ret = regmap_read(priv->pctrl, 0x10, + &val); + if (!ret) + dev_info(priv->dev, "pctrl 0x10 %x\n", val); + } + + return 0; +out: + dev_err(priv->dev, "failed to init phy ret: %d\n", ret); + return ret; +} + +static int kirin970_phy_exit(struct phy *phy) +{ + struct kirin970_priv *priv = phy_get_drvdata(phy); + u32 mask; + int ret; + + /* Assert phy */ + mask = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, mask, 0); + if (ret) + goto out; + + if (!kirin970_is_abbclk_seleted(priv)) { + ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6, + GT_CLK_USB2PHY_REF); + if (ret) + goto out; + } + + return 0; +out: + dev_err(priv->dev, "failed to exit phy ret: %d\n", ret); + return ret; +} + +static struct phy_ops kirin970_phy_ops = { + .init = kirin970_phy_init, + .exit = kirin970_phy_exit, + .owner = THIS_MODULE, +}; + +static int kirin970_phy_probe(struct platform_device *pdev) +{ + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *phy; + struct kirin970_priv *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node, + "hisilicon,pericrg-syscon"); + if (IS_ERR(priv->peri_crg)) { + dev_err(dev, "no hisilicon,pericrg-syscon\n"); + return PTR_ERR(priv->peri_crg); + } + + priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node, + "hisilicon,pctrl-syscon"); + if (IS_ERR(priv->pctrl)) { + dev_err(dev, "no hisilicon,pctrl-syscon\n"); + return PTR_ERR(priv->pctrl); + } + + priv->sctrl = syscon_regmap_lookup_by_phandle(dev->of_node, + "hisilicon,sctrl-syscon"); + if (IS_ERR(priv->sctrl)) { + dev_err(dev, "no hisilicon,sctrl-syscon\n"); + return PTR_ERR(priv->sctrl); + } + + priv->usb31misc = syscon_regmap_lookup_by_phandle(dev->of_node, + "hisilicon,usb31-misc-syscon"); + if (IS_ERR(priv->usb31misc)) { + dev_err(dev, "no hisilicon,usb31-misc-syscon\n"); + return PTR_ERR(priv->usb31misc); + } + + if (of_property_read_u32(dev->of_node, "eye-diagram-param", + &(priv->eye_diagram_param))) + priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM; + + if (of_property_read_u32(dev->of_node, "usb3-phy-tx-vboost-lvl", + &(priv->tx_vboost_lvl))) + priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_VBOOST; + + phy = devm_phy_create(dev, NULL, &kirin970_phy_ops); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + phy_set_drvdata(phy, priv); + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id kirin970_phy_of_match[] = { + {.compatible = "hisilicon,kirin970-usb-phy",}, + { }, +}; +MODULE_DEVICE_TABLE(of, kirin970_phy_of_match); + +static struct platform_driver kirin970_phy_driver = { + .probe = kirin970_phy_probe, + .driver = { + .name = "kirin970-usb-phy", + .of_match_table = kirin970_phy_of_match, + } +}; +module_platform_driver(kirin970_phy_driver); + +MODULE_AUTHOR("Yu Chen "); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Hilisicon Kirin970 USB31 PHY Driver"); diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.txt b/drivers/staging/hikey9xx/phy-hi3670-usb3.txt new file mode 100644 index 000000000000..4cb02612ff23 --- /dev/null +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.txt @@ -0,0 +1,25 @@ +Hisilicon Kirin970 usb PHY +----------------------- + +Required properties: +- compatible: should be "hisilicon,kirin970-usb-phy" +- #phy-cells: must be 0 +- hisilicon,pericrg-syscon: phandle of syscon used to control phy. +- hisilicon,pctrl-syscon: phandle of syscon used to control phy. +- hisilicon,sctrl-syscon: phandle of syscon used to control phy. +- hisilicon,usb31-misc-syscon: phandle of syscon used to control phy. +- eye-diagram-param: parameter set for phy +- usb3-phy-tx-vboost-lvl: parameter set for phy +Refer to phy/phy-bindings.txt for the generic PHY binding properties + +Example: + usb_phy: usbphy { + compatible = "hisilicon,kirin970-usb-phy"; + #phy-cells = <0>; + hisilicon,pericrg-syscon = <&crg_ctrl>; + hisilicon,pctrl-syscon = <&pctrl>; + hisilicon,sctrl-syscon = <&sctrl>; + hisilicon,usb31-misc-syscon = <&usb31_misc>; + eye-diagram-param = <0xFDFEE4>; + usb3-phy-tx-vboost-lvl = <0x5>; + }; -- cgit v1.2.3 From 2a0dc2c368fccc9d69bf72ce389065939187af23 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:06 +0200 Subject: staging: hikey9xx: add build for the Kirin 970 PHY driver Add the needed bits in order to build the Kirin 970 PHY driver. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/60aae73e91348430e940638cf9668a0a63a85c1c.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/Kconfig | 11 +++++++++++ drivers/staging/hikey9xx/Makefile | 2 ++ 2 files changed, 13 insertions(+) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig index 0e97b5b9a56a..b29f5d5df134 100644 --- a/drivers/staging/hikey9xx/Kconfig +++ b/drivers/staging/hikey9xx/Kconfig @@ -1,5 +1,16 @@ # SPDX-License-Identifier: GPL-2.0 +# to be placed at drivers/phy +config PHY_HI3670_USB + tristate "hi3670 USB PHY support" + depends on (ARCH_HISI && ARM64) || COMPILE_TEST + select GENERIC_PHY + select MFD_SYSCON + help + Enable this to support the HISILICON HI3670 USB PHY. + + To compile this driver as a module, choose M here. + # to be placed at drivers/spmi config SPMI_HISI3670 tristate "Hisilicon 3670 SPMI Controller" diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile index 9371dcc3d35b..1924fadac952 100644 --- a/drivers/staging/hikey9xx/Makefile +++ b/drivers/staging/hikey9xx/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_PHY_HI3670_USB) += phy-hi3670-usb3.o + obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o -- cgit v1.2.3 From b9e1814a915174edd6f55db7c7d029d76703466a Mon Sep 17 00:00:00 2001 From: Yu Chen Date: Thu, 17 Sep 2020 12:42:07 +0200 Subject: staging: hikey9xx: phy-hi3670-usb3: fix some issues at the init code There are some problems at the initialization part of this phy. Solve them. Signed-off-by: Yu Chen Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5080774c68784afed1183cb54f540350e0551b07.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 70 ++++++++++++++---------------- 1 file changed, 32 insertions(+), 38 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c index 4e04ac97728d..1d4caf7a2aaf 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -63,6 +63,7 @@ #define TCA_INTR_STS (0x208) #define TCA_GCFG (0x210) #define TCA_TCPC (0x214) +#define TCA_SYSMODE_CFG (0x218) #define TCA_VBUS_CTRL (0x240) #define CTRL0_USB3_VBUSVLD BIT(7) @@ -109,12 +110,16 @@ #define CLK_RST_SUSPEND_CLK_EN BIT(0) #define GCFG_ROLE_HSTDEV BIT(4) +#define GCFG_OP_MODE (3 << 0) +#define GCFG_OP_MODE_CTRL_SYNC_MODE BIT(0) #define TCPC_VALID BIT(4) #define TCPC_LOW_POWER_EN BIT(3) #define TCPC_MUX_CONTROL_MASK (3 << 0) #define TCPC_MUX_CONTROL_USB31 (1 << 0) +#define SYSMODE_CFG_TYPEC_DISABLE BIT(3) + #define VBUS_CTRL_POWERPRESENT_OVERRD (3 << 2) #define VBUS_CTRL_VBUSVALID_OVERRD (3 << 0) @@ -363,6 +368,11 @@ static int kirin970_config_phy_clock(struct kirin970_priv *priv) if (ret) goto out; + /* enable usb_tcxo_en */ + ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, + USB_TCXO_EN | + (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START)); + /* select usbphy clk from abb */ mask = SC_CLK_USB3PHY_3MUX1_SEL; ret = regmap_update_bits(priv->pctrl, @@ -437,7 +447,13 @@ static int kirin970_config_tca(struct kirin970_priv *priv) goto out; ret = regmap_update_bits(priv->usb31misc, TCA_GCFG, - GCFG_ROLE_HSTDEV, GCFG_ROLE_HSTDEV); + GCFG_ROLE_HSTDEV | GCFG_OP_MODE, + GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE); + if (ret) + goto out; + + ret = regmap_update_bits(priv->usb31misc, TCA_SYSMODE_CFG, + SYSMODE_CFG_TYPEC_DISABLE, 0); if (ret) goto out; @@ -461,18 +477,15 @@ out: return ret; } -static int kirin970_phy_exit(struct phy *phy); - static int kirin970_phy_init(struct phy *phy) { struct kirin970_priv *priv = phy_get_drvdata(phy); u32 val; int ret; - kirin970_phy_exit(phy); - dev_info(priv->dev, "%s in\n", __func__); /* assert controller */ - val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET; + val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET | + CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0); if (ret) goto out; @@ -493,6 +506,14 @@ static int kirin970_phy_init(struct phy *phy) if (ret) goto out; + /* Deassert phy */ + val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val); + if (ret) + goto out; + + udelay(100); + /* Tell the PHY power is stable */ val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE | CFG54_PHY0_PMA_PWR_STABLE; @@ -512,14 +533,6 @@ static int kirin970_phy_init(struct phy *phy) if (ret) goto out; - /* Deassert phy */ - val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; - ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val); - if (ret) - goto out; - - udelay(100); - /* Deassert controller */ val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET; ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val); @@ -545,29 +558,6 @@ static int kirin970_phy_init(struct phy *phy) if (ret) goto out; - { - ret = regmap_read(priv->peri_crg, 0x4c, - &val); - if (!ret) - dev_info(priv->dev, "peri_crg 0x4c %x\n", val); - ret = regmap_read(priv->peri_crg, 0x404, - &val); - if (!ret) - dev_info(priv->dev, "peri_crg 0x404 %x\n", val); - ret = regmap_read(priv->peri_crg, 0xc, - &val); - if (!ret) - dev_info(priv->dev, "peri_crg 0xc %x\n", val); - ret = regmap_read(priv->peri_crg, 0xac, - &val); - if (!ret) - dev_info(priv->dev, "peri_crg 0xac %x\n", val); - ret = regmap_read(priv->pctrl, 0x10, - &val); - if (!ret) - dev_info(priv->dev, "pctrl 0x10 %x\n", val); - } - return 0; out: dev_err(priv->dev, "failed to init phy ret: %d\n", ret); @@ -586,7 +576,11 @@ static int kirin970_phy_exit(struct phy *phy) if (ret) goto out; - if (!kirin970_is_abbclk_seleted(priv)) { + if (kirin970_is_abbclk_seleted(priv)) { + /* disable usb_tcxo_en */ + ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, + USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START); + } else { ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6, GT_CLK_USB2PHY_REF); if (ret) -- cgit v1.2.3 From 521703d6e38225049271a7e46d3c88f3f436d701 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:08 +0200 Subject: staging: hikey9xx: phy-hi3670-usb3: use a consistent namespace Rename hikey970 to hi3670, in order to use a namespace similar to hi3660 driver. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/0a2b7d1d1779551be604532a9959237fd3513971.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 98 +++++++++++++++--------------- 1 file changed, 49 insertions(+), 49 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c index 1d4caf7a2aaf..fd679b39185a 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -130,7 +130,7 @@ #define TX_VBOOST_LVL_START (6) #define TX_VBOOST_LVL_ENABLE BIT(9) -struct kirin970_priv { +struct hi3670_priv { struct device *dev; struct regmap *peri_crg; struct regmap *pctrl; @@ -145,7 +145,7 @@ struct kirin970_priv { u32 usb31misc_offset; }; -static int kirin970_phy_cr_clk(struct regmap *usb31misc) +static int hi3670_phy_cr_clk(struct regmap *usb31misc) { int ret; @@ -162,13 +162,13 @@ static int kirin970_phy_cr_clk(struct regmap *usb31misc) return ret; } -static int kirin970_phy_cr_set_sel(struct regmap *usb31misc) +static int hi3670_phy_cr_set_sel(struct regmap *usb31misc) { return regmap_update_bits(usb31misc, USB_MISC_CFG54, CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL); } -static int kirin970_phy_cr_start(struct regmap *usb31misc, int direction) +static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction) { int ret; @@ -182,7 +182,7 @@ static int kirin970_phy_cr_start(struct regmap *usb31misc, int direction) if (ret) return ret; - ret = kirin970_phy_cr_clk(usb31misc); + ret = hi3670_phy_cr_clk(usb31misc); if (ret) return ret; @@ -192,7 +192,7 @@ static int kirin970_phy_cr_start(struct regmap *usb31misc, int direction) return ret; } -static int kirin970_phy_cr_wait_ack(struct regmap *usb31misc) +static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc) { u32 reg; int retry = 100000; @@ -205,7 +205,7 @@ static int kirin970_phy_cr_wait_ack(struct regmap *usb31misc) if ((reg & CFG54_USB31PHY_CR_ACK) == CFG54_USB31PHY_CR_ACK) return 0; - ret = kirin970_phy_cr_clk(usb31misc); + ret = hi3670_phy_cr_clk(usb31misc); if (ret) return ret; } @@ -213,7 +213,7 @@ static int kirin970_phy_cr_wait_ack(struct regmap *usb31misc) return -ETIMEDOUT; } -static int kirin970_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) +static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) { u32 reg; int ret; @@ -230,31 +230,31 @@ static int kirin970_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) return ret; } -static int kirin970_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) +static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) { int reg; int i; int ret; for (i = 0; i < 100; i++) { - ret = kirin970_phy_cr_clk(usb31misc); + ret = hi3670_phy_cr_clk(usb31misc); if (ret) return ret; } - ret = kirin970_phy_cr_set_sel(usb31misc); + ret = hi3670_phy_cr_set_sel(usb31misc); if (ret) return ret; - ret = kirin970_phy_cr_set_addr(usb31misc, addr); + ret = hi3670_phy_cr_set_addr(usb31misc, addr); if (ret) return ret; - ret = kirin970_phy_cr_start(usb31misc, 0); + ret = hi3670_phy_cr_start(usb31misc, 0); if (ret) return ret; - ret = kirin970_phy_cr_wait_ack(usb31misc); + ret = hi3670_phy_cr_wait_ack(usb31misc); if (ret) return ret; @@ -268,22 +268,22 @@ static int kirin970_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val) return 0; } -static int kirin970_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) +static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) { int i; int ret; for (i = 0; i < 100; i++) { - ret = kirin970_phy_cr_clk(usb31misc); + ret = hi3670_phy_cr_clk(usb31misc); if (ret) return ret; } - ret = kirin970_phy_cr_set_sel(usb31misc); + ret = hi3670_phy_cr_set_sel(usb31misc); if (ret) return ret; - ret = kirin970_phy_cr_set_addr(usb31misc, addr); + ret = hi3670_phy_cr_set_addr(usb31misc, addr); if (ret) return ret; @@ -292,16 +292,16 @@ static int kirin970_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) if (ret) return ret; - ret = kirin970_phy_cr_start(usb31misc, 1); + ret = hi3670_phy_cr_start(usb31misc, 1); if (ret) return ret; - ret = kirin970_phy_cr_wait_ack(usb31misc); + ret = hi3670_phy_cr_wait_ack(usb31misc); return ret; } -static int kirin970_phy_set_params(struct kirin970_priv *priv) +static int hi3670_phy_set_params(struct hi3670_priv *priv) { u32 reg; int ret; @@ -315,7 +315,7 @@ static int kirin970_phy_set_params(struct kirin970_priv *priv) } while (retry-- > 0) { - ret = kirin970_phy_cr_read(priv->usb31misc, + ret = hi3670_phy_cr_read(priv->usb31misc, TX_VBOOST_LVL_REG, ®); if (!ret) break; @@ -329,14 +329,14 @@ static int kirin970_phy_set_params(struct kirin970_priv *priv) reg |= (TX_VBOOST_LVL_ENABLE | (priv->tx_vboost_lvl << TX_VBOOST_LVL_START)); - ret = kirin970_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg); + ret = hi3670_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg); if (ret) dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n"); return ret; } -static int kirin970_is_abbclk_seleted(struct kirin970_priv *priv) +static int hi3670_is_abbclk_seleted(struct hi3670_priv *priv) { u32 reg; @@ -356,12 +356,12 @@ static int kirin970_is_abbclk_seleted(struct kirin970_priv *priv) return 0; } -static int kirin970_config_phy_clock(struct kirin970_priv *priv) +static int hi3670_config_phy_clock(struct hi3670_priv *priv) { u32 val, mask; int ret; - if (kirin970_is_abbclk_seleted(priv)) { + if (hi3670_is_abbclk_seleted(priv)) { /* usb refclk iso disable */ ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, USB_REFCLK_ISO_EN); @@ -427,7 +427,7 @@ out: return ret; } -static int kirin970_config_tca(struct kirin970_priv *priv) +static int hi3670_config_tca(struct hi3670_priv *priv) { u32 val, mask; int ret; @@ -477,9 +477,9 @@ out: return ret; } -static int kirin970_phy_init(struct phy *phy) +static int hi3670_phy_init(struct phy *phy) { - struct kirin970_priv *priv = phy_get_drvdata(phy); + struct hi3670_priv *priv = phy_get_drvdata(phy); u32 val; int ret; @@ -490,7 +490,7 @@ static int kirin970_phy_init(struct phy *phy) if (ret) goto out; - ret = kirin970_config_phy_clock(priv); + ret = hi3670_config_phy_clock(priv); if (ret) goto out; @@ -522,7 +522,7 @@ static int kirin970_phy_init(struct phy *phy) if (ret) goto out; - ret = kirin970_config_tca(priv); + ret = hi3670_config_tca(priv); if (ret) goto out; @@ -554,7 +554,7 @@ static int kirin970_phy_init(struct phy *phy) udelay(100); - ret = kirin970_phy_set_params(priv); + ret = hi3670_phy_set_params(priv); if (ret) goto out; @@ -564,9 +564,9 @@ out: return ret; } -static int kirin970_phy_exit(struct phy *phy) +static int hi3670_phy_exit(struct phy *phy) { - struct kirin970_priv *priv = phy_get_drvdata(phy); + struct hi3670_priv *priv = phy_get_drvdata(phy); u32 mask; int ret; @@ -576,7 +576,7 @@ static int kirin970_phy_exit(struct phy *phy) if (ret) goto out; - if (kirin970_is_abbclk_seleted(priv)) { + if (hi3670_is_abbclk_seleted(priv)) { /* disable usb_tcxo_en */ ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START); @@ -593,18 +593,18 @@ out: return ret; } -static struct phy_ops kirin970_phy_ops = { - .init = kirin970_phy_init, - .exit = kirin970_phy_exit, +static struct phy_ops hi3670_phy_ops = { + .init = hi3670_phy_init, + .exit = hi3670_phy_exit, .owner = THIS_MODULE, }; -static int kirin970_phy_probe(struct platform_device *pdev) +static int hi3670_phy_probe(struct platform_device *pdev) { struct phy_provider *phy_provider; struct device *dev = &pdev->dev; struct phy *phy; - struct kirin970_priv *priv; + struct hi3670_priv *priv; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -647,7 +647,7 @@ static int kirin970_phy_probe(struct platform_device *pdev) &(priv->tx_vboost_lvl))) priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_VBOOST; - phy = devm_phy_create(dev, NULL, &kirin970_phy_ops); + phy = devm_phy_create(dev, NULL, &hi3670_phy_ops); if (IS_ERR(phy)) return PTR_ERR(phy); @@ -656,20 +656,20 @@ static int kirin970_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } -static const struct of_device_id kirin970_phy_of_match[] = { - {.compatible = "hisilicon,kirin970-usb-phy",}, +static const struct of_device_id hi3670_phy_of_match[] = { + {.compatible = "hisilicon,hi3670-usb-phy",}, { }, }; -MODULE_DEVICE_TABLE(of, kirin970_phy_of_match); +MODULE_DEVICE_TABLE(of, hi3670_phy_of_match); -static struct platform_driver kirin970_phy_driver = { - .probe = kirin970_phy_probe, +static struct platform_driver hi3670_phy_driver = { + .probe = hi3670_phy_probe, .driver = { - .name = "kirin970-usb-phy", - .of_match_table = kirin970_phy_of_match, + .name = "hi3670-usb-phy", + .of_match_table = hi3670_phy_of_match, } }; -module_platform_driver(kirin970_phy_driver); +module_platform_driver(hi3670_phy_driver); MODULE_AUTHOR("Yu Chen "); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From cf58bf42da0a015b312a239891faf34ff4106ed3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:09 +0200 Subject: staging: hikey9xx: phy-hi3670-usb3.txt: use a consistent namespace While this driver is not used yet, use a more consistent namespace, similar to the PHY layer for Kirin 960 (hi3660). Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/49c2f648516e62d75d339edf42a029bac138e6c0.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.txt b/drivers/staging/hikey9xx/phy-hi3670-usb3.txt index 4cb02612ff23..2fb27cb8beaf 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.txt +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.txt @@ -2,7 +2,7 @@ Hisilicon Kirin970 usb PHY ----------------------- Required properties: -- compatible: should be "hisilicon,kirin970-usb-phy" +- compatible: should be "hisilicon,hi3670-usb-phy" - #phy-cells: must be 0 - hisilicon,pericrg-syscon: phandle of syscon used to control phy. - hisilicon,pctrl-syscon: phandle of syscon used to control phy. @@ -14,7 +14,7 @@ Refer to phy/phy-bindings.txt for the generic PHY binding properties Example: usb_phy: usbphy { - compatible = "hisilicon,kirin970-usb-phy"; + compatible = "hisilicon,hi3670-usb-phy"; #phy-cells = <0>; hisilicon,pericrg-syscon = <&crg_ctrl>; hisilicon,pctrl-syscon = <&pctrl>; -- cgit v1.2.3 From 8c2a794c8774eddbea00ae22e1a75ae4c7491024 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:10 +0200 Subject: staging: hikey9xx: phy-hi3670-usb3: fix coding style Address the issues reported by checkpatch --strict, and add a SPDX tag. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/6b1f66068905b7d0a9a988c9d0bd4ebef19a6fc2.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 155 ++++++++++++++--------------- 1 file changed, 75 insertions(+), 80 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c index fd679b39185a..cb0bfcbbfbfa 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -1,28 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform * - * Copyright (C) 2017-2018 Hilisicon Electronics Co., Ltd. + * Copyright (C) 2017-2020 Hilisicon Electronics Co., Ltd. * http://www.huawei.com * * Authors: Yu Chen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 of - * the License as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ +#include #include #include #include -#include #include +#include #include -#include #define SCTRL_SCDEEPSLEEPED (0x0) #define USB_CLK_SELECTED BIT(20) @@ -116,7 +108,7 @@ #define TCPC_VALID BIT(4) #define TCPC_LOW_POWER_EN BIT(3) #define TCPC_MUX_CONTROL_MASK (3 << 0) -#define TCPC_MUX_CONTROL_USB31 (1 << 0) +#define TCPC_MUX_CONTROL_USB31 BIT(0) #define SYSMODE_CFG_TYPEC_DISABLE BIT(3) @@ -151,13 +143,13 @@ static int hi3670_phy_cr_clk(struct regmap *usb31misc) /* Clock up */ ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK); + CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK); if (ret) return ret; /* Clock down */ ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_CLK, 0); + CFG54_USB31PHY_CR_CLK, 0); return ret; } @@ -165,7 +157,7 @@ static int hi3670_phy_cr_clk(struct regmap *usb31misc) static int hi3670_phy_cr_set_sel(struct regmap *usb31misc) { return regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL); + CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL); } static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction) @@ -174,10 +166,12 @@ static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction) if (direction) ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_WR_EN, CFG54_USB31PHY_CR_WR_EN); + CFG54_USB31PHY_CR_WR_EN, + CFG54_USB31PHY_CR_WR_EN); else ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_RD_EN, CFG54_USB31PHY_CR_RD_EN); + CFG54_USB31PHY_CR_RD_EN, + CFG54_USB31PHY_CR_RD_EN); if (ret) return ret; @@ -187,7 +181,7 @@ static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction) return ret; ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, - CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0); + CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0); return ret; } @@ -223,8 +217,7 @@ static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr) return ret; reg &= ~(CFG54_USB31PHY_CR_ADDR_MASK << CFG54_USB31PHY_CR_ADDR_SHIFT); - reg |= ((addr & CFG54_USB31PHY_CR_ADDR_MASK) << - CFG54_USB31PHY_CR_ADDR_SHIFT); + reg |= ((addr & CFG54_USB31PHY_CR_ADDR_MASK) << CFG54_USB31PHY_CR_ADDR_SHIFT); ret = regmap_write(usb31misc, USB_MISC_CFG54, reg); return ret; @@ -288,7 +281,7 @@ static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val) return ret; ret = regmap_write(usb31misc, USB_MISC_CFG58, - val & CFG58_USB31PHY_CR_DATA_MASK); + val & CFG58_USB31PHY_CR_DATA_MASK); if (ret) return ret; @@ -308,7 +301,7 @@ static int hi3670_phy_set_params(struct hi3670_priv *priv) int retry = 3; ret = regmap_write(priv->usb31misc, USB3OTG_CTRL4, - priv->eye_diagram_param); + priv->eye_diagram_param); if (ret) { dev_err(priv->dev, "set USB3OTG_CTRL4 failed\n"); return ret; @@ -316,10 +309,11 @@ static int hi3670_phy_set_params(struct hi3670_priv *priv) while (retry-- > 0) { ret = hi3670_phy_cr_read(priv->usb31misc, - TX_VBOOST_LVL_REG, ®); + TX_VBOOST_LVL_REG, ®); if (!ret) break; - else if (ret != -ETIMEDOUT) { + + if (ret != -ETIMEDOUT) { dev_err(priv->dev, "read TX_VBOOST_LVL_REG failed\n"); return ret; } @@ -327,8 +321,7 @@ static int hi3670_phy_set_params(struct hi3670_priv *priv) if (ret) return ret; - reg |= (TX_VBOOST_LVL_ENABLE | - (priv->tx_vboost_lvl << TX_VBOOST_LVL_START)); + reg |= (TX_VBOOST_LVL_ENABLE | (priv->tx_vboost_lvl << TX_VBOOST_LVL_START)); ret = hi3670_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg); if (ret) dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n"); @@ -364,24 +357,24 @@ static int hi3670_config_phy_clock(struct hi3670_priv *priv) if (hi3670_is_abbclk_seleted(priv)) { /* usb refclk iso disable */ ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS, - USB_REFCLK_ISO_EN); + USB_REFCLK_ISO_EN); if (ret) goto out; /* enable usb_tcxo_en */ ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, - USB_TCXO_EN | - (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START)); + USB_TCXO_EN | + (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START)); /* select usbphy clk from abb */ mask = SC_CLK_USB3PHY_3MUX1_SEL; ret = regmap_update_bits(priv->pctrl, - PCTRL_PERI_CTRL24, mask, 0); + PCTRL_PERI_CTRL24, mask, 0); if (ret) goto out; ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, - CFGA0_USB2PHY_REFCLK_SELECT, 0); + CFGA0_USB2PHY_REFCLK_SELECT, 0); if (ret) goto out; @@ -393,33 +386,35 @@ static int hi3670_config_phy_clock(struct hi3670_priv *priv) ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val); if (ret) goto out; - } else { - ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54, - CFG54_USB3PHY_REF_USE_PAD, - CFG54_USB3PHY_REF_USE_PAD); - if (ret) - goto out; - ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, - CFGA0_USB2PHY_REFCLK_SELECT, - CFGA0_USB2PHY_REFCLK_SELECT); - if (ret) - goto out; + return 0; + } - ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val); - if (ret) - goto out; - val &= ~CTRL7_USB2_REFCLKSEL_MASK; - val |= CTRL7_USB2_REFCLKSEL_PAD; - ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val); - if (ret) - goto out; + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54, + CFG54_USB3PHY_REF_USE_PAD, + CFG54_USB3PHY_REF_USE_PAD); + if (ret) + goto out; - ret = regmap_write(priv->peri_crg, - PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF); - if (ret) - goto out; - } + ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, + CFGA0_USB2PHY_REFCLK_SELECT, + CFGA0_USB2PHY_REFCLK_SELECT); + if (ret) + goto out; + + ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val); + if (ret) + goto out; + val &= ~CTRL7_USB2_REFCLKSEL_MASK; + val |= CTRL7_USB2_REFCLKSEL_PAD; + ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val); + if (ret) + goto out; + + ret = regmap_write(priv->peri_crg, + PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF); + if (ret) + goto out; return 0; out: @@ -437,7 +432,7 @@ static int hi3670_config_tca(struct hi3670_priv *priv) goto out; ret = regmap_write(priv->usb31misc, TCA_INTR_EN, - INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN); + INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN); if (ret) goto out; @@ -447,13 +442,13 @@ static int hi3670_config_tca(struct hi3670_priv *priv) goto out; ret = regmap_update_bits(priv->usb31misc, TCA_GCFG, - GCFG_ROLE_HSTDEV | GCFG_OP_MODE, - GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE); + GCFG_ROLE_HSTDEV | GCFG_OP_MODE, + GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE); if (ret) goto out; ret = regmap_update_bits(priv->usb31misc, TCA_SYSMODE_CFG, - SYSMODE_CFG_TYPEC_DISABLE, 0); + SYSMODE_CFG_TYPEC_DISABLE, 0); if (ret) goto out; @@ -467,7 +462,7 @@ static int hi3670_config_tca(struct hi3670_priv *priv) goto out; ret = regmap_write(priv->usb31misc, TCA_VBUS_CTRL, - VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD); + VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD); if (ret) goto out; @@ -485,7 +480,7 @@ static int hi3670_phy_init(struct phy *phy) /* assert controller */ val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET | - CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; + CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR; ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0); if (ret) goto out; @@ -496,13 +491,13 @@ static int hi3670_phy_init(struct phy *phy) /* Exit from IDDQ mode */ ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL5, - CTRL5_USB2_SIDDQ, 0); + CTRL5_USB2_SIDDQ, 0); if (ret) goto out; /* Release USB31 PHY out of TestPowerDown mode */ ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG50, - CFG50_USB3_PHY_TEST_POWERDOWN, 0); + CFG50_USB3_PHY_TEST_POWERDOWN, 0); if (ret) goto out; @@ -512,13 +507,13 @@ static int hi3670_phy_init(struct phy *phy) if (ret) goto out; - udelay(100); + usleep_range(100, 120); /* Tell the PHY power is stable */ val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE | - CFG54_PHY0_PMA_PWR_STABLE; + CFG54_PHY0_PMA_PWR_STABLE; ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54, - val, val); + val, val); if (ret) goto out; @@ -528,8 +523,8 @@ static int hi3670_phy_init(struct phy *phy) /* Enable SSC */ ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG5C, - CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN, - CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN); + CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN, + CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN); if (ret) goto out; @@ -539,7 +534,7 @@ static int hi3670_phy_init(struct phy *phy) if (ret) goto out; - udelay(100); + usleep_range(100, 120); /* Set fake vbus valid signal */ val = CTRL0_USB3_VBUSVLD | CTRL0_USB3_VBUSVLD_SEL; @@ -552,7 +547,7 @@ static int hi3670_phy_init(struct phy *phy) if (ret) goto out; - udelay(100); + usleep_range(100, 120); ret = hi3670_phy_set_params(priv); if (ret) @@ -579,10 +574,10 @@ static int hi3670_phy_exit(struct phy *phy) if (hi3670_is_abbclk_seleted(priv)) { /* disable usb_tcxo_en */ ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3, - USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START); + USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START); } else { ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6, - GT_CLK_USB2PHY_REF); + GT_CLK_USB2PHY_REF); if (ret) goto out; } @@ -612,39 +607,39 @@ static int hi3670_phy_probe(struct platform_device *pdev) priv->dev = dev; priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node, - "hisilicon,pericrg-syscon"); + "hisilicon,pericrg-syscon"); if (IS_ERR(priv->peri_crg)) { dev_err(dev, "no hisilicon,pericrg-syscon\n"); return PTR_ERR(priv->peri_crg); } priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node, - "hisilicon,pctrl-syscon"); + "hisilicon,pctrl-syscon"); if (IS_ERR(priv->pctrl)) { dev_err(dev, "no hisilicon,pctrl-syscon\n"); return PTR_ERR(priv->pctrl); } priv->sctrl = syscon_regmap_lookup_by_phandle(dev->of_node, - "hisilicon,sctrl-syscon"); + "hisilicon,sctrl-syscon"); if (IS_ERR(priv->sctrl)) { dev_err(dev, "no hisilicon,sctrl-syscon\n"); return PTR_ERR(priv->sctrl); } priv->usb31misc = syscon_regmap_lookup_by_phandle(dev->of_node, - "hisilicon,usb31-misc-syscon"); + "hisilicon,usb31-misc-syscon"); if (IS_ERR(priv->usb31misc)) { dev_err(dev, "no hisilicon,usb31-misc-syscon\n"); return PTR_ERR(priv->usb31misc); } if (of_property_read_u32(dev->of_node, "eye-diagram-param", - &(priv->eye_diagram_param))) + &priv->eye_diagram_param)) priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM; if (of_property_read_u32(dev->of_node, "usb3-phy-tx-vboost-lvl", - &(priv->tx_vboost_lvl))) + &priv->tx_vboost_lvl)) priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_VBOOST; phy = devm_phy_create(dev, NULL, &hi3670_phy_ops); @@ -657,7 +652,7 @@ static int hi3670_phy_probe(struct platform_device *pdev) } static const struct of_device_id hi3670_phy_of_match[] = { - {.compatible = "hisilicon,hi3670-usb-phy",}, + { .compatible = "hisilicon,hi3670-usb-phy" }, { }, }; MODULE_DEVICE_TABLE(of, hi3670_phy_of_match); -- cgit v1.2.3 From aa125e718785808f7677dc23a44b93400fcc5d6e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:11 +0200 Subject: staging: hikey9xx: phy-hi3670-usb3: change some DT properties Do some changes at the DT properties in order to make it follow the phy-hi3660-usb3 example and to simplify usb3-phy-tx-vboost-lvl name. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/da128b9943bcb6a3d44a9512cedc7fa7a4aedee6.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c index cb0bfcbbfbfa..42dbc20a0b9a 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -627,18 +627,18 @@ static int hi3670_phy_probe(struct platform_device *pdev) return PTR_ERR(priv->sctrl); } - priv->usb31misc = syscon_regmap_lookup_by_phandle(dev->of_node, - "hisilicon,usb31-misc-syscon"); + /* node of hi3670 phy is a sub-node of usb3_otg_bc */ + priv->usb31misc = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(priv->usb31misc)) { - dev_err(dev, "no hisilicon,usb31-misc-syscon\n"); + dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n"); return PTR_ERR(priv->usb31misc); } - if (of_property_read_u32(dev->of_node, "eye-diagram-param", + if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param", &priv->eye_diagram_param)) priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM; - if (of_property_read_u32(dev->of_node, "usb3-phy-tx-vboost-lvl", + if (of_property_read_u32(dev->of_node, "hisilicon,tx-vboost-lvl", &priv->tx_vboost_lvl)) priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_VBOOST; -- cgit v1.2.3 From 8436f932d84b1d53d2f4a2fa88c7aacdb0313265 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 17 Sep 2020 12:42:12 +0200 Subject: staging: hikey9xx: convert phy-kirin970-usb3.txt to yaml Use the new YAML for this physical layer. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/03535ba996b3d82d522ce9c529bc2ce8e1d8d531.1600338981.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.txt | 25 ---------- drivers/staging/hikey9xx/phy-hi3670-usb3.yaml | 72 +++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 25 deletions(-) delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.txt create mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.txt b/drivers/staging/hikey9xx/phy-hi3670-usb3.txt deleted file mode 100644 index 2fb27cb8beaf..000000000000 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.txt +++ /dev/null @@ -1,25 +0,0 @@ -Hisilicon Kirin970 usb PHY ------------------------ - -Required properties: -- compatible: should be "hisilicon,hi3670-usb-phy" -- #phy-cells: must be 0 -- hisilicon,pericrg-syscon: phandle of syscon used to control phy. -- hisilicon,pctrl-syscon: phandle of syscon used to control phy. -- hisilicon,sctrl-syscon: phandle of syscon used to control phy. -- hisilicon,usb31-misc-syscon: phandle of syscon used to control phy. -- eye-diagram-param: parameter set for phy -- usb3-phy-tx-vboost-lvl: parameter set for phy -Refer to phy/phy-bindings.txt for the generic PHY binding properties - -Example: - usb_phy: usbphy { - compatible = "hisilicon,hi3670-usb-phy"; - #phy-cells = <0>; - hisilicon,pericrg-syscon = <&crg_ctrl>; - hisilicon,pctrl-syscon = <&pctrl>; - hisilicon,sctrl-syscon = <&sctrl>; - hisilicon,usb31-misc-syscon = <&usb31_misc>; - eye-diagram-param = <0xFDFEE4>; - usb3-phy-tx-vboost-lvl = <0x5>; - }; diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml new file mode 100644 index 000000000000..125a5d6546ae --- /dev/null +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml @@ -0,0 +1,72 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/hisilicon,hi3670-usb3.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Hisilicon Kirin970 USB PHY + +maintainers: + - Mauro Carvalho Chehab +description: |+ + Bindings for USB3 PHY on HiSilicon Kirin 970. + +properties: + compatible: + const: hisilicon,hi3670-usb-phy + + "#phy-cells": + const: 0 + + hisilicon,pericrg-syscon: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: phandle of syscon used to control iso refclk. + + hisilicon,pctrl-syscon: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: phandle of syscon used to control usb tcxo. + + hisilicon,sctrl-syscon: + $ref: '/schemas/types.yaml#/definitions/phandle' + description: phandle of syscon used to control phy deep sleep. + + hisilicon,eye-diagram-param: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Eye diagram for phy. + + hisilicon,tx-vboost-lvl: + $ref: /schemas/types.yaml#/definitions/uint32 + description: TX level vboost for phy. + +required: + - compatible + - hisilicon,pericrg-syscon + - hisilicon,pctrl-syscon + - hisilicon,sctrl-syscon + - hisilicon,eye-diagram-param + - hisilicon,tx-vboost-lvl + - "#phy-cells" + +additionalProperties: false + +examples: + - | + bus { + #address-cells = <2>; + #size-cells = <2>; + + usb3_otg_bc: usb3_otg_bc@ff200000 { + compatible = "syscon", "simple-mfd"; + reg = <0x0 0xff200000 0x0 0x1000>; + + usb_phy { + compatible = "hisilicon,hi3670-usb-phy"; + #phy-cells = <0>; + hisilicon,pericrg-syscon = <&crg_ctrl>; + hisilicon,pctrl-syscon = <&pctrl>; + hisilicon,sctrl-syscon = <&sctrl>; + hisilicon,eye-diagram-param = <0xfdfee4>; + hisilicon,tx-vboost-lvl = <0x5>; + }; + }; + }; -- cgit v1.2.3 From dbbc8fdf2ad57629436bcdb421c2d4ad9aa1974f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Sep 2020 17:33:38 +0300 Subject: staging: spmi: hisi-spmi-controller: Use devm_ version of ioremap(). The ioremap() was never unmapped in the probe error handling or in the remove function. The fix is to use the devm_ioremap() function so it gets cleaned up automatically. Fixes: 70f59c90c819 ("staging: spmi: add Hikey 970 SPMI controller driver") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/20200918143338.GE909725@mwanda Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/hisi-spmi-controller.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c index 5ffe79f45d9a..f831c43f4783 100644 --- a/drivers/staging/hikey9xx/hisi-spmi-controller.c +++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c @@ -281,7 +281,8 @@ static int spmi_controller_probe(struct platform_device *pdev) return -EINVAL; } - spmi_controller->base = ioremap(iores->start, resource_size(iores)); + spmi_controller->base = devm_ioremap(&pdev->dev, iores->start, + resource_size(iores)); if (!spmi_controller->base) { dev_err(&pdev->dev, "can not remap base addr!\n"); return -EADDRNOTAVAIL; -- cgit v1.2.3 From c823f6a7980b3b0972faf2abf50e120269a26f93 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Mon, 21 Sep 2020 22:21:47 +0100 Subject: staging: hikey9xx: Fix incorrect assignment In hi3670_phy_probe(), when reading property tx-vboost-lvl fails, its default value is assigned to priv->eye_diagram_param, rather than to priv->tx_vboost_lvl. Fix this. Fixes: 8971a3b880b2 ("staging: hikey9xx: add USB physical layer for Kirin 3670") Addresses-Coverity: CID 1497107: Incorrect expression (COPY_PASTE_ERROR) Signed-off-by: Alex Dewar Link: https://lore.kernel.org/r/20200921212146.34662-1-alex.dewar90@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/hikey9xx/phy-hi3670-usb3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/staging/hikey9xx') diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c index 42dbc20a0b9a..4fc013911a78 100644 --- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c +++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c @@ -640,7 +640,7 @@ static int hi3670_phy_probe(struct platform_device *pdev) if (of_property_read_u32(dev->of_node, "hisilicon,tx-vboost-lvl", &priv->tx_vboost_lvl)) - priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_VBOOST; + priv->tx_vboost_lvl = KIRIN970_USB_DEFAULT_PHY_VBOOST; phy = devm_phy_create(dev, NULL, &hi3670_phy_ops); if (IS_ERR(phy)) -- cgit v1.2.3