summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBraden Kell <bradenkell@google.com>2017-07-14 17:27:07 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-07-14 17:27:07 +0000
commit803e2d8a0e746e017ecb5791bca7915b57b65bf4 (patch)
treee3a186cd2af52d198027ea49629898fd8ca95314
parent2d57130f9bea7e2fe14fb0bd933ab8784e3a02ae (diff)
parent4cdad48d03043c5035c3ea5171a8e285887ae6f4 (diff)
downloadpi-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.c66
-rw-r--r--drivers/pinctrl/android-things/devicetree.c40
-rw-r--r--drivers/pinctrl/android-things/platform_devices.c99
-rw-r--r--drivers/pinctrl/android-things/platform_devices.h44
-rw-r--r--drivers/pinctrl/android-things/runtimepinconfig.h14
-rw-r--r--drivers/pinctrl/android-things/sysfs.c27
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;
+ }
}
}