2021-07-14 09:14:07

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 0/9] Move Hisilicon 6421v600 SPMI and USB drivers out of staging

Hi Greg,

This series contain the final bits needed for the USB3 bus to work without
staging drivers on Hikey 970. It is based on next-20210714, as it depends
on a patch on this branch:

https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next

v13:
- Addressed an issue pointed by Rob Herring at the DT file (patch 6).
v12:
- Added Mark Brown's ack to patch 5;
- Addressed a couple issues at the DT binding, as pointed by Rob Herring
(patch 1).

Mauro Carvalho Chehab (9):
staging: hi6421-spmi-pmic: rename GPIO IRQ OF node
staging: hi6421-spmi-pmic: add a missing dot at copyright
staging: hikey9xx: split hi6421v600 irq into a separate driver
staging: hi6421-spmi-pmic: cleanup drvdata
staging: hi6421-spmi-pmic: rename spmi_device struct
staging: hisilicon,hi6421-spmi-pmic.yaml: fix patternProperties
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 | 12 +-
MAINTAINERS | 7 +
.../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 +
.../mfd/hi6421-spmi-pmic.c | 78 +++++--
drivers/misc/Kconfig | 10 +
drivers/misc/Makefile | 1 +
.../hi6421v600-irq.c} | 208 +++++++++---------
drivers/regulator/hi6421v600-regulator.c | 10 +-
drivers/staging/Kconfig | 2 -
drivers/staging/Makefile | 1 -
drivers/staging/hikey9xx/Kconfig | 19 --
drivers/staging/hikey9xx/Makefile | 3 -
drivers/staging/hikey9xx/TODO | 5 -
17 files changed, 463 insertions(+), 182 deletions(-)
rename {drivers/staging/hikey9xx => Documentation/devicetree/bindings/mfd}/hisilicon,hi6421-spmi-pmic.yaml (93%)
create mode 100644 arch/arm64/boot/dts/hisilicon/hikey970-pmic.dtsi
rename include/linux/mfd/hi6421-spmi-pmic.h => drivers/mfd/hi6421-spmi-pmic.c (4%)
rename drivers/{staging/hikey9xx/hi6421-spmi-pmic.c => misc/hi6421v600-irq.c} (48%)
delete mode 100644 drivers/staging/hikey9xx/Kconfig
delete mode 100644 drivers/staging/hikey9xx/Makefile
delete mode 100644 drivers/staging/hikey9xx/TODO

--
2.31.1



2021-07-14 09:14:07

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 5/9] staging: hi6421-spmi-pmic: rename spmi_device struct

Let's not call a pointer to spmi_device as pdev, as it is
something else.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index f63ba73c9e33..c9c0c3d7011f 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -26,19 +26,19 @@ static const struct regmap_config regmap_config = {
.fast_io = true
};

-static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
+static int hi6421_spmi_pmic_probe(struct spmi_device *sdev)
{
- struct device *dev = &pdev->dev;
+ struct device *dev = &sdev->dev;
struct regmap *regmap;
int ret;

- regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
+ regmap = devm_regmap_init_spmi_ext(sdev, &regmap_config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);

- dev_set_drvdata(&pdev->dev, regmap);
+ dev_set_drvdata(&sdev->dev, regmap);

- ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
+ ret = devm_mfd_add_devices(&sdev->dev, PLATFORM_DEVID_NONE,
hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
NULL, 0, NULL);
if (ret < 0)
--
2.31.1

2021-07-14 09:14:19

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 8/9] dts: hisilicon: add support for the PMIC found on Hikey 970

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 <[email protected]>
---
.../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 d8abf442ee7e..7c32f5fd5cc5 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

2021-07-14 09:14:20

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 1/9] staging: hi6421-spmi-pmic: rename GPIO IRQ OF node

Instead of using the standard name ("gpios"), use "interrupts".

Suggested-by: Rob Herring <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +-
drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 35ef3d4c760b..9a7e095246f7 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -233,7 +233,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)

ddata->dev = dev;

- ddata->gpio = of_get_gpio(np, 0);
+ ddata->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);
if (ddata->gpio < 0)
return ddata->gpio;

diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
index 8e355cddd437..252b600f02a8 100644
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
@@ -34,7 +34,7 @@ properties:

interrupt-controller: true

