linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging
@ 2021-06-24  9:01 Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 1/8] staging: phy-hi3670-usb3: do a some minor cleanups Mauro Carvalho Chehab
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, Rob Herring,
	Stephen Boyd, devicetree, linux-arm-kernel, linux-kernel,
	linux-phy, linux-staging, linux-usb

Notes:
   1. Patch resent with --no-renames, in order to show the full code when
      moving the code out of staging (on this RESEND);

   2. the previous series is at:
      https://lore.kernel.org/lkml/cover.1616695231.git.mchehab+huawei@kernel.org/

Hi Greg,

Those are the remaining patches that are needed for the USB to work
with Hikey970.

This series address the comments made on v5. Sorry for taking so long to
return back on this. Got sidetracked by other unrelated stuff.

Changes from v5:

- Some changes at DT to comply with Rob Herring's feedback;
- a couple of cleanups at the phy-hi3670-usb3;
- Vinod's ack added to patch 4;
- Several cleanups at hi6421-spmi-pmic.c, in order to address
  Lee Jones feedbacks.

On this series, I opted to keep using "gpios" for the DT IRQ gpios needed
by the PMIC driver, as this is the string expected by of_get_gpio(), and
it is the most common pattern for IRQ gpios. If required, I'll send a
followup patch changing it to use, instead, the of_get_named_gpio_flags()
variant.


Mauro Carvalho Chehab (8):
  staging: phy-hi3670-usb3: do a some minor cleanups
  staging: hisi-spmi-controller: rename spmi-channel property
  staging: phy-hi3670-usb3: do some additional cleanups
  phy: phy-hi3670-usb3: move driver from staging into phy
  spmi: hisi-spmi-controller: move driver from staging
  mfd: hi6421-spmi-pmic: move driver from staging
  dts: hisilicon: add support for the PMIC found on Hikey 970
  dts: hisilicon: add support for USB3 on Hikey 970

 .../mfd/hisilicon,hi6421-spmi-pmic.yaml       | 134 ++++
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |  73 ++
 .../spmi/hisilicon,hisi-spmi-controller.yaml  |  73 ++
 MAINTAINERS                                   |  23 +-
 .../boot/dts/hisilicon/hi3670-hikey970.dts    | 129 +++-
 arch/arm64/boot/dts/hisilicon/hi3670.dtsi     |  56 ++
 .../boot/dts/hisilicon/hikey970-pmic.dtsi     |  87 +++
 drivers/mfd/Kconfig                           |  16 +
 drivers/mfd/Makefile                          |   1 +
 drivers/mfd/hi6421-spmi-pmic.c                | 316 +++++++++
 drivers/phy/hisilicon/Kconfig                 |  10 +
 drivers/phy/hisilicon/Makefile                |   1 +
 drivers/phy/hisilicon/phy-hi3670-usb3.c       | 661 +++++++++++++++++
 drivers/spmi/Kconfig                          |   9 +
 drivers/spmi/Makefile                         |   1 +
 drivers/spmi/hisi-spmi-controller.c           | 367 ++++++++++
 drivers/staging/Kconfig                       |   2 -
 drivers/staging/Makefile                      |   1 -
 drivers/staging/hikey9xx/Kconfig              |  41 --
 drivers/staging/hikey9xx/Makefile             |   6 -
 drivers/staging/hikey9xx/TODO                 |   5 -
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 297 --------
 .../staging/hikey9xx/hisi-spmi-controller.c   | 367 ----------
 .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 135 ----
 .../hisilicon,hisi-spmi-controller.yaml       |  71 --
 drivers/staging/hikey9xx/phy-hi3670-usb3.c    | 668 ------------------
 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml |  73 --
 27 files changed, 1937 insertions(+), 1686 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 create mode 100644 Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.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/phy/hisilicon/phy-hi3670-usb3.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/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
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml

-- 
2.31.1



^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 1/8] staging: phy-hi3670-usb3: do a some minor cleanups
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 2/8] staging: hisi-spmi-controller: rename spmi-channel property Mauro Carvalho Chehab
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, linux-kernel,
	linux-staging

Before moving this driver out of staging:

1. group some integers altogether;

2. Use:

	return some_function()

instead of:

	ret = some_function();
	return ret;

This is just a cleanup. No functional changes.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 drivers/staging/hikey9xx/phy-hi3670-usb3.c | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c
index e7e579ce0302..b9ffe08abaab 100644
--- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c
+++ b/drivers/staging/hikey9xx/phy-hi3670-usb3.c
@@ -148,10 +148,8 @@ static int hi3670_phy_cr_clk(struct regmap *usb31misc)
 		return ret;
 
 	/* Clock down */
-	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				 CFG54_USB31PHY_CR_CLK, 0);
-
-	return ret;
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_CLK, 0);
 }
 
 static int hi3670_phy_cr_set_sel(struct regmap *usb31misc)
@@ -215,17 +213,14 @@ static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr)
 		return ret;
 
 	reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr);
-	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				 CFG54_USB31PHY_CR_ADDR_MASK, reg);
 
-	return ret;
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_ADDR_MASK, reg);
 }
 
 static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val)
 {
-	int reg;
-	int i;
-	int ret;
+	int reg, i, ret;
 
 	for (i = 0; i < 100; i++) {
 		ret = hi3670_phy_cr_clk(usb31misc);
@@ -286,9 +281,7 @@ static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val)
 	if (ret)
 		return ret;
 
-	ret = hi3670_phy_cr_wait_ack(usb31misc);
-
-	return ret;
+	return hi3670_phy_cr_wait_ack(usb31misc);
 }
 
 static int hi3670_phy_set_params(struct hi3670_priv *priv)
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 2/8] staging: hisi-spmi-controller: rename spmi-channel property
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 1/8] staging: phy-hi3670-usb3: do a some minor cleanups Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 3/8] staging: phy-hi3670-usb3: do some additional cleanups Mauro Carvalho Chehab
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, linux-kernel,
	linux-staging

The spmi-channel is not used on other drivers. So, rename it,
in order to document that this is specific to those devices.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 drivers/staging/hikey9xx/hisi-spmi-controller.c        |  2 +-
 .../hikey9xx/hisilicon,hisi-spmi-controller.yaml       | 10 ++++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c
index 0d42bc65f39b..5bd23262abd6 100644
--- a/drivers/staging/hikey9xx/hisi-spmi-controller.c
+++ b/drivers/staging/hikey9xx/hisi-spmi-controller.c
@@ -290,7 +290,7 @@ static int spmi_controller_probe(struct platform_device *pdev)
 		goto err_put_controller;
 	}
 
-	ret = of_property_read_u32(pdev->dev.of_node, "spmi-channel",
+	ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
 				   &spmi_controller->channel);
 	if (ret) {
 		dev_err(&pdev->dev, "can not get channel\n");
diff --git a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
index 6b755039a74c..f882903769f9 100644
--- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
@@ -14,7 +14,7 @@ description: |
   It is a MIPI System Power Management (SPMI) controller.
 
   The PMIC part is provided by
-  drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml.
+  ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml.
 
 allOf:
   - $ref: spmi.yaml#
@@ -30,7 +30,7 @@ properties:
   reg:
     maxItems: 1
 
-  spmi-channel:
+  hisilicon,spmi-channel:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: |
       number of the Kirin 970 SPMI channel where the SPMI devices are connected.
@@ -38,10 +38,12 @@ properties:
 required:
   - compatible
   - reg
-  - spmi-channel
+  - hisilicon,spmi-channel
 
 patternProperties:
   "@[0-9a-f]$":
+    type: object
+
     description: |
       PMIC properties, which are specific to the used SPMI PMIC device(s).
       When used in combination with HiSilicon 6421v600, the properties
@@ -61,7 +63,7 @@ examples:
         #address-cells = <2>;
         #size-cells = <0>;
         reg = <0x0 0xfff24000 0x0 0x1000>;
-        spmi-channel = <2>;
+        hisilicon,spmi-channel = <2>;
 
         pmic@0 {
           reg = <0 0>;
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 3/8] staging: phy-hi3670-usb3: do some additional cleanups
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 1/8] staging: phy-hi3670-usb3: do a some minor cleanups Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 2/8] staging: hisi-spmi-controller: rename spmi-channel property Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 4/8] phy: phy-hi3670-usb3: move driver from staging into phy Mauro Carvalho Chehab
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, linux-kernel,
	linux-staging

Before moving this driver out of staging, do a couple of
cleanups, in order to make the driver clearer.

No functional changes.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 89 +++++++++++--------
 .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  |  7 +-
 2 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 626140cb96f2..2b7172560df7 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -33,17 +33,27 @@ enum hi6421_spmi_pmic_irq_list {
 	SIM0_HPD_F,
 	SIM1_HPD_R,
 	SIM1_HPD_F,
-	PMIC_IRQ_LIST_MAX,
+
+	PMIC_IRQ_LIST_MAX
 };
 
-#define HISI_IRQ_ARRAY			2
-#define HISI_IRQ_NUM			(HISI_IRQ_ARRAY * 8)
+#define HISI_IRQ_BANK_SIZE		2
 
-#define HISI_IRQ_KEY_NUM		0
+/*
+ * IRQ number for the power key button and mask for both UP and DOWN IRQs
+ */
+#define HISI_POWERKEY_IRQ_NUM		0
+#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
 
-#define HISI_BITS			8
-#define HISI_IRQ_KEY_VALUE		(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
-#define HISI_MASK			GENMASK(HISI_BITS - 1, 0)
+/*
+ * Registers for IRQ address and IRQ mask bits
+ *
+ * Please notice that we need to regmap a larger region, as other
+ * registers are used by the regulators.
+ * See drivers/regulator/hi6421-regulator.c.
+ */
+#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
+#define SOC_PMIC_IRQ0_ADDR		0x0212
 
 /*
  * The IRQs are mapped as:
@@ -67,13 +77,14 @@ enum hi6421_spmi_pmic_irq_list {
  *	SIM1_HPD_R		0x0203		0x213		bit 4
  *	SIM1_HPD_F		0x0203		0x213		bit 5
  *	======================  =============   ============	=====
+ *
+ * Each mask register contains 8 bits. The ancillary macros below
+ * convert a number from 0 to 14 into a register address and a bit mask
  */
-#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
-#define SOC_PMIC_IRQ0_ADDR		0x0212
-
-#define IRQ_MASK_REGISTER(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
-					 (irqd_to_hwirq(irq_data) >> 3))
-#define IRQ_MASK_BIT(irq_data)		BIT(irqd_to_hwirq(irq_data) & 0x07)
+#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
+					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
+#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
+#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)
 
 static const struct mfd_cell hi6421v600_devs[] = {
 	{ .name = "hi6421v600-regulator", },
@@ -86,23 +97,30 @@ static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
 	unsigned int in;
 	int i, offset;
 
-	for (i = 0; i < HISI_IRQ_ARRAY; i++) {
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
 		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
-		pending = HISI_MASK & in;
+
+		/* Mark pending IRQs as handled */
+		pending = HISI_8BITS_MASK & in;
 		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
 
-		if (i == HISI_IRQ_KEY_NUM &&
-		    (pending & HISI_IRQ_KEY_VALUE) == HISI_IRQ_KEY_VALUE) {
+		if (i == HISI_POWERKEY_IRQ_NUM &&
+		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
+			/*
+			 * If both powerkey down and up IRQs are received,
+			 * handle them at the right order
+			 */
 			generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
 			generic_handle_irq(ddata->irqs[POWERKEY_UP]);
-			pending &= (~HISI_IRQ_KEY_VALUE);
+			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
 		}
 
 		if (!pending)
 			continue;
 
-		for_each_set_bit(offset, &pending, HISI_BITS)
-			generic_handle_irq(ddata->irqs[offset + i * HISI_BITS]);
+		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
+			generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
+		}
 	}
 
 	return IRQ_HANDLED;
@@ -115,12 +133,12 @@ static void hi6421_spmi_irq_mask(struct irq_data *d)
 	unsigned int data;
 	u32 offset;
 
-	offset = IRQ_MASK_REGISTER(d);
+	offset = HISI_IRQ_MASK_REG(d);
 
 	spin_lock_irqsave(&ddata->lock, flags);
 
 	regmap_read(ddata->regmap, offset, &data);
-	data |= IRQ_MASK_BIT(d);
+	data |= HISI_IRQ_MASK_BIT(d);
 	regmap_write(ddata->regmap, offset, data);
 
 	spin_unlock_irqrestore(&ddata->lock, flags);
@@ -132,20 +150,19 @@ static void hi6421_spmi_irq_unmask(struct irq_data *d)
 	u32 data, offset;
 	unsigned long flags;
 
-	offset = (irqd_to_hwirq(d) >> 3);
-	offset += SOC_PMIC_IRQ_MASK_0_ADDR;
+	offset = HISI_IRQ_MASK_REG(d);
 
 	spin_lock_irqsave(&ddata->lock, flags);
 
 	regmap_read(ddata->regmap, offset, &data);
-	data &= ~(1 << (irqd_to_hwirq(d) & 0x07));
+	data &= ~HISI_IRQ_MASK_BIT(d);
 	regmap_write(ddata->regmap, offset, data);
 
 	spin_unlock_irqrestore(&ddata->lock, flags);
 }
 
 static struct irq_chip hi6421_spmi_pmu_irqchip = {
-	.name		= "hisi-irq",
+	.name		= "hi6421v600-irq",
 	.irq_mask	= hi6421_spmi_irq_mask,
 	.irq_unmask	= hi6421_spmi_irq_unmask,
 	.irq_disable	= hi6421_spmi_irq_mask,
@@ -158,7 +175,7 @@ static int hi6421_spmi_irq_map(struct irq_domain *d, unsigned int virq,
 	struct hi6421_spmi_pmic *ddata = d->host_data;
 
 	irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
-				      handle_simple_irq, "hisi");
+				      handle_simple_irq, "hi6421v600");
 	irq_set_chip_data(virq, ddata);
 	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
@@ -175,20 +192,22 @@ static void hi6421_spmi_pmic_irq_init(struct hi6421_spmi_pmic *ddata)
 	int i;
 	unsigned int pending;
 
-	for (i = 0; i < HISI_IRQ_ARRAY; i++)
+	/* Mask all IRQs */
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
 		regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
-			     HISI_MASK);
+			     HISI_8BITS_MASK);
 
-	for (i = 0; i < HISI_IRQ_ARRAY; i++) {
+	/* Mark all IRQs as handled */
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
 		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
 		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
-			     HISI_MASK);
+			     HISI_8BITS_MASK);
 	}
 }
 
 static const struct regmap_config regmap_config = {
 	.reg_bits		= 16,
-	.val_bits		= HISI_BITS,
+	.val_bits		= BITS_PER_BYTE,
 	.max_register		= 0xffff,
 	.fast_io		= true
 };
@@ -230,18 +249,18 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
 
 	hi6421_spmi_pmic_irq_init(ddata);
 
-	ddata->irqs = devm_kzalloc(dev, HISI_IRQ_NUM * sizeof(int), GFP_KERNEL);
+	ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
 	if (!ddata->irqs)
 		return -ENOMEM;
 
-	ddata->domain = irq_domain_add_simple(np, HISI_IRQ_NUM, 0,
+	ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
 					      &hi6421_spmi_domain_ops, ddata);
 	if (!ddata->domain) {
 		dev_err(dev, "Failed to create IRQ domain\n");
 		return -ENODEV;
 	}
 
-	for (i = 0; i < HISI_IRQ_NUM; i++) {
+	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
 		virq = irq_create_mapping(ddata->domain, i);
 		if (!virq) {
 			dev_err(dev, "Failed to map H/W IRQ\n");
diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
index 3b23ad56b31a..8e355cddd437 100644
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
@@ -17,7 +17,7 @@ description: |
   node.
 
   The SPMI controller part is provided by
-  drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml.
+  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
 
 properties:
   $nodename:
@@ -32,12 +32,11 @@ properties:
   '#interrupt-cells':
     const: 2
 
-  interrupt-controller:
-    description:
-      Identify that the PMIC is capable of behaving as an interrupt controller.
+  interrupt-controller: true
 
   gpios:
     maxItems: 1
+    description: GPIO used for IRQs
 
   regulators:
     type: object
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 4/8] phy: phy-hi3670-usb3: move driver from staging into phy
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
                   ` (2 preceding siblings ...)
  2021-06-24  9:01 ` [PATCH RESEND v6 3/8] staging: phy-hi3670-usb3: do some additional cleanups Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 5/8] spmi: hisi-spmi-controller: move driver from staging Mauro Carvalho Chehab
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, Alex Dewar,
	Atul Gopinathan, Kishon Vijay Abraham I, Mauro Carvalho Chehab,
	Rob Herring, Vinod Koul, Yu Chen, devicetree, linux-kernel,
	linux-phy, linux-staging, linux-usb, Rob Herring

The phy USB3 driver for Hisilicon 970 (hi3670) is ready
for mainstream. Mode it from staging into the main driver's
phy/ directory.

Acked-by: Rob Herring <robh@kernel.org>
Acked-By: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 .../bindings/phy/hisilicon,hi3670-usb3.yaml   |  73 ++
 MAINTAINERS                                   |   9 +-
 drivers/phy/hisilicon/Kconfig                 |  10 +
 drivers/phy/hisilicon/Makefile                |   1 +
 drivers/phy/hisilicon/phy-hi3670-usb3.c       | 661 ++++++++++++++++++
 drivers/staging/hikey9xx/Kconfig              |  11 -
 drivers/staging/hikey9xx/Makefile             |   2 -
 drivers/staging/hikey9xx/phy-hi3670-usb3.c    | 661 ------------------
 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml |  73 --
 9 files changed, 753 insertions(+), 748 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
 create mode 100644 drivers/phy/hisilicon/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.c
 delete mode 100644 drivers/staging/hikey9xx/phy-hi3670-usb3.yaml

