aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpio
diff options
context:
space:
mode:
authorGravatar Hans de Goede <hdegoede@redhat.com> 2021-06-16 17:48:18 +0200
committerGravatar Hans de Goede <hdegoede@redhat.com> 2021-06-16 17:48:18 +0200
commit6c8f2df3b5064fa848f365fe6a51861b90b5ce7f (patch)
treec7eae493c4cc5782091d7786fbcbab3aaa6d839b /drivers/gpio
parentMerge tag 'platform-drivers-x86-goodix-v5.14-1' into review-hans (diff)
parentgpiolib: acpi: Add acpi_gpio_get_io_resource() (diff)
downloadlinux-6c8f2df3b5064fa848f365fe6a51861b90b5ce7f.tar.gz
linux-6c8f2df3b5064fa848f365fe6a51861b90b5ce7f.tar.bz2
linux-6c8f2df3b5064fa848f365fe6a51861b90b5ce7f.zip
Merge tag 'intel-gpio-v5.14-1' into review-hans
intel-gpio for v5.14-1 * Export two functions from GPIO ACPI for wider use * Clean up Whiskey Cove and Crystal Cove GPIO drivers The following is an automated git shortlog grouped by driver: crystalcove: - remove platform_set_drvdata() + cleanup probe gpiolib: - acpi: Add acpi_gpio_get_io_resource() - acpi: Introduce acpi_get_and_request_gpiod() helper wcove: - Split error handling for CTRL and IRQ registers - Unify style of to_reg() with to_ireg() - Use IRQ hardware number getter instead of direct access
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-crystalcove.c10
-rw-r--r--drivers/gpio/gpio-wcove.c39
-rw-r--r--drivers/gpio/gpiolib-acpi.c51
3 files changed, 71 insertions, 29 deletions
diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c
index 2ba225720086..5a909f3c79e8 100644
--- a/drivers/gpio/gpio-crystalcove.c
+++ b/drivers/gpio/gpio-crystalcove.c
@@ -339,8 +339,6 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
if (!cg)
return -ENOMEM;
- platform_set_drvdata(pdev, cg);
-
mutex_init(&cg->buslock);
cg->chip.label = KBUILD_MODNAME;
cg->chip.direction_input = crystalcove_gpio_dir_in;
@@ -372,13 +370,7 @@ static int crystalcove_gpio_probe(struct platform_device *pdev)
return retval;
}
- retval = devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg);
- if (retval) {
- dev_warn(&pdev->dev, "add gpio chip error: %d\n", retval);
- return retval;
- }
-
- return 0;
+ return devm_gpiochip_add_data(&pdev->dev, &cg->chip, cg);
}
static struct platform_driver crystalcove_gpio_driver = {
diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c
index a19eeef6cf1e..16a0fae1e32e 100644
--- a/drivers/gpio/gpio-wcove.c
+++ b/drivers/gpio/gpio-wcove.c
@@ -99,19 +99,14 @@ struct wcove_gpio {
bool set_irq_mask;
};
-static inline int to_reg(int gpio, enum ctrl_register reg_type)
+static inline int to_reg(int gpio, enum ctrl_register type)
{
- unsigned int reg;
+ unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE;
if (gpio >= WCOVE_GPIO_NUM)
return -EOPNOTSUPP;
- if (reg_type == CTRL_IN)
- reg = GPIO_IN_CTRL_BASE + gpio;
- else
- reg = GPIO_OUT_CTRL_BASE + gpio;
-
- return reg;
+ return reg + gpio;
}
static inline int to_ireg(int gpio, enum ctrl_register type, unsigned int *mask)
@@ -129,7 +124,7 @@ static inline int to_ireg(int gpio, enum ctrl_register type, unsigned int *mask)
return reg;
}
-static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio)
+static void wcove_update_irq_mask(struct wcove_gpio *wg, irq_hw_number_t gpio)
{
unsigned int mask, reg = to_ireg(gpio, IRQ_MASK, &mask);
@@ -139,13 +134,10 @@ static void wcove_update_irq_mask(struct wcove_gpio *wg, int gpio)
regmap_clear_bits(wg->regmap, reg, mask);
}
-static void wcove_update_irq_ctrl(struct wcove_gpio *wg, int gpio)
+static void wcove_update_irq_ctrl(struct wcove_gpio *wg, irq_hw_number_t gpio)
{
int reg = to_reg(gpio, CTRL_IN);
- if (reg < 0)
- return;
-
regmap_update_bits(wg->regmap, reg, CTLI_INTCNT_BE, wg->intcnt);
}
@@ -248,8 +240,9 @@ static int wcove_irq_type(struct irq_data *data, unsigned int type)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct wcove_gpio *wg = gpiochip_get_data(chip);
+ irq_hw_number_t gpio = irqd_to_hwirq(data);
- if (data->hwirq >= WCOVE_GPIO_NUM)
+ if (gpio >= WCOVE_GPIO_NUM)
return 0;
switch (type) {
@@ -286,7 +279,7 @@ static void wcove_bus_sync_unlock(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct wcove_gpio *wg = gpiochip_get_data(chip);
- int gpio = data->hwirq;
+ irq_hw_number_t gpio = irqd_to_hwirq(data);
if (wg->update & UPDATE_IRQ_TYPE)
wcove_update_irq_ctrl(wg, gpio);
@@ -301,8 +294,9 @@ static void wcove_irq_unmask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct wcove_gpio *wg = gpiochip_get_data(chip);
+ irq_hw_number_t gpio = irqd_to_hwirq(data);
- if (data->hwirq >= WCOVE_GPIO_NUM)
+ if (gpio >= WCOVE_GPIO_NUM)
return;
wg->set_irq_mask = false;
@@ -313,8 +307,9 @@ static void wcove_irq_mask(struct irq_data *data)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
struct wcove_gpio *wg = gpiochip_get_data(chip);
+ irq_hw_number_t gpio = irqd_to_hwirq(data);
- if (data->hwirq >= WCOVE_GPIO_NUM)
+ if (gpio >= WCOVE_GPIO_NUM)
return;
wg->set_irq_mask = true;
@@ -369,8 +364,7 @@ static irqreturn_t wcove_gpio_irq_handler(int irq, void *data)
return IRQ_HANDLED;
}
-static void wcove_gpio_dbg_show(struct seq_file *s,
- struct gpio_chip *chip)
+static void wcove_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
unsigned int ctlo, ctli, irq_mask, irq_status;
struct wcove_gpio *wg = gpiochip_get_data(chip);
@@ -379,10 +373,15 @@ static void wcove_gpio_dbg_show(struct seq_file *s,
for (gpio = 0; gpio < WCOVE_GPIO_NUM; gpio++) {
ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_OUT), &ctlo);
ret += regmap_read(wg->regmap, to_reg(gpio, CTRL_IN), &ctli);
+ if (ret) {
+ dev_err(wg->dev, "Failed to read registers: CTRL out/in\n");
+ break;
+ }
+
ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_MASK, &mask), &irq_mask);
ret += regmap_read(wg->regmap, to_ireg(gpio, IRQ_STATUS, &mask), &irq_status);
if (ret) {
- pr_err("Failed to read registers: ctrl out/in or irq status/mask\n");
+ dev_err(wg->dev, "Failed to read registers: IRQ status/mask\n");
break;
}
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 3ef22a3c104d..cf99a5752fe0 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -128,6 +128,34 @@ static struct gpio_desc *acpi_get_gpiod(char *path, int pin)
return gpiochip_get_desc(chip, pin);
}
+/**
+ * acpi_get_and_request_gpiod - Translate ACPI GPIO pin to GPIO descriptor and
+ * hold a refcount to the GPIO device.
+ * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
+ * @pin: ACPI GPIO pin number (0-based, controller-relative)
+ * @label: Label to pass to gpiod_request()
+ *
+ * This function is a simple pass-through to acpi_get_gpiod(), except that
+ * as it is intended for use outside of the GPIO layer (in a similar fashion to
+ * gpiod_get_index() for example) it also holds a reference to the GPIO device.
+ */
+struct gpio_desc *acpi_get_and_request_gpiod(char *path, int pin, char *label)
+{
+ struct gpio_desc *gpio;
+ int ret;
+
+ gpio = acpi_get_gpiod(path, pin);
+ if (IS_ERR(gpio))
+ return gpio;
+
+ ret = gpiod_request(gpio, label);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return gpio;
+}
+EXPORT_SYMBOL_GPL(acpi_get_and_request_gpiod);
+
static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
{
struct acpi_gpio_event *event = data;
@@ -168,6 +196,29 @@ bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
}
EXPORT_SYMBOL_GPL(acpi_gpio_get_irq_resource);
+/**
+ * acpi_gpio_get_io_resource - Fetch details of an ACPI resource if it is a GPIO
+ * I/O resource or return False if not.
+ * @ares: Pointer to the ACPI resource to fetch
+ * @agpio: Pointer to a &struct acpi_resource_gpio to store the output pointer
+ */
+bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
+ struct acpi_resource_gpio **agpio)
+{
+ struct acpi_resource_gpio *gpio;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+ return false;
+
+ gpio = &ares->data.gpio;
+ if (gpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
+ return false;
+
+ *agpio = gpio;
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_gpio_get_io_resource);
+
static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
struct acpi_gpio_event *event)
{