diff --git a/drivers/gpio/gpio-sam.c b/drivers/gpio/gpio-sam.c index 62cea48..4d59058 100644 --- a/drivers/gpio/gpio-sam.c +++ b/drivers/gpio/gpio-sam.c @@ -25,6 +25,8 @@ #include #include +#include "gpiolib.h" + /* gpio status/configuration */ #define SAM_GPIO_NEG_EDGE (1 << 8) #define SAM_GPIO_NEG_EDGE_EN (1 << 7) @@ -166,14 +168,7 @@ static void sam_gpio_setup(struct sam_gpio *sam) chip->dev = sam->dev; chip->label = dev_name(sam->dev); - /* - * Setting the owner results in the module being locked - * into the kernel if gpio pins are auto-exported. - * Don't set the gpio chip owner until we find a better - * solution. - * - * chip->owner = THIS_MODULE; - */ + chip->owner = THIS_MODULE; chip->direction_input = sam_gpio_direction_input; chip->get = sam_gpio_get; chip->direction_output = sam_gpio_direction_output; @@ -564,10 +559,9 @@ static int sam_gpio_unexport(struct sam_gpio *sam) /* un-export all auto-exported pins */ for (i = 0; i < sam->gpio_count; i++) { - if (sam->export_flags[i] & GPIOF_EXPORT) { - gpio_unexport(i + sam->gpio.base); - gpio_free(i + sam->gpio.base); - } + struct gpio_desc *desc = gpiochip_get_desc(&sam->gpio, i); + if (sam->export_flags[i] & GPIOF_EXPORT) + gpiochip_free_own_desc(desc); } return 0; } @@ -582,11 +576,32 @@ static int sam_gpio_export(struct sam_gpio *sam) /* auto-export pins as requested */ for (i = 0; i < sam->gpio_count; i++) { + enum of_gpio_flags flags = sam->export_flags[i]; + struct gpio_desc *desc = gpiochip_get_desc(&sam->gpio, i); + /* request and initialize exported pins */ - if (sam->export_flags[i] & GPIOF_EXPORT) { - ret = gpio_request_one(i + sam->gpio.base, - sam->export_flags[i], - sam->names[i]); + if (flags & GPIOF_EXPORT) { + ret = gpiod_sysfs_set_active_low(desc, + flags & GPIOF_ACTIVE_LOW); + if (ret) + goto error; + + ret = gpiochip_request_own_desc(desc, "sam-export"); + if (ret) + goto error; + + if (flags & GPIOF_DIR_IN) { + ret = gpiod_direction_input(desc); + if (ret) + goto error; + } else { + ret = gpiod_direction_output(desc, + flags & GPIOF_OUT_INIT_HIGH); + if (ret) + goto error; + } + ret = gpiod_export(desc, + flags & GPIOF_EXPORT_CHANGEABLE); if (ret) goto error; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 61de1ef..f011834 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1711,6 +1711,7 @@ int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label) return __gpiod_request(desc, label); } +EXPORT_SYMBOL(gpiochip_request_own_desc); /** * gpiochip_free_own_desc - Free GPIO requested by the chip driver @@ -1724,6 +1725,7 @@ void gpiochip_free_own_desc(struct gpio_desc *desc) if (desc) __gpiod_free(desc); } +EXPORT_SYMBOL(gpiochip_free_own_desc); /* Drivers MUST set GPIO direction before making get/set calls. In * some cases this is done in early boot, before IRQs are enabled.