diff options
author | Linus Torvalds | 2021-06-30 11:15:39 -0700 |
---|---|---|
committer | Linus Torvalds | 2021-06-30 11:15:39 -0700 |
commit | 776ba3ad659e4955079f57f8d859e7994ea35076 (patch) | |
tree | 18b27ed3684dfbe1c1ee2d4b54706657c551b346 /drivers/gpio | |
parent | ebb81c14543fb43cb2e1f2bfb5d32f5e390cf895 (diff) | |
parent | 0e695c3f7f66c66e0a1da90cc5378198a656d494 (diff) |
Merge tag 'platform-drivers-x86-v5.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86
Pull x86 platform driver updates from Hans de Goede:
"Highlights:
- New think-lmi driver adding support for changing Lenovo Thinkpad
BIOS settings from within Linux using the standard firmware-
attributes class sysfs API
- MS Surface aggregator-cdev now also supports forwarding events to
user-space (for debugging / new driver development purposes only)
- New intel_skl_int3472 driver this provides the necessary glue to
translate ACPI table information to GPIOs, regulators, etc. for
camera sensors on Intel devices with IPU3 attached MIPI cameras
- A whole bunch of other fixes + device-specific quirk additions
- New devm_work_autocancel() devm-helpers.h function"
* tag 'platform-drivers-x86-v5.14-1' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: (83 commits)
platform/x86: dell-wmi-sysman: Change user experience when Admin/System Password is modified
platform/x86: intel_skl_int3472: Uninitialized variable in skl_int3472_handle_gpio_resources()
platform/x86: think-lmi: Move kfree(setting->possible_values) to tlmi_attr_setting_release()
platform/x86: think-lmi: Split current_value to reflect only the value
platform/x86: think-lmi: Fix issues with duplicate attributes
platform/x86: think-lmi: Return EINVAL when kbdlang gets set to a 0 length string
platform/x86: intel_cht_int33fe: Move to its own subfolder
platform/x86: intel_skl_int3472: Move to intel/ subfolder
platform/x86: intel_skl_int3472: Provide skl_int3472_unregister_clock()
platform/x86: intel_skl_int3472: Provide skl_int3472_unregister_regulator()
platform/x86: intel_skl_int3472: Use ACPI GPIO resource directly
platform/x86: intel_skl_int3472: Fix dependencies (drop CLKDEV_LOOKUP)
platform/x86: intel_skl_int3472: Free ACPI device resources after use
platform/x86: Remove "default n" entries
platform/x86: ISST: Use numa node id for cpu pci dev mapping
platform/x86: ISST: Optimize CPU to PCI device mapping
tools/power/x86/intel-speed-select: v1.10 release
tools/power/x86/intel-speed-select: Fix uncore memory frequency display
extcon: extcon-max8997: Simplify driver using devm
extcon: extcon-max8997: Fix IRQ freeing at error path
...
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/gpio/gpio-crystalcove.c | 10 | ||||
-rw-r--r-- | drivers/gpio/gpio-wcove.c | 39 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 51 |
4 files changed, 72 insertions, 30 deletions
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3c69b785cb79..63b84ba161dc 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1367,7 +1367,7 @@ config GPIO_TPS65912 config GPIO_TPS68470 bool "TPS68470 GPIO" - depends on MFD_TPS68470 + depends on INTEL_SKL_INT3472 help Select this option to enable GPIO driver for the TPS68470 chip family. 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 5b4111e4be3f..411525ac4cc4 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) { |