diff --git a/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml b/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
new file mode 100644
index 000000000000..ebd78acfe2de
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/phy/hisilicon,hi3670-usb3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hisilicon Kirin970 USB PHY
+
+maintainers:
+  - Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+
+description: |+
+  Bindings for USB3 PHY on HiSilicon Kirin 970.
+
+properties:
+  compatible:
+    const: hisilicon,hi3670-usb-phy
+
+  "#phy-cells":
+    const: 0
+
+  hisilicon,pericrg-syscon:
+    $ref: '/schemas/types.yaml#/definitions/phandle'
+    description: phandle of syscon used to control iso refclk.
+
+  hisilicon,pctrl-syscon:
+    $ref: '/schemas/types.yaml#/definitions/phandle'
+    description: phandle of syscon used to control usb tcxo.
+
+  hisilicon,sctrl-syscon:
+    $ref: '/schemas/types.yaml#/definitions/phandle'
+    description: phandle of syscon used to control phy deep sleep.
+
+  hisilicon,eye-diagram-param:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: Eye diagram for phy.
+
+  hisilicon,tx-vboost-lvl:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: TX level vboost for phy.
+
+required:
+  - compatible
+  - hisilicon,pericrg-syscon
+  - hisilicon,pctrl-syscon
+  - hisilicon,sctrl-syscon
+  - hisilicon,eye-diagram-param
+  - hisilicon,tx-vboost-lvl
+  - "#phy-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      usb3_otg_bc: usb3_otg_bc@ff200000 {
+        compatible = "syscon", "simple-mfd";
+        reg = <0x0 0xff200000 0x0 0x1000>;
+
+        usb_phy {
+          compatible = "hisilicon,hi3670-usb-phy";
+          #phy-cells = <0>;
+          hisilicon,pericrg-syscon = <&crg_ctrl>;
+          hisilicon,pctrl-syscon = <&pctrl>;
+          hisilicon,sctrl-syscon = <&sctrl>;
+          hisilicon,eye-diagram-param = <0xfdfee4>;
+          hisilicon,tx-vboost-lvl = <0x5>;
+        };
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 8c5ee008301a..6e01424234eb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18859,7 +18859,7 @@ L:	linux-usb@vger.kernel.org
 S:	Maintained
 F:	drivers/usb/roles/intel-xhci-usb-role-switch.c
 
-USB IP DRIVER FOR HISILICON KIRIN
+USB IP DRIVER FOR HISILICON KIRIN 960
 M:	Yu Chen <chenyu56@huawei.com>
 M:	Binghui Wang <wangbinghui@hisilicon.com>
 L:	linux-usb@vger.kernel.org
@@ -18867,6 +18867,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/phy/hisilicon,hi3660-usb3.yaml
 F:	drivers/phy/hisilicon/phy-hi3660-usb3.c
 
+USB IP DRIVER FOR HISILICON KIRIN 970
+M:	Mauro Carvalho Chehab <mchehab@kernel.org>
+L:	linux-usb@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/phy/hisilicon,hi3670-usb3.yaml
+F:	drivers/phy/hisilicon/phy-kirin970-usb3.c
+
 USB ISP116X DRIVER
 M:	Olav Kongas <ok@artecdesign.ee>
 L:	linux-usb@vger.kernel.org
diff --git a/drivers/phy/hisilicon/Kconfig b/drivers/phy/hisilicon/Kconfig
index 1c73053bcc98..4d008cfc279c 100644
--- a/drivers/phy/hisilicon/Kconfig
+++ b/drivers/phy/hisilicon/Kconfig
@@ -23,6 +23,16 @@ config PHY_HI3660_USB
 
 	  To compile this driver as a module, choose M here.
 
+config PHY_HI3670_USB
+	tristate "hi3670 USB PHY support"
+	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Enable this to support the HISILICON HI3670 USB PHY.
+
+	  To compile this driver as a module, choose M here.
+
 config PHY_HISTB_COMBPHY
 	tristate "HiSilicon STB SoCs COMBPHY support"
 	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
diff --git a/drivers/phy/hisilicon/Makefile b/drivers/phy/hisilicon/Makefile
index 92e874ae9c74..51729868145b 100644
--- a/drivers/phy/hisilicon/Makefile
+++ b/drivers/phy/hisilicon/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PHY_HI6220_USB)		+= phy-hi6220-usb.o
 obj-$(CONFIG_PHY_HI3660_USB)		+= phy-hi3660-usb3.o
+obj-$(CONFIG_PHY_HI3670_USB)		+= phy-hi3670-usb3.o
 obj-$(CONFIG_PHY_HISTB_COMBPHY)		+= phy-histb-combphy.o
 obj-$(CONFIG_PHY_HISI_INNO_USB2)	+= phy-hisi-inno-usb2.o
 obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