- gpios:
+ interrupts:
maxItems: 1
description: GPIO used for IRQs

@@ -71,7 +71,7 @@ examples:

#interrupt-cells = <2>;
interrupt-controller;
- gpios = <&gpio28 0 0>;
+ interrupts = <&gpio28 0 0>;

regulators {
#address-cells = <1>;
--
2.31.1

2021-07-14 09:14:29

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 4/9] staging: hi6421-spmi-pmic: cleanup drvdata

There are lots of fields at struct hi6421_spmi_pmic that aren't
used. In a matter of fact, only regmap is needed.

So, drop the struct as a hole, and set just the regmap as
the drvdata.

While here, add a missing dot at the Huawei's copyrights.

Acked-by: Mark Brown <[email protected]>
Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
drivers/misc/hi6421v600-irq.c | 9 ++++----
drivers/regulator/hi6421v600-regulator.c | 10 ++++-----
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 16 +++++--------
include/linux/mfd/hi6421-spmi-pmic.h | 25 ---------------------
4 files changed, 14 insertions(+), 46 deletions(-)
delete mode 100644 include/linux/mfd/hi6421-spmi-pmic.h

diff --git a/drivers/misc/hi6421v600-irq.c b/drivers/misc/hi6421v600-irq.c
index 04623557ec3c..fd9d7223a202 100644
--- a/drivers/misc/hi6421v600-irq.c
+++ b/drivers/misc/hi6421v600-irq.c
@@ -10,7 +10,6 @@
#include <linux/bitops.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
@@ -220,7 +219,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = pmic_dev->of_node;
struct hi6421v600_irq *priv;
- struct hi6421_spmi_pmic *pmic;
+ struct regmap *regmap;
unsigned int virq;
int i, ret;

@@ -229,8 +228,8 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
* which should first set drvdata. If this doesn't happen, hit
* a warn on and return.
*/
- pmic = dev_get_drvdata(pmic_dev);
- if (WARN_ON(!pmic))
+ regmap = dev_get_drvdata(pmic_dev);
+ if (WARN_ON(!regmap))
return -ENODEV;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -238,7 +237,7 @@ static int hi6421v600_irq_probe(struct platform_device *pdev)
return -ENOMEM;

priv->dev = dev;
- priv->regmap = pmic->regmap;
+ priv->regmap = regmap;

spin_lock_init(&priv->lock);

diff --git a/drivers/regulator/hi6421v600-regulator.c b/drivers/regulator/hi6421v600-regulator.c
index 916d4e1f9061..23cdf90944e9 100644
--- a/drivers/regulator/hi6421v600-regulator.c
+++ b/drivers/regulator/hi6421v600-regulator.c
@@ -9,8 +9,8 @@
// Guodong Xu <[email protected]>

#include <linux/delay.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
@@ -237,7 +237,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
struct hi6421_spmi_reg_priv *priv;
struct hi6421_spmi_reg_info *info;
struct device *dev = &pdev->dev;
- struct hi6421_spmi_pmic *pmic;
+ struct regmap *regmap;
struct regulator_dev *rdev;
int i;

@@ -246,8 +246,8 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)
* which should first set drvdata. If this doesn't happen, hit
* a warn on and return.
*/
- pmic = dev_get_drvdata(pmic_dev);
- if (WARN_ON(!pmic))
+ regmap = dev_get_drvdata(pmic_dev);
+ if (WARN_ON(!regmap))
return -ENODEV;

priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -261,7 +261,7 @@ static int hi6421_spmi_regulator_probe(struct platform_device *pdev)

config.dev = pdev->dev.parent;
config.driver_data = priv;
- config.regmap = pmic->regmap;
+ config.regmap = regmap;

