Commit dc80a271 authored by Linus Walleij's avatar Linus Walleij

Merge tag 'intel-gpio-v5.11-1' of...

Merge tag 'intel-gpio-v5.11-1' of gitolite.kernel.org:pub/scm/linux/kernel/git/andy/linux-gpio-intel into devel

intel-gpio for v5.11-1

* Refactor GPIO library to support bias and debounce ACPI settings

The following is an automated git shortlog grouped by driver:

gpiolib:
 -  acpi: Make Intel GPIO tree official for GPIO ACPI work
 -  acpi: Use BIT() macro to increase readability
 -  acpi: Convert pin_index to be u16
 -  acpi: Extract acpi_request_own_gpiod() helper
 -  acpi: Make acpi_gpio_to_gpiod_flags() usable for GpioInt()
 -  acpi: Set initial value for output pin based on bias and polarity
 -  acpi: Move acpi_gpio_to_gpiod_flags() upper in the code
 -  acpi: Move non-critical code outside of critical section
 -  acpi: Take into account debounce settings
 -  acpi: Use named item for enum gpiod_flags variable
 -  acpi: Respect bias settings for GpioInt() resource
 -  Introduce gpio_set_debounce_timeout() for internal use
 -  Extract gpio_set_config_with_argument_optional() helper
 -  move bias related code from gpio_set_config() to gpio_set_bias()
 -  Extract gpio_set_config_with_argument() for future use
 -  use proper API to pack pin configuration parameters
 -  add missed break statement
 -  Replace unsigned by unsigned int

Merge tag 'intel-pinctrl-v5.10-2' into HEAD:
 - Merge tag 'intel-pinctrl-v5.10-2' into HEAD

pinctrl:
 -  intel: Set default bias in case no particular value given
 -  intel: Fix 2 kOhm bias which is 833 Ohm