diff --git a/drivers/phy/hisilicon/phy-hi3670-usb3.c b/drivers/phy/hisilicon/phy-hi3670-usb3.c
new file mode 100644
index 000000000000..b9ffe08abaab
--- /dev/null
+++ b/drivers/phy/hisilicon/phy-hi3670-usb3.c
@@ -0,0 +1,661 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform
+ *
+ * Copyright (C) 2017-2020 Hilisicon Electronics Co., Ltd.
+ *		http://www.huawei.com
+ *
+ * Authors: Yu Chen <chenyu56@huawei.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SCTRL_SCDEEPSLEEPED		(0x0)
+#define USB_CLK_SELECTED		BIT(20)
+
+#define PERI_CRG_PEREN0			(0x00)
+#define PERI_CRG_PERDIS0		(0x04)
+#define PERI_CRG_PEREN4			(0x40)
+#define PERI_CRG_PERDIS4		(0x44)
+#define PERI_CRG_PERRSTEN4		(0x90)
+#define PERI_CRG_PERRSTDIS4		(0x94)
+#define PERI_CRG_ISODIS			(0x148)
+#define PERI_CRG_PEREN6			(0x410)
+#define PERI_CRG_PERDIS6		(0x414)
+
+#define USB_REFCLK_ISO_EN		BIT(25)
+
+#define GT_CLK_USB2PHY_REF		BIT(19)
+
+#define PCTRL_PERI_CTRL3		(0x10)
+#define PCTRL_PERI_CTRL3_MSK_START	(16)
+#define USB_TCXO_EN			BIT(1)
+
+#define PCTRL_PERI_CTRL24		(0x64)
+#define SC_CLK_USB3PHY_3MUX1_SEL	BIT(25)
+
+#define USB3OTG_CTRL0			(0x00)
+#define USB3OTG_CTRL3			(0x0c)
+#define USB3OTG_CTRL4			(0x10)
+#define USB3OTG_CTRL5			(0x14)
+#define USB3OTG_CTRL7			(0x1c)
+#define USB_MISC_CFG50			(0x50)
+#define USB_MISC_CFG54			(0x54)
+#define USB_MISC_CFG58			(0x58)
+#define USB_MISC_CFG5C			(0x5c)
+#define USB_MISC_CFGA0			(0xa0)
+#define TCA_CLK_RST			(0x200)
+#define TCA_INTR_EN			(0x204)
+#define TCA_INTR_STS			(0x208)
+#define TCA_GCFG			(0x210)
+#define TCA_TCPC			(0x214)
+#define TCA_SYSMODE_CFG			(0x218)
+#define TCA_VBUS_CTRL			(0x240)
+
+#define CTRL0_USB3_VBUSVLD		BIT(7)
+#define CTRL0_USB3_VBUSVLD_SEL		BIT(6)
+
+#define CTRL3_USB2_VBUSVLDEXT0		BIT(6)
+#define CTRL3_USB2_VBUSVLDEXTSEL0	BIT(5)
+
+#define CTRL5_USB2_SIDDQ		BIT(0)
+
+#define CTRL7_USB2_REFCLKSEL_MASK	GENMASK(4, 3)
+#define CTRL7_USB2_REFCLKSEL_ABB	(BIT(4) | BIT(3))
+#define CTRL7_USB2_REFCLKSEL_PAD	BIT(4)
+
+#define CFG50_USB3_PHY_TEST_POWERDOWN	BIT(23)
+
+#define CFG54_USB31PHY_CR_ADDR_MASK	GENMASK(31, 16)
+
+#define CFG54_USB3PHY_REF_USE_PAD	BIT(12)
+#define CFG54_PHY0_PMA_PWR_STABLE	BIT(11)
+#define CFG54_PHY0_PCS_PWR_STABLE	BIT(9)
+#define CFG54_USB31PHY_CR_ACK		BIT(7)
+#define CFG54_USB31PHY_CR_WR_EN		BIT(5)
+#define CFG54_USB31PHY_CR_SEL		BIT(4)
+#define CFG54_USB31PHY_CR_RD_EN		BIT(3)
+#define CFG54_USB31PHY_CR_CLK		BIT(2)
+#define CFG54_USB3_PHY0_ANA_PWR_EN	BIT(1)
+
+#define CFG58_USB31PHY_CR_DATA_MASK     GENMASK(31, 16)
+
+#define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN	BIT(1)
+
+#define CFGA0_VAUX_RESET		BIT(9)
+#define CFGA0_USB31C_RESET		BIT(8)
+#define CFGA0_USB2PHY_REFCLK_SELECT	BIT(4)
+#define CFGA0_USB3PHY_RESET		BIT(1)
+#define CFGA0_USB2PHY_POR		BIT(0)
+
+#define INTR_EN_XA_TIMEOUT_EVT_EN	BIT(1)
+#define INTR_EN_XA_ACK_EVT_EN		BIT(0)
+
+#define CLK_RST_TCA_REF_CLK_EN		BIT(1)
+#define CLK_RST_SUSPEND_CLK_EN		BIT(0)
+
+#define GCFG_ROLE_HSTDEV		BIT(4)
+#define GCFG_OP_MODE			GENMASK(1, 0)
+#define GCFG_OP_MODE_CTRL_SYNC_MODE	BIT(0)
+
+#define TCPC_VALID			BIT(4)
+#define TCPC_LOW_POWER_EN		BIT(3)
+#define TCPC_MUX_CONTROL_MASK		GENMASK(1, 0)
+#define TCPC_MUX_CONTROL_USB31		BIT(0)
+
+#define SYSMODE_CFG_TYPEC_DISABLE	BIT(3)
+
+#define VBUS_CTRL_POWERPRESENT_OVERRD	GENMASK(3, 2)
+#define VBUS_CTRL_VBUSVALID_OVERRD	GENMASK(1, 0)
+
+#define KIRIN970_USB_DEFAULT_PHY_PARAM	(0xfdfee4)
+#define KIRIN970_USB_DEFAULT_PHY_VBOOST	(0x5)
+
+#define TX_VBOOST_LVL_REG		(0xf)
+#define TX_VBOOST_LVL_START		(6)
+#define TX_VBOOST_LVL_ENABLE		BIT(9)
+
+struct hi3670_priv {
+	struct device *dev;
+	struct regmap *peri_crg;
+	struct regmap *pctrl;
+	struct regmap *sctrl;
+	struct regmap *usb31misc;
+
+	u32 eye_diagram_param;
+	u32 tx_vboost_lvl;
+
+	u32 peri_crg_offset;
+	u32 pctrl_offset;
+	u32 usb31misc_offset;
+};
+
+static int hi3670_phy_cr_clk(struct regmap *usb31misc)
+{
+	int ret;
+
+	/* Clock up */
+	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				 CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK);
+	if (ret)
+		return ret;
+
+	/* Clock down */
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_CLK, 0);
+}
+
+static int hi3670_phy_cr_set_sel(struct regmap *usb31misc)
+{
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL);
+}
+
+static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction)
+{
+	int ret, reg;
+
+	if (direction)
+		reg = CFG54_USB31PHY_CR_WR_EN;
+	else
+		reg = CFG54_USB31PHY_CR_RD_EN;
+
+	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, reg, reg);
+
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_clk(usb31misc);
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0);
+}
+
+static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc)
+{
+	u32 reg;
+	int retry = 10;
+	int ret;
+
+	while (retry-- > 0) {
+		ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
+		if (ret)
+			return ret;
+		if ((reg & CFG54_USB31PHY_CR_ACK) == CFG54_USB31PHY_CR_ACK)
+			return 0;
+
+		ret = hi3670_phy_cr_clk(usb31misc);
+		if (ret)
+			return ret;
+
+		usleep_range(10, 20);
+	}
+
+	return -ETIMEDOUT;
+}
+
+static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr)
+{
+	u32 reg;
+	int ret;
+
+	ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
+	if (ret)
+		return ret;
+
+	reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr);
+
+	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
+				  CFG54_USB31PHY_CR_ADDR_MASK, reg);
+}
+
+static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val)
+{
+	int reg, i, ret;
+
+	for (i = 0; i < 100; i++) {
+		ret = hi3670_phy_cr_clk(usb31misc);
+		if (ret)
+			return ret;
+	}
+
+	ret = hi3670_phy_cr_set_sel(usb31misc);
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_start(usb31misc, 0);
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_wait_ack(usb31misc);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(usb31misc, USB_MISC_CFG58, &reg);
+	if (ret)
+		return ret;
+
+	*val = FIELD_GET(CFG58_USB31PHY_CR_DATA_MASK, reg);
+
+	return 0;
+}
+
+static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < 100; i++) {
+		ret = hi3670_phy_cr_clk(usb31misc);
+		if (ret)
+			return ret;
+	}
+
+	ret = hi3670_phy_cr_set_sel(usb31misc);
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
+	if (ret)
+		return ret;
+
+	ret = regmap_write(usb31misc, USB_MISC_CFG58,
+			   FIELD_PREP(CFG58_USB31PHY_CR_DATA_MASK, val));
+	if (ret)
+		return ret;
+
+	ret = hi3670_phy_cr_start(usb31misc, 1);
+	if (ret)
+		return ret;
+
+	return hi3670_phy_cr_wait_ack(usb31misc);
+}
+
+static int hi3670_phy_set_params(struct hi3670_priv *priv)
+{
+	u32 reg;
+	int ret;
+	int retry = 3;
+
+	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL4,
+			   priv->eye_diagram_param);
+	if (ret) {
+		dev_err(priv->dev, "set USB3OTG_CTRL4 failed\n");
+		return ret;
+	}
+
+	while (retry-- > 0) {
+		ret = hi3670_phy_cr_read(priv->usb31misc,
+					 TX_VBOOST_LVL_REG, &reg);
+		if (!ret)
+			break;
+
+		if (ret != -ETIMEDOUT) {
+			dev_err(priv->dev, "read TX_VBOOST_LVL_REG failed\n");
+			return ret;
+		}
+	}
+	if (ret)
+		return ret;
+
+	reg |= (TX_VBOOST_LVL_ENABLE | (priv->tx_vboost_lvl << TX_VBOOST_LVL_START));
+	ret = hi3670_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg);
+	if (ret)
+		dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n");
+
+	return ret;
+}
+
+static bool hi3670_is_abbclk_selected(struct hi3670_priv *priv)
+{
+	u32 reg;
+
+	if (!priv->sctrl) {
+		dev_err(priv->dev, "priv->sctrl is null!\n");
+		return false;
+	}
+
+	if (regmap_read(priv->sctrl, SCTRL_SCDEEPSLEEPED, &reg)) {
+		dev_err(priv->dev, "SCTRL_SCDEEPSLEEPED read failed!\n");
+		return false;
+	}
+
+	if ((reg & USB_CLK_SELECTED) == 0)
+		return false;
+
+	return true;
+}
+
+static int hi3670_config_phy_clock(struct hi3670_priv *priv)
+{
+	u32 val, mask;
+	int ret;
+
+	if (!hi3670_is_abbclk_selected(priv)) {
+		/* usb refclk iso disable */
+		ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS,
+				   USB_REFCLK_ISO_EN);
+		if (ret)
+			goto out;
+
+		/* enable usb_tcxo_en */
+		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
+				   USB_TCXO_EN |
+				   (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START));
+
+		/* select usbphy clk from abb */
+		mask = SC_CLK_USB3PHY_3MUX1_SEL;
+		ret = regmap_update_bits(priv->pctrl,
+					 PCTRL_PERI_CTRL24, mask, 0);
+		if (ret)
+			goto out;
+
+		ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
+					 CFGA0_USB2PHY_REFCLK_SELECT, 0);
+		if (ret)
+			goto out;
+
+		ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
+		if (ret)
+			goto out;
+		val &= ~CTRL7_USB2_REFCLKSEL_MASK;
+		val |= CTRL7_USB2_REFCLKSEL_ABB;
+		ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
+		if (ret)
+			goto out;
+
+		return 0;
+	}
+
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
+				 CFG54_USB3PHY_REF_USE_PAD,
+				 CFG54_USB3PHY_REF_USE_PAD);
+	if (ret)
+		goto out;
+
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
+				 CFGA0_USB2PHY_REFCLK_SELECT,
+				 CFGA0_USB2PHY_REFCLK_SELECT);
+	if (ret)
+		goto out;
+
+	ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
+	if (ret)
+		goto out;
+	val &= ~CTRL7_USB2_REFCLKSEL_MASK;
+	val |= CTRL7_USB2_REFCLKSEL_PAD;
+	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(priv->peri_crg,
+			   PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF);
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
+	return ret;
+}
+
+static int hi3670_config_tca(struct hi3670_priv *priv)
+{
+	u32 val, mask;
+	int ret;
+
+	ret = regmap_write(priv->usb31misc, TCA_INTR_STS, 0xffff);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(priv->usb31misc, TCA_INTR_EN,
+			   INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN);
+	if (ret)
+		goto out;
+
+	mask = CLK_RST_TCA_REF_CLK_EN | CLK_RST_SUSPEND_CLK_EN;
+	ret = regmap_update_bits(priv->usb31misc, TCA_CLK_RST, mask, 0);
+	if (ret)
+		goto out;
+
+	ret = regmap_update_bits(priv->usb31misc, TCA_GCFG,
+				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE,
+				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE);
+	if (ret)
+		goto out;
+
+	ret = regmap_update_bits(priv->usb31misc, TCA_SYSMODE_CFG,
+				 SYSMODE_CFG_TYPEC_DISABLE, 0);
+	if (ret)
+		goto out;
+
+	ret = regmap_read(priv->usb31misc, TCA_TCPC, &val);
+	if (ret)
+		goto out;
+	val &= ~(TCPC_VALID | TCPC_LOW_POWER_EN | TCPC_MUX_CONTROL_MASK);
+	val |= (TCPC_VALID | TCPC_MUX_CONTROL_USB31);
+	ret = regmap_write(priv->usb31misc, TCA_TCPC, val);
+	if (ret)
+		goto out;
+
+	ret = regmap_write(priv->usb31misc, TCA_VBUS_CTRL,
+			   VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD);
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
+	return ret;
+}
+
+static int hi3670_phy_init(struct phy *phy)
+{
+	struct hi3670_priv *priv = phy_get_drvdata(phy);
+	u32 val;
+	int ret;
+
+	/* assert controller */
+	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET |
+	      CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0);
+	if (ret)
+		goto out;
+
+	ret = hi3670_config_phy_clock(priv);
+	if (ret)
+		goto out;
+
+	/* Exit from IDDQ mode */
+	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL5,
+				 CTRL5_USB2_SIDDQ, 0);
+	if (ret)
+		goto out;
+
+	/* Release USB31 PHY out of TestPowerDown mode */
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG50,
+				 CFG50_USB3_PHY_TEST_POWERDOWN, 0);
+	if (ret)
+		goto out;
+
+	/* Deassert phy */
+	val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
+	if (ret)
+		goto out;
+
+	usleep_range(100, 120);
+
+	/* Tell the PHY power is stable */
+	val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE |
+	      CFG54_PHY0_PMA_PWR_STABLE;
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
+				 val, val);
+	if (ret)
+		goto out;
+
+	ret = hi3670_config_tca(priv);
+	if (ret)
+		goto out;
+
+	/* Enable SSC */
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG5C,
+				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN,
+				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN);
+	if (ret)
+		goto out;
+
+	/* Deassert controller */
+	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET;
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
+	if (ret)
+		goto out;
+
+	usleep_range(100, 120);
+
+	/* Set fake vbus valid signal */
+	val = CTRL0_USB3_VBUSVLD | CTRL0_USB3_VBUSVLD_SEL;
+	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL0, val, val);
+	if (ret)
+		goto out;
+
+	val = CTRL3_USB2_VBUSVLDEXT0 | CTRL3_USB2_VBUSVLDEXTSEL0;
+	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL3, val, val);
+	if (ret)
+		goto out;
+
+	usleep_range(100, 120);
+
+	ret = hi3670_phy_set_params(priv);
+	if (ret)
+		goto out;
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to init phy ret: %d\n", ret);
+	return ret;
+}
+
+static int hi3670_phy_exit(struct phy *phy)
+{
+	struct hi3670_priv *priv = phy_get_drvdata(phy);
+	u32 mask;
+	int ret;
+
+	/* Assert phy */
+	mask = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
+	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, mask, 0);
+	if (ret)
+		goto out;
+
+	if (!hi3670_is_abbclk_selected(priv)) {
+		/* disable usb_tcxo_en */
+		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
+				   USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
+	} else {
+		ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6,
+				   GT_CLK_USB2PHY_REF);
+		if (ret)
+			goto out;
+	}
+
+	return 0;
+out:
+	dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);
+	return ret;
+}
+
+static const struct phy_ops hi3670_phy_ops = {
+	.init		= hi3670_phy_init,
+	.exit		= hi3670_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int hi3670_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct phy *phy;
+	struct hi3670_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+	priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,
+							 "hisilicon,pericrg-syscon");
+	if (IS_ERR(priv->peri_crg)) {
+		dev_err(dev, "no hisilicon,pericrg-syscon\n");
+		return PTR_ERR(priv->peri_crg);
+	}
+
+	priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+						      "hisilicon,pctrl-syscon");
+	if (IS_ERR(priv->pctrl)) {
+		dev_err(dev, "no hisilicon,pctrl-syscon\n");
+		return PTR_ERR(priv->pctrl);
+	}
+
+	priv->sctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+						      "hisilicon,sctrl-syscon");
+	if (IS_ERR(priv->sctrl)) {
+		dev_err(dev, "no hisilicon,sctrl-syscon\n");
+		return PTR_ERR(priv->sctrl);
+	}
+
+	/* node of hi3670 phy is a sub-node of usb3_otg_bc */
+	priv->usb31misc = syscon_node_to_regmap(dev->parent->of_node);
+	if (IS_ERR(priv->usb31misc)) {
+		dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");
+		return PTR_ERR(priv->usb31misc);
+	}
+
+	if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param",
+				 &priv->eye_diagram_param))
+		priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM;
+
+	if (of_property_read_u32(dev->of_node, "hisilicon,tx-vboost-lvl",
+				 &priv->tx_vboost_lvl))
+		priv->tx_vboost_lvl = KIRIN970_USB_DEFAULT_PHY_VBOOST;
+
+	phy = devm_phy_create(dev, NULL, &hi3670_phy_ops);
+	if (IS_ERR(phy))
+		return PTR_ERR(phy);
+
+	phy_set_drvdata(phy, priv);
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id hi3670_phy_of_match[] = {
+	{ .compatible = "hisilicon,hi3670-usb-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hi3670_phy_of_match);
+
+static struct platform_driver hi3670_phy_driver = {
+	.probe	= hi3670_phy_probe,
+	.driver = {
+		.name	= "hi3670-usb-phy",
+		.of_match_table	= hi3670_phy_of_match,
+	}
+};
+module_platform_driver(hi3670_phy_driver);
+
+MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hilisicon Kirin970 USB31 PHY Driver");
diff --git a/drivers/staging/hikey9xx/Kconfig b/drivers/staging/hikey9xx/Kconfig
index c4dc1016edf2..3ceda03f2864 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/phy
-config PHY_HI3670_USB
-	tristate "hi3670 USB PHY support"
-	depends on (ARCH_HISI && ARM64) || COMPILE_TEST
-	select GENERIC_PHY
-	select MFD_SYSCON
-	help
-	  Enable this to support the HISILICON HI3670 USB PHY.
-
-	  To compile this driver as a module, choose M here.
-
 # to be placed at drivers/spmi
 config SPMI_HISI3670
 	tristate "Hisilicon 3670 SPMI Controller"
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
index 9103735d8377..42d486104525 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,6 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_PHY_HI3670_USB)		+= phy-hi3670-usb3.o
-
 obj-$(CONFIG_SPMI_HISI3670)		+= hisi-spmi-controller.o
 obj-$(CONFIG_MFD_HI6421_SPMI)		+= hi6421-spmi-pmic.o
diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.c b/drivers/staging/hikey9xx/phy-hi3670-usb3.c
deleted file mode 100644
index b9ffe08abaab..000000000000
--- a/drivers/staging/hikey9xx/phy-hi3670-usb3.c
+++ /dev/null
@@ -1,661 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Phy provider for USB 3.1 controller on HiSilicon Kirin970 platform
- *
- * Copyright (C) 2017-2020 Hilisicon Electronics Co., Ltd.
- *		http://www.huawei.com
- *
- * Authors: Yu Chen <chenyu56@huawei.com>
- */
-
-#include <linux/bitfield.h>
-#include <linux/clk.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-
-#define SCTRL_SCDEEPSLEEPED		(0x0)
-#define USB_CLK_SELECTED		BIT(20)
-
-#define PERI_CRG_PEREN0			(0x00)
-#define PERI_CRG_PERDIS0		(0x04)
-#define PERI_CRG_PEREN4			(0x40)
-#define PERI_CRG_PERDIS4		(0x44)
-#define PERI_CRG_PERRSTEN4		(0x90)
-#define PERI_CRG_PERRSTDIS4		(0x94)
-#define PERI_CRG_ISODIS			(0x148)
-#define PERI_CRG_PEREN6			(0x410)
-#define PERI_CRG_PERDIS6		(0x414)
-
-#define USB_REFCLK_ISO_EN		BIT(25)
-
-#define GT_CLK_USB2PHY_REF		BIT(19)
-
-#define PCTRL_PERI_CTRL3		(0x10)
-#define PCTRL_PERI_CTRL3_MSK_START	(16)
-#define USB_TCXO_EN			BIT(1)
-
-#define PCTRL_PERI_CTRL24		(0x64)
-#define SC_CLK_USB3PHY_3MUX1_SEL	BIT(25)
-
-#define USB3OTG_CTRL0			(0x00)
-#define USB3OTG_CTRL3			(0x0c)
-#define USB3OTG_CTRL4			(0x10)
-#define USB3OTG_CTRL5			(0x14)
-#define USB3OTG_CTRL7			(0x1c)
-#define USB_MISC_CFG50			(0x50)
-#define USB_MISC_CFG54			(0x54)
-#define USB_MISC_CFG58			(0x58)
-#define USB_MISC_CFG5C			(0x5c)
-#define USB_MISC_CFGA0			(0xa0)
-#define TCA_CLK_RST			(0x200)
-#define TCA_INTR_EN			(0x204)
-#define TCA_INTR_STS			(0x208)
-#define TCA_GCFG			(0x210)
-#define TCA_TCPC			(0x214)
-#define TCA_SYSMODE_CFG			(0x218)
-#define TCA_VBUS_CTRL			(0x240)
-
-#define CTRL0_USB3_VBUSVLD		BIT(7)
-#define CTRL0_USB3_VBUSVLD_SEL		BIT(6)
-
-#define CTRL3_USB2_VBUSVLDEXT0		BIT(6)
-#define CTRL3_USB2_VBUSVLDEXTSEL0	BIT(5)
-
-#define CTRL5_USB2_SIDDQ		BIT(0)
-
-#define CTRL7_USB2_REFCLKSEL_MASK	GENMASK(4, 3)
-#define CTRL7_USB2_REFCLKSEL_ABB	(BIT(4) | BIT(3))
-#define CTRL7_USB2_REFCLKSEL_PAD	BIT(4)
-
-#define CFG50_USB3_PHY_TEST_POWERDOWN	BIT(23)
-
-#define CFG54_USB31PHY_CR_ADDR_MASK	GENMASK(31, 16)
-
-#define CFG54_USB3PHY_REF_USE_PAD	BIT(12)
-#define CFG54_PHY0_PMA_PWR_STABLE	BIT(11)
-#define CFG54_PHY0_PCS_PWR_STABLE	BIT(9)
-#define CFG54_USB31PHY_CR_ACK		BIT(7)
-#define CFG54_USB31PHY_CR_WR_EN		BIT(5)
-#define CFG54_USB31PHY_CR_SEL		BIT(4)
-#define CFG54_USB31PHY_CR_RD_EN		BIT(3)
-#define CFG54_USB31PHY_CR_CLK		BIT(2)
-#define CFG54_USB3_PHY0_ANA_PWR_EN	BIT(1)
-
-#define CFG58_USB31PHY_CR_DATA_MASK     GENMASK(31, 16)
-
-#define CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN	BIT(1)
-
-#define CFGA0_VAUX_RESET		BIT(9)
-#define CFGA0_USB31C_RESET		BIT(8)
-#define CFGA0_USB2PHY_REFCLK_SELECT	BIT(4)
-#define CFGA0_USB3PHY_RESET		BIT(1)
-#define CFGA0_USB2PHY_POR		BIT(0)
-
-#define INTR_EN_XA_TIMEOUT_EVT_EN	BIT(1)
-#define INTR_EN_XA_ACK_EVT_EN		BIT(0)
-
-#define CLK_RST_TCA_REF_CLK_EN		BIT(1)
-#define CLK_RST_SUSPEND_CLK_EN		BIT(0)
-
-#define GCFG_ROLE_HSTDEV		BIT(4)
-#define GCFG_OP_MODE			GENMASK(1, 0)
-#define GCFG_OP_MODE_CTRL_SYNC_MODE	BIT(0)
-
-#define TCPC_VALID			BIT(4)
-#define TCPC_LOW_POWER_EN		BIT(3)
-#define TCPC_MUX_CONTROL_MASK		GENMASK(1, 0)
-#define TCPC_MUX_CONTROL_USB31		BIT(0)
-
-#define SYSMODE_CFG_TYPEC_DISABLE	BIT(3)
-
-#define VBUS_CTRL_POWERPRESENT_OVERRD	GENMASK(3, 2)
-#define VBUS_CTRL_VBUSVALID_OVERRD	GENMASK(1, 0)
-
-#define KIRIN970_USB_DEFAULT_PHY_PARAM	(0xfdfee4)
-#define KIRIN970_USB_DEFAULT_PHY_VBOOST	(0x5)
-
-#define TX_VBOOST_LVL_REG		(0xf)
-#define TX_VBOOST_LVL_START		(6)
-#define TX_VBOOST_LVL_ENABLE		BIT(9)
-
-struct hi3670_priv {
-	struct device *dev;
-	struct regmap *peri_crg;
-	struct regmap *pctrl;
-	struct regmap *sctrl;
-	struct regmap *usb31misc;
-
-	u32 eye_diagram_param;
-	u32 tx_vboost_lvl;
-
-	u32 peri_crg_offset;
-	u32 pctrl_offset;
-	u32 usb31misc_offset;
-};
-
-static int hi3670_phy_cr_clk(struct regmap *usb31misc)
-{
-	int ret;
-
-	/* Clock up */
-	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				 CFG54_USB31PHY_CR_CLK, CFG54_USB31PHY_CR_CLK);
-	if (ret)
-		return ret;
-
-	/* Clock down */
-	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				  CFG54_USB31PHY_CR_CLK, 0);
-}
-
-static int hi3670_phy_cr_set_sel(struct regmap *usb31misc)
-{
-	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				  CFG54_USB31PHY_CR_SEL, CFG54_USB31PHY_CR_SEL);
-}
-
-static int hi3670_phy_cr_start(struct regmap *usb31misc, int direction)
-{
-	int ret, reg;
-
-	if (direction)
-		reg = CFG54_USB31PHY_CR_WR_EN;
-	else
-		reg = CFG54_USB31PHY_CR_RD_EN;
-
-	ret = regmap_update_bits(usb31misc, USB_MISC_CFG54, reg, reg);
-
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_clk(usb31misc);
-	if (ret)
-		return ret;
-
-	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				  CFG54_USB31PHY_CR_RD_EN | CFG54_USB31PHY_CR_WR_EN, 0);
-}
-
-static int hi3670_phy_cr_wait_ack(struct regmap *usb31misc)
-{
-	u32 reg;
-	int retry = 10;
-	int ret;
-
-	while (retry-- > 0) {
-		ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
-		if (ret)
-			return ret;
-		if ((reg & CFG54_USB31PHY_CR_ACK) == CFG54_USB31PHY_CR_ACK)
-			return 0;
-
-		ret = hi3670_phy_cr_clk(usb31misc);
-		if (ret)
-			return ret;
-
-		usleep_range(10, 20);
-	}
-
-	return -ETIMEDOUT;
-}
-
-static int hi3670_phy_cr_set_addr(struct regmap *usb31misc, u32 addr)
-{
-	u32 reg;
-	int ret;
-
-	ret = regmap_read(usb31misc, USB_MISC_CFG54, &reg);
-	if (ret)
-		return ret;
-
-	reg = FIELD_PREP(CFG54_USB31PHY_CR_ADDR_MASK, addr);
-
-	return regmap_update_bits(usb31misc, USB_MISC_CFG54,
-				  CFG54_USB31PHY_CR_ADDR_MASK, reg);
-}
-
-static int hi3670_phy_cr_read(struct regmap *usb31misc, u32 addr, u32 *val)
-{
-	int reg, i, ret;
-
-	for (i = 0; i < 100; i++) {
-		ret = hi3670_phy_cr_clk(usb31misc);
-		if (ret)
-			return ret;
-	}
-
-	ret = hi3670_phy_cr_set_sel(usb31misc);
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_start(usb31misc, 0);
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_wait_ack(usb31misc);
-	if (ret)
-		return ret;
-
-	ret = regmap_read(usb31misc, USB_MISC_CFG58, &reg);
-	if (ret)
-		return ret;
-
-	*val = FIELD_GET(CFG58_USB31PHY_CR_DATA_MASK, reg);
-
-	return 0;
-}
-
-static int hi3670_phy_cr_write(struct regmap *usb31misc, u32 addr, u32 val)
-{
-	int i;
-	int ret;
-
-	for (i = 0; i < 100; i++) {
-		ret = hi3670_phy_cr_clk(usb31misc);
-		if (ret)
-			return ret;
-	}
-
-	ret = hi3670_phy_cr_set_sel(usb31misc);
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_set_addr(usb31misc, addr);
-	if (ret)
-		return ret;
-
-	ret = regmap_write(usb31misc, USB_MISC_CFG58,
-			   FIELD_PREP(CFG58_USB31PHY_CR_DATA_MASK, val));
-	if (ret)
-		return ret;
-
-	ret = hi3670_phy_cr_start(usb31misc, 1);
-	if (ret)
-		return ret;
-
-	return hi3670_phy_cr_wait_ack(usb31misc);
-}
-
-static int hi3670_phy_set_params(struct hi3670_priv *priv)
-{
-	u32 reg;
-	int ret;
-	int retry = 3;
-
-	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL4,
-			   priv->eye_diagram_param);
-	if (ret) {
-		dev_err(priv->dev, "set USB3OTG_CTRL4 failed\n");
-		return ret;
-	}
-
-	while (retry-- > 0) {
-		ret = hi3670_phy_cr_read(priv->usb31misc,
-					 TX_VBOOST_LVL_REG, &reg);
-		if (!ret)
-			break;
-
-		if (ret != -ETIMEDOUT) {
-			dev_err(priv->dev, "read TX_VBOOST_LVL_REG failed\n");
-			return ret;
-		}
-	}
-	if (ret)
-		return ret;
-
-	reg |= (TX_VBOOST_LVL_ENABLE | (priv->tx_vboost_lvl << TX_VBOOST_LVL_START));
-	ret = hi3670_phy_cr_write(priv->usb31misc, TX_VBOOST_LVL_REG, reg);
-	if (ret)
-		dev_err(priv->dev, "write TX_VBOOST_LVL_REG failed\n");
-
-	return ret;
-}
-
-static bool hi3670_is_abbclk_selected(struct hi3670_priv *priv)
-{
-	u32 reg;
-
-	if (!priv->sctrl) {
-		dev_err(priv->dev, "priv->sctrl is null!\n");
-		return false;
-	}
-
-	if (regmap_read(priv->sctrl, SCTRL_SCDEEPSLEEPED, &reg)) {
-		dev_err(priv->dev, "SCTRL_SCDEEPSLEEPED read failed!\n");
-		return false;
-	}
-
-	if ((reg & USB_CLK_SELECTED) == 0)
-		return false;
-
-	return true;
-}
-
-static int hi3670_config_phy_clock(struct hi3670_priv *priv)
-{
-	u32 val, mask;
-	int ret;
-
-	if (!hi3670_is_abbclk_selected(priv)) {
-		/* usb refclk iso disable */
-		ret = regmap_write(priv->peri_crg, PERI_CRG_ISODIS,
-				   USB_REFCLK_ISO_EN);
-		if (ret)
-			goto out;
-
-		/* enable usb_tcxo_en */
-		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
-				   USB_TCXO_EN |
-				   (USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START));
-
-		/* select usbphy clk from abb */
-		mask = SC_CLK_USB3PHY_3MUX1_SEL;
-		ret = regmap_update_bits(priv->pctrl,
-					 PCTRL_PERI_CTRL24, mask, 0);
-		if (ret)
-			goto out;
-
-		ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
-					 CFGA0_USB2PHY_REFCLK_SELECT, 0);
-		if (ret)
-			goto out;
-
-		ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
-		if (ret)
-			goto out;
-		val &= ~CTRL7_USB2_REFCLKSEL_MASK;
-		val |= CTRL7_USB2_REFCLKSEL_ABB;
-		ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
-		if (ret)
-			goto out;
-
-		return 0;
-	}
-
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
-				 CFG54_USB3PHY_REF_USE_PAD,
-				 CFG54_USB3PHY_REF_USE_PAD);
-	if (ret)
-		goto out;
-
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0,
-				 CFGA0_USB2PHY_REFCLK_SELECT,
-				 CFGA0_USB2PHY_REFCLK_SELECT);
-	if (ret)
-		goto out;
-
-	ret = regmap_read(priv->usb31misc, USB3OTG_CTRL7, &val);
-	if (ret)
-		goto out;
-	val &= ~CTRL7_USB2_REFCLKSEL_MASK;
-	val |= CTRL7_USB2_REFCLKSEL_PAD;
-	ret = regmap_write(priv->usb31misc, USB3OTG_CTRL7, val);
-	if (ret)
-		goto out;
-
-	ret = regmap_write(priv->peri_crg,
-			   PERI_CRG_PEREN6, GT_CLK_USB2PHY_REF);
-	if (ret)
-		goto out;
-
-	return 0;
-out:
-	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
-	return ret;
-}
-
-static int hi3670_config_tca(struct hi3670_priv *priv)
-{
-	u32 val, mask;
-	int ret;
-
-	ret = regmap_write(priv->usb31misc, TCA_INTR_STS, 0xffff);
-	if (ret)
-		goto out;
-
-	ret = regmap_write(priv->usb31misc, TCA_INTR_EN,
-			   INTR_EN_XA_TIMEOUT_EVT_EN | INTR_EN_XA_ACK_EVT_EN);
-	if (ret)
-		goto out;
-
-	mask = CLK_RST_TCA_REF_CLK_EN | CLK_RST_SUSPEND_CLK_EN;
-	ret = regmap_update_bits(priv->usb31misc, TCA_CLK_RST, mask, 0);
-	if (ret)
-		goto out;
-
-	ret = regmap_update_bits(priv->usb31misc, TCA_GCFG,
-				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE,
-				 GCFG_ROLE_HSTDEV | GCFG_OP_MODE_CTRL_SYNC_MODE);
-	if (ret)
-		goto out;
-
-	ret = regmap_update_bits(priv->usb31misc, TCA_SYSMODE_CFG,
-				 SYSMODE_CFG_TYPEC_DISABLE, 0);
-	if (ret)
-		goto out;
-
-	ret = regmap_read(priv->usb31misc, TCA_TCPC, &val);
-	if (ret)
-		goto out;
-	val &= ~(TCPC_VALID | TCPC_LOW_POWER_EN | TCPC_MUX_CONTROL_MASK);
-	val |= (TCPC_VALID | TCPC_MUX_CONTROL_USB31);
-	ret = regmap_write(priv->usb31misc, TCA_TCPC, val);
-	if (ret)
-		goto out;
-
-	ret = regmap_write(priv->usb31misc, TCA_VBUS_CTRL,
-			   VBUS_CTRL_POWERPRESENT_OVERRD | VBUS_CTRL_VBUSVALID_OVERRD);
-	if (ret)
-		goto out;
-
-	return 0;
-out:
-	dev_err(priv->dev, "failed to config phy clock ret: %d\n", ret);
-	return ret;
-}
-
-static int hi3670_phy_init(struct phy *phy)
-{
-	struct hi3670_priv *priv = phy_get_drvdata(phy);
-	u32 val;
-	int ret;
-
-	/* assert controller */
-	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET |
-	      CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, 0);
-	if (ret)
-		goto out;
-
-	ret = hi3670_config_phy_clock(priv);
-	if (ret)
-		goto out;
-
-	/* Exit from IDDQ mode */
-	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL5,
-				 CTRL5_USB2_SIDDQ, 0);
-	if (ret)
-		goto out;
-
-	/* Release USB31 PHY out of TestPowerDown mode */
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG50,
-				 CFG50_USB3_PHY_TEST_POWERDOWN, 0);
-	if (ret)
-		goto out;
-
-	/* Deassert phy */
-	val = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
-	if (ret)
-		goto out;
-
-	usleep_range(100, 120);
-
-	/* Tell the PHY power is stable */
-	val = CFG54_USB3_PHY0_ANA_PWR_EN | CFG54_PHY0_PCS_PWR_STABLE |
-	      CFG54_PHY0_PMA_PWR_STABLE;
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG54,
-				 val, val);
-	if (ret)
-		goto out;
-
-	ret = hi3670_config_tca(priv);
-	if (ret)
-		goto out;
-
-	/* Enable SSC */
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFG5C,
-				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN,
-				 CFG5C_USB3_PHY0_SS_MPLLA_SSC_EN);
-	if (ret)
-		goto out;
-
-	/* Deassert controller */
-	val = CFGA0_VAUX_RESET | CFGA0_USB31C_RESET;
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, val, val);
-	if (ret)
-		goto out;
-
-	usleep_range(100, 120);
-
-	/* Set fake vbus valid signal */
-	val = CTRL0_USB3_VBUSVLD | CTRL0_USB3_VBUSVLD_SEL;
-	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL0, val, val);
-	if (ret)
-		goto out;
-
-	val = CTRL3_USB2_VBUSVLDEXT0 | CTRL3_USB2_VBUSVLDEXTSEL0;
-	ret = regmap_update_bits(priv->usb31misc, USB3OTG_CTRL3, val, val);
-	if (ret)
-		goto out;
-
-	usleep_range(100, 120);
-
-	ret = hi3670_phy_set_params(priv);
-	if (ret)
-		goto out;
-
-	return 0;
-out:
-	dev_err(priv->dev, "failed to init phy ret: %d\n", ret);
-	return ret;
-}
-
-static int hi3670_phy_exit(struct phy *phy)
-{
-	struct hi3670_priv *priv = phy_get_drvdata(phy);
-	u32 mask;
-	int ret;
-
-	/* Assert phy */
-	mask = CFGA0_USB3PHY_RESET | CFGA0_USB2PHY_POR;
-	ret = regmap_update_bits(priv->usb31misc, USB_MISC_CFGA0, mask, 0);
-	if (ret)
-		goto out;
-
-	if (!hi3670_is_abbclk_selected(priv)) {
-		/* disable usb_tcxo_en */
-		ret = regmap_write(priv->pctrl, PCTRL_PERI_CTRL3,
-				   USB_TCXO_EN << PCTRL_PERI_CTRL3_MSK_START);
-	} else {
-		ret = regmap_write(priv->peri_crg, PERI_CRG_PERDIS6,
-				   GT_CLK_USB2PHY_REF);
-		if (ret)
-			goto out;
-	}
-
-	return 0;
-out:
-	dev_err(priv->dev, "failed to exit phy ret: %d\n", ret);
-	return ret;
-}
-
-static const struct phy_ops hi3670_phy_ops = {
-	.init		= hi3670_phy_init,
-	.exit		= hi3670_phy_exit,
-	.owner		= THIS_MODULE,
-};
-
-static int hi3670_phy_probe(struct platform_device *pdev)
-{
-	struct phy_provider *phy_provider;
-	struct device *dev = &pdev->dev;
-	struct phy *phy;
-	struct hi3670_priv *priv;
-
-	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv)
-		return -ENOMEM;
-
-	priv->dev = dev;
-	priv->peri_crg = syscon_regmap_lookup_by_phandle(dev->of_node,
-							 "hisilicon,pericrg-syscon");
-	if (IS_ERR(priv->peri_crg)) {
-		dev_err(dev, "no hisilicon,pericrg-syscon\n");
-		return PTR_ERR(priv->peri_crg);
-	}
-
-	priv->pctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
-						      "hisilicon,pctrl-syscon");
-	if (IS_ERR(priv->pctrl)) {
-		dev_err(dev, "no hisilicon,pctrl-syscon\n");
-		return PTR_ERR(priv->pctrl);
-	}
-
-	priv->sctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
-						      "hisilicon,sctrl-syscon");
-	if (IS_ERR(priv->sctrl)) {
-		dev_err(dev, "no hisilicon,sctrl-syscon\n");
-		return PTR_ERR(priv->sctrl);
-	}
-
-	/* node of hi3670 phy is a sub-node of usb3_otg_bc */
-	priv->usb31misc = syscon_node_to_regmap(dev->parent->of_node);
-	if (IS_ERR(priv->usb31misc)) {
-		dev_err(dev, "no hisilicon,usb3-otg-bc-syscon\n");
-		return PTR_ERR(priv->usb31misc);
-	}
-
-	if (of_property_read_u32(dev->of_node, "hisilicon,eye-diagram-param",
-				 &priv->eye_diagram_param))
-		priv->eye_diagram_param = KIRIN970_USB_DEFAULT_PHY_PARAM;
-
-	if (of_property_read_u32(dev->of_node, "hisilicon,tx-vboost-lvl",
-				 &priv->tx_vboost_lvl))
-		priv->tx_vboost_lvl = KIRIN970_USB_DEFAULT_PHY_VBOOST;
-
-	phy = devm_phy_create(dev, NULL, &hi3670_phy_ops);
-	if (IS_ERR(phy))
-		return PTR_ERR(phy);
-
-	phy_set_drvdata(phy, priv);
-	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	return PTR_ERR_OR_ZERO(phy_provider);
-}
-
-static const struct of_device_id hi3670_phy_of_match[] = {
-	{ .compatible = "hisilicon,hi3670-usb-phy" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, hi3670_phy_of_match);
-
-static struct platform_driver hi3670_phy_driver = {
-	.probe	= hi3670_phy_probe,
-	.driver = {
-		.name	= "hi3670-usb-phy",
-		.of_match_table	= hi3670_phy_of_match,
-	}
-};
-module_platform_driver(hi3670_phy_driver);
-
-MODULE_AUTHOR("Yu Chen <chenyu56@huawei.com>");
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Hilisicon Kirin970 USB31 PHY Driver");
diff --git a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml b/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
deleted file mode 100644
index ebd78acfe2de..000000000000
--- a/drivers/staging/hikey9xx/phy-hi3670-usb3.yaml
+++ /dev/null
@@ -1,73 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/phy/hisilicon,hi3670-usb3.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Hisilicon Kirin970 USB PHY
-
-maintainers:
-  - Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-
-description: |+
-  Bindings for USB3 PHY on HiSilicon Kirin 970.
-
-properties:
-  compatible:
-    const: hisilicon,hi3670-usb-phy
-
-  "#phy-cells":
-    const: 0
-
-  hisilicon,pericrg-syscon:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
-    description: phandle of syscon used to control iso refclk.
-
-  hisilicon,pctrl-syscon:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
-    description: phandle of syscon used to control usb tcxo.
-
-  hisilicon,sctrl-syscon:
-    $ref: '/schemas/types.yaml#/definitions/phandle'
-    description: phandle of syscon used to control phy deep sleep.
-
-  hisilicon,eye-diagram-param:
-    $ref: /schemas/types.yaml#/definitions/uint32
-    description: Eye diagram for phy.
-
-  hisilicon,tx-vboost-lvl:
-    $ref: /schemas/types.yaml#/definitions/uint32
-    description: TX level vboost for phy.
-
-required:
-  - compatible
-  - hisilicon,pericrg-syscon
-  - hisilicon,pctrl-syscon
-  - hisilicon,sctrl-syscon
-  - hisilicon,eye-diagram-param
-  - hisilicon,tx-vboost-lvl
-  - "#phy-cells"
-
-additionalProperties: false
-
-examples:
-  - |
-    bus {
-      #address-cells = <2>;
-      #size-cells = <2>;
-
-      usb3_otg_bc: usb3_otg_bc@ff200000 {
-        compatible = "syscon", "simple-mfd";
-        reg = <0x0 0xff200000 0x0 0x1000>;
-
-        usb_phy {
-          compatible = "hisilicon,hi3670-usb-phy";
-          #phy-cells = <0>;
-          hisilicon,pericrg-syscon = <&crg_ctrl>;
-          hisilicon,pctrl-syscon = <&pctrl>;
-          hisilicon,sctrl-syscon = <&sctrl>;
-          hisilicon,eye-diagram-param = <0xfdfee4>;
-          hisilicon,tx-vboost-lvl = <0x5>;
-        };
-      };
-    };
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 5/8] spmi: hisi-spmi-controller: move driver from staging
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
                   ` (3 preceding siblings ...)
  2021-06-24  9:01 ` [PATCH RESEND v6 4/8] phy: phy-hi3670-usb3: move driver from staging into phy Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: " Mauro Carvalho Chehab
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, Rob Herring,
	Stephen Boyd, devicetree, linux-kernel, linux-staging