rdev = devm_regulator_register(dev, &info->desc, &config);
if (IS_ERR(rdev)) {
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 46dc1b856217..f63ba73c9e33 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -8,7 +8,6 @@
*/

#include <linux/mfd/core.h>
-#include <linux/mfd/hi6421-spmi-pmic.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
@@ -30,19 +29,14 @@ static const struct regmap_config regmap_config = {
static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
{
struct device *dev = &pdev->dev;
+ struct regmap *regmap;
int ret;
- struct hi6421_spmi_pmic *ddata;
- 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);
+ regmap = devm_regmap_init_spmi_ext(pdev, &regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);

- ddata->dev = dev;
-
- dev_set_drvdata(&pdev->dev, ddata);
+ dev_set_drvdata(&pdev->dev, regmap);

ret = devm_mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE,
hi6421v600_devs, ARRAY_SIZE(hi6421v600_devs),
diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h
deleted file mode 100644
index e5b8dbf828b6..000000000000
--- a/include/linux/mfd/hi6421-spmi-pmic.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Header file for device driver Hi6421 PMIC
- *
- * Copyright (c) 2013 Linaro Ltd.
- * Copyright (C) 2011 Hisilicon.
- * Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
- *
- * Guodong Xu <[email protected]>
- */
-
-#ifndef __HISI_PMIC_H
-#define __HISI_PMIC_H
-
-#include <linux/irqdomain.h>
-#include <linux/regmap.h>
-
-struct hi6421_spmi_pmic {
- struct resource *res;
- struct device *dev;
- void __iomem *regs;
- struct regmap *regmap;
-};
-
-#endif /* __HISI_PMIC_H */
--
2.31.1

2021-07-14 09:14:36

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 7/9] mfd: hi6421-spmi-pmic: move driver from staging

This driver is ready for mainstream. So, move it out of staging.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
.../mfd}/hisilicon,hi6421-spmi-pmic.yaml | 0
MAINTAINERS | 7 +++++++
drivers/mfd/Kconfig | 16 ++++++++++++++++
drivers/mfd/Makefile | 1 +
.../hikey9xx => mfd}/hi6421-spmi-pmic.c | 0
drivers/staging/Kconfig | 2 --
drivers/staging/Makefile | 1 -
drivers/staging/hikey9xx/Kconfig | 19 -------------------
drivers/staging/hikey9xx/Makefile | 3 ---
drivers/staging/hikey9xx/TODO | 5 -----
10 files changed, 24 insertions(+), 30 deletions(-)
rename {drivers/staging/hikey9xx => Documentation/devicetree/bindings/mfd}/hisilicon,hi6421-spmi-pmic.yaml (100%)
rename drivers/{staging/hikey9xx => mfd}/hi6421-spmi-pmic.c (100%)
delete mode 100644 drivers/staging/hikey9xx/Kconfig
delete mode 100644 drivers/staging/hikey9xx/Makefile
delete mode 100644 drivers/staging/hikey9xx/TODO

diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
similarity index 100%
rename from drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
rename to Documentation/devicetree/bindings/mfd/hisilicon,hi6421-spmi-pmic.yaml
diff --git a/MAINTAINERS b/MAINTAINERS
index 50df0c02ba03..c553766c7ac3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8451,6 +8451,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 <[email protected]>
+L: [email protected]
+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 <[email protected]>
S: Maintained
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6a3fd2d75f96..01bb42f0ca0b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -510,6 +510,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 8116c19d5fd4..570b9ffb34d0 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -231,6 +231,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_RT4831) += rt4831.o
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/mfd/hi6421-spmi-pmic.c
similarity index 100%
rename from drivers/staging/hikey9xx/hi6421-spmi-pmic.c
rename to drivers/mfd/hi6421-spmi-pmic.c
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index c8eaae6412bb..03ee99d98945 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -102,6 +102,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 818b6f964369..9a4c0e6f34d5 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -41,4 +41,3 @@ obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
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.
--
2.31.1

2021-07-14 09:14:41

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 9/9] dts: hisilicon: add support for USB3 on Hikey 970

Add the USB3 bindings for Kirin 970 phy and Hikey 970 board.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
.../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 7c32f5fd5cc5..16f81f86e3fa 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 20698cfd0637..1f228612192c 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

2021-07-14 09:14:41

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: [PATCH v13 3/9] staging: hikey9xx: split hi6421v600 irq into a separate driver

Per MFD subsystem requirements, split the IRQ part of the
driver into a separate one with just the IRQ handling code
and the powerkey support.

Signed-off-by: Mauro Carvalho Chehab <[email protected]>
---
drivers/misc/Kconfig | 10 +
drivers/misc/Makefile | 1 +
drivers/misc/hi6421v600-irq.c | 314 ++++++++++++++++++
drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 245 +-------------
.../hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 2 +-
include/linux/mfd/hi6421-spmi-pmic.h | 5 -
6 files changed, 329 insertions(+), 248 deletions(-)
create mode 100644 drivers/misc/hi6421v600-irq.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f4fb5c52b863..29294c52d5af 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -208,6 +208,16 @@ config CS5535_CLOCK_EVENT_SRC
MFGPTs have a better resolution and max interval than the
generic PIT, and are suitable for use as high-res timers.

