diff options
author | Braden Kell <bradenkell@google.com> | 2017-07-14 17:27:07 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-07-14 17:27:07 +0000 |
commit | 803e2d8a0e746e017ecb5791bca7915b57b65bf4 (patch) | |
tree | e3a186cd2af52d198027ea49629898fd8ca95314 | |
parent | 2d57130f9bea7e2fe14fb0bd933ab8784e3a02ae (diff) | |
parent | 4cdad48d03043c5035c3ea5171a8e285887ae6f4 (diff) | |
download | pi-v4.4-803e2d8a0e746e017ecb5791bca7915b57b65bf4.tar.gz |
PIO: Uncouple pin groups from pin functions
am: 4cdad48d03
Change-Id: I44417329cc71f7ffc09811508e9d4412652a9bc9
-rw-r--r-- | drivers/pinctrl/android-things/devices.c | 66 | ||||
-rw-r--r-- | drivers/pinctrl/android-things/devicetree.c | 40 | ||||
-rw-r--r-- | drivers/pinctrl/android-things/platform_devices.c | 99 | ||||
-rw-r--r-- | drivers/pinctrl/android-things/platform_devices.h | 44 | ||||
-rw-r--r-- | drivers/pinctrl/android-things/runtimepinconfig.h | 14 | ||||
-rw-r--r-- | drivers/pinctrl/android-things/sysfs.c | 27 |
6 files changed, 146 insertions, 144 deletions
diff --git a/drivers/pinctrl/android-things/devices.c b/drivers/pinctrl/android-things/devices.c index 6ba8905ce1c8..1ec2c34edb84 100644 --- a/drivers/pinctrl/android-things/devices.c +++ b/drivers/pinctrl/android-things/devices.c @@ -275,7 +275,7 @@ static int register_device_and_aux(struct bcm_device *dev) /* Restore the device's default pin configuration and register it. */ static inline int register_default_device(struct bcm_device *dev) { - int ret = set_device_config(dev, NULL); + int ret = set_device_default_config(dev); if (ret) return ret; @@ -410,10 +410,9 @@ int platform_devices_init(struct class *class) unregister_device_and_aux(dev, bdev); } - if ((ret = expand_property(bdev, PROP_PULL, 0))) + if ((ret = expand_property(bdev, PROP_PULL, false))) goto err_init_prop; - if ((ret = expand_property(bdev, PROP_FUNC, - bdev->pin_groups[0].function))) + if ((ret = expand_property(bdev, PROP_FUNC, true))) goto err_init_prop; /* @@ -426,7 +425,7 @@ int platform_devices_init(struct class *class) * to be registered if we mess up. */ if (bdev->init_unreg) { - if ((ret = set_device_config(bdev, NULL))) + if ((ret = set_device_default_config(bdev))) goto err_init_prop; } } @@ -659,28 +658,25 @@ static inline int set_function_gpio(struct pin_device *dev) /* Replace a pin used by a device and register a pin device for the old pin. */ static inline int replace_pin(struct bcm_device *bcm_dev, - struct pin_group *group, u32 pin) + struct pin_function *pin) { struct pin_device *pin_dev; int ret; __be32 *pin_prop; __be32 *function; - u32 pin_index; u32 old_pin; - pin_index = pin - group->base; pin_prop = find_pin_property(bcm_dev->node.of_node, PROP_PINS, - pin_index); - + pin->index); if (!pin_prop) { pr_err(TAG "unable to find pin index %d in %s\n", - pin_index, bcm_dev->name); + pin->index, bcm_dev->name); return -EINVAL; } old_pin = be32_to_cpup(pin_prop); - *pin_prop = cpu_to_be32p(&pin); + *pin_prop = cpu_to_be32p(&pin->pin); if (!(pin_dev = get_pin_device_by_pin(old_pin))) { /* @@ -693,14 +689,14 @@ static inline int replace_pin(struct bcm_device *bcm_dev, /* Set the pin's function property in the device tree. */ function = find_pin_property(bcm_dev->node.of_node, PROP_FUNC, - pin_index); + pin->index); if (!function) { pr_err(TAG "unable to find pin function index %d in %s\n", - pin_index, bcm_dev->name); + pin->index, bcm_dev->name); return -EINVAL; } - *function = cpu_to_be32p(&group->function); + *function = cpu_to_be32p(&pin->function); return 0; } @@ -713,7 +709,7 @@ static inline int replace_pin(struct bcm_device *bcm_dev, */ static inline int __set_function(struct pin_device *dev, struct bcm_device *bcm_dev, - struct pin_group *group) + struct pin_function *pin) { struct device *new_dev; struct device *exdev; @@ -723,7 +719,7 @@ static inline int __set_function(struct pin_device *dev, int has_pin; int ret = 0; - if (!bcm_dev->node.path) + if (!pin) return set_function_gpio(dev); if (!bcm_dev->node.of_node) { @@ -743,19 +739,8 @@ static inline int __set_function(struct pin_device *dev, /* Unregister this device so we can change its pins. */ unregister_device_and_maybe_aux(new_dev, bcm_dev); - if (bcm_dev->use_default) { - /* - * By default, this device uses non-user pins. Rather than mix - * user and non-user pins, set this device to use all user pins - * as soon as it is requested. - */ - if ((ret = set_device_config(bcm_dev, group))) { - pr_err(TAG "unable to set config for %s\n", - bcm_dev->name); - return ret; - } - } else if (!has_pin) { - if ((ret = replace_pin(bcm_dev, group, dev->pin))) + if (!has_pin) { + if ((ret = replace_pin(bcm_dev, pin))) return ret; } @@ -810,31 +795,30 @@ static inline int __set_function(struct pin_device *dev, } int set_function(struct pin_device *dev, struct bcm_device *bcm_dev, - struct pin_group *group) + struct pin_function *pin) { int ret; mutex_lock(&sysfs_mutex); - ret = __set_function(dev, bcm_dev, group); + ret = __set_function(dev, bcm_dev, pin); mutex_unlock(&sysfs_mutex); return ret; } - /* - * Find a matching pin group and return this pin's index in the property + * Find a matching pin_function and return this pin's index in the property * list. */ -static inline u32 get_pin_property_index(struct bcm_device *dev, u32 pin) +static inline int get_pin_property_index(struct bcm_device *dev, u32 pin) { - struct pin_group *groups; - size_t i; + int i, j; - groups = dev->pin_groups; - for (i = 0 ; dev->pin_group_count; i++) { - if (pin_in_group(pin, groups[i].base, dev->pin_count)) - return pin - groups[i].base; + for (i = 0; i < dev->pin_count; i++) { + for (j = 0; j < dev->pin_groups; j++) { + if (dev->pins[i][j].pin == pin) + return i; + } } return -1; diff --git a/drivers/pinctrl/android-things/devicetree.c b/drivers/pinctrl/android-things/devicetree.c index f33f31662bf7..3c327c85d400 100644 --- a/drivers/pinctrl/android-things/devicetree.c +++ b/drivers/pinctrl/android-things/devicetree.c @@ -120,11 +120,14 @@ static inline void fill_value(__be32 *array, u32 value, int length) * * @dev: The device to check. * @prop_name: The string name of the property to check. - * @value: The new value to fill an expanded property with. + * @require: Whether or not to require an existing property with prop_name + * and at least length 1. This is for the function property which + * does not have a default value to use. In that case, duplicate + * the one existing value for each pin in the node. * * Returns 0 on success. */ -int expand_property(struct bcm_device *dev, const char *prop_name, u32 value) +int expand_property(struct bcm_device *dev, const char *prop_name, bool require) { struct of_changeset changeset; struct device_node *prop; @@ -135,6 +138,7 @@ int expand_property(struct bcm_device *dev, const char *prop_name, u32 value) int ret; unsigned long action; int i = 0; + u32 value; of_changeset_init(&changeset); @@ -164,6 +168,18 @@ int expand_property(struct bcm_device *dev, const char *prop_name, u32 value) */ of_node_put(prop); continue; + } else if (require && (!pull || pull_length < 1)) { + /* + * We require a property of at least length 1 in order + * to fill the rest of the entries. + */ + pr_err(TAG "%s[%d] doesn't have the required property %s\n", + dev->name, i - 1, prop_name); + goto err_prop; + } else if (require) { + value = be32_to_cpup(pull->value); + } else { + value = 0; } new_pull = create_property(prop_name, pins_length); @@ -225,27 +241,23 @@ struct device *find_device_by_node(struct device_node *node) } /* - * set_device_config() - Sets a device's device tree configuration. + * set_device_default_config() - Sets a device's device tree configuration to + * the default specified in platform_devices. * * @dev: The device to change. - * @group: The new pin group to set, or NULL for the default. * * Returns 0 on success. */ -int set_device_config(struct bcm_device *dev, struct pin_group *group) +int set_device_default_config(struct bcm_device *dev) { struct device_node *prop; struct property *pins, *function, *pull; __be32 *list; __be32 *flist = NULL; __be32 *plist = NULL; - u32 pin; int length; int i, j, total; - if (!group) - group = &dev->pin_groups[0]; - i = 0; j = 0; while ((prop = of_parse_phandle(dev->node.of_node, STATE_0, i++))) { @@ -273,15 +285,9 @@ int set_device_config(struct bcm_device *dev, struct pin_group *group) length /= sizeof(*list); total = j + length; - if (total > dev->pin_count) { - pr_warn(TAG "%s has %d pins, more than the %d we know about\n", - dev->name, total, dev->pin_count); - } - for ( ; j < total && j < dev->pin_count; j++) { - pin = group->base + j; - *list++ = cpu_to_be32p(&pin); - *flist++ = cpu_to_be32p(&group->function); + *list++ = cpu_to_be32p(&dev->pins[j]->pin); + *flist++ = cpu_to_be32p(&dev->pins[j]->function); *plist++ = cpu_to_be32p(&dev->pin_pull[j]); } diff --git a/drivers/pinctrl/android-things/platform_devices.c b/drivers/pinctrl/android-things/platform_devices.c index cfa04258709e..fbc9d8592e4c 100644 --- a/drivers/pinctrl/android-things/platform_devices.c +++ b/drivers/pinctrl/android-things/platform_devices.c @@ -40,14 +40,21 @@ struct bcm_device platform_devices[] = { .aux_dev = { .path = NULL }, .use_default = 0, .always_unreg_aux = 0, - .init_unreg = 0, + .init_unreg = 1, .pin_count = 5, .pin_pull = (u32 []) { NONE, NONE, NONE, NONE, NONE }, - .pin_group_count = 1, - .pin_groups = (struct pin_group []) { - { - .base = 7, - .function = ALT0 + .pin_groups = 1, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 7, .index = 0, .function = GPIO_OUT } + }, (struct pin_function []) { + { .pin = 8, .index = 1, .function = GPIO_OUT } + }, (struct pin_function []) { + { .pin = 9, .index = 2, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 10, .index = 3, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 11, .index = 4, .function = ALT0 } } }, .excl = NULL @@ -60,14 +67,14 @@ struct bcm_device platform_devices[] = { .init_unreg = 1, .pin_count = 2, .pin_pull = (u32 []) { NONE, NONE, }, - .pin_group_count = 2, - .pin_groups = (struct pin_group []) { - { - .base = 12, - .function = ALT0 - }, { - .base = 18, - .function = ALT5 + .pin_groups = 2, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 18, .index = 0, .function = ALT5 }, + { .pin = 12, .index = 0, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 13, .index = 1, .function = ALT0 }, + { .pin = 19, .index = 1, .function = ALT5 } } }, .excl = (struct bcm_device *[]) { @@ -83,11 +90,12 @@ struct bcm_device platform_devices[] = { .init_unreg = 1, .pin_count = 2, .pin_pull = (u32 []) { NONE, NONE }, - .pin_group_count = 1, - .pin_groups = (struct pin_group []) { - { - .base = 2, - .function = ALT0 + .pin_groups = 1, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 2, .index = 0, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 3, .index = 1, .function = ALT0 } } }, .excl = NULL @@ -100,14 +108,14 @@ struct bcm_device platform_devices[] = { .init_unreg = 0, .pin_count = 2, .pin_pull = (u32 []) { NONE, UP }, - .pin_group_count = 2, - .pin_groups = (struct pin_group []) { - { - .base = 32, - .function = ALT3 - }, { - .base = 14, - .function = ALT0 + .pin_groups = 2, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 32, .index = 0, .function = ALT3 }, + { .pin = 14, .index = 0, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 33, .index = 1, .function = ALT3 }, + { .pin = 15, .index = 1, .function = ALT0 } } }, .excl = NULL @@ -120,11 +128,12 @@ struct bcm_device platform_devices[] = { .init_unreg = 0, .pin_count = 2, .pin_pull = (u32 []) { NONE, UP }, - .pin_group_count = 1, - .pin_groups = (struct pin_group []) { - { - .base = 14, - .function = ALT5 + .pin_groups = 1, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 14, .index = 0, .function = ALT5 } + }, (struct pin_function []) { + { .pin = 15, .index = 1, .function = ALT5 } } }, .excl = NULL @@ -137,11 +146,16 @@ struct bcm_device platform_devices[] = { .init_unreg = 1, .pin_count = 4, .pin_pull = (u32 []) { NONE, NONE, NONE, NONE }, - .pin_group_count = 1, - .pin_groups = (struct pin_group []) { - { - .base = 18, - .function = ALT0 + .pin_groups = 1, + .pins = (struct pin_function *[]) { + (struct pin_function []) { + { .pin = 18, .index = 0, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 19, .index = 1, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 20, .index = 2, .function = ALT0 } + }, (struct pin_function []) { + { .pin = 21, .index = 3, .function = ALT0 } } }, .excl = (struct bcm_device *[]) { @@ -155,14 +169,9 @@ struct bcm_device platform_devices[] = { .use_default = 0, .always_unreg_aux = 0, .init_unreg = 0, - .pin_count = 26, - .pin_group_count = 1, - .pin_groups = (struct pin_group []) { - { - .base = 2, - .function = GPIO - } - }, + .pin_count = 0, + .pin_groups = 0, + .pins = NULL, .excl = NULL }, { .name = NULL diff --git a/drivers/pinctrl/android-things/platform_devices.h b/drivers/pinctrl/android-things/platform_devices.h index a8e6340de2f1..f698662ff8c5 100644 --- a/drivers/pinctrl/android-things/platform_devices.h +++ b/drivers/pinctrl/android-things/platform_devices.h @@ -36,7 +36,8 @@ struct node_path { /* Broadcom pin function numbers. See drivers/pinctrl/bcm/pinctrl-bcm2835.c */ enum bcm_fsel { - GPIO = 0, + GPIO_IN = 0, + GPIO_OUT = 1, ALT0 = 4, ALT1 = 5, ALT2 = 6, @@ -46,13 +47,17 @@ enum bcm_fsel { }; /* - * struct pin_group - Defines the starting pin and hardware-specific function - * number for a group of pins used by a peripheral. We assume that each group - * has the same function number and contains bcm_device.pin_count consecutive - * pins. + * struct pin_function - Defines the pin number and hardware-specific function + * number for a pin used by a device. We assume that devices may have different + * groups of pins that they can use and that mixing between groups is allowed, + * but no one pin can take on multiple functions for one device. We also assume + * that each group of pins for a device follows the same order of functions, + * and that this order is followed by pinctrl properties in the device tree. + * The index member here is used to specify the pin's place in its group. */ -struct pin_group { - u32 base; +struct pin_function { + u32 pin; + int index; enum bcm_fsel function; }; @@ -65,12 +70,12 @@ struct pin_group { * @aux_dev: A node_path containing the device tree node for this device's * auxiliary device. The auxiliary device may depend on this * device, or this device may depend on it. - * @use_default: Whether or not we should register this device on - * a default pin_group if nobody is using it. For example, - * uart0 on the Raspberry Pi 3 is also used for Bluetooth, - * so we need to register uart0 again when the user stops - * using it directly. pin_groups[0] is the default - * pin_group. + * @use_default: Whether or not we should register this device on a set + * of default pin_functions if nobody is using it. For + * example, uart0 on the Raspberry Pi 3 is also used For + * Bluetooth, so we need to register uart0 again when the + * user stops using it directly. bcm_device.pins[n][0] are + * the default pin_functions used. * @always_unreg_aux: Whether or not we should unregister the auxiliary device * whenever we unregister this device. This flag also * controls the order in which the devices get @@ -79,11 +84,14 @@ struct pin_group { * module. This is useful for mutually exclusive devices which all * may be registered at boot. * @pin_count: The number of pins used by this peripheral. + * @pin_groups: The number of pin groups that can be used by this device. * @pin_pull: Specifies default resistor values for this device. Only used * with use_default. - * @pin_group_count: The number of pin_groups available to this device and - * the length of the following array. - * @pin_groups: Array of pin_groups for this device. + * @pins: An array of arrays of pin_functions available to this device. + * The top-level array has bcm_device.pin_count entries, and each + * array in it has bcm_device.pin_groups entries. The first + * pin_functions in each array make up the default group for each + * device. * @excl: NULL-terminated array of bcm_devices that are mutually exclusive * with this device. Whenever we register this device, we must * first unregister every device in this array. For example, i2s @@ -98,9 +106,9 @@ struct bcm_device { int always_unreg_aux:1; int init_unreg:1; int pin_count; + int pin_groups; u32 *pin_pull; - int pin_group_count; - struct pin_group *pin_groups; + struct pin_function **pins; struct bcm_device **excl; }; diff --git a/drivers/pinctrl/android-things/runtimepinconfig.h b/drivers/pinctrl/android-things/runtimepinconfig.h index 3e61e87c9f86..8cdec46d2522 100644 --- a/drivers/pinctrl/android-things/runtimepinconfig.h +++ b/drivers/pinctrl/android-things/runtimepinconfig.h @@ -25,7 +25,7 @@ #define TAG "runtimepinconfig: " -struct pin_group; +struct pin_function; struct bcm_device; /* @@ -56,7 +56,7 @@ ssize_t resistor_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t buflen); int set_function(struct pin_device *dev, struct bcm_device *bcm_dev, - struct pin_group *group); + struct pin_function *pin); int set_resistor(struct pin_device *dev, u32 resistor); struct pin_device *track_pin_device(struct platform_device *dev); @@ -67,13 +67,9 @@ int pin_devices_init(void); int get_pin(struct device_node *node, u32 *pin); int device_has_pin(struct device_node *node, u32 pin); -int expand_property(struct bcm_device *dev, const char *prop_name, u32 value); +int expand_property(struct bcm_device *dev, const char *prop_name, + bool require); struct device *find_device_by_node(struct device_node *node); -int set_device_config(struct bcm_device *dev, struct pin_group *group); - -static inline int pin_in_group(int pin, int base, int count) -{ - return (pin >= base && pin < base + count); -} +int set_device_default_config(struct bcm_device *dev); #endif /* RUNTIMEPINCONFIG_H_ */ diff --git a/drivers/pinctrl/android-things/sysfs.c b/drivers/pinctrl/android-things/sysfs.c index eb264489d243..8602a47bea0e 100644 --- a/drivers/pinctrl/android-things/sysfs.c +++ b/drivers/pinctrl/android-things/sysfs.c @@ -23,16 +23,14 @@ /* * These functions are the sysfs interface. Parse the user input and match it to - * a peripheral device or resistor value. Use the pin number to determine the - * pin_group, if necessary. + * a pin on a peripheral device or a resistor value. */ ssize_t function_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t bufsize) { struct pin_device *pin_dev = dev_get_drvdata(dev); struct bcm_device *bcm_dev = NULL; - size_t i, namelen, inlen; - struct pin_group *group; + size_t i, j, namelen, inlen; int ret; for (inlen = 0; buf[inlen] != '\n' && inlen < bufsize; inlen++) @@ -54,18 +52,19 @@ ssize_t function_store(struct device *dev, struct device_attribute *attr, pr_warn(TAG "no matching platform device found on pin %d\n", pin_dev->pin); return -ENODEV; + } else if (bcm_dev->pin_count == 0) { + ret = set_function(pin_dev, bcm_dev, NULL); + return (ret) ? ret : bufsize; } - group = bcm_dev->pin_groups; - - /* Match the pin number to a pin group available to the device. */ - for (i = 0; i < bcm_dev->pin_group_count; i++) { - if (pin_in_group(pin_dev->pin, group[i].base, - bcm_dev->pin_count)) { - if ((ret = set_function(pin_dev, bcm_dev, &group[i]))) - pr_err(TAG "set function %s failed on pin %d\n", - bcm_dev->name, pin_dev->pin); - return (ret) ? ret : bufsize; + /* Loop over the possible pins for this device. */ + for (i = 0; i < bcm_dev->pin_count; i++) { + for (j = 0; j < bcm_dev->pin_groups; j++) { + if (bcm_dev->pins[i][j].pin == pin_dev->pin) { + ret = set_function(pin_dev, bcm_dev, + &bcm_dev->pins[i][j]); + return (ret) ? ret : bufsize; + } } } |