The Hisilicon 6421v600 SPMI driver is ready for mainstream.

So, move it from staging.

Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
---
 .../spmi/hisilicon,hisi-spmi-controller.yaml  |  73 ++++
 MAINTAINERS                                   |   7 +
 drivers/spmi/Kconfig                          |   9 +
 drivers/spmi/Makefile                         |   1 +
 drivers/spmi/hisi-spmi-controller.c           | 367 ++++++++++++++++++
 drivers/staging/hikey9xx/Kconfig              |  11 -
 drivers/staging/hikey9xx/Makefile             |   1 -
 .../staging/hikey9xx/hisi-spmi-controller.c   | 367 ------------------
 .../hisilicon,hisi-spmi-controller.yaml       |  73 ----
 9 files changed, 457 insertions(+), 452 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..f882903769f9
--- /dev/null
+++ b/Documentation/devicetree/bindings/spmi/hisilicon,hisi-spmi-controller.yaml
@@ -0,0 +1,73 @@
+# 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
+  ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml.
+
+allOf:
+  - $ref: spmi.yaml#
+
+properties:
+
+  $nodename:
+    pattern: "spmi@[0-9a-f]"
+
+  compatible:
+    const: hisilicon,kirin970-spmi-controller
+
+  reg:
+    maxItems: 1
+
+  hisilicon,spmi-channel:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      number of the Kirin 970 SPMI channel where the SPMI devices are connected.
+
+required:
+  - compatible
+  - reg
+  - hisilicon,spmi-channel
+
+patternProperties:
+  "@[0-9a-f]$":
+    type: object
+
+    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.
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+
+      spmi: spmi@fff24000 {
+        compatible = "hisilicon,kirin970-spmi-controller";
+        #address-cells = <2>;
+        #size-cells = <0>;
+        reg = <0x0 0xfff24000 0x0 0x1000>;
+        hisilicon,spmi-channel = <2>;
+
+        pmic@0 {
+          reg = <0 0>;
+          /* pmic properties */
+        };
+      };
+    };
diff --git a/MAINTAINERS b/MAINTAINERS
index 6e01424234eb..9a69e3810964 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8284,6 +8284,13 @@ S:	Maintained
 W:	http://www.hisilicon.com
 F:	drivers/spi/spi-hisi-kunpeng.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>
 S:	Maintained
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..5bd23262abd6
--- /dev/null
+++ b/drivers/spmi/hisi-spmi-controller.c
@@ -0,0 +1,367 @@
+// 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((__be32 __force)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((u32 __force)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");
+		ret = -EINVAL;
+		goto err_put_controller;
+	}
+
+	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");
+		ret = -EADDRNOTAVAIL;
+		goto err_put_controller;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
+				   &spmi_controller->channel);
+	if (ret) {
+		dev_err(&pdev->dev, "can not get channel\n");
+		ret = -ENODEV;
+		goto err_put_controller;
+	}
+
+	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_controller_add failed with error %d!\n", ret);
+		goto err_put_controller;
+	}
+
+	return 0;
+
+err_put_controller:
+	spmi_controller_put(ctrl);
+	return ret;
+}
+
+static int spmi_del_controller(struct platform_device *pdev)
+{
+	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
+
+	spmi_controller_remove(ctrl);
+	spmi_controller_put(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 3ceda03f2864..9f53df9068fe 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 42d486104525..e3108d7dd849 100644
--- a/drivers/staging/hikey9xx/Makefile
+++ b/drivers/staging/hikey9xx/Makefile
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_SPMI_HISI3670)		+= hisi-spmi-controller.o
 obj-$(CONFIG_MFD_HI6421_SPMI)		+= hi6421-spmi-pmic.o
diff --git a/drivers/staging/hikey9xx/hisi-spmi-controller.c b/drivers/staging/hikey9xx/hisi-spmi-controller.c
deleted file mode 100644
index 5bd23262abd6..000000000000
--- a/drivers/staging/hikey9xx/hisi-spmi-controller.c
+++ /dev/null
@@ -1,367 +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((__be32 __force)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((u32 __force)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");
-		ret = -EINVAL;
-		goto err_put_controller;
-	}
-
-	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");
-		ret = -EADDRNOTAVAIL;
-		goto err_put_controller;
-	}
-
-	ret = of_property_read_u32(pdev->dev.of_node, "hisilicon,spmi-channel",
-				   &spmi_controller->channel);
-	if (ret) {
-		dev_err(&pdev->dev, "can not get channel\n");
-		ret = -ENODEV;
-		goto err_put_controller;
-	}
-
-	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_controller_add failed with error %d!\n", ret);
-		goto err_put_controller;
-	}
-
-	return 0;
-
-err_put_controller:
-	spmi_controller_put(ctrl);
-	return ret;
-}
-
-static int spmi_del_controller(struct platform_device *pdev)
-{
-	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
-
-	spmi_controller_remove(ctrl);
-	spmi_controller_put(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 f882903769f9..000000000000
--- a/drivers/staging/hikey9xx/hisilicon,hisi-spmi-controller.yaml
+++ /dev/null
@@ -1,73 +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
-  ./Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml.
-
-allOf:
-  - $ref: spmi.yaml#
-
-properties:
-
-  $nodename:
-    pattern: "spmi@[0-9a-f]"
-
-  compatible:
-    const: hisilicon,kirin970-spmi-controller
-
-  reg:
-    maxItems: 1
-
-  hisilicon,spmi-channel:
-    $ref: /schemas/types.yaml#/definitions/uint32
-    description: |
-      number of the Kirin 970 SPMI channel where the SPMI devices are connected.
-
-required:
-  - compatible
-  - reg
-  - hisilicon,spmi-channel
-
-patternProperties:
-  "@[0-9a-f]$":
-    type: object
-
-    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.
-
-unevaluatedProperties: false
-
-examples:
-  - |
-    bus {
-      #address-cells = <2>;
-      #size-cells = <2>;
-
-      spmi: spmi@fff24000 {
-        compatible = "hisilicon,kirin970-spmi-controller";
-        #address-cells = <2>;
-        #size-cells = <0>;
-        reg = <0x0 0xfff24000 0x0 0x1000>;
-        hisilicon,spmi-channel = <2>;
-
-        pmic@0 {
-          reg = <0 0>;
-          /* pmic properties */
-        };
-      };
-    };
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
                   ` (4 preceding siblings ...)
  2021-06-24  9:01 ` [PATCH RESEND v6 5/8] spmi: hisi-spmi-controller: move driver from staging Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24 11:33   ` Lee Jones
  2021-06-24 15:26   ` Rob Herring
  2021-06-24  9:01 ` [PATCH RESEND v6 7/8] dts: hisilicon: add support for the PMIC found on Hikey 970 Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 8/8] dts: hisilicon: add support for USB3 " Mauro Carvalho Chehab
  7 siblings, 2 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, Mauro Carvalho Chehab, Lee Jones,
	Rob Herring, devicetree, linux-kernel, linux-staging

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       | 134 ++++++++
 MAINTAINERS                                   |   7 +
 drivers/mfd/Kconfig                           |  16 +
 drivers/mfd/Makefile                          |   1 +
 drivers/mfd/hi6421-spmi-pmic.c                | 316 ++++++++++++++++++
 drivers/staging/Kconfig                       |   2 -
 drivers/staging/Makefile                      |   1 -
 drivers/staging/hikey9xx/Kconfig              |  19 --
 drivers/staging/hikey9xx/Makefile             |   3 -
 drivers/staging/hikey9xx/TODO                 |   5 -
 drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 316 ------------------
 .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 134 --------
 12 files changed, 474 insertions(+), 480 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/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/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..8e355cddd437
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
@@ -0,0 +1,134 @@
+# 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
+  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
+
+properties:
+  $nodename:
+    pattern: "pmic@[0-9a-f]"
+
+  compatible:
+    const: hisilicon,hi6421v600-spmi
+
+  reg:
+    maxItems: 1
+
+  '#interrupt-cells':
+    const: 2
+
+  interrupt-controller: true
+
+  gpios:
+    maxItems: 1
+    description: GPIO used for IRQs
+
+  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
+
+additionalProperties: false
+
+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 9a69e3810964..89e84b050de6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8291,6 +8291,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>
 S:	Maintained
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 5c7f2b100191..99b8da2548b5 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -509,6 +509,22 @@ 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
+	select REGMAP_SPMI
+	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 4f6d2b8a5f76..e87230fc61ac 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -232,6 +232,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..2b7172560df7
--- /dev/null
+++ b/drivers/mfd/hi6421-spmi-pmic.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device driver for regulators in HISI PMIC IC
+ *
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2011 Hisilicon.
+ * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
+ */
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+
+enum hi6421_spmi_pmic_irq_list {
+	OTMP = 0,
+	VBUS_CONNECT,
+	VBUS_DISCONNECT,
+	ALARMON_R,
+	HOLD_6S,
+	HOLD_1S,
+	POWERKEY_UP,
+	POWERKEY_DOWN,
+	OCP_SCP_R,
+	COUL_R,
+	SIM0_HPD_R,
+	SIM0_HPD_F,
+	SIM1_HPD_R,
+	SIM1_HPD_F,
+
+	PMIC_IRQ_LIST_MAX
+};
+
+#define HISI_IRQ_BANK_SIZE		2
+
+/*
+ * IRQ number for the power key button and mask for both UP and DOWN IRQs
+ */
+#define HISI_POWERKEY_IRQ_NUM		0
+#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
+
+/*
+ * Registers for IRQ address and IRQ mask bits
+ *
+ * Please notice that we need to regmap a larger region, as other
+ * registers are used by the regulators.
+ * See drivers/regulator/hi6421-regulator.c.
+ */
+#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
+#define SOC_PMIC_IRQ0_ADDR		0x0212
+
+/*
+ * The IRQs are mapped as:
+ *
+ *	======================  =============   ============	=====
+ *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
+ *	======================  =============   ============	=====
+ *	OTMP			0x0202		0x212		bit 0
+ *	VBUS_CONNECT		0x0202		0x212		bit 1
+ *	VBUS_DISCONNECT		0x0202		0x212		bit 2
+ *	ALARMON_R		0x0202		0x212		bit 3
+ *	HOLD_6S			0x0202		0x212		bit 4
+ *	HOLD_1S			0x0202		0x212		bit 5
+ *	POWERKEY_UP		0x0202		0x212		bit 6
+ *	POWERKEY_DOWN		0x0202		0x212		bit 7
+ *
+ *	OCP_SCP_R		0x0203		0x213		bit 0
+ *	COUL_R			0x0203		0x213		bit 1
+ *	SIM0_HPD_R		0x0203		0x213		bit 2
+ *	SIM0_HPD_F		0x0203		0x213		bit 3
+ *	SIM1_HPD_R		0x0203		0x213		bit 4
+ *	SIM1_HPD_F		0x0203		0x213		bit 5
+ *	======================  =============   ============	=====
+ *
+ * Each mask register contains 8 bits. The ancillary macros below
+ * convert a number from 0 to 14 into a register address and a bit mask
+ */
+#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
+					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
+#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
+#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)
+
+static const struct mfd_cell hi6421v600_devs[] = {
+	{ .name = "hi6421v600-regulator", },
+};
+
+static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
+{
+	struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
+	unsigned long pending;
+	unsigned int in;
+	int i, offset;
+
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
+		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
+
+		/* Mark pending IRQs as handled */
+		pending = HISI_8BITS_MASK & in;
+		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
+
+		if (i == HISI_POWERKEY_IRQ_NUM &&
+		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
+			/*
+			 * If both powerkey down and up IRQs are received,
+			 * handle them at the right order
+			 */
+			generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
+			generic_handle_irq(ddata->irqs[POWERKEY_UP]);
+			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
+		}
+
+		if (!pending)
+			continue;
+
+		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
+			generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void hi6421_spmi_irq_mask(struct irq_data *d)
+{
+	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
+	unsigned long flags;
+	unsigned int data;
+	u32 offset;
+
+	offset = HISI_IRQ_MASK_REG(d);
+
+	spin_lock_irqsave(&ddata->lock, flags);
+
+	regmap_read(ddata->regmap, offset, &data);
+	data |= HISI_IRQ_MASK_BIT(d);
+	regmap_write(ddata->regmap, offset, data);
+
+	spin_unlock_irqrestore(&ddata->lock, flags);
+}
+
+static void hi6421_spmi_irq_unmask(struct irq_data *d)
+{
+	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
+	u32 data, offset;
+	unsigned long flags;
+
+	offset = HISI_IRQ_MASK_REG(d);
+
+	spin_lock_irqsave(&ddata->lock, flags);
+
+	regmap_read(ddata->regmap, offset, &data);
+	data &= ~HISI_IRQ_MASK_BIT(d);
+	regmap_write(ddata->regmap, offset, data);
+
+	spin_unlock_irqrestore(&ddata->lock, flags);
+}
+
+static struct irq_chip hi6421_spmi_pmu_irqchip = {
+	.name		= "hi6421v600-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 *ddata = d->host_data;
+
+	irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
+				      handle_simple_irq, "hi6421v600");
+	irq_set_chip_data(virq, ddata);
+	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_init(struct hi6421_spmi_pmic *ddata)
+{
+	int i;
+	unsigned int pending;
+
+	/* Mask all IRQs */
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
+		regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
+			     HISI_8BITS_MASK);
+
+	/* Mark all IRQs as handled */
+	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
+		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
+		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
+			     HISI_8BITS_MASK);
+	}
+}
+
+static const struct regmap_config regmap_config = {
+	.reg_bits		= 16,
+	.val_bits		= BITS_PER_BYTE,
+	.max_register		= 0xffff,
+	.fast_io		= true
+};
+
+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 *ddata;
+	unsigned int virq;
+	int ret, i;
+
+	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
+	if (!ddata)
+		return -ENOMEM;
+
+	ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
+	if (IS_ERR(ddata->regmap))
+		return PTR_ERR(ddata->regmap);
+
+	spin_lock_init(&ddata->lock);
+
+	ddata->dev = dev;
+
+	ddata->gpio = of_get_gpio(np, 0);
+	if (ddata->gpio < 0)
+		return ddata->gpio;
+
+	if (!gpio_is_valid(ddata->gpio))
+		return -EINVAL;
+
+	ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
+	if (ret < 0) {
+		dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
+		return ret;
+	}
+
+	ddata->irq = gpio_to_irq(ddata->gpio);
+
+	hi6421_spmi_pmic_irq_init(ddata);
+
+	ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
+	if (!ddata->irqs)
+		return -ENOMEM;
+
+	ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
+					      &hi6421_spmi_domain_ops, ddata);
+	if (!ddata->domain) {
+		dev_err(dev, "Failed to create IRQ domain\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
+		virq = irq_create_mapping(ddata->domain, i);
+		if (!virq) {
+			dev_err(dev, "Failed to map H/W IRQ\n");
+			return -ENOSPC;
+		}
+		ddata->irqs[i] = virq;
+	}
+
+	ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
+				   IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
+				   "pmic", ddata);
+	if (ret < 0) {
+		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
+			ret);
+		return ret;
+	}
+
+	dev_set_drvdata(&pdev->dev, ddata);
+
+	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
+				   hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
+				   NULL, 0, NULL);
+	if (ret < 0)
+		dev_err(dev, "Failed to add child devices: %d\n", ret);
+
+	return ret;
+}
+
+static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
+{
+	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
+
+	free_irq(ddata->irq, ddata);
+}
+
+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/Kconfig b/drivers/staging/Kconfig
index b7ae5bdc4eb5..5b4267d3ed6b 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -104,6 +104,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 075c979bfe7c..7179cdcaafe7 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -42,4 +42,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 9f53df9068fe..000000000000
--- a/drivers/staging/hikey9xx/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# 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 HAS_IOMEM
-	depends on OF
-	depends on SPMI
-	select MFD_CORE
-	select REGMAP_SPMI
-	help
-	  Add support for HiSilicon Hi6421v600 SPMI PMIC. Hi6421 includes
-	  multi-functions, such as regulators, RTC, codec, Coulomb counter,
-	  etc.
-
-	  This driver includes core APIs _only_. You have to select
-	  individual components like voltage regulators under corresponding
-	  menus in order to enable them.
-	  We communicate with the Hi6421v600 via a SPMI bus.
diff --git a/drivers/staging/hikey9xx/Makefile b/drivers/staging/hikey9xx/Makefile
deleted file mode 100644
index e3108d7dd849..000000000000
--- a/drivers/staging/hikey9xx/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_MFD_HI6421_SPMI)		+= hi6421-spmi-pmic.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/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
deleted file mode 100644
index 2b7172560df7..000000000000
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ /dev/null
@@ -1,316 +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.
- * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
- */
-
-#include <linux/bitops.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
-#include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/spmi.h>
-
-enum hi6421_spmi_pmic_irq_list {
-	OTMP = 0,
-	VBUS_CONNECT,
-	VBUS_DISCONNECT,
-	ALARMON_R,
-	HOLD_6S,
-	HOLD_1S,
-	POWERKEY_UP,
-	POWERKEY_DOWN,
-	OCP_SCP_R,
-	COUL_R,
-	SIM0_HPD_R,
-	SIM0_HPD_F,
-	SIM1_HPD_R,
-	SIM1_HPD_F,
-
-	PMIC_IRQ_LIST_MAX
-};
-
-#define HISI_IRQ_BANK_SIZE		2
-
-/*
- * IRQ number for the power key button and mask for both UP and DOWN IRQs
- */
-#define HISI_POWERKEY_IRQ_NUM		0
-#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
-
-/*
- * Registers for IRQ address and IRQ mask bits
- *
- * Please notice that we need to regmap a larger region, as other
- * registers are used by the regulators.
- * See drivers/regulator/hi6421-regulator.c.
- */
-#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
-#define SOC_PMIC_IRQ0_ADDR		0x0212
-
-/*
- * The IRQs are mapped as:
- *
- *	======================  =============   ============	=====
- *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
- *	======================  =============   ============	=====
- *	OTMP			0x0202		0x212		bit 0
- *	VBUS_CONNECT		0x0202		0x212		bit 1
- *	VBUS_DISCONNECT		0x0202		0x212		bit 2
- *	ALARMON_R		0x0202		0x212		bit 3
- *	HOLD_6S			0x0202		0x212		bit 4
- *	HOLD_1S			0x0202		0x212		bit 5
- *	POWERKEY_UP		0x0202		0x212		bit 6
- *	POWERKEY_DOWN		0x0202		0x212		bit 7
- *
- *	OCP_SCP_R		0x0203		0x213		bit 0
- *	COUL_R			0x0203		0x213		bit 1
- *	SIM0_HPD_R		0x0203		0x213		bit 2
- *	SIM0_HPD_F		0x0203		0x213		bit 3
- *	SIM1_HPD_R		0x0203		0x213		bit 4
- *	SIM1_HPD_F		0x0203		0x213		bit 5
- *	======================  =============   ============	=====
- *
- * Each mask register contains 8 bits. The ancillary macros below
- * convert a number from 0 to 14 into a register address and a bit mask
- */
-#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
-					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
-#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
-#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)
-
-static const struct mfd_cell hi6421v600_devs[] = {
-	{ .name = "hi6421v600-regulator", },
-};
-
-static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
-{
-	struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
-	unsigned long pending;
-	unsigned int in;
-	int i, offset;
-
-	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
-		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
-
-		/* Mark pending IRQs as handled */
-		pending = HISI_8BITS_MASK & in;
-		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
-
-		if (i == HISI_POWERKEY_IRQ_NUM &&
-		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
-			/*
-			 * If both powerkey down and up IRQs are received,
-			 * handle them at the right order
-			 */
-			generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
-			generic_handle_irq(ddata->irqs[POWERKEY_UP]);
-			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
-		}
-
-		if (!pending)
-			continue;
-
-		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
-			generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
-		}
-	}
-
-	return IRQ_HANDLED;
-}
-
-static void hi6421_spmi_irq_mask(struct irq_data *d)
-{
-	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
-	unsigned long flags;
-	unsigned int data;
-	u32 offset;
-
-	offset = HISI_IRQ_MASK_REG(d);
-
-	spin_lock_irqsave(&ddata->lock, flags);
-
-	regmap_read(ddata->regmap, offset, &data);
-	data |= HISI_IRQ_MASK_BIT(d);
-	regmap_write(ddata->regmap, offset, data);
-
-	spin_unlock_irqrestore(&ddata->lock, flags);
-}
-
-static void hi6421_spmi_irq_unmask(struct irq_data *d)
-{
-	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
-	u32 data, offset;
-	unsigned long flags;
-
-	offset = HISI_IRQ_MASK_REG(d);
-
-	spin_lock_irqsave(&ddata->lock, flags);
-
-	regmap_read(ddata->regmap, offset, &data);
-	data &= ~HISI_IRQ_MASK_BIT(d);
-	regmap_write(ddata->regmap, offset, data);
-
-	spin_unlock_irqrestore(&ddata->lock, flags);
-}
-
-static struct irq_chip hi6421_spmi_pmu_irqchip = {
-	.name		= "hi6421v600-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 *ddata = d->host_data;
-
-	irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
-				      handle_simple_irq, "hi6421v600");
-	irq_set_chip_data(virq, ddata);
-	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_init(struct hi6421_spmi_pmic *ddata)
-{
-	int i;
-	unsigned int pending;
-
-	/* Mask all IRQs */
-	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
-		regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
-			     HISI_8BITS_MASK);
-
-	/* Mark all IRQs as handled */
-	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
-		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
-		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
-			     HISI_8BITS_MASK);
-	}
-}
-
-static const struct regmap_config regmap_config = {
-	.reg_bits		= 16,
-	.val_bits		= BITS_PER_BYTE,
-	.max_register		= 0xffff,
-	.fast_io		= true
-};
-
-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 *ddata;
-	unsigned int virq;
-	int ret, i;
-
-	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
-	if (!ddata)
-		return -ENOMEM;
-
-	ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
-	if (IS_ERR(ddata->regmap))
-		return PTR_ERR(ddata->regmap);
-
-	spin_lock_init(&ddata->lock);
-
-	ddata->dev = dev;
-
-	ddata->gpio = of_get_gpio(np, 0);
-	if (ddata->gpio < 0)
-		return ddata->gpio;
-
-	if (!gpio_is_valid(ddata->gpio))
-		return -EINVAL;
-
-	ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
-	if (ret < 0) {
-		dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
-		return ret;
-	}
-
-	ddata->irq = gpio_to_irq(ddata->gpio);
-
-	hi6421_spmi_pmic_irq_init(ddata);
-
-	ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
-	if (!ddata->irqs)
-		return -ENOMEM;
-
-	ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
-					      &hi6421_spmi_domain_ops, ddata);
-	if (!ddata->domain) {
-		dev_err(dev, "Failed to create IRQ domain\n");
-		return -ENODEV;
-	}
-
-	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
-		virq = irq_create_mapping(ddata->domain, i);
-		if (!virq) {
-			dev_err(dev, "Failed to map H/W IRQ\n");
-			return -ENOSPC;
-		}
-		ddata->irqs[i] = virq;
-	}
-
-	ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
-				   IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
-				   "pmic", ddata);
-	if (ret < 0) {
-		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
-			ret);
-		return ret;
-	}
-
-	dev_set_drvdata(&pdev->dev, ddata);
-
-	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
-				   hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
-				   NULL, 0, NULL);
-	if (ret < 0)
-		dev_err(dev, "Failed to add child devices: %d\n", ret);
-
-	return ret;
-}
-
-static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
-{
-	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
-
-	free_irq(ddata->irq, ddata);
-}
-
-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 8e355cddd437..000000000000
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ /dev/null
@@ -1,134 +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
-  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
-
-properties:
-  $nodename:
-    pattern: "pmic@[0-9a-f]"
-
-  compatible:
-    const: hisilicon,hi6421v600-spmi
-
-  reg:
-    maxItems: 1
-
-  '#interrupt-cells':
-    const: 2
-
-  interrupt-controller: true
-
-  gpios:
-    maxItems: 1
-    description: GPIO used for IRQs
-
-  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
-
-additionalProperties: false
-
-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.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 7/8] dts: hisilicon: add support for the PMIC found on Hikey 970
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
                   ` (5 preceding siblings ...)
  2021-06-24  9:01 ` [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: " Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  2021-06-24  9:01 ` [PATCH RESEND v6 8/8] dts: hisilicon: add support for USB3 " Mauro Carvalho Chehab
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, 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 7f9f9886c349..5e6d7b329771 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";
@@ -402,8 +386,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..48c739eacba0
--- /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>;
+		hisilicon,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 { /* HDMI */
+					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 { /* USB HUB */
+					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.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH RESEND v6 8/8] dts: hisilicon: add support for USB3 on Hikey 970
  2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
                   ` (6 preceding siblings ...)
  2021-06-24  9:01 ` [PATCH RESEND v6 7/8] dts: hisilicon: add support for the PMIC found on Hikey 970 Mauro Carvalho Chehab
@ 2021-06-24  9:01 ` Mauro Carvalho Chehab
  7 siblings, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24  9:01 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linuxarm, mauro.chehab, 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    | 107 ++++++++++++++++++
 arch/arm64/boot/dts/hisilicon/hi3670.dtsi     |  56 +++++++++
 2 files changed, 163 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
index 5e6d7b329771..9e3dfe877ebe 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3670-hikey970.dts
@@ -53,6 +53,30 @@ 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>;
+			};
+		};
+	};
 };
 
 /*
@@ -430,3 +454,86 @@ &uart6 {
 	label = "LS-UART1";
 	status = "okay";
 };
+
+&usb_phy {
+	phy-supply = <&ldo17>;
+};
+
+&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 8830795c8efc..6476149d99e3 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";
@@ -785,5 +786,60 @@ 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>;
+			};
+		};
+
+		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: usb@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.31.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24  9:01 ` [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: " Mauro Carvalho Chehab
@ 2021-06-24 11:33   ` Lee Jones
  2021-06-24 12:36     ` Mauro Carvalho Chehab
  2021-06-24 15:26   ` Rob Herring
  1 sibling, 1 reply; 19+ messages in thread
From: Lee Jones @ 2021-06-24 11:33 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab, Rob Herring,
	devicetree, linux-kernel, linux-staging

On Thu, 24 Jun 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       | 134 ++++++++
>  MAINTAINERS                                   |   7 +
>  drivers/mfd/Kconfig                           |  16 +
>  drivers/mfd/Makefile                          |   1 +
>  drivers/mfd/hi6421-spmi-pmic.c                | 316 ++++++++++++++++++
>  drivers/staging/Kconfig                       |   2 -
>  drivers/staging/Makefile                      |   1 -
>  drivers/staging/hikey9xx/Kconfig              |  19 --
>  drivers/staging/hikey9xx/Makefile             |   3 -
>  drivers/staging/hikey9xx/TODO                 |   5 -
>  drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 316 ------------------
>  .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 134 --------
>  12 files changed, 474 insertions(+), 480 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/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/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..8e355cddd437
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> @@ -0,0 +1,134 @@
> +# 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
> +  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> +
> +properties:
> +  $nodename:
> +    pattern: "pmic@[0-9a-f]"
> +
> +  compatible:
> +    const: hisilicon,hi6421v600-spmi
> +
> +  reg:
> +    maxItems: 1
> +
> +  '#interrupt-cells':
> +    const: 2
> +
> +  interrupt-controller: true
> +
> +  gpios:
> +    maxItems: 1
> +    description: GPIO used for IRQs
> +
> +  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
> +
> +additionalProperties: false
> +
> +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 9a69e3810964..89e84b050de6 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -8291,6 +8291,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>
>  S:	Maintained
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 5c7f2b100191..99b8da2548b5 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -509,6 +509,22 @@ 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
> +	select REGMAP_SPMI
> +	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 4f6d2b8a5f76..e87230fc61ac 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -232,6 +232,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..2b7172560df7
> --- /dev/null
> +++ b/drivers/mfd/hi6421-spmi-pmic.c
> @@ -0,0 +1,316 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Device driver for regulators in HISI PMIC IC
> + *
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2011 Hisilicon.
> + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd

Can this be updated?

> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/mfd/core.h>
> +#include <linux/mfd/hi6421-spmi-pmic.h>
> +#include <linux/module.h>
> +#include <linux/of_gpio.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/spmi.h>
> +
> +enum hi6421_spmi_pmic_irq_list {
> +	OTMP = 0,
> +	VBUS_CONNECT,
> +	VBUS_DISCONNECT,
> +	ALARMON_R,
> +	HOLD_6S,
> +	HOLD_1S,
> +	POWERKEY_UP,
> +	POWERKEY_DOWN,
> +	OCP_SCP_R,
> +	COUL_R,
> +	SIM0_HPD_R,
> +	SIM0_HPD_F,
> +	SIM1_HPD_R,
> +	SIM1_HPD_F,
> +
> +	PMIC_IRQ_LIST_MAX
> +};
> +
> +#define HISI_IRQ_BANK_SIZE		2
> +
> +/*
> + * IRQ number for the power key button and mask for both UP and DOWN IRQs
> + */
> +#define HISI_POWERKEY_IRQ_NUM		0
> +#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
> +
> +/*
> + * Registers for IRQ address and IRQ mask bits
> + *
> + * Please notice that we need to regmap a larger region, as other
> + * registers are used by the regulators.
> + * See drivers/regulator/hi6421-regulator.c.
> + */
> +#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
> +#define SOC_PMIC_IRQ0_ADDR		0x0212
> +
> +/*
> + * The IRQs are mapped as:
> + *
> + *	======================  =============   ============	=====
> + *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
> + *	======================  =============   ============	=====
> + *	OTMP			0x0202		0x212		bit 0
> + *	VBUS_CONNECT		0x0202		0x212		bit 1
> + *	VBUS_DISCONNECT		0x0202		0x212		bit 2
> + *	ALARMON_R		0x0202		0x212		bit 3
> + *	HOLD_6S			0x0202		0x212		bit 4
> + *	HOLD_1S			0x0202		0x212		bit 5
> + *	POWERKEY_UP		0x0202		0x212		bit 6
> + *	POWERKEY_DOWN		0x0202		0x212		bit 7
> + *
> + *	OCP_SCP_R		0x0203		0x213		bit 0
> + *	COUL_R			0x0203		0x213		bit 1
> + *	SIM0_HPD_R		0x0203		0x213		bit 2
> + *	SIM0_HPD_F		0x0203		0x213		bit 3
> + *	SIM1_HPD_R		0x0203		0x213		bit 4
> + *	SIM1_HPD_F		0x0203		0x213		bit 5
> + *	======================  =============   ============	=====
> + *
> + * Each mask register contains 8 bits. The ancillary macros below
> + * convert a number from 0 to 14 into a register address and a bit mask
> + */
> +#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
> +					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
> +#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
> +#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)

Are these lines up in real code?  Looks like they're not in the diff.

HISI_8BITS_MASK is just 0xff right?  I think we're more used to seeing
the value used in place.  Creating a macro for it out of GENMASK is
probably slightly over-engineering it a little.

> +static const struct mfd_cell hi6421v600_devs[] = {
> +	{ .name = "hi6421v600-regulator", },
> +};

Where are the other devices?

> +static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
> +{
> +	struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
> +	unsigned long pending;
> +	unsigned int in;
> +	int i, offset;
> +
> +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
> +		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
> +
> +		/* Mark pending IRQs as handled */
> +		pending = HISI_8BITS_MASK & in;

It looks odd to see them this way around.

Usually mark the value with the mask, not the mask with the value.

> +		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
> +
> +		if (i == HISI_POWERKEY_IRQ_NUM &&
> +		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
> +			/*
> +			 * If both powerkey down and up IRQs are received,
> +			 * handle them at the right order
> +			 */
> +			generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
> +			generic_handle_irq(ddata->irqs[POWERKEY_UP]);
> +			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
> +		}
> +
> +		if (!pending)
> +			continue;
> +
> +		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
> +			generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
> +		}
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void hi6421_spmi_irq_mask(struct irq_data *d)
> +{
> +	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
> +	unsigned long flags;
> +	unsigned int data;
> +	u32 offset;
> +
> +	offset = HISI_IRQ_MASK_REG(d);
> +
> +	spin_lock_irqsave(&ddata->lock, flags);
> +
> +	regmap_read(ddata->regmap, offset, &data);
> +	data |= HISI_IRQ_MASK_BIT(d);
> +	regmap_write(ddata->regmap, offset, data);
> +
> +	spin_unlock_irqrestore(&ddata->lock, flags);
> +}
> +
> +static void hi6421_spmi_irq_unmask(struct irq_data *d)
> +{
> +	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
> +	u32 data, offset;
> +	unsigned long flags;
> +
> +	offset = HISI_IRQ_MASK_REG(d);
> +
> +	spin_lock_irqsave(&ddata->lock, flags);
> +
> +	regmap_read(ddata->regmap, offset, &data);
> +	data &= ~HISI_IRQ_MASK_BIT(d);
> +	regmap_write(ddata->regmap, offset, data);
> +
> +	spin_unlock_irqrestore(&ddata->lock, flags);
> +}
> +
> +static struct irq_chip hi6421_spmi_pmu_irqchip = {
> +	.name		= "hi6421v600-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 *ddata = d->host_data;
> +
> +	irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
> +				      handle_simple_irq, "hi6421v600");
> +	irq_set_chip_data(virq, ddata);
> +	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_init(struct hi6421_spmi_pmic *ddata)
> +{
> +	int i;
> +	unsigned int pending;
> +
> +	/* Mask all IRQs */
> +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
> +		regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
> +			     HISI_8BITS_MASK);
> +
> +	/* Mark all IRQs as handled */
> +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
> +		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
> +		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
> +			     HISI_8BITS_MASK);
> +	}
> +}
> +
> +static const struct regmap_config regmap_config = {
> +	.reg_bits		= 16,
> +	.val_bits		= BITS_PER_BYTE,
> +	.max_register		= 0xffff,
> +	.fast_io		= true
> +};

Why are these tabbed out this far?  Legacy?

> +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 *ddata;
> +	unsigned int virq;
> +	int ret, i;
> +
> +	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
> +	if (!ddata)
> +		return -ENOMEM;
> +
> +	ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
> +	if (IS_ERR(ddata->regmap))
> +		return PTR_ERR(ddata->regmap);
> +
> +	spin_lock_init(&ddata->lock);
> +
> +	ddata->dev = dev;
> +
> +	ddata->gpio = of_get_gpio(np, 0);
> +	if (ddata->gpio < 0)
> +		return ddata->gpio;
> +
> +	if (!gpio_is_valid(ddata->gpio))
> +		return -EINVAL;
> +
> +	ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
> +		return ret;
> +	}
> +
> +	ddata->irq = gpio_to_irq(ddata->gpio);
> +
> +	hi6421_spmi_pmic_irq_init(ddata);
> +
> +	ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
> +	if (!ddata->irqs)
> +		return -ENOMEM;
> +
> +	ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
> +					      &hi6421_spmi_domain_ops, ddata);
> +	if (!ddata->domain) {
> +		dev_err(dev, "Failed to create IRQ domain\n");
> +		return -ENODEV;
> +	}
> +
> +	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
> +		virq = irq_create_mapping(ddata->domain, i);
> +		if (!virq) {
> +			dev_err(dev, "Failed to map H/W IRQ\n");
> +			return -ENOSPC;

-ENOSPC doesn't seem right here.

Can't find any other uses of it for irq_create_mapping() either.

> +		}
> +		ddata->irqs[i] = virq;
> +	}
> +
> +	ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
> +				   IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
> +				   "pmic", ddata);
> +	if (ret < 0) {
> +		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	dev_set_drvdata(&pdev->dev, ddata);
> +
> +	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
> +				   hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
> +				   NULL, 0, NULL);
> +	if (ret < 0)
> +		dev_err(dev, "Failed to add child devices: %d\n", ret);
> +
> +	return ret;
> +}
> +
> +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
> +{
> +	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
> +
> +	free_irq(ddata->irq, ddata);

No devm_* version?

> +}
> +
> +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");

-- 
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] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 11:33   ` Lee Jones
@ 2021-06-24 12:36     ` Mauro Carvalho Chehab
  2021-06-24 13:07       ` Dan Carpenter
  2021-06-24 14:08       ` Lee Jones
  0 siblings, 2 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-24 12:36 UTC (permalink / raw)
  To: Lee Jones
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab, Rob Herring,
	devicetree, linux-kernel, linux-staging

Em Thu, 24 Jun 2021 12:33:28 +0100
Lee Jones <lee.jones@linaro.org> escreveu:

> On Thu, 24 Jun 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       | 134 ++++++++
> >  MAINTAINERS                                   |   7 +
> >  drivers/mfd/Kconfig                           |  16 +
> >  drivers/mfd/Makefile                          |   1 +
> >  drivers/mfd/hi6421-spmi-pmic.c                | 316 ++++++++++++++++++
> >  drivers/staging/Kconfig                       |   2 -
> >  drivers/staging/Makefile                      |   1 -
> >  drivers/staging/hikey9xx/Kconfig              |  19 --
> >  drivers/staging/hikey9xx/Makefile             |   3 -
> >  drivers/staging/hikey9xx/TODO                 |   5 -
> >  drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 316 ------------------
> >  .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 134 --------
> >  12 files changed, 474 insertions(+), 480 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/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/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..8e355cddd437
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > @@ -0,0 +1,134 @@
> > +# 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
> > +  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > +
> > +properties:
> > +  $nodename:
> > +    pattern: "pmic@[0-9a-f]"
> > +
> > +  compatible:
> > +    const: hisilicon,hi6421v600-spmi
> > +
> > +  reg:
> > +    maxItems: 1
> > +
> > +  '#interrupt-cells':
> > +    const: 2
> > +
> > +  interrupt-controller: true
> > +
> > +  gpios:
> > +    maxItems: 1
> > +    description: GPIO used for IRQs
> > +
> > +  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
> > +
> > +additionalProperties: false
> > +
> > +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 9a69e3810964..89e84b050de6 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -8291,6 +8291,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>
> >  S:	Maintained
> > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > index 5c7f2b100191..99b8da2548b5 100644
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -509,6 +509,22 @@ 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
> > +	select REGMAP_SPMI
> > +	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 4f6d2b8a5f76..e87230fc61ac 100644
> > --- a/drivers/mfd/Makefile
> > +++ b/drivers/mfd/Makefile
> > @@ -232,6 +232,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..2b7172560df7
> > --- /dev/null
> > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > @@ -0,0 +1,316 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Device driver for regulators in HISI PMIC IC
> > + *
> > + * Copyright (c) 2013 Linaro Ltd.
> > + * Copyright (c) 2011 Hisilicon.
> > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> 
> Can this be updated?

Do you mean updating the copyrights to cover this year? E.g.
something like this:

	 * Copyright (c) 2013-2021 Linaro Ltd.
	 * Copyright (c) 2011-2021 Hisilicon.
	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  

Right? Or are you meaning something else?

Btw, this device is a variant of the already-existing devices
provided by the hi6421-pmic-core, which has:

	 * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
	 *              http://www.hisilicon.com
	 * Copyright (c) <2013-2017> Linaro Ltd.
	 *              https://www.linaro.org
	 *

The main difference is that this device is connected via a 
SPMI bus (there are other differences on register settings and
LDO/BUCK regulators).


> 
> > + */
> > +
> > +#include <linux/bitops.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irq.h>
> > +#include <linux/mfd/core.h>
> > +#include <linux/mfd/hi6421-spmi-pmic.h>
> > +#include <linux/module.h>
> > +#include <linux/of_gpio.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +#include <linux/spmi.h>
> > +
> > +enum hi6421_spmi_pmic_irq_list {
> > +	OTMP = 0,
> > +	VBUS_CONNECT,
> > +	VBUS_DISCONNECT,
> > +	ALARMON_R,
> > +	HOLD_6S,
> > +	HOLD_1S,
> > +	POWERKEY_UP,
> > +	POWERKEY_DOWN,
> > +	OCP_SCP_R,
> > +	COUL_R,
> > +	SIM0_HPD_R,
> > +	SIM0_HPD_F,
> > +	SIM1_HPD_R,
> > +	SIM1_HPD_F,
> > +
> > +	PMIC_IRQ_LIST_MAX
> > +};
> > +
> > +#define HISI_IRQ_BANK_SIZE		2
> > +
> > +/*
> > + * IRQ number for the power key button and mask for both UP and DOWN IRQs
> > + */
> > +#define HISI_POWERKEY_IRQ_NUM		0
> > +#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
> > +
> > +/*
> > + * Registers for IRQ address and IRQ mask bits
> > + *
> > + * Please notice that we need to regmap a larger region, as other
> > + * registers are used by the regulators.
> > + * See drivers/regulator/hi6421-regulator.c.
> > + */
> > +#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
> > +#define SOC_PMIC_IRQ0_ADDR		0x0212
> > +
> > +/*
> > + * The IRQs are mapped as:
> > + *
> > + *	======================  =============   ============	=====
> > + *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
> > + *	======================  =============   ============	=====
> > + *	OTMP			0x0202		0x212		bit 0
> > + *	VBUS_CONNECT		0x0202		0x212		bit 1
> > + *	VBUS_DISCONNECT		0x0202		0x212		bit 2
> > + *	ALARMON_R		0x0202		0x212		bit 3
> > + *	HOLD_6S			0x0202		0x212		bit 4
> > + *	HOLD_1S			0x0202		0x212		bit 5
> > + *	POWERKEY_UP		0x0202		0x212		bit 6
> > + *	POWERKEY_DOWN		0x0202		0x212		bit 7
> > + *
> > + *	OCP_SCP_R		0x0203		0x213		bit 0
> > + *	COUL_R			0x0203		0x213		bit 1
> > + *	SIM0_HPD_R		0x0203		0x213		bit 2
> > + *	SIM0_HPD_F		0x0203		0x213		bit 3
> > + *	SIM1_HPD_R		0x0203		0x213		bit 4
> > + *	SIM1_HPD_F		0x0203		0x213		bit 5
> > + *	======================  =============   ============	=====
> > + *
> > + * Each mask register contains 8 bits. The ancillary macros below
> > + * convert a number from 0 to 14 into a register address and a bit mask
> > + */
> > +#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
> > +					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
> > +#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
> > +#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)  
> 
> Are these lines up in real code?  Looks like they're not in the diff.

Weird. The changes to use those are at patch 3/8. All the above
macros are used at the patch.

> 
> HISI_8BITS_MASK is just 0xff right?  I think we're more used to seeing
> the value used in place.  Creating a macro for it out of GENMASK is
> probably slightly over-engineering it a little.

Ok, I'll replace it to 0xff everywhere. I guess we added it due to
some previous review.

> 
> > +static const struct mfd_cell hi6421v600_devs[] = {
> > +	{ .name = "hi6421v600-regulator", },
> > +};  
> 
> Where are the other devices?

While this is a MFD device, as it has regulators, ADC and other
stuff, right now, only the regulator and the IRQs are implemented. 

The IRQs are at the core of this driver, while the regulator 
is at the separate regulator driver.

> 
> > +static irqreturn_t hi6421_spmi_irq_handler(int irq, void *priv)
> > +{
> > +	struct hi6421_spmi_pmic *ddata = (struct hi6421_spmi_pmic *)priv;
> > +	unsigned long pending;
> > +	unsigned int in;
> > +	int i, offset;
> > +
> > +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
> > +		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
> > +
> > +		/* Mark pending IRQs as handled */
> > +		pending = HISI_8BITS_MASK & in;  
> 
> It looks odd to see them this way around.
> 
> Usually mark the value with the mask, not the mask with the value.

Yeah, I guess we can simply drop this line.

> 
> > +		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, pending);
> > +
> > +		if (i == HISI_POWERKEY_IRQ_NUM &&
> > +		    (pending & HISI_IRQ_POWERKEY_UP_DOWN) == HISI_IRQ_POWERKEY_UP_DOWN) {
> > +			/*
> > +			 * If both powerkey down and up IRQs are received,
> > +			 * handle them at the right order
> > +			 */
> > +			generic_handle_irq(ddata->irqs[POWERKEY_DOWN]);
> > +			generic_handle_irq(ddata->irqs[POWERKEY_UP]);
> > +			pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
> > +		}
> > +
> > +		if (!pending)
> > +			continue;
> > +
> > +		for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
> > +			generic_handle_irq(ddata->irqs[offset + i * BITS_PER_BYTE]);
> > +		}
> > +	}
> > +
> > +	return IRQ_HANDLED;
> > +}
> > +
> > +static void hi6421_spmi_irq_mask(struct irq_data *d)
> > +{
> > +	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
> > +	unsigned long flags;
> > +	unsigned int data;
> > +	u32 offset;
> > +
> > +	offset = HISI_IRQ_MASK_REG(d);
> > +
> > +	spin_lock_irqsave(&ddata->lock, flags);
> > +
> > +	regmap_read(ddata->regmap, offset, &data);
> > +	data |= HISI_IRQ_MASK_BIT(d);
> > +	regmap_write(ddata->regmap, offset, data);
> > +
> > +	spin_unlock_irqrestore(&ddata->lock, flags);
> > +}
> > +
> > +static void hi6421_spmi_irq_unmask(struct irq_data *d)
> > +{
> > +	struct hi6421_spmi_pmic *ddata = irq_data_get_irq_chip_data(d);
> > +	u32 data, offset;
> > +	unsigned long flags;
> > +
> > +	offset = HISI_IRQ_MASK_REG(d);
> > +
> > +	spin_lock_irqsave(&ddata->lock, flags);
> > +
> > +	regmap_read(ddata->regmap, offset, &data);
> > +	data &= ~HISI_IRQ_MASK_BIT(d);
> > +	regmap_write(ddata->regmap, offset, data);
> > +
> > +	spin_unlock_irqrestore(&ddata->lock, flags);
> > +}
> > +
> > +static struct irq_chip hi6421_spmi_pmu_irqchip = {
> > +	.name		= "hi6421v600-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 *ddata = d->host_data;
> > +
> > +	irq_set_chip_and_handler_name(virq, &hi6421_spmi_pmu_irqchip,
> > +				      handle_simple_irq, "hi6421v600");
> > +	irq_set_chip_data(virq, ddata);
> > +	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_init(struct hi6421_spmi_pmic *ddata)
> > +{
> > +	int i;
> > +	unsigned int pending;
> > +
> > +	/* Mask all IRQs */
> > +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
> > +		regmap_write(ddata->regmap, SOC_PMIC_IRQ_MASK_0_ADDR + i,
> > +			     HISI_8BITS_MASK);
> > +
> > +	/* Mark all IRQs as handled */
> > +	for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
> > +		regmap_read(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
> > +		regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i,
> > +			     HISI_8BITS_MASK);
> > +	}
> > +}
> > +
> > +static const struct regmap_config regmap_config = {
> > +	.reg_bits		= 16,
> > +	.val_bits		= BITS_PER_BYTE,
> > +	.max_register		= 0xffff,
> > +	.fast_io		= true
> > +};  
> 
> Why are these tabbed out this far?  Legacy?

No particular reason. This is not legacy, as the conversion to
regmap was done after a review request. I guess it is probably
due to copy-and-paste from some other driver.

Anyway, I'll adjust it, using just one tab instead of two.

> 
> > +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 *ddata;
> > +	unsigned int virq;
> > +	int ret, i;
> > +
> > +	ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
> > +	if (!ddata)
> > +		return -ENOMEM;
> > +
> > +	ddata->regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
> > +	if (IS_ERR(ddata->regmap))
> > +		return PTR_ERR(ddata->regmap);
> > +
> > +	spin_lock_init(&ddata->lock);
> > +
> > +	ddata->dev = dev;
> > +
> > +	ddata->gpio = of_get_gpio(np, 0);
> > +	if (ddata->gpio < 0)
> > +		return ddata->gpio;
> > +
> > +	if (!gpio_is_valid(ddata->gpio))
> > +		return -EINVAL;
> > +
> > +	ret = devm_gpio_request_one(dev, ddata->gpio, GPIOF_IN, "pmic");
> > +	if (ret < 0) {
> > +		dev_err(dev, "Failed to request gpio%d\n", ddata->gpio);
> > +		return ret;
> > +	}
> > +
> > +	ddata->irq = gpio_to_irq(ddata->gpio);
> > +
> > +	hi6421_spmi_pmic_irq_init(ddata);
> > +
> > +	ddata->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
> > +	if (!ddata->irqs)
> > +		return -ENOMEM;
> > +
> > +	ddata->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
> > +					      &hi6421_spmi_domain_ops, ddata);
> > +	if (!ddata->domain) {
> > +		dev_err(dev, "Failed to create IRQ domain\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
> > +		virq = irq_create_mapping(ddata->domain, i);
> > +		if (!virq) {
> > +			dev_err(dev, "Failed to map H/W IRQ\n");
> > +			return -ENOSPC;  
> 
> -ENOSPC doesn't seem right here.
> 
> Can't find any other uses of it for irq_create_mapping() either.

There are two drivers returning -ENOSPC:

	arch/powerpc/platforms/pseries/msi.c
	arch/powerpc/sysdev/mpic_u3msi.c

But others return -EIO, -EINVAL, -ENOMEM, -ENODEV, -ENXIO.

I think that -ENODEV would fit better here.

> 
> > +		}
> > +		ddata->irqs[i] = virq;
> > +	}
> > +
> > +	ret = request_threaded_irq(ddata->irq, hi6421_spmi_irq_handler, NULL,
> > +				   IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
> > +				   "pmic", ddata);
> > +	if (ret < 0) {
> > +		dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
> > +			ret);
> > +		return ret;
> > +	}
> > +
> > +	dev_set_drvdata(&pdev->dev, ddata);
> > +
> > +	ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
> > +				   hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
> > +				   NULL, 0, NULL);
> > +	if (ret < 0)
> > +		dev_err(dev, "Failed to add child devices: %d\n", ret);
> > +
> > +	return ret;
> > +}
> > +
> > +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
> > +{
> > +	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
> > +
> > +	free_irq(ddata->irq, ddata);  
> 
> No devm_* version?

Are there a devm_* variant for gpio_to_irq()?

> 
> > +}
> > +
> > +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");  
> 



Thanks,
Mauro

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 12:36     ` Mauro Carvalho Chehab
@ 2021-06-24 13:07       ` Dan Carpenter
  2021-06-24 14:08       ` Lee Jones
  1 sibling, 0 replies; 19+ messages in thread
From: Dan Carpenter @ 2021-06-24 13:07 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Lee Jones, Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Rob Herring, devicetree, linux-kernel, linux-staging

On Thu, Jun 24, 2021 at 02:36:05PM +0200, Mauro Carvalho Chehab wrote:
> Em Thu, 24 Jun 2021 12:33:28 +0100
> Lee Jones <lee.jones@linaro.org> escreveu:
> 
> > On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:
> > > +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
> > > +{
> > > +	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
> > > +
> > > +	free_irq(ddata->irq, ddata);  
> > 
> > No devm_* version?
> 
> Are there a devm_* variant for gpio_to_irq()?
> 

It's the request_threaded_irq() which needs unwound not the gpio_to_irq()
so you could use devm_request_threaded_irq().

Using the devm_ version would fix a leak in probe which Smatch is
supposed to find but does not.  :(

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 12:36     ` Mauro Carvalho Chehab
  2021-06-24 13:07       ` Dan Carpenter
@ 2021-06-24 14:08       ` Lee Jones
  2021-06-24 14:26         ` Johan Hovold
  2021-06-25 11:13         ` Mauro Carvalho Chehab
  1 sibling, 2 replies; 19+ messages in thread
From: Lee Jones @ 2021-06-24 14:08 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab, Rob Herring,
	devicetree, linux-kernel, linux-staging

On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:

> Em Thu, 24 Jun 2021 12:33:28 +0100
> Lee Jones <lee.jones@linaro.org> escreveu:
> 
> > On Thu, 24 Jun 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       | 134 ++++++++
> > >  MAINTAINERS                                   |   7 +
> > >  drivers/mfd/Kconfig                           |  16 +
> > >  drivers/mfd/Makefile                          |   1 +
> > >  drivers/mfd/hi6421-spmi-pmic.c                | 316 ++++++++++++++++++
> > >  drivers/staging/Kconfig                       |   2 -
> > >  drivers/staging/Makefile                      |   1 -
> > >  drivers/staging/hikey9xx/Kconfig              |  19 --
> > >  drivers/staging/hikey9xx/Makefile             |   3 -
> > >  drivers/staging/hikey9xx/TODO                 |   5 -
> > >  drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 316 ------------------
> > >  .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 134 --------
> > >  12 files changed, 474 insertions(+), 480 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/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/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..8e355cddd437
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > > @@ -0,0 +1,134 @@
> > > +# 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
> > > +  Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
> > > +
> > > +properties:
> > > +  $nodename:
> > > +    pattern: "pmic@[0-9a-f]"
> > > +
> > > +  compatible:
> > > +    const: hisilicon,hi6421v600-spmi
> > > +
> > > +  reg:
> > > +    maxItems: 1
> > > +
> > > +  '#interrupt-cells':
> > > +    const: 2
> > > +
> > > +  interrupt-controller: true
> > > +
> > > +  gpios:
> > > +    maxItems: 1
> > > +    description: GPIO used for IRQs
> > > +
> > > +  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
> > > +
> > > +additionalProperties: false
> > > +
> > > +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 9a69e3810964..89e84b050de6 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -8291,6 +8291,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>
> > >  S:	Maintained
> > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > > index 5c7f2b100191..99b8da2548b5 100644
> > > --- a/drivers/mfd/Kconfig
> > > +++ b/drivers/mfd/Kconfig
> > > @@ -509,6 +509,22 @@ 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
> > > +	select REGMAP_SPMI
> > > +	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 4f6d2b8a5f76..e87230fc61ac 100644
> > > --- a/drivers/mfd/Makefile
> > > +++ b/drivers/mfd/Makefile
> > > @@ -232,6 +232,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..2b7172560df7
> > > --- /dev/null
> > > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > > @@ -0,0 +1,316 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Device driver for regulators in HISI PMIC IC
> > > + *
> > > + * Copyright (c) 2013 Linaro Ltd.
> > > + * Copyright (c) 2011 Hisilicon.
> > > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > 
> > Can this be updated?
> 
> Do you mean updating the copyrights to cover this year? E.g.
> something like this:
> 
> 	 * Copyright (c) 2013-2021 Linaro Ltd.
> 	 * Copyright (c) 2011-2021 Hisilicon.
> 	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> 
> Right? Or are you meaning something else?

Yes, that's it.  I know this is just a move, but to MFD, it's new.

> Btw, this device is a variant of the already-existing devices
> provided by the hi6421-pmic-core, which has:
> 
> 	 * Copyright (c) <2011-2014> HiSilicon Technologies Co., Ltd.
> 	 *              http://www.hisilicon.com
> 	 * Copyright (c) <2013-2017> Linaro Ltd.
> 	 *              https://www.linaro.org
> 	 *
> 
> The main difference is that this device is connected via a 
> SPMI bus (there are other differences on register settings and
> LDO/BUCK regulators).
> 
> > 
> > > + */
> > > +
> > > +#include <linux/bitops.h>
> > > +#include <linux/interrupt.h>
> > > +#include <linux/irq.h>
> > > +#include <linux/mfd/core.h>
> > > +#include <linux/mfd/hi6421-spmi-pmic.h>
> > > +#include <linux/module.h>
> > > +#include <linux/of_gpio.h>
> > > +#include <linux/platform_device.h>
> > > +#include <linux/slab.h>
> > > +#include <linux/spmi.h>
> > > +
> > > +enum hi6421_spmi_pmic_irq_list {
> > > +	OTMP = 0,
> > > +	VBUS_CONNECT,
> > > +	VBUS_DISCONNECT,
> > > +	ALARMON_R,
> > > +	HOLD_6S,
> > > +	HOLD_1S,
> > > +	POWERKEY_UP,
> > > +	POWERKEY_DOWN,
> > > +	OCP_SCP_R,
> > > +	COUL_R,
> > > +	SIM0_HPD_R,
> > > +	SIM0_HPD_F,
> > > +	SIM1_HPD_R,
> > > +	SIM1_HPD_F,
> > > +
> > > +	PMIC_IRQ_LIST_MAX
> > > +};
> > > +
> > > +#define HISI_IRQ_BANK_SIZE		2
> > > +
> > > +/*
> > > + * IRQ number for the power key button and mask for both UP and DOWN IRQs
> > > + */
> > > +#define HISI_POWERKEY_IRQ_NUM		0
> > > +#define HISI_IRQ_POWERKEY_UP_DOWN	(BIT(POWERKEY_DOWN) | BIT(POWERKEY_UP))
> > > +
> > > +/*
> > > + * Registers for IRQ address and IRQ mask bits
> > > + *
> > > + * Please notice that we need to regmap a larger region, as other
> > > + * registers are used by the regulators.
> > > + * See drivers/regulator/hi6421-regulator.c.
> > > + */
> > > +#define SOC_PMIC_IRQ_MASK_0_ADDR	0x0202
> > > +#define SOC_PMIC_IRQ0_ADDR		0x0212
> > > +
> > > +/*
> > > + * The IRQs are mapped as:
> > > + *
> > > + *	======================  =============   ============	=====
> > > + *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
> > > + *	======================  =============   ============	=====
> > > + *	OTMP			0x0202		0x212		bit 0
> > > + *	VBUS_CONNECT		0x0202		0x212		bit 1
> > > + *	VBUS_DISCONNECT		0x0202		0x212		bit 2
> > > + *	ALARMON_R		0x0202		0x212		bit 3
> > > + *	HOLD_6S			0x0202		0x212		bit 4
> > > + *	HOLD_1S			0x0202		0x212		bit 5
> > > + *	POWERKEY_UP		0x0202		0x212		bit 6
> > > + *	POWERKEY_DOWN		0x0202		0x212		bit 7
> > > + *
> > > + *	OCP_SCP_R		0x0203		0x213		bit 0
> > > + *	COUL_R			0x0203		0x213		bit 1
> > > + *	SIM0_HPD_R		0x0203		0x213		bit 2
> > > + *	SIM0_HPD_F		0x0203		0x213		bit 3
> > > + *	SIM1_HPD_R		0x0203		0x213		bit 4
> > > + *	SIM1_HPD_F		0x0203		0x213		bit 5
> > > + *	======================  =============   ============	=====
> > > + *
> > > + * Each mask register contains 8 bits. The ancillary macros below
> > > + * convert a number from 0 to 14 into a register address and a bit mask
> > > + */
> > > +#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
> > > +					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
> > > +#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
> > > +#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)  
> > 
> > Are these lines up in real code?  Looks like they're not in the diff.
> 
> Weird. The changes to use those are at patch 3/8. All the above
> macros are used at the patch.

Sorry, that made no sense - it's been a long few days!

I meant to say "do these (the tabs) line up?"

> > > +static const struct mfd_cell hi6421v600_devs[] = {
> > > +	{ .name = "hi6421v600-regulator", },
> > > +};  
> > 
> > Where are the other devices?
> 
> While this is a MFD device, as it has regulators, ADC and other
> stuff, right now, only the regulator and the IRQs are implemented. 
> 
> The IRQs are at the core of this driver, while the regulator 
> is at the separate regulator driver.

The rule usually goes:

 Drivers don't qualify as MFDs until you register >1 device.

[...]

> > > +	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
> > > +		virq = irq_create_mapping(ddata->domain, i);
> > > +		if (!virq) {
> > > +			dev_err(dev, "Failed to map H/W IRQ\n");
> > > +			return -ENOSPC;  
> > 
> > -ENOSPC doesn't seem right here.
> > 
> > Can't find any other uses of it for irq_create_mapping() either.
> 
> There are two drivers returning -ENOSPC:
> 
> 	arch/powerpc/platforms/pseries/msi.c
> 	arch/powerpc/sysdev/mpic_u3msi.c

I only looked in drivers/

> But others return -EIO, -EINVAL, -ENOMEM, -ENODEV, -ENXIO.
> 
> I think that -ENODEV would fit better here.

I think -ENXIO is the most common, followed by -EINVAL.

This doesn't have anything to do with devices per say.

> > > +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
> > > +{
> > > +	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
> > > +
> > > +	free_irq(ddata->irq, ddata);  
> > 
> > No devm_* version?
> 
> Are there a devm_* variant for gpio_to_irq()?

Please refer to Dan's response.

-- 
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] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 14:08       ` Lee Jones
@ 2021-06-24 14:26         ` Johan Hovold
  2021-06-25 11:38           ` Mauro Carvalho Chehab
  2021-06-28 10:43           ` Lee Jones
  2021-06-25 11:13         ` Mauro Carvalho Chehab
  1 sibling, 2 replies; 19+ messages in thread
From: Johan Hovold @ 2021-06-24 14:26 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, linuxarm,
	mauro.chehab, Rob Herring, devicetree, linux-kernel,
	linux-staging

On Thu, Jun 24, 2021 at 03:08:00PM +0100, Lee Jones wrote:
> On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:
> 
> > Em Thu, 24 Jun 2021 12:33:28 +0100
> > Lee Jones <lee.jones@linaro.org> escreveu:

> > > > --- /dev/null
> > > > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > > > @@ -0,0 +1,316 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +/*
> > > > + * Device driver for regulators in HISI PMIC IC
> > > > + *
> > > > + * Copyright (c) 2013 Linaro Ltd.
> > > > + * Copyright (c) 2011 Hisilicon.
> > > > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > > 
> > > Can this be updated?
> > 
> > Do you mean updating the copyrights to cover this year? E.g.
> > something like this:
> > 
> > 	 * Copyright (c) 2013-2021 Linaro Ltd.
> > 	 * Copyright (c) 2011-2021 Hisilicon.
> > 	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > 
> > Right? Or are you meaning something else?
> 
> Yes, that's it.  I know this is just a move, but to MFD, it's new.

That's not how copyright works. Unless Linaro and Hisilicon made
nontrivial changes every year from 2011/2013 to 2021 you should not
change those lines like this.

Johan

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24  9:01 ` [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: " Mauro Carvalho Chehab
  2021-06-24 11:33   ` Lee Jones
@ 2021-06-24 15:26   ` Rob Herring
  1 sibling, 0 replies; 19+ messages in thread
From: Rob Herring @ 2021-06-24 15:26 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: linux-kernel, Lee Jones, linuxarm, devicetree,
	Greg Kroah-Hartman, mauro.chehab, Rob Herring, linux-staging

On Thu, 24 Jun 2021 11:01:10 +0200, 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       | 134 ++++++++
>  MAINTAINERS                                   |   7 +
>  drivers/mfd/Kconfig                           |  16 +
>  drivers/mfd/Makefile                          |   1 +
>  drivers/mfd/hi6421-spmi-pmic.c                | 316 ++++++++++++++++++
>  drivers/staging/Kconfig                       |   2 -
>  drivers/staging/Makefile                      |   1 -
>  drivers/staging/hikey9xx/Kconfig              |  19 --
>  drivers/staging/hikey9xx/Makefile             |   3 -
>  drivers/staging/hikey9xx/TODO                 |   5 -
>  drivers/staging/hikey9xx/hi6421-spmi-pmic.c   | 316 ------------------
>  .../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml  | 134 --------
>  12 files changed, 474 insertions(+), 480 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/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/hisilicon,hi6421-spmi-pmic.yaml
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.example.dt.yaml:0:0: /example-0/pmic@0: failed to match any schema with compatible: ['hisilicon,hi6421-spmi']
\ndoc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/1496456

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] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 14:08       ` Lee Jones
  2021-06-24 14:26         ` Johan Hovold
@ 2021-06-25 11:13         ` Mauro Carvalho Chehab
  1 sibling, 0 replies; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-25 11:13 UTC (permalink / raw)
  To: Lee Jones
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab, Rob Herring,
	devicetree, linux-kernel, linux-staging

Em Thu, 24 Jun 2021 15:08:00 +0100
Lee Jones <lee.jones@linaro.org> escreveu:

> > > > +/*
> > > > + * The IRQs are mapped as:
> > > > + *
> > > > + *	======================  =============   ============	=====
> > > > + *	IRQ			MASK REGISTER	IRQ REGISTER	BIT
> > > > + *	======================  =============   ============	=====
> > > > + *	OTMP			0x0202		0x212		bit 0
> > > > + *	VBUS_CONNECT		0x0202		0x212		bit 1
> > > > + *	VBUS_DISCONNECT		0x0202		0x212		bit 2
> > > > + *	ALARMON_R		0x0202		0x212		bit 3
> > > > + *	HOLD_6S			0x0202		0x212		bit 4
> > > > + *	HOLD_1S			0x0202		0x212		bit 5
> > > > + *	POWERKEY_UP		0x0202		0x212		bit 6
> > > > + *	POWERKEY_DOWN		0x0202		0x212		bit 7
> > > > + *
> > > > + *	OCP_SCP_R		0x0203		0x213		bit 0
> > > > + *	COUL_R			0x0203		0x213		bit 1
> > > > + *	SIM0_HPD_R		0x0203		0x213		bit 2
> > > > + *	SIM0_HPD_F		0x0203		0x213		bit 3
> > > > + *	SIM1_HPD_R		0x0203		0x213		bit 4
> > > > + *	SIM1_HPD_F		0x0203		0x213		bit 5
> > > > + *	======================  =============   ============	=====
> > > > + *
> > > > + * Each mask register contains 8 bits. The ancillary macros below
> > > > + * convert a number from 0 to 14 into a register address and a bit mask
> > > > + */
> > > > +#define HISI_IRQ_MASK_REG(irq_data)	(SOC_PMIC_IRQ_MASK_0_ADDR + \
> > > > +					 (irqd_to_hwirq(irq_data) / BITS_PER_BYTE))
> > > > +#define HISI_IRQ_MASK_BIT(irq_data)	BIT(irqd_to_hwirq(irq_data) & (BITS_PER_BYTE - 1))
> > > > +#define HISI_8BITS_MASK			GENMASK(BITS_PER_BYTE - 1, 0)    
> > > 
> > > Are these lines up in real code?  Looks like they're not in the diff.  
> > 
> > Weird. The changes to use those are at patch 3/8. All the above
> > macros are used at the patch.  
> 
> Sorry, that made no sense - it's been a long few days!
> 
> I meant to say "do these (the tabs) line up?"

Yes, they line up (and aligned with the parenthesis, in the case of
HISI_IRQ_MASK_REG).

> > > > +static const struct mfd_cell hi6421v600_devs[] = {
> > > > +	{ .name = "hi6421v600-regulator", },
> > > > +};    
> > > 
> > > Where are the other devices?  
> > 
> > While this is a MFD device, as it has regulators, ADC and other
> > stuff, right now, only the regulator and the IRQs are implemented. 
> > 
> > The IRQs are at the core of this driver, while the regulator 
> > is at the separate regulator driver.  
> 
> The rule usually goes:
> 
>  Drivers don't qualify as MFDs until you register >1 device.

Do you mean that, in order for this to be accepted, should
I move the irq code to a separate driver?

> > > > +	for (i = 0; i < PMIC_IRQ_LIST_MAX; i++) {
> > > > +		virq = irq_create_mapping(ddata->domain, i);
> > > > +		if (!virq) {
> > > > +			dev_err(dev, "Failed to map H/W IRQ\n");
> > > > +			return -ENOSPC;    
> > > 
> > > -ENOSPC doesn't seem right here.
> > > 
> > > Can't find any other uses of it for irq_create_mapping() either.  
> > 
> > There are two drivers returning -ENOSPC:
> > 
> > 	arch/powerpc/platforms/pseries/msi.c
> > 	arch/powerpc/sysdev/mpic_u3msi.c  
> 
> I only looked in drivers/
> 
> > But others return -EIO, -EINVAL, -ENOMEM, -ENODEV, -ENXIO.
> > 
> > I think that -ENODEV would fit better here.  
> 
> I think -ENXIO is the most common, followed by -EINVAL.
> 
> This doesn't have anything to do with devices per say.

Ok. I'll change it to -ENXIO.

> > > > +static void hi6421_spmi_pmic_remove(struct spmi_device *pdev)
> > > > +{
> > > > +	struct hi6421_spmi_pmic *ddata = dev_get_drvdata(&pdev->dev);
> > > > +
> > > > +	free_irq(ddata->irq, ddata);    
> > > 
> > > No devm_* version?  
> > 
> > Are there a devm_* variant for gpio_to_irq()?  
> 
> Please refer to Dan's response.

Ok.

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 14:26         ` Johan Hovold
@ 2021-06-25 11:38           ` Mauro Carvalho Chehab
  2021-06-28 10:43             ` Lee Jones
  2021-06-28 10:43           ` Lee Jones
  1 sibling, 1 reply; 19+ messages in thread
From: Mauro Carvalho Chehab @ 2021-06-25 11:38 UTC (permalink / raw)
  To: Johan Hovold, Lee Jones
  Cc: Greg Kroah-Hartman, linuxarm, mauro.chehab, Rob Herring,
	devicetree, linux-kernel, linux-staging

Em Thu, 24 Jun 2021 16:26:00 +0200
Johan Hovold <johan@kernel.org> escreveu:

> On Thu, Jun 24, 2021 at 03:08:00PM +0100, Lee Jones wrote:
> > On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:
> >   
> > > Em Thu, 24 Jun 2021 12:33:28 +0100
> > > Lee Jones <lee.jones@linaro.org> escreveu:  
> 
> > > > > --- /dev/null
> > > > > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > > > > @@ -0,0 +1,316 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * Device driver for regulators in HISI PMIC IC
> > > > > + *
> > > > > + * Copyright (c) 2013 Linaro Ltd.
> > > > > + * Copyright (c) 2011 Hisilicon.
> > > > > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd    
> > > > 
> > > > Can this be updated?  
> > > 
> > > Do you mean updating the copyrights to cover this year? E.g.
> > > something like this:
> > > 
> > > 	 * Copyright (c) 2013-2021 Linaro Ltd.
> > > 	 * Copyright (c) 2011-2021 Hisilicon.
> > > 	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > > 
> > > Right? Or are you meaning something else?  
> > 
> > Yes, that's it.  I know this is just a move, but to MFD, it's new.  
> 
> That's not how copyright works. Unless Linaro and Hisilicon made
> nontrivial changes every year from 2011/2013 to 2021 you should not
> change those lines like this.

Only Linaro can answer what happened up to 2018, as this driver 
originally came from a Linaro tree, which has exactly one commit
for this driver:

	https://github.com/96boards-hikey/linux/commit/08464419fba2417aa849fce976fac9c5f51b3ada#diff-604ef8563dcd9ace6e3e58aac38337c72924b0889f6972d7ee9e15e2335ba964

After merged upstream at staging, all changes are covered by the
Huawei's copyright (2020-2021).

So, I'll just drop this patch. If the information is not accurate,
someone from the original copyright holders can send followup
patches.

Thanks,
Mauro

^ permalink raw reply	[flat|nested] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-25 11:38           ` Mauro Carvalho Chehab
@ 2021-06-28 10:43             ` Lee Jones
  0 siblings, 0 replies; 19+ messages in thread
From: Lee Jones @ 2021-06-28 10:43 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Johan Hovold, Greg Kroah-Hartman, linuxarm, mauro.chehab,
	Rob Herring, devicetree, linux-kernel, linux-staging

On Fri, 25 Jun 2021, Mauro Carvalho Chehab wrote:

> Em Thu, 24 Jun 2021 16:26:00 +0200
> Johan Hovold <johan@kernel.org> escreveu:
> 
> > On Thu, Jun 24, 2021 at 03:08:00PM +0100, Lee Jones wrote:
> > > On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:
> > >   
> > > > Em Thu, 24 Jun 2021 12:33:28 +0100
> > > > Lee Jones <lee.jones@linaro.org> escreveu:  
> > 
> > > > > > --- /dev/null
> > > > > > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > > > > > @@ -0,0 +1,316 @@
> > > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > > +/*
> > > > > > + * Device driver for regulators in HISI PMIC IC
> > > > > > + *
> > > > > > + * Copyright (c) 2013 Linaro Ltd.
> > > > > > + * Copyright (c) 2011 Hisilicon.
> > > > > > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd    
> > > > > 
> > > > > Can this be updated?  
> > > > 
> > > > Do you mean updating the copyrights to cover this year? E.g.
> > > > something like this:
> > > > 
> > > > 	 * Copyright (c) 2013-2021 Linaro Ltd.
> > > > 	 * Copyright (c) 2011-2021 Hisilicon.
> > > > 	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > > > 
> > > > Right? Or are you meaning something else?  
> > > 
> > > Yes, that's it.  I know this is just a move, but to MFD, it's new.  
> > 
> > That's not how copyright works. Unless Linaro and Hisilicon made
> > nontrivial changes every year from 2011/2013 to 2021 you should not
> > change those lines like this.
> 
> Only Linaro can answer what happened up to 2018, as this driver 
> originally came from a Linaro tree, which has exactly one commit
> for this driver:
> 
> 	https://github.com/96boards-hikey/linux/commit/08464419fba2417aa849fce976fac9c5f51b3ada#diff-604ef8563dcd9ace6e3e58aac38337c72924b0889f6972d7ee9e15e2335ba964
> 
> After merged upstream at staging, all changes are covered by the
> Huawei's copyright (2020-2021).
> 
> So, I'll just drop this patch. If the information is not accurate,
> someone from the original copyright holders can send followup
> patches.

After taking the time to read up on Copyright rules and expectations,
I think we can pretty much safely say that all of the Copyright
entries above are incorrect.

Copyright dates should only be listed if significant works were
undertaken in each of the years listed.  So unless large adaptions
happened every year since 2011, which I doubt very much, they're
wrong.

-- 
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] 19+ messages in thread

* Re: [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: move driver from staging
  2021-06-24 14:26         ` Johan Hovold
  2021-06-25 11:38           ` Mauro Carvalho Chehab
@ 2021-06-28 10:43           ` Lee Jones
  1 sibling, 0 replies; 19+ messages in thread
From: Lee Jones @ 2021-06-28 10:43 UTC (permalink / raw)
  To: Johan Hovold
  Cc: Mauro Carvalho Chehab, Greg Kroah-Hartman, linuxarm,
	mauro.chehab, Rob Herring, devicetree, linux-kernel,
	linux-staging

On Thu, 24 Jun 2021, Johan Hovold wrote:

> On Thu, Jun 24, 2021 at 03:08:00PM +0100, Lee Jones wrote:
> > On Thu, 24 Jun 2021, Mauro Carvalho Chehab wrote:
> > 
> > > Em Thu, 24 Jun 2021 12:33:28 +0100
> > > Lee Jones <lee.jones@linaro.org> escreveu:
> 
> > > > > --- /dev/null
> > > > > +++ b/drivers/mfd/hi6421-spmi-pmic.c
> > > > > @@ -0,0 +1,316 @@
> > > > > +// SPDX-License-Identifier: GPL-2.0
> > > > > +/*
> > > > > + * Device driver for regulators in HISI PMIC IC
> > > > > + *
> > > > > + * Copyright (c) 2013 Linaro Ltd.
> > > > > + * Copyright (c) 2011 Hisilicon.
> > > > > + * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > > > 
> > > > Can this be updated?
> > > 
> > > Do you mean updating the copyrights to cover this year? E.g.
> > > something like this:
> > > 
> > > 	 * Copyright (c) 2013-2021 Linaro Ltd.
> > > 	 * Copyright (c) 2011-2021 Hisilicon.
> > > 	 * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd  
> > > 
> > > Right? Or are you meaning something else?
> > 
> > Yes, that's it.  I know this is just a move, but to MFD, it's new.
> 
> That's not how copyright works. Unless Linaro and Hisilicon made
> nontrivial changes every year from 2011/2013 to 2021 you should not
> change those lines like this.

Thanks for the pointer.  After receiving these, I went and did some
reading-up on the subject, and you're quite right in what you say.

-- 
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] 19+ messages in thread

end of thread, other threads:[~2021-06-28 10:44 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-24  9:01 [PATCH RESEND v6 0/8] Move Hisilicon 6421v600 SPMI and USB drivers out of staging Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 1/8] staging: phy-hi3670-usb3: do a some minor cleanups Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 2/8] staging: hisi-spmi-controller: rename spmi-channel property Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 3/8] staging: phy-hi3670-usb3: do some additional cleanups Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 4/8] phy: phy-hi3670-usb3: move driver from staging into phy Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 5/8] spmi: hisi-spmi-controller: move driver from staging Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 6/8] mfd: hi6421-spmi-pmic: " Mauro Carvalho Chehab
2021-06-24 11:33   ` Lee Jones
2021-06-24 12:36     ` Mauro Carvalho Chehab
2021-06-24 13:07       ` Dan Carpenter
2021-06-24 14:08       ` Lee Jones
2021-06-24 14:26         ` Johan Hovold
2021-06-25 11:38           ` Mauro Carvalho Chehab
2021-06-28 10:43             ` Lee Jones
2021-06-28 10:43           ` Lee Jones
2021-06-25 11:13         ` Mauro Carvalho Chehab
2021-06-24 15:26   ` Rob Herring
2021-06-24  9:01 ` [PATCH RESEND v6 7/8] dts: hisilicon: add support for the PMIC found on Hikey 970 Mauro Carvalho Chehab
2021-06-24  9:01 ` [PATCH RESEND v6 8/8] dts: hisilicon: add support for USB3 " 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).