From 0d9a693cc8619b28f0eeb689a554647d42848fde Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Wed, 29 Oct 2014 15:41:01 +0100 Subject: gpio / ACPI: Add support for _DSD device properties With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and other things as well) returned by _CRS. Previously we were only able to use integer index to find the corresponding GPIO, which is pretty error prone if the order changes. With _DSD we can now query GPIOs using name instead of an integer index, like the below example shows: // Bluetooth device with reset and shutdown GPIOs Device (BTH) { Name (_HID, ...) Name (_CRS, ResourceTemplate () { GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, "\\_SB.GPO0", 0, ResourceConsumer) {15} GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly, "\\_SB.GPO0", 0, ResourceConsumer) {27, 31} }) Name (_DSD, Package () { ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), Package () { Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }}, Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }}, } }) } The format of the supported GPIO property is: Package () { "name", Package () { ref, index, pin, active_low }} ref - The device that has _CRS containing GpioIo()/GpioInt() resources, typically this is the device itself (BTH in our case). index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero. pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero. active_low - If 1 the GPIO is marked as active_low. Since ACPI GpioIo() resource does not have field saying whether it is active low or high, the "active_low" argument can be used here. Setting it to 1 marks the GPIO as active low. In our Bluetooth example the "reset-gpio" refers to the second GpioIo() resource, second pin in that resource with the GPIO number of 31. This patch implements necessary support to gpiolib for extracting GPIOs using _DSD device properties. Signed-off-by: Mika Westerberg Acked-by: Linus Walleij Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki --- drivers/gpio/gpiolib-acpi.c | 78 +++++++++++++++++++++++++++++++++++++-------- drivers/gpio/gpiolib.c | 30 ++++++++++++++--- drivers/gpio/gpiolib.h | 7 ++-- 3 files changed, 94 insertions(+), 21 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 05c6275da22..8aa6ca47374 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -290,6 +290,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; + int pin_index; struct gpio_desc *desc; int n; }; @@ -303,13 +304,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) if (lookup->n++ == lookup->index && !lookup->desc) { const struct acpi_resource_gpio *agpio = &ares->data.gpio; + int pin_index = lookup->pin_index; + + if (pin_index >= agpio->pin_table_length) + return 1; lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, - agpio->pin_table[0]); + agpio->pin_table[pin_index]); lookup->info.gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; - lookup->info.active_low = - agpio->polarity == ACPI_ACTIVE_LOW; + + /* + * ActiveLow is only specified for GpioInt resource. If + * GpioIo is used then the only way to set the flag is + * to use _DSD "gpios" property. + */ + if (lookup->info.gpioint) + lookup->info.active_low = + agpio->polarity == ACPI_ACTIVE_LOW; } return 1; @@ -317,40 +329,75 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) /** * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources - * @dev: pointer to a device to get GPIO from + * @adev: pointer to a ACPI device to get GPIO from + * @propname: Property name of the GPIO (optional) * @index: index of GpioIo/GpioInt resource (starting from %0) * @info: info pointer to fill in (optional) * - * Function goes through ACPI resources for @dev and based on @index looks + * Function goes through ACPI resources for @adev and based on @index looks * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor, * and returns it. @index matches GpioIo/GpioInt resources only so if there * are total %3 GPIO resources, the index goes from %0 to %2. * + * If @propname is specified the GPIO is looked using device property. In + * that case @index is used to select the GPIO entry in the property value + * (in case of multiple). + * * If the GPIO cannot be translated or there is an error an ERR_PTR is * returned. * * Note: if the GPIO resource has multiple entries in the pin list, this * function only returns the first. */ -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, + const char *propname, int index, struct acpi_gpio_info *info) { struct acpi_gpio_lookup lookup; struct list_head resource_list; - struct acpi_device *adev; - acpi_handle handle; + bool active_low = false; int ret; - if (!dev) - return ERR_PTR(-EINVAL); - - handle = ACPI_HANDLE(dev); - if (!handle || acpi_bus_get_device(handle, &adev)) + if (!adev) return ERR_PTR(-ENODEV); memset(&lookup, 0, sizeof(lookup)); lookup.index = index; + if (propname) { + struct acpi_reference_args args; + + dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); + + memset(&args, 0, sizeof(args)); + ret = acpi_dev_get_property_reference(adev, propname, NULL, + index, &args); + if (ret) + return ERR_PTR(ret); + + /* + * The property was found and resolved so need to + * lookup the GPIO based on returned args instead. + */ + adev = args.adev; + if (args.nargs >= 2) { + lookup.index = args.args[0]; + lookup.pin_index = args.args[1]; + /* + * 3rd argument, if present is used to + * specify active_low. + */ + if (args.nargs >= 3) + active_low = !!args.args[2]; + } + + dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n", + dev_name(&adev->dev), args.nargs, + args.args[0], args.args[1], args.args[2]); + } else { + dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); + } + INIT_LIST_HEAD(&resource_list); ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, &lookup); @@ -359,8 +406,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, acpi_dev_free_resource_list(&resource_list); - if (lookup.desc && info) + if (lookup.desc && info) { *info = lookup.info; + if (active_low) + info->active_low = active_low; + } return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index e8e98ca25ec..2bca0495cb4 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, unsigned int idx, enum gpio_lookup_flags *flags) { + static const char * const suffixes[] = { "gpios", "gpio" }; + struct acpi_device *adev = ACPI_COMPANION(dev); struct acpi_gpio_info info; struct gpio_desc *desc; + char propname[32]; + int i; - desc = acpi_get_gpiod_by_index(dev, idx, &info); - if (IS_ERR(desc)) - return desc; + /* Try first from _DSD */ + for (i = 0; i < ARRAY_SIZE(suffixes); i++) { + if (con_id && strcmp(con_id, "gpios")) { + snprintf(propname, sizeof(propname), "%s-%s", + con_id, suffixes[i]); + } else { + snprintf(propname, sizeof(propname), "%s", + suffixes[i]); + } + + desc = acpi_get_gpiod_by_index(adev, propname, idx, &info); + if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER)) + break; + } + + /* Then from plain _CRS GPIOs */ + if (IS_ERR(desc)) { + desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info); + if (IS_ERR(desc)) + return desc; + } - if (info.gpioint && info.active_low) + if (info.active_low) *flags |= GPIO_ACTIVE_LOW; return desc; diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 9db2b6a71c5..e3a52113a54 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip); void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, + const char *propname, int index, struct acpi_gpio_info *info); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } @@ -47,8 +48,8 @@ static inline void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } static inline struct gpio_desc * -acpi_get_gpiod_by_index(struct device *dev, int index, - struct acpi_gpio_info *info) +acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, + int index, struct acpi_gpio_info *info) { return ERR_PTR(-ENOSYS); } -- cgit v1.2.3-70-g09d2 From c479ff093328c63ae9e496951a34f7fef550503a Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 21 Oct 2014 13:33:56 +0200 Subject: gpio: sch: Consolidate core and resume banks This is actually a single device with two sets of identical registers, which just happen to start from a different offset. Instead of having separate GPIO chips created we consolidate them to be single GPIO chip. In addition having a single GPIO chip allows us to handle ACPI GPIO translation in the core in a more generic way, since the two GPIO chips share the same parent ACPI device. Signed-off-by: Mika Westerberg Acked-by: Linus Walleij Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki --- drivers/gpio/gpio-sch.c | 293 ++++++++++++++++++------------------------------ 1 file changed, 112 insertions(+), 181 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c index 41e91d70301..99720c8bc8e 100644 --- a/drivers/gpio/gpio-sch.c +++ b/drivers/gpio/gpio-sch.c @@ -29,290 +29,221 @@ #include -static DEFINE_SPINLOCK(gpio_lock); - -#define CGEN (0x00) -#define CGIO (0x04) -#define CGLV (0x08) - -#define RGEN (0x20) -#define RGIO (0x24) -#define RGLV (0x28) - -static unsigned short gpio_ba; - -static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num) -{ - u8 curr_dirs; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - - if (!(curr_dirs & (1 << bit))) - outb(curr_dirs | (1 << bit), gpio_ba + offset); +#define GEN 0x00 +#define GIO 0x04 +#define GLV 0x08 + +struct sch_gpio { + struct gpio_chip chip; + spinlock_t lock; + unsigned short iobase; + unsigned short core_base; + unsigned short resume_base; +}; - spin_unlock(&gpio_lock); - return 0; -} +#define to_sch_gpio(c) container_of(c, struct sch_gpio, chip) -static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num) +static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio, + unsigned reg) { - int res; - unsigned short offset, bit; + unsigned base = 0; - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; + if (gpio >= sch->resume_base) { + gpio -= sch->resume_base; + base += 0x20; + } - res = !!(inb(gpio_ba + offset) & (1 << bit)); - return res; + return base + reg + gpio / 8; } -static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val) +static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio) { - u8 curr_vals; - unsigned short offset, bit; - - spin_lock(&gpio_lock); - - offset = CGLV + gpio_num / 8; - bit = gpio_num % 8; - - curr_vals = inb(gpio_ba + offset); - - if (val) - outb(curr_vals | (1 << bit), gpio_ba + offset); - else - outb((curr_vals & ~(1 << bit)), gpio_ba + offset); - spin_unlock(&gpio_lock); + if (gpio >= sch->resume_base) + gpio -= sch->resume_base; + return gpio % 8; } -static int sch_gpio_core_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) +static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio) { - u8 curr_dirs; unsigned short offset, bit; + u8 enable; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = CGIO + gpio_num / 8; - bit = gpio_num % 8; - - curr_dirs = inb(gpio_ba + offset); - if (curr_dirs & (1 << bit)) - outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + offset = sch_gpio_offset(sch, gpio, GEN); + bit = sch_gpio_bit(sch, gpio); - spin_unlock(&gpio_lock); + enable = inb(sch->iobase + offset); + if (!(enable & (1 << bit))) + outb(enable | (1 << bit), sch->iobase + offset); - /* - * according to the datasheet, writing to the level register has no - * effect when GPIO is programmed as input. - * Actually the the level register is read-only when configured as input. - * Thus presetting the output level before switching to output is _NOT_ possible. - * Hence we set the level after configuring the GPIO as output. - * But we cannot prevent a short low pulse if direction is set to high - * and an external pull-up is connected. - */ - sch_gpio_core_set(gc, gpio_num, val); - return 0; + spin_unlock(&sch->lock); } -static struct gpio_chip sch_gpio_core = { - .label = "sch_gpio_core", - .owner = THIS_MODULE, - .direction_input = sch_gpio_core_direction_in, - .get = sch_gpio_core_get, - .direction_output = sch_gpio_core_direction_out, - .set = sch_gpio_core_set, -}; - -static int sch_gpio_resume_direction_in(struct gpio_chip *gc, - unsigned gpio_num) +static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_dirs; unsigned short offset, bit; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = RGIO + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GIO); + bit = sch_gpio_bit(sch, gpio_num); - curr_dirs = inb(gpio_ba + offset); + curr_dirs = inb(sch->iobase + offset); if (!(curr_dirs & (1 << bit))) - outb(curr_dirs | (1 << bit), gpio_ba + offset); + outb(curr_dirs | (1 << bit), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); return 0; } -static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) +static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num) { + struct sch_gpio *sch = to_sch_gpio(gc); + int res; unsigned short offset, bit; - offset = RGLV + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GLV); + bit = sch_gpio_bit(sch, gpio_num); + + res = !!(inb(sch->iobase + offset) & (1 << bit)); - return !!(inb(gpio_ba + offset) & (1 << bit)); + return res; } -static void sch_gpio_resume_set(struct gpio_chip *gc, - unsigned gpio_num, int val) +static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_vals; unsigned short offset, bit; - spin_lock(&gpio_lock); + spin_lock(&sch->lock); - offset = RGLV + gpio_num / 8; - bit = gpio_num % 8; + offset = sch_gpio_offset(sch, gpio_num, GLV); + bit = sch_gpio_bit(sch, gpio_num); - curr_vals = inb(gpio_ba + offset); + curr_vals = inb(sch->iobase + offset); if (val) - outb(curr_vals | (1 << bit), gpio_ba + offset); + outb(curr_vals | (1 << bit), sch->iobase + offset); else - outb((curr_vals & ~(1 << bit)), gpio_ba + offset); + outb((curr_vals & ~(1 << bit)), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); } -static int sch_gpio_resume_direction_out(struct gpio_chip *gc, - unsigned gpio_num, int val) +static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num, + int val) { + struct sch_gpio *sch = to_sch_gpio(gc); u8 curr_dirs; unsigned short offset, bit; - offset = RGIO + gpio_num / 8; - bit = gpio_num % 8; + spin_lock(&sch->lock); - spin_lock(&gpio_lock); + offset = sch_gpio_offset(sch, gpio_num, GIO); + bit = sch_gpio_bit(sch, gpio_num); - curr_dirs = inb(gpio_ba + offset); + curr_dirs = inb(sch->iobase + offset); if (curr_dirs & (1 << bit)) - outb(curr_dirs & ~(1 << bit), gpio_ba + offset); + outb(curr_dirs & ~(1 << bit), sch->iobase + offset); - spin_unlock(&gpio_lock); + spin_unlock(&sch->lock); /* - * according to the datasheet, writing to the level register has no - * effect when GPIO is programmed as input. - * Actually the the level register is read-only when configured as input. - * Thus presetting the output level before switching to output is _NOT_ possible. - * Hence we set the level after configuring the GPIO as output. - * But we cannot prevent a short low pulse if direction is set to high - * and an external pull-up is connected. - */ - sch_gpio_resume_set(gc, gpio_num, val); + * according to the datasheet, writing to the level register has no + * effect when GPIO is programmed as input. + * Actually the the level register is read-only when configured as input. + * Thus presetting the output level before switching to output is _NOT_ possible. + * Hence we set the level after configuring the GPIO as output. + * But we cannot prevent a short low pulse if direction is set to high + * and an external pull-up is connected. + */ + sch_gpio_set(gc, gpio_num, val); return 0; } -static struct gpio_chip sch_gpio_resume = { - .label = "sch_gpio_resume", +static struct gpio_chip sch_gpio_chip = { + .label = "sch_gpio", .owner = THIS_MODULE, - .direction_input = sch_gpio_resume_direction_in, - .get = sch_gpio_resume_get, - .direction_output = sch_gpio_resume_direction_out, - .set = sch_gpio_resume_set, + .direction_input = sch_gpio_direction_in, + .get = sch_gpio_get, + .direction_output = sch_gpio_direction_out, + .set = sch_gpio_set, }; static int sch_gpio_probe(struct platform_device *pdev) { + struct sch_gpio *sch; struct resource *res; - int err, id; - id = pdev->id; - if (!id) - return -ENODEV; + sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL); + if (!sch) + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!res) return -EBUSY; - if (!request_region(res->start, resource_size(res), pdev->name)) + if (!devm_request_region(&pdev->dev, res->start, resource_size(res), + pdev->name)) return -EBUSY; - gpio_ba = res->start; + spin_lock_init(&sch->lock); + sch->iobase = res->start; + sch->chip = sch_gpio_chip; + sch->chip.label = dev_name(&pdev->dev); + sch->chip.dev = &pdev->dev; - switch (id) { + switch (pdev->id) { case PCI_DEVICE_ID_INTEL_SCH_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 10; - sch_gpio_resume.base = 10; - sch_gpio_resume.ngpio = 4; + sch->core_base = 0; + sch->resume_base = 10; + sch->chip.ngpio = 14; + /* * GPIO[6:0] enabled by default * GPIO7 is configured by the CMC as SLPIOVR * Enable GPIO[9:8] core powered gpios explicitly */ - outb(0x3, gpio_ba + CGEN + 1); + sch_gpio_enable(sch, 8); + sch_gpio_enable(sch, 9); /* * SUS_GPIO[2:0] enabled by default * Enable SUS_GPIO3 resume powered gpio explicitly */ - outb(0x8, gpio_ba + RGEN); + sch_gpio_enable(sch, 13); break; case PCI_DEVICE_ID_INTEL_ITC_LPC: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 5; - sch_gpio_resume.base = 5; - sch_gpio_resume.ngpio = 9; + sch->core_base = 0; + sch->resume_base = 5; + sch->chip.ngpio = 14; break; case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: - sch_gpio_core.base = 0; - sch_gpio_core.ngpio = 21; - sch_gpio_resume.base = 21; - sch_gpio_resume.ngpio = 9; + sch->core_base = 0; + sch->resume_base = 21; + sch->chip.ngpio = 30; break; default: - err = -ENODEV; - goto err_sch_gpio_core; + return -ENODEV; } - sch_gpio_core.dev = &pdev->dev; - sch_gpio_resume.dev = &pdev->dev; - - err = gpiochip_add(&sch_gpio_core); - if (err < 0) - goto err_sch_gpio_core; + platform_set_drvdata(pdev, sch); - err = gpiochip_add(&sch_gpio_resume); - if (err < 0) - goto err_sch_gpio_resume; - - return 0; - -err_sch_gpio_resume: - gpiochip_remove(&sch_gpio_core); - -err_sch_gpio_core: - release_region(res->start, resource_size(res)); - gpio_ba = 0; - - return err; + return gpiochip_add(&sch->chip); } static int sch_gpio_remove(struct platform_device *pdev) { - struct resource *res; - if (gpio_ba) { - - gpiochip_remove(&sch_gpio_core); - gpiochip_remove(&sch_gpio_resume); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - - release_region(res->start, resource_size(res)); - gpio_ba = 0; - } + struct sch_gpio *sch = platform_get_drvdata(pdev); + gpiochip_remove(&sch->chip); return 0; } -- cgit v1.2.3-70-g09d2 From 40b7318319281b1bdec804f6435f26cadd329c13 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 21 Oct 2014 13:33:59 +0200 Subject: gpio: Support for unified device properties interface Some drivers need to deal with only firmware representation of its GPIOs. An example would be a GPIO button array driver where each button is described as a separate firmware node in device tree. Typically these child nodes do not have physical representation in the Linux device model. In order to help device drivers to handle such firmware child nodes we add dev[m]_get_named_gpiod_from_child() that takes a child firmware node pointer as its second argument (the first one is the parent device itself), finds the GPIO using whatever is the underlying firmware method, and requests the GPIO properly. Signed-off-by: Mika Westerberg Acked-by: Alexandre Courbot Acked-by: Grant Likely Signed-off-by: Rafael J. Wysocki --- drivers/gpio/devres.c | 32 +++++++++++++++++++++++++ drivers/gpio/gpiolib.c | 55 +++++++++++++++++++++++++++++++++++++++++++ include/linux/gpio/consumer.h | 7 ++++++ 3 files changed, 94 insertions(+) (limited to 'drivers/gpio') diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c index 954b9f6b0ef..13dbd3dfc33 100644 --- a/drivers/gpio/devres.c +++ b/drivers/gpio/devres.c @@ -108,6 +108,38 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev, } EXPORT_SYMBOL(__devm_gpiod_get_index); +/** + * devm_get_gpiod_from_child - get a GPIO descriptor from a device's child node + * @dev: GPIO consumer + * @child: firmware node (child of @dev) + * + * GPIO descriptors returned from this function are automatically disposed on + * driver detach. + */ +struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, + struct fwnode_handle *child) +{ + struct gpio_desc **dr; + struct gpio_desc *desc; + + dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *), + GFP_KERNEL); + if (!dr) + return ERR_PTR(-ENOMEM); + + desc = fwnode_get_named_gpiod(child, "gpios"); + if (IS_ERR(desc)) { + devres_free(dr); + return desc; + } + + *dr = desc; + devres_add(dev, dr); + + return desc; +} +EXPORT_SYMBOL(devm_get_gpiod_from_child); + /** * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional() * @dev: GPIO consumer diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 2bca0495cb4..58659dbe702 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1734,6 +1734,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev, } EXPORT_SYMBOL_GPL(__gpiod_get_index); +/** + * fwnode_get_named_gpiod - obtain a GPIO from firmware node + * @fwnode: handle of the firmware node + * @propname: name of the firmware property representing the GPIO + * + * This function can be used for drivers that get their configuration + * from firmware. + * + * Function properly finds the corresponding GPIO using whatever is the + * underlying firmware interface and then makes sure that the GPIO + * descriptor is requested before it is returned to the caller. + * + * In case of error an ERR_PTR() is returned. + */ +struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, + const char *propname) +{ + struct gpio_desc *desc = ERR_PTR(-ENODEV); + bool active_low = false; + int ret; + + if (!fwnode) + return ERR_PTR(-EINVAL); + + if (is_of_node(fwnode)) { + enum of_gpio_flags flags; + + desc = of_get_named_gpiod_flags(of_node(fwnode), propname, 0, + &flags); + if (!IS_ERR(desc)) + active_low = flags & OF_GPIO_ACTIVE_LOW; + } else if (is_acpi_node(fwnode)) { + struct acpi_gpio_info info; + + desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname, 0, + &info); + if (!IS_ERR(desc)) + active_low = info.active_low; + } + + if (IS_ERR(desc)) + return desc; + + ret = gpiod_request(desc, NULL); + if (ret) + return ERR_PTR(ret); + + /* Only value flag can be set from both DT and ACPI is active_low */ + if (active_low) + set_bit(FLAG_ACTIVE_LOW, &desc->flags); + + return desc; +} +EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod); + /** * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO * function diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index 12f146fa660..00b1b70d68b 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -94,6 +94,13 @@ int gpiod_to_irq(const struct gpio_desc *desc); struct gpio_desc *gpio_to_desc(unsigned gpio); int desc_to_gpio(const struct gpio_desc *desc); +/* Child properties interface */ +struct fwnode_handle; + +struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, + const char *propname); +struct gpio_desc *devm_get_gpiod_from_child(struct device *dev, + struct fwnode_handle *child); #else /* CONFIG_GPIOLIB */ static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev, -- cgit v1.2.3-70-g09d2 From f028d5242d7ecb0a1bfc80e7bd292201c8612641 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 3 Nov 2014 23:39:41 +0100 Subject: ACPI / GPIO: Driver GPIO mappings for ACPI GPIOs Provide a way for device drivers using GPIOs described by ACPI GpioIo resources in _CRS to tell the GPIO subsystem what names (connection IDs) to associate with specific GPIO pins defined in there. To do that, a driver needs to define a mapping table as a NULL-terminated array of struct acpi_gpio_mapping objects that each contain a name, a pointer to an array of line data (struct acpi_gpio_params) objects and the size of that array. Each struct acpi_gpio_params object consists of three fields, crs_entry_index, line_index, active_low, representing the index of the target GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target line in that resource starting from zero, and the active-low flag for that line, respectively. Next, the mapping table needs to be passed as the second argument to acpi_dev_add_driver_gpios() that will register it with the ACPI device object pointed to by its first argument. That should be done in the driver's .probe() routine. On removal, the driver should unregister its GPIO mapping table by calling acpi_dev_remove_driver_gpios() on the ACPI device object where that table was previously registered. Included are fixes from Mika Westerberg. Acked-by: Alexandre Courbot Reviewed-by: Linus Walleij Signed-off-by: Rafael J. Wysocki --- drivers/gpio/gpiolib-acpi.c | 43 +++++++++++++++++++++++++++++++++++++++++-- include/acpi/acpi_bus.h | 3 +++ include/linux/acpi.h | 30 ++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 8aa6ca47374..5a4d061e787 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -287,6 +287,41 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) } } +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + if (adev && gpios) { + adev->driver_gpios = gpios; + return 0; + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios); + +static bool acpi_get_driver_gpio_data(struct acpi_device *adev, + const char *name, int index, + struct acpi_reference_args *args) +{ + const struct acpi_gpio_mapping *gm; + + if (!adev->driver_gpios) + return false; + + for (gm = adev->driver_gpios; gm->name; gm++) + if (!strcmp(name, gm->name) && gm->data && index < gm->size) { + const struct acpi_gpio_params *par = gm->data + index; + + args->adev = adev; + args->args[0] = par->crs_entry_index; + args->args[1] = par->line_index; + args->args[2] = par->active_low; + args->nargs = 3; + return true; + } + + return false; +} + struct acpi_gpio_lookup { struct acpi_gpio_info info; int index; @@ -372,8 +407,12 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, memset(&args, 0, sizeof(args)); ret = acpi_dev_get_property_reference(adev, propname, NULL, index, &args); - if (ret) - return ERR_PTR(ret); + if (ret) { + bool found = acpi_get_driver_gpio_data(adev, propname, + index, &args); + if (!found) + return ERR_PTR(ret); + } /* * The property was found and resolved so need to diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a361f43b197..7d1ce40e201 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -345,6 +345,8 @@ struct acpi_device_data { const union acpi_object *of_compatible; }; +struct acpi_gpio_mapping; + /* Device */ struct acpi_device { int device_type; @@ -366,6 +368,7 @@ struct acpi_device { struct acpi_scan_handler *handler; struct acpi_hotplug_context *hp; struct acpi_driver *driver; + const struct acpi_gpio_mapping *driver_gpios; void *driver_data; struct device dev; unsigned int physical_node_count; diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 5b8802216a9..0902426c452 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -673,6 +673,36 @@ do { \ #endif #endif +struct acpi_gpio_params { + unsigned int crs_entry_index; + unsigned int line_index; + bool active_low; +}; + +struct acpi_gpio_mapping { + const char *name; + const struct acpi_gpio_params *data; + unsigned int size; +}; + +#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) +int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios); + +static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) +{ + if (adev) + adev->driver_gpios = NULL; +} +#else +static inline int acpi_dev_add_driver_gpios(struct acpi_device *adev, + const struct acpi_gpio_mapping *gpios) +{ + return -ENXIO; +} +static inline void acpi_dev_remove_driver_gpios(struct acpi_device *adev) {} +#endif + /* Device properties */ #define MAX_ACPI_REFERENCE_ARGS 8 -- cgit v1.2.3-70-g09d2 From 60ba032ed76e851d30d4fa514847285252147d07 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 5 Nov 2014 00:29:07 +0100 Subject: ACPI / property: Drop size_prop from acpi_dev_get_property_reference() The size_prop argument of the recently added function acpi_dev_get_property_reference() is not used by the only current caller of that function and is very unlikely to be used at any time going forward. Namely, for a property whose value is a list of items each containing a references to a device object possibly accompanied by some integers, the number of items in the list can always be computed as the number of elements of type ACPI_TYPE_LOCAL_REFERENCE in the property package. Thus it should never be necessary to provide an additional "cells" property with a value equal to the number of items in that list. It also should never be necessary to provide a "cells" property specifying how many integers are supposed to be following each reference. For this reason, drop the size_prop argument from acpi_dev_get_property_reference() and update its caller accordingly. Link: http://marc.info/?l=linux-kernel&m=141511255610556&w=2 Suggested-by: Grant Likely Acked-by: Grant Likely Acked-by: Mika Westerberg Tested-by: Mika Westerberg Signed-off-by: Rafael J. Wysocki --- drivers/acpi/property.c | 62 ++++++++++++--------------------------------- drivers/gpio/gpiolib-acpi.c | 2 +- include/linux/acpi.h | 4 +-- 3 files changed, 19 insertions(+), 49 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 27add91bc27..0d083736e25 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -273,25 +273,21 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); * acpi_dev_get_property_reference - returns handle to the referenced object * @adev: ACPI device to get property * @name: Name of the property - * @size_prop: Name of the "size" property in referenced object * @index: Index of the reference to return * @args: Location to store the returned reference with optional arguments * * Find property with @name, verifify that it is a package containing at least * one object reference and if so, store the ACPI device object pointer to the - * target object in @args->adev. + * target object in @args->adev. If the reference includes arguments, store + * them in the @args->args[] array. * - * If the reference includes arguments (@size_prop is not %NULL) follow the - * reference and check whether or not there is an integer property @size_prop - * under the target object and if so, whether or not its value matches the - * number of arguments that follow the reference. If there's more than one - * reference in the property value package, @index is used to select the one to - * return. + * If there's more than one reference in the property value package, @index is + * used to select the one to return. * * Return: %0 on success, negative error code on failure. */ -int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, - const char *size_prop, size_t index, +int acpi_dev_get_property_reference(struct acpi_device *adev, + const char *name, size_t index, struct acpi_reference_args *args) { const union acpi_object *element, *end; @@ -308,7 +304,7 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, * return that reference then. */ if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) { - if (size_prop || index) + if (index) return -EINVAL; ret = acpi_bus_get_device(obj->reference.handle, &device); @@ -348,42 +344,16 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, element++; nargs = 0; - if (size_prop) { - const union acpi_object *prop; - - /* - * Find out how many arguments the refenced object - * expects by reading its size_prop property. - */ - ret = acpi_dev_get_property(device, size_prop, - ACPI_TYPE_INTEGER, &prop); - if (ret) - return ret; - - nargs = prop->integer.value; - if (nargs > MAX_ACPI_REFERENCE_ARGS - || element + nargs > end) - return -EPROTO; + /* assume following integer elements are all args */ + for (i = 0; element + i < end; i++) { + int type = element[i].type; - /* - * Skip to the start of the arguments and verify - * that they all are in fact integers. - */ - for (i = 0; i < nargs; i++) - if (element[i].type != ACPI_TYPE_INTEGER) - return -EPROTO; - } else { - /* assume following integer elements are all args */ - for (i = 0; element + i < end; i++) { - int type = element[i].type; - - if (type == ACPI_TYPE_INTEGER) - nargs++; - else if (type == ACPI_TYPE_LOCAL_REFERENCE) - break; - else - return -EPROTO; - } + if (type == ACPI_TYPE_INTEGER) + nargs++; + else if (type == ACPI_TYPE_LOCAL_REFERENCE) + break; + else + return -EPROTO; } if (idx++ == index) { diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 5a4d061e787..ba98bb59a58 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -405,7 +405,7 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); memset(&args, 0, sizeof(args)); - ret = acpi_dev_get_property_reference(adev, propname, NULL, + ret = acpi_dev_get_property_reference(adev, propname, index, &args); if (ret) { bool found = acpi_get_driver_gpio_data(adev, propname, diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 0902426c452..10f2ed95645 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -718,8 +718,8 @@ int acpi_dev_get_property(struct acpi_device *adev, const char *name, int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, acpi_object_type type, const union acpi_object **obj); -int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, - const char *cells_name, size_t index, +int acpi_dev_get_property_reference(struct acpi_device *adev, + const char *name, size_t index, struct acpi_reference_args *args); int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, -- cgit v1.2.3-70-g09d2 From 6ed23b806e73bdd5b17722df507b0f4570c606b6 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Dec 2014 00:34:11 +0100 Subject: PM: Merge the SET*_RUNTIME_PM_OPS() macros The SET_PM_RUNTIME_PM_OPS() and SET_RUNTIME_PM_OPS() macros are identical except that one of them is not empty for CONFIG_PM set, while the other one is not empty for CONFIG_PM_RUNTIME set, respectively. However, after commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is selected) PM_RUNTIME is always set if PM is set, so one of these macros is now redundant. For this reason, replace SET_PM_RUNTIME_PM_OPS() with SET_RUNTIME_PM_OPS() everywhere and redefine the SET_PM_RUNTIME_PM_OPS symbol as SET_RUNTIME_PM_OPS in case new code is starting to use the macro being removed here. Reviewed-by: Ulf Hansson Acked-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki --- drivers/amba/bus.c | 2 +- drivers/dma/ste_dma40.c | 2 +- drivers/gpio/gpio-zynq.c | 2 +- drivers/i2c/busses/i2c-hix5hd2.c | 2 +- drivers/i2c/busses/i2c-nomadik.c | 2 +- drivers/mmc/host/mmci.c | 2 +- drivers/mmc/host/sh_mobile_sdhi.c | 2 +- drivers/mmc/host/tmio_mmc.c | 2 +- drivers/spi/spi-pl022.c | 2 +- include/linux/pm.h | 11 ++--------- 10 files changed, 11 insertions(+), 18 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 47bbdc1b5be..973a3332a85 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -124,7 +124,7 @@ static const struct dev_pm_ops amba_pm = { .thaw = pm_generic_thaw, .poweroff = pm_generic_poweroff, .restore = pm_generic_restore, - SET_PM_RUNTIME_PM_OPS( + SET_RUNTIME_PM_OPS( amba_pm_runtime_suspend, amba_pm_runtime_resume, NULL diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 5fe59335e24..d9ca3e32d74 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -3051,7 +3051,7 @@ static int dma40_runtime_resume(struct device *dev) static const struct dev_pm_ops dma40_pm_ops = { SET_LATE_SYSTEM_SLEEP_PM_OPS(dma40_suspend, dma40_resume) - SET_PM_RUNTIME_PM_OPS(dma40_runtime_suspend, + SET_RUNTIME_PM_OPS(dma40_runtime_suspend, dma40_runtime_resume, NULL) }; diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 74cd480bf8d..184c4b1b255 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -578,7 +578,7 @@ static void zynq_gpio_free(struct gpio_chip *chip, unsigned offset) static const struct dev_pm_ops zynq_gpio_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(zynq_gpio_suspend, zynq_gpio_resume) - SET_PM_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, + SET_RUNTIME_PM_OPS(zynq_gpio_runtime_suspend, zynq_gpio_runtime_resume, NULL) }; diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index 9490d0f4255..8fe78d08e01 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -528,7 +528,7 @@ static int hix5hd2_i2c_runtime_resume(struct device *dev) #endif static const struct dev_pm_ops hix5hd2_i2c_pm_ops = { - SET_PM_RUNTIME_PM_OPS(hix5hd2_i2c_runtime_suspend, + SET_RUNTIME_PM_OPS(hix5hd2_i2c_runtime_suspend, hix5hd2_i2c_runtime_resume, NULL) }; diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 9ad038d223c..97998946c4f 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -932,7 +932,7 @@ static int nmk_i2c_runtime_resume(struct device *dev) static const struct dev_pm_ops nmk_i2c_pm = { SET_LATE_SYSTEM_SLEEP_PM_OPS(nmk_i2c_suspend_late, nmk_i2c_resume_early) - SET_PM_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, + SET_RUNTIME_PM_OPS(nmk_i2c_runtime_suspend, nmk_i2c_runtime_resume, NULL) }; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 43af791e2e4..184ea59afa7 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1843,7 +1843,7 @@ static int mmci_runtime_resume(struct device *dev) static const struct dev_pm_ops mmci_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL) + SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL) }; static struct amba_id mmci_ids[] = { diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c index a2e81a1ea6a..00c8ebdf8ec 100644 --- a/drivers/mmc/host/sh_mobile_sdhi.c +++ b/drivers/mmc/host/sh_mobile_sdhi.c @@ -375,7 +375,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev) static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) - SET_PM_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, + SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, tmio_mmc_host_runtime_resume, NULL) }; diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 659028ddb8b..2616fdfdbbe 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c @@ -135,7 +135,7 @@ static int tmio_mmc_remove(struct platform_device *pdev) static const struct dev_pm_ops tmio_mmc_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_suspend, tmio_mmc_resume) - SET_PM_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, + SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend, tmio_mmc_host_runtime_resume, NULL) }; diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index fc2dd844160..89ca162801d 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2377,7 +2377,7 @@ static int pl022_runtime_resume(struct device *dev) static const struct dev_pm_ops pl022_dev_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pl022_suspend, pl022_resume) - SET_PM_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) + SET_RUNTIME_PM_OPS(pl022_runtime_suspend, pl022_runtime_resume, NULL) }; static struct vendor_data vendor_arm = { diff --git a/include/linux/pm.h b/include/linux/pm.h index 53b56cf5db3..1dc338f6d4a 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -342,7 +342,7 @@ struct dev_pm_ops { #define SET_LATE_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) #endif -#ifdef CONFIG_PM_RUNTIME +#ifdef CONFIG_PM #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ .runtime_suspend = suspend_fn, \ .runtime_resume = resume_fn, \ @@ -351,14 +351,7 @@ struct dev_pm_ops { #define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) #endif -#ifdef CONFIG_PM -#define SET_PM_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \ - .runtime_suspend = suspend_fn, \ - .runtime_resume = resume_fn, \ - .runtime_idle = idle_fn, -#else -#define SET_PM_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) -#endif +#define SET_PM_RUNTIME_PM_OPS SET_RUNTIME_PM_OPS /* * Use this if you want to use the same suspend and resume callbacks for suspend -- cgit v1.2.3-70-g09d2 From ecb2312fa3c1f9792bf8a81c21ea4e011f4a2a90 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 4 Dec 2014 01:03:40 +0100 Subject: gpio / PM: Replace CONFIG_PM_RUNTIME with CONFIG_PM After commit b2b49ccbdd54 (PM: Kconfig: Set PM_RUNTIME if PM_SLEEP is selected) PM_RUNTIME is always set if PM is set, so #ifdef blocks depending on CONFIG_PM_RUNTIME may now be changed to depend on CONFIG_PM. Replace CONFIG_PM_RUNTIME with CONFIG_PM in drivers/gpio/gpio-omap.c. Signed-off-by: Rafael J. Wysocki Acked-by: Alexandre Courbot Acked-by: Javier Martinez Canillas Reviewed-by: Linus Walleij --- drivers/gpio/gpio-omap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpio') diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 415682f6921..3d6b445665a 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -1259,7 +1259,7 @@ static int omap_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_OMAP2PLUS -#if defined(CONFIG_PM_RUNTIME) +#if defined(CONFIG_PM) static void omap_gpio_restore_context(struct gpio_bank *bank); static int omap_gpio_runtime_suspend(struct device *dev) @@ -1440,7 +1440,7 @@ static int omap_gpio_runtime_resume(struct device *dev) return 0; } -#endif /* CONFIG_PM_RUNTIME */ +#endif /* CONFIG_PM */ void omap2_gpio_prepare_for_idle(int pwr_mode) { @@ -1468,7 +1468,7 @@ void omap2_gpio_resume_after_idle(void) } } -#if defined(CONFIG_PM_RUNTIME) +#if defined(CONFIG_PM) static void omap_gpio_init_context(struct gpio_bank *p) { struct omap_gpio_reg_offs *regs = p->regs; @@ -1525,7 +1525,7 @@ static void omap_gpio_restore_context(struct gpio_bank *bank) writel_relaxed(bank->context.irqenable2, bank->base + bank->regs->irqenable2); } -#endif /* CONFIG_PM_RUNTIME */ +#endif /* CONFIG_PM */ #else #define omap_gpio_runtime_suspend NULL #define omap_gpio_runtime_resume NULL -- cgit v1.2.3-70-g09d2