parents ad9a72f9 e709a7b5
......@@ -7480,6 +7480,7 @@ M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
L: linux-gpio@vger.kernel.org
L: linux-acpi@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/andy/linux-gpio-intel.git
F: Documentation/firmware-guide/acpi/gpio-properties.rst
F: drivers/gpio/gpiolib-acpi.c
F: drivers/gpio/gpiolib-acpi.h
......
......@@ -205,6 +205,67 @@ static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
acpi_gpiochip_request_irq(acpi_gpio, event);
}
static enum gpiod_flags
acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
{
/* GpioInt() implies input configuration */
if (agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
return GPIOD_IN;
switch (agpio->io_restriction) {
case ACPI_IO_RESTRICT_INPUT:
return GPIOD_IN;
case ACPI_IO_RESTRICT_OUTPUT:
/*
* ACPI GPIO resources don't contain an initial value for the
* GPIO. Therefore we deduce that value from the pull field
* and the polarity instead. If the pin is pulled up we assume
* default to be high, if it is pulled down we assume default
* to be low, otherwise we leave pin untouched. For active low
* polarity values will be switched. See also
* Documentation/firmware-guide/acpi/gpio-properties.rst.
*/
switch (agpio->pin_config) {
case ACPI_PIN_CONFIG_PULLUP:
return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH;
case ACPI_PIN_CONFIG_PULLDOWN:
return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
default:
break;
}
default:
break;
}
/*
* Assume that the BIOS has configured the direction and pull
* accordingly.
*/
return GPIOD_ASIS;
}
static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
struct acpi_resource_gpio *agpio,
unsigned int index,
const char *label)
{
int polarity = GPIO_ACTIVE_HIGH;
enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
unsigned int pin = agpio->pin_table[index];
struct gpio_desc *desc;
int ret;
desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags);
if (IS_ERR(desc))
return desc;
ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout);
if (ret)
gpiochip_free_own_desc(desc);
return ret ? ERR_PTR(ret) : desc;
}
static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
{
const char *controller, *pin_str;
......@@ -290,8 +351,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
if (!handler)
return AE_OK;
desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event",
GPIO_ACTIVE_HIGH, GPIOD_IN);
desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
if (IS_ERR(desc)) {
dev_err(chip->parent,
"Failed to request GPIO for pin 0x%04X, err %ld\n",
......@@ -526,39 +586,6 @@ static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
return false;
}
static enum gpiod_flags
acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
{
switch (agpio->io_restriction) {
case ACPI_IO_RESTRICT_INPUT:
return GPIOD_IN;
case ACPI_IO_RESTRICT_OUTPUT:
/*
* ACPI GPIO resources don't contain an initial value for the
* GPIO. Therefore we deduce that value from the pull field
* instead. If the pin is pulled up we assume default to be
* high, if it is pulled down we assume default to be low,
* otherwise we leave pin untouched.
*/
switch (agpio->pin_config) {
case ACPI_PIN_CONFIG_PULLUP:
return GPIOD_OUT_HIGH;
case ACPI_PIN_CONFIG_PULLDOWN:
return GPIOD_OUT_LOW;
default:
break;
}
default:
break;
}
/*
* Assume that the BIOS has configured the direction and pull
* accordingly.
*/
return GPIOD_ASIS;
}
static int
__acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
{
......@@ -633,7 +660,7 @@ int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
struct acpi_gpio_lookup {
struct acpi_gpio_info info;
int index;
int pin_index;
u16 pin_index;
bool active_low;
struct gpio_desc *desc;
int n;
......@@ -649,7 +676,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (!lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio;
bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
int pin_index;
u16 pin_index;
if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
lookup->index++;
......@@ -664,6 +691,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]);
lookup->info.pin_config = agpio->pin_config;
lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint;
/*
......@@ -674,13 +702,13 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
* - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
*/
if (lookup->info.gpioint) {
lookup->info.flags = GPIOD_IN;
lookup->info.polarity = agpio->polarity;
lookup->info.triggering = agpio->triggering;
} else {
lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio);
lookup->info.polarity = lookup->active_low;
}
lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio, lookup->info.polarity);
}
return 1;
......@@ -794,7 +822,7 @@ static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
if (ret)
return ERR_PTR(ret);
dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n",
dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %u %u\n",
dev_name(&lookup.info.adev->dev), lookup.index,
lookup.pin_index, lookup.active_low);
} else {
......@@ -942,6 +970,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
if (info.gpioint && idx++ == index) {
unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
enum gpiod_flags dflags = GPIOD_ASIS;
char label[32];
int irq;
......@@ -952,11 +981,18 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
if (irq < 0)
return irq;
acpi_gpio_update_gpiod_flags(&dflags, &info);
acpi_gpio_update_gpiod_lookup_flags(&lflags, &info);
snprintf(label, sizeof(label), "GpioInt() %d", index);
ret = gpiod_configure_flags(desc, label, lflags, info.flags);
ret = gpiod_configure_flags(desc, label, lflags, dflags);
if (ret < 0)
return ret;
ret = gpio_set_debounce_timeout(desc, info.debounce);
if (ret)
return ret;
irq_flags = acpi_dev_get_irq_type(info.triggering,
info.polarity);
......@@ -982,7 +1018,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
struct gpio_chip *chip = achip->chip;
struct acpi_resource_gpio *agpio;
struct acpi_resource *ares;
int pin_index = (int)address;
u16 pin_index = address;
acpi_status status;
int length;
int i;
......@@ -1005,7 +1041,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
return AE_BAD_PARAMETER;
}
length = min(agpio->pin_table_length, (u16)(pin_index + bits));
length = min_t(u16, agpio->pin_table_length, pin_index + bits);
for (i = pin_index; i < length; ++i) {
int pin = agpio->pin_table[i];
struct acpi_gpio_connection *conn;
......@@ -1042,23 +1078,18 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
}
if (!found) {
enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio);
const char *label = "ACPI:OpRegion";
desc = gpiochip_request_own_desc(chip, pin, label,
GPIO_ACTIVE_HIGH,
flags);
desc = acpi_request_own_gpiod(chip, agpio, i, "ACPI:OpRegion");
if (IS_ERR(desc)) {
status = AE_ERROR;
mutex_unlock(&achip->conn_lock);
status = AE_ERROR;
goto out;
}
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn) {
status = AE_NO_MEMORY;
gpiochip_free_own_desc(desc);
mutex_unlock(&achip->conn_lock);
status = AE_NO_MEMORY;
goto out;
}
......@@ -1070,8 +1101,7 @@ acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
mutex_unlock(&achip->conn_lock);
if (function == ACPI_WRITE)
gpiod_set_raw_value_cansleep(desc,
!!((1 << i) & *value));
gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i)));
else
*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
}
......@@ -1132,7 +1162,7 @@ acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
int ret;
*lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
*dflags = 0;
*dflags = GPIOD_ASIS;
*name = NULL;
ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
......
......@@ -18,6 +18,7 @@ struct acpi_device;
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
* @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
......@@ -27,6 +28,7 @@ struct acpi_gpio_info {
int pin_config;
int polarity;
int triggering;
unsigned int debounce;
unsigned int quirks;
};
......
......@@ -211,7 +211,7 @@ static int gpiochip_find_base(int ngpio)
int gpiod_get_direction(struct gpio_desc *desc)
{
struct gpio_chip *gc;
unsigned offset;
unsigned int offset;
int ret;
gc = gpiod_to_chip(desc);
......@@ -1333,7 +1333,7 @@ void gpiochip_irq_domain_deactivate(struct irq_domain *domain,
}
EXPORT_SYMBOL_GPL(gpiochip_irq_domain_deactivate);
static int gpiochip_to_irq(struct gpio_chip *gc, unsigned offset)
static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
{
struct irq_domain *domain = gc->irq.domain;
......@@ -1635,7 +1635,7 @@ static inline void gpiochip_irqchip_free_valid_mask(struct gpio_chip *gc)
* @gc: the gpiochip owning the GPIO
* @offset: the offset of the GPIO to request for GPIO function
*/
int gpiochip_generic_request(struct gpio_chip *gc, unsigned offset)
int gpiochip_generic_request(struct gpio_chip *gc, unsigned int offset)
{
#ifdef CONFIG_PINCTRL
if (list_empty(&gc->gpiodev->pin_ranges))
......@@ -1651,7 +1651,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_request);
* @gc: the gpiochip to request the gpio function for
* @offset: the offset of the GPIO to free from GPIO function
*/
void gpiochip_generic_free(struct gpio_chip *gc, unsigned offset)
void gpiochip_generic_free(struct gpio_chip *gc, unsigned int offset)
{
pinctrl_gpio_free(gc->gpiodev->base + offset);
}
......@@ -1663,7 +1663,7 @@ EXPORT_SYMBOL_GPL(gpiochip_generic_free);
* @offset: the offset of the GPIO to apply the configuration
* @config: the configuration to be applied
*/
int gpiochip_generic_config(struct gpio_chip *gc, unsigned offset,
int gpiochip_generic_config(struct gpio_chip *gc, unsigned int offset,
unsigned long config)
{
return pinctrl_gpio_set_config(gc->gpiodev->base + offset, config);
......@@ -1993,7 +1993,7 @@ void gpiod_free(struct gpio_desc *desc)
* help with diagnostics, and knowing that the signal is used as a GPIO
* can help avoid accidentally multiplexing it to another controller.
*/
const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned offset)
const char *gpiochip_is_requested(struct gpio_chip *gc, unsigned int offset)
{
struct gpio_desc *desc;
......@@ -2093,30 +2093,49 @@ static int gpio_do_set_config(struct gpio_chip *gc, unsigned int offset,
return gc->set_config(gc, offset, config);
}
static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
static int gpio_set_config_with_argument(struct gpio_desc *desc,
enum pin_config_param mode,
u32 argument)
{
struct gpio_chip *gc = desc->gdev->chip;
unsigned long config;
unsigned arg;
config = pinconf_to_config_packed(mode, argument);
return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
}
static int gpio_set_config_with_argument_optional(struct gpio_desc *desc,
enum pin_config_param mode,
u32 argument)
{
struct device *dev = &desc->gdev->dev;
int gpio = gpio_chip_hwgpio(desc);
int ret;
ret = gpio_set_config_with_argument(desc, mode, argument);
if (ret != -ENOTSUPP)
return ret;
switch (mode) {
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
arg = 1;
case PIN_CONFIG_PERSIST_STATE:
dev_dbg(dev, "Persistence not supported for GPIO %d\n", gpio);
break;
default:
arg = 0;
break;
}
config = PIN_CONF_PACKED(mode, arg);
return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
return 0;
}
static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
{
return gpio_set_config_with_argument(desc, mode, 0);
}
static int gpio_set_bias(struct gpio_desc *desc)
{
enum pin_config_param bias;
int ret;
unsigned int arg;
if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
bias = PIN_CONFIG_BIAS_DISABLE;
......@@ -2127,11 +2146,25 @@ static int gpio_set_bias(struct gpio_desc *desc)
else
return 0;
ret = gpio_set_config(desc, bias);
if (ret != -ENOTSUPP)
return ret;
switch (bias) {
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
arg = 1;
break;
return 0;
default:
arg = 0;
break;
}
return gpio_set_config_with_argument_optional(desc, bias, arg);
}
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce)
{
return gpio_set_config_with_argument_optional(desc,
PIN_CONFIG_INPUT_DEBOUNCE,
debounce);
}
/**
......@@ -2353,7 +2386,7 @@ EXPORT_SYMBOL_GPL(gpiod_set_config);
* 0 on success, %-ENOTSUPP if the controller doesn't support setting the
* debounce time.
*/
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce)
{
unsigned long config;
......@@ -2372,11 +2405,6 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce);
*/
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
{
struct gpio_chip *gc;
unsigned long packed;
int gpio;
int rc;
VALIDATE_DESC(desc);
/*
* Handle FLAG_TRANSITORY first, enabling queries to gpiolib for
......@@ -2385,21 +2413,9 @@ int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
assign_bit(FLAG_TRANSITORY, &desc->flags, transitory);
/* If the driver supports it, set the persistence state now */
gc = desc->gdev->chip;
if (!gc->set_config)
return 0;
packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE,
!transitory);
gpio = gpio_chip_hwgpio(desc);
rc = gpio_do_set_config(gc, gpio, packed);
if (rc == -ENOTSUPP) {
dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO %d\n",
gpio);
return 0;
}
return rc;
return gpio_set_config_with_argument_optional(desc,
PIN_CONFIG_PERSIST_STATE,
!transitory);
}
EXPORT_SYMBOL_GPL(gpiod_set_transitory);
......
......@@ -134,6 +134,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags);
int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags);
......
......@@ -158,7 +158,7 @@ int gpiod_set_raw_array_value_cansleep(unsigned int array_size,
unsigned long *value_bitmap);
int gpiod_set_config(struct gpio_desc *desc, unsigned long config);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce);
int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce);
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory);
void gpiod_toggle_active_low(struct gpio_desc *desc);
......@@ -481,7 +481,7 @@ static inline int gpiod_set_config(struct gpio_desc *desc, unsigned long config)
return -ENOSYS;
}
static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce)
static inline int gpiod_set_debounce(struct gpio_desc *desc, unsigned int debounce)
{
/* GPIO can never have been requested */
WARN_ON(desc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment