aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio_oxnas.txt2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt16
-rw-r--r--Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt2
-rw-r--r--drivers/pinctrl/pinctrl-oxnas.c605
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c232
5 files changed, 734 insertions, 123 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
index 928ed4f43907..966514744df4 100644
--- a/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio_oxnas.txt
@@ -3,7 +3,7 @@
Please refer to gpio.txt for generic information regarding GPIO bindings.
Required properties:
- - compatible: "oxsemi,ox810se-gpio"
+ - compatible: "oxsemi,ox810se-gpio" or "oxsemi,ox820-gpio"
- reg: Base address and length for the device.
- interrupts: The port interrupt shared by all pins.
- gpio-controller: Marks the port as GPIO controller.
diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
index 1685821eea41..35eef433e518 100644
--- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt
@@ -37,6 +37,22 @@ pins it needs, and how they should be configured, with regard to muxer
configuration, drive strength and pullups. If one of these options is
not set, its actual value will be unspecified.
+This driver supports the generic pin multiplexing and configuration
+bindings. For details on each properties, you can refer to
+./pinctrl-bindings.txt.
+
+Required sub-node properties:
+ - pins
+ - function
+
+Optional sub-node properties:
+ - bias-disable
+ - bias-pull-up
+ - bias-pull-down
+ - drive-strength
+
+*** Deprecated pin configuration and multiplexing binding
+
Required subnode-properties:
- allwinner,pins: List of strings containing the pin name.
diff --git a/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
index d6074321f730..09e81a95bbfd 100644
--- a/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/oxnas,pinctrl.txt
@@ -9,7 +9,7 @@ used for a specific device or function. This node represents configurations of
pins, optional function, and optional mux related configuration.
Required properties for pin controller node:
- - compatible: "oxsemi,ox810se-pinctrl"
+ - compatible: "oxsemi,ox810se-pinctrl" or "oxsemi,ox820-pinctrl"
- oxsemi,sys-ctrl: a phandle to the system controller syscon node
Required properties for pin configuration sub-nodes:
diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c
index 917a7d2535d7..494ec9a7573a 100644
--- a/drivers/pinctrl/pinctrl-oxnas.c
+++ b/drivers/pinctrl/pinctrl-oxnas.c
@@ -37,15 +37,24 @@
#define GPIO_BANK_START(bank) ((bank) * PINS_PER_BANK)
-/* Regmap Offsets */
-#define PINMUX_PRIMARY_SEL0 0x0c
-#define PINMUX_SECONDARY_SEL0 0x14
-#define PINMUX_TERTIARY_SEL0 0x8c
-#define PINMUX_PRIMARY_SEL1 0x10
-#define PINMUX_SECONDARY_SEL1 0x18
-#define PINMUX_TERTIARY_SEL1 0x90
-#define PINMUX_PULLUP_CTRL0 0xac
-#define PINMUX_PULLUP_CTRL1 0xb0
+/* OX810 Regmap Offsets */
+#define PINMUX_810_PRIMARY_SEL0 0x0c
+#define PINMUX_810_SECONDARY_SEL0 0x14
+#define PINMUX_810_TERTIARY_SEL0 0x8c
+#define PINMUX_810_PRIMARY_SEL1 0x10
+#define PINMUX_810_SECONDARY_SEL1 0x18
+#define PINMUX_810_TERTIARY_SEL1 0x90
+#define PINMUX_810_PULLUP_CTRL0 0xac
+#define PINMUX_810_PULLUP_CTRL1 0xb0
+
+/* OX820 Regmap Offsets */
+#define PINMUX_820_BANK_OFFSET 0x100000
+#define PINMUX_820_SECONDARY_SEL 0x14
+#define PINMUX_820_TERTIARY_SEL 0x8c
+#define PINMUX_820_QUATERNARY_SEL 0x94
+#define PINMUX_820_DEBUG_SEL 0x9c
+#define PINMUX_820_ALTERNATIVE_SEL 0xa4
+#define PINMUX_820_PULLUP_CTRL 0xac
/* GPIO Registers */
#define INPUT_VALUE 0x00
@@ -87,8 +96,6 @@ struct oxnas_pinctrl {
struct regmap *regmap;
struct device *dev;
struct pinctrl_dev *pctldev;
- const struct pinctrl_pin_desc *pins;
- unsigned int npins;
const struct oxnas_function *functions;
unsigned int nfunctions;
const struct oxnas_pin_group *groups;
@@ -97,7 +104,50 @@ struct oxnas_pinctrl {
unsigned int nbanks;
};
-static const struct pinctrl_pin_desc oxnas_pins[] = {
+struct oxnas_pinctrl_data {
+ struct pinctrl_desc *desc;
+ struct oxnas_pinctrl *pctl;
+};
+
+static const struct pinctrl_pin_desc oxnas_ox810se_pins[] = {
+ PINCTRL_PIN(0, "gpio0"),
+ PINCTRL_PIN(1, "gpio1"),
+ PINCTRL_PIN(2, "gpio2"),
+ PINCTRL_PIN(3, "gpio3"),
+ PINCTRL_PIN(4, "gpio4"),
+ PINCTRL_PIN(5, "gpio5"),
+ PINCTRL_PIN(6, "gpio6"),
+ PINCTRL_PIN(7, "gpio7"),
+ PINCTRL_PIN(8, "gpio8"),
+ PINCTRL_PIN(9, "gpio9"),
+ PINCTRL_PIN(10, "gpio10"),
+ PINCTRL_PIN(11, "gpio11"),
+ PINCTRL_PIN(12, "gpio12"),
+ PINCTRL_PIN(13, "gpio13"),
+ PINCTRL_PIN(14, "gpio14"),
+ PINCTRL_PIN(15, "gpio15"),
+ PINCTRL_PIN(16, "gpio16"),
+ PINCTRL_PIN(17, "gpio17"),
+ PINCTRL_PIN(18, "gpio18"),
+ PINCTRL_PIN(19, "gpio19"),
+ PINCTRL_PIN(20, "gpio20"),
+ PINCTRL_PIN(21, "gpio21"),
+ PINCTRL_PIN(22, "gpio22"),
+ PINCTRL_PIN(23, "gpio23"),
+ PINCTRL_PIN(24, "gpio24"),
+ PINCTRL_PIN(25, "gpio25"),
+ PINCTRL_PIN(26, "gpio26"),
+ PINCTRL_PIN(27, "gpio27"),
+ PINCTRL_PIN(28, "gpio28"),
+ PINCTRL_PIN(29, "gpio29"),
+ PINCTRL_PIN(30, "gpio30"),
+ PINCTRL_PIN(31, "gpio31"),
+ PINCTRL_PIN(32, "gpio32"),
+ PINCTRL_PIN(33, "gpio33"),
+ PINCTRL_PIN(34, "gpio34"),
+};
+
+static const struct pinctrl_pin_desc oxnas_ox820_pins[] = {
PINCTRL_PIN(0, "gpio0"),
PINCTRL_PIN(1, "gpio1"),
PINCTRL_PIN(2, "gpio2"),
@@ -133,9 +183,24 @@ static const struct pinctrl_pin_desc oxnas_pins[] = {
PINCTRL_PIN(32, "gpio32"),
PINCTRL_PIN(33, "gpio33"),
PINCTRL_PIN(34, "gpio34"),
+ PINCTRL_PIN(35, "gpio35"),
+ PINCTRL_PIN(36, "gpio36"),
+ PINCTRL_PIN(37, "gpio37"),
+ PINCTRL_PIN(38, "gpio38"),
+ PINCTRL_PIN(39, "gpio39"),
+ PINCTRL_PIN(40, "gpio40"),
+ PINCTRL_PIN(41, "gpio41"),
+ PINCTRL_PIN(42, "gpio42"),
+ PINCTRL_PIN(43, "gpio43"),
+ PINCTRL_PIN(44, "gpio44"),
+ PINCTRL_PIN(45, "gpio45"),
+ PINCTRL_PIN(46, "gpio46"),
+ PINCTRL_PIN(47, "gpio47"),
+ PINCTRL_PIN(48, "gpio48"),
+ PINCTRL_PIN(49, "gpio49"),
};
-static const char * const oxnas_fct0_group[] = {
+static const char * const oxnas_ox810se_fct0_group[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7",
"gpio8", "gpio9", "gpio10", "gpio11",
@@ -147,7 +212,7 @@ static const char * const oxnas_fct0_group[] = {
"gpio32", "gpio33", "gpio34"
};
-static const char * const oxnas_fct3_group[] = {
+static const char * const oxnas_ox810se_fct3_group[] = {
"gpio0", "gpio1", "gpio2", "gpio3",
"gpio4", "gpio5", "gpio6", "gpio7",
"gpio8", "gpio9",
@@ -158,6 +223,40 @@ static const char * const oxnas_fct3_group[] = {
"gpio34"
};
+static const char * const oxnas_ox820_fct0_group[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+ "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14", "gpio15",
+ "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio28", "gpio29", "gpio30", "gpio31",
+ "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39",
+ "gpio40", "gpio41", "gpio42", "gpio43",
+ "gpio44", "gpio45", "gpio46", "gpio47",
+ "gpio48", "gpio49"
+};
+
+static const char * const oxnas_ox820_fct1_group[] = {
+ "gpio3", "gpio4",
+ "gpio12", "gpio13", "gpio14", "gpio15",
+ "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio20", "gpio21", "gpio22", "gpio23",
+ "gpio24"
+};
+
+static const char * const oxnas_ox820_fct4_group[] = {
+ "gpio5", "gpio6", "gpio7", "gpio8",
+ "gpio24", "gpio25", "gpio26", "gpio27",
+ "gpio40", "gpio41", "gpio42", "gpio43"
+};
+
+static const char * const oxnas_ox820_fct5_group[] = {
+ "gpio28", "gpio29", "gpio30", "gpio31"
+};
+
#define FUNCTION(_name, _gr) \
{ \
.name = #_name, \
@@ -165,9 +264,16 @@ static const char * const oxnas_fct3_group[] = {
.ngroups = ARRAY_SIZE(oxnas_##_gr##_group), \
}
-static const struct oxnas_function oxnas_functions[] = {
- FUNCTION(gpio, fct0),
- FUNCTION(fct3, fct3),
+static const struct oxnas_function oxnas_ox810se_functions[] = {
+ FUNCTION(gpio, ox810se_fct0),
+ FUNCTION(fct3, ox810se_fct3),
+};
+
+static const struct oxnas_function oxnas_ox820_functions[] = {
+ FUNCTION(gpio, ox820_fct0),
+ FUNCTION(fct1, ox820_fct1),
+ FUNCTION(fct4, ox820_fct4),
+ FUNCTION(fct5, ox820_fct5),
};
#define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \
@@ -185,7 +291,7 @@ static const struct oxnas_function oxnas_functions[] = {
.fct = _fct, \
}
-static const struct oxnas_pin_group oxnas_groups[] = {
+static const struct oxnas_pin_group oxnas_ox810se_groups[] = {
OXNAS_PINCTRL_GROUP(0, gpio0,
OXNAS_PINCTRL_FUNCTION(gpio, 0),
OXNAS_PINCTRL_FUNCTION(fct3, 3)),
@@ -282,6 +388,140 @@ static const struct oxnas_pin_group oxnas_groups[] = {
OXNAS_PINCTRL_FUNCTION(fct3, 3)),
};
+static const struct oxnas_pin_group oxnas_ox820_groups[] = {
+ OXNAS_PINCTRL_GROUP(0, gpio0,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(1, gpio1,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(2, gpio2,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(3, gpio3,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(4, gpio4,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(5, gpio5,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(6, gpio6,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(7, gpio7,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(8, gpio8,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(9, gpio9,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(10, gpio10,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(11, gpio11,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(12, gpio12,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(13, gpio13,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(14, gpio14,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(15, gpio15,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(16, gpio16,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(17, gpio17,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(18, gpio18,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(19, gpio19,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(20, gpio20,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(21, gpio21,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(22, gpio22,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(23, gpio23,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1)),
+ OXNAS_PINCTRL_GROUP(24, gpio24,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct1, 1),
+ OXNAS_PINCTRL_FUNCTION(fct4, 5)),
+ OXNAS_PINCTRL_GROUP(25, gpio25,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(26, gpio26,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(27, gpio27,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(28, gpio28,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(29, gpio29,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(30, gpio30,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(31, gpio31,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct5, 5)),
+ OXNAS_PINCTRL_GROUP(32, gpio32,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(33, gpio33,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(34, gpio34,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(35, gpio35,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(36, gpio36,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(37, gpio37,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(38, gpio38,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(39, gpio39,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(40, gpio40,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(41, gpio41,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(42, gpio42,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(43, gpio43,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0),
+ OXNAS_PINCTRL_FUNCTION(fct4, 4)),
+ OXNAS_PINCTRL_GROUP(44, gpio44,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(45, gpio45,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(46, gpio46,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(47, gpio47,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(48, gpio48,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+ OXNAS_PINCTRL_GROUP(49, gpio49,
+ OXNAS_PINCTRL_FUNCTION(gpio, 0)),
+};
+
static inline struct oxnas_gpio_bank *pctl_to_bank(struct oxnas_pinctrl *pctl,
unsigned int pin)
{
@@ -352,8 +592,8 @@ static int oxnas_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
-static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
- unsigned int func, unsigned int group)
+static int oxnas_ox810se_pinmux_enable(struct pinctrl_dev *pctldev,
+ unsigned int func, unsigned int group)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
const struct oxnas_pin_group *pg = &pctl->groups[group];
@@ -371,22 +611,22 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_PRIMARY_SEL1 :
- PINMUX_PRIMARY_SEL0),
+ PINMUX_810_PRIMARY_SEL1 :
+ PINMUX_810_PRIMARY_SEL0),
mask,
(functions->fct == 1 ?
mask : 0));
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_SECONDARY_SEL1 :
- PINMUX_SECONDARY_SEL0),
+ PINMUX_810_SECONDARY_SEL1 :
+ PINMUX_810_SECONDARY_SEL0),
mask,
(functions->fct == 2 ?
mask : 0));
regmap_write_bits(pctl->regmap,
(pg->bank ?
- PINMUX_TERTIARY_SEL1 :
- PINMUX_TERTIARY_SEL0),
+ PINMUX_810_TERTIARY_SEL1 :
+ PINMUX_810_TERTIARY_SEL0),
mask,
(functions->fct == 3 ?
mask : 0));
@@ -402,9 +642,64 @@ static int oxnas_pinmux_enable(struct pinctrl_dev *pctldev,
return -EINVAL;
}
-static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned int offset)
+static int oxnas_ox820_pinmux_enable(struct pinctrl_dev *pctldev,
+ unsigned int func, unsigned int group)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ const struct oxnas_pin_group *pg = &pctl->groups[group];
+ const struct oxnas_function *pf = &pctl->functions[func];
+ const char *fname = pf->name;
+ struct oxnas_desc_function *functions = pg->functions;
+ unsigned int offset = (pg->bank ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(pg->pin);
+
+ while (functions->name) {
+ if (!strcmp(functions->name, fname)) {
+ dev_dbg(pctl->dev,
+ "setting function %s bank %d pin %d fct %d mask %x\n",
+ fname, pg->bank, pg->pin,
+ functions->fct, mask);
+
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_SECONDARY_SEL,
+ mask,
+ (functions->fct == 1 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_TERTIARY_SEL,
+ mask,
+ (functions->fct == 2 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_QUATERNARY_SEL,
+ mask,
+ (functions->fct == 3 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_DEBUG_SEL,
+ mask,
+ (functions->fct == 4 ?
+ mask : 0));
+ regmap_write_bits(pctl->regmap,
+ offset + PINMUX_820_ALTERNATIVE_SEL,
+ mask,
+ (functions->fct == 5 ?
+ mask : 0));
+
+ return 0;
+ }
+
+ functions++;
+ }
+
+ dev_err(pctl->dev, "cannot mux pin %u to function %u\n", group, func);
+
+ return -EINVAL;
+}
+
+static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc);
@@ -415,18 +710,49 @@ static int oxnas_gpio_request_enable(struct pinctrl_dev *pctldev,
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_PRIMARY_SEL1 :
- PINMUX_PRIMARY_SEL0),
+ PINMUX_810_PRIMARY_SEL1 :
+ PINMUX_810_PRIMARY_SEL0),
mask, 0);
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_SECONDARY_SEL1 :
- PINMUX_SECONDARY_SEL0),
+ PINMUX_810_SECONDARY_SEL1 :
+ PINMUX_810_SECONDARY_SEL0),
mask, 0);
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_TERTIARY_SEL1 :
- PINMUX_TERTIARY_SEL0),
+ PINMUX_810_TERTIARY_SEL1 :
+ PINMUX_810_TERTIARY_SEL0),
+ mask, 0);
+
+ return 0;
+}
+
+static int oxnas_ox820_gpio_request_enable(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned int offset)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = gpiochip_get_data(range->gc);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(offset - bank->gpio_chip.base);
+
+ dev_dbg(pctl->dev, "requesting gpio %d in bank %d (id %d) with mask 0x%x\n",
+ offset, bank->gpio_chip.base, bank->id, mask);
+
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_SECONDARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_TERTIARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_QUATERNARY_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_DEBUG_SEL,
+ mask, 0);
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_ALTERNATIVE_SEL,
mask, 0);
return 0;
@@ -498,17 +824,26 @@ static int oxnas_gpio_set_direction(struct pinctrl_dev *pctldev,
return 0;
}
-static const struct pinmux_ops oxnas_pinmux_ops = {
+static const struct pinmux_ops oxnas_ox810se_pinmux_ops = {
.get_functions_count = oxnas_pinmux_get_functions_count,
.get_function_name = oxnas_pinmux_get_function_name,
.get_function_groups = oxnas_pinmux_get_function_groups,
- .set_mux = oxnas_pinmux_enable,
- .gpio_request_enable = oxnas_gpio_request_enable,
+ .set_mux = oxnas_ox810se_pinmux_enable,
+ .gpio_request_enable = oxnas_ox810se_gpio_request_enable,
.gpio_set_direction = oxnas_gpio_set_direction,
};
-static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *config)
+static const struct pinmux_ops oxnas_ox820_pinmux_ops = {
+ .get_functions_count = oxnas_pinmux_get_functions_count,
+ .get_function_name = oxnas_pinmux_get_function_name,
+ .get_function_groups = oxnas_pinmux_get_function_groups,
+ .set_mux = oxnas_ox820_pinmux_enable,
+ .gpio_request_enable = oxnas_ox820_gpio_request_enable,
+ .gpio_set_direction = oxnas_gpio_set_direction,
+};
+
+static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
@@ -521,8 +856,38 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
case PIN_CONFIG_BIAS_PULL_UP:
ret = regmap_read(pctl->regmap,
(bank->id ?
- PINMUX_PULLUP_CTRL1 :
- PINMUX_PULLUP_CTRL0),
+ PINMUX_810_PULLUP_CTRL1 :
+ PINMUX_810_PULLUP_CTRL0),
+ &arg);
+ if (ret)
+ return ret;
+
+ arg = !!(arg & mask);
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+
+ *config = pinconf_to_config_packed(param, arg);
+
+ return 0;
+}
+
+static int oxnas_ox820_pinconf_get(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *config)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+ unsigned int param = pinconf_to_config_param(*config);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ u32 mask = BIT(pin - bank->gpio_chip.base);
+ int ret;
+ u32 arg;
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = regmap_read(pctl->regmap,
+ bank_offset + PINMUX_820_PULLUP_CTRL,
&arg);
if (ret)
return ret;
@@ -538,8 +903,9 @@ static int oxnas_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
-static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
- unsigned long *configs, unsigned int num_configs)
+static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
{
struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
@@ -561,8 +927,8 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
dev_dbg(pctl->dev, " pullup\n");
regmap_write_bits(pctl->regmap,
(bank->id ?
- PINMUX_PULLUP_CTRL1 :
- PINMUX_PULLUP_CTRL0),
+ PINMUX_810_PULLUP_CTRL1 :
+ PINMUX_810_PULLUP_CTRL0),
mask, mask);
break;
default:
@@ -575,18 +941,53 @@ static int oxnas_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
return 0;
}
-static const struct pinconf_ops oxnas_pinconf_ops = {
- .pin_config_get = oxnas_pinconf_get,
- .pin_config_set = oxnas_pinconf_set,
+static int oxnas_ox820_pinconf_set(struct pinctrl_dev *pctldev,
+ unsigned int pin, unsigned long *configs,
+ unsigned int num_configs)
+{
+ struct oxnas_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct oxnas_gpio_bank *bank = pctl_to_bank(pctl, pin);
+ unsigned int bank_offset = (bank->id ? PINMUX_820_BANK_OFFSET : 0);
+ unsigned int param;
+ u32 arg;
+ unsigned int i;
+ u32 offset = pin - bank->gpio_chip.base;
+ u32 mask = BIT(offset);
+
+ dev_dbg(pctl->dev, "setting pin %d bank %d mask 0x%x\n",
+ pin, bank->gpio_chip.base, mask);
+
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_PULL_UP:
+ dev_dbg(pctl->dev, " pullup\n");
+ regmap_write_bits(pctl->regmap,
+ bank_offset + PINMUX_820_PULLUP_CTRL,
+ mask, mask);
+ break;
+ default:
+ dev_err(pctl->dev, "Property %u not supported\n",
+ param);
+ return -ENOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+static const struct pinconf_ops oxnas_ox810se_pinconf_ops = {
+ .pin_config_get = oxnas_ox810se_pinconf_get,
+ .pin_config_set = oxnas_ox810se_pinconf_set,
.is_generic = true,
};
-static struct pinctrl_desc oxnas_pinctrl_desc = {
- .name = "oxnas-pinctrl",
- .pctlops = &oxnas_pinctrl_ops,
- .pmxops = &oxnas_pinmux_ops,
- .confops = &oxnas_pinconf_ops,
- .owner = THIS_MODULE,
+static const struct pinconf_ops oxnas_ox820_pinconf_ops = {
+ .pin_config_get = oxnas_ox820_pinconf_get,
+ .pin_config_set = oxnas_ox820_pinconf_set,
+ .is_generic = true,
};
static void oxnas_gpio_irq_ack(struct irq_data *data)
@@ -699,10 +1100,78 @@ static struct oxnas_gpio_bank oxnas_gpio_banks[] = {
GPIO_BANK(1),
};
+static struct oxnas_pinctrl ox810se_pinctrl = {
+ .functions = oxnas_ox810se_functions,
+ .nfunctions = ARRAY_SIZE(oxnas_ox810se_functions),
+ .groups = oxnas_ox810se_groups,
+ .ngroups = ARRAY_SIZE(oxnas_ox810se_groups),
+ .gpio_banks = oxnas_gpio_banks,
+ .nbanks = ARRAY_SIZE(oxnas_gpio_banks),
+};
+
+static struct pinctrl_desc oxnas_ox810se_pinctrl_desc = {
+ .name = "oxnas-pinctrl",
+ .pins = oxnas_ox810se_pins,
+ .npins = ARRAY_SIZE(oxnas_ox810se_pins),
+ .pctlops = &oxnas_pinctrl_ops,
+ .pmxops = &oxnas_ox810se_pinmux_ops,
+ .confops = &oxnas_ox810se_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static struct oxnas_pinctrl ox820_pinctrl = {
+ .functions = oxnas_ox820_functions,
+ .nfunctions = ARRAY_SIZE(oxnas_ox820_functions),
+ .groups = oxnas_ox820_groups,
+ .ngroups = ARRAY_SIZE(oxnas_ox820_groups),
+ .gpio_banks = oxnas_gpio_banks,
+ .nbanks = ARRAY_SIZE(oxnas_gpio_banks),
+};
+
+static struct pinctrl_desc oxnas_ox820_pinctrl_desc = {
+ .name = "oxnas-pinctrl",
+ .pins = oxnas_ox820_pins,
+ .npins = ARRAY_SIZE(oxnas_ox820_pins),
+ .pctlops = &oxnas_pinctrl_ops,
+ .pmxops = &oxnas_ox820_pinmux_ops,
+ .confops = &oxnas_ox820_pinconf_ops,
+ .owner = THIS_MODULE,
+};
+
+static struct oxnas_pinctrl_data oxnas_ox810se_pinctrl_data = {
+ .desc = &oxnas_ox810se_pinctrl_desc,
+ .pctl = &ox810se_pinctrl,
+};
+
+static struct oxnas_pinctrl_data oxnas_ox820_pinctrl_data = {
+ .desc = &oxnas_ox820_pinctrl_desc,
+ .pctl = &ox820_pinctrl,
+};
+
+static const struct of_device_id oxnas_pinctrl_of_match[] = {
+ { .compatible = "oxsemi,ox810se-pinctrl",
+ .data = &oxnas_ox810se_pinctrl_data
+ },
+ { .compatible = "oxsemi,ox820-pinctrl",
+ .data = &oxnas_ox820_pinctrl_data,
+ },
+ { },
+};
+
static int oxnas_pinctrl_probe(struct platform_device *pdev)
{
+ const struct of_device_id *id;
+ const struct oxnas_pinctrl_data *data;
struct oxnas_pinctrl *pctl;
+ id = of_match_node(oxnas_pinctrl_of_match, pdev->dev.of_node);
+ if (!id)
+ return -ENODEV;
+
+ data = id->data;
+ if (!data || !data->pctl || !data->desc)
+ return -EINVAL;
+
pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
if (!pctl)
return -ENOMEM;
@@ -716,20 +1185,14 @@ static int oxnas_pinctrl_probe(struct platform_device *pdev)
return -ENODEV;
}
- pctl->pins = oxnas_pins;
- pctl->npins = ARRAY_SIZE(oxnas_pins);
- pctl->functions = oxnas_functions;
- pctl->nfunctions = ARRAY_SIZE(oxnas_functions);
- pctl->groups = oxnas_groups;
- pctl->ngroups = ARRAY_SIZE(oxnas_groups);
- pctl->gpio_banks = oxnas_gpio_banks;
- pctl->nbanks = ARRAY_SIZE(oxnas_gpio_banks);
-
- oxnas_pinctrl_desc.pins = pctl->pins;
- oxnas_pinctrl_desc.npins = pctl->npins;
+ pctl->functions = data->pctl->functions;
+ pctl->nfunctions = data->pctl->nfunctions;
+ pctl->groups = data->pctl->groups;
+ pctl->ngroups = data->pctl->ngroups;
+ pctl->gpio_banks = data->pctl->gpio_banks;
+ pctl->nbanks = data->pctl->nbanks;
- pctl->pctldev = pinctrl_register(&oxnas_pinctrl_desc,
- &pdev->dev, pctl);
+ pctl->pctldev = pinctrl_register(data->desc, &pdev->dev, pctl);
if (IS_ERR(pctl->pctldev)) {
dev_err(&pdev->dev, "Failed to register pinctrl device\n");
return PTR_ERR(pctl->pctldev);
@@ -805,11 +1268,6 @@ static int oxnas_gpio_probe(struct platform_device *pdev)
return 0;
}
-static const struct of_device_id oxnas_pinctrl_of_match[] = {
- { .compatible = "oxsemi,ox810se-pinctrl", },
- { },
-};
-
static struct platform_driver oxnas_pinctrl_driver = {
.driver = {
.name = "oxnas-pinctrl",
@@ -821,6 +1279,7 @@ static struct platform_driver oxnas_pinctrl_driver = {
static const struct of_device_id oxnas_gpio_of_match[] = {
{ .compatible = "oxsemi,ox810se-gpio", },
+ { .compatible = "oxsemi,ox820-gpio", },
{ },
};
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 0facbea5f465..7e27204d3eea 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -28,6 +28,8 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
#include "../core.h"
#include "pinctrl-sunxi.h"
@@ -145,6 +147,156 @@ static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
return 0;
}
+static bool sunxi_pctrl_has_bias_prop(struct device_node *node)
+{
+ return of_find_property(node, "bias-pull-up", NULL) ||
+ of_find_property(node, "bias-pull-down", NULL) ||
+ of_find_property(node, "bias-disable", NULL) ||
+ of_find_property(node, "allwinner,pull", NULL);
+}
+
+static bool sunxi_pctrl_has_drive_prop(struct device_node *node)
+{
+ return of_find_property(node, "drive-strength", NULL) ||
+ of_find_property(node, "allwinner,drive", NULL);
+}
+
+static int sunxi_pctrl_parse_bias_prop(struct device_node *node)
+{
+ u32 val;
+
+ /* Try the new style binding */
+ if (of_find_property(node, "bias-pull-up", NULL))
+ return PIN_CONFIG_BIAS_PULL_UP;
+
+ if (of_find_property(node, "bias-pull-down", NULL))
+ return PIN_CONFIG_BIAS_PULL_DOWN;
+
+ if (of_find_property(node, "bias-disable", NULL))
+ return PIN_CONFIG_BIAS_DISABLE;
+
+ /* And fall back to the old binding */
+ if (of_property_read_u32(node, "allwinner,pull", &val))
+ return -EINVAL;
+
+ switch (val) {
+ case SUN4I_PINCTRL_NO_PULL:
+ return PIN_CONFIG_BIAS_DISABLE;
+ case SUN4I_PINCTRL_PULL_UP:
+ return PIN_CONFIG_BIAS_PULL_UP;
+ case SUN4I_PINCTRL_PULL_DOWN:
+ return PIN_CONFIG_BIAS_PULL_DOWN;
+ }
+
+ return -EINVAL;
+}
+
+static int sunxi_pctrl_parse_drive_prop(struct device_node *node)
+{
+ u32 val;
+
+ /* Try the new style binding */
+ if (!of_property_read_u32(node, "drive-strength", &val)) {
+ /* We can't go below 10mA ... */
+ if (val < 10)
+ return -EINVAL;
+
+ /* ... and only up to 40 mA ... */
+ if (val > 40)
+ val = 40;
+
+ /* by steps of 10 mA */
+ return rounddown(val, 10);
+ }
+
+ /* And then fall back to the old binding */
+ if (of_property_read_u32(node, "allwinner,drive", &val))
+ return -EINVAL;
+
+ return (val + 1) * 10;
+}
+
+static const char *sunxi_pctrl_parse_function_prop(struct device_node *node)
+{
+ const char *function;
+ int ret;
+
+ /* Try the generic binding */
+ ret = of_property_read_string(node, "function", &function);
+ if (!ret)
+ return function;
+
+ /* And fall back to our legacy one */
+ ret = of_property_read_string(node, "allwinner,function", &function);
+ if (!ret)
+ return function;
+
+ return NULL;
+}
+
+static const char *sunxi_pctrl_find_pins_prop(struct device_node *node,
+ int *npins)
+{
+ int count;
+
+ /* Try the generic binding */
+ count = of_property_count_strings(node, "pins");
+ if (count > 0) {
+ *npins = count;
+ return "pins";
+ }
+
+ /* And fall back to our legacy one */
+ count = of_property_count_strings(node, "allwinner,pins");
+ if (count > 0) {
+ *npins = count;
+ return "allwinner,pins";
+ }
+
+ return NULL;
+}
+
+static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
+ unsigned int *len)
+{
+ unsigned long *pinconfig;
+ unsigned int configlen = 0, idx = 0;
+
+ if (sunxi_pctrl_has_drive_prop(node))
+ configlen++;
+ if (sunxi_pctrl_has_bias_prop(node))
+ configlen++;
+
+ pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
+ if (!pinconfig)
+ return NULL;
+
+ if (sunxi_pctrl_has_drive_prop(node)) {
+ int drive = sunxi_pctrl_parse_drive_prop(node);
+ if (drive < 0)
+ goto err_free;
+
+ pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
+ drive);
+ }
+
+ if (sunxi_pctrl_has_bias_prop(node)) {
+ int pull = sunxi_pctrl_parse_bias_prop(node);
+ if (pull < 0)
+ goto err_free;
+
+ pinconfig[idx++] = pinconf_to_config_packed(pull, 0);
+ }
+
+
+ *len = configlen;
+ return pinconfig;
+
+err_free:
+ kfree(pinconfig);
+ return NULL;
+}
+
static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct device_node *node,
struct pinctrl_map **map,
@@ -153,38 +305,45 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
unsigned long *pinconfig;
struct property *prop;
- const char *function;
+ const char *function, *pin_prop;
const char *group;
- int ret, nmaps, i = 0;
- u32 val;
+ int ret, npins, nmaps, configlen = 0, i = 0;
*map = NULL;
*num_maps = 0;
- ret = of_property_read_string(node, "allwinner,function", &function);
- if (ret) {
- dev_err(pctl->dev,
- "missing allwinner,function property in node %s\n",
+ function = sunxi_pctrl_parse_function_prop(node);
+ if (!function) {
+ dev_err(pctl->dev, "missing function property in node %s\n",
node->name);
return -EINVAL;
}
- nmaps = of_property_count_strings(node, "allwinner,pins") * 2;
- if (nmaps < 0) {
- dev_err(pctl->dev,
- "missing allwinner,pins property in node %s\n",
+ pin_prop = sunxi_pctrl_find_pins_prop(node, &npins);
+ if (!pin_prop) {
+ dev_err(pctl->dev, "missing pins property in node %s\n",
node->name);
return -EINVAL;
}
+ /*
+ * We have two maps for each pin: one for the function, one
+ * for the configuration (bias, strength, etc)
+ */
+ nmaps = npins * 2;
*map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
- of_property_for_each_string(node, "allwinner,pins", prop, group) {
+ pinconfig = sunxi_pctrl_build_pin_config(node, &configlen);
+ if (!pinconfig) {
+ ret = -EINVAL;
+ goto err_free_map;
+ }
+
+ of_property_for_each_string(node, pin_prop, prop, group) {
struct sunxi_pinctrl_group *grp =
sunxi_pinctrl_find_group_by_name(pctl, group);
- int j = 0, configlen = 0;
if (!grp) {
dev_err(pctl->dev, "unknown pin %s", group);
@@ -207,34 +366,6 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
(*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP;
(*map)[i].data.configs.group_or_pin = group;
-
- if (of_find_property(node, "allwinner,drive", NULL))
- configlen++;
- if (of_find_property(node, "allwinner,pull", NULL))
- configlen++;
-
- pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
- if (!pinconfig) {
- kfree(*map);
- return -ENOMEM;
- }
-
- if (!of_property_read_u32(node, "allwinner,drive", &val)) {
- u16 strength = (val + 1) * 10;
- pinconfig[j++] =
- pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH,
- strength);
- }
-
- if (!of_property_read_u32(node, "allwinner,pull", &val)) {
- enum pin_config_param pull = PIN_CONFIG_END;
- if (val == 1)
- pull = PIN_CONFIG_BIAS_PULL_UP;
- else if (val == 2)
- pull = PIN_CONFIG_BIAS_PULL_DOWN;
- pinconfig[j++] = pinconf_to_config_packed(pull, 0);
- }
-
(*map)[i].data.configs.configs = pinconfig;
(*map)[i].data.configs.num_configs = configlen;
@@ -244,19 +375,18 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
*num_maps = nmaps;
return 0;
+
+err_free_map:
+ kfree(map);
+ return ret;
}
static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev,
struct pinctrl_map *map,
unsigned num_maps)
{
- int i;
-
- for (i = 0; i < num_maps; i++) {
- if (map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP)
- kfree(map[i].data.configs.configs);
- }
-
+ /* All the maps have the same pin config, free only the first one */
+ kfree(map[0].data.configs.configs);
kfree(map);
}
@@ -317,6 +447,12 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev,
| dlevel << sunxi_dlevel_offset(pin),
pctl->membase + sunxi_dlevel_reg(pin));
break;
+ case PIN_CONFIG_BIAS_DISABLE:
+ val = readl(pctl->membase + sunxi_pull_reg(pin));
+ mask = PULL_PINS_MASK << sunxi_pull_offset(pin);
+ writel((val & ~mask),
+ pctl->membase + sunxi_pull_reg(pin));
+ break;
case PIN_CONFIG_BIAS_PULL_UP:
val = readl(pctl->membase + sunxi_pull_reg(pin));
mask = PULL_PINS_MASK << sunxi_pull_offset(pin);