* [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging
@ 2021-01-18 13:28 Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 09/13] spmi: hi6421-spmi-pmic: move driver from staging Mauro Carvalho Chehab
` (4 more replies)
0 siblings, 5 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Colin Ian King, Dan Carpenter,
Greg Kroah-Hartman, Lee Jones, Liam Girdwood, Mayulong,
Rob Herring, Stephen Boyd, Wei Xu, YueHaibing, devel, devicetree,
linux-arm-kernel, linux-arm-msm, linux-kernel
Hi Mark,
This patch series finish addressing support for Hikey 970
SPMI controller, PMIC and regulators.
I removed some unrelated DT patches from this series,
plus the Hikey 970 PHY USB3 code from it, in order to avoid
mixing different stuff on this series[1].
[1] Those unrelated patches were submitted last week on
separate series.
The entire patchset is on this branch:
https://git.linuxtv.org/mchehab/experimental.git/log/?h=devel/destage-usb
In order to make easier for review, this series was generated
with --no-merges. So, you don't need to take a look at the
staging patches, as the entire code will be there on patches 9-11.
Patches 12 and 13 on this series will require that the other
patch series to get merged first. It probably makes sense to be
merged via DT tree. I opted to add them here just because,
on the last submission, you asked to see the DT patches.
On this version 2, I addressed almost all issues you pointed during
your review:
- this driver's probe routine is very similar to the one at the non-SPMI
variant of Hisilicon 6421;
- The register/voltage data were moved from DT into the driver itself;
- It doesn't have anymore any static data;
- All debug messages got removed;
- Addressed a few be32 warnings from sparse.
Regards,
Mauro
Mauro Carvalho Chehab (13):
staging: hikey9xx: hisilicon,hisi-spmi-controller.yaml fix bindings
staging: hikey9xx: hisi-spmi-controller: clean sparse warnings
staging: hikey9xx: hi6421v600-regulator: do some cleanups
staging: hikey9xx: hi6421v600-regulator: move LDO config from DT
staging: hikey9xx: hi6421v600-regulator: cleanup debug msgs
staging: hikey9xx: hisilicon,hi6421-spmi-pmic.yaml: simplify props
staging: hikey970: get rid of an static data
staging: hikey9xx: hi6421v600-regulator: do some cleanups
spmi: hi6421-spmi-pmic: move driver from staging
mfd: hi6421-spmi-pmic: move driver from staging
regulator: hi6421v600-regulator: move it from staging
dts: hisilicon: add support for USB3 on Hikey 970
dts: hisilicon: add support for the PMIC found on Hikey 970
.../mfd/hisilicon,hi6421-spmi-pmic.yaml | 135 +++++
.../spmi/hisilicon,hisi-spmi-controller.yaml | 75 +++
MAINTAINERS | 15 +-
.../boot/dts/hisilicon/hi3670-hikey970.dts | 124 ++++-
arch/arm64/boot/dts/hisilicon/hi3670.dtsi | 58 +++
.../boot/dts/hisilicon/hikey970-pmic.dtsi | 87 ++++
drivers/mfd/Kconfig | 15 +
drivers/mfd/Makefile | 1 +
drivers/mfd/hi6421-spmi-pmic.c | 342 +++++++++++++
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/hi6421v600-regulator.c | 347 +++++++++++++
drivers/spmi/Kconfig | 9 +
drivers/spmi/Makefile | 1 +
drivers/spmi/hisi-spmi-controller.c | 358 +++++++++++++
drivers/staging/Kconfig | 2 -
drivers/staging/Makefile | 1 -
drivers/staging/hikey9xx/Kconfig | 38 --
drivers/staging/hikey9xx/Makefile | 5 -
drivers/staging/hikey9xx/TODO | 5 -
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 -------------
.../staging/hikey9xx/hi6421v600-regulator.c | 478 ------------------
.../staging/hikey9xx/hisi-spmi-controller.c | 358 -------------
.../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 159 ------
.../hisilicon,hisi-spmi-controller.yaml | 62 ---
25 files changed, 1554 insertions(+), 1472 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
create mode 100644 Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
create mode 100644 drivers/regulator/hi6421v600-regulator.c
create mode 100644 drivers/spmi/hisi-spmi-controller.c
delete mode 100644 drivers/staging/hikey9xx/Kconfig
delete mode 100644 drivers/staging/hikey9xx/Makefile
delete mode 100644 drivers/staging/hikey9xx/TODO
delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c
delete mode 100644 drivers/staging/hikey9xx/hi6421v600-regulator.c
delete mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c
delete mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
delete mode 100644 drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
--
2.29.2
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v2 09/13] spmi: hi6421-spmi-pmic: move driver from staging
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
@ 2021-01-18 13:28 ` Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 10/13] mfd: " Mauro Carvalho Chehab
` (3 subsequent siblings)
4 siblings, 0 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Colin Ian King, Dan Carpenter,
Greg Kroah-Hartman, Mayulong, Rob Herring, Stephen Boyd,
YueHaibing, devel, devicetree, linux-arm-msm, linux-kernel
The Hisilicon 6421v600 SPMI driver is ready for mainstream.
So, move it from staging.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
.../spmi/hisilicon,hisi-spmi-controller.yaml | 75 ++++
MAINTAINERS | 7 +
drivers/spmi/Kconfig | 9 +
drivers/spmi/Makefile | 1 +
drivers/spmi/hisi-spmi-controller.c | 358 ++++++++++++++++++
drivers/staging/hikey9xx/Kconfig | 11 -
drivers/staging/hikey9xx/Makefile | 1 -
.../staging/hikey9xx/hisi-spmi-controller.c | 358 ------------------
.../hisilicon,hisi-spmi-controller.yaml | 75 ----
9 files changed, 450 insertions(+), 445 deletions(-)
create mode 100644 Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
create mode 100644 drivers/spmi/hisi-spmi-controller.c
delete mode 100644 drivers/staging/hikey9xx/hisi-spmi-controller.c
delete mode 100644 drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
diff --git a/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
new file mode 100644
index 000000000000..21f68a9c2df1
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
@@ -0,0 +1,75 @@
+# 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 <mchehab+huawei@kernel.org>
+
+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
+ drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+
+properties:
+ $nodename:
+ pattern: "spmi@[0-9a-f]"
+
+ compatible:
+ const: hisilicon,kirin970-spmi-controller
+
+ reg:
+ maxItems: 1
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 0
+
+ spmi-channel:
+ description: |
+ number of the Kirin 970 SPMI channel where the SPMI devices are connected.
+
+required:
+ - compatible
+ - reg
+ - spmi-channel
+ - "#address-cells"
+ - "#size-cells"
+
+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
+ drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+
+additionalProperties: false
+
+examples:
+ - |
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ spmi: spmi@fff24000 {
+ compatible = "hisilicon,kirin970-spmi-controller";
+ #address-cells = <2>;
+ #size-cells = <0>;
+ status = "ok";
+ reg = <0x0 0xfff24000 0x0 0x1000>;
+ spmi-channel = <2>;
+
+ pmic@0 {
+ reg = <0 0>;
+ /* pmic properties */
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8d858e8d5a52..85e5b6ab57ca 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7999,6 +7999,13 @@ F: drivers/crypto/hisilicon/sec2/sec_crypto.c
F: drivers/crypto/hisilicon/sec2/sec_crypto.h
F: drivers/crypto/hisilicon/sec2/sec_main.c
+HISILICON SPMI CONTROLLER DRIVER FOR HIKEY 970
+M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
+F: drivers/spmi/hisi-spmi-controller.c
+
HISILICON STAGING DRIVERS FOR HIKEY 960/970
M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
L: devel@driverdev.osuosl.org
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index a53bad541f1a..2874b6c26028 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -11,6 +11,15 @@ menuconfig SPMI
if SPMI
+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.
+
config SPMI_MSM_PMIC_ARB
tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
select IRQ_DOMAIN_HIERARCHY
diff --git a/drivers/spmi/Makefile b/drivers/spmi/Makefile
index 55a94cadeffe..6e092e6f290c 100644
--- a/drivers/spmi/Makefile
+++ b/drivers/spmi/Makefile
@@ -4,4 +4,5 @@
#
obj-$(CONFIG_SPMI) += spmi.o
+obj-$(CONFIG_SPMI_HISI3670) += hisi-spmi-controller.o
obj-$(CONFIG_SPMI_MSM_PMIC_ARB) += spmi-pmic-arb.o
diff --git a/drivers/spmi/hisi-spmi-controller.c b/drivers/spmi/hisi-spmi-controller.c
new file mode 100644
index 000000000000..4be2344ad7b5
--- /dev/null
+++ b/drivers/spmi/hisi-spmi-controller.c
@@ -0,0 +1,358 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+/*
+ * SPMI register addr
+ */
+#define SPMI_CHANNEL_OFFSET 0x0300
+#define SPMI_SLAVE_OFFSET 0x20
+
+#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100
+
+#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
+
+#define SPMI_PER_DATAREG_BYTE 4
+/*
+ * SPMI cmd register
+ */
+#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
+
+/* Command Opcodes */
+
+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,
+};
+
+/*
+ * SPMI status register
+ */
+#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
+
+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 device *dev,
+ struct spmi_controller_dev *ctrl_dev,
+ void __iomem *base, u8 sid, u16 addr)
+{
+ u32 timeout = SPMI_CONTROLLER_TIMEOUT_US;
+ u32 status, offset;
+
+ offset = SPMI_APB_SPMI_STATUS_BASE_ADDR;
+ offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid;
+
+ do {
+ status = readl(base + offset);
+
+ if (status & SPMI_APB_TRANS_DONE) {
+ if (status & SPMI_APB_TRANS_FAIL) {
+ 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);
+ } 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 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;
+ u8 op_code, i;
+
+ if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
+ dev_err(&ctrl->dev,
+ "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
+ SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
+ return -EINVAL;
+ }
+
+ switch (opc) {
+ case SPMI_CMD_READ:
+ op_code = SPMI_CMD_REG_READ;
+ break;
+ case SPMI_CMD_EXT_READ:
+ op_code = SPMI_CMD_EXT_REG_READ;
+ break;
+ case SPMI_CMD_EXT_READL:
+ op_code = SPMI_CMD_EXT_REG_READ_L;
+ 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) |
+ ((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, slave_id, slave_addr);
+ if (rc)
+ goto done;
+
+ 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((__force __be32)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);
+ buf += (bc % 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 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",
+ __func__, slave_id, slave_addr, (int)bc, __buf);
+
+ return rc;
+}
+
+static int spmi_write_cmd(struct spmi_controller *ctrl,
+ 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;
+ u8 op_code, i;
+
+ if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
+ dev_err(&ctrl->dev,
+ "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
+ SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
+ return -EINVAL;
+ }
+
+ switch (opc) {
+ case SPMI_CMD_WRITE:
+ op_code = SPMI_CMD_REG_WRITE;
+ break;
+ case SPMI_CMD_EXT_WRITE:
+ op_code = SPMI_CMD_EXT_REG_WRITE;
+ break;
+ case SPMI_CMD_EXT_WRITEL:
+ op_code = SPMI_CMD_EXT_REG_WRITE_L;
+ 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) |
+ ((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);
+
+ 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));
+ buf += sizeof(data);
+ } else {
+ memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
+ buf += (bc % SPMI_PER_DATAREG_BYTE);
+ }
+
+ writel((__force u32)cpu_to_be32(data),
+ 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, slave_id,
+ slave_addr);
+ 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:%zu\n",
+ opc, slave_id, slave_addr, bc);
+ else
+ 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;
+}
+
+static int spmi_controller_probe(struct platform_device *pdev)
+{
+ struct spmi_controller_dev *spmi_controller;
+ struct spmi_controller *ctrl;
+ struct resource *iores;
+ int ret;
+
+ ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller));
+ if (!ctrl) {
+ dev_err(&pdev->dev, "can not allocate spmi_controller data\n");
+ return -ENOMEM;
+ }
+ spmi_controller = spmi_controller_get_drvdata(ctrl);
+ spmi_controller->controller = ctrl;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores) {
+ dev_err(&pdev->dev, "can not get resource!\n");
+ return -EINVAL;
+ }
+
+ 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;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel",
+ &spmi_controller->channel);
+ if (ret) {
+ dev_err(&pdev->dev, "can not get channel\n");
+ return -ENODEV;
+ }
+
+ 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 with error %d!\n", ret);
+
+ return ret;
+}
+
+static int spmi_del_controller(struct platform_device *pdev)
+{
+ struct spmi_controller *ctrl = platform_get_drvdata(pdev);
+
+ spmi_controller_remove(ctrl);
+ kfree(ctrl);
+ return 0;
+}
+
+static const struct of_device_id spmi_controller_match_table[] = {
+ {
+ .compatible = "hisilicon,kirin970-spmi-controller",
+ },
+ {}
+};
+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 = "hisi_spmi_controller",
+ .of_match_table = spmi_controller_match_table,
+ },
+};
+
+static int __init spmi_controller_init(void)
+{
+ return platform_driver_register(&spmi_controller_driver);
+}
+postcore_initcall(spmi_controller_init);
+
+static void __exit spmi_controller_exit(void)
+{
+ platform_driver_unregister(&spmi_controller_driver);
+}
+module_exit(spmi_controller_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform:spmi_controller");
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 0e97b5b9a56a..69392e42cd0d 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -1,16 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-# to be placed at drivers/spmi
-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
- processors.
-
# to be placed at drivers/mfd
config MFD_HI6421_SPMI
tristate "HiSilicon Hi6421v600 SPMI PMU/Codec IC"
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
index 9371dcc3d35b..347880fd378f 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,5 +1,4 @@
# 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_REGULATOR_HI6421V600) += hi6421v600-regulator.o
diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c
deleted file mode 100644
index 4be2344ad7b5..000000000000
--- a/drivers/staging/hikey9xx/hisi-spmi-controller.c
+++ /dev/null
@@ -1,358 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/spmi.h>
-
-/*
- * SPMI register addr
- */
-#define SPMI_CHANNEL_OFFSET 0x0300
-#define SPMI_SLAVE_OFFSET 0x20
-
-#define SPMI_APB_SPMI_CMD_BASE_ADDR 0x0100
-
-#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
-
-#define SPMI_PER_DATAREG_BYTE 4
-/*
- * SPMI cmd register
- */
-#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
-
-/* Command Opcodes */
-
-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,
-};
-
-/*
- * SPMI status register
- */
-#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
-
-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 device *dev,
- struct spmi_controller_dev *ctrl_dev,
- void __iomem *base, u8 sid, u16 addr)
-{
- u32 timeout = SPMI_CONTROLLER_TIMEOUT_US;
- u32 status, offset;
-
- offset = SPMI_APB_SPMI_STATUS_BASE_ADDR;
- offset += SPMI_CHANNEL_OFFSET * ctrl_dev->channel + SPMI_SLAVE_OFFSET * sid;
-
- do {
- status = readl(base + offset);
-
- if (status & SPMI_APB_TRANS_DONE) {
- if (status & SPMI_APB_TRANS_FAIL) {
- 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);
- } 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 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;
- u8 op_code, i;
-
- if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
- dev_err(&ctrl->dev,
- "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
- SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
- return -EINVAL;
- }
-
- switch (opc) {
- case SPMI_CMD_READ:
- op_code = SPMI_CMD_REG_READ;
- break;
- case SPMI_CMD_EXT_READ:
- op_code = SPMI_CMD_EXT_REG_READ;
- break;
- case SPMI_CMD_EXT_READL:
- op_code = SPMI_CMD_EXT_REG_READ_L;
- 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) |
- ((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, slave_id, slave_addr);
- if (rc)
- goto done;
-
- 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((__force __be32)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);
- buf += (bc % 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 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",
- __func__, slave_id, slave_addr, (int)bc, __buf);
-
- return rc;
-}
-
-static int spmi_write_cmd(struct spmi_controller *ctrl,
- 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;
- u8 op_code, i;
-
- if (bc > SPMI_CONTROLLER_MAX_TRANS_BYTES) {
- dev_err(&ctrl->dev,
- "spmi_controller supports 1..%d bytes per trans, but:%zu requested\n",
- SPMI_CONTROLLER_MAX_TRANS_BYTES, bc);
- return -EINVAL;
- }
-
- switch (opc) {
- case SPMI_CMD_WRITE:
- op_code = SPMI_CMD_REG_WRITE;
- break;
- case SPMI_CMD_EXT_WRITE:
- op_code = SPMI_CMD_EXT_REG_WRITE;
- break;
- case SPMI_CMD_EXT_WRITEL:
- op_code = SPMI_CMD_EXT_REG_WRITE_L;
- 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) |
- ((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);
-
- 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));
- buf += sizeof(data);
- } else {
- memcpy(&data, buf, bc % SPMI_PER_DATAREG_BYTE);
- buf += (bc % SPMI_PER_DATAREG_BYTE);
- }
-
- writel((__force u32)cpu_to_be32(data),
- 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, slave_id,
- slave_addr);
- 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:%zu\n",
- opc, slave_id, slave_addr, bc);
- else
- 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;
-}
-
-static int spmi_controller_probe(struct platform_device *pdev)
-{
- struct spmi_controller_dev *spmi_controller;
- struct spmi_controller *ctrl;
- struct resource *iores;
- int ret;
-
- ctrl = spmi_controller_alloc(&pdev->dev, sizeof(*spmi_controller));
- if (!ctrl) {
- dev_err(&pdev->dev, "can not allocate spmi_controller data\n");
- return -ENOMEM;
- }
- spmi_controller = spmi_controller_get_drvdata(ctrl);
- spmi_controller->controller = ctrl;
-
- iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!iores) {
- dev_err(&pdev->dev, "can not get resource!\n");
- return -EINVAL;
- }
-
- 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;
- }
-
- ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel",
- &spmi_controller->channel);
- if (ret) {
- dev_err(&pdev->dev, "can not get channel\n");
- return -ENODEV;
- }
-
- 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 with error %d!\n", ret);
-
- return ret;
-}
-
-static int spmi_del_controller(struct platform_device *pdev)
-{
- struct spmi_controller *ctrl = platform_get_drvdata(pdev);
-
- spmi_controller_remove(ctrl);
- kfree(ctrl);
- return 0;
-}
-
-static const struct of_device_id spmi_controller_match_table[] = {
- {
- .compatible = "hisilicon,kirin970-spmi-controller",
- },
- {}
-};
-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 = "hisi_spmi_controller",
- .of_match_table = spmi_controller_match_table,
- },
-};
-
-static int __init spmi_controller_init(void)
-{
- return platform_driver_register(&spmi_controller_driver);
-}
-postcore_initcall(spmi_controller_init);
-
-static void __exit spmi_controller_exit(void)
-{
- platform_driver_unregister(&spmi_controller_driver);
-}
-module_exit(spmi_controller_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION("1.0");
-MODULE_ALIAS("platform:spmi_controller");
diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
deleted file mode 100644
index 21f68a9c2df1..000000000000
--- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
+++ /dev/null
@@ -1,75 +0,0 @@
-# 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 <mchehab+huawei@kernel.org>
-
-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
- drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
-
-properties:
- $nodename:
- pattern: "spmi@[0-9a-f]"
-
- compatible:
- const: hisilicon,kirin970-spmi-controller
-
- reg:
- maxItems: 1
-
- "#address-cells":
- const: 2
-
- "#size-cells":
- const: 0
-
- spmi-channel:
- description: |
- number of the Kirin 970 SPMI channel where the SPMI devices are connected.
-
-required:
- - compatible
- - reg
- - spmi-channel
- - "#address-cells"
- - "#size-cells"
-
-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
- drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
-
-additionalProperties: false
-
-examples:
- - |
- bus {
- #address-cells = <2>;
- #size-cells = <2>;
-
- spmi: spmi@fff24000 {
- compatible = "hisilicon,kirin970-spmi-controller";
- #address-cells = <2>;
- #size-cells = <0>;
- status = "ok";
- reg = <0x0 0xfff24000 0x0 0x1000>;
- spmi-channel = <2>;
-
- pmic@0 {
- reg = <0 0>;
- /* pmic properties */
- };
- };
- };
--
2.29.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 10/13] mfd: hi6421-spmi-pmic: move driver from staging
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 09/13] spmi: hi6421-spmi-pmic: move driver from staging Mauro Carvalho Chehab
@ 2021-01-18 13:28 ` Mauro Carvalho Chehab
2021-01-18 15:12 ` Lee Jones
2021-01-18 15:47 ` Rob Herring
2021-01-18 13:28 ` [PATCH v2 11/13] regulator: hi6421v600-regulator: move it " Mauro Carvalho Chehab
` (2 subsequent siblings)
4 siblings, 2 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, Lee Jones, Mayulong,
Rob Herring, devel, devicetree, linux-kernel
This driver is ready for mainstream. So, move it out of staging.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
.../mfd/hisilicon,hi6421-spmi-pmic.yaml | 133 +++++++
MAINTAINERS | 7 +
drivers/mfd/Kconfig | 15 +
drivers/mfd/Makefile | 1 +
drivers/mfd/hi6421-spmi-pmic.c | 342 ++++++++++++++++++
drivers/staging/hikey9xx/Kconfig | 16 -
drivers/staging/hikey9xx/Makefile | 1 -
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 ------------------
.../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 133 -------
9 files changed, 498 insertions(+), 492 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c
delete mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
new file mode 100644
index 000000000000..f385146d2bd1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -0,0 +1,133 @@
+# 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 <mchehab+huawei@kernel.org>
+
+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
+ drivers/staging/hikey9xx/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#"
+
+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 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-boot-on;
+ };
+
+ ldo4: LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <1725000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-boot-on;
+ };
+
+ ldo9: LDO9 {
+ regulator-name = "ldo9";
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo15: LDO15 {
+ regulator-name = "ldo15";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo16: LDO16 {
+ regulator-name = "ldo16";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ };
+
+ ldo17: LDO17 {
+ regulator-name = "ldo17";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo33: LDO33 {
+ regulator-name = "ldo33";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo34: LDO34 {
+ regulator-name = "ldo34";
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
diff --git a/MAINTAINERS b/MAINTAINERS
index 85e5b6ab57ca..c5b36a58ede5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8006,6 +8006,13 @@ S: Maintained
F: Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
F: drivers/spmi/hisi-spmi-controller.c
+HISILICON SPMI PMIC DRIVER FOR HIKEY 6421v600
+M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+F: drivers/mfd/hi6421-spmi-pmic.c
+
HISILICON STAGING DRIVERS FOR HIKEY 960/970
M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
L: devel@driverdev.osuosl.org
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 8b99a13669bf..c04c2f6be1d9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -509,6 +509,21 @@ config MFD_HI6421_PMIC
menus in order to enable them.
We communicate with the Hi6421 via memory-mapped I/O.
+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
+ 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.
+
config MFD_HI655X_PMIC
tristate "HiSilicon Hi655X series PMU/Codec IC"
depends on ARCH_HISI || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 1780019d2474..7744993c42bc 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -233,6 +233,7 @@ obj-$(CONFIG_MFD_IPAQ_MICRO) += ipaq-micro.o
obj-$(CONFIG_MFD_IQS62X) += iqs62x.o
obj-$(CONFIG_MFD_MENF21BMC) += menf21bmc.o
obj-$(CONFIG_MFD_HI6421_PMIC) += hi6421-pmic-core.o
+obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o
obj-$(CONFIG_MFD_HI655X_PMIC) += hi655x-pmic.o
obj-$(CONFIG_MFD_DLN2) += dln2.o
obj-$(CONFIG_MFD_RT5033) += rt5033.o
diff --git a/drivers/mfd/hi6421-spmi-pmic.c b/drivers/mfd/hi6421-spmi-pmic.c
new file mode 100644
index 000000000000..64b30d263c8d
--- /dev/null
+++ b/drivers/mfd/hi6421-spmi-pmic.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * 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 <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+/* 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
+#define HISI_IRQ_KEY_UP 6
+
+#define HISI_MASK_FIELD 0xFF
+#define HISI_BITS 8
+
+/*define the first group interrupt register number*/
+#define HISI_PMIC_FIRST_GROUP_INT_NUM 2
+
+static const struct mfd_cell hi6421v600_devs[] = {
+ { .name = "hi6421v600-regulator", },
+};
+
+/*
+ * 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.
+ */
+int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg)
+{
+ 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 -ENODEV;
+ }
+
+ ret = spmi_ext_register_readl(pdev, reg, &read_value, 1);
+ if (ret) {
+ pr_err("%s: spmi_ext_register_readl failed!\n", __func__);
+ return ret;
+ }
+ return read_value;
+}
+EXPORT_SYMBOL(hi6421_spmi_pmic_read);
+
+int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val)
+{
+ struct spmi_device *pdev;
+ u32 ret;
+
+ pdev = to_spmi_device(pmic->dev);
+ if (!pdev) {
+ pr_err("%s: pdev get failed!\n", __func__);
+ return -ENODEV;
+ }
+
+ ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1);
+ if (ret)
+ pr_err("%s: spmi_ext_register_writel failed!\n", __func__);
+
+ return ret;
+}
+EXPORT_SYMBOL(hi6421_spmi_pmic_write);
+
+int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg,
+ u32 mask, u32 bits)
+{
+ unsigned long flags;
+ u32 data;
+ int ret;
+
+ spin_lock_irqsave(&pmic->lock, flags);
+ data = hi6421_spmi_pmic_read(pmic, reg) & ~mask;
+ data |= mask & bits;
+ ret = hi6421_spmi_pmic_write(pmic, reg, data);
+ spin_unlock_irqrestore(&pmic->lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(hi6421_spmi_pmic_rmw);
+
+static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
+{
+ struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data;
+ unsigned long pending;
+ int i, offset;
+
+ 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 + SOC_PMIC_IRQ0_ADDR), pending);
+
+ /* 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);
+ }
+
+ if (pending) {
+ for_each_set_bit(offset, &pending, HISI_BITS)
+ generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void hi6421_spmi_irq_mask(struct irq_data *d)
+{
+ struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+ u32 data, offset;
+ unsigned long flags;
+
+ offset = (irqd_to_hwirq(d) >> 3);
+ offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+
+ spin_lock_irqsave(&pmic->lock, flags);
+ data = hi6421_spmi_pmic_read(pmic, offset);
+ data |= (1 << (irqd_to_hwirq(d) & 0x07));
+ hi6421_spmi_pmic_write(pmic, offset, data);
+ spin_unlock_irqrestore(&pmic->lock, flags);
+}
+
+static void hi6421_spmi_irq_unmask(struct irq_data *d)
+{
+ struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
+ u32 data, offset;
+ unsigned long flags;
+
+ offset = (irqd_to_hwirq(d) >> 3);
+ offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+
+ spin_lock_irqsave(&pmic->lock, flags);
+ data = hi6421_spmi_pmic_read(pmic, offset);
+ data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
+ hi6421_spmi_pmic_write(pmic, offset, data);
+ spin_unlock_irqrestore(&pmic->lock, flags);
+}
+
+static struct irq_chip hi6421_spmi_pmu_irqchip = {
+ .name = "hisi-irq",
+ .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 hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct hi6421_spmi_pmic *pmic = d->host_data;
+
+ 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);
+
+ return 0;
+}
+
+static const struct irq_domain_ops hi6421_spmi_domain_ops = {
+ .map = hi6421_spmi_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic)
+{
+ int i, pending;
+
+ 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 < 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",
+ SOC_PMIC_IRQ0_ADDR + i, pending);
+ hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ0_ADDR + i,
+ HISI_MASK_STATE);
+ }
+}
+
+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;
+ unsigned int virq;
+ int ret, i;
+
+ pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
+ if (!pmic)
+ return -ENOMEM;
+
+ spin_lock_init(&pmic->lock);
+
+ pmic->dev = dev;
+
+ pmic->gpio = of_get_gpio(np, 0);
+ if (pmic->gpio < 0)
+ return pmic->gpio;
+
+ if (!gpio_is_valid(pmic->gpio))
+ return -EINVAL;
+
+ 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;
+ }
+
+ pmic->irq = gpio_to_irq(pmic->gpio);
+
+ hi6421_spmi_pmic_irq_prc(pmic);
+
+ 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, HISI_IRQ_NUM, 0,
+ &hi6421_spmi_domain_ops, pmic);
+ if (!pmic->domain) {
+ dev_err(dev, "failed irq domain add simple!\n");
+ ret = -ENODEV;
+ goto irq_malloc;
+ }
+
+ for (i = 0; i < HISI_IRQ_NUM; i++) {
+ virq = irq_create_mapping(pmic->domain, i);
+ if (!virq) {
+ dev_err(dev, "Failed mapping hwirq\n");
+ ret = -ENOSPC;
+ goto irq_malloc;
+ }
+ pmic->irqs[i] = virq;
+ 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 IRQ: error %d\n", ret);
+ goto irq_malloc;
+ }
+
+ 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 children 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)
+ return 0;
+
+ dev_err(dev, "Failed to add child devices: %d\n", ret);
+
+irq_malloc:
+ free_irq(pmic->irq, pmic);
+
+ return ret;
+}
+
+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);
+}
+
+static const struct of_device_id pmic_spmi_id_table[] = {
+ { .compatible = "hisilicon,hi6421-spmi" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
+
+static struct spmi_driver hi6421_spmi_pmic_driver = {
+ .driver = {
+ .name = "hi6421-spmi-pmic",
+ .of_match_table = pmic_spmi_id_table,
+ },
+ .probe = hi6421_spmi_pmic_probe,
+ .remove = hi6421_spmi_pmic_remove,
+};
+module_spmi_driver(hi6421_spmi_pmic_driver);
+
+MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index 69392e42cd0d..1afb8648a2c4 100644
--- a/drivers/staging/hikey9xx/Kconfig
+++ b/drivers/staging/hikey9xx/Kconfig
@@ -1,21 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-# to be placed at drivers/mfd
-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
- 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.
-
# to be placed at drivers/regulator
config REGULATOR_HI6421V600
tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
index 347880fd378f..4d63184e6086 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_MFD_HI6421_SPMI) += hi6421-spmi-pmic.o
obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
deleted file mode 100644
index 64b30d263c8d..000000000000
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ /dev/null
@@ -1,342 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * 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 <linux/delay.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/of.h>
-#include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spmi.h>
-
-/* 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
-#define HISI_IRQ_KEY_UP 6
-
-#define HISI_MASK_FIELD 0xFF
-#define HISI_BITS 8
-
-/*define the first group interrupt register number*/
-#define HISI_PMIC_FIRST_GROUP_INT_NUM 2
-
-static const struct mfd_cell hi6421v600_devs[] = {
- { .name = "hi6421v600-regulator", },
-};
-
-/*
- * 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.
- */
-int hi6421_spmi_pmic_read(struct hi6421_spmi_pmic *pmic, int reg)
-{
- 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 -ENODEV;
- }
-
- ret = spmi_ext_register_readl(pdev, reg, &read_value, 1);
- if (ret) {
- pr_err("%s: spmi_ext_register_readl failed!\n", __func__);
- return ret;
- }
- return read_value;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_read);
-
-int hi6421_spmi_pmic_write(struct hi6421_spmi_pmic *pmic, int reg, u32 val)
-{
- struct spmi_device *pdev;
- u32 ret;
-
- pdev = to_spmi_device(pmic->dev);
- if (!pdev) {
- pr_err("%s: pdev get failed!\n", __func__);
- return -ENODEV;
- }
-
- ret = spmi_ext_register_writel(pdev, reg, (unsigned char *)&val, 1);
- if (ret)
- pr_err("%s: spmi_ext_register_writel failed!\n", __func__);
-
- return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_write);
-
-int hi6421_spmi_pmic_rmw(struct hi6421_spmi_pmic *pmic, int reg,
- u32 mask, u32 bits)
-{
- unsigned long flags;
- u32 data;
- int ret;
-
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, reg) & ~mask;
- data |= mask & bits;
- ret = hi6421_spmi_pmic_write(pmic, reg, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
-
- return ret;
-}
-EXPORT_SYMBOL(hi6421_spmi_pmic_rmw);
-
-static irqreturn_t hi6421_spmi_irq_handler(int irq, void *data)
-{
- struct hi6421_spmi_pmic *pmic = (struct hi6421_spmi_pmic *)data;
- unsigned long pending;
- int i, offset;
-
- 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 + SOC_PMIC_IRQ0_ADDR), pending);
-
- /* 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);
- }
-
- if (pending) {
- for_each_set_bit(offset, &pending, HISI_BITS)
- generic_handle_irq(pmic->irqs[offset + i * HISI_BITS]);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static void hi6421_spmi_irq_mask(struct irq_data *d)
-{
- struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
- u32 data, offset;
- unsigned long flags;
-
- offset = (irqd_to_hwirq(d) >> 3);
- offset += SOC_PMIC_IRQ_MASK_0_ADDR;
-
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, offset);
- data |= (1 << (irqd_to_hwirq(d) & 0x07));
- hi6421_spmi_pmic_write(pmic, offset, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
-}
-
-static void hi6421_spmi_irq_unmask(struct irq_data *d)
-{
- struct hi6421_spmi_pmic *pmic = irq_data_get_irq_chip_data(d);
- u32 data, offset;
- unsigned long flags;
-
- offset = (irqd_to_hwirq(d) >> 3);
- offset += SOC_PMIC_IRQ_MASK_0_ADDR;
-
- spin_lock_irqsave(&pmic->lock, flags);
- data = hi6421_spmi_pmic_read(pmic, offset);
- data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
- hi6421_spmi_pmic_write(pmic, offset, data);
- spin_unlock_irqrestore(&pmic->lock, flags);
-}
-
-static struct irq_chip hi6421_spmi_pmu_irqchip = {
- .name = "hisi-irq",
- .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 hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct hi6421_spmi_pmic *pmic = d->host_data;
-
- 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);
-
- return 0;
-}
-
-static const struct irq_domain_ops hi6421_spmi_domain_ops = {
- .map = hi6421_spmi_irq_map,
- .xlate = irq_domain_xlate_twocell,
-};
-
-static void hi6421_spmi_pmic_irq_prc(struct hi6421_spmi_pmic *pmic)
-{
- int i, pending;
-
- 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 < 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",
- SOC_PMIC_IRQ0_ADDR + i, pending);
- hi6421_spmi_pmic_write(pmic, SOC_PMIC_IRQ0_ADDR + i,
- HISI_MASK_STATE);
- }
-}
-
-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;
- unsigned int virq;
- int ret, i;
-
- pmic = devm_kzalloc(dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
- return -ENOMEM;
-
- spin_lock_init(&pmic->lock);
-
- pmic->dev = dev;
-
- pmic->gpio = of_get_gpio(np, 0);
- if (pmic->gpio < 0)
- return pmic->gpio;
-
- if (!gpio_is_valid(pmic->gpio))
- return -EINVAL;
-
- 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;
- }
-
- pmic->irq = gpio_to_irq(pmic->gpio);
-
- hi6421_spmi_pmic_irq_prc(pmic);
-
- 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, HISI_IRQ_NUM, 0,
- &hi6421_spmi_domain_ops, pmic);
- if (!pmic->domain) {
- dev_err(dev, "failed irq domain add simple!\n");
- ret = -ENODEV;
- goto irq_malloc;
- }
-
- for (i = 0; i < HISI_IRQ_NUM; i++) {
- virq = irq_create_mapping(pmic->domain, i);
- if (!virq) {
- dev_err(dev, "Failed mapping hwirq\n");
- ret = -ENOSPC;
- goto irq_malloc;
- }
- pmic->irqs[i] = virq;
- 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 IRQ: error %d\n", ret);
- goto irq_malloc;
- }
-
- 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 children 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)
- return 0;
-
- dev_err(dev, "Failed to add child devices: %d\n", ret);
-
-irq_malloc:
- free_irq(pmic->irq, pmic);
-
- return ret;
-}
-
-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);
-}
-
-static const struct of_device_id pmic_spmi_id_table[] = {
- { .compatible = "hisilicon,hi6421-spmi" },
- { }
-};
-MODULE_DEVICE_TABLE(of, pmic_spmi_id_table);
-
-static struct spmi_driver hi6421_spmi_pmic_driver = {
- .driver = {
- .name = "hi6421-spmi-pmic",
- .of_match_table = pmic_spmi_id_table,
- },
- .probe = hi6421_spmi_pmic_probe,
- .remove = hi6421_spmi_pmic_remove,
-};
-module_spmi_driver(hi6421_spmi_pmic_driver);
-
-MODULE_DESCRIPTION("HiSilicon Hi6421v600 SPMI PMIC driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
deleted file mode 100644
index f385146d2bd1..000000000000
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ /dev/null
@@ -1,133 +0,0 @@
-# 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 <mchehab+huawei@kernel.org>
-
-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
- drivers/staging/hikey9xx/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#"
-
-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 {
- regulator-name = "ldo3";
- regulator-min-microvolt = <1500000>;
- regulator-max-microvolt = <2000000>;
- regulator-boot-on;
- };
-
- ldo4: LDO4 {
- regulator-name = "ldo4";
- regulator-min-microvolt = <1725000>;
- regulator-max-microvolt = <1900000>;
- regulator-boot-on;
- };
-
- ldo9: LDO9 {
- regulator-name = "ldo9";
- regulator-min-microvolt = <1750000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- };
-
- ldo15: LDO15 {
- regulator-name = "ldo15";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3000000>;
- regulator-always-on;
- };
-
- ldo16: LDO16 {
- regulator-name = "ldo16";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3000000>;
- regulator-boot-on;
- };
-
- ldo17: LDO17 {
- regulator-name = "ldo17";
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <3300000>;
- };
-
- ldo33: LDO33 {
- regulator-name = "ldo33";
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- };
-
- ldo34: LDO34 {
- regulator-name = "ldo34";
- regulator-min-microvolt = <2600000>;
- regulator-max-microvolt = <3300000>;
- };
- };
- };
--
2.29.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 11/13] regulator: hi6421v600-regulator: move it from staging
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 09/13] spmi: hi6421-spmi-pmic: move driver from staging Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 10/13] mfd: " Mauro Carvalho Chehab
@ 2021-01-18 13:28 ` Mauro Carvalho Chehab
2021-01-18 13:54 ` Mark Brown
2021-01-18 13:28 ` [PATCH v2 12/13] dts: hisilicon: add support for USB3 on Hikey 970 Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 13/13] dts: hisilicon: add support for the PMIC found " Mauro Carvalho Chehab
4 siblings, 1 reply; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, Lee Jones,
Liam Girdwood, Mayulong, Rob Herring, devel, devicetree,
linux-kernel
This driver is ready for mainstream. Move it out of staging.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
.../mfd/hisilicon,hi6421-spmi-pmic.yaml | 2 +
MAINTAINERS | 7 +-
drivers/regulator/Kconfig | 8 +
drivers/regulator/Makefile | 1 +
drivers/regulator/hi6421v600-regulator.c | 347 ++++++++++++++++++
drivers/staging/Kconfig | 2 -
drivers/staging/Makefile | 1 -
drivers/staging/hikey9xx/Kconfig | 11 -
drivers/staging/hikey9xx/Makefile | 3 -
drivers/staging/hikey9xx/TODO | 5 -
.../staging/hikey9xx/hi6421v600-regulator.c | 347 ------------------
11 files changed, 359 insertions(+), 375 deletions(-)
create mode 100644 drivers/regulator/hi6421v600-regulator.c
delete mode 100644 drivers/staging/hikey9xx/Kconfig
delete mode 100644 drivers/staging/hikey9xx/Makefile
delete mode 100644 drivers/staging/hikey9xx/TODO
delete mode 100644 drivers/staging/hikey9xx/hi6421v600-regulator.c
diff --git a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
index f385146d2bd1..3b23ad56b31a 100644
--- a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -60,6 +60,8 @@ required:
- reg
- regulators
+additionalProperties: false
+
examples:
- |
/* pmic properties */
diff --git a/MAINTAINERS b/MAINTAINERS
index c5b36a58ede5..138798bbb32e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8012,12 +8012,7 @@ L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
F: drivers/mfd/hi6421-spmi-pmic.c
-
-HISILICON STAGING DRIVERS FOR HIKEY 960/970
-M: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-L: devel@driverdev.osuosl.org
-S: Maintained
-F: drivers/staging/hikey9xx/
+F: drivers/regulator/hi6421v600-regulator.c
HISILICON TRUE RANDOM NUMBER GENERATOR V2 SUPPORT
M: Zaibo Xu <xuzaibo@huawei.com>
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 020a00d6696b..ca983e5a7a4d 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -394,6 +394,14 @@ config REGULATOR_HI655X
This driver provides support for the voltage regulators of the
Hisilicon Hi655x PMIC device.
+config REGULATOR_HI6421V600
+ tristate "HiSilicon Hi6421v600 PMIC voltage regulator support"
+ depends on MFD_HI6421_SPMI && 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.
+
config REGULATOR_ISL9305
tristate "Intersil ISL9305 regulator"
depends on I2C
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6ebae516258e..45d1883de54b 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_REGULATOR_FAN53880) += fan53880.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
+obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
diff --git a/drivers/regulator/hi6421v600-regulator.c b/drivers/regulator/hi6421v600-regulator.c
new file mode 100644
index 000000000000..a8a268f326f5
--- /dev/null
+++ b/drivers/regulator/hi6421v600-regulator.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Device driver for regulators in Hisi IC
+//
+// Copyright (c) 2013 Linaro Ltd.
+// Copyright (c) 2011 Hisilicon.
+//
+// Guodong Xu <guodong.xu@linaro.org>
+//
+// 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 <linux/delay.h>
+#include <linux/mfd/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/spmi.h>
+
+struct hi6421_spmi_reg_info {
+ struct regulator_desc desc;
+ struct hi6421_spmi_pmic *pmic;
+ u8 eco_mode_mask;
+ u32 eco_uA;
+
+ /* Serialize regulator enable logic */
+ struct mutex enable_mutex;
+};
+
+static const unsigned int ldo3_voltages[] = {
+ 1500000, 1550000, 1600000, 1650000,
+ 1700000, 1725000, 1750000, 1775000,
+ 1800000, 1825000, 1850000, 1875000,
+ 1900000, 1925000, 1950000, 2000000
+};
+
+static const unsigned int ldo4_voltages[] = {
+ 1725000, 1750000, 1775000, 1800000,
+ 1825000, 1850000, 1875000, 1900000
+};
+
+static const unsigned int ldo9_voltages[] = {
+ 1750000, 1800000, 1825000, 2800000,
+ 2850000, 2950000, 3000000, 3300000
+};
+
+static const unsigned int ldo15_voltages[] = {
+ 1800000, 1850000, 2400000, 2600000,
+ 2700000, 2850000, 2950000, 3000000
+};
+
+static const unsigned int ldo17_voltages[] = {
+ 2500000, 2600000, 2700000, 2800000,
+ 3000000, 3100000, 3200000, 3300000
+};
+
+static const unsigned int ldo34_voltages[] = {
+ 2600000, 2700000, 2800000, 2900000,
+ 3000000, 3100000, 3200000, 3300000
+};
+
+/*
+ * _id - LDO id name string
+ * _match - of match name string
+ * v_table - voltage table
+ * vreg - voltage select register
+ * vmask - voltage select mask
+ * ereg - enable register
+ * emask - enable mask
+ * odelay - off/on delay time in uS
+ * ecomask - eco mode mask
+ * ecoamp - eco mode load uppler limit in uA
+ */
+#define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \
+ odelay, etime, ecomask, ecoamp) \
+ [HI6421V600_##_id] = { \
+ .desc = { \
+ .name = #_id, \
+ .of_match = of_match_ptr(#_id), \
+ .regulators_node = of_match_ptr("regulators"), \
+ .ops = &hi6421_spmi_ldo_rops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = HI6421V600_##_id, \
+ .owner = THIS_MODULE, \
+ .volt_table = vtable, \
+ .n_voltages = ARRAY_SIZE(vtable), \
+ .vsel_mask = (1 << (ARRAY_SIZE(vtable) - 1)) - 1, \
+ .vsel_reg = vreg, \
+ .enable_reg = ereg, \
+ .enable_mask = emask, \
+ .enable_time = etime, \
+ .ramp_delay = etime, \
+ .off_on_delay = odelay, \
+ }, \
+ .eco_mode_mask = ecomask, \
+ .eco_uA = ecoamp, \
+ }
+
+static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
+{
+ struct hi6421_spmi_reg_info *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);
+
+ return ((reg_val & rdev->desc->enable_mask) != 0);
+}
+
+static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_pmic *pmic = sreg->pmic;
+ int ret;
+
+ /* cannot enable more than one regulator at one time */
+ mutex_lock(&sreg->enable_mutex);
+ usleep_range(HISI_REGS_ENA_PROTECT_TIME,
+ HISI_REGS_ENA_PROTECT_TIME + 1000);
+
+ /* set enable register */
+ ret = hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
+ rdev->desc->enable_mask,
+ rdev->desc->enable_mask);
+
+ mutex_unlock(&sreg->enable_mutex);
+
+ return ret;
+}
+
+static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_pmic *pmic = sreg->pmic;
+
+ /* set enable register to 0 */
+ return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
+ rdev->desc->enable_mask, 0);
+}
+
+static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_pmic *pmic = sreg->pmic;
+ u32 reg_val;
+
+ /* get voltage selector */
+ reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg);
+
+ return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1);
+}
+
+static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
+ unsigned int selector)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_pmic *pmic = sreg->pmic;
+ u32 reg_val;
+
+ if (unlikely(selector >= rdev->desc->n_voltages))
+ return -EINVAL;
+
+ reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
+
+ /* set voltage selector */
+ return hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg,
+ rdev->desc->vsel_mask, reg_val);
+}
+
+static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
+{
+ struct hi6421_spmi_reg_info *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);
+
+ if (reg_val & sreg->eco_mode_mask)
+ return REGULATOR_MODE_IDLE;
+
+ return REGULATOR_MODE_NORMAL;
+}
+
+static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+ struct hi6421_spmi_pmic *pmic = sreg->pmic;
+ u32 val;
+
+ switch (mode) {
+ case REGULATOR_MODE_NORMAL:
+ val = 0;
+ break;
+ case REGULATOR_MODE_IDLE:
+ val = sreg->eco_mode_mask << (ffs(sreg->eco_mode_mask) - 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set mode */
+ return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
+ sreg->eco_mode_mask, val);
+}
+
+static unsigned int
+hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV,
+ int load_uA)
+{
+ struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
+
+ if (load_uA || ((unsigned int)load_uA > sreg->eco_uA))
+ return REGULATOR_MODE_NORMAL;
+
+ return REGULATOR_MODE_IDLE;
+}
+
+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,
+ .list_voltage = regulator_list_voltage_table,
+ .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,
+};
+
+/* HI6421v600 regulators with known registers */
+enum hi6421_spmi_regulator_id {
+ HI6421V600_LDO3,
+ HI6421V600_LDO4,
+ HI6421V600_LDO9,
+ HI6421V600_LDO15,
+ HI6421V600_LDO16,
+ HI6421V600_LDO17,
+ HI6421V600_LDO33,
+ HI6421V600_LDO34,
+};
+
+static struct hi6421_spmi_reg_info regulator_info[] = {
+ HI6421V600_LDO(LDO3, ldo3_voltages,
+ 0x16, 0x01, 0x51,
+ 20000, 120,
+ 0, 0),
+ HI6421V600_LDO(LDO4, ldo4_voltages,
+ 0x17, 0x01, 0x52,
+ 20000, 120,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO9, ldo9_voltages,
+ 0x1c, 0x01, 0x57,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO15, ldo15_voltages,
+ 0x21, 0x01, 0x5c,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO16, ldo15_voltages,
+ 0x22, 0x01, 0x5d,
+ 20000, 360,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO17, ldo17_voltages,
+ 0x23, 0x01, 0x5e,
+ 20000, 120,
+ 0x10, 10000),
+ HI6421V600_LDO(LDO33, ldo17_voltages,
+ 0x32, 0x01, 0x6d,
+ 20000, 120,
+ 0, 0),
+ HI6421V600_LDO(LDO34, ldo34_voltages,
+ 0x33, 0x01, 0x6e,
+ 20000, 120,
+ 0, 0),
+};
+
+static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
+{
+ struct device *pmic_dev = pdev->dev.parent;
+ struct regulator_config config = { };
+ struct hi6421_spmi_reg_info *sreg;
+ struct hi6421_spmi_reg_info *info;
+ struct device *dev = &pdev->dev;
+ struct hi6421_spmi_pmic *pmic;
+ struct regulator_dev *rdev;
+ int i;
+
+ /*
+ * 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;
+
+ sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
+ if (!sreg)
+ return -ENOMEM;
+
+ sreg->pmic = pmic;
+ mutex_init(&sreg->enable_mutex);
+
+ for (i = 0; i < ARRAY_SIZE(regulator_info); i++) {
+ /* assign per-regulator data */
+ info = ®ulator_info[i];
+
+ config.dev = pdev->dev.parent;
+ config.driver_data = sreg;
+
+ rdev = devm_regulator_register(dev, &info->desc, &config);
+ if (IS_ERR(rdev)) {
+ dev_err(dev, "failed to register %s\n", sreg->desc.name);
+ return PTR_ERR(rdev);
+ }
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id hi6421_spmi_regulator_table[] = {
+ { .name = "hi6421v600-regulator" },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, hi6421_spmi_regulator_table);
+
+static struct platform_driver hi6421_spmi_regulator_driver = {
+ .id_table = hi6421_spmi_regulator_table,
+ .driver = {
+ .name = "hi6421v600-regulator",
+ },
+ .probe = hi6421_spmi_regulator_probe,
+};
+module_platform_driver(hi6421_spmi_regulator_driver);
+
+MODULE_DESCRIPTION("Hi6421v600 SPMI regulator driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 2d0310448eba..e6c831c6cccc 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -116,6 +116,4 @@ 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 757a892ab5b9..a3b1fd0622f9 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -48,4 +48,3 @@ 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
deleted file mode 100644
index 1afb8648a2c4..000000000000
--- a/drivers/staging/hikey9xx/Kconfig
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-# to be placed at drivers/regulator
-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.
- This is used on Kirin 3670 boards, like HiKey 970.
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
deleted file mode 100644
index 4d63184e6086..000000000000
--- a/drivers/staging/hikey9xx/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
diff --git a/drivers/staging/hikey9xx/TODO b/drivers/staging/hikey9xx/TODO
deleted file mode 100644
index 65e7996a3066..000000000000
--- a/drivers/staging/hikey9xx/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-ToDo list:
-
-- Port other drivers needed by Hikey 960/970;
-- Test drivers on Hikey 960;
-- Validate device tree bindings.
diff --git a/drivers/staging/hikey9xx/hi6421v600-regulator.c b/drivers/staging/hikey9xx/hi6421v600-regulator.c
deleted file mode 100644
index a8a268f326f5..000000000000
--- a/drivers/staging/hikey9xx/hi6421v600-regulator.c
+++ /dev/null
@@ -1,347 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// Device driver for regulators in Hisi IC
-//
-// Copyright (c) 2013 Linaro Ltd.
-// Copyright (c) 2011 Hisilicon.
-//
-// Guodong Xu <guodong.xu@linaro.org>
-//
-// 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 <linux/delay.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/driver.h>
-#include <linux/spmi.h>
-
-struct hi6421_spmi_reg_info {
- struct regulator_desc desc;
- struct hi6421_spmi_pmic *pmic;
- u8 eco_mode_mask;
- u32 eco_uA;
-
- /* Serialize regulator enable logic */
- struct mutex enable_mutex;
-};
-
-static const unsigned int ldo3_voltages[] = {
- 1500000, 1550000, 1600000, 1650000,
- 1700000, 1725000, 1750000, 1775000,
- 1800000, 1825000, 1850000, 1875000,
- 1900000, 1925000, 1950000, 2000000
-};
-
-static const unsigned int ldo4_voltages[] = {
- 1725000, 1750000, 1775000, 1800000,
- 1825000, 1850000, 1875000, 1900000
-};
-
-static const unsigned int ldo9_voltages[] = {
- 1750000, 1800000, 1825000, 2800000,
- 2850000, 2950000, 3000000, 3300000
-};
-
-static const unsigned int ldo15_voltages[] = {
- 1800000, 1850000, 2400000, 2600000,
- 2700000, 2850000, 2950000, 3000000
-};
-
-static const unsigned int ldo17_voltages[] = {
- 2500000, 2600000, 2700000, 2800000,
- 3000000, 3100000, 3200000, 3300000
-};
-
-static const unsigned int ldo34_voltages[] = {
- 2600000, 2700000, 2800000, 2900000,
- 3000000, 3100000, 3200000, 3300000
-};
-
-/*
- * _id - LDO id name string
- * _match - of match name string
- * v_table - voltage table
- * vreg - voltage select register
- * vmask - voltage select mask
- * ereg - enable register
- * emask - enable mask
- * odelay - off/on delay time in uS
- * ecomask - eco mode mask
- * ecoamp - eco mode load uppler limit in uA
- */
-#define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \
- odelay, etime, ecomask, ecoamp) \
- [HI6421V600_##_id] = { \
- .desc = { \
- .name = #_id, \
- .of_match = of_match_ptr(#_id), \
- .regulators_node = of_match_ptr("regulators"), \
- .ops = &hi6421_spmi_ldo_rops, \
- .type = REGULATOR_VOLTAGE, \
- .id = HI6421V600_##_id, \
- .owner = THIS_MODULE, \
- .volt_table = vtable, \
- .n_voltages = ARRAY_SIZE(vtable), \
- .vsel_mask = (1 << (ARRAY_SIZE(vtable) - 1)) - 1, \
- .vsel_reg = vreg, \
- .enable_reg = ereg, \
- .enable_mask = emask, \
- .enable_time = etime, \
- .ramp_delay = etime, \
- .off_on_delay = odelay, \
- }, \
- .eco_mode_mask = ecomask, \
- .eco_uA = ecoamp, \
- }
-
-static int hi6421_spmi_regulator_is_enabled(struct regulator_dev *rdev)
-{
- struct hi6421_spmi_reg_info *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);
-
- return ((reg_val & rdev->desc->enable_mask) != 0);
-}
-
-static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- int ret;
-
- /* cannot enable more than one regulator at one time */
- mutex_lock(&sreg->enable_mutex);
- usleep_range(HISI_REGS_ENA_PROTECT_TIME,
- HISI_REGS_ENA_PROTECT_TIME + 1000);
-
- /* set enable register */
- ret = hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- rdev->desc->enable_mask,
- rdev->desc->enable_mask);
-
- mutex_unlock(&sreg->enable_mutex);
-
- return ret;
-}
-
-static int hi6421_spmi_regulator_disable(struct regulator_dev *rdev)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
-
- /* set enable register to 0 */
- return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- rdev->desc->enable_mask, 0);
-}
-
-static int hi6421_spmi_regulator_get_voltage_sel(struct regulator_dev *rdev)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 reg_val;
-
- /* get voltage selector */
- reg_val = hi6421_spmi_pmic_read(pmic, rdev->desc->vsel_reg);
-
- return (reg_val & rdev->desc->vsel_mask) >> (ffs(rdev->desc->vsel_mask) - 1);
-}
-
-static int hi6421_spmi_regulator_set_voltage_sel(struct regulator_dev *rdev,
- unsigned int selector)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 reg_val;
-
- if (unlikely(selector >= rdev->desc->n_voltages))
- return -EINVAL;
-
- reg_val = selector << (ffs(rdev->desc->vsel_mask) - 1);
-
- /* set voltage selector */
- return hi6421_spmi_pmic_rmw(pmic, rdev->desc->vsel_reg,
- rdev->desc->vsel_mask, reg_val);
-}
-
-static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
-{
- struct hi6421_spmi_reg_info *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);
-
- if (reg_val & sreg->eco_mode_mask)
- return REGULATOR_MODE_IDLE;
-
- return REGULATOR_MODE_NORMAL;
-}
-
-static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
- unsigned int mode)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
- struct hi6421_spmi_pmic *pmic = sreg->pmic;
- u32 val;
-
- switch (mode) {
- case REGULATOR_MODE_NORMAL:
- val = 0;
- break;
- case REGULATOR_MODE_IDLE:
- val = sreg->eco_mode_mask << (ffs(sreg->eco_mode_mask) - 1);
- break;
- default:
- return -EINVAL;
- }
-
- /* set mode */
- return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
- sreg->eco_mode_mask, val);
-}
-
-static unsigned int
-hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
- int input_uV, int output_uV,
- int load_uA)
-{
- struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
-
- if (load_uA || ((unsigned int)load_uA > sreg->eco_uA))
- return REGULATOR_MODE_NORMAL;
-
- return REGULATOR_MODE_IDLE;
-}
-
-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,
- .list_voltage = regulator_list_voltage_table,
- .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,
-};
-
-/* HI6421v600 regulators with known registers */
-enum hi6421_spmi_regulator_id {
- HI6421V600_LDO3,
- HI6421V600_LDO4,
- HI6421V600_LDO9,
- HI6421V600_LDO15,
- HI6421V600_LDO16,
- HI6421V600_LDO17,
- HI6421V600_LDO33,
- HI6421V600_LDO34,
-};
-
-static struct hi6421_spmi_reg_info regulator_info[] = {
- HI6421V600_LDO(LDO3, ldo3_voltages,
- 0x16, 0x01, 0x51,
- 20000, 120,
- 0, 0),
- HI6421V600_LDO(LDO4, ldo4_voltages,
- 0x17, 0x01, 0x52,
- 20000, 120,
- 0x10, 10000),
- HI6421V600_LDO(LDO9, ldo9_voltages,
- 0x1c, 0x01, 0x57,
- 20000, 360,
- 0x10, 10000),
- HI6421V600_LDO(LDO15, ldo15_voltages,
- 0x21, 0x01, 0x5c,
- 20000, 360,
- 0x10, 10000),
- HI6421V600_LDO(LDO16, ldo15_voltages,
- 0x22, 0x01, 0x5d,
- 20000, 360,
- 0x10, 10000),
- HI6421V600_LDO(LDO17, ldo17_voltages,
- 0x23, 0x01, 0x5e,
- 20000, 120,
- 0x10, 10000),
- HI6421V600_LDO(LDO33, ldo17_voltages,
- 0x32, 0x01, 0x6d,
- 20000, 120,
- 0, 0),
- HI6421V600_LDO(LDO34, ldo34_voltages,
- 0x33, 0x01, 0x6e,
- 20000, 120,
- 0, 0),
-};
-
-static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
-{
- struct device *pmic_dev = pdev->dev.parent;
- struct regulator_config config = { };
- struct hi6421_spmi_reg_info *sreg;
- struct hi6421_spmi_reg_info *info;
- struct device *dev = &pdev->dev;
- struct hi6421_spmi_pmic *pmic;
- struct regulator_dev *rdev;
- int i;
-
- /*
- * 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;
-
- sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
- if (!sreg)
- return -ENOMEM;
-
- sreg->pmic = pmic;
- mutex_init(&sreg->enable_mutex);
-
- for (i = 0; i < ARRAY_SIZE(regulator_info); i++) {
- /* assign per-regulator data */
- info = ®ulator_info[i];
-
- config.dev = pdev->dev.parent;
- config.driver_data = sreg;
-
- rdev = devm_regulator_register(dev, &info->desc, &config);
- if (IS_ERR(rdev)) {
- dev_err(dev, "failed to register %s\n", sreg->desc.name);
- return PTR_ERR(rdev);
- }
- }
-
- return 0;
-}
-
-static const struct platform_device_id hi6421_spmi_regulator_table[] = {
- { .name = "hi6421v600-regulator" },
- {},
-};
-MODULE_DEVICE_TABLE(platform, hi6421_spmi_regulator_table);
-
-static struct platform_driver hi6421_spmi_regulator_driver = {
- .id_table = hi6421_spmi_regulator_table,
- .driver = {
- .name = "hi6421v600-regulator",
- },
- .probe = hi6421_spmi_regulator_probe,
-};
-module_platform_driver(hi6421_spmi_regulator_driver);
-
-MODULE_DESCRIPTION("Hi6421v600 SPMI regulator driver");
-MODULE_LICENSE("GPL v2");
-
--
2.29.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 12/13] dts: hisilicon: add support for USB3 on Hikey 970
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
` (2 preceding siblings ...)
2021-01-18 13:28 ` [PATCH v2 11/13] regulator: hi6421v600-regulator: move it " Mauro Carvalho Chehab
@ 2021-01-18 13:28 ` Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 13/13] dts: hisilicon: add support for the PMIC found " Mauro Carvalho Chehab
4 siblings, 0 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Rob Herring, Wei Xu, devicetree,
linux-arm-kernel, linux-kernel
Add the USB3 bindings for Kirin 970 phy and Hikey 970 board.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
.../boot/dts/hisilicon/hi3670-hikey970.dts | 102 ++++++++++++++++++
arch/arm64/boot/dts/hisilicon/hi3670.dtsi | 58 ++++++++++
2 files changed, 160 insertions(+)
diff --git a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
index 7f9f9886c349..fe6600dbad61 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
@@ -69,6 +69,29 @@ wlan_en: wlan-en-1-8v {
startup-delay-us = <70000>;
enable-active-high;
};
+ hikey_usbhub: hikey_usbhub {
+ compatible = "hisilicon,kirin970_hikey_usbhub";
+
+ typec-vbus-gpios = <&gpio26 1 0>;
+ otg-switch-gpios = <&gpio4 2 0>;
+ hub_reset_en_gpio = <&gpio0 3 0>;
+ hub-vdd-supply = <&ldo17>;
+ usb-role-switch;
+
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hikey_usb_ep0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&dwc3_role_switch>;
+ };
+ hikey_usb_ep1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&rt1711h_ep>;
+ };
+ };
+ };
};
/*
@@ -446,3 +469,82 @@ &uart6 {
label = "LS-UART1";
status = "okay";
};
+
+&i2c1 {
+ status = "okay";
+
+ rt1711h: rt1711h@4e {
+ compatible = "richtek,rt1711h";
+ reg = <0x4e>;
+ status = "okay";
+ interrupt-parent = <&gpio27>;
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb_cfg_func>;
+
+ usb_con: connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+ data-role = "dual";
+ power-role = "dual";
+ try-power-role = "sink";
+ source-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)>;
+ sink-pdos = <PDO_FIXED(5000, 500, PDO_FIXED_USB_COMM)
+ PDO_VAR(5000, 5000, 1000)>;
+ op-sink-microwatt = <10000000>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@1 {
+ reg = <1>;
+ usb_con_ss: endpoint {
+ remote-endpoint = <&dwc3_ss>;
+ };
+ };
+ };
+ };
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rt1711h_ep: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hikey_usb_ep1>;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ /* USB HUB is on this bus at address 0x44 */
+ status = "okay";
+};
+
+&dwc3 { /* USB */
+ dr_mode = "otg";
+ maximum-speed = "super-speed";
+ phy_type = "utmi";
+ snps,dis-del-phy-power-chg-quirk;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_u3_susphy_quirk;
+ snps,tx_de_emphasis_quirk;
+ snps,tx_de_emphasis = <1>;
+ snps,dis-split-quirk;
+ snps,gctl-reset-quirk;
+ usb-role-switch;
+ role-switch-default-mode = "host";
+ port {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dwc3_role_switch: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&hikey_usb_ep0>;
+ };
+
+ dwc3_ss: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&usb_con_ss>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3670.dtsi b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
index 36d3ae493c7d..d44af856f90d 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3670.dtsi
@@ -8,6 +8,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/hi3670-clock.h>
+#include <dt-bindings/usb/pd.h>
/ {
compatible = "hisilicon,hi3670";
@@ -786,5 +787,62 @@ i2c4: i2c@fdf0d000 {
pinctrl-0 = <&i2c4_pmx_func &i2c4_cfg_func>;
status = "disabled";
};
+
+ usb3_otg_bc: usb3_otg_bc@ff200000 {
+ compatible = "syscon", "simple-mfd";
+ reg = <0x0 0xff200000 0x0 0x1000>;
+
+ 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,eye-diagram-param = <0xFDFEE4>;
+ hisilicon,tx-vboost-lvl = <0x5>;
+
+ phy-supply = <&ldo17>;
+ };
+ };
+
+ usb31_misc_rst: usb31_misc_rst_controller {
+ compatible = "hisilicon,hi3660-reset";
+ #reset-cells = <2>;
+ hisi,rst-syscon = <&usb3_otg_bc>;
+ };
+
+ usb3: hisi_dwc3 {
+ compatible = "hisilicon,hi3670-dwc3";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ clocks = <&crg_ctrl HI3670_CLK_GATE_ABB_USB>,
+ <&crg_ctrl HI3670_HCLK_GATE_USB3OTG>,
+ <&crg_ctrl HI3670_CLK_GATE_USB3OTG_REF>,
+ <&crg_ctrl HI3670_ACLK_GATE_USB3DVFS>;
+ clock-names = "clk_gate_abb_usb",
+ "hclk_gate_usb3otg",
+ "clk_gate_usb3otg_ref",
+ "aclk_gate_usb3dvfs";
+
+ assigned-clocks = <&crg_ctrl HI3670_ACLK_GATE_USB3DVFS>;
+ assigned-clock-rates = <238000000>;
+ resets = <&crg_rst 0x90 6>,
+ <&crg_rst 0x90 7>,
+ <&usb31_misc_rst 0xA0 8>,
+ <&usb31_misc_rst 0xA0 9>;
+
+ dwc3: dwc3@ff100000 {
+ compatible = "snps,dwc3";
+ reg = <0x0 0xff100000 0x0 0x100000>;
+
+ interrupts = <0 159 IRQ_TYPE_LEVEL_HIGH>,
+ <0 161 IRQ_TYPE_LEVEL_HIGH>;
+
+ phys = <&usb_phy>;
+ phy-names = "usb3-phy";
+ };
+ };
};
};
--
2.29.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v2 13/13] dts: hisilicon: add support for the PMIC found on Hikey 970
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
` (3 preceding siblings ...)
2021-01-18 13:28 ` [PATCH v2 12/13] dts: hisilicon: add support for USB3 on Hikey 970 Mauro Carvalho Chehab
@ 2021-01-18 13:28 ` Mauro Carvalho Chehab
4 siblings, 0 replies; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 13:28 UTC (permalink / raw)
To: Mark Brown
Cc: Mauro Carvalho Chehab, Rob Herring, Wei Xu, devicetree,
linux-arm-kernel, linux-kernel
Add a device tree for the HiSilicon 6421v600 SPMI PMIC, used
on HiKey970 board.
As we now have support for it, change the fixed regulators
used by the SD I/O to use the proper LDO supplies.
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
.../boot/dts/hisilicon/hi3670-hikey970.dts | 22 +----
.../boot/dts/hisilicon/hikey970-pmic.dtsi | 87 +++++++++++++++++++
2 files changed, 90 insertions(+), 19 deletions(-)
create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
diff --git a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
index fe6600dbad61..1f221cb97690 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
@@ -12,6 +12,7 @@
#include "hi3670.dtsi"
#include "hikey970-pinctrl.dtsi"
+#include "hikey970-pmic.dtsi"
/ {
model = "HiKey970";
@@ -39,23 +40,6 @@ memory@0 {
reg = <0x0 0x0 0x0 0x0>;
};
- sd_1v8: regulator-1v8 {
- compatible = "regulator-fixed";
- regulator-name = "fixed-1.8V";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- };
-
- sd_3v3: regulator-3v3 {
- compatible = "regulator-fixed";
- regulator-name = "fixed-3.3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
- regulator-always-on;
- };
-
wlan_en: wlan-en-1-8v {
compatible = "regulator-fixed";
regulator-name = "wlan-en-regulator";
@@ -425,8 +409,8 @@ &dwmmc1 {
pinctrl-0 = <&sd_pmx_func
&sd_clk_cfg_func
&sd_cfg_func>;
- vmmc-supply = <&sd_3v3>;
- vqmmc-supply = <&sd_1v8>;
+ vmmc-supply = <&ldo16>;
+ vqmmc-supply = <&ldo9>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi b/arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
new file mode 100644
index 000000000000..8cf45b962fea
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for Hi6421v600 SPMI PMIC used at the HiKey970 Development Board
+ *
+ * Copyright (C) 2020, Huawei Tech. Co., Ltd.
+ */
+
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+ spmi: spmi@fff24000 {
+ compatible = "hisilicon,kirin970-spmi-controller";
+ #address-cells = <2>;
+ #size-cells = <0>;
+ status = "okay";
+ reg = <0x0 0xfff24000 0x0 0x1000>;
+ spmi-channel = <2>;
+
+ pmic: pmic@0 {
+ compatible = "hisilicon,hi6421-spmi";
+ reg = <0 SPMI_USID>;
+
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ gpios = <&gpio28 0 0>;
+
+ regulators {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ldo3: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-boot-on;
+ };
+
+ ldo4: LDO4 { /* 40 PIN */
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <1725000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-boot-on;
+ };
+
+ ldo9: LDO9 { /* SDCARD I/O */
+ regulator-name = "ldo9";
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo15: LDO15 { /* UFS */
+ regulator-name = "ldo15";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ };
+
+ ldo16: LDO16 { /* SD */
+ regulator-name = "ldo16";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ };
+
+ ldo17: LDO17 {
+ regulator-name = "ldo17";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo33: LDO33 { /* PEX8606 */
+ regulator-name = "ldo33";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ };
+
+ ldo34: LDO34 { /* GPS AUX IN VDD */
+ regulator-name = "ldo34";
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+ };
+};
--
2.29.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v2 11/13] regulator: hi6421v600-regulator: move it from staging
2021-01-18 13:28 ` [PATCH v2 11/13] regulator: hi6421v600-regulator: move it " Mauro Carvalho Chehab
@ 2021-01-18 13:54 ` Mark Brown
2021-01-18 16:02 ` Mauro Carvalho Chehab
0 siblings, 1 reply; 13+ messages in thread
From: Mark Brown @ 2021-01-18 13:54 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Greg Kroah-Hartman, Lee Jones, Liam Girdwood, Mayulong,
Rob Herring, devel, devicetree, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2813 bytes --]
On Mon, Jan 18, 2021 at 02:28:12PM +0100, Mauro Carvalho Chehab wrote:
> index f385146d2bd1..3b23ad56b31a 100644
> --- a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> @@ -60,6 +60,8 @@ required:
> - reg
> - regulators
>
> +additionalProperties: false
> +
> examples:
> - |
> /* pmic properties */
Why is this part of this patch?
> +// SPDX-License-Identifier: GPL-2.0
> +//
> +// Device driver for regulators in Hisi IC
> +//
> +// Copyright (c) 2013 Linaro Ltd.
> +// Copyright (c) 2011 Hisilicon.
> +//
This looks like it needs an update.
> +// 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.
This boilerplate can be removed.
> +static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
> +{
> + struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
> + struct hi6421_spmi_pmic *pmic = sreg->pmic;
> + int ret;
> +
> + /* cannot enable more than one regulator at one time */
> + mutex_lock(&sreg->enable_mutex);
> + usleep_range(HISI_REGS_ENA_PROTECT_TIME,
> + HISI_REGS_ENA_PROTECT_TIME + 1000);
> +
> + /* set enable register */
> + ret = hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
> + rdev->desc->enable_mask,
> + rdev->desc->enable_mask);
If for some reason the PMIC is sufficiently fragile to need a delay
between enables it's not clear why the driver is doing it before
enabling rather than after, presumably there's issues with the regulator
ramping up and stabalising its output
> + /* set enable register to 0 */
> + return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
> + rdev->desc->enable_mask, 0);
I'm not sure all these comments are adding anything.
> + if (unlikely(selector >= rdev->desc->n_voltages))
> + return -EINVAL;
This should not be a hot path that needs an unlikely() annotation.
> +static unsigned int
> +hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
> + int input_uV, int output_uV,
> + int load_uA)
> +{
> + struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
> +
> + if (load_uA || ((unsigned int)load_uA > sreg->eco_uA))
> + return REGULATOR_MODE_NORMAL;
This means that for *any* load at all we select NORMAL - I'm not
convinced this is intentional?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 10/13] mfd: hi6421-spmi-pmic: move driver from staging
2021-01-18 13:28 ` [PATCH v2 10/13] mfd: " Mauro Carvalho Chehab
@ 2021-01-18 15:12 ` Lee Jones
2021-01-18 15:32 ` Mauro Carvalho Chehab
2021-01-18 15:47 ` Rob Herring
1 sibling, 1 reply; 13+ messages in thread
From: Lee Jones @ 2021-01-18 15:12 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Mark Brown, Greg Kroah-Hartman, Mayulong, Rob Herring, devel,
devicetree, linux-kernel
On Mon, 18 Jan 2021, Mauro Carvalho Chehab wrote:
> This driver is ready for mainstream. So, move it out of staging.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
> .../mfd/hisilicon,hi6421-spmi-pmic.yaml | 133 +++++++
> MAINTAINERS | 7 +
> drivers/mfd/Kconfig | 15 +
> drivers/mfd/Makefile | 1 +
> drivers/mfd/hi6421-spmi-pmic.c | 342 ++++++++++++++++++
> drivers/staging/hikey9xx/Kconfig | 16 -
> drivers/staging/hikey9xx/Makefile | 1 -
> drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 ------------------
> .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 133 -------
> 9 files changed, 498 insertions(+), 492 deletions(-)
Could you please resubmit this will the correct flags.
I believe it's the `git format-patch` -M flag that you want.
--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 10/13] mfd: hi6421-spmi-pmic: move driver from staging
2021-01-18 15:12 ` Lee Jones
@ 2021-01-18 15:32 ` Mauro Carvalho Chehab
2021-01-18 15:50 ` Lee Jones
0 siblings, 1 reply; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 15:32 UTC (permalink / raw)
To: Lee Jones
Cc: Mark Brown, Greg Kroah-Hartman, Mayulong, Rob Herring, devel,
devicetree, linux-kernel
Em Mon, 18 Jan 2021 15:12:27 +0000
Lee Jones <lee.jones@linaro.org> escreveu:
> On Mon, 18 Jan 2021, Mauro Carvalho Chehab wrote:
>
> > This driver is ready for mainstream. So, move it out of staging.
> >
> > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > ---
> > .../mfd/hisilicon,hi6421-spmi-pmic.yaml | 133 +++++++
> > MAINTAINERS | 7 +
> > drivers/mfd/Kconfig | 15 +
> > drivers/mfd/Makefile | 1 +
> > drivers/mfd/hi6421-spmi-pmic.c | 342 ++++++++++++++++++
> > drivers/staging/hikey9xx/Kconfig | 16 -
> > drivers/staging/hikey9xx/Makefile | 1 -
> > drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 ------------------
> > .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 133 -------
> > 9 files changed, 498 insertions(+), 492 deletions(-)
>
> Could you please resubmit this will the correct flags.
>
> I believe it's the `git format-patch` -M flag that you want.
As explained at patch 00/13, this was intentionally generated with
--no-merges, in order to allow reviewers to view the entire source
code at the patch.
Anyway, I'll re-send the series with -M, as it makes easier to merge,
if everything is ok.
Thanks,
Mauro
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 10/13] mfd: hi6421-spmi-pmic: move driver from staging
2021-01-18 13:28 ` [PATCH v2 10/13] mfd: " Mauro Carvalho Chehab
2021-01-18 15:12 ` Lee Jones
@ 2021-01-18 15:47 ` Rob Herring
1 sibling, 0 replies; 13+ messages in thread
From: Rob Herring @ 2021-01-18 15:47 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Mayulong, Rob Herring, Mark Brown, Lee Jones, devicetree,
Greg Kroah-Hartman, devel, linux-kernel
On Mon, 18 Jan 2021 14:28:11 +0100, Mauro Carvalho Chehab wrote:
> This driver is ready for mainstream. So, move it out of staging.
>
> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> ---
> .../mfd/hisilicon,hi6421-spmi-pmic.yaml | 133 +++++++
> MAINTAINERS | 7 +
> drivers/mfd/Kconfig | 15 +
> drivers/mfd/Makefile | 1 +
> drivers/mfd/hi6421-spmi-pmic.c | 342 ++++++++++++++++++
> drivers/staging/hikey9xx/Kconfig | 16 -
> drivers/staging/hikey9xx/Makefile | 1 -
> drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 ------------------
> .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 133 -------
> 9 files changed, 498 insertions(+), 492 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> create mode 100644 drivers/mfd/hi6421-spmi-pmic.c
> delete mode 100644 drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> delete mode 100644 drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
>
My bot found errors running 'make dt_binding_check' on your patch:
yamllint warnings/errors:
dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml: 'additionalProperties' is a required property
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml: ignoring, error in schema:
warning: no schema found in file: ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
See https://patchwork.ozlabs.org/patch/1428169
This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.
If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:
pip3 install dtschema --upgrade
Please check and re-submit.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 10/13] mfd: hi6421-spmi-pmic: move driver from staging
2021-01-18 15:32 ` Mauro Carvalho Chehab
@ 2021-01-18 15:50 ` Lee Jones
0 siblings, 0 replies; 13+ messages in thread
From: Lee Jones @ 2021-01-18 15:50 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Mark Brown, Greg Kroah-Hartman, Mayulong, Rob Herring, devel,
devicetree, linux-kernel
On Mon, 18 Jan 2021, Mauro Carvalho Chehab wrote:
> Em Mon, 18 Jan 2021 15:12:27 +0000
> Lee Jones <lee.jones@linaro.org> escreveu:
>
> > On Mon, 18 Jan 2021, Mauro Carvalho Chehab wrote:
> >
> > > This driver is ready for mainstream. So, move it out of staging.
> > >
> > > Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
> > > ---
> > > .../mfd/hisilicon,hi6421-spmi-pmic.yaml | 133 +++++++
> > > MAINTAINERS | 7 +
> > > drivers/mfd/Kconfig | 15 +
> > > drivers/mfd/Makefile | 1 +
> > > drivers/mfd/hi6421-spmi-pmic.c | 342 ++++++++++++++++++
> > > drivers/staging/hikey9xx/Kconfig | 16 -
> > > drivers/staging/hikey9xx/Makefile | 1 -
> > > drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 342 ------------------
> > > .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 133 -------
> > > 9 files changed, 498 insertions(+), 492 deletions(-)
> >
> > Could you please resubmit this will the correct flags.
> >
> > I believe it's the `git format-patch` -M flag that you want.
>
> As explained at patch 00/13, this was intentionally generated with
> --no-merges, in order to allow reviewers to view the entire source
> code at the patch.
That's a fair point. Please leave it as it is for now then.
I'll get around to the review soon I hope.
> Anyway, I'll re-send the series with -M, as it makes easier to merge,
> if everything is ok.
--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 11/13] regulator: hi6421v600-regulator: move it from staging
2021-01-18 13:54 ` Mark Brown
@ 2021-01-18 16:02 ` Mauro Carvalho Chehab
2021-01-18 16:20 ` Mark Brown
0 siblings, 1 reply; 13+ messages in thread
From: Mauro Carvalho Chehab @ 2021-01-18 16:02 UTC (permalink / raw)
To: Mark Brown
Cc: Greg Kroah-Hartman, Lee Jones, Liam Girdwood, Mayulong,
Rob Herring, devel, devicetree, linux-kernel
Em Mon, 18 Jan 2021 13:54:40 +0000
Mark Brown <broonie@kernel.org> escreveu:
> On Mon, Jan 18, 2021 at 02:28:12PM +0100, Mauro Carvalho Chehab wrote:
>
> > index f385146d2bd1..3b23ad56b31a 100644
> > --- a/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > @@ -60,6 +60,8 @@ required:
> > - reg
> > - regulators
> >
> > +additionalProperties: false
> > +
> > examples:
> > - |
> > /* pmic properties */
>
> Why is this part of this patch?
I'll place on a separate one.
>
> > +// SPDX-License-Identifier: GPL-2.0
> > +//
> > +// Device driver for regulators in Hisi IC
> > +//
> > +// Copyright (c) 2013 Linaro Ltd.
> > +// Copyright (c) 2011 Hisilicon.
> > +//
>
> This looks like it needs an update.
Ok.
>
> > +// 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.
>
> This boilerplate can be removed.
Ok.
>
> > +static int hi6421_spmi_regulator_enable(struct regulator_dev *rdev)
> > +{
> > + struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
> > + struct hi6421_spmi_pmic *pmic = sreg->pmic;
> > + int ret;
> > +
> > + /* cannot enable more than one regulator at one time */
> > + mutex_lock(&sreg->enable_mutex);
> > + usleep_range(HISI_REGS_ENA_PROTECT_TIME,
> > + HISI_REGS_ENA_PROTECT_TIME + 1000);
> > +
> > + /* set enable register */
> > + ret = hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
> > + rdev->desc->enable_mask,
> > + rdev->desc->enable_mask);
>
> If for some reason the PMIC is sufficiently fragile to need a delay
> between enables it's not clear why the driver is doing it before
> enabling rather than after, presumably there's issues with the regulator
> ramping up and stabalising its output
I don't have any datasheets or documentation from this device, except for
the Linaro's official driver for Kernel 4.9 (from where this driver
was originally ported), and a high-level documentation for this
hardware at 96boards site, which doesn't cover any details.
-
My understanding is that the issue here seems to be different.
This is the original code (which can be seen on changeset 42f24d9d446a,
already upstream):
struct timeval last_enabled;
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_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;
}
What I did here was to play safe. So, I removed the static var and the
call to gettimeofday() and replaced by just a delay.
As, on this device, the power lines don't change too often: only
the USB power supply changes over time during its reset sequence.
The other power lines are powered during the boot and remain powered
if the hardware is detected.
> > + /* set enable register to 0 */
> > + return hi6421_spmi_pmic_rmw(pmic, rdev->desc->enable_reg,
> > + rdev->desc->enable_mask, 0);
>
> I'm not sure all these comments are adding anything.
I'll drop on a next version.
>
> > + if (unlikely(selector >= rdev->desc->n_voltages))
> > + return -EINVAL;
>
> This should not be a hot path that needs an unlikely() annotation.
I'll drop unlikely().
> > +static unsigned int
> > +hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
> > + int input_uV, int output_uV,
> > + int load_uA)
> > +{
> > + struct hi6421_spmi_reg_info *sreg = rdev_get_drvdata(rdev);
> > +
> > + if (load_uA || ((unsigned int)load_uA > sreg->eco_uA))
> > + return REGULATOR_MODE_NORMAL;
>
> This means that for *any* load at all we select NORMAL - I'm not
> convinced this is intentional?
Indeed this seems to be a bug. Thanks for noticing it!
I'll fix that.
Thanks,
Mauro
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v2 11/13] regulator: hi6421v600-regulator: move it from staging
2021-01-18 16:02 ` Mauro Carvalho Chehab
@ 2021-01-18 16:20 ` Mark Brown
0 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2021-01-18 16:20 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Greg Kroah-Hartman, Lee Jones, Liam Girdwood, Mayulong,
Rob Herring, devel, devicetree, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 811 bytes --]
On Mon, Jan 18, 2021 at 05:02:45PM +0100, Mauro Carvalho Chehab wrote:
> Mark Brown <broonie@kernel.org> escreveu:
> > If for some reason the PMIC is sufficiently fragile to need a delay
> > between enables it's not clear why the driver is doing it before
> > enabling rather than after, presumably there's issues with the regulator
> > ramping up and stabalising its output
> I don't have any datasheets or documentation from this device, except for
> the Linaro's official driver for Kernel 4.9 (from where this driver
> was originally ported), and a high-level documentation for this
> hardware at 96boards site, which doesn't cover any details.
This misses the point. To repeat, if the driver is hard coding
a delay why is the driver doing this *before* rather than *after*
enabling?
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2021-01-18 16:52 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-01-18 13:28 [PATCH v2 00/13] Move Hisilicon 6421v600 SPMI driver set out of staging Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 09/13] spmi: hi6421-spmi-pmic: move driver from staging Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 10/13] mfd: " Mauro Carvalho Chehab
2021-01-18 15:12 ` Lee Jones
2021-01-18 15:32 ` Mauro Carvalho Chehab
2021-01-18 15:50 ` Lee Jones
2021-01-18 15:47 ` Rob Herring
2021-01-18 13:28 ` [PATCH v2 11/13] regulator: hi6421v600-regulator: move it " Mauro Carvalho Chehab
2021-01-18 13:54 ` Mark Brown
2021-01-18 16:02 ` Mauro Carvalho Chehab
2021-01-18 16:20 ` Mark Brown
2021-01-18 13:28 ` [PATCH v2 12/13] dts: hisilicon: add support for USB3 on Hikey 970 Mauro Carvalho Chehab
2021-01-18 13:28 ` [PATCH v2 13/13] dts: hisilicon: add support for the PMIC found " Mauro Carvalho Chehab
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).