summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-11-09 10:54:54 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-11-09 10:54:54 +0100
commit5576a028d0b722a1c3b125d3ac0322debc7e724b (patch)
tree2f1145c4ffee70a891a474942ca098747ea3e458
parente61cca2117eb7dfe45cac376544ffade1d94b643 (diff)
parent9984960ac43b85faa36269d905c56c01e7549bde (diff)
downloadbarebox-5576a028d0b722a1c3b125d3ac0322debc7e724b.tar.gz
barebox-5576a028d0b722a1c3b125d3ac0322debc7e724b.tar.xz
Merge branch 'for-next/gpio'
-rw-r--r--arch/arm/boards/zii-imx6q-rdu2/board.c38
-rw-r--r--arch/arm/boards/zii-vf610-dev/board.c5
-rw-r--r--arch/arm/dts/imx51-zii-rdu1.dts13
-rw-r--r--arch/arm/dts/imx6qdl-zii-rdu2.dtsi42
-rw-r--r--arch/arm/dts/imx7d-zii-rpu2.dts9
-rw-r--r--arch/arm/dts/vf610-zii-cfu1.dts11
-rw-r--r--arch/arm/dts/vf610-zii-dev-rev-c.dts12
-rw-r--r--arch/arm/dts/vf610-zii-ssmb-spu3.dts11
-rw-r--r--commands/gpio.c54
-rw-r--r--drivers/gpio/gpio-dw.c2
-rw-r--r--drivers/gpio/gpio-imx.c2
-rw-r--r--drivers/gpio/gpio-mxs.c2
-rw-r--r--drivers/gpio/gpio-vf610.c5
-rw-r--r--drivers/gpio/gpiolib.c30
-rw-r--r--drivers/pinctrl/imx-iomux-v1.c2
-rw-r--r--drivers/pinctrl/imx-iomux-v2.c2
-rw-r--r--drivers/pinctrl/imx-iomux-v3.c2
-rw-r--r--drivers/pinctrl/mvebu/armada-370.c2
-rw-r--r--drivers/pinctrl/mvebu/armada-xp.c2
-rw-r--r--drivers/pinctrl/mvebu/dove.c2
-rw-r--r--drivers/pinctrl/mvebu/kirkwood.c2
-rw-r--r--drivers/pinctrl/pinctrl-at91.c4
-rw-r--r--drivers/pinctrl/pinctrl-mxs.c2
-rw-r--r--drivers/pinctrl/pinctrl-single.c2
-rw-r--r--drivers/pinctrl/pinctrl-tegra-xusb.c2
-rw-r--r--drivers/pinctrl/pinctrl-tegra20.c2
-rw-r--r--drivers/pinctrl/pinctrl-tegra30.c2
-rw-r--r--drivers/pinctrl/pinctrl-vf610.c2
-rw-r--r--include/gpio.h6
-rw-r--r--include/linux/ctype.h9
-rw-r--r--include/linux/kernel.h95
-rw-r--r--include/linux/string.h2
-rw-r--r--lib/Makefile1
-rw-r--r--lib/kstrtox.c366
-rw-r--r--lib/kstrtox.h9
35 files changed, 666 insertions, 88 deletions
diff --git a/arch/arm/boards/zii-imx6q-rdu2/board.c b/arch/arm/boards/zii-imx6q-rdu2/board.c
index c99f993f02..e174032c96 100644
--- a/arch/arm/boards/zii-imx6q-rdu2/board.c
+++ b/arch/arm/boards/zii-imx6q-rdu2/board.c
@@ -97,44 +97,6 @@ static int rdu2_reset_audio_touchscreen_nfc(void)
*/
late_initcall(rdu2_reset_audio_touchscreen_nfc);
-static const struct gpio rdu2_front_panel_usb_gpios[] = {
- {
- .gpio = IMX_GPIO_NR(3, 19),
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "usb-emulation",
- },
- {
- .gpio = IMX_GPIO_NR(3, 20),
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "usb-mode1",
- },
- {
- .gpio = IMX_GPIO_NR(3, 23),
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "usb-mode2",
- },
-};
-
-static int rdu2_enable_front_panel_usb(void)
-{
- int ret;
-
- if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
- !of_machine_is_compatible("zii,imx6qp-zii-rdu2"))
- return 0;
-
- ret = gpio_request_array(rdu2_front_panel_usb_gpios,
- ARRAY_SIZE(rdu2_front_panel_usb_gpios));
- if (ret) {
- pr_err("Failed to request RDU2 front panel USB gpios: %s\n",
- strerror(-ret));
-
- }
-
- return ret;
-}
-late_initcall(rdu2_enable_front_panel_usb);
-
static int rdu2_devices_init(void)
{
if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
diff --git a/arch/arm/boards/zii-vf610-dev/board.c b/arch/arm/boards/zii-vf610-dev/board.c
index 275d0a432c..a8fa1ef61f 100644
--- a/arch/arm/boards/zii-vf610-dev/board.c
+++ b/arch/arm/boards/zii-vf610-dev/board.c
@@ -64,11 +64,6 @@ static int zii_vf610_cfu1_spu3_expose_signals(void)
{
static const struct gpio signals[] = {
{
- .gpio = 107,
- .flags = GPIOF_OUT_INIT_HIGH,
- .label = "soc_sw_rstn",
- },
- {
.gpio = 98,
.flags = GPIOF_IN,
.label = "e6352_intn",
diff --git a/arch/arm/dts/imx51-zii-rdu1.dts b/arch/arm/dts/imx51-zii-rdu1.dts
index 93bb344f51..c649db45c9 100644
--- a/arch/arm/dts/imx51-zii-rdu1.dts
+++ b/arch/arm/dts/imx51-zii-rdu1.dts
@@ -24,6 +24,15 @@
device-path = &spinor, "partname:barebox-environment";
};
};
+
+ aliases {
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch-eeprom = &switch;
+ };
};
&ecspi1 {
@@ -51,6 +60,10 @@
};
};
+&mdio_gpio {
+ switch: switch@0 {};
+};
+
&uart3 {
rave-sp {
watchdog {
diff --git a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
index f63b5d2ed7..a3f6dbd151 100644
--- a/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
+++ b/arch/arm/dts/imx6qdl-zii-rdu2.dtsi
@@ -52,6 +52,12 @@
aliases {
ethernet0 = &fec;
ethernet1 = &i210;
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch-eeprom = &switch;
};
};
@@ -124,3 +130,39 @@
};
};
};
+
+&gpio3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio3_hog>;
+
+ usb-emulation {
+ gpio-hog;
+ gpios = <19 GPIO_ACTIVE_HIGH>;
+ output-low;
+ line-name = "usb-emulation";
+ };
+
+ usb-mode1 {
+ gpio-hog;
+ gpios = <20 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "usb-mode1";
+ };
+
+ usb-mode2 {
+ gpio-hog;
+ gpios = <23 GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "usb-mode2";
+ };
+};
+
+&iomuxc {
+ pinctrl_gpio3_hog: gpio3hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x40000038
+ MX6QDL_PAD_EIM_D20__GPIO3_IO20 0x40000038
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x40000038
+ >;
+ };
+};
diff --git a/arch/arm/dts/imx7d-zii-rpu2.dts b/arch/arm/dts/imx7d-zii-rpu2.dts
index 6fba73f437..24a6d40f77 100644
--- a/arch/arm/dts/imx7d-zii-rpu2.dts
+++ b/arch/arm/dts/imx7d-zii-rpu2.dts
@@ -19,6 +19,15 @@
stdout-path = &uart2;
};
+ aliases {
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch-eeprom = &switch0;
+ };
+
gpio-leds {
compatible = "gpio-leds";
pinctrl-0 = <&pinctrl_leds_debug>;
diff --git a/arch/arm/dts/vf610-zii-cfu1.dts b/arch/arm/dts/vf610-zii-cfu1.dts
index 80d3f54f78..1493335963 100644
--- a/arch/arm/dts/vf610-zii-cfu1.dts
+++ b/arch/arm/dts/vf610-zii-cfu1.dts
@@ -8,3 +8,14 @@
#include "vf610-zii-dev.dtsi"
+/ {
+ aliases {
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch-eeprom = &switch0;
+ };
+};
+
diff --git a/arch/arm/dts/vf610-zii-dev-rev-c.dts b/arch/arm/dts/vf610-zii-dev-rev-c.dts
index 797b31bef9..c6341a0279 100644
--- a/arch/arm/dts/vf610-zii-dev-rev-c.dts
+++ b/arch/arm/dts/vf610-zii-dev-rev-c.dts
@@ -46,6 +46,18 @@
#include "vf610-zii-dev.dtsi"
+/ {
+ aliases {
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch0-eeprom = &switch0;
+ switch1-eeprom = &switch1;
+ };
+};
+
&dspi0 {
m25p128@0 {
partition@0 {
diff --git a/arch/arm/dts/vf610-zii-ssmb-spu3.dts b/arch/arm/dts/vf610-zii-ssmb-spu3.dts
index e030109ce2..5b2460cafa 100644
--- a/arch/arm/dts/vf610-zii-ssmb-spu3.dts
+++ b/arch/arm/dts/vf610-zii-ssmb-spu3.dts
@@ -3,3 +3,14 @@
#include <arm/vf610-zii-ssmb-spu3.dts>
#include "vf610-zii-dev.dtsi"
+
+/ {
+ aliases {
+ /*
+ * NVMEM device corresponding to EEPROM attached to
+ * the switch shared DT node with it, so we use that
+ * fact to create a desirable naming
+ */
+ switch-eeprom = &switch0;
+ };
+};
diff --git a/commands/gpio.c b/commands/gpio.c
index 08ecc152d9..951ad2c285 100644
--- a/commands/gpio.c
+++ b/commands/gpio.c
@@ -16,14 +16,35 @@
#include <errno.h>
#include <gpio.h>
-static int do_gpio_get_value(int argc, char *argv[])
+static int get_gpio_and_value(int argc, char *argv[],
+ int *gpio, int *value)
{
- int gpio, value;
+ const int count = value ? 3 : 2;
+ int ret = 0;
- if (argc < 2)
+ if (argc < count)
return COMMAND_ERROR_USAGE;
- gpio = simple_strtoul(argv[1], NULL, 0);
+ *gpio = gpio_find_by_label(argv[1]);
+ if (*gpio < 0) {
+ ret = kstrtoint(argv[1], 0, gpio);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (value)
+ ret = kstrtoint(argv[2], 0, value);
+
+ return ret;
+}
+
+static int do_gpio_get_value(int argc, char *argv[])
+{
+ int gpio, value, ret;
+
+ ret = get_gpio_and_value(argc, argv, &gpio, NULL);
+ if (ret)
+ return ret;
value = gpio_get_value(gpio);
if (value < 0)
@@ -41,13 +62,11 @@ BAREBOX_CMD_END
static int do_gpio_set_value(int argc, char *argv[])
{
- int gpio, value;
-
- if (argc < 3)
- return COMMAND_ERROR_USAGE;
+ int gpio, value, ret;
- gpio = simple_strtoul(argv[1], NULL, 0);
- value = simple_strtoul(argv[2], NULL, 0);
+ ret = get_gpio_and_value(argc, argv, &gpio, &value);
+ if (ret)
+ return ret;
gpio_set_value(gpio, value);
@@ -65,10 +84,9 @@ static int do_gpio_direction_input(int argc, char *argv[])
{
int gpio, ret;
- if (argc < 2)
- return COMMAND_ERROR_USAGE;
-
- gpio = simple_strtoul(argv[1], NULL, 0);
+ ret = get_gpio_and_value(argc, argv, &gpio, NULL);
+ if (ret)
+ return ret;
ret = gpio_direction_input(gpio);
if (ret)
@@ -88,11 +106,9 @@ static int do_gpio_direction_output(int argc, char *argv[])
{
int gpio, value, ret;
- if (argc < 3)
- return COMMAND_ERROR_USAGE;
-
- gpio = simple_strtoul(argv[1], NULL, 0);
- value = simple_strtoul(argv[2], NULL, 0);
+ ret = get_gpio_and_value(argc, argv, &gpio, &value);
+ if (ret)
+ return ret;
ret = gpio_direction_output(gpio, value);
if (ret)
diff --git a/drivers/gpio/gpio-dw.c b/drivers/gpio/gpio-dw.c
index f145c01232..b81e6a75c5 100644
--- a/drivers/gpio/gpio-dw.c
+++ b/drivers/gpio/gpio-dw.c
@@ -199,4 +199,4 @@ static int __init dwgpio_init(void)
{
return platform_driver_register(&dwgpio_driver);
}
-core_initcall(dwgpio_init);
+postcore_initcall(dwgpio_init);
diff --git a/drivers/gpio/gpio-imx.c b/drivers/gpio/gpio-imx.c
index d618e60119..2827e11e73 100644
--- a/drivers/gpio/gpio-imx.c
+++ b/drivers/gpio/gpio-imx.c
@@ -222,4 +222,4 @@ static int imx_gpio_add(void)
platform_driver_register(&imx_gpio_driver);
return 0;
}
-core_initcall(imx_gpio_add);
+postcore_initcall(imx_gpio_add);
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c
index b2b3ad3ac6..ef78873ad2 100644
--- a/drivers/gpio/gpio-mxs.c
+++ b/drivers/gpio/gpio-mxs.c
@@ -183,4 +183,4 @@ static int mxs_gpio_add(void)
platform_driver_register(&mxs_gpio_driver);
return 0;
}
-core_initcall(mxs_gpio_add);
+postcore_initcall(mxs_gpio_add);
diff --git a/drivers/gpio/gpio-vf610.c b/drivers/gpio/gpio-vf610.c
index 2aff62be59..ab35310fbe 100644
--- a/drivers/gpio/gpio-vf610.c
+++ b/drivers/gpio/gpio-vf610.c
@@ -142,9 +142,8 @@ static int vf610_gpio_probe(struct device_d *dev)
port->chip.base *= VF610_GPIO_PER_PORT;
port->chip.dev = dev;
- gpiochip_add(&port->chip);
- return 0;
+ return gpiochip_add(&port->chip);
free_port:
free(port);
@@ -161,4 +160,4 @@ static int __init gpio_vf610_init(void)
{
return platform_driver_register(&vf610_gpio_driver);
}
-core_initcall(gpio_vf610_init);
+postcore_initcall(gpio_vf610_init);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index b83a27de7d..4c7aee4a0b 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -91,6 +91,23 @@ done:
return ret;
}
+int gpio_find_by_label(const char *label)
+{
+ int i;
+
+ for (i = 0; i < ARCH_NR_GPIOS; i++) {
+ struct gpio_info *info = &gpio_desc[i];
+
+ if (!info->requested || !info->chip || !info->label)
+ continue;
+
+ if (!strcmp(info->label, label))
+ return i;
+ }
+
+ return -ENOENT;
+}
+
void gpio_free(unsigned gpio)
{
struct gpio_info *gi = gpio_to_desc(gpio);
@@ -352,12 +369,12 @@ static int of_hog_gpio(struct device_node *np, struct gpio_chip *chip,
flags |= GPIOF_ACTIVE_LOW;
gpio = gpio_get_num(chip->dev, gpio_num);
- if (ret == -EPROBE_DEFER)
- return ret;
+ if (gpio == -EPROBE_DEFER)
+ return gpio;
- if (ret < 0) {
+ if (gpio < 0) {
dev_err(chip->dev, "unable to get gpio %u\n", gpio_num);
- return ret;
+ return gpio;
}
@@ -382,7 +399,10 @@ static int of_hog_gpio(struct device_node *np, struct gpio_chip *chip,
else
return -EINVAL;
- of_property_read_string(np, "line-name", &name);
+ /* The line-name is optional and if not present the node name is used */
+ ret = of_property_read_string(np, "line-name", &name);
+ if (ret < 0)
+ name = np->name;
return gpio_request_one(gpio, flags, name);
}
diff --git a/drivers/pinctrl/imx-iomux-v1.c b/drivers/pinctrl/imx-iomux-v1.c
index a3f04802a2..61e8f9680f 100644
--- a/drivers/pinctrl/imx-iomux-v1.c
+++ b/drivers/pinctrl/imx-iomux-v1.c
@@ -314,4 +314,4 @@ static int imx_iomux_v1_init(void)
{
return platform_driver_register(&imx_iomux_v1_driver);
}
-postcore_initcall(imx_iomux_v1_init);
+core_initcall(imx_iomux_v1_init);
diff --git a/drivers/pinctrl/imx-iomux-v2.c b/drivers/pinctrl/imx-iomux-v2.c
index 0c985a69d3..60b635a8a8 100644
--- a/drivers/pinctrl/imx-iomux-v2.c
+++ b/drivers/pinctrl/imx-iomux-v2.c
@@ -154,4 +154,4 @@ static int imx_iomux_init(void)
{
return platform_driver_register(&imx_iomux_driver);
}
-postcore_initcall(imx_iomux_init);
+core_initcall(imx_iomux_init);
diff --git a/drivers/pinctrl/imx-iomux-v3.c b/drivers/pinctrl/imx-iomux-v3.c
index 0ab97040e0..b2a67fcccc 100644
--- a/drivers/pinctrl/imx-iomux-v3.c
+++ b/drivers/pinctrl/imx-iomux-v3.c
@@ -266,4 +266,4 @@ static int imx_iomux_v3_init(void)
{
return platform_driver_register(&imx_iomux_v3_driver);
}
-postcore_initcall(imx_iomux_v3_init);
+core_initcall(imx_iomux_v3_init);
diff --git a/drivers/pinctrl/mvebu/armada-370.c b/drivers/pinctrl/mvebu/armada-370.c
index 2fd07a7b87..4fde16ab5d 100644
--- a/drivers/pinctrl/mvebu/armada-370.c
+++ b/drivers/pinctrl/mvebu/armada-370.c
@@ -415,4 +415,4 @@ static int armada_370_pinctrl_init(void)
{
return platform_driver_register(&armada_370_pinctrl_driver);
}
-postcore_initcall(armada_370_pinctrl_init);
+core_initcall(armada_370_pinctrl_init);
diff --git a/drivers/pinctrl/mvebu/armada-xp.c b/drivers/pinctrl/mvebu/armada-xp.c
index 2657db5fcf..089942d696 100644
--- a/drivers/pinctrl/mvebu/armada-xp.c
+++ b/drivers/pinctrl/mvebu/armada-xp.c
@@ -405,4 +405,4 @@ static int armada_xp_pinctrl_init(void)
{
return platform_driver_register(&armada_xp_pinctrl_driver);
}
-postcore_initcall(armada_xp_pinctrl_init);
+core_initcall(armada_xp_pinctrl_init);
diff --git a/drivers/pinctrl/mvebu/dove.c b/drivers/pinctrl/mvebu/dove.c
index 8de01e74d6..2d9d8094f8 100644
--- a/drivers/pinctrl/mvebu/dove.c
+++ b/drivers/pinctrl/mvebu/dove.c
@@ -742,4 +742,4 @@ static int dove_pinctrl_init(void)
{
return platform_driver_register(&dove_pinctrl_driver);
}
-postcore_initcall(dove_pinctrl_init);
+core_initcall(dove_pinctrl_init);
diff --git a/drivers/pinctrl/mvebu/kirkwood.c b/drivers/pinctrl/mvebu/kirkwood.c
index 4b2618cd2e..a347239028 100644
--- a/drivers/pinctrl/mvebu/kirkwood.c
+++ b/drivers/pinctrl/mvebu/kirkwood.c
@@ -456,4 +456,4 @@ static int kirkwood_pinctrl_init(void)
{
return platform_driver_register(&kirkwood_pinctrl_driver);
}
-postcore_initcall(kirkwood_pinctrl_init);
+core_initcall(kirkwood_pinctrl_init);
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 0303869774..84348a0530 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -538,7 +538,7 @@ static int at91_pinctrl_init(void)
{
return platform_driver_register(&at91_pinctrl_driver);
}
-postcore_initcall(at91_pinctrl_init);
+core_initcall(at91_pinctrl_init);
static int at91_gpio_get(struct gpio_chip *chip, unsigned offset)
{
@@ -718,4 +718,4 @@ static int at91_gpio_init(void)
{
return platform_driver_register(&at91_gpio_driver);
}
-postcore_initcall(at91_gpio_init);
+core_initcall(at91_gpio_init);
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index 479c31a426..b48ed2ace1 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -168,4 +168,4 @@ static int mxs_pinctrl_init(void)
{
return platform_driver_register(&mxs_pinctrl_driver);
}
-postcore_initcall(mxs_pinctrl_init);
+core_initcall(mxs_pinctrl_init);
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 15b74cc1df..3c581ed5d3 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -167,4 +167,4 @@ static int pcs_init(void)
{
return platform_driver_register(&pcs_driver);
}
-postcore_initcall(pcs_init);
+core_initcall(pcs_init);
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index a7a75bb9c5..e477280e62 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -518,4 +518,4 @@ static int pinctrl_tegra_xusb_init(void)
{
return platform_driver_register(&pinctrl_tegra_xusb_driver);
}
-postcore_initcall(pinctrl_tegra_xusb_init);
+core_initcall(pinctrl_tegra_xusb_init);
diff --git a/drivers/pinctrl/pinctrl-tegra20.c b/drivers/pinctrl/pinctrl-tegra20.c
index eaaba9e7a7..337992c21f 100644
--- a/drivers/pinctrl/pinctrl-tegra20.c
+++ b/drivers/pinctrl/pinctrl-tegra20.c
@@ -350,4 +350,4 @@ static int pinctrl_tegra20_init(void)
{
return platform_driver_register(&pinctrl_tegra20_driver);
}
-postcore_initcall(pinctrl_tegra20_init);
+core_initcall(pinctrl_tegra20_init);
diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c
index 4b271dd0b6..d9b49c57d9 100644
--- a/drivers/pinctrl/pinctrl-tegra30.c
+++ b/drivers/pinctrl/pinctrl-tegra30.c
@@ -935,4 +935,4 @@ static int pinctrl_tegra30_init(void)
{
return platform_driver_register(&pinctrl_tegra30_driver);
}
-postcore_initcall(pinctrl_tegra30_init);
+core_initcall(pinctrl_tegra30_init);
diff --git a/drivers/pinctrl/pinctrl-vf610.c b/drivers/pinctrl/pinctrl-vf610.c
index a46b0e2ca0..662fa9b6c9 100644
--- a/drivers/pinctrl/pinctrl-vf610.c
+++ b/drivers/pinctrl/pinctrl-vf610.c
@@ -165,4 +165,4 @@ static int pinctrl_vf610_init(void)
{
return platform_driver_register(&pinctrl_vf610_driver);
}
-postcore_initcall(pinctrl_vf610_init);
+core_initcall(pinctrl_vf610_init);
diff --git a/include/gpio.h b/include/gpio.h
index e42fa23383..38d6ba2df9 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -92,6 +92,11 @@ static inline int gpio_request(unsigned gpio, const char *label)
return 0;
}
+static inline int gpio_find_by_label(const char *label)
+{
+ return -ENOSYS;
+}
+
static inline void gpio_free(unsigned gpio)
{
}
@@ -114,6 +119,7 @@ static inline void gpio_free_array(const struct gpio *array, size_t num)
}
#else
int gpio_request(unsigned gpio, const char *label);
+int gpio_find_by_label(const char *label);
void gpio_free(unsigned gpio);
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
int gpio_request_array(const struct gpio *array, size_t num);
diff --git a/include/linux/ctype.h b/include/linux/ctype.h
index 74fb735778..633c3862d8 100644
--- a/include/linux/ctype.h
+++ b/include/linux/ctype.h
@@ -53,4 +53,13 @@ static inline unsigned char __toupper(unsigned char c)
#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)
+/*
+ * Fast implementation of tolower() for internal usage. Do not use in your
+ * code.
+ */
+static inline char _tolower(const char c)
+{
+ return c | 0x20;
+}
+
#endif
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index ab713f20e9..cc6d6f7467 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -269,4 +269,99 @@ extern char *bin2hex(char *dst, const void *src, size_t count);
#define swap(a, b) \
do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)
+
+/* Internal, do not use. */
+int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res);
+int __must_check _kstrtol(const char *s, unsigned int base, long *res);
+
+int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res);
+int __must_check kstrtoll(const char *s, unsigned int base, long long *res);
+
+/**
+ * kstrtoul - convert a string to an unsigned long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+*/
+static inline int __must_check kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+ /*
+ * We want to shortcut function call, but
+ * __builtin_types_compatible_p(unsigned long, unsigned long long) = 0.
+ */
+ if (sizeof(unsigned long) == sizeof(unsigned long long) &&
+ __alignof__(unsigned long) == __alignof__(unsigned long long))
+ return kstrtoull(s, base, (unsigned long long *)res);
+ else
+ return _kstrtoul(s, base, res);
+}
+
+/**
+ * kstrtol - convert a string to a long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
+static inline int __must_check kstrtol(const char *s, unsigned int base, long *res)
+{
+ /*
+ * We want to shortcut function call, but
+ * __builtin_types_compatible_p(long, long long) = 0.
+ */
+ if (sizeof(long) == sizeof(long long) &&
+ __alignof__(long) == __alignof__(long long))
+ return kstrtoll(s, base, (long long *)res);
+ else
+ return _kstrtol(s, base, res);
+}
+
+int __must_check kstrtouint(const char *s, unsigned int base, unsigned int *res);
+int __must_check kstrtoint(const char *s, unsigned int base, int *res);
+
+static inline int __must_check kstrtou64(const char *s, unsigned int base, u64 *res)
+{
+ return kstrtoull(s, base, res);
+}
+
+static inline int __must_check kstrtos64(const char *s, unsigned int base, s64 *res)
+{
+ return kstrtoll(s, base, res);
+}
+
+static inline int __must_check kstrtou32(const char *s, unsigned int base, u32 *res)
+{
+ return kstrtouint(s, base, res);
+}
+
+static inline int __must_check kstrtos32(const char *s, unsigned int base, s32 *res)
+{
+ return kstrtoint(s, base, res);
+}
+
+int __must_check kstrtou16(const char *s, unsigned int base, u16 *res);
+int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
+int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
+int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
+int __must_check kstrtobool(const char *s, bool *res);
+
#endif /* _LINUX_KERNEL_H */
diff --git a/include/linux/string.h b/include/linux/string.h
index 3418b4fbe4..90fe1b6ec8 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -122,4 +122,6 @@ static inline void *kmemdup(const void *src, size_t len, gfp_t gfp)
return memdup(src, len);
}
+extern int kstrtobool(const char *s, bool *res);
+
#endif /* _LINUX_STRING_H_ */
diff --git a/lib/Makefile b/lib/Makefile
index 693945fb2c..24dc3d9eeb 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -5,6 +5,7 @@ obj-y += rbtree.o
obj-y += display_options.o
obj-y += string.o
obj-y += strtox.o
+obj-y += kstrtox.o
obj-y += vsprintf.o
pbl-$(CONFIG_PBL_CONSOLE) += vsprintf.o
obj-y += div64.o
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
new file mode 100644
index 0000000000..0e4b590531
--- /dev/null
+++ b/lib/kstrtox.c
@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Convert integer string representation to an integer.
+ * If an integer doesn't fit into specified type, -E is returned.
+ *
+ * Integer starts with optional sign.
+ * kstrtou*() functions do not accept sign "-".
+ *
+ * Radix 0 means autodetection: leading "0x" implies radix 16,
+ * leading "0" implies radix 8, otherwise radix is 10.
+ * Autodetection hints work after optional sign, but not before.
+ *
+ * If -E is returned, result is not touched.
+ */
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/types.h>
+
+#include "kstrtox.h"
+
+const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
+{
+ if (*base == 0) {
+ if (s[0] == '0') {
+ if (_tolower(s[1]) == 'x' && isxdigit(s[2]))
+ *base = 16;
+ else
+ *base = 8;
+ } else
+ *base = 10;
+ }
+ if (*base == 16 && s[0] == '0' && _tolower(s[1]) == 'x')
+ s += 2;
+ return s;
+}
+
+/*
+ * Convert non-negative integer string representation in explicitly given radix
+ * to an integer.
+ * Return number of characters consumed maybe or-ed with overflow bit.
+ * If overflow occurs, result integer (incorrect) is still returned.
+ *
+ * Don't you dare use this function.
+ */
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p)
+{
+ unsigned long long res;
+ unsigned int rv;
+
+ res = 0;
+ rv = 0;
+ while (1) {
+ unsigned int c = *s;
+ unsigned int lc = c | 0x20; /* don't tolower() this line */
+ unsigned int val;
+
+ if ('0' <= c && c <= '9')
+ val = c - '0';
+ else if ('a' <= lc && lc <= 'f')
+ val = lc - 'a' + 10;
+ else
+ break;
+
+ if (val >= base)
+ break;
+ /*
+ * Check for overflow only if we are within range of
+ * it in the max base we support (16)
+ */
+ if (unlikely(res & (~0ull << 60))) {
+ if (res > div_u64(ULLONG_MAX - val, base))
+ rv |= KSTRTOX_OVERFLOW;
+ }
+ res = res * base + val;
+ rv++;
+ s++;
+ }
+ *p = res;
+ return rv;
+}
+
+static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+ unsigned long long _res;
+ unsigned int rv;
+
+ s = _parse_integer_fixup_radix(s, &base);
+ rv = _parse_integer(s, base, &_res);
+ if (rv & KSTRTOX_OVERFLOW)
+ return -ERANGE;
+ if (rv == 0)
+ return -EINVAL;
+ s += rv;
+ if (*s == '\n')
+ s++;
+ if (*s)
+ return -EINVAL;
+ *res = _res;
+ return 0;
+}
+
+/**
+ * kstrtoull - convert a string to an unsigned long long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
+int kstrtoull(const char *s, unsigned int base, unsigned long long *res)
+{
+ if (s[0] == '+')
+ s++;
+ return _kstrtoull(s, base, res);
+}
+EXPORT_SYMBOL(kstrtoull);
+
+/**
+ * kstrtoll - convert a string to a long long
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
+int kstrtoll(const char *s, unsigned int base, long long *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ if (s[0] == '-') {
+ rv = _kstrtoull(s + 1, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if ((long long)-tmp > 0)
+ return -ERANGE;
+ *res = -tmp;
+ } else {
+ rv = kstrtoull(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if ((long long)tmp < 0)
+ return -ERANGE;
+ *res = tmp;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kstrtoll);
+
+/* Internal, do not use. */
+int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ rv = kstrtoull(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (unsigned long long)(unsigned long)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(_kstrtoul);
+
+/* Internal, do not use. */
+int _kstrtol(const char *s, unsigned int base, long *res)
+{
+ long long tmp;
+ int rv;
+
+ rv = kstrtoll(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (long long)(long)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(_kstrtol);
+
+/**
+ * kstrtouint - convert a string to an unsigned int
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign, but not a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
+int kstrtouint(const char *s, unsigned int base, unsigned int *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ rv = kstrtoull(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (unsigned long long)(unsigned int)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtouint);
+
+/**
+ * kstrtoint - convert a string to an int
+ * @s: The start of the string. The string must be null-terminated, and may also
+ * include a single newline before its terminating null. The first character
+ * may also be a plus sign or a minus sign.
+ * @base: The number base to use. The maximum supported base is 16. If base is
+ * given as 0, then the base of the string is automatically detected with the
+ * conventional semantics - If it begins with 0x the number will be parsed as a
+ * hexadecimal (case insensitive), if it otherwise begins with 0, it will be
+ * parsed as an octal number. Otherwise it will be parsed as a decimal.
+ * @res: Where to write the result of the conversion on success.
+ *
+ * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error.
+ * Used as a replacement for the obsolete simple_strtoull. Return code must
+ * be checked.
+ */
+int kstrtoint(const char *s, unsigned int base, int *res)
+{
+ long long tmp;
+ int rv;
+
+ rv = kstrtoll(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (long long)(int)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtoint);
+
+int kstrtou16(const char *s, unsigned int base, u16 *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ rv = kstrtoull(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (unsigned long long)(u16)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtou16);
+
+int kstrtos16(const char *s, unsigned int base, s16 *res)
+{
+ long long tmp;
+ int rv;
+
+ rv = kstrtoll(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (long long)(s16)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtos16);
+
+int kstrtou8(const char *s, unsigned int base, u8 *res)
+{
+ unsigned long long tmp;
+ int rv;
+
+ rv = kstrtoull(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (unsigned long long)(u8)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtou8);
+
+int kstrtos8(const char *s, unsigned int base, s8 *res)
+{
+ long long tmp;
+ int rv;
+
+ rv = kstrtoll(s, base, &tmp);
+ if (rv < 0)
+ return rv;
+ if (tmp != (long long)(s8)tmp)
+ return -ERANGE;
+ *res = tmp;
+ return 0;
+}
+EXPORT_SYMBOL(kstrtos8);
+
+/**
+ * kstrtobool - convert common user inputs into boolean values
+ * @s: input string
+ * @res: result
+ *
+ * This routine returns 0 iff the first character is one of 'Yy1Nn0', or
+ * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
+ * pointed to by res is updated upon finding a match.
+ */
+int kstrtobool(const char *s, bool *res)
+{
+ if (!s)
+ return -EINVAL;
+
+ switch (s[0]) {
+ case 'y':
+ case 'Y':
+ case '1':
+ *res = true;
+ return 0;
+ case 'n':
+ case 'N':
+ case '0':
+ *res = false;
+ return 0;
+ case 'o':
+ case 'O':
+ switch (s[1]) {
+ case 'n':
+ case 'N':
+ *res = true;
+ return 0;
+ case 'f':
+ case 'F':
+ *res = false;
+ return 0;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(kstrtobool); \ No newline at end of file
diff --git a/lib/kstrtox.h b/lib/kstrtox.h
new file mode 100644
index 0000000000..3b4637bcd2
--- /dev/null
+++ b/lib/kstrtox.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LIB_KSTRTOX_H
+#define _LIB_KSTRTOX_H
+
+#define KSTRTOX_OVERFLOW (1U << 31)
+const char *_parse_integer_fixup_radix(const char *s, unsigned int *base);
+unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res);
+
+#endif