[PATCH v3] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge --- Applies to v3.17-rc4 v3: Removed superfluous whitespace v2: Removed #ifdef statements Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be "nxp,pca9532" +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + nxp,typecodes = <0x>; + nxp,statecodes = <0x>; + reg = <0x60>; + }; + + sd@20098000 { + wp-gpios = < 5 0>; + cd-gpios = < 4 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include #include #include +#include /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) >> 3) @@ -442,6 +443,43 @@ exit: return err; } +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, "nxp,typecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].type = + (typecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32(np, "nxp,statecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].state = + (statecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32_array(np, "nxp,pwm", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, "nxp,psc", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->psc[i] = psc[i]; + } + + pca9532_pdata->gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +487,9 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(>dev); + if (IS_ENABLED(CONFIG_OF) && !pca9532_pdata && client->dev.of_node) + pca9532_pdata = pca9532_parse_dt(>dev); + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] leds: Add DT support for leds-pca9532
On 09/09/2014 08:08 PM, Arnd Bergmann wrote: > Is this a full PWM controller? If it is, it would be better to also > provide a #pwm-cells property and register the device with the PWM > subsystem to allow arbitrary users. > > If the PWM is only really usable for LED, it's probably enough to > leave this used by the LED subsystem. Right, this PWM is really only intended for LED use (as already done w/o DT). Sending the updated patch. Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge --- Applies to v3.17-rc4 v2: Removed #ifdef statements Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be "nxp,pca9532" +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + nxp,typecodes = <0x>; + nxp,statecodes = <0x>; + reg = <0x60>; + }; + + sd@20098000 { + wp-gpios = < 5 0>; + cd-gpios = < 4 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include #include #include +#include /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) >> 3) @@ -442,6 +443,43 @@ exit: return err; } +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, "nxp,typecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].type = + (typecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32(np, "nxp,statecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].state = + (statecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32_array(np, "nxp,pwm", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, "nxp,psc", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->psc[i] = psc[i]; + } + + pca9532_pdata->gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +487,10 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(>dev); + + if (IS_ENABLED(CONFIG_OF) && !pca9532_pdata && client->dev.of_node) + pca9532_pdata = pca9532_parse_dt(>dev); + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v2] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge sti...@antcom.de --- Applies to v3.17-rc4 v2: Removed #ifdef statements Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be nxp,pca9532 +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = nxp,pca9532; + gpio-controller; + #gpio-cells = 2; + nxp,typecodes = 0x; + nxp,statecodes = 0x; + reg = 0x60; + }; + + sd@20098000 { + wp-gpios = pca9532 5 0; + cd-gpios = pca9532 4 0; + cd-inverted; + bus-width = 4; + status = okay; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include linux/workqueue.h #include linux/leds-pca9532.h #include linux/gpio.h +#include linux/of.h /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) 3) @@ -442,6 +443,43 @@ exit: return err; } +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev-of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, nxp,typecodes, typecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].type = + (typecodes (2 * i)) 0x3; + } + if (!of_property_read_u32(np, nxp,statecodes, statecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].state = + (statecodes (2 * i)) 0x3; + } + if (!of_property_read_u32_array(np, nxp,pwm, pwm[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, nxp,psc, psc[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-psc[i] = psc[i]; + } + + pca9532_pdata-gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +487,10 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(client-dev); + + if (IS_ENABLED(CONFIG_OF) !pca9532_pdata client-dev.of_node) + pca9532_pdata = pca9532_parse_dt(client-dev); + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] leds: Add DT support for leds-pca9532
On 09/09/2014 08:08 PM, Arnd Bergmann wrote: Is this a full PWM controller? If it is, it would be better to also provide a #pwm-cells property and register the device with the PWM subsystem to allow arbitrary users. If the PWM is only really usable for LED, it's probably enough to leave this used by the LED subsystem. Right, this PWM is really only intended for LED use (as already done w/o DT). Sending the updated patch. Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH v3] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge sti...@antcom.de --- Applies to v3.17-rc4 v3: Removed superfluous whitespace v2: Removed #ifdef statements Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be nxp,pca9532 +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = nxp,pca9532; + gpio-controller; + #gpio-cells = 2; + nxp,typecodes = 0x; + nxp,statecodes = 0x; + reg = 0x60; + }; + + sd@20098000 { + wp-gpios = pca9532 5 0; + cd-gpios = pca9532 4 0; + cd-inverted; + bus-width = 4; + status = okay; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include linux/workqueue.h #include linux/leds-pca9532.h #include linux/gpio.h +#include linux/of.h /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) 3) @@ -442,6 +443,43 @@ exit: return err; } +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev-of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, nxp,typecodes, typecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].type = + (typecodes (2 * i)) 0x3; + } + if (!of_property_read_u32(np, nxp,statecodes, statecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].state = + (statecodes (2 * i)) 0x3; + } + if (!of_property_read_u32_array(np, nxp,pwm, pwm[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, nxp,psc, psc[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-psc[i] = psc[i]; + } + + pca9532_pdata-gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +487,9 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(client-dev); + if (IS_ENABLED(CONFIG_OF) !pca9532_pdata client-dev.of_node) + pca9532_pdata = pca9532_parse_dt(client-dev); + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge --- Applies to v3.17-rc4 Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be "nxp,pca9532" +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = "nxp,pca9532"; + gpio-controller; + #gpio-cells = <2>; + nxp,typecodes = <0x>; + nxp,statecodes = <0x>; + reg = <0x60>; + }; + + sd@20098000 { + wp-gpios = < 5 0>; + cd-gpios = < 4 0>; + cd-inverted; + bus-width = <4>; + status = "okay"; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include #include #include +#include /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) >> 3) @@ -442,6 +443,45 @@ exit: return err; } +#ifdef CONFIG_OF +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev->of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, "nxp,typecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].type = + (typecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32(np, "nxp,statecodes", )) { + for (i = 0; i < 16; i++) + pca9532_pdata->leds[i].state = + (statecodes >> (2 * i)) & 0x3; + } + if (!of_property_read_u32_array(np, "nxp,pwm", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, "nxp,psc", [0], 2)) { + for (i = 0; i < 2; i++) + pca9532_pdata->psc[i] = psc[i]; + } + + pca9532_pdata->gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} +#endif + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +489,11 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(>dev); +#ifdef CONFIG_OF + if (!pca9532_pdata && client->dev.of_node) + pca9532_pdata = pca9532_parse_dt(>dev); +#endif + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] SPI: Fix error message
This patch fixes an error message typo ("not" missing). Signed-off-by: Roland Stigge --- drivers/spi/spi-pl022.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2136,7 +2136,7 @@ static int pl022_probe(struct amba_devic cs_gpio); else if (gpio_direction_output(cs_gpio, 1)) dev_err(>dev, - "could set gpio %d as output\n", + "could not set gpio %d as output\n", cs_gpio); } } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] SPI: Fix error message
This patch fixes an error message typo (not missing). Signed-off-by: Roland Stigge sti...@antcom.de --- drivers/spi/spi-pl022.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -2136,7 +2136,7 @@ static int pl022_probe(struct amba_devic cs_gpio); else if (gpio_direction_output(cs_gpio, 1)) dev_err(adev-dev, - could set gpio %d as output\n, + could not set gpio %d as output\n, cs_gpio); } } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] leds: Add DT support for leds-pca9532
This patch adds DT support for leds-pca9532. Signed-off-by: Roland Stigge sti...@antcom.de --- Applies to v3.17-rc4 Documentation/devicetree/bindings/leds/leds-pca9532.txt | 43 ++ drivers/leds/leds-pca9532.c | 47 2 files changed, 90 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/leds/leds-pca9532.txt @@ -0,0 +1,43 @@ +NXP PCA9532 LED (incl. GPIO) controller + +Required properties: +- compatible: must be nxp,pca9532 +- reg: I2C address +- gpio-controller: Marks the device node as a GPIO controller. +- #gpio-cells: Should be 2: + 1) pin number + 2) optional parameters: + - bit 0 specifies polarity (0 for normal, 1 for inverted) +- nxp,typecodes: groups of 2 bits for each of the 16 pins: + 0: None + 1: LED + 2: Beep + 3: GPIO +- nxp,statecodes: groups of 2 bits for each of the 16 pins: + 0: off + 1: on + 2: pwm0 + 3: pwm1 + +Optional properties: +- nxp,psc: array of 2 numbers: PSC values for the two PWM channels (see datasheet) +- nxp,pwm: array of 2 numbers: PWM values for the two PWM channels (see datasheet) + +Example: + + pca9532: pca9532@60 { + compatible = nxp,pca9532; + gpio-controller; + #gpio-cells = 2; + nxp,typecodes = 0x; + nxp,statecodes = 0x; + reg = 0x60; + }; + + sd@20098000 { + wp-gpios = pca9532 5 0; + cd-gpios = pca9532 4 0; + cd-inverted; + bus-width = 4; + status = okay; + }; --- linux-2.6.orig/drivers/leds/leds-pca9532.c +++ linux-2.6/drivers/leds/leds-pca9532.c @@ -21,6 +21,7 @@ #include linux/workqueue.h #include linux/leds-pca9532.h #include linux/gpio.h +#include linux/of.h /* m = num_leds*/ #define PCA9532_REG_INPUT(i) ((i) 3) @@ -442,6 +443,45 @@ exit: return err; } +#ifdef CONFIG_OF +static struct pca9532_platform_data *pca9532_parse_dt(struct device *dev) +{ + struct device_node *np = dev-of_node; + struct pca9532_platform_data *pca9532_pdata; + u32 typecodes, statecodes; + u32 pwm[2]; + u32 psc[2]; + int i; + + pca9532_pdata = devm_kzalloc(dev, sizeof(*pca9532_pdata), GFP_KERNEL); + if (!pca9532_pdata) + return NULL; + + if (!of_property_read_u32(np, nxp,typecodes, typecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].type = + (typecodes (2 * i)) 0x3; + } + if (!of_property_read_u32(np, nxp,statecodes, statecodes)) { + for (i = 0; i 16; i++) + pca9532_pdata-leds[i].state = + (statecodes (2 * i)) 0x3; + } + if (!of_property_read_u32_array(np, nxp,pwm, pwm[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-pwm[i] = pwm[i]; + } + if (!of_property_read_u32_array(np, nxp,psc, psc[0], 2)) { + for (i = 0; i 2; i++) + pca9532_pdata-psc[i] = psc[i]; + } + + pca9532_pdata-gpio_base = -1; /* dynamically assign gpio base */ + + return pca9532_pdata; +} +#endif + static int pca9532_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -449,6 +489,11 @@ static int pca9532_probe(struct i2c_clie struct pca9532_platform_data *pca9532_pdata = dev_get_platdata(client-dev); +#ifdef CONFIG_OF + if (!pca9532_pdata client-dev.of_node) + pca9532_pdata = pca9532_parse_dt(client-dev); +#endif + if (!pca9532_pdata) return -EIO; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 05/12] ARM: lpc32xx: add MTD_SPI_NOR (new dependency for M25P80)
On 01/05/14 08:26, Brian Norris wrote: > This defconfig contains the CONFIG_M25P80 symbol, which is now > dependent on the MTD_SPI_NOR symbol. Add CONFIG_MTD_SPI_NOR to satisfy > the new dependency. Can't the CONFIG_M25P80 declare its dependency on CONFIG_MTD_SPI_NOR itself, or put CONFIG_M25P80 etc. into a submenu under CONFIG_MTD_SPI_NOR? > > At the same time, drop the now-nonexistent CONFIG_MTD_CHAR symbol. > > Signed-off-by: Brian Norris > Cc: Roland Stigge > Cc: linux-arm-ker...@lists.infradead.org > Cc: linux-kernel@vger.kernel.org > --- > arch/arm/configs/lpc32xx_defconfig | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/arm/configs/lpc32xx_defconfig > b/arch/arm/configs/lpc32xx_defconfig > index 398a367ffce8..2de54c35fb47 100644 > --- a/arch/arm/configs/lpc32xx_defconfig > +++ b/arch/arm/configs/lpc32xx_defconfig > @@ -53,12 +53,12 @@ CONFIG_DEVTMPFS_MOUNT=y > # CONFIG_FW_LOADER is not set > CONFIG_MTD=y > CONFIG_MTD_CMDLINE_PARTS=y > -CONFIG_MTD_CHAR=y > CONFIG_MTD_BLOCK=y > CONFIG_MTD_M25P80=y > CONFIG_MTD_NAND=y > CONFIG_MTD_NAND_SLC_LPC32XX=y > CONFIG_MTD_NAND_MLC_LPC32XX=y > +CONFIG_MTD_SPI_NOR=y > CONFIG_BLK_DEV_LOOP=y > CONFIG_BLK_DEV_CRYPTOLOOP=y > CONFIG_BLK_DEV_RAM=y > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 05/12] ARM: lpc32xx: add MTD_SPI_NOR (new dependency for M25P80)
On 01/05/14 08:26, Brian Norris wrote: This defconfig contains the CONFIG_M25P80 symbol, which is now dependent on the MTD_SPI_NOR symbol. Add CONFIG_MTD_SPI_NOR to satisfy the new dependency. Can't the CONFIG_M25P80 declare its dependency on CONFIG_MTD_SPI_NOR itself, or put CONFIG_M25P80 etc. into a submenu under CONFIG_MTD_SPI_NOR? At the same time, drop the now-nonexistent CONFIG_MTD_CHAR symbol. Signed-off-by: Brian Norris computersforpe...@gmail.com Cc: Roland Stigge sti...@antcom.de Cc: linux-arm-ker...@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- arch/arm/configs/lpc32xx_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 398a367ffce8..2de54c35fb47 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -53,12 +53,12 @@ CONFIG_DEVTMPFS_MOUNT=y # CONFIG_FW_LOADER is not set CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y -CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y CONFIG_MTD_M25P80=y CONFIG_MTD_NAND=y CONFIG_MTD_NAND_SLC_LPC32XX=y CONFIG_MTD_NAND_MLC_LPC32XX=y +CONFIG_MTD_SPI_NOR=y CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/7] ARM: lpc32xx: don't select HAVE_PWM
On 10/02/14 02:09, Jingoo Han wrote: > The HAVE_PWM symbol is only for legacy platforms that provide > the PWM API without using the generic framework. The lpc32xx > platforms use the generic PWM framework, after the commit "2132fa8 > pwm: add lpc32xx PWM support". > > Signed-off-by: Jingoo Han > --- > arch/arm/Kconfig |1 - > 1 file changed, 1 deletion(-) > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index e254198..897fa15 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -632,7 +632,6 @@ config ARCH_LPC32XX > select CPU_ARM926T > select GENERIC_CLOCKEVENTS > select HAVE_IDE > - select HAVE_PWM > select USB_ARCH_HAS_OHCI > select USE_OF > help > Acked-by: Roland Stigge -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/7] ARM: lpc32xx: don't select HAVE_PWM
On 10/02/14 02:09, Jingoo Han wrote: The HAVE_PWM symbol is only for legacy platforms that provide the PWM API without using the generic framework. The lpc32xx platforms use the generic PWM framework, after the commit 2132fa8 pwm: add lpc32xx PWM support. Signed-off-by: Jingoo Han jg1@samsung.com --- arch/arm/Kconfig |1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e254198..897fa15 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -632,7 +632,6 @@ config ARCH_LPC32XX select CPU_ARM926T select GENERIC_CLOCKEVENTS select HAVE_IDE - select HAVE_PWM select USB_ARCH_HAS_OHCI select USE_OF help Acked-by: Roland Stigge sti...@antcom.de -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] ARM: LPC32xx: Fix reset function
In the recent change to the reset function API (commit 7b6d864b48d95e6ea1df7df64475b9cb9616dcf9), the mode argument changed from a char to an enum. lpc23xx_restart() only handles REBOOT_SOFT and REBOOT_HARD, but the new kernel code emits REBOOT_COLD (0) on reboots now which leads to lpc32xx simply not rebooting (but halting). This patch fixes this by just resetting unconditionally as on other platforms (e.g. mach-bcm2835). Pulling lpc32xx_watchdog_reset() into lpc23xx_restart() since the while() in lpc23xx_restart() is part of the procedure anyway and lpc32xx_watchdog_reset() isn't used anywhere else anymore. Signed-off-by: Roland Stigge -- Will provide a pull request for arm-soc when someone commented on this one. --- arch/arm/mach-lpc32xx/common.c | 29 ++--- 1 file changed, 6 insertions(+), 23 deletions(-) --- linux-2.6.orig/arch/arm/mach-lpc32xx/common.c +++ linux-2.6/arch/arm/mach-lpc32xx/common.c @@ -57,20 +57,6 @@ int clk_is_sysclk_mainosc(void) } /* - * System reset via the watchdog timer - */ -static void lpc32xx_watchdog_reset(void) -{ - /* Make sure WDT clocks are enabled */ - __raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN, - LPC32XX_CLKPWR_TIMER_CLK_CTRL); - - /* Instant assert of RESETOUT_N with pulse length 1mS */ - __raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18)); - __raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC)); -} - -/* * Detects and returns IRAM size for the device variation */ #define LPC32XX_IRAM_BANK_SIZE SZ_128K @@ -209,16 +195,13 @@ void __init lpc32xx_map_io(void) void lpc23xx_restart(enum reboot_mode mode, const char *cmd) { - switch (mode) { - case REBOOT_SOFT: - case REBOOT_HARD: - lpc32xx_watchdog_reset(); - break; + /* Make sure WDT clocks are enabled */ + __raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN, + LPC32XX_CLKPWR_TIMER_CLK_CTRL); - default: - /* Do nothing */ - break; - } + /* Instant assert of RESETOUT_N with pulse length 1mS */ + __raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18)); + __raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC)); /* Wait for watchdog to reset system */ while (1) -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] ARM: LPC32xx: Fix reset function
In the recent change to the reset function API (commit 7b6d864b48d95e6ea1df7df64475b9cb9616dcf9), the mode argument changed from a char to an enum. lpc23xx_restart() only handles REBOOT_SOFT and REBOOT_HARD, but the new kernel code emits REBOOT_COLD (0) on reboots now which leads to lpc32xx simply not rebooting (but halting). This patch fixes this by just resetting unconditionally as on other platforms (e.g. mach-bcm2835). Pulling lpc32xx_watchdog_reset() into lpc23xx_restart() since the while() in lpc23xx_restart() is part of the procedure anyway and lpc32xx_watchdog_reset() isn't used anywhere else anymore. Signed-off-by: Roland Stigge sti...@antcom.de -- Will provide a pull request for arm-soc when someone commented on this one. --- arch/arm/mach-lpc32xx/common.c | 29 ++--- 1 file changed, 6 insertions(+), 23 deletions(-) --- linux-2.6.orig/arch/arm/mach-lpc32xx/common.c +++ linux-2.6/arch/arm/mach-lpc32xx/common.c @@ -57,20 +57,6 @@ int clk_is_sysclk_mainosc(void) } /* - * System reset via the watchdog timer - */ -static void lpc32xx_watchdog_reset(void) -{ - /* Make sure WDT clocks are enabled */ - __raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN, - LPC32XX_CLKPWR_TIMER_CLK_CTRL); - - /* Instant assert of RESETOUT_N with pulse length 1mS */ - __raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18)); - __raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC)); -} - -/* * Detects and returns IRAM size for the device variation */ #define LPC32XX_IRAM_BANK_SIZE SZ_128K @@ -209,16 +195,13 @@ void __init lpc32xx_map_io(void) void lpc23xx_restart(enum reboot_mode mode, const char *cmd) { - switch (mode) { - case REBOOT_SOFT: - case REBOOT_HARD: - lpc32xx_watchdog_reset(); - break; + /* Make sure WDT clocks are enabled */ + __raw_writel(LPC32XX_CLKPWR_PWMCLK_WDOG_EN, + LPC32XX_CLKPWR_TIMER_CLK_CTRL); - default: - /* Do nothing */ - break; - } + /* Instant assert of RESETOUT_N with pulse length 1mS */ + __raw_writel(13000, io_p2v(LPC32XX_WDTIM_BASE + 0x18)); + __raw_writel(0x70, io_p2v(LPC32XX_WDTIM_BASE + 0xC)); /* Wait for watchdog to reset system */ while (1) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] MAX7301 GPIO: Reverting "Do not force SPI speed when using OF Platform"
On 08/20/2013 08:29 AM, Christophe Leroy wrote: > This patch reverts commit 047b93a35961f7a6561e6f5dcb040738f822b892 which > breaks > MAX7301 GPIO driver because that commit was dependant on a rejected patch that > was implementing selection of SPI speed from the Device Tree. > > Signed-off-by: Christophe Leroy Acked-by: Roland Stigge Good, thanks! > > --- linux-3.11-rc6/drivers/gpio/gpio-max7301.c2013-08-17 > 21:09:17.0 +0200 > +++ linux/drivers/gpio/gpio-max7301.c 2013-08-18 06:31:52.0 +0200 > @@ -56,8 +56,7 @@ > int ret; > > /* bits_per_word cannot be configured in platform data */ > - if (spi->dev.platform_data) > - spi->bits_per_word = 16; > + spi->bits_per_word = 16; > ret = spi_setup(spi); > if (ret < 0) > return ret; > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] MAX7301 GPIO: Reverting Do not force SPI speed when using OF Platform
On 08/20/2013 08:29 AM, Christophe Leroy wrote: This patch reverts commit 047b93a35961f7a6561e6f5dcb040738f822b892 which breaks MAX7301 GPIO driver because that commit was dependant on a rejected patch that was implementing selection of SPI speed from the Device Tree. Signed-off-by: Christophe Leroy christophe.le...@c-s.fr Acked-by: Roland Stigge sti...@antcom.de Good, thanks! --- linux-3.11-rc6/drivers/gpio/gpio-max7301.c2013-08-17 21:09:17.0 +0200 +++ linux/drivers/gpio/gpio-max7301.c 2013-08-18 06:31:52.0 +0200 @@ -56,8 +56,7 @@ int ret; /* bits_per_word cannot be configured in platform data */ - if (spi-dev.platform_data) - spi-bits_per_word = 16; + spi-bits_per_word = 16; ret = spi_setup(spi); if (ret 0) return ret; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] USB: lpc32xx: USB_LPC32XX need not depend on USB_PHY
On 05/29/2013 01:43 PM, Roger Quadros wrote: > As the USB PHY drivers no longer depend on USB_PHY but > select it if needed, the controller drivers need not > depend on USB_PHY. They can safely select the necessary > PHY driver i.e. USB_ISP1301 in this case. > > Signed-off-by: Roger Quadros Acked-by: Roland Stigge Tested-by: Roland Stigge Thanks! > CC: Roland Stigge > --- > drivers/usb/gadget/Kconfig |1 - > 1 files changed, 0 insertions(+), 1 deletions(-) > > diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig > index f41aa0d..2b98bce 100644 > --- a/drivers/usb/gadget/Kconfig > +++ b/drivers/usb/gadget/Kconfig > @@ -144,7 +144,6 @@ config USB_AT91 > config USB_LPC32XX > tristate "LPC32XX USB Peripheral Controller" > depends on ARCH_LPC32XX > - depends on USB_PHY > select USB_ISP1301 > help > This option selects the USB device controller in the LPC32xx SoC. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 4/5] USB: lpc32xx: USB_LPC32XX need not depend on USB_PHY
On 05/29/2013 01:43 PM, Roger Quadros wrote: As the USB PHY drivers no longer depend on USB_PHY but select it if needed, the controller drivers need not depend on USB_PHY. They can safely select the necessary PHY driver i.e. USB_ISP1301 in this case. Signed-off-by: Roger Quadros rog...@ti.com Acked-by: Roland Stigge sti...@antcom.de Tested-by: Roland Stigge sti...@antcom.de Thanks! CC: Roland Stigge sti...@antcom.de --- drivers/usb/gadget/Kconfig |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index f41aa0d..2b98bce 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -144,7 +144,6 @@ config USB_AT91 config USB_LPC32XX tristate LPC32XX USB Peripheral Controller depends on ARCH_LPC32XX - depends on USB_PHY select USB_ISP1301 help This option selects the USB device controller in the LPC32xx SoC. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 19/21] USB: lpc32xx: ISP1301 needs USB_PHY
On 25/04/13 19:29, Arnd Bergmann wrote: > The Kconfig entry for USB_LPC32XX unconditionally selects USB_ISP1301, > which is now only visible when USB_PHY is also enabled. > > This adds an appropriate dependency and enables USB_PHY in the msm > defconfig, avoiding these build errors: > > warning: (USB_LPC32XX) selects USB_ISP1301 which has unmet direct > dependencies (USB_SUPPORT && USB_PHY && (USB || USB_GADGET) && I2C) > drivers/built-in.o: In function `usb_hcd_nxp_probe': > drivers/usb/host/ohci-nxp.c:224: undefined reference to `isp1301_get_client' > drivers/built-in.o: In function `lpc32xx_udc_probe': > drivers/usb/gadget/lpc32xx_udc.c:3071: undefined reference to > `isp1301_get_client' > > Signed-off-by: Arnd Bergmann > Cc: linux-...@vger.kernel.org > Cc: Greg Kroah-Hartman > Cc: Felipe Balbi > Cc: Roland Stigge Tested-by: Roland Stigge Acked-by: Roland Stigge > --- > arch/arm/configs/lpc32xx_defconfig | 1 + > drivers/usb/gadget/Kconfig | 1 + > 2 files changed, 2 insertions(+) > > diff --git a/arch/arm/configs/lpc32xx_defconfig > b/arch/arm/configs/lpc32xx_defconfig > index 8fee514..398a367 100644 > --- a/arch/arm/configs/lpc32xx_defconfig > +++ b/arch/arm/configs/lpc32xx_defconfig > @@ -146,6 +146,7 @@ CONFIG_SND_DEBUG_VERBOSE=y > # CONFIG_SND_SPI is not set > CONFIG_SND_SOC=y > CONFIG_USB=y > +CONFIG_USB_PHY=y > CONFIG_USB_OHCI_HCD=y > CONFIG_USB_STORAGE=y > CONFIG_USB_GADGET=y > diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig > index a61d981..f85b427 100644 > --- a/drivers/usb/gadget/Kconfig > +++ b/drivers/usb/gadget/Kconfig > @@ -144,6 +144,7 @@ config USB_AT91 > config USB_LPC32XX > tristate "LPC32XX USB Peripheral Controller" > depends on ARCH_LPC32XX > + depends on USB_PHY > select USB_ISP1301 > select USB_OTG_UTILS > help -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 19/21] USB: lpc32xx: ISP1301 needs USB_PHY
On 25/04/13 19:29, Arnd Bergmann wrote: The Kconfig entry for USB_LPC32XX unconditionally selects USB_ISP1301, which is now only visible when USB_PHY is also enabled. This adds an appropriate dependency and enables USB_PHY in the msm defconfig, avoiding these build errors: warning: (USB_LPC32XX) selects USB_ISP1301 which has unmet direct dependencies (USB_SUPPORT USB_PHY (USB || USB_GADGET) I2C) drivers/built-in.o: In function `usb_hcd_nxp_probe': drivers/usb/host/ohci-nxp.c:224: undefined reference to `isp1301_get_client' drivers/built-in.o: In function `lpc32xx_udc_probe': drivers/usb/gadget/lpc32xx_udc.c:3071: undefined reference to `isp1301_get_client' Signed-off-by: Arnd Bergmann a...@arndb.de Cc: linux-...@vger.kernel.org Cc: Greg Kroah-Hartman gre...@linuxfoundation.org Cc: Felipe Balbi ba...@ti.com Cc: Roland Stigge sti...@antcom.de Tested-by: Roland Stigge sti...@antcom.de Acked-by: Roland Stigge sti...@antcom.de --- arch/arm/configs/lpc32xx_defconfig | 1 + drivers/usb/gadget/Kconfig | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_defconfig index 8fee514..398a367 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -146,6 +146,7 @@ CONFIG_SND_DEBUG_VERBOSE=y # CONFIG_SND_SPI is not set CONFIG_SND_SOC=y CONFIG_USB=y +CONFIG_USB_PHY=y CONFIG_USB_OHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a61d981..f85b427 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -144,6 +144,7 @@ config USB_AT91 config USB_LPC32XX tristate LPC32XX USB Peripheral Controller depends on ARCH_LPC32XX + depends on USB_PHY select USB_ISP1301 select USB_OTG_UTILS help -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RESEND][PATCH RFT 2/2] pwm: lpc32xx: Don't change PWM_ENABLE bit in lpc32xx_pwm_config
On 04/23/2013 08:02 AM, Axel Lin wrote: > lpc32xx_pwm_config() is supposed to set duty_ns and period_ns, > it should not change PWM_ENABLE bit. > > Signed-off-by: Axel Lin Tested-by: Roland Stigge > --- > drivers/pwm/pwm-lpc32xx.c |7 +-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c > index 1a5075e..e936202 100644 > --- a/drivers/pwm/pwm-lpc32xx.c > +++ b/drivers/pwm/pwm-lpc32xx.c > @@ -37,6 +37,7 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct > pwm_device *pwm, > struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); > unsigned long long c; > int period_cycles, duty_cycles; > + u32 val; > > c = clk_get_rate(lpc32xx->clk) / 256; > c = c * period_ns; > @@ -68,8 +69,10 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, > struct pwm_device *pwm, > c = 255; > duty_cycles = 256 - c; > > - writel(PWM_ENABLE | PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles), > - lpc32xx->base + (pwm->hwpwm << 2)); > + val = readl(lpc32xx->base + (pwm->hwpwm << 2)); > + val &= ~0x; > + val |= PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles); > + writel(val, lpc32xx->base + (pwm->hwpwm << 2)); > > return 0; > } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RESEND][PATCH RFT 1/2] pwm: lpc32xx: Properly set PWM_ENABLE bit in lpc32xx_pwm_[enable|disable]
On 04/23/2013 08:01 AM, Axel Lin wrote: > According to the LPC32x0 User Manual [1]: > > For both PWM1 and PWM2 Control Registers: > BIT 31: > This bit gates the PWM_CLK signal and enables the external output pin > to the PWM_PIN_STATE logical level. > > 0 = PWM disabled. (Default) > 1 = PWM enabled > > So in lpc32xx_pwm_enable(), we should set PWM_ENABLE bit. > In lpc32xx_pwm_disable(), we should just clear PWM_ENABLE bit rather than > write 0 to the register which will also clear PWMx_RELOADV and PWMx_DUTY bits. > > [1] http://www.nxp.com/documents/user_manual/UM10326.pdf > > Signed-off-by: Axel Lin Tested-by: Roland Stigge > --- > Hi, > I don't have this hardware handy so I'd appreciate if someone can test this > patch serial. > > This patch serial was sent on https://lkml.org/lkml/2013/3/30/104 > Seems no feedback so far. > So I just try again, maybe someone can help testing it. > Thanks, > Axel > > drivers/pwm/pwm-lpc32xx.c | 18 -- > 1 file changed, 16 insertions(+), 2 deletions(-) > > diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c > index b3f0d0d..1a5075e 100644 > --- a/drivers/pwm/pwm-lpc32xx.c > +++ b/drivers/pwm/pwm-lpc32xx.c > @@ -77,15 +77,29 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, > struct pwm_device *pwm, > static int lpc32xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) > { > struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); > + u32 val; > + int ret; > + > + ret = clk_enable(lpc32xx->clk); > + if (ret) > + return ret; > > - return clk_enable(lpc32xx->clk); > + val = readl(lpc32xx->base + (pwm->hwpwm << 2)); > + val |= PWM_ENABLE; > + writel(val, lpc32xx->base + (pwm->hwpwm << 2)); > + > + return 0; > } > > static void lpc32xx_pwm_disable(struct pwm_chip *chip, struct pwm_device > *pwm) > { > struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); > + u32 val; > + > + val = readl(lpc32xx->base + (pwm->hwpwm << 2)); > + val &= ~PWM_ENABLE; > + writel(val, lpc32xx->base + (pwm->hwpwm << 2)); > > - writel(0, lpc32xx->base + (pwm->hwpwm << 2)); > clk_disable(lpc32xx->clk); > } > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RESEND][PATCH RFT 1/2] pwm: lpc32xx: Properly set PWM_ENABLE bit in lpc32xx_pwm_[enable|disable]
On 04/23/2013 08:01 AM, Axel Lin wrote: According to the LPC32x0 User Manual [1]: For both PWM1 and PWM2 Control Registers: BIT 31: This bit gates the PWM_CLK signal and enables the external output pin to the PWM_PIN_STATE logical level. 0 = PWM disabled. (Default) 1 = PWM enabled So in lpc32xx_pwm_enable(), we should set PWM_ENABLE bit. In lpc32xx_pwm_disable(), we should just clear PWM_ENABLE bit rather than write 0 to the register which will also clear PWMx_RELOADV and PWMx_DUTY bits. [1] http://www.nxp.com/documents/user_manual/UM10326.pdf Signed-off-by: Axel Lin axel@ingics.com Tested-by: Roland Stigge sti...@antcom.de --- Hi, I don't have this hardware handy so I'd appreciate if someone can test this patch serial. This patch serial was sent on https://lkml.org/lkml/2013/3/30/104 Seems no feedback so far. So I just try again, maybe someone can help testing it. Thanks, Axel drivers/pwm/pwm-lpc32xx.c | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c index b3f0d0d..1a5075e 100644 --- a/drivers/pwm/pwm-lpc32xx.c +++ b/drivers/pwm/pwm-lpc32xx.c @@ -77,15 +77,29 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, static int lpc32xx_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); + u32 val; + int ret; + + ret = clk_enable(lpc32xx-clk); + if (ret) + return ret; - return clk_enable(lpc32xx-clk); + val = readl(lpc32xx-base + (pwm-hwpwm 2)); + val |= PWM_ENABLE; + writel(val, lpc32xx-base + (pwm-hwpwm 2)); + + return 0; } static void lpc32xx_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) { struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); + u32 val; + + val = readl(lpc32xx-base + (pwm-hwpwm 2)); + val = ~PWM_ENABLE; + writel(val, lpc32xx-base + (pwm-hwpwm 2)); - writel(0, lpc32xx-base + (pwm-hwpwm 2)); clk_disable(lpc32xx-clk); } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RESEND][PATCH RFT 2/2] pwm: lpc32xx: Don't change PWM_ENABLE bit in lpc32xx_pwm_config
On 04/23/2013 08:02 AM, Axel Lin wrote: lpc32xx_pwm_config() is supposed to set duty_ns and period_ns, it should not change PWM_ENABLE bit. Signed-off-by: Axel Lin axel@ingics.com Tested-by: Roland Stigge sti...@antcom.de --- drivers/pwm/pwm-lpc32xx.c |7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/pwm/pwm-lpc32xx.c b/drivers/pwm/pwm-lpc32xx.c index 1a5075e..e936202 100644 --- a/drivers/pwm/pwm-lpc32xx.c +++ b/drivers/pwm/pwm-lpc32xx.c @@ -37,6 +37,7 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, struct lpc32xx_pwm_chip *lpc32xx = to_lpc32xx_pwm_chip(chip); unsigned long long c; int period_cycles, duty_cycles; + u32 val; c = clk_get_rate(lpc32xx-clk) / 256; c = c * period_ns; @@ -68,8 +69,10 @@ static int lpc32xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, c = 255; duty_cycles = 256 - c; - writel(PWM_ENABLE | PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles), - lpc32xx-base + (pwm-hwpwm 2)); + val = readl(lpc32xx-base + (pwm-hwpwm 2)); + val = ~0x; + val |= PWM_RELOADV(period_cycles) | PWM_DUTY(duty_cycles); + writel(val, lpc32xx-base + (pwm-hwpwm 2)); return 0; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: LPC32xx: changed lpc23xx_restart to lpc32xx_restart
On 02/04/13 17:58, Olof Johansson wrote: > On Wed, Mar 06, 2013 at 09:18:58PM +0100, Martin Knoll wrote: >> This function has an odd name. This is probably a typo. > > You should cc the platform maintainer on these kind of patches (Roland > Stigge). > But it seems that he's not actually listed in MAINTAINERS. I indeed missed the above patch - should be a simple syntactic fix in 3 places in arch/arm/. You can go ahead this time and directly take this fix. Otherwise, please forward to me so I can add it to a lpc32xx tree and do request pull. > Roland, can you send a patch adding yourself as LPC32XX maintainer so these > kind of patches don't get dropped? Thanks! OK, just did. Thanks for notifying! Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] MAINTAINERS: Add maintainer for LPC32xx
This patch adds Roland Stigge as maintainer for NXP LPC32xx. Signed-off-by: Roland Stigge --- MAINTAINERS |6 ++ 1 file changed, 6 insertions(+) --- linux-2.6.orig/MAINTAINERS +++ linux-2.6/MAINTAINERS @@ -4941,6 +4941,12 @@ W: logfs.org S: Maintained F: fs/logfs/ +LPC32XX MACHINE SUPPORT +M: Roland Stigge +L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-lpc32xx/ + LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) M: Nagalakshmi Nandigama M: Sreekanth Reddy -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] MAINTAINERS: Add maintainer for LPC32xx
This patch adds Roland Stigge as maintainer for NXP LPC32xx. Signed-off-by: Roland Stigge sti...@antcom.de --- MAINTAINERS |6 ++ 1 file changed, 6 insertions(+) --- linux-2.6.orig/MAINTAINERS +++ linux-2.6/MAINTAINERS @@ -4941,6 +4941,12 @@ W: logfs.org S: Maintained F: fs/logfs/ +LPC32XX MACHINE SUPPORT +M: Roland Stigge sti...@antcom.de +L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: arch/arm/mach-lpc32xx/ + LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) M: Nagalakshmi Nandigama nagalakshmi.nandig...@lsi.com M: Sreekanth Reddy sreekanth.re...@lsi.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] ARM: LPC32xx: changed lpc23xx_restart to lpc32xx_restart
On 02/04/13 17:58, Olof Johansson wrote: On Wed, Mar 06, 2013 at 09:18:58PM +0100, Martin Knoll wrote: This function has an odd name. This is probably a typo. You should cc the platform maintainer on these kind of patches (Roland Stigge). But it seems that he's not actually listed in MAINTAINERS. I indeed missed the above patch - should be a simple syntactic fix in 3 places in arch/arm/. You can go ahead this time and directly take this fix. Otherwise, please forward to me so I can add it to a lpc32xx tree and do request pull. Roland, can you send a patch adding yourself as LPC32XX maintainer so these kind of patches don't get dropped? Thanks! OK, just did. Thanks for notifying! Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
-BEGIN PGP SIGNED MESSAGE- Hash: RIPEMD160 On 03/26/2013 08:24 PM, Felipe Balbi wrote: > commit ? 1c2088812f095df77f4b3224b65db79d7111a300 Seems to be based on the assumption that only OTG needs a PHY. -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFRUgQ/caH/YBv43g8RA7RwAKC5HfJmtZonZnwGs6h+hW6Nqi1++wCg25xt 0lckwMSSDwJ4PNiDKqqtRpY= =Zpq1 -END PGP SIGNATURE- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
-BEGIN PGP SIGNED MESSAGE- Hash: RIPEMD160 On 03/26/2013 07:03 PM, Felipe Balbi wrote: > On Tue, Mar 26, 2013 at 06:36:01PM +0100, Roland Stigge wrote: >> The current lpc32xx_defconfig breaks like this, caused by recent >> phy restructuring: > > which commit actually caused this ? I need to know to make sure if > this should be sent to stable or not. The issue definitely surfaced after v3.8, so no need for patching stable, I guess. -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFRUfSMcaH/YBv43g8RA70DAKCigz7Qy4f01S9P5dNLH6jxlERF6gCg3H3q qMlT8LpXfybr588cZFJUjcc= =45cd -END PGP SIGNATURE- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
The current lpc32xx_defconfig breaks like this, caused by recent phy restructuring: LD init/built-in.o drivers/built-in.o: In function `usb_hcd_nxp_probe': drivers/usb/host/ohci-nxp.c:224: undefined reference to `isp1301_get_client' drivers/built-in.o: In function `lpc32xx_udc_probe': drivers/usb/gadget/lpc32xx_udc.c:3104: undefined reference to `isp1301_get_client' distcc[27867] ERROR: compile (null) on localhost failed make: *** [vmlinux] Error 1 This patch fixes this by selecting USB_OTG_UTILS in Kconfig which causes the phy driver to be built again. Signed-off-by: Roland Stigge -- Applies to v3.9-rc4 --- drivers/usb/gadget/Kconfig |1 + drivers/usb/phy/Kconfig|1 + 2 files changed, 2 insertions(+) --- linux-2.6.orig/drivers/usb/gadget/Kconfig +++ linux-2.6/drivers/usb/gadget/Kconfig @@ -145,6 +145,7 @@ config USB_LPC32XX tristate "LPC32XX USB Peripheral Controller" depends on ARCH_LPC32XX select USB_ISP1301 + select USB_OTG_UTILS help This option selects the USB device controller in the LPC32xx SoC. --- linux-2.6.orig/drivers/usb/phy/Kconfig +++ linux-2.6/drivers/usb/phy/Kconfig @@ -38,6 +38,7 @@ config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" depends on USB || USB_GADGET depends on I2C + select USB_OTG_UTILS help Say Y here to add support for the NXP ISP1301 USB transceiver driver. This chip is typically used as USB transceiver for USB host, gadget -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
The current lpc32xx_defconfig breaks like this, caused by recent phy restructuring: LD init/built-in.o drivers/built-in.o: In function `usb_hcd_nxp_probe': drivers/usb/host/ohci-nxp.c:224: undefined reference to `isp1301_get_client' drivers/built-in.o: In function `lpc32xx_udc_probe': drivers/usb/gadget/lpc32xx_udc.c:3104: undefined reference to `isp1301_get_client' distcc[27867] ERROR: compile (null) on localhost failed make: *** [vmlinux] Error 1 This patch fixes this by selecting USB_OTG_UTILS in Kconfig which causes the phy driver to be built again. Signed-off-by: Roland Stigge sti...@antcom.de -- Applies to v3.9-rc4 --- drivers/usb/gadget/Kconfig |1 + drivers/usb/phy/Kconfig|1 + 2 files changed, 2 insertions(+) --- linux-2.6.orig/drivers/usb/gadget/Kconfig +++ linux-2.6/drivers/usb/gadget/Kconfig @@ -145,6 +145,7 @@ config USB_LPC32XX tristate LPC32XX USB Peripheral Controller depends on ARCH_LPC32XX select USB_ISP1301 + select USB_OTG_UTILS help This option selects the USB device controller in the LPC32xx SoC. --- linux-2.6.orig/drivers/usb/phy/Kconfig +++ linux-2.6/drivers/usb/phy/Kconfig @@ -38,6 +38,7 @@ config USB_ISP1301 tristate NXP ISP1301 USB transceiver support depends on USB || USB_GADGET depends on I2C + select USB_OTG_UTILS help Say Y here to add support for the NXP ISP1301 USB transceiver driver. This chip is typically used as USB transceiver for USB host, gadget -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
-BEGIN PGP SIGNED MESSAGE- Hash: RIPEMD160 On 03/26/2013 07:03 PM, Felipe Balbi wrote: On Tue, Mar 26, 2013 at 06:36:01PM +0100, Roland Stigge wrote: The current lpc32xx_defconfig breaks like this, caused by recent phy restructuring: which commit actually caused this ? I need to know to make sure if this should be sent to stable or not. The issue definitely surfaced after v3.8, so no need for patching stable, I guess. -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFRUfSMcaH/YBv43g8RA70DAKCigz7Qy4f01S9P5dNLH6jxlERF6gCg3H3q qMlT8LpXfybr588cZFJUjcc= =45cd -END PGP SIGNATURE- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] usb: Fix compile error by selecting USB_OTG_UTILS
-BEGIN PGP SIGNED MESSAGE- Hash: RIPEMD160 On 03/26/2013 08:24 PM, Felipe Balbi wrote: commit ? 1c2088812f095df77f4b3224b65db79d7111a300 Seems to be based on the assumption that only OTG needs a PHY. -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iD8DBQFRUgQ/caH/YBv43g8RA7RwAKC5HfJmtZonZnwGs6h+hW6Nqi1++wCg25xt 0lckwMSSDwJ4PNiDKqqtRpY= =Zpq1 -END PGP SIGNATURE- -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] mmc: mmc_spi: Fix return value evaluation of irq_of_parse_and_map()
When irq_of_parse_and_map() returns an error, it does as zero. But in mmc_spi_get_pdata(), the error return case is compared against NO_IRQ. This might work where NO_IRQ is zero (defaults to zero when undefined, as on MIPS) but not where NO_IRQ is sth. different, e.g. on ARM, where it is -1. This patch changes to comparison with 0 which is the error return value of irq_of_parse_and_map(). Tested on ARM that mmc_spi is working now. Signed-off-by: Roland Stigge diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 1534b58..d720b5e 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -146,7 +146,7 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) oms->pdata.get_ro = of_mmc_spi_get_ro; oms->detect_irq = irq_of_parse_and_map(np, 0); - if (oms->detect_irq != NO_IRQ) { + if (oms->detect_irq != 0) { oms->pdata.init = of_mmc_spi_init; oms->pdata.exit = of_mmc_spi_exit; } else { -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] mmc: mmc_spi: Fix return value evaluation of irq_of_parse_and_map()
When irq_of_parse_and_map() returns an error, it does as zero. But in mmc_spi_get_pdata(), the error return case is compared against NO_IRQ. This might work where NO_IRQ is zero (defaults to zero when undefined, as on MIPS) but not where NO_IRQ is sth. different, e.g. on ARM, where it is -1. This patch changes to comparison with 0 which is the error return value of irq_of_parse_and_map(). Tested on ARM that mmc_spi is working now. Signed-off-by: Roland Stigge sti...@antcom.de diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 1534b58..d720b5e 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -146,7 +146,7 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) oms-pdata.get_ro = of_mmc_spi_get_ro; oms-detect_irq = irq_of_parse_and_map(np, 0); - if (oms-detect_irq != NO_IRQ) { + if (oms-detect_irq != 0) { oms-pdata.init = of_mmc_spi_init; oms-pdata.exit = of_mmc_spi_exit; } else { -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
On 01/28/2013 12:39 PM, Stijn Devriendt wrote: >>> In the device-tree this is specified as: >>> >>> powr@0x20 { >>>// other properties >>> >>> gpios = < 4 0 >>> 5 0>; >>> }; >>> >>> Is this kind of integration also possible? >> >> You can reference the gpio block via a phandle, e.g.: >> >> blockgpio { >> compatible = "linux,gpio-block"; >> >> selector1 { >> gpios = < 4 0>, >> < 5 0>; >> }; >> }; >> >> powr@0x20 { >> // ... >> >> gpios = <>; >> }; >> >> >> In the driver, you can get the gpio block like this: >> >> block = gpio_block_find_by_name(of_parse_phandle(powr, "gpios", 0)->name); >> >> (Simplified by removed error/NULL handling!) >> >> If this turns out to be a common pattern, I can add a convenience "get" >> function for this. > > Given the pick-up of device-tree in ARM and MIPS, I think this stands > a good chance > of becoming a common pattern. Do mind the "gpios" name; it's already used by > the > normal GPIO request functions... Right, when providing the respective convenience function, I'll better use sth. like "gpioblock" as property name. Specifying a traditional list of GPIOs instead is easy, actually. The respective driver just needs to allocate a gpio block explicitly (insteady of implicitly via phandle as above). Unfortunately, gpio blocks that should be exported and available to userspace can't be specified this way. Therefore the strategy as above. Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
On 01/28/2013 12:39 PM, Stijn Devriendt wrote: In the device-tree this is specified as: powr@0x20 { // other properties gpios = gpio 4 0 gpio 5 0; }; Is this kind of integration also possible? You can reference the gpio block via a phandle, e.g.: blockgpio { compatible = linux,gpio-block; selector1 { gpios = gpio 4 0, gpio 5 0; }; }; powr@0x20 { // ... gpios = selector1; }; In the driver, you can get the gpio block like this: block = gpio_block_find_by_name(of_parse_phandle(powr, gpios, 0)-name); (Simplified by removed error/NULL handling!) If this turns out to be a common pattern, I can add a convenience get function for this. Given the pick-up of device-tree in ARM and MIPS, I think this stands a good chance of becoming a common pattern. Do mind the gpios name; it's already used by the normal GPIO request functions... Right, when providing the respective convenience function, I'll better use sth. like gpioblock as property name. Specifying a traditional list of GPIOs instead is easy, actually. The respective driver just needs to allocate a gpio block explicitly (insteady of implicitly via phandle as above). Unfortunately, gpio blocks that should be exported and available to userspace can't be specified this way. Therefore the strategy as above. Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
On 27/01/13 14:07, Stijn Devriendt wrote: >> +Example: >> + >> +blockgpio { >> +compatible = "linux,gpio-block"; >> + >> +block0 { >> +gpios = < 3 0 0>, >> +< 3 1 0>; >> +}; >> +block1 { >> +gpios = < 4 1 0>, >> +< 4 3 0>, >> +< 4 2 0>, >> +< 4 4 0>, >> +< 4 5 0>, >> +< 4 6 0>, >> +< 4 7 0>, >> +< 4 8 0>, >> +< 4 9 0>, >> +< 4 10 0>, >> +< 4 19 0>; >> +}; >> +}; > > How do you see bindings for other kinds of drivers? > > In my patchset, it's possible for other drivers to use gpio-blocks. > One example we have is a power sequencer with 2 pins attached > to GPIO pins. These 2 pins form a 2bit word to select power margining. > These 2 pins need to be set synchronously (as otherwise when going > from profile 0 to profile 3 you pass either profile 1 or profile 2 which > could be bad for hardware) > > In the device-tree this is specified as: > > powr@0x20 { >// other properties > > gpios = < 4 0 > 5 0>; > }; > > Is this kind of integration also possible? You can reference the gpio block via a phandle, e.g.: blockgpio { compatible = "linux,gpio-block"; selector1 { gpios = < 4 0>, < 5 0>; }; }; powr@0x20 { // ... gpios = <>; }; In the driver, you can get the gpio block like this: block = gpio_block_find_by_name(of_parse_phandle(powr, "gpios", 0)->name); (Simplified by removed error/NULL handling!) If this turns out to be a common pattern, I can add a convenience "get" function for this. Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/6 v14] gpio: Add a block GPIO API to gpiolib
On 27/01/13 14:19, Stijn Devriendt wrote: >> +Block GPIO >> +-- >> + >> +The above described interface concentrates on handling single GPIOs. >> However, >> +in applications where it is critical to set several GPIOs at once, this >> +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO >> lines. >> +Consider a GPIO controller that is connected via a slow I2C line. When >> +switching two or more GPIOs one after another, there can be considerable >> time >> +between those events. This is solved by an interface called Block GPIO: >> + >> +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, >> +const char *name); >> + >> +This creates a new block of GPIOs as a list of GPIO numbers with the >> specified >> +size which are accessible via the returned struct gpio_block and the >> accessor >> +functions described below. Please note that you need to request the GPIOs >> +separately via gpio_request(). Similarly, the direction of the used GPIOs >> need >> +to be set by the user before using the block. > > Is there anything holding you back from letting gpio_block_create() do > the request > for all the pins? It's analoguous to plain GPIOs: They exist, but are not requested (by whom?) by default. > Also, wouldn't it make sense to have a gpio_block_direction_input() > and _output() > variant? On the other hand, for things like I2C and SPI emulation, > some pins will > naturally be always output (like clock lines) while other could be > switched between > in and output (like the i2c data line). Right. Current implementation emphasizes on switching, not direction or other convenience functions, which could be added, nevertheless. Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
On 27/01/13 13:18, Stijn Devriendt wrote: >>> In my patch, I go out of the way of this kind of thing for a simple reason: >>> You may generate incorrect timing by doing this. >> >> You are right, certain things like synchronous on+off is not really >> possible. >> >> However, the above at least supports switching on simulaneously, and >> switching off simultaneously, which is an improvement in certain cases >> (and this certain hardware part doesn't support more). Maybe this >> certain driver behaviour can be documented even better than just in the >> driver source. >> > > The question here is: do you expect a user of the block-GPIO API to > go look into the base-driver code to see what will be supported? > > In my version of the patch this means: > - do not provide a single GPIO-block that crosses multiple base-drivers > - only provide gpio_block_get/set for GPIO drivers that support the complete > operation in a single go. (for example, in the above example there would be > no gpio_block_set() function) > > Perhaps the best approach is to make this explicit: Allow drivers to expose > their capabilities wrt timing and allow users to request strict-timing or > loose-timing. Loose-timing allows multiple gpio-drivers to be combined and > allows drivers with separate set/clear, hi/lo registers to be used. Interesting idea. However, it will be difficult to agree on good metrics here. As Mark Brown pointed out, even when hardware seems to support "simultaneousness" by registers, this doesn't actually mean that voltage levels are switched simultaneously wrt. sub-nanosecond timing. Also, it depends on further wiring between the actually supported GPIO hardware chip and the integrated device's I/O connections. Resulting in scenarios where GPIO chips (in terms of Linux drivers) without explicit I/O set registers (e.g., set/clear regs) could be "more simultaneous" than those having explicit I/O regs but hardware wiring leading to bad "simultaneousness" behaviour. Questionable if the kernel could address those details. > Of course, for a first version you may as well leave it out. Perhaps the > use-cases for cross-GPIO-driver blocks are not worth the extra complexity > as of today? I actually started the current block gpio patches to support this kind of use case. :-) Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
On 27/01/13 13:18, Stijn Devriendt wrote: In my patch, I go out of the way of this kind of thing for a simple reason: You may generate incorrect timing by doing this. You are right, certain things like synchronous on+off is not really possible. However, the above at least supports switching on simulaneously, and switching off simultaneously, which is an improvement in certain cases (and this certain hardware part doesn't support more). Maybe this certain driver behaviour can be documented even better than just in the driver source. The question here is: do you expect a user of the block-GPIO API to go look into the base-driver code to see what will be supported? In my version of the patch this means: - do not provide a single GPIO-block that crosses multiple base-drivers - only provide gpio_block_get/set for GPIO drivers that support the complete operation in a single go. (for example, in the above example there would be no gpio_block_set() function) Perhaps the best approach is to make this explicit: Allow drivers to expose their capabilities wrt timing and allow users to request strict-timing or loose-timing. Loose-timing allows multiple gpio-drivers to be combined and allows drivers with separate set/clear, hi/lo registers to be used. Interesting idea. However, it will be difficult to agree on good metrics here. As Mark Brown pointed out, even when hardware seems to support simultaneousness by registers, this doesn't actually mean that voltage levels are switched simultaneously wrt. sub-nanosecond timing. Also, it depends on further wiring between the actually supported GPIO hardware chip and the integrated device's I/O connections. Resulting in scenarios where GPIO chips (in terms of Linux drivers) without explicit I/O set registers (e.g., set/clear regs) could be more simultaneous than those having explicit I/O regs but hardware wiring leading to bad simultaneousness behaviour. Questionable if the kernel could address those details. Of course, for a first version you may as well leave it out. Perhaps the use-cases for cross-GPIO-driver blocks are not worth the extra complexity as of today? I actually started the current block gpio patches to support this kind of use case. :-) Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/6 v14] gpio: Add a block GPIO API to gpiolib
On 27/01/13 14:19, Stijn Devriendt wrote: +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. Is there anything holding you back from letting gpio_block_create() do the request for all the pins? It's analoguous to plain GPIOs: They exist, but are not requested (by whom?) by default. Also, wouldn't it make sense to have a gpio_block_direction_input() and _output() variant? On the other hand, for things like I2C and SPI emulation, some pins will naturally be always output (like clock lines) while other could be switched between in and output (like the i2c data line). Right. Current implementation emphasizes on switching, not direction or other convenience functions, which could be added, nevertheless. Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
On 27/01/13 14:07, Stijn Devriendt wrote: +Example: + +blockgpio { +compatible = linux,gpio-block; + +block0 { +gpios = gpio 3 0 0, +gpio 3 1 0; +}; +block1 { +gpios = gpio 4 1 0, +gpio 4 3 0, +gpio 4 2 0, +gpio 4 4 0, +gpio 4 5 0, +gpio 4 6 0, +gpio 4 7 0, +gpio 4 8 0, +gpio 4 9 0, +gpio 4 10 0, +gpio 4 19 0; +}; +}; How do you see bindings for other kinds of drivers? In my patchset, it's possible for other drivers to use gpio-blocks. One example we have is a power sequencer with 2 pins attached to GPIO pins. These 2 pins form a 2bit word to select power margining. These 2 pins need to be set synchronously (as otherwise when going from profile 0 to profile 3 you pass either profile 1 or profile 2 which could be bad for hardware) In the device-tree this is specified as: powr@0x20 { // other properties gpios = gpio 4 0 gpio 5 0; }; Is this kind of integration also possible? You can reference the gpio block via a phandle, e.g.: blockgpio { compatible = linux,gpio-block; selector1 { gpios = gpio 4 0, gpio 5 0; }; }; powr@0x20 { // ... gpios = selector1; }; In the driver, you can get the gpio block like this: block = gpio_block_find_by_name(of_parse_phandle(powr, gpios, 0)-name); (Simplified by removed error/NULL handling!) If this turns out to be a common pattern, I can add a convenience get function for this. Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
On 01/24/2013 01:02 PM, Stijn Devriendt wrote: >> +static void lpc32xx_gpio_set_block_p3(struct gpio_chip *chip, >> + unsigned long mask, >> + unsigned long values) >> +{ >> + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); >> + u32 set_bits = values & mask; >> + u32 clr_bits = ~values & mask; >> + >> + /* States of GPIO 0-5 start at bit 25 */ >> + set_bits <<= 25; >> + clr_bits <<= 25; >> + >> + /* Note: On LPC32xx, GPOs can only be set at once or cleared at once, >> +* but not set and cleared at once >> +*/ >> + if (set_bits) >> + __raw_writel(set_bits, group->gpio_grp->outp_set); >> + if (clr_bits) >> + __raw_writel(clr_bits, group->gpio_grp->outp_clr); >> +} >> + > > In my patch, I go out of the way of this kind of thing for a simple reason: > You may generate incorrect timing by doing this. You are right, certain things like synchronous on+off is not really possible. However, the above at least supports switching on simulaneously, and switching off simultaneously, which is an improvement in certain cases (and this certain hardware part doesn't support more). Maybe this certain driver behaviour can be documented even better than just in the driver source. If there is consensus that everything else in the patch set is settled, and we just don't want to support behaviour like the above - well, we can still drop it. Thanks for the note, Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
On 01/24/2013 01:02 PM, Stijn Devriendt wrote: +static void lpc32xx_gpio_set_block_p3(struct gpio_chip *chip, + unsigned long mask, + unsigned long values) +{ + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + u32 set_bits = values mask; + u32 clr_bits = ~values mask; + + /* States of GPIO 0-5 start at bit 25 */ + set_bits = 25; + clr_bits = 25; + + /* Note: On LPC32xx, GPOs can only be set at once or cleared at once, +* but not set and cleared at once +*/ + if (set_bits) + __raw_writel(set_bits, group-gpio_grp-outp_set); + if (clr_bits) + __raw_writel(clr_bits, group-gpio_grp-outp_clr); +} + In my patch, I go out of the way of this kind of thing for a simple reason: You may generate incorrect timing by doing this. You are right, certain things like synchronous on+off is not really possible. However, the above at least supports switching on simulaneously, and switching off simultaneously, which is an improvement in certain cases (and this certain hardware part doesn't support more). Maybe this certain driver behaviour can be documented even better than just in the driver source. If there is consensus that everything else in the patch set is settled, and we just don't want to support behaviour like the above - well, we can still drop it. Thanks for the note, Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 3/6 v14] gpio: Add userland device interface to block GPIO
On 23/01/13 02:03, Jonathan Corbet wrote: > On Tue, 22 Jan 2013 13:06:41 +0100 > Roland Stigge wrote: > >> This patch adds a character device interface to the block GPIO system. > > So I was looking at this, and a couple of things caught my eye... Good points you mentioned. Will address them on a subsequent update. Thanks, Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 3/6 v14] gpio: Add userland device interface to block GPIO
On 23/01/13 02:03, Jonathan Corbet wrote: On Tue, 22 Jan 2013 13:06:41 +0100 Roland Stigge sti...@antcom.de wrote: This patch adds a character device interface to the block GPIO system. So I was looking at this, and a couple of things caught my eye... Good points you mentioned. Will address them on a subsequent update. Thanks, Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 2/6 v14] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their "exported" + boolean attribute must be set to "1". Then, the attribute "values" is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i < block->ngpio; i++) - if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + if ((block->cur_mask & BIT(i)) && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip->label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", block->ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", gpio_block_get(block, block->cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + mutex_lock(_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block->cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", block->cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + block->cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysf
[PATCH 4/6 v14] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - _attr_value.attr, - _attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, "%d\n", chip->base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, "%s\n", chip->label ? : ""); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, "%u\n", chip->ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - _attr_base.attr, - _attr_label.attr, - _attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = "gpio", .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = "gpiochip", + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(>kobj, _attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, _attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in g
[PATCH 0/6 v14] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge Tested by: Wolfgang Grandegger -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Applies to v3.8-rc4 Changes since v13: * Adjusted __raw_readl to readl_relaxed, __raw_writel to writel_relaxed (forward porting of pinctrl-at91.c) * Adjusted to mainline change: Removed __devinit and __devinitdata Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch <1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on "exported" and "values" attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu, Mark Rutland and Nicolas Ferre for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Kconfig |2 drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-ge.c| 29 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 driv
[PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge For pinctrl-at91.c: Acked-by: Nicolas Ferre --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool "MPC512x/MPC8xxx GPIO support" depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask & 0x; + unsigned long mask_oh = mask >> 16; + + unsigned long values_ol = values & mask_ol; + unsigned long values_oh = (values >> 16) & mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol << 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh << 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = >gpio_chip; gpio_chip->direction_input = em_gio_direction_input; gpio_chip->get = em_gio_get; + gpio_chip->get_block = em_gio_get_block; gpio_chip->direction_output = em_gio_direction_output; gpio_chip->set = em_gio_set; + gpio_chip->set_block = em_gio_set_block; gpio_chip->to_irq = em_gio_to_irq; gpio_chip->label = name; gpio_chip->owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip->regs + GEF_GPIO_IN) & mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip->regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data &= ~mask; + data |= values & mask; + +
[PATCH 3/6 v14] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/ +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: The /dev/ character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, ) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #define CREATE_TRACE_POINTS #include @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, _block_list, list) + if (i->miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block->gpio[index]); + int i; + + for (i = 0; i < index; i++) + if (gpio_to_irq(block->gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(>wait_queue); + block->got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in->i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block->irq_controlled = false; + block->got_int = false; + spin_lock_init(>lock); + init_waitqueue_head(>wait_queue); + f->private_data = block; + + for (i = 0; i < block->ngpio; i++) { + status = gpio_request(block->gpio[i], block->name); + if (status) + goto err1; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block->name, block); + if (status) + goto err2; + + block->irq_controlled = true; + } + } + + return 0; + +err1: + while (i > 0) { + i--; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block->gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f->
[PATCH 1/6 v14] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal "Block GPIO" API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i < block->ngpio; i++) + if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip *
[PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be "linux,gpio-block" + +Required subnodes: +- the name will be the registered name of the block +- property "gpios" is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = "linux,gpio-block"; + +block0 { +gpios = < 3 0 0>, +< 3 1 0>; +}; +block1 { +gpios = < 4 1 0>, +< 4 3 0>, +< 4 2 0>, +< 4 4 0>, +< 4 5 0>, +< 4 6 0>, +< 4 7 0>, +< 4 8 0>, +< 4 9 0>, +< 4 10 0>, +< 4 19 0>; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev->dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio < 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i < ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret < 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block->name); + if (IS_ERR(gb)) { + dev_err(>dev, + "Error creating GPIO block from device tree\n"); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret < 0) + goto err3; + + kfree(gpios); + dev_info(>dev, "Registered gpio block %s: %d gpios\n", +block->name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] = { + { .compatible = "linux,gpio-block", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = "gpio-block", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION("GPIO Block driver"); +MODULE_AUTHOR("R
[PATCH 1/6 v14] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal Block GPIO API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i block-ngpio; i++) + if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip
[PATCH 6/6 v14] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge sti...@antcom.de For pinctrl-at91.c: Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool MPC512x/MPC8xxx GPIO support depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask 0x; + unsigned long mask_oh = mask 16; + + unsigned long values_ol = values mask_ol; + unsigned long values_oh = (values 16) mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = p-gpio_chip; gpio_chip-direction_input = em_gio_direction_input; gpio_chip-get = em_gio_get; + gpio_chip-get_block = em_gio_get_block; gpio_chip-direction_output = em_gio_direction_output; gpio_chip-set = em_gio_set; + gpio_chip-set_block = em_gio_set_block; gpio_chip-to_irq = em_gio_to_irq; gpio_chip-label = name; gpio_chip-owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip-regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip-regs + GEF_GPIO_IN) mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip-regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data = ~mask; + data |= values mask; + + iowrite32be(data, reg); +} + static int __init gef_gpio_init(void) { struct
[PATCH 3/6 v14] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/gpioblock +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: The /dev/gpioblock character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, mask) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include linux/of_gpio.h #include linux/idr.h #include linux/slab.h +#include linux/uaccess.h +#include linux/poll.h #define CREATE_TRACE_POINTS #include trace/events/gpio.h @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, gpio_block_list, list) + if (i-miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block-gpio[index]); + int i; + + for (i = 0; i index; i++) + if (gpio_to_irq(block-gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(block-wait_queue); + block-got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in-i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block-irq_controlled = false; + block-got_int = false; + spin_lock_init(block-lock); + init_waitqueue_head(block-wait_queue); + f-private_data = block; + + for (i = 0; i block-ngpio; i++) { + status = gpio_request(block-gpio[i], block-name); + if (status) + goto err1; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block-name, block); + if (status) + goto err2; + + block-irq_controlled = true; + } + } + + return 0; + +err1: + while (i 0) { + i--; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block-gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f
[PATCH 5/6 v14] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be linux,gpio-block + +Required subnodes: +- the name will be the registered name of the block +- property gpios is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = linux,gpio-block; + +block0 { +gpios = gpio 3 0 0, +gpio 3 1 0; +}; +block1 { +gpios = gpio 4 1 0, +gpio 4 3 0, +gpio 4 2 0, +gpio 4 4 0, +gpio 4 5 0, +gpio 4 6 0, +gpio 4 7 0, +gpio 4 8 0, +gpio 4 9 0, +gpio 4 10 0, +gpio 4 19 0; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge sti...@antcom.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/platform_device.h +#include linux/gpio.h +#include linux/of.h +#include linux/of_gpio.h +#include linux/module.h +#include linux/slab.h +#include linux/err.h + +static int gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev-dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block-name); + if (IS_ERR(gb)) { + dev_err(pdev-dev, + Error creating GPIO block from device tree\n); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret 0) + goto err3; + + kfree(gpios); + dev_info(pdev-dev, Registered gpio block %s: %d gpios\n, +block-name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] = { + { .compatible = linux,gpio-block, }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = gpio-block, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION(GPIO Block driver); +MODULE_AUTHOR(Roland Stigge sti...@antcom.de
[PATCH 0/6 v14] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge sti...@antcom.de Tested by: Wolfgang Grandegger w...@grandegger.com -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Applies to v3.8-rc4 Changes since v13: * Adjusted __raw_readl to readl_relaxed, __raw_writel to writel_relaxed (forward porting of pinctrl-at91.c) * Adjusted to mainline change: Removed __devinit and __devinitdata Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch 1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on exported and values attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu, Mark Rutland and Nicolas Ferre for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Kconfig |2 drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-ge.c| 29 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 drivers/gpio/gpio
[PATCH 2/6 v14] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their exported + boolean attribute must be set to 1. Then, the attribute values is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i block-ngpio; i++) - if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + if ((block-cur_mask BIT(i)) + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip-label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, %u\n, block-ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, gpio_block_get(block, block-cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, value); + if (status == 0) { + mutex_lock(sysfs_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block-cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(sysfs_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, block-cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, mask); + if (status == 0) { + block-cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysfs_dirent *sd = NULL; + + mutex_lock(sysfs_lock); + dev = class_find_device
[PATCH 4/6 v14] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - dev_attr_value.attr, - dev_attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, %d\n, chip-base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, %s\n, chip-label ? : ); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, %u\n, chip-ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - dev_attr_base.attr, - dev_attr_label.attr, - dev_attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = gpio, .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = gpiochip, + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(dev-kobj, gpio_attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, dev_attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in gpiolib_sysfs_init() ... here
Re: [PATCH RESEND 1/6 v13] gpio: Add a block GPIO API to gpiolib
Hi Stijn, On 01/18/2013 01:13 PM, Stijn Devriendt wrote: > Hi Roland, > > This mail has been long overdue due to issues with some internal > permission-tool. > Just to be clear, this is not a competing implementation, it's what we > currently use as-is. I'm just posting this as a reference to see if > perhaps more concepts could be reused. It's based on a 2.6.32 kernel. > > It includes: > - labels in sysfs (to provide useful names to userspace) > - gpio group support > - exporting individual/groups of gpios dictated by platform-data or > device-tree > - open-drain support (different from mainline) > - examplary support for multi-gpio to pcf8575 driver > - gpio_direction_output_keep() function that prevents toggling when > changing direction > > Provided-as-is-by: Stijn Devriendt Thanks for posting. Except for open-drain support, everything in the above list is supported in the last posted version of block GPIO. So please tell if there are certain details you would like to discuss about or need an alternative implementation. Thanks in advance, Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RESEND 1/6 v13] gpio: Add a block GPIO API to gpiolib
Hi Stijn, On 01/18/2013 01:13 PM, Stijn Devriendt wrote: Hi Roland, This mail has been long overdue due to issues with some internal permission-tool. Just to be clear, this is not a competing implementation, it's what we currently use as-is. I'm just posting this as a reference to see if perhaps more concepts could be reused. It's based on a 2.6.32 kernel. It includes: - labels in sysfs (to provide useful names to userspace) - gpio group support - exporting individual/groups of gpios dictated by platform-data or device-tree - open-drain support (different from mainline) - examplary support for multi-gpio to pcf8575 driver - gpio_direction_output_keep() function that prevents toggling when changing direction Provided-as-is-by: Stijn Devriendt sdevr...@cisco.com Thanks for posting. Except for open-drain support, everything in the above list is supported in the last posted version of block GPIO. So please tell if there are certain details you would like to discuss about or need an alternative implementation. Thanks in advance, Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH RESEND 6/6 v13] gpio: Add block gpio to several gpio drivers
On 01/15/2013 02:18 PM, Nicolas Ferre wrote: >> --- linux-2.6.orig/drivers/pinctrl/pinctrl-at91.c >> +++ linux-2.6/drivers/pinctrl/pinctrl-at91.c >> @@ -49,6 +49,7 @@ struct at91_gpio_chip { >> struct clk*clock;/* associated clock */ >> struct irq_domain*domain;/* associated irq domain */ >> struct at91_pinctrl_mux_ops *ops;/* ops */ >> +unsigned longmask_cache;/* cached mask for block gpio */ >> }; >> >> #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, >> chip) >> @@ -1125,6 +1126,32 @@ static void at91_gpio_set(struct gpio_ch >> writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); >> } >> >> +static unsigned long at91_gpio_get_block(struct gpio_chip *chip, >> + unsigned long mask) >> +{ >> +struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); >> +void __iomem *pio = at91_gpio->regbase; >> +u32 pdsr; >> + >> +pdsr = __raw_readl(pio + PIO_PDSR); > > Maybe you should use readl_relaxed() here as it is used in the > at91_gpio_[get|set]() functions. Thanks for the note! Seem to have missed this when forward porting in pinctrl-at91.c was due. Will include the respective change in a subsequent update. Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RESEND 2/6 v13] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their "exported" + boolean attribute must be set to "1". Then, the attribute "values" is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i < block->ngpio; i++) - if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + if ((block->cur_mask & BIT(i)) && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip->label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", block->ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", gpio_block_get(block, block->cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + mutex_lock(_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block->cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", block->cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + block->cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysf
[PATCH RESEND 1/6 v13] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal "Block GPIO" API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i < block->ngpio; i++) + if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip *
[PATCH RESEND 3/6 v13] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/ +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: The /dev/ character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, ) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #define CREATE_TRACE_POINTS #include @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, _block_list, list) + if (i->miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block->gpio[index]); + int i; + + for (i = 0; i < index; i++) + if (gpio_to_irq(block->gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(>wait_queue); + block->got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in->i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block->irq_controlled = false; + block->got_int = false; + spin_lock_init(>lock); + init_waitqueue_head(>wait_queue); + f->private_data = block; + + for (i = 0; i < block->ngpio; i++) { + status = gpio_request(block->gpio[i], block->name); + if (status) + goto err1; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block->name, block); + if (status) + goto err2; + + block->irq_controlled = true; + } + } + + return 0; + +err1: + while (i > 0) { + i--; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block->gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f->
[PATCH RESEND 6/6 v13] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool "MPC512x/MPC8xxx GPIO support" depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask & 0x; + unsigned long mask_oh = mask >> 16; + + unsigned long values_ol = values & mask_ol; + unsigned long values_oh = (values >> 16) & mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol << 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh << 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = >gpio_chip; gpio_chip->direction_input = em_gio_direction_input; gpio_chip->get = em_gio_get; + gpio_chip->get_block = em_gio_get_block; gpio_chip->direction_output = em_gio_direction_output; gpio_chip->set = em_gio_set; + gpio_chip->set_block = em_gio_set_block; gpio_chip->to_irq = em_gio_to_irq; gpio_chip->label = name; gpio_chip->owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip->regs + GEF_GPIO_IN) & mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip->regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data &= ~mask; + data |= values & mask; + + iowrite32be(data, reg); +} + static in
[PATCH RESEND 0/6 v13] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge Tested by: Wolfgang Grandegger -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch <1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on "exported" and "values" attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu and Mark Rutland for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Kconfig |2 drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-ge.c| 29 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 drivers/gpio/gpio-lpc32xx.c | 82 + drivers/gpio/gpio-max730x.c | 61 + drivers/gpio/gpio-max732x.c | 59 + drivers/gpio/gpio-mc33880.c | 16 dri
[PATCH RESEND 5/6 v13] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be "linux,gpio-block" + +Required subnodes: +- the name will be the registered name of the block +- property "gpios" is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = "linux,gpio-block"; + +block0 { +gpios = < 3 0 0>, +< 3 1 0>; +}; +block1 { +gpios = < 4 1 0>, +< 4 3 0>, +< 4 2 0>, +< 4 4 0>, +< 4 5 0>, +< 4 6 0>, +< 4 7 0>, +< 4 8 0>, +< 4 9 0>, +< 4 10 0>, +< 4 19 0>; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int __devinit gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev->dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio < 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i < ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret < 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block->name); + if (IS_ERR(gb)) { + dev_err(>dev, + "Error creating GPIO block from device tree\n"); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret < 0) + goto err3; + + kfree(gpios); + dev_info(>dev, "Registered gpio block %s: %d gpios\n", +block->name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] __devinitdata = { + { .compatible = "linux,gpio-block", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = "gpio-block", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION("GPIO Block driver");
[PATCH RESEND 4/6 v13] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - _attr_value.attr, - _attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, "%d\n", chip->base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, "%s\n", chip->label ? : ""); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, "%u\n", chip->ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - _attr_base.attr, - _attr_label.attr, - _attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = "gpio", .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = "gpiochip", + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(>kobj, _attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, _attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in g
[PATCH RESEND 4/6 v13] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - dev_attr_value.attr, - dev_attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, %d\n, chip-base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, %s\n, chip-label ? : ); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, %u\n, chip-ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - dev_attr_base.attr, - dev_attr_label.attr, - dev_attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = gpio, .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = gpiochip, + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(dev-kobj, gpio_attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, dev_attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in gpiolib_sysfs_init() ... here
[PATCH RESEND 5/6 v13] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be linux,gpio-block + +Required subnodes: +- the name will be the registered name of the block +- property gpios is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = linux,gpio-block; + +block0 { +gpios = gpio 3 0 0, +gpio 3 1 0; +}; +block1 { +gpios = gpio 4 1 0, +gpio 4 3 0, +gpio 4 2 0, +gpio 4 4 0, +gpio 4 5 0, +gpio 4 6 0, +gpio 4 7 0, +gpio 4 8 0, +gpio 4 9 0, +gpio 4 10 0, +gpio 4 19 0; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge sti...@antcom.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/platform_device.h +#include linux/gpio.h +#include linux/of.h +#include linux/of_gpio.h +#include linux/module.h +#include linux/slab.h +#include linux/err.h + +static int __devinit gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev-dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block-name); + if (IS_ERR(gb)) { + dev_err(pdev-dev, + Error creating GPIO block from device tree\n); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret 0) + goto err3; + + kfree(gpios); + dev_info(pdev-dev, Registered gpio block %s: %d gpios\n, +block-name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] __devinitdata = { + { .compatible = linux,gpio-block, }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = gpio-block, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION(GPIO Block driver); +MODULE_AUTHOR(Roland
[PATCH RESEND 0/6 v13] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge sti...@antcom.de Tested by: Wolfgang Grandegger w...@grandegger.com -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch 1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on exported and values attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu and Mark Rutland for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Kconfig |2 drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-ge.c| 29 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 drivers/gpio/gpio-lpc32xx.c | 82 + drivers/gpio/gpio-max730x.c | 61 + drivers/gpio/gpio-max732x.c | 59 + drivers/gpio/gpio-mc33880.c | 16
[PATCH RESEND 3/6 v13] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/gpioblock +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: The /dev/gpioblock character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, mask) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include linux/of_gpio.h #include linux/idr.h #include linux/slab.h +#include linux/uaccess.h +#include linux/poll.h #define CREATE_TRACE_POINTS #include trace/events/gpio.h @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, gpio_block_list, list) + if (i-miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block-gpio[index]); + int i; + + for (i = 0; i index; i++) + if (gpio_to_irq(block-gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(block-wait_queue); + block-got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in-i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block-irq_controlled = false; + block-got_int = false; + spin_lock_init(block-lock); + init_waitqueue_head(block-wait_queue); + f-private_data = block; + + for (i = 0; i block-ngpio; i++) { + status = gpio_request(block-gpio[i], block-name); + if (status) + goto err1; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block-name, block); + if (status) + goto err2; + + block-irq_controlled = true; + } + } + + return 0; + +err1: + while (i 0) { + i--; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block-gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f
[PATCH RESEND 6/6 v13] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge sti...@antcom.de --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool MPC512x/MPC8xxx GPIO support depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask 0x; + unsigned long mask_oh = mask 16; + + unsigned long values_ol = values mask_ol; + unsigned long values_oh = (values 16) mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = p-gpio_chip; gpio_chip-direction_input = em_gio_direction_input; gpio_chip-get = em_gio_get; + gpio_chip-get_block = em_gio_get_block; gpio_chip-direction_output = em_gio_direction_output; gpio_chip-set = em_gio_set; + gpio_chip-set_block = em_gio_set_block; gpio_chip-to_irq = em_gio_to_irq; gpio_chip-label = name; gpio_chip-owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip-regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip-regs + GEF_GPIO_IN) mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip-regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data = ~mask; + data |= values mask; + + iowrite32be(data, reg); +} + static int __init gef_gpio_init(void) { struct device_node *np; @@ -125,6 +148,8 @@ static int __init gef_gpio_init(void
[PATCH RESEND 2/6 v13] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their exported + boolean attribute must be set to 1. Then, the attribute values is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i block-ngpio; i++) - if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + if ((block-cur_mask BIT(i)) + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip-label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, %u\n, block-ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, gpio_block_get(block, block-cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, value); + if (status == 0) { + mutex_lock(sysfs_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block-cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(sysfs_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, block-cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, mask); + if (status == 0) { + block-cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysfs_dirent *sd = NULL; + + mutex_lock(sysfs_lock); + dev = class_find_device
[PATCH RESEND 1/6 v13] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal Block GPIO API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i block-ngpio; i++) + if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip
Re: [PATCH RESEND 6/6 v13] gpio: Add block gpio to several gpio drivers
On 01/15/2013 02:18 PM, Nicolas Ferre wrote: --- linux-2.6.orig/drivers/pinctrl/pinctrl-at91.c +++ linux-2.6/drivers/pinctrl/pinctrl-at91.c @@ -49,6 +49,7 @@ struct at91_gpio_chip { struct clk*clock;/* associated clock */ struct irq_domain*domain;/* associated irq domain */ struct at91_pinctrl_mux_ops *ops;/* ops */ +unsigned longmask_cache;/* cached mask for block gpio */ }; #define to_at91_gpio_chip(c) container_of(c, struct at91_gpio_chip, chip) @@ -1125,6 +1126,32 @@ static void at91_gpio_set(struct gpio_ch writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); } +static unsigned long at91_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ +struct at91_gpio_chip *at91_gpio = to_at91_gpio_chip(chip); +void __iomem *pio = at91_gpio-regbase; +u32 pdsr; + +pdsr = __raw_readl(pio + PIO_PDSR); Maybe you should use readl_relaxed() here as it is used in the at91_gpio_[get|set]() functions. Thanks for the note! Seem to have missed this when forward porting in pinctrl-at91.c was due. Will include the respective change in a subsequent update. Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 6/6 v13] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool "MPC512x/MPC8xxx GPIO support" depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) & mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask & 0x; + unsigned long mask_oh = mask >> 16; + + unsigned long values_ol = values & mask_ol; + unsigned long values_oh = (values >> 16) & mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol << 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh << 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = >gpio_chip; gpio_chip->direction_input = em_gio_direction_input; gpio_chip->get = em_gio_get; + gpio_chip->get_block = em_gio_get_block; gpio_chip->direction_output = em_gio_direction_output; gpio_chip->set = em_gio_set; + gpio_chip->set_block = em_gio_set_block; gpio_chip->to_irq = em_gio_to_irq; gpio_chip->label = name; gpio_chip->owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip->regs + GEF_GPIO_IN) & mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip->regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data &= ~mask; + data |= values & mask; + + iowrite32be(data, reg); +} + static in
[PATCH 1/6 v13] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal "Block GPIO" API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i < block->ngpio; i++) + if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip *
[PATCH 2/6 v13] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their "exported" + boolean attribute must be set to "1". Then, the attribute "values" is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i < block->ngpio; i++) - if (!test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) + if ((block->cur_mask & BIT(i)) && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip->label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", block->ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", gpio_block_get(block, block->cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + mutex_lock(_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block->cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? "0x%08lx\n" : + "0x%016lx\n", block->cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, ); + if (status == 0) { + block->cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysf
[PATCH 4/6 v13] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - _attr_value.attr, - _attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, "%d\n", chip->base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, "%s\n", chip->label ? : ""); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, "%u\n", chip->ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - _attr_base.attr, - _attr_label.attr, - _attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = "gpio", .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = "gpiochip", + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(>kobj, _attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, _attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in g
[PATCH 0/6 v13] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge Tested by: Wolfgang Grandegger -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch <1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on "exported" and "values" attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu and Mark Rutland for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-lpc32xx.c | 82 + drivers/gpio/gpio-max730x.c | 61 + drivers/gpio/gpio-max732x.c | 59 + drivers/gpio/gpio-mm-lantiq.c | 22 drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 drivers/gpio/gpio-pch.c | 27 dr
[PATCH 3/6 v13] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/ +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge +Description: The /dev/ character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, ) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #define CREATE_TRACE_POINTS #include @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, _block_list, list) + if (i->miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block->gpio[index]); + int i; + + for (i = 0; i < index; i++) + if (gpio_to_irq(block->gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(>wait_queue); + block->got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in->i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block->irq_controlled = false; + block->got_int = false; + spin_lock_init(>lock); + init_waitqueue_head(>wait_queue); + f->private_data = block; + + for (i = 0; i < block->ngpio; i++) { + status = gpio_request(block->gpio[i], block->name); + if (status) + goto err1; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block->name, block); + if (status) + goto err2; + + block->irq_controlled = true; + } + } + + return 0; + +err1: + while (i > 0) { + i--; + + irq = gpio_to_irq(block->gpio[i]); + if (irq >= 0 && + !test_bit(FLAG_IS_OUT, _desc[block->gpio[i]].flags) && + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block->gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f->
[PATCH 5/6 v13] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be "linux,gpio-block" + +Required subnodes: +- the name will be the registered name of the block +- property "gpios" is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = "linux,gpio-block"; + +block0 { +gpios = < 3 0 0>, +< 3 1 0>; +}; +block1 { +gpios = < 4 1 0>, +< 4 3 0>, +< 4 2 0>, +< 4 4 0>, +< 4 5 0>, +< 4 6 0>, +< 4 7 0>, +< 4 8 0>, +< 4 9 0>, +< 4 10 0>, +< 4 19 0>; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int __devinit gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev->dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio < 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i < ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret < 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block->name); + if (IS_ERR(gb)) { + dev_err(>dev, + "Error creating GPIO block from device tree\n"); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret < 0) + goto err3; + + kfree(gpios); + dev_info(>dev, "Registered gpio block %s: %d gpios\n", +block->name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] __devinitdata = { + { .compatible = "linux,gpio-block", }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = "gpio-block", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION("GPIO Block driver");
[PATCH 3/6 v13] gpio: Add userland device interface to block GPIO
This patch adds a character device interface to the block GPIO system. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/dev-gpioblock | 34 drivers/gpio/gpiolib.c | 225 +++- include/linux/gpio.h| 13 + 3 files changed, 271 insertions(+), 1 deletion(-) --- /dev/null +++ linux-2.6/Documentation/ABI/testing/dev-gpioblock @@ -0,0 +1,34 @@ +What: /dev/gpioblock +Date: Nov 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: The /dev/gpioblock character device node provides userspace + access to GPIO blocks, named exactly as the block, e.g. + /dev/block0. + + Reading: + When reading sizeof(unsigned long) bytes from the device, the + current state of the block, masked by the current mask (see + below) can be obtained as a word. When the device is opened + with O_NONBLOCK, read() always returns with data immediately, + otherwise it blocks until data is available, see IRQ handling + below. + + Writing: + By writing sizeof(unsigned long) bytes to the device, the + current state of the block can be set. This operation is + masked by the current mask (see below). + + IRQ handling: + When one or more IRQs in the block are IRQ capable, you can + poll() on the device to check/wait for this IRQ. If no IRQ + is available, poll() returns -ENOSYS and userspace needs to + (busy) poll itself if necessary. + + Setting the mask (default: all bits set): + By doing an ioctl(fd, 0, mask) with an unsigned long mask, the + current mask for read and write operations on this gpio block + can be set. + + See also Documentation/gpio.txt for an explanation of block + GPIO. --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -11,6 +11,8 @@ #include linux/of_gpio.h #include linux/idr.h #include linux/slab.h +#include linux/uaccess.h +#include linux/poll.h #define CREATE_TRACE_POINTS #include trace/events/gpio.h @@ -2243,6 +2245,207 @@ struct gpio_block *gpio_block_find_by_na } EXPORT_SYMBOL_GPL(gpio_block_find_by_name); +static struct gpio_block *gpio_block_find_by_minor(int minor) +{ + struct gpio_block *i; + + list_for_each_entry(i, gpio_block_list, list) + if (i-miscdev.minor == minor) + return i; + return NULL; +} + +static bool gpio_block_is_irq_duplicate(struct gpio_block *block, int index) +{ + int irq = gpio_to_irq(block-gpio[index]); + int i; + + for (i = 0; i index; i++) + if (gpio_to_irq(block-gpio[i]) == irq) + return true; + return false; +} + +static irqreturn_t gpio_block_irq_handler(int irq, void *dev) +{ + struct gpio_block *block = dev; + + wake_up_interruptible(block-wait_queue); + block-got_int = true; + + return IRQ_HANDLED; +} + +static int gpio_block_fop_open(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = gpio_block_find_by_minor(MINOR(in-i_rdev)); + int status; + int irq; + + if (!block) + return -ENOENT; + + block-irq_controlled = false; + block-got_int = false; + spin_lock_init(block-lock); + init_waitqueue_head(block-wait_queue); + f-private_data = block; + + for (i = 0; i block-ngpio; i++) { + status = gpio_request(block-gpio[i], block-name); + if (status) + goto err1; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) { + status = request_irq(irq, gpio_block_irq_handler, +IRQF_SHARED, +block-name, block); + if (status) + goto err2; + + block-irq_controlled = true; + } + } + + return 0; + +err1: + while (i 0) { + i--; + + irq = gpio_to_irq(block-gpio[i]); + if (irq = 0 + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags) + !gpio_block_is_irq_duplicate(block, i)) + free_irq(irq, block); +err2: + gpio_free(block-gpio[i]); + } + return status; +} + +static int gpio_block_fop_release(struct inode *in, struct file *f) +{ + int i; + struct gpio_block *block = (struct gpio_block *)f
[PATCH 5/6 v13] gpio: Add device tree support to block GPIO API
This patch adds device tree support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 ++ drivers/gpio/Makefile |1 drivers/gpio/gpioblock-of.c | 100 ++ 3 files changed, 137 insertions(+) --- /dev/null +++ linux-2.6/Documentation/devicetree/bindings/gpio/gpio-block.txt @@ -0,0 +1,36 @@ +Block GPIO definition += + +This binding specifies arbitrary blocks of gpios, combining gpios from one or +more GPIO controllers together, to form a word for r/w access. + +Required property: +- compatible: must be linux,gpio-block + +Required subnodes: +- the name will be the registered name of the block +- property gpios is a list of gpios for the respective block + +Example: + +blockgpio { +compatible = linux,gpio-block; + +block0 { +gpios = gpio 3 0 0, +gpio 3 1 0; +}; +block1 { +gpios = gpio 4 1 0, +gpio 4 3 0, +gpio 4 2 0, +gpio 4 4 0, +gpio 4 5 0, +gpio 4 6 0, +gpio 4 7 0, +gpio 4 8 0, +gpio 4 9 0, +gpio 4 10 0, +gpio 4 19 0; +}; +}; --- linux-2.6.orig/drivers/gpio/Makefile +++ linux-2.6/drivers/gpio/Makefile @@ -5,6 +5,7 @@ ccflags-$(CONFIG_DEBUG_GPIO)+= -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o obj-$(CONFIG_OF_GPIO) += gpiolib-of.o obj-$(CONFIG_GPIO_ACPI)+= gpiolib-acpi.o +obj-$(CONFIG_OF_GPIO) += gpioblock-of.o # Device drivers. Generally keep list sorted alphabetically obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o --- /dev/null +++ linux-2.6/drivers/gpio/gpioblock-of.c @@ -0,0 +1,100 @@ +/* + * OF implementation for Block GPIO + * + * Copyright (C) 2012 Roland Stigge sti...@antcom.de + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include linux/kernel.h +#include linux/module.h +#include linux/platform_device.h +#include linux/gpio.h +#include linux/of.h +#include linux/of_gpio.h +#include linux/module.h +#include linux/slab.h +#include linux/err.h + +static int __devinit gpioblock_of_probe(struct platform_device *pdev) +{ + struct device_node *block; + unsigned *gpios; + int ngpio; + int ret; + struct gpio_block *gb; + + for_each_available_child_of_node(pdev-dev.of_node, block) { + int i; + + ngpio = of_gpio_count(block); + if (ngpio 1) { + ret = -ENODEV; + goto err1; + } + + gpios = kzalloc(ngpio * sizeof(*gpios), GFP_KERNEL); + if (!gpios) { + ret = -ENOMEM; + goto err1; + } + + for (i = 0; i ngpio; i++) { + ret = of_get_gpio(block, i); + if (ret 0) + goto err2; /* expect -EPROBE_DEFER */ + gpios[i] = ret; + } + gb = gpio_block_create(gpios, ngpio, block-name); + if (IS_ERR(gb)) { + dev_err(pdev-dev, + Error creating GPIO block from device tree\n); + ret = PTR_ERR(gb); + goto err2; + } + ret = gpio_block_register(gb); + if (ret 0) + goto err3; + + kfree(gpios); + dev_info(pdev-dev, Registered gpio block %s: %d gpios\n, +block-name, ngpio); + } + return 0; + +err3: + gpio_block_free(gb); +err2: + kfree(gpios); +err1: + of_node_put(block); + return ret; +} + +#ifdef CONFIG_OF +static struct of_device_id gpioblock_of_match[] __devinitdata = { + { .compatible = linux,gpio-block, }, + { }, +}; +MODULE_DEVICE_TABLE(of, gpioblock_of_match); +#endif + +static struct platform_driver gpioblock_of_driver = { + .driver = { + .name = gpio-block, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(gpioblock_of_match), + + }, + .probe = gpioblock_of_probe, +}; + +module_platform_driver(gpioblock_of_driver); + +MODULE_DESCRIPTION(GPIO Block driver); +MODULE_AUTHOR(Roland
[PATCH 0/6 v13] gpio: Add block GPIO
This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge sti...@antcom.de Tested by: Wolfgang Grandegger w...@grandegger.com -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v12: * Added support for gpio drivers ge, ks8695, mc33880, ml-ioh, mpc5200 and mpc8xxx * Added support for pinctrl driver at91 Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation * Fixed mask setting via sysfs * Device interface: declare gpio_block_fop_poll() static Changes since v10: * gpioblock-of.c: Catch 1 specified GPIOs * gpioblock-of.c: Fixed memory leak in probe()'s error path * gpioblock-of.c: Fixed block node's refcount via of_node_put() * Added driver support for samsung, mm-lantiq and sa1100 * Added driver support for at91 (by Wolfgang Grandegger) * Added pinctrl driver support for pinctl-nomadik Changed since v9: * Changed IRQ flags for device interface's poll() from IRQF_TRIGGER_FALLING to IRQF_SHARED * Use block name on gpio_request * Added spinlock for ISR manipulated data (dev interface / poll()) Changed since v8: * Added poll() function to dev interface for IRQ handling * Fixed gpio_block_register() in case of missing CONFIG_GPIO_SYSFS * Fixed mask handling in sysfs interface * Fixed get_user/put_user pointer (cast) Changes since v7: * Fixed error in API documentation (name arg missing in prototype) * Fixed compile error if sysfs is missing: Moved gpio_block_is_output() out of sysfs-ifdef * Added error handling to gpio_block_register() * Added mask attribute to sysfs (although dev interface exists now) Changes since v6: * Changed realloc to list handling * Added mask to kernel API * Added device interface as userspace API * Changed sizeof() to BITS_PER_LONG * Fixed multiline comment style * Documented direction setting by the user * Documented order of handled chips in case of multiple chips in one block Changes since v5: * Documented sysfs: elaborated on exported and values attributes * Documented sysfs: gpiochip is a separate class now * Aggregated driver support patches for block gpio into one single patch * Added gpio block driver support for twl6040 and pch Changes since v4: * Documented word width * Bugfix: export/unexport on register/unregister * Using default dev_attrs for gpio_block_class * Fix gpiolib: race condition on device creation * Added driver support for ucb14500, vt8500, xilinx Changes since v3: * Added driver support for pca953x, em, pl061, max732x, pcf857x * Coding style improvements * Fixed krealloc memory leak in error case * sysfs: values in hex * Register blocks in a list * Narrowing lock scope * Use S_IWUSR and S_IRUGO instead of direct octal values * Use for_each_set_bit() * Change from unsigned to unsigned long for masks and values Changes since v2: * Added sysfs support * Added devicetree support * Added support for lpc32xx, generic * Added functions for GPIO block registration * Added more error checking * Bit remapping bugfix Changes since v1: * API change to 32/64 bit word, bit masks Thanks to Ryan Mallon, Linus Walleij, Stijn Devriendt, Jean-Christophe Plagniol-Villard, Mark Brown, Greg Kroah-Hartman, Grant Likely, Stefan Roese, Wolfgang Grandegger, Tobias Rutz, Fengguang Wu and Mark Rutland for reviewing and testing! Roland Stigge (6): gpio: Add a block GPIO API to gpiolib gpio: Add sysfs support to block GPIO API gpio: Add userland device interface to block GPIO gpiolib: Fix default attributes for class gpio: Add device tree support to block GPIO API gpio: Add block gpio to several gpio drivers Documentation/ABI/testing/dev-gpioblock | 34 Documentation/ABI/testing/sysfs-gpio | 31 Documentation/devicetree/bindings/gpio/gpio-block.txt | 36 Documentation/gpio.txt| 58 + drivers/gpio/Makefile |1 drivers/gpio/gpio-em.c| 23 drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-lpc32xx.c | 82 + drivers/gpio/gpio-max730x.c | 61 + drivers/gpio/gpio-max732x.c | 59 + drivers/gpio/gpio-mm-lantiq.c | 22 drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 drivers/gpio/gpio-pch.c | 27
[PATCH 2/6 v13] gpio: Add sysfs support to block GPIO API
This patch adds sysfs support to the block GPIO API. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 20 ++ drivers/gpio/gpiolib.c | 252 ++- include/asm-generic/gpio.h | 11 + include/linux/gpio.h | 15 ++ 4 files changed, 297 insertions(+), 1 deletion(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -25,3 +25,23 @@ Description: /label ... (r/o) descriptive, not necessarily unique /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1) +What: /sys/class/gpioblock/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Block GPIO devices are visible in sysfs as soon as they are registered + (e.g. via devicetree definition). For actual I/O use, their exported + boolean attribute must be set to 1. Then, the attribute values is + created and at the same time, the GPIOs in the block are requested for + exclusive use by sysfs. + +/sys/class/gpioblock + /BLOCKNAME ... for each GPIO block name + /ngpio ... (r/o) number of GPIOs in this group + /exported ... sysfs export state of this group (0, 1) + /value ... current value as 32 or 64 bit integer in hex + (only available if /exported is 1) + /mask ... current mask as 32 or 64 bit integer in hex + (only available if /exported is 1) --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -224,7 +224,8 @@ static bool gpio_block_is_output(struct int i; for (i = 0; i block-ngpio; i++) - if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + if ((block-cur_mask BIT(i)) + !test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) return false; return true; } @@ -1020,6 +1021,240 @@ static void gpiochip_unexport(struct gpi chip-label, status); } +static ssize_t gpio_block_ngpio_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, %u\n, block-ngpio); +} + +static ssize_t gpio_block_value_show(struct device *dev, +struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, gpio_block_get(block, block-cur_mask)); +} + +static ssize_t gpio_block_value_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long value; + + status = kstrtoul(buf, 0, value); + if (status == 0) { + mutex_lock(sysfs_lock); + if (gpio_block_is_output(block)) { + gpio_block_set(block, block-cur_mask, value); + status = size; + } else { + status = -EPERM; + } + mutex_unlock(sysfs_lock); + } + return status; +} + +static struct device_attribute +dev_attr_block_value = __ATTR(value, S_IWUSR | S_IRUGO, gpio_block_value_show, + gpio_block_value_store); + +static ssize_t gpio_block_mask_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const struct gpio_block *block = dev_get_drvdata(dev); + + return sprintf(buf, sizeof(unsigned long) == 4 ? 0x%08lx\n : + 0x%016lx\n, block-cur_mask); +} + +static ssize_t gpio_block_mask_store(struct device *dev, +struct device_attribute *attr, +const char *buf, size_t size) +{ + ssize_t status; + struct gpio_block *block = dev_get_drvdata(dev); + unsigned long mask; + + status = kstrtoul(buf, 0, mask); + if (status == 0) { + block-cur_mask = mask; + status = size; + } + return status; +} + +static struct device_attribute +dev_attr_block_mask = __ATTR(mask, S_IWUSR | S_IRUGO, gpio_block_mask_show, +gpio_block_mask_store); + +static struct class gpio_block_class; + +static int gpio_block_value_is_exported(struct gpio_block *block) +{ + struct device *dev; + struct sysfs_dirent *sd = NULL; + + mutex_lock(sysfs_lock); + dev = class_find_device
[PATCH 4/6 v13] gpiolib: Fix default attributes for class
There is a race condition between creating a gpio or gpiochip device and adding default attributes. This patch fixes this by defining the default attributes as dev_attrs of the class. For this, it was necessary to create a separate gpiochip_class besides gpio_class. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/ABI/testing/sysfs-gpio | 11 drivers/gpio/gpiolib.c | 78 ++- 2 files changed, 44 insertions(+), 45 deletions(-) --- linux-2.6.orig/Documentation/ABI/testing/sysfs-gpio +++ linux-2.6/Documentation/ABI/testing/sysfs-gpio @@ -20,6 +20,17 @@ Description: /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low /edge ... r/w as: none, falling, rising, both + +What: /sys/class/gpiochip/ +Date: October 2012 +KernelVersion: 3.7 +Contact: Roland Stigge sti...@antcom.de +Description: + + Each gpiochip is represented by a separate device having the following + attributes: + +/sys/class/gpiochip /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -362,9 +362,6 @@ static ssize_t gpio_value_store(struct d return status; } -static const DEVICE_ATTR(value, 0644, - gpio_value_show, gpio_value_store); - static irqreturn_t gpio_sysfs_irq(int irq, void *priv) { struct sysfs_dirent *value_sd = priv; @@ -585,19 +582,6 @@ static ssize_t gpio_active_low_store(str return status ? : size; } -static const DEVICE_ATTR(active_low, 0644, - gpio_active_low_show, gpio_active_low_store); - -static const struct attribute *gpio_attrs[] = { - dev_attr_value.attr, - dev_attr_active_low.attr, - NULL, -}; - -static const struct attribute_group gpio_attr_group = { - .attrs = (struct attribute **) gpio_attrs, -}; - /* * /sys/class/gpio/gpiochipN/ * /base ... matching gpio_chip.base (N) @@ -612,7 +596,6 @@ static ssize_t chip_base_show(struct dev return sprintf(buf, %d\n, chip-base); } -static DEVICE_ATTR(base, 0444, chip_base_show, NULL); static ssize_t chip_label_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -621,7 +604,6 @@ static ssize_t chip_label_show(struct de return sprintf(buf, %s\n, chip-label ? : ); } -static DEVICE_ATTR(label, 0444, chip_label_show, NULL); static ssize_t chip_ngpio_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -630,18 +612,6 @@ static ssize_t chip_ngpio_show(struct de return sprintf(buf, %u\n, chip-ngpio); } -static DEVICE_ATTR(ngpio, 0444, chip_ngpio_show, NULL); - -static const struct attribute *gpiochip_attrs[] = { - dev_attr_base.attr, - dev_attr_label.attr, - dev_attr_ngpio.attr, - NULL, -}; - -static const struct attribute_group gpiochip_attr_group = { - .attrs = (struct attribute **) gpiochip_attrs, -}; /* * /sys/class/gpio/export ... write-only @@ -720,11 +690,32 @@ static struct class_attribute gpio_class __ATTR_NULL, }; +static struct device_attribute gpio_attrs[] = { + __ATTR(active_low, 0644, gpio_active_low_show, gpio_active_low_store), + __ATTR(value, 0644, gpio_value_show, gpio_value_store), + __ATTR_NULL, +}; + static struct class gpio_class = { .name = gpio, .owner =THIS_MODULE, - .class_attrs = gpio_class_attrs, + .class_attrs = gpio_class_attrs, + .dev_attrs = gpio_attrs, +}; + +static struct device_attribute gpiochip_attrs[] = { + __ATTR(label, 0444, chip_label_show, NULL), + __ATTR(base, 0444, chip_base_show, NULL), + __ATTR(ngpio, 0444, chip_ngpio_show, NULL), + __ATTR_NULL, +}; + +static struct class gpiochip_class = { + .name = gpiochip, + .owner =THIS_MODULE, + + .dev_attrs =gpiochip_attrs, }; @@ -791,10 +782,6 @@ int gpio_export(unsigned gpio, bool dire goto fail_unlock; } - status = sysfs_create_group(dev-kobj, gpio_attr_group); - if (status) - goto fail_unregister_device; - if (direction_may_change) { status = device_create_file(dev, dev_attr_direction); if (status) @@ -962,25 +949,22 @@ EXPORT_SYMBOL_GPL(gpio_unexport); static int gpiochip_export(struct gpio_chip *chip) { - int status; + int status = 0; struct device *dev; /* Many systems register gpio chips for SOC support very early, * before driver model support is available. In those cases we * export this later, in gpiolib_sysfs_init() ... here
[PATCH 6/6 v13] gpio: Add block gpio to several gpio drivers
This patch adds block GPIO support to several gpio drivers. This implements block GPIO only for some selected drivers since block GPIO is an optional feature which may not be suitable for every GPIO hardware. (With automatic fallback to the single GPIO functions if not available in a driver.) Signed-off-by: Roland Stigge sti...@antcom.de --- drivers/gpio/Kconfig |2 drivers/gpio/gpio-em.c| 23 ++ drivers/gpio/gpio-ge.c| 29 + drivers/gpio/gpio-generic.c | 56 + drivers/gpio/gpio-ks8695.c| 34 +++ drivers/gpio/gpio-lpc32xx.c | 82 ++ drivers/gpio/gpio-max730x.c | 61 drivers/gpio/gpio-max732x.c | 59 +++ drivers/gpio/gpio-mc33880.c | 16 +++ drivers/gpio/gpio-ml-ioh.c| 27 drivers/gpio/gpio-mm-lantiq.c | 22 ++ drivers/gpio/gpio-mpc5200.c | 64 + drivers/gpio/gpio-mpc8xxx.c | 41 +++ drivers/gpio/gpio-pca953x.c | 64 + drivers/gpio/gpio-pcf857x.c | 24 +++ drivers/gpio/gpio-pch.c | 27 drivers/gpio/gpio-pl061.c | 17 +++ drivers/gpio/gpio-sa1100.c| 20 + drivers/gpio/gpio-samsung.c | 31 ++ drivers/gpio/gpio-twl6040.c | 32 ++ drivers/gpio/gpio-ucb1400.c | 23 ++ drivers/gpio/gpio-vt8500.c| 24 +++ drivers/gpio/gpio-xilinx.c| 44 drivers/pinctrl/pinctrl-at91.c| 29 + drivers/pinctrl/pinctrl-nomadik.c | 36 25 files changed, 887 insertions(+) --- linux-2.6.orig/drivers/gpio/Kconfig +++ linux-2.6/drivers/gpio/Kconfig @@ -144,11 +144,13 @@ config GPIO_MM_LANTIQ config GPIO_MPC5200 def_bool y depends on PPC_MPC52xx + select BITREVERSE config GPIO_MPC8XXX bool MPC512x/MPC8xxx GPIO support depends on PPC_MPC512x || PPC_MPC831x || PPC_MPC834x || PPC_MPC837x || \ FSL_SOC_BOOKE || PPC_86xx + select BITREVERSE help Say Y here if you're going to use hardware that connects to the MPC512x/831x/834x/837x/8572/8610 GPIOs. --- linux-2.6.orig/drivers/gpio/gpio-em.c +++ linux-2.6/drivers/gpio/gpio-em.c @@ -202,6 +202,27 @@ static void em_gio_set(struct gpio_chip __em_gio_set(chip, GIO_OH, offset - 16, value); } +static unsigned long em_gio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + return (int)(em_gio_read(gpio_to_priv(chip), GIO_I) mask); +} + +static void em_gio_set_block(struct gpio_chip *chip, unsigned long mask, +unsigned long values) +{ + unsigned long mask_ol = mask 0x; + unsigned long mask_oh = mask 16; + + unsigned long values_ol = values mask_ol; + unsigned long values_oh = (values 16) mask_oh; + + em_gio_write(gpio_to_priv(chip), GIO_OL, +mask_ol 16 | values_ol); + em_gio_write(gpio_to_priv(chip), GIO_OH, +mask_oh 16 | values_oh); +} + static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset, int value) { @@ -282,8 +303,10 @@ static int em_gio_probe(struct platform_ gpio_chip = p-gpio_chip; gpio_chip-direction_input = em_gio_direction_input; gpio_chip-get = em_gio_get; + gpio_chip-get_block = em_gio_get_block; gpio_chip-direction_output = em_gio_direction_output; gpio_chip-set = em_gio_set; + gpio_chip-set_block = em_gio_set_block; gpio_chip-to_irq = em_gio_to_irq; gpio_chip-label = name; gpio_chip-owner = THIS_MODULE; --- linux-2.6.orig/drivers/gpio/gpio-ge.c +++ linux-2.6/drivers/gpio/gpio-ge.c @@ -100,6 +100,29 @@ static void gef_gpio_set(struct gpio_chi _gef_gpio_set(mmchip-regs + GEF_GPIO_OUT, offset, value); } +static unsigned long gef_gpio_get_block(struct gpio_chip *chip, + unsigned long mask) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + + return ioread32be(mmchip-regs + GEF_GPIO_IN) mask; +} + +static void gef_gpio_set_block(struct gpio_chip *chip, + unsigned long mask, unsigned long values) +{ + struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip); + void __iomem *reg = mmchip-regs + GEF_GPIO_OUT; + unsigned int data; + + data = ioread32be(reg); + + data = ~mask; + data |= values mask; + + iowrite32be(data, reg); +} + static int __init gef_gpio_init(void) { struct device_node *np; @@ -125,6 +148,8 @@ static int __init gef_gpio_init(void
[PATCH 1/6 v13] gpio: Add a block GPIO API to gpiolib
The recurring task of providing simultaneous access to GPIO lines (especially for bit banging protocols) needs an appropriate API. This patch adds a kernel internal Block GPIO API that enables simultaneous access to several GPIOs. This is done by abstracting GPIOs to an n-bit word: Once requested, it provides access to a group of GPIOs which can range over multiple GPIO chips. Signed-off-by: Roland Stigge sti...@antcom.de --- Documentation/gpio.txt | 58 +++ drivers/gpio/gpiolib.c | 227 + include/asm-generic/gpio.h | 17 +++ include/linux/gpio.h | 97 +++ 4 files changed, 399 insertions(+) --- linux-2.6.orig/Documentation/gpio.txt +++ linux-2.6/Documentation/gpio.txt @@ -481,6 +481,64 @@ exact name string of pinctrl device has argument to this routine. +Block GPIO +-- + +The above described interface concentrates on handling single GPIOs. However, +in applications where it is critical to set several GPIOs at once, this +interface doesn't work well, e.g. bit-banging protocols via grouped GPIO lines. +Consider a GPIO controller that is connected via a slow I2C line. When +switching two or more GPIOs one after another, there can be considerable time +between those events. This is solved by an interface called Block GPIO: + +struct gpio_block *gpio_block_create(unsigned int *gpios, size_t size, +const char *name); + +This creates a new block of GPIOs as a list of GPIO numbers with the specified +size which are accessible via the returned struct gpio_block and the accessor +functions described below. Please note that you need to request the GPIOs +separately via gpio_request(). Similarly, the direction of the used GPIOs need +to be set by the user before using the block. An arbitrary list of globally +valid GPIOs can be specified, even ranging over several gpio_chips. Actual +handling of I/O operations will be done on a best effort base, i.e. +simultaneous I/O only where possible by hardware and implemented in the +respective GPIO driver. The number of GPIOs in one block is limited to the +number of bits in an unsigned long, or BITS_PER_LONG, of the respective +platform, i.e. typically at least 32 on a 32 bit system, and at least 64 on a +64 bit system. However, several blocks can be defined at once. + +unsigned long gpio_block_get(struct gpio_block *block, unsigned long mask); +void gpio_block_set(struct gpio_block *block, unsigned long mask, + unsigned long values); + +With those accessor functions, setting and getting the GPIO values is possible, +analogous to gpio_get_value() and gpio_set_value(). Each bit in the return +value of gpio_block_get() and in the value argument of gpio_block_set() +corresponds to a bit specified on gpio_block_create(). The mask parameters +specify which bits in the block are acted upon. This is useful to let some bits +untouched when doing a set operation on the block. + +Block operations in hardware are only possible where the respective GPIO driver +implements it, falling back to using single GPIO operations where the driver +only implements single GPIO access. + +If a GPIO block includes GPIOs from several chips, the chips are handled one +after another in the order of first specification in the list of GPIOs defined +in the GPIO block, starting with bit 0. Note that in this case, you typically +can't assume simultaneous access. + +void gpio_block_free(struct gpio_block *block); + +After the GPIO block isn't used anymore, it should be free'd via +gpio_block_free(). + +int gpio_block_register(struct gpio_block *block); +void gpio_block_unregister(struct gpio_block *block); + +These functions can be used to register a GPIO block. Blocks registered this +way will be available via userspace API. + + What do these conventions omit? === One of the biggest things these conventions omit is pin multiplexing, since --- linux-2.6.orig/drivers/gpio/gpiolib.c +++ linux-2.6/drivers/gpio/gpiolib.c @@ -83,6 +83,8 @@ static inline void desc_set_label(struct #endif } +static LIST_HEAD(gpio_block_list); + /* Warn when drivers omit gpio_request() calls -- legal but ill-advised * when setting direction, and otherwise illegal. Until board setup code * and drivers use explicit requests everywhere (which won't happen when @@ -217,6 +219,16 @@ static int gpio_get_direction(unsigned g return status; } +static bool gpio_block_is_output(struct gpio_block *block) +{ + int i; + + for (i = 0; i block-ngpio; i++) + if (!test_bit(FLAG_IS_OUT, gpio_desc[block-gpio[i]].flags)) + return false; + return true; +} + #ifdef CONFIG_GPIO_SYSFS /* lock protects against unexport_gpio() being called while @@ -1799,6 +1811,221 @@ void __gpio_set_value(unsigned gpio, int } EXPORT_SYMBOL_GPL(__gpio_set_value); +static struct gpio_block_chip
Re: [PATCH 0/6 v12] gpio: Add block GPIO
On 29/12/12 13:13, Jean-Christophe PLAGNIOL-VILLARD wrote: > On 13:01 Sat 29 Dec , Roland Stigge wrote: >> On 29/12/12 11:20, Jean-Christophe PLAGNIOL-VILLARD wrote: >>> On 17:49 Sun 23 Dec , Roland Stigge wrote: >>>> This set of patches adds: >>>> >>>> * Block GPIO API to gpiolib >>>> * Sysfs support for GPIO API, to provide userland access >>>> * Device interface for userland access (alternative to sysfs) >>>> * Devicetree support to instantiate GPIO blocks via DT >>>> * Example implementations in several gpio drivers since they need >>>> special accessor functions for block wise GPIO access (only for some >>>> selected drivers since the feature is optional and not suitable for >>>> all GPIO hardware) >>>> * Fix for race condition in gpiolib on device creation >>>> >>>> Signed-off-by: Roland Stigge >>>> Tested by: Wolfgang Grandegger >>>> -- >>>> >>>> Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio >>>> >>>> Changes since v11: >>>> * Removed support for at91, since this one is currently in the migration >>>> process to pinctrl implementation >>> already done for 3.8 >>> >>> in Linus tree >> >> Good, thanks for the note! So we include support for block GPIO in >> pinctrl-at91.c now. >> >> I guess the redundant code in arch/arm/mach-at91/gpio.c will be removed? > no we keep for non DT platform So would it be helpful it to maintain/mainline Wolfgang's patch for this one regarding block GPIO? (Besides patching pinctrl-at91.c?) Thanks, Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/6 v12] gpio: Add block GPIO
Hi, On 29/12/12 11:20, Jean-Christophe PLAGNIOL-VILLARD wrote: > On 17:49 Sun 23 Dec , Roland Stigge wrote: >> This set of patches adds: >> >> * Block GPIO API to gpiolib >> * Sysfs support for GPIO API, to provide userland access >> * Device interface for userland access (alternative to sysfs) >> * Devicetree support to instantiate GPIO blocks via DT >> * Example implementations in several gpio drivers since they need >> special accessor functions for block wise GPIO access (only for some >> selected drivers since the feature is optional and not suitable for >> all GPIO hardware) >> * Fix for race condition in gpiolib on device creation >> >> Signed-off-by: Roland Stigge >> Tested by: Wolfgang Grandegger >> -- >> >> Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio >> >> Changes since v11: >> * Removed support for at91, since this one is currently in the migration >> process to pinctrl implementation > already done for 3.8 > > in Linus tree Good, thanks for the note! So we include support for block GPIO in pinctrl-at91.c now. I guess the redundant code in arch/arm/mach-at91/gpio.c will be removed? Thanks, Roland -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/6 v12] gpio: Add block GPIO
Hi, On 29/12/12 11:20, Jean-Christophe PLAGNIOL-VILLARD wrote: On 17:49 Sun 23 Dec , Roland Stigge wrote: This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge sti...@antcom.de Tested by: Wolfgang Grandegger w...@grandegger.com -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation already done for 3.8 in Linus tree Good, thanks for the note! So we include support for block GPIO in pinctrl-at91.c now. I guess the redundant code in arch/arm/mach-at91/gpio.c will be removed? Thanks, Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 0/6 v12] gpio: Add block GPIO
On 29/12/12 13:13, Jean-Christophe PLAGNIOL-VILLARD wrote: On 13:01 Sat 29 Dec , Roland Stigge wrote: On 29/12/12 11:20, Jean-Christophe PLAGNIOL-VILLARD wrote: On 17:49 Sun 23 Dec , Roland Stigge wrote: This set of patches adds: * Block GPIO API to gpiolib * Sysfs support for GPIO API, to provide userland access * Device interface for userland access (alternative to sysfs) * Devicetree support to instantiate GPIO blocks via DT * Example implementations in several gpio drivers since they need special accessor functions for block wise GPIO access (only for some selected drivers since the feature is optional and not suitable for all GPIO hardware) * Fix for race condition in gpiolib on device creation Signed-off-by: Roland Stigge sti...@antcom.de Tested by: Wolfgang Grandegger w...@grandegger.com -- Testing branch available at: git://git.antcom.de/linux-2.6.git blockgpio Changes since v11: * Removed support for at91, since this one is currently in the migration process to pinctrl implementation already done for 3.8 in Linus tree Good, thanks for the note! So we include support for block GPIO in pinctrl-at91.c now. I guess the redundant code in arch/arm/mach-at91/gpio.c will be removed? no we keep for non DT platform So would it be helpful it to maintain/mainline Wolfgang's patch for this one regarding block GPIO? (Besides patching pinctrl-at91.c?) Thanks, Roland -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/