From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> To: unlisted-recipients:; (no To-header on input) Cc: linuxarm@huawei.com, mauro.chehab@huawei.com, Mayulong <mayulong1@huawei.com>, Mauro Carvalho Chehab <mchehab+huawei@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, linux-kernel@vger.kernel.org, devel@driverdev.osuosl.org Subject: [PATCH 01/44] staging: spmi: add Hikey 970 SPMI controller driver Date: Wed, 12 Aug 2020 17:56:11 +0200 [thread overview] Message-ID: <4305f945d257cf590646100cad752a0a6542a152.1597247164.git.mchehab+huawei@kernel.org> (raw) In-Reply-To: <cover.1597247164.git.mchehab+huawei@kernel.org> From: Mayulong <mayulong1@huawei.com> 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 <mayulong1@huawei.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> --- .../staging/hikey9xx/hisi-spmi-controller.c | 390 ++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c 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 <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/spmi.h> +#include <linux/spmi.h> + +#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,*)*/ + -- 2.26.2
WARNING: multiple messages have this Message-ID (diff)
From: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> Cc: devel@driverdev.osuosl.org, Mayulong <mayulong1@huawei.com>, Mauro Carvalho Chehab <mchehab+huawei@kernel.org>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, linuxarm@huawei.com, linux-kernel@vger.kernel.org, mauro.chehab@huawei.com Subject: [PATCH 01/44] staging: spmi: add Hikey 970 SPMI controller driver Date: Wed, 12 Aug 2020 17:56:11 +0200 [thread overview] Message-ID: <4305f945d257cf590646100cad752a0a6542a152.1597247164.git.mchehab+huawei@kernel.org> (raw) In-Reply-To: <cover.1597247164.git.mchehab+huawei@kernel.org> From: Mayulong <mayulong1@huawei.com> 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 <mayulong1@huawei.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> --- .../staging/hikey9xx/hisi-spmi-controller.c | 390 ++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c 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 <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/spmi.h> +#include <linux/spmi.h> + +#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,*)*/ + -- 2.26.2 _______________________________________________ devel mailing list devel@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
next prev parent reply other threads:[~2020-08-12 15:59 UTC|newest] Thread overview: 129+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-08-12 15:56 [PATCH 00/44] SPMI patches needed by Hikey 970 Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab [this message] 2020-08-12 15:56 ` [PATCH 01/44] staging: spmi: add Hikey 970 SPMI controller driver Mauro Carvalho Chehab 2020-08-12 16:28 ` Greg Kroah-Hartman 2020-08-12 16:28 ` Greg Kroah-Hartman 2020-08-12 18:59 ` Mauro Carvalho Chehab 2020-08-12 18:59 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 02/44] staging: spmi: hisi-spmi-controller: coding style fixup Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 03/44] staging: spmi: hisi-spmi-controller: fix it to probe successfully Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 04/44] staging: spmi: hisi-spmi-controller: fix a typo Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 05/44] staging: spmi: hisi-spmi-controller: adjust whitespaces at defines Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 06/44] staging: spmi: hisi-spmi-controller: use le32 macros where needed Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 16:21 ` Joe Perches 2020-08-12 16:21 ` Joe Perches 2020-08-12 19:02 ` Mauro Carvalho Chehab 2020-08-12 19:02 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 07/44] staging: spmi: hisi-spmi-controller: add debug when values are read/write Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 08/44] staging: spmi: hisi-spmi-controller: fix the dev_foo() logic Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 09/44] staging: spmi: hisi-spmi-controller: add it to the building system Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 10/44] staging: spmi: hisi-spmi-controller: do some code cleanups Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 16:17 ` Joe Perches 2020-08-12 16:17 ` Joe Perches 2020-08-12 15:56 ` [PATCH 11/44] staging: mfd: add a PMIC driver for HiSilicon 6421 SPMI version Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 12/44] staging: mfd: hi6421-spmi-pmic: get rid of unused code Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 13/44] staging: mfd: hi6421-spmi-pmic: deal with non-static functions Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 14/44] staging: mfd: hi6421-spmi-pmic: get rid of the static vars Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 15/44] staging: mfd: hi6421-spmi-pmic: cleanup hi6421-spmi-pmic.h header Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 16/44] staging: mfd: hi6421-spmi-pmic: change the binding logic Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 17/44] staging: mfd: hi6421-spmi-pmic: get rid of unused OF properties Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 18/44] staging: mfd: hi6421-spmi-pmic: cleanup " Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 19/44] staging: mfd: hi6421-spmi-pmic: change namespace on its functions Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 20/44] staging: mfd: hi6421-spmi-pmic: fix some coding style issues Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 16:12 ` Joe Perches 2020-08-12 16:12 ` Joe Perches 2020-08-12 15:56 ` [PATCH 21/44] staging: mfd: hi6421-spmi-pmic: add it to the building system Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 22/44] staging: mfd: hi6421-spmi-pmic: cleanup the code Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 23/44] staging: regulator: add a regulator driver for HiSilicon 6421v600 SPMI PMIC Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 24/44] staging: regulator: hi6421v600-regulator: get rid of unused code Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 25/44] staging: regulator: hi6421v600-regulator: port it to upstream Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 26/44] staging: regulator: hi6421v600-regulator: coding style fixups Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 27/44] staging: regulator: hi6421v600-regulator: change the binding logic Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 28/44] staging: regulator: hi6421v600-regulator: cleanup struct hisi_regulator Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 29/44] staging: regulator: hi6421v600-regulator: cleanup debug messages Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 30/44] staging: regulator: hi6421v600-regulator: use shorter names for OF properties Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 31/44] staging: regulator: hi6421v600-regulator: better handle modes Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 32/44] staging: regulator: hi6421v600-regulator: change namespace Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 33/44] staging: regulator: hi6421v600-regulator: convert to use get/set voltage_sel Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 34/44] staging: regulator: hi6421v600-regulator: don't use usleep_range for off_on_delay Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 35/44] staging: regulator: hi6421v600-regulator: add a driver-specific debug macro Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 16:10 ` Joe Perches 2020-08-12 16:10 ` Joe Perches 2020-08-13 10:10 ` Mauro Carvalho Chehab 2020-08-13 10:10 ` Mauro Carvalho Chehab 2020-08-13 15:07 ` Joe Perches 2020-08-13 15:07 ` Joe Perches 2020-08-14 4:01 ` [PATCH] media: debugging logging cleanup Joe Perches 2020-08-14 4:01 ` Joe Perches 2020-08-12 15:56 ` [PATCH 36/44] staging: regulator: hi6421v600-regulator: initialize ramp_delay Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 37/44] staging: regulator: hi6421v600-regulator: cleanup DT settings Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 38/44] staging: regulator: hi6421v600-regulator: fix some coding style issues Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 39/44] staging: regulator: hi6421v600-regulator: add it to the building system Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 40/44] staging: regulator: hi6421v600-regulator: code cleanup Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 41/44] staging: hikey9xx: add a TODO list Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 42/44] MAINTAINERS: add an entry for HiSilicon 6421v600 drivers Mauro Carvalho Chehab 2020-08-12 15:56 ` [PATCH 43/44] dt: document HiSilicon SPMI controller and mfd/regulator properties Mauro Carvalho Chehab 2020-08-14 20:17 ` Rob Herring 2020-08-15 9:55 ` Mauro Carvalho Chehab 2020-08-17 14:13 ` Rob Herring 2020-08-12 15:56 ` [PATCH 44/44] dt: hisilicon: add support for the PMIC found on Hikey 970 Mauro Carvalho Chehab 2020-08-12 15:56 ` Mauro Carvalho Chehab 2020-08-12 17:13 ` [PATCH 00/44] SPMI patches needed by " Joe Perches 2020-08-12 17:13 ` Joe Perches 2020-08-12 17:13 ` Joe Perches 2020-08-12 18:47 ` Mauro Carvalho Chehab 2020-08-12 18:47 ` Mauro Carvalho Chehab 2020-08-12 18:47 ` Mauro Carvalho Chehab 2020-08-12 18:58 ` Joe Perches 2020-08-12 18:58 ` Joe Perches 2020-08-12 18:58 ` Joe Perches 2020-08-12 19:07 ` Mauro Carvalho Chehab 2020-08-12 19:07 ` Mauro Carvalho Chehab 2020-08-12 19:07 ` Mauro Carvalho Chehab 2020-08-13 7:58 ` Lee Jones 2020-08-13 7:58 ` Lee Jones 2020-08-13 7:58 ` Lee Jones 2020-08-13 9:58 ` Mauro Carvalho Chehab 2020-08-13 9:58 ` Mauro Carvalho Chehab 2020-08-13 9:58 ` Mauro Carvalho Chehab
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=4305f945d257cf590646100cad752a0a6542a152.1597247164.git.mchehab+huawei@kernel.org \ --to=mchehab+huawei@kernel.org \ --cc=devel@driverdev.osuosl.org \ --cc=gregkh@linuxfoundation.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linuxarm@huawei.com \ --cc=mauro.chehab@huawei.com \ --cc=mayulong1@huawei.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.