* [PATCH v2] gpio: rockchip: support acpi
@ 2022-09-06 1:30 ` Jianqun Xu
0 siblings, 0 replies; 5+ messages in thread
From: Jianqun Xu @ 2022-09-06 1:30 UTC (permalink / raw)
To: heiko, linus.walleij, brgl
Cc: andriy.shevchenko, linux-gpio, linux-rockchip, linux-kernel,
huangtao, Jianqun Xu
This patch fix driver to support acpi by following changes:
* support get gpio bank number from uid of acpi
* try to get clocks for dt nodes but for acpi
* try to get clocks by a char id first, if a dt patch applied
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
---
v2:
- fix rockchip_pin_output_deferred to rockchip_pin_deferred
drivers/gpio/gpio-rockchip.c | 233 ++++++++++++++++++++++-------------
1 file changed, 144 insertions(+), 89 deletions(-)
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index ebb50c25a461..05c5b2a80260 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -6,9 +6,9 @@
* Copyright (c) 2021 Rockchip Electronics Co. Ltd.
*/
+#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/clk.h>
-#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
@@ -16,10 +16,9 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
+#include <linux/platform_device.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include "../pinctrl/core.h"
@@ -29,6 +28,8 @@
#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */
#define GPIO_TYPE_V2_1 (0x0101157C) /* GPIO Version ID 0x0101157C */
+#define GPIO_MAX_PINS (32)
+
static const struct rockchip_gpio_regs gpio_regs_v1 = {
.port_dr = 0x00,
.port_ddr = 0x04,
@@ -200,6 +201,9 @@ static int rockchip_gpio_set_debounce(struct gpio_chip *gc,
if (bank->gpio_type == GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) {
div_debounce_support = true;
freq = clk_get_rate(bank->db_clk);
+ if (!freq)
+ return -EINVAL;
+
max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq;
if (debounce > max_debounce)
return -EINVAL;
@@ -507,7 +511,7 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank)
struct irq_chip_generic *gc;
int ret;
- bank->domain = irq_domain_add_linear(bank->of_node, 32,
+ bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32,
&irq_generic_chip_ops, NULL);
if (!bank->domain) {
dev_warn(bank->dev, "could not init irq domain for bank %s\n",
@@ -578,6 +582,16 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
gc->label = bank->name;
gc->parent = bank->dev;
+ if (!gc->base)
+ gc->base = GPIO_MAX_PINS * bank->bank_num;
+ if (!gc->ngpio)
+ gc->ngpio = GPIO_MAX_PINS;
+ if (!gc->label) {
+ gc->label = kasprintf(GFP_KERNEL, "gpio%d", bank->bank_num);
+ if (!gc->label)
+ return -ENOMEM;
+ }
+
ret = gpiochip_add_data(gc, bank);
if (ret) {
dev_err(bank->dev, "failed to add gpiochip %s, %d\n",
@@ -585,35 +599,6 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return ret;
}
- /*
- * For DeviceTree-supported systems, the gpio core checks the
- * pinctrl's device node for the "gpio-ranges" property.
- * If it is present, it takes care of adding the pin ranges
- * for the driver. In this case the driver can skip ahead.
- *
- * In order to remain compatible with older, existing DeviceTree
- * files which don't set the "gpio-ranges" property or systems that
- * utilize ACPI the driver has to call gpiochip_add_pin_range().
- */
- if (!of_property_read_bool(bank->of_node, "gpio-ranges")) {
- struct device_node *pctlnp = of_get_parent(bank->of_node);
- struct pinctrl_dev *pctldev = NULL;
-
- if (!pctlnp)
- return -ENODATA;
-
- pctldev = of_pinctrl_get(pctlnp);
- if (!pctldev)
- return -ENODEV;
-
- ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
- gc->base, gc->ngpio);
- if (ret) {
- dev_err(bank->dev, "Failed to add pin range\n");
- goto fail;
- }
- }
-
ret = rockchip_interrupts_register(bank);
if (ret) {
dev_err(bank->dev, "failed to register interrupt, %d\n", ret);
@@ -628,47 +613,18 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return ret;
}
-static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+static void rockchip_gpio_get_ver(struct rockchip_pin_bank *bank)
{
- struct resource res;
- int id = 0;
-
- if (of_address_to_resource(bank->of_node, 0, &res)) {
- dev_err(bank->dev, "cannot find IO resource for bank\n");
- return -ENOENT;
- }
-
- bank->reg_base = devm_ioremap_resource(bank->dev, &res);
- if (IS_ERR(bank->reg_base))
- return PTR_ERR(bank->reg_base);
-
- bank->irq = irq_of_parse_and_map(bank->of_node, 0);
- if (!bank->irq)
- return -EINVAL;
-
- bank->clk = of_clk_get(bank->of_node, 0);
- if (IS_ERR(bank->clk))
- return PTR_ERR(bank->clk);
-
- clk_prepare_enable(bank->clk);
- id = readl(bank->reg_base + gpio_regs_v2.version_id);
+ int id = readl(bank->reg_base + gpio_regs_v2.version_id);
/* If not gpio v2, that is default to v1. */
if (id == GPIO_TYPE_V2 || id == GPIO_TYPE_V2_1) {
bank->gpio_regs = &gpio_regs_v2;
bank->gpio_type = GPIO_TYPE_V2;
- bank->db_clk = of_clk_get(bank->of_node, 1);
- if (IS_ERR(bank->db_clk)) {
- dev_err(bank->dev, "cannot find debounce clk\n");
- clk_disable_unprepare(bank->clk);
- return -EINVAL;
- }
} else {
bank->gpio_regs = &gpio_regs_v1;
bank->gpio_type = GPIO_TYPE_V1;
}
-
- return 0;
}
static struct rockchip_pin_bank *
@@ -690,40 +646,117 @@ rockchip_gpio_find_bank(struct pinctrl_dev *pctldev, int id)
return found ? bank : NULL;
}
+static int rockchip_gpio_of_get_bank_id(struct device *dev)
+{
+ static int gpio;
+ int bank_id = -1;
+
+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+ bank_id = of_alias_get_id(dev->of_node, "gpio");
+ if (bank_id < 0)
+ bank_id = gpio++;
+ }
+
+ return bank_id;
+}
+
+#ifdef CONFIG_ACPI
+static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
+{
+ struct acpi_device *adev;
+ unsigned long bank_id = -1;
+ const char *uid;
+ int ret;
+
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
+ return -ENXIO;
+
+ uid = acpi_device_uid(adev);
+ if (!uid || !(*uid)) {
+ dev_err(dev, "Cannot retrieve UID\n");
+ return -ENODEV;
+ }
+
+ ret = kstrtoul(uid, 0, &bank_id);
+
+ return !ret ? bank_id : -ERANGE;
+}
+#else
+static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
+{
+ return -ENOENT;
+}
+#endif /* CONFIG_ACPI */
+
static int rockchip_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct device_node *pctlnp = of_get_parent(np);
struct pinctrl_dev *pctldev = NULL;
struct rockchip_pin_bank *bank = NULL;
- struct rockchip_pin_deferred *cfg;
- static int gpio;
- int id, ret;
+ int bank_id = 0;
+ int ret;
- if (!np || !pctlnp)
- return -ENODEV;
+ bank_id = rockchip_gpio_acpi_get_bank_id(dev);
+ if (bank_id < 0) {
+ bank_id = rockchip_gpio_of_get_bank_id(dev);
+ if (bank_id < 0)
+ return bank_id;
+ }
+
+ if (!ACPI_COMPANION(dev)) {
+ struct device_node *pctlnp = of_get_parent(dev->of_node);
- pctldev = of_pinctrl_get(pctlnp);
- if (!pctldev)
- return -EPROBE_DEFER;
+ pctldev = of_pinctrl_get(pctlnp);
+ if (!pctldev)
+ return -EPROBE_DEFER;
- id = of_alias_get_id(np, "gpio");
- if (id < 0)
- id = gpio++;
+ bank = rockchip_gpio_find_bank(pctldev, bank_id);
+ if (!bank)
+ return -ENODEV;
+ }
- bank = rockchip_gpio_find_bank(pctldev, id);
- if (!bank)
- return -EINVAL;
+ if (!bank) {
+ bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
+ if (!bank)
+ return -ENOMEM;
+ }
+ bank->bank_num = bank_id;
bank->dev = dev;
- bank->of_node = np;
+
+ bank->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bank->reg_base))
+ return PTR_ERR(bank->reg_base);
+
+ bank->irq = platform_get_irq(pdev, 0);
+ if (bank->irq < 0)
+ return bank->irq;
raw_spin_lock_init(&bank->slock);
- ret = rockchip_get_bank_data(bank);
- if (ret)
- return ret;
+ if (!ACPI_COMPANION(dev)) {
+ bank->clk = devm_clk_get(dev, "bus");
+ if (IS_ERR(bank->clk)) {
+ bank->clk = of_clk_get(dev->of_node, 0);
+ if (IS_ERR(bank->clk)) {
+ dev_err(dev, "fail to get apb clock\n");
+ return PTR_ERR(bank->clk);
+ }
+ }
+
+ bank->db_clk = devm_clk_get(dev, "db");
+ if (IS_ERR(bank->db_clk)) {
+ bank->db_clk = of_clk_get(dev->of_node, 1);
+ if (IS_ERR(bank->db_clk))
+ bank->db_clk = NULL;
+ }
+ }
+
+ clk_prepare_enable(bank->clk);
+ clk_prepare_enable(bank->db_clk);
+
+ rockchip_gpio_get_ver(bank);
/*
* Prevent clashes with a deferred output setting
@@ -733,14 +766,29 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
ret = rockchip_gpiolib_register(bank);
if (ret) {
- clk_disable_unprepare(bank->clk);
- mutex_unlock(&bank->deferred_lock);
- return ret;
+ dev_err(bank->dev, "Failed to register gpio %d\n", ret);
+ goto err_unlock;
+ }
+
+ if (!device_property_read_bool(bank->dev, "gpio-ranges") && pctldev) {
+ struct gpio_chip *gc = &bank->gpio_chip;
+
+ ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
+ gc->base, gc->ngpio);
+ if (ret) {
+ dev_err(bank->dev, "Failed to add pin range\n");
+ goto err_unlock;
+ }
}
while (!list_empty(&bank->deferred_pins)) {
+ struct rockchip_pin_deferred *cfg;
+
cfg = list_first_entry(&bank->deferred_pins,
struct rockchip_pin_deferred, head);
+ if (!cfg)
+ break;
+
list_del(&cfg->head);
switch (cfg->param) {
@@ -765,9 +813,15 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
mutex_unlock(&bank->deferred_lock);
platform_set_drvdata(pdev, bank);
- dev_info(dev, "probed %pOF\n", np);
+ dev_info(dev, "probed %pfw\n", dev_fwnode(dev));
return 0;
+err_unlock:
+ mutex_unlock(&bank->deferred_lock);
+ clk_disable_unprepare(bank->clk);
+ clk_disable_unprepare(bank->db_clk);
+
+ return ret;
}
static int rockchip_gpio_remove(struct platform_device *pdev)
@@ -775,6 +829,7 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
clk_disable_unprepare(bank->clk);
+ clk_disable_unprepare(bank->db_clk);
gpiochip_remove(&bank->gpio_chip);
return 0;
--
2.25.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2] gpio: rockchip: support acpi
@ 2022-09-06 1:30 ` Jianqun Xu
0 siblings, 0 replies; 5+ messages in thread
From: Jianqun Xu @ 2022-09-06 1:30 UTC (permalink / raw)
To: heiko, linus.walleij, brgl
Cc: andriy.shevchenko, linux-gpio, linux-rockchip, linux-kernel,
huangtao, Jianqun Xu
This patch fix driver to support acpi by following changes:
* support get gpio bank number from uid of acpi
* try to get clocks for dt nodes but for acpi
* try to get clocks by a char id first, if a dt patch applied
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
---
v2:
- fix rockchip_pin_output_deferred to rockchip_pin_deferred
drivers/gpio/gpio-rockchip.c | 233 ++++++++++++++++++++++-------------
1 file changed, 144 insertions(+), 89 deletions(-)
diff --git a/drivers/gpio/gpio-rockchip.c b/drivers/gpio/gpio-rockchip.c
index ebb50c25a461..05c5b2a80260 100644
--- a/drivers/gpio/gpio-rockchip.c
+++ b/drivers/gpio/gpio-rockchip.c
@@ -6,9 +6,9 @@
* Copyright (c) 2021 Rockchip Electronics Co. Ltd.
*/
+#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/clk.h>
-#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/driver.h>
#include <linux/init.h>
@@ -16,10 +16,9 @@
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_irq.h>
+#include <linux/platform_device.h>
#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/property.h>
#include <linux/regmap.h>
#include "../pinctrl/core.h"
@@ -29,6 +28,8 @@
#define GPIO_TYPE_V2 (0x01000C2B) /* GPIO Version ID 0x01000C2B */
#define GPIO_TYPE_V2_1 (0x0101157C) /* GPIO Version ID 0x0101157C */
+#define GPIO_MAX_PINS (32)
+
static const struct rockchip_gpio_regs gpio_regs_v1 = {
.port_dr = 0x00,
.port_ddr = 0x04,
@@ -200,6 +201,9 @@ static int rockchip_gpio_set_debounce(struct gpio_chip *gc,
if (bank->gpio_type == GPIO_TYPE_V2 && !IS_ERR(bank->db_clk)) {
div_debounce_support = true;
freq = clk_get_rate(bank->db_clk);
+ if (!freq)
+ return -EINVAL;
+
max_debounce = (GENMASK(23, 0) + 1) * 2 * 1000000 / freq;
if (debounce > max_debounce)
return -EINVAL;
@@ -507,7 +511,7 @@ static int rockchip_interrupts_register(struct rockchip_pin_bank *bank)
struct irq_chip_generic *gc;
int ret;
- bank->domain = irq_domain_add_linear(bank->of_node, 32,
+ bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32,
&irq_generic_chip_ops, NULL);
if (!bank->domain) {
dev_warn(bank->dev, "could not init irq domain for bank %s\n",
@@ -578,6 +582,16 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
gc->label = bank->name;
gc->parent = bank->dev;
+ if (!gc->base)
+ gc->base = GPIO_MAX_PINS * bank->bank_num;
+ if (!gc->ngpio)
+ gc->ngpio = GPIO_MAX_PINS;
+ if (!gc->label) {
+ gc->label = kasprintf(GFP_KERNEL, "gpio%d", bank->bank_num);
+ if (!gc->label)
+ return -ENOMEM;
+ }
+
ret = gpiochip_add_data(gc, bank);
if (ret) {
dev_err(bank->dev, "failed to add gpiochip %s, %d\n",
@@ -585,35 +599,6 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return ret;
}
- /*
- * For DeviceTree-supported systems, the gpio core checks the
- * pinctrl's device node for the "gpio-ranges" property.
- * If it is present, it takes care of adding the pin ranges
- * for the driver. In this case the driver can skip ahead.
- *
- * In order to remain compatible with older, existing DeviceTree
- * files which don't set the "gpio-ranges" property or systems that
- * utilize ACPI the driver has to call gpiochip_add_pin_range().
- */
- if (!of_property_read_bool(bank->of_node, "gpio-ranges")) {
- struct device_node *pctlnp = of_get_parent(bank->of_node);
- struct pinctrl_dev *pctldev = NULL;
-
- if (!pctlnp)
- return -ENODATA;
-
- pctldev = of_pinctrl_get(pctlnp);
- if (!pctldev)
- return -ENODEV;
-
- ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
- gc->base, gc->ngpio);
- if (ret) {
- dev_err(bank->dev, "Failed to add pin range\n");
- goto fail;
- }
- }
-
ret = rockchip_interrupts_register(bank);
if (ret) {
dev_err(bank->dev, "failed to register interrupt, %d\n", ret);
@@ -628,47 +613,18 @@ static int rockchip_gpiolib_register(struct rockchip_pin_bank *bank)
return ret;
}
-static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
+static void rockchip_gpio_get_ver(struct rockchip_pin_bank *bank)
{
- struct resource res;
- int id = 0;
-
- if (of_address_to_resource(bank->of_node, 0, &res)) {
- dev_err(bank->dev, "cannot find IO resource for bank\n");
- return -ENOENT;
- }
-
- bank->reg_base = devm_ioremap_resource(bank->dev, &res);
- if (IS_ERR(bank->reg_base))
- return PTR_ERR(bank->reg_base);
-
- bank->irq = irq_of_parse_and_map(bank->of_node, 0);
- if (!bank->irq)
- return -EINVAL;
-
- bank->clk = of_clk_get(bank->of_node, 0);
- if (IS_ERR(bank->clk))
- return PTR_ERR(bank->clk);
-
- clk_prepare_enable(bank->clk);
- id = readl(bank->reg_base + gpio_regs_v2.version_id);
+ int id = readl(bank->reg_base + gpio_regs_v2.version_id);
/* If not gpio v2, that is default to v1. */
if (id == GPIO_TYPE_V2 || id == GPIO_TYPE_V2_1) {
bank->gpio_regs = &gpio_regs_v2;
bank->gpio_type = GPIO_TYPE_V2;
- bank->db_clk = of_clk_get(bank->of_node, 1);
- if (IS_ERR(bank->db_clk)) {
- dev_err(bank->dev, "cannot find debounce clk\n");
- clk_disable_unprepare(bank->clk);
- return -EINVAL;
- }
} else {
bank->gpio_regs = &gpio_regs_v1;
bank->gpio_type = GPIO_TYPE_V1;
}
-
- return 0;
}
static struct rockchip_pin_bank *
@@ -690,40 +646,117 @@ rockchip_gpio_find_bank(struct pinctrl_dev *pctldev, int id)
return found ? bank : NULL;
}
+static int rockchip_gpio_of_get_bank_id(struct device *dev)
+{
+ static int gpio;
+ int bank_id = -1;
+
+ if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+ bank_id = of_alias_get_id(dev->of_node, "gpio");
+ if (bank_id < 0)
+ bank_id = gpio++;
+ }
+
+ return bank_id;
+}
+
+#ifdef CONFIG_ACPI
+static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
+{
+ struct acpi_device *adev;
+ unsigned long bank_id = -1;
+ const char *uid;
+ int ret;
+
+ adev = ACPI_COMPANION(dev);
+ if (!adev)
+ return -ENXIO;
+
+ uid = acpi_device_uid(adev);
+ if (!uid || !(*uid)) {
+ dev_err(dev, "Cannot retrieve UID\n");
+ return -ENODEV;
+ }
+
+ ret = kstrtoul(uid, 0, &bank_id);
+
+ return !ret ? bank_id : -ERANGE;
+}
+#else
+static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
+{
+ return -ENOENT;
+}
+#endif /* CONFIG_ACPI */
+
static int rockchip_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- struct device_node *pctlnp = of_get_parent(np);
struct pinctrl_dev *pctldev = NULL;
struct rockchip_pin_bank *bank = NULL;
- struct rockchip_pin_deferred *cfg;
- static int gpio;
- int id, ret;
+ int bank_id = 0;
+ int ret;
- if (!np || !pctlnp)
- return -ENODEV;
+ bank_id = rockchip_gpio_acpi_get_bank_id(dev);
+ if (bank_id < 0) {
+ bank_id = rockchip_gpio_of_get_bank_id(dev);
+ if (bank_id < 0)
+ return bank_id;
+ }
+
+ if (!ACPI_COMPANION(dev)) {
+ struct device_node *pctlnp = of_get_parent(dev->of_node);
- pctldev = of_pinctrl_get(pctlnp);
- if (!pctldev)
- return -EPROBE_DEFER;
+ pctldev = of_pinctrl_get(pctlnp);
+ if (!pctldev)
+ return -EPROBE_DEFER;
- id = of_alias_get_id(np, "gpio");
- if (id < 0)
- id = gpio++;
+ bank = rockchip_gpio_find_bank(pctldev, bank_id);
+ if (!bank)
+ return -ENODEV;
+ }
- bank = rockchip_gpio_find_bank(pctldev, id);
- if (!bank)
- return -EINVAL;
+ if (!bank) {
+ bank = devm_kzalloc(dev, sizeof(*bank), GFP_KERNEL);
+ if (!bank)
+ return -ENOMEM;
+ }
+ bank->bank_num = bank_id;
bank->dev = dev;
- bank->of_node = np;
+
+ bank->reg_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bank->reg_base))
+ return PTR_ERR(bank->reg_base);
+
+ bank->irq = platform_get_irq(pdev, 0);
+ if (bank->irq < 0)
+ return bank->irq;
raw_spin_lock_init(&bank->slock);
- ret = rockchip_get_bank_data(bank);
- if (ret)
- return ret;
+ if (!ACPI_COMPANION(dev)) {
+ bank->clk = devm_clk_get(dev, "bus");
+ if (IS_ERR(bank->clk)) {
+ bank->clk = of_clk_get(dev->of_node, 0);
+ if (IS_ERR(bank->clk)) {
+ dev_err(dev, "fail to get apb clock\n");
+ return PTR_ERR(bank->clk);
+ }
+ }
+
+ bank->db_clk = devm_clk_get(dev, "db");
+ if (IS_ERR(bank->db_clk)) {
+ bank->db_clk = of_clk_get(dev->of_node, 1);
+ if (IS_ERR(bank->db_clk))
+ bank->db_clk = NULL;
+ }
+ }
+
+ clk_prepare_enable(bank->clk);
+ clk_prepare_enable(bank->db_clk);
+
+ rockchip_gpio_get_ver(bank);
/*
* Prevent clashes with a deferred output setting
@@ -733,14 +766,29 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
ret = rockchip_gpiolib_register(bank);
if (ret) {
- clk_disable_unprepare(bank->clk);
- mutex_unlock(&bank->deferred_lock);
- return ret;
+ dev_err(bank->dev, "Failed to register gpio %d\n", ret);
+ goto err_unlock;
+ }
+
+ if (!device_property_read_bool(bank->dev, "gpio-ranges") && pctldev) {
+ struct gpio_chip *gc = &bank->gpio_chip;
+
+ ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
+ gc->base, gc->ngpio);
+ if (ret) {
+ dev_err(bank->dev, "Failed to add pin range\n");
+ goto err_unlock;
+ }
}
while (!list_empty(&bank->deferred_pins)) {
+ struct rockchip_pin_deferred *cfg;
+
cfg = list_first_entry(&bank->deferred_pins,
struct rockchip_pin_deferred, head);
+ if (!cfg)
+ break;
+
list_del(&cfg->head);
switch (cfg->param) {
@@ -765,9 +813,15 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
mutex_unlock(&bank->deferred_lock);
platform_set_drvdata(pdev, bank);
- dev_info(dev, "probed %pOF\n", np);
+ dev_info(dev, "probed %pfw\n", dev_fwnode(dev));
return 0;
+err_unlock:
+ mutex_unlock(&bank->deferred_lock);
+ clk_disable_unprepare(bank->clk);
+ clk_disable_unprepare(bank->db_clk);
+
+ return ret;
}
static int rockchip_gpio_remove(struct platform_device *pdev)
@@ -775,6 +829,7 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
clk_disable_unprepare(bank->clk);
+ clk_disable_unprepare(bank->db_clk);
gpiochip_remove(&bank->gpio_chip);
return 0;
--
2.25.1
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: rockchip: support acpi
2022-09-06 1:30 ` Jianqun Xu
@ 2022-09-06 16:18 ` Andy Shevchenko
-1 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2022-09-06 16:18 UTC (permalink / raw)
To: Jianqun Xu
Cc: heiko, linus.walleij, brgl, linux-gpio, linux-rockchip,
linux-kernel, huangtao
On Tue, Sep 06, 2022 at 09:30:25AM +0800, Jianqun Xu wrote:
> This patch fix driver to support acpi by following changes:
> * support get gpio bank number from uid of acpi
> * try to get clocks for dt nodes but for acpi
> * try to get clocks by a char id first, if a dt patch applied
...
> - bank->domain = irq_domain_add_linear(bank->of_node, 32,
> + bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32,
> &irq_generic_chip_ops, NULL);
Should it be converted to use GPIO_MAX_PINS at the same time?
...
> +static int rockchip_gpio_of_get_bank_id(struct device *dev)
> +{
> + static int gpio;
> + int bank_id = -1;
> + if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
Can't is_of_node() be sufficient check?
> + bank_id = of_alias_get_id(dev->of_node, "gpio");
> + if (bank_id < 0)
> + bank_id = gpio++;
> + }
> +
> + return bank_id;
> +}
...
> +#ifdef CONFIG_ACPI
Why?
> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
> +{
> + struct acpi_device *adev;
> + unsigned long bank_id = -1;
> + const char *uid;
> + int ret;
> +
> + adev = ACPI_COMPANION(dev);
> + if (!adev)
> + return -ENXIO;
> +
> + uid = acpi_device_uid(adev);
> + if (!uid || !(*uid)) {
> + dev_err(dev, "Cannot retrieve UID\n");
> + return -ENODEV;
Why is it a fatal error? Can't be the same approach as for OF be used?
> + }
> +
> + ret = kstrtoul(uid, 0, &bank_id);
> +
> + return !ret ? bank_id : -ERANGE;
Use standard pattern, i.e.
if (ret)
return ret;
> +}
> +#else
> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
> +{
> + return -ENOENT;
> +}
> +#endif /* CONFIG_ACPI */
...
> + int bank_id = 0;
Redundant assignment.
...
> + if (!ACPI_COMPANION(dev)) {
One of:
is_of_node()
!is_acpi_node()
?
...
> + if (!ACPI_COMPANION(dev)) {
Ditto.
But looking how this disrupts the code, just leave OF and ACPI parts separate,
don't mix them.
...
> + if (!device_property_read_bool(bank->dev, "gpio-ranges") && pctldev) {
> + struct gpio_chip *gc = &bank->gpio_chip;
> +
> + ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
> + gc->base, gc->ngpio);
> + if (ret) {
> + dev_err(bank->dev, "Failed to add pin range\n");
> + goto err_unlock;
> + }
> }
Why? What's wrong with GPIO library doing this for all chips?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] gpio: rockchip: support acpi
@ 2022-09-06 16:18 ` Andy Shevchenko
0 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2022-09-06 16:18 UTC (permalink / raw)
To: Jianqun Xu
Cc: heiko, linus.walleij, brgl, linux-gpio, linux-rockchip,
linux-kernel, huangtao
On Tue, Sep 06, 2022 at 09:30:25AM +0800, Jianqun Xu wrote:
> This patch fix driver to support acpi by following changes:
> * support get gpio bank number from uid of acpi
> * try to get clocks for dt nodes but for acpi
> * try to get clocks by a char id first, if a dt patch applied
...
> - bank->domain = irq_domain_add_linear(bank->of_node, 32,
> + bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32,
> &irq_generic_chip_ops, NULL);
Should it be converted to use GPIO_MAX_PINS at the same time?
...
> +static int rockchip_gpio_of_get_bank_id(struct device *dev)
> +{
> + static int gpio;
> + int bank_id = -1;
> + if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
Can't is_of_node() be sufficient check?
> + bank_id = of_alias_get_id(dev->of_node, "gpio");
> + if (bank_id < 0)
> + bank_id = gpio++;
> + }
> +
> + return bank_id;
> +}
...
> +#ifdef CONFIG_ACPI
Why?
> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
> +{
> + struct acpi_device *adev;
> + unsigned long bank_id = -1;
> + const char *uid;
> + int ret;
> +
> + adev = ACPI_COMPANION(dev);
> + if (!adev)
> + return -ENXIO;
> +
> + uid = acpi_device_uid(adev);
> + if (!uid || !(*uid)) {
> + dev_err(dev, "Cannot retrieve UID\n");
> + return -ENODEV;
Why is it a fatal error? Can't be the same approach as for OF be used?
> + }
> +
> + ret = kstrtoul(uid, 0, &bank_id);
> +
> + return !ret ? bank_id : -ERANGE;
Use standard pattern, i.e.
if (ret)
return ret;
> +}
> +#else
> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
> +{
> + return -ENOENT;
> +}
> +#endif /* CONFIG_ACPI */
...
> + int bank_id = 0;
Redundant assignment.
...
> + if (!ACPI_COMPANION(dev)) {
One of:
is_of_node()
!is_acpi_node()
?
...
> + if (!ACPI_COMPANION(dev)) {
Ditto.
But looking how this disrupts the code, just leave OF and ACPI parts separate,
don't mix them.
...
> + if (!device_property_read_bool(bank->dev, "gpio-ranges") && pctldev) {
> + struct gpio_chip *gc = &bank->gpio_chip;
> +
> + ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
> + gc->base, gc->ngpio);
> + if (ret) {
> + dev_err(bank->dev, "Failed to add pin range\n");
> + goto err_unlock;
> + }
> }
Why? What's wrong with GPIO library doing this for all chips?
--
With Best Regards,
Andy Shevchenko
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Re: [PATCH v2] gpio: rockchip: support acpi
2022-09-06 16:18 ` Andy Shevchenko
(?)
@ 2022-09-07 0:58 ` jay.xu
-1 siblings, 0 replies; 5+ messages in thread
From: jay.xu @ 2022-09-07 0:58 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Heiko Stübner, linus.walleij, Bartosz Golaszewski,
linux-gpio, open list:ARM/Rockchip SoC..., linux-kernel,
Tao Huang
Hi Andy
--------------
jay.xu@rock-chips.com
>On Tue, Sep 06, 2022 at 09:30:25AM +0800, Jianqun Xu wrote:
>> This patch fix driver to support acpi by following changes:
>> * support get gpio bank number from uid of acpi
>> * try to get clocks for dt nodes but for acpi
>> * try to get clocks by a char id first, if a dt patch applied
>
>...
>
>> - bank->domain = irq_domain_add_linear(bank->of_node, 32,
>> + bank->domain = irq_domain_create_linear(dev_fwnode(bank->dev), 32,
>> &irq_generic_chip_ops, NULL);
>
>Should it be converted to use GPIO_MAX_PINS at the same time?
okay, will fix in v3
>
>...
>
>> +static int rockchip_gpio_of_get_bank_id(struct device *dev)
>> +{
>> + static int gpio;
>> + int bank_id = -1;
>
>> + if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
>
>Can't is_of_node() be sufficient check?
okay, will fix in v3
>
>> + bank_id = of_alias_get_id(dev->of_node, "gpio");
>> + if (bank_id < 0)
>> + bank_id = gpio++;
>> + }
>> +
>> + return bank_id;
>> +}
>
>...
>
>> +#ifdef CONFIG_ACPI
>
>Why?
Because the acpi_device_uid only defined under CONFIG_ACPI,
>
>> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
>> +{
>> + struct acpi_device *adev;
>> + unsigned long bank_id = -1;
>> + const char *uid;
>> + int ret;
>> +
>> + adev = ACPI_COMPANION(dev);
>> + if (!adev)
>> + return -ENXIO;
>> +
>> + uid = acpi_device_uid(adev);
>> + if (!uid || !(*uid)) {
>> + dev_err(dev, "Cannot retrieve UID\n");
>> + return -ENODEV;
>
>Why is it a fatal error? Can't be the same approach as for OF be used?
For the OF, the very early driver get the gpio id from the node name of dt node, such as
gpio0@xxxxxx
After a patch to change the dt node as common name like gpio0: gpio@xxxxx, but lack of the alias
the driver should to conside that so use a static gpio number id, also support get the controller id
from the aliasment.
For the ACPI, here we locat at the first version, and reference to the ACPI ducument, the gpio controller
id should passed by the uid, so this patch treat it as a requirement but a option.
>
>> + }
>> +
>> + ret = kstrtoul(uid, 0, &bank_id);
>> +
>> + return !ret ? bank_id : -ERANGE;
>
>Use standard pattern, i.e.
>
> if (ret)
> return ret;
>
>> +}
>> +#else
>> +static int rockchip_gpio_acpi_get_bank_id(struct device *dev)
>> +{
>> + return -ENOENT;
>> +}
>> +#endif /* CONFIG_ACPI */
>
>...
>
>> + int bank_id = 0;
>
>Redundant assignment.
>
>...
>
>> + if (!ACPI_COMPANION(dev)) {
>
>One of:
>
> is_of_node()
> !is_acpi_node()
>
>?
>
>...
>
>> + if (!ACPI_COMPANION(dev)) {
>
>Ditto.
>
>But looking how this disrupts the code, just leave OF and ACPI parts separate,
>don't mix them.
>
>...
>
>> + if (!device_property_read_bool(bank->dev, "gpio-ranges") && pctldev) {
>> + struct gpio_chip *gc = &bank->gpio_chip;
>> +
>> + ret = gpiochip_add_pin_range(gc, dev_name(pctldev->dev), 0,
>> + gc->base, gc->ngpio);
>> + if (ret) {
>> + dev_err(bank->dev, "Failed to add pin range\n");
>> + goto err_unlock;
>> + }
>> }
>
>Why? What's wrong with GPIO library doing this for all chips?
Under ACPI case, the pinctrl device maybe not exist, currently our board runs without pinctrl,
so add a check to the pctldev.
>
>--
>With Best Regards,
>Andy Shevchenko
>
>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-09-07 0:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-09-06 1:30 [PATCH v2] gpio: rockchip: support acpi Jianqun Xu
2022-09-06 1:30 ` Jianqun Xu
2022-09-06 16:18 ` Andy Shevchenko
2022-09-06 16:18 ` Andy Shevchenko
2022-09-07 0:58 ` jay.xu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.