+config HI6421V600_IRQ
+ tristate "HiSilicon Hi6421v600 IRQ and powerkey"
+ depends on OF
+ depends on SPMI
+ select MFD_CORE
+ select REGMAP_SPMI
+ help
+ This driver provides IRQ handling for Hi6421v600, used on
+ some Kirin chipsets, like the one at Hikey 970.
+
config HP_ILO
tristate "Channel interface driver for the HP iLO processor"
depends on PCI
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e92a56d4442f..f91cab8c3d55 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -57,3 +57,4 @@ obj-$(CONFIG_HABANA_AI) += habanalabs/
obj-$(CONFIG_UACCE) += uacce/
obj-$(CONFIG_XILINX_SDFEC) += xilinx_sdfec.o
obj-$(CONFIG_HISI_HIKEY_USB) += hisi_hikey_usb.o
+obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o
diff --git a/drivers/misc/hi6421v600-irq.c b/drivers/misc/hi6421v600-irq.c
new file mode 100644
index 000000000000..04623557ec3c
--- /dev/null
+++ b/drivers/misc/hi6421v600-irq.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device driver for irqs 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/hi6421-spmi-pmic.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+
+struct hi6421v600_irq {
+ struct device *dev;
+ struct irq_domain *domain;
+ int irq;
+ int gpio;
+ unsigned int *irqs;
+ struct regmap *regmap;
+
+ /* Protect IRQ mask changes */
+ spinlock_t lock;
+};
+
+enum hi6421v600_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 irqs.
+ * See drivers/irq/hi6421-irq.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 0xff
+
+static irqreturn_t hi6421v600_irq_handler(int irq, void *__priv)
+{
+ struct hi6421v600_irq *priv = __priv;
+ unsigned long pending;
+ unsigned int in;
+ int i, offset;
+
+ for (i = 0; i < HISI_IRQ_BANK_SIZE; i++) {
+ regmap_read(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &in);
+
+ /* Mark pending IRQs as handled */
+ regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, in);
+
+ pending = in & HISI_8BITS_MASK;
+
+ 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(priv->irqs[POWERKEY_DOWN]);
+ generic_handle_irq(priv->irqs[POWERKEY_UP]);
+ pending &= ~HISI_IRQ_POWERKEY_UP_DOWN;
+ }
+
+ if (!pending)
+ continue;
+
+ for_each_set_bit(offset, &pending, BITS_PER_BYTE) {
+ generic_handle_irq(priv->irqs[offset + i * BITS_PER_BYTE]);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static void hi6421v600_irq_mask(struct irq_data *d)
+{
+ struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+ unsigned int data;
+ u32 offset;
+
+ offset = HISI_IRQ_MASK_REG(d);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ regmap_read(priv->regmap, offset, &data);
+ data |= HISI_IRQ_MASK_BIT(d);
+ regmap_write(priv->regmap, offset, data);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void hi6421v600_irq_unmask(struct irq_data *d)
+{
+ struct hi6421v600_irq *priv = irq_data_get_irq_chip_data(d);
+ u32 data, offset;
+ unsigned long flags;
+
+ offset = HISI_IRQ_MASK_REG(d);
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ regmap_read(priv->regmap, offset, &data);
+ data &= ~HISI_IRQ_MASK_BIT(d);
+ regmap_write(priv->regmap, offset, data);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static struct irq_chip hi6421v600_pmu_irqchip = {
+ .name = "hi6421v600-irq",
+ .irq_mask = hi6421v600_irq_mask,
+ .irq_unmask = hi6421v600_irq_unmask,
+ .irq_disable = hi6421v600_irq_mask,
+ .irq_enable = hi6421v600_irq_unmask,
+};
+
+static int hi6421v600_irq_map(struct irq_domain *d, unsigned int virq,
+ irq_hw_number_t hw)
+{
+ struct hi6421v600_irq *priv = d->host_data;
+
+ irq_set_chip_and_handler_name(virq, &hi6421v600_pmu_irqchip,
+ handle_simple_irq, "hi6421v600");
+ irq_set_chip_data(virq, priv);
+ irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+ return 0;
+}
+
+static const struct irq_domain_ops hi6421v600_domain_ops = {
+ .map = hi6421v600_irq_map,
+ .xlate = irq_domain_xlate_twocell,
+};
+
+static void hi6421v600_irq_init(struct hi6421v600_irq *priv)
+{
+ int i;
+ unsigned int pending;
+
+ /* Mask all IRQs */
+ for (i = 0; i < HISI_IRQ_BANK_SIZE; i++)
+ regmap_write(priv->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(priv->regmap, SOC_PMIC_IRQ0_ADDR + i, &pending);
+ regmap_write(priv->regmap, SOC_PMIC_IRQ0_ADDR + i,
+ HISI_8BITS_MASK);
+ }
+}
+
+static int hi6421v600_irq_probe(struct platform_device *pdev)
+{
+ struct device *pmic_dev = pdev->dev.parent;
+ struct device *dev = &pdev->dev;
+ struct device_node *np = pmic_dev->of_node;
+ struct hi6421v600_irq *priv;
+ struct hi6421_spmi_pmic *pmic;
+ unsigned int virq;
+ int i, ret;
+
+ /*
+ * This driver is meant to be called by hi6421-spmi-core,
+ * which should first set drvdata. If this doesn't happen, hit
+ * a warn on and return.
+ */
+ pmic = dev_get_drvdata(pmic_dev);
+ if (WARN_ON(!pmic))
+ return -ENODEV;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->dev = dev;
+ priv->regmap = pmic->regmap;
+
+ spin_lock_init(&priv->lock);
+
+ priv->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);
+ if (priv->gpio < 0)
+ return priv->gpio;
+
+ if (!gpio_is_valid(priv->gpio))
+ return -EINVAL;
+
+ ret = devm_gpio_request_one(dev, priv->gpio, GPIOF_IN, "pmic");
+ if (ret < 0) {
+ dev_err(dev, "Failed to request gpio%d\n", priv->gpio);
+ return ret;
+ }
+
+ priv->irq = gpio_to_irq(priv->gpio);
+
+ platform_set_drvdata(pdev, priv);
+
+ hi6421v600_irq_init(priv);
+
+ priv->irqs = devm_kzalloc(dev, PMIC_IRQ_LIST_MAX * sizeof(int), GFP_KERNEL);
+ if (!priv->irqs)
+ return -ENOMEM;
+
+ priv->domain = irq_domain_add_simple(np, PMIC_IRQ_LIST_MAX, 0,
+ &hi6421v600_domain_ops, priv);
+ if (!priv->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(priv->domain, i);
+ if (!virq) {
+ dev_err(dev, "Failed to map H/W IRQ\n");
+ return -ENODEV;
+ }
+ priv->irqs[i] = virq;
+ }
+
+ ret = devm_request_threaded_irq(dev,
+ priv->irq, hi6421v600_irq_handler,
+ NULL,
+ IRQF_TRIGGER_LOW | IRQF_SHARED | IRQF_NO_SUSPEND,
+ "pmic", priv);
+ if (ret < 0) {
+ dev_err(dev, "Failed to start IRQ handling thread: error %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct platform_device_id hi6421v600_irq_table[] = {
+ { .name = "hi6421v600-irq" },
+ {},
+};
+MODULE_DEVICE_TABLE(platform, hi6421v600_irq_table);
+
+static struct platform_driver hi6421v600_irq_driver = {
+ .id_table = hi6421v600_irq_table,
+ .driver = {
+ .name = "hi6421v600-irq",
+ },
+ .probe = hi6421v600_irq_probe,
+};
+module_platform_driver(hi6421v600_irq_driver);
+
+MODULE_DESCRIPTION("HiSilicon Hi6421v600 IRQ driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
index 08b6f33c505d..46dc1b856217 100644
--- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
+++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
@@ -7,205 +7,19 @@
* 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/regmap.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 0xff
-
static const struct mfd_cell hi6421v600_devs[] = {
+ { .name = "hi6421v600-irq", },
{ .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 */
- regmap_write(ddata->regmap, SOC_PMIC_IRQ0_ADDR + i, in);
-
- pending = in & HISI_8BITS_MASK;
-
- 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,
@@ -216,11 +30,8 @@ static const struct regmap_config regmap_config = {
static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
+ int ret;
struct hi6421_spmi_pmic *ddata;
- unsigned int virq;
- int ret, i;
-
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
return -ENOMEM;
@@ -229,58 +40,8 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
if (IS_ERR(ddata->regmap))
return PTR_ERR(ddata->regmap);

- spin_lock_init(&ddata->lock);
-
ddata->dev = dev;

- ddata->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);
- 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 -ENODEV;
- }
- ddata->irqs[i] = virq;
- }
-
- ret = devm_request_threaded_irq(dev,
- 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,
diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
index 252b600f02a8..a2963bea87ea 100644
--- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
+++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
@@ -66,7 +66,7 @@ examples:
/* pmic properties */

pmic: pmic@0 {
- compatible = "hisilicon,hi6421-spmi";
+ compatible = "hisilicon,hi6421v600-spmi";
reg = <0 0>;

#interrupt-cells = <2>;
diff --git a/include/linux/mfd/hi6421-spmi-pmic.h b/include/linux/mfd/hi6421-spmi-pmic.h
index 2660226138b8..e5b8dbf828b6 100644
--- a/include/linux/mfd/hi6421-spmi-pmic.h
+++ b/include/linux/mfd/hi6421-spmi-pmic.h
@@ -19,11 +19,6 @@ struct hi6421_spmi_pmic {
struct resource *res;
struct device *dev;
void __iomem *regs;
- spinlock_t lock;
- struct irq_domain *domain;
- int irq;
- int gpio;
- unsigned int *irqs;
struct regmap *regmap;
};

--
2.31.1

2021-07-14 13:41:17

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v13 1/9] staging: hi6421-spmi-pmic: rename GPIO IRQ OF node

On Wed, Jul 14, 2021 at 3:13 AM Mauro Carvalho Chehab
<[email protected]> wrote:
>
> Instead of using the standard name ("gpios"), use "interrupts".
>
> Suggested-by: Rob Herring <[email protected]>
> Signed-off-by: Mauro Carvalho Chehab <[email protected]>
> ---
> drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +-
> drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> index 35ef3d4c760b..9a7e095246f7 100644
> --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> @@ -233,7 +233,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
>
> ddata->dev = dev;
>
> - ddata->gpio = of_get_gpio(np, 0);
> + ddata->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);

It's an interrupt, you should be using platform_get_irq() and
devm_request_irq().

In general, you should not be using of_get_* for any resources, but
use the firmware agnostic flavors.

> if (ddata->gpio < 0)
> return ddata->gpio;
>
> diff --git a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
> index 8e355cddd437..252b600f02a8 100644
> --- a/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
> +++ b/drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml
> @@ -34,7 +34,7 @@ properties:
>
> interrupt-controller: true
>
> - gpios:
> + interrupts:
> maxItems: 1
> description: GPIO used for IRQs
>
> @@ -71,7 +71,7 @@ examples:
>
> #interrupt-cells = <2>;
> interrupt-controller;
> - gpios = <&gpio28 0 0>;
> + interrupts = <&gpio28 0 0>;
>
> regulators {
> #address-cells = <1>;
> --
> 2.31.1
>

2021-07-16 14:47:35

by Mauro Carvalho Chehab

[permalink] [raw]
Subject: Re: [PATCH v13 1/9] staging: hi6421-spmi-pmic: rename GPIO IRQ OF node

Em Wed, 14 Jul 2021 07:36:43 -0600
Rob Herring <[email protected]> escreveu:

> On Wed, Jul 14, 2021 at 3:13 AM Mauro Carvalho Chehab
> <[email protected]> wrote:
> >
> > Instead of using the standard name ("gpios"), use "interrupts".
> >
> > Suggested-by: Rob Herring <[email protected]>
> > Signed-off-by: Mauro Carvalho Chehab <[email protected]>
> > ---
> > drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +-
> > drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 4 ++--
> > 2 files changed, 3 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > index 35ef3d4c760b..9a7e095246f7 100644
> > --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > @@ -233,7 +233,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
> >
> > ddata->dev = dev;
> >
> > - ddata->gpio = of_get_gpio(np, 0);
> > + ddata->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);
>
> It's an interrupt, you should be using platform_get_irq() and
> devm_request_irq().
>
> In general, you should not be using of_get_* for any resources, but
> use the firmware agnostic flavors.

I've no idea how to convert to use platform_get_irq().

I tried to replace the logic:

priv->gpio = of_get_gpio(np, 0);
if (priv->gpio < 0)
return priv->gpio;

if (!gpio_is_valid(priv->gpio))
return -EINVAL;

ret = devm_gpio_request_one(dev, priv->gpio, GPIOF_IN, "pmic");
if (ret < 0) {
dev_err(dev, "Failed to request gpio%d\n", priv->gpio);
return ret;
}

Into:

priv->irq = platform_get_irq(pdev, 0);

But it didn't work (I also tried the platform_get_irq_byname):

[ 1.109586] hi6421v600-irq hi6421v600-irq: hi6421v600_irq_probe:
[ 1.115676] hi6421v600-irq hi6421v600-irq: IRQ index 0 not found
[ 1.121751] hi6421v600-irq hi6421v600-irq: Error -6 when getting IRQs

The original DT schema as:

gpios = <&gpio28 0 0>;

Based on your past review, this was replaced by:

interrupts = <&gpio28 0 0>;


What am I missing?

Thanks,
Mauro

2021-07-16 15:01:43

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v13 1/9] staging: hi6421-spmi-pmic: rename GPIO IRQ OF node

On Fri, Jul 16, 2021 at 8:45 AM Mauro Carvalho Chehab
<[email protected]> wrote:
>
> Em Wed, 14 Jul 2021 07:36:43 -0600
> Rob Herring <[email protected]> escreveu:
>
> > On Wed, Jul 14, 2021 at 3:13 AM Mauro Carvalho Chehab
> > <[email protected]> wrote:
> > >
> > > Instead of using the standard name ("gpios"), use "interrupts".
> > >
> > > Suggested-by: Rob Herring <[email protected]>
> > > Signed-off-by: Mauro Carvalho Chehab <[email protected]>
> > > ---
> > > drivers/staging/hikey9xx/hi6421-spmi-pmic.c | 2 +-
> > > drivers/staging/hikey9xx/hisilicon,hi6421-spmi-pmic.yaml | 4 ++--
> > > 2 files changed, 3 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > > index 35ef3d4c760b..9a7e095246f7 100644
> > > --- a/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > > +++ b/drivers/staging/hikey9xx/hi6421-spmi-pmic.c
> > > @@ -233,7 +233,7 @@ static int hi6421_spmi_pmic_probe(struct spmi_device *pdev)
> > >
> > > ddata->dev = dev;
> > >
> > > - ddata->gpio = of_get_gpio(np, 0);
> > > + ddata->gpio = of_get_named_gpio_flags(np, "interrupts", 0, NULL);
> >
> > It's an interrupt, you should be using platform_get_irq() and
> > devm_request_irq().
> >
> > In general, you should not be using of_get_* for any resources, but
> > use the firmware agnostic flavors.
>
> I've no idea how to convert to use platform_get_irq().
>
> I tried to replace the logic:
>
> priv->gpio = of_get_gpio(np, 0);
> if (priv->gpio < 0)
> return priv->gpio;
>
> if (!gpio_is_valid(priv->gpio))
> return -EINVAL;
>
> ret = devm_gpio_request_one(dev, priv->gpio, GPIOF_IN, "pmic");
> if (ret < 0) {
> dev_err(dev, "Failed to request gpio%d\n", priv->gpio);
> return ret;
> }
>
> Into:
>
> priv->irq = platform_get_irq(pdev, 0);
>
> But it didn't work (I also tried the platform_get_irq_byname):
>
> [ 1.109586] hi6421v600-irq hi6421v600-irq: hi6421v600_irq_probe:
> [ 1.115676] hi6421v600-irq hi6421v600-irq: IRQ index 0 not found
> [ 1.121751] hi6421v600-irq hi6421v600-irq: Error -6 when getting IRQs
>
> The original DT schema as:
>
> gpios = <&gpio28 0 0>;
>
> Based on your past review, this was replaced by:
>
> interrupts = <&gpio28 0 0>;
>
>
> What am I missing?

'interrupts' doesn't take a phandle. You need:

interrupts = <0 0>;
interrupt-parent = <&gpio28>;

You should have been getting dtc warnings that this was wrong.

Rob