From 02609a2335fd21c34288ef2ab532a0c2e9f20b6a Mon Sep 17 00:00:00 2001 From: Ulrich Hecht Date: Wed, 14 Sep 2016 18:46:08 +0200 Subject: pinctrl: sh-pfc: r8a7796: Add I2C pin support Signed-off-by: Ulrich Hecht Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 77 ++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index dc9b671ccf2e..42db74581d49 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1490,6 +1490,57 @@ static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), }; +/* - I2C -------------------------------------------------------------------- */ +static const unsigned int i2c1_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 11), RCAR_GP_PIN(5, 10), +}; +static const unsigned int i2c1_a_mux[] = { + SDA1_A_MARK, SCL1_A_MARK, +}; +static const unsigned int i2c1_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 23), +}; +static const unsigned int i2c1_b_mux[] = { + SDA1_B_MARK, SCL1_B_MARK, +}; +static const unsigned int i2c2_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4), +}; +static const unsigned int i2c2_a_mux[] = { + SDA2_A_MARK, SCL2_A_MARK, +}; +static const unsigned int i2c2_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(3, 13), RCAR_GP_PIN(3, 12), +}; +static const unsigned int i2c2_b_mux[] = { + SDA2_B_MARK, SCL2_B_MARK, +}; +static const unsigned int i2c6_a_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 11), +}; +static const unsigned int i2c6_a_mux[] = { + SDA6_A_MARK, SCL6_A_MARK, +}; +static const unsigned int i2c6_b_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25), +}; +static const unsigned int i2c6_b_mux[] = { + SDA6_B_MARK, SCL6_B_MARK, +}; +static const unsigned int i2c6_c_pins[] = { + /* SDA, SCL */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), +}; +static const unsigned int i2c6_c_mux[] = { + SDA6_C_MARK, SCL6_C_MARK, +}; + /* - SCIF0 ------------------------------------------------------------------ */ static const unsigned int scif0_data_pins[] = { /* RX, TX */ @@ -1912,6 +1963,13 @@ static const unsigned int sdhi3_ds_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(i2c1_a), + SH_PFC_PIN_GROUP(i2c1_b), + SH_PFC_PIN_GROUP(i2c2_a), + SH_PFC_PIN_GROUP(i2c2_b), + SH_PFC_PIN_GROUP(i2c6_a), + SH_PFC_PIN_GROUP(i2c6_b), + SH_PFC_PIN_GROUP(i2c6_c), SH_PFC_PIN_GROUP(scif0_data), SH_PFC_PIN_GROUP(scif0_clk), SH_PFC_PIN_GROUP(scif0_ctrl), @@ -1969,6 +2027,22 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ds), }; +static const char * const i2c1_groups[] = { + "i2c1_a", + "i2c1_b", +}; + +static const char * const i2c2_groups[] = { + "i2c2_a", + "i2c2_b", +}; + +static const char * const i2c6_groups[] = { + "i2c6_a", + "i2c6_b", + "i2c6_c", +}; + static const char * const scif0_groups[] = { "scif0_data", "scif0_clk", @@ -2058,6 +2132,9 @@ static const char * const sdhi3_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(i2c1), + SH_PFC_FUNCTION(i2c2), + SH_PFC_FUNCTION(i2c6), SH_PFC_FUNCTION(scif0), SH_PFC_FUNCTION(scif1), SH_PFC_FUNCTION(scif2), -- cgit 1.4.1 From fb0828316bf655d26c74321240bbf83b2a1d89ad Mon Sep 17 00:00:00 2001 From: Ramesh Shanmugasundaram Date: Thu, 13 Oct 2016 10:29:14 +0100 Subject: pinctrl: sh-pfc: r8a7796: Add DRIF support This patch adds DRIF[0-3] pinmux support for r8a7796 SoC. Signed-off-by: Ramesh Shanmugasundaram Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 291 +++++++++++++++++++++++++++++++++++ 1 file changed, 291 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 42db74581d49..dd23198492b5 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1490,6 +1490,221 @@ static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), }; +/* - DRIF0 --------------------------------------------------------------- */ +static const unsigned int drif0_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9), +}; +static const unsigned int drif0_ctrl_a_mux[] = { + RIF0_CLK_A_MARK, RIF0_SYNC_A_MARK, +}; +static const unsigned int drif0_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int drif0_data0_a_mux[] = { + RIF0_D0_A_MARK, +}; +static const unsigned int drif0_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 7), +}; +static const unsigned int drif0_data1_a_mux[] = { + RIF0_D1_A_MARK, +}; +static const unsigned int drif0_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 4), +}; +static const unsigned int drif0_ctrl_b_mux[] = { + RIF0_CLK_B_MARK, RIF0_SYNC_B_MARK, +}; +static const unsigned int drif0_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 1), +}; +static const unsigned int drif0_data0_b_mux[] = { + RIF0_D0_B_MARK, +}; +static const unsigned int drif0_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 2), +}; +static const unsigned int drif0_data1_b_mux[] = { + RIF0_D1_B_MARK, +}; +static const unsigned int drif0_ctrl_c_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 15), +}; +static const unsigned int drif0_ctrl_c_mux[] = { + RIF0_CLK_C_MARK, RIF0_SYNC_C_MARK, +}; +static const unsigned int drif0_data0_c_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 13), +}; +static const unsigned int drif0_data0_c_mux[] = { + RIF0_D0_C_MARK, +}; +static const unsigned int drif0_data1_c_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 14), +}; +static const unsigned int drif0_data1_c_mux[] = { + RIF0_D1_C_MARK, +}; +/* - DRIF1 --------------------------------------------------------------- */ +static const unsigned int drif1_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18), +}; +static const unsigned int drif1_ctrl_a_mux[] = { + RIF1_CLK_A_MARK, RIF1_SYNC_A_MARK, +}; +static const unsigned int drif1_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 19), +}; +static const unsigned int drif1_data0_a_mux[] = { + RIF1_D0_A_MARK, +}; +static const unsigned int drif1_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int drif1_data1_a_mux[] = { + RIF1_D1_A_MARK, +}; +static const unsigned int drif1_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 9), RCAR_GP_PIN(5, 3), +}; +static const unsigned int drif1_ctrl_b_mux[] = { + RIF1_CLK_B_MARK, RIF1_SYNC_B_MARK, +}; +static const unsigned int drif1_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 7), +}; +static const unsigned int drif1_data0_b_mux[] = { + RIF1_D0_B_MARK, +}; +static const unsigned int drif1_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 8), +}; +static const unsigned int drif1_data1_b_mux[] = { + RIF1_D1_B_MARK, +}; +static const unsigned int drif1_ctrl_c_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 11), +}; +static const unsigned int drif1_ctrl_c_mux[] = { + RIF1_CLK_C_MARK, RIF1_SYNC_C_MARK, +}; +static const unsigned int drif1_data0_c_pins[] = { + /* D0 */ + RCAR_GP_PIN(5, 6), +}; +static const unsigned int drif1_data0_c_mux[] = { + RIF1_D0_C_MARK, +}; +static const unsigned int drif1_data1_c_pins[] = { + /* D1 */ + RCAR_GP_PIN(5, 10), +}; +static const unsigned int drif1_data1_c_mux[] = { + RIF1_D1_C_MARK, +}; +/* - DRIF2 --------------------------------------------------------------- */ +static const unsigned int drif2_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9), +}; +static const unsigned int drif2_ctrl_a_mux[] = { + RIF2_CLK_A_MARK, RIF2_SYNC_A_MARK, +}; +static const unsigned int drif2_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 7), +}; +static const unsigned int drif2_data0_a_mux[] = { + RIF2_D0_A_MARK, +}; +static const unsigned int drif2_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 10), +}; +static const unsigned int drif2_data1_a_mux[] = { + RIF2_D1_A_MARK, +}; +static const unsigned int drif2_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 26), RCAR_GP_PIN(6, 27), +}; +static const unsigned int drif2_ctrl_b_mux[] = { + RIF2_CLK_B_MARK, RIF2_SYNC_B_MARK, +}; +static const unsigned int drif2_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 30), +}; +static const unsigned int drif2_data0_b_mux[] = { + RIF2_D0_B_MARK, +}; +static const unsigned int drif2_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 31), +}; +static const unsigned int drif2_data1_b_mux[] = { + RIF2_D1_B_MARK, +}; +/* - DRIF3 --------------------------------------------------------------- */ +static const unsigned int drif3_ctrl_a_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18), +}; +static const unsigned int drif3_ctrl_a_mux[] = { + RIF3_CLK_A_MARK, RIF3_SYNC_A_MARK, +}; +static const unsigned int drif3_data0_a_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 19), +}; +static const unsigned int drif3_data0_a_mux[] = { + RIF3_D0_A_MARK, +}; +static const unsigned int drif3_data1_a_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 20), +}; +static const unsigned int drif3_data1_a_mux[] = { + RIF3_D1_A_MARK, +}; +static const unsigned int drif3_ctrl_b_pins[] = { + /* CLK, SYNC */ + RCAR_GP_PIN(6, 24), RCAR_GP_PIN(6, 25), +}; +static const unsigned int drif3_ctrl_b_mux[] = { + RIF3_CLK_B_MARK, RIF3_SYNC_B_MARK, +}; +static const unsigned int drif3_data0_b_pins[] = { + /* D0 */ + RCAR_GP_PIN(6, 28), +}; +static const unsigned int drif3_data0_b_mux[] = { + RIF3_D0_B_MARK, +}; +static const unsigned int drif3_data1_b_pins[] = { + /* D1 */ + RCAR_GP_PIN(6, 29), +}; +static const unsigned int drif3_data1_b_mux[] = { + RIF3_D1_B_MARK, +}; + /* - I2C -------------------------------------------------------------------- */ static const unsigned int i2c1_a_pins[] = { /* SDA, SCL */ @@ -1963,6 +2178,36 @@ static const unsigned int sdhi3_ds_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(drif0_ctrl_a), + SH_PFC_PIN_GROUP(drif0_data0_a), + SH_PFC_PIN_GROUP(drif0_data1_a), + SH_PFC_PIN_GROUP(drif0_ctrl_b), + SH_PFC_PIN_GROUP(drif0_data0_b), + SH_PFC_PIN_GROUP(drif0_data1_b), + SH_PFC_PIN_GROUP(drif0_ctrl_c), + SH_PFC_PIN_GROUP(drif0_data0_c), + SH_PFC_PIN_GROUP(drif0_data1_c), + SH_PFC_PIN_GROUP(drif1_ctrl_a), + SH_PFC_PIN_GROUP(drif1_data0_a), + SH_PFC_PIN_GROUP(drif1_data1_a), + SH_PFC_PIN_GROUP(drif1_ctrl_b), + SH_PFC_PIN_GROUP(drif1_data0_b), + SH_PFC_PIN_GROUP(drif1_data1_b), + SH_PFC_PIN_GROUP(drif1_ctrl_c), + SH_PFC_PIN_GROUP(drif1_data0_c), + SH_PFC_PIN_GROUP(drif1_data1_c), + SH_PFC_PIN_GROUP(drif2_ctrl_a), + SH_PFC_PIN_GROUP(drif2_data0_a), + SH_PFC_PIN_GROUP(drif2_data1_a), + SH_PFC_PIN_GROUP(drif2_ctrl_b), + SH_PFC_PIN_GROUP(drif2_data0_b), + SH_PFC_PIN_GROUP(drif2_data1_b), + SH_PFC_PIN_GROUP(drif3_ctrl_a), + SH_PFC_PIN_GROUP(drif3_data0_a), + SH_PFC_PIN_GROUP(drif3_data1_a), + SH_PFC_PIN_GROUP(drif3_ctrl_b), + SH_PFC_PIN_GROUP(drif3_data0_b), + SH_PFC_PIN_GROUP(drif3_data1_b), SH_PFC_PIN_GROUP(i2c1_a), SH_PFC_PIN_GROUP(i2c1_b), SH_PFC_PIN_GROUP(i2c2_a), @@ -2027,6 +2272,48 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ds), }; +static const char * const drif0_groups[] = { + "drif0_ctrl_a", + "drif0_data0_a", + "drif0_data1_a", + "drif0_ctrl_b", + "drif0_data0_b", + "drif0_data1_b", + "drif0_ctrl_c", + "drif0_data0_c", + "drif0_data1_c", +}; + +static const char * const drif1_groups[] = { + "drif1_ctrl_a", + "drif1_data0_a", + "drif1_data1_a", + "drif1_ctrl_b", + "drif1_data0_b", + "drif1_data1_b", + "drif1_ctrl_c", + "drif1_data0_c", + "drif1_data1_c", +}; + +static const char * const drif2_groups[] = { + "drif2_ctrl_a", + "drif2_data0_a", + "drif2_data1_a", + "drif2_ctrl_b", + "drif2_data0_b", + "drif2_data1_b", +}; + +static const char * const drif3_groups[] = { + "drif3_ctrl_a", + "drif3_data0_a", + "drif3_data1_a", + "drif3_ctrl_b", + "drif3_data0_b", + "drif3_data1_b", +}; + static const char * const i2c1_groups[] = { "i2c1_a", "i2c1_b", @@ -2132,6 +2419,10 @@ static const char * const sdhi3_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(drif0), + SH_PFC_FUNCTION(drif1), + SH_PFC_FUNCTION(drif2), + SH_PFC_FUNCTION(drif3), SH_PFC_FUNCTION(i2c1), SH_PFC_FUNCTION(i2c2), SH_PFC_FUNCTION(i2c6), -- cgit 1.4.1 From f233dbca6227703eaae2f67d6d9c79819773f16b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:45:59 +0200 Subject: pinctrl: sunxi: Rework the pin config building code In order to support more easily the generic pinctrl properties, rework the pinctrl maps configuration and split it into several sub-functions. One of the side-effects from that rework is that we only parse the pin configuration once, since it's going to be common to every pin, instead of having to parsing once for each pin. Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 178 +++++++++++++++++++++++++--------- 1 file changed, 130 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 0facbea5f465..cf7eb799c6de 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -145,6 +145,110 @@ 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, "allwinner,pull", NULL); +} + +static bool sunxi_pctrl_has_drive_prop(struct device_node *node) +{ + return of_find_property(node, "allwinner,drive", NULL); +} + +static int sunxi_pctrl_parse_bias_prop(struct device_node *node) +{ + u32 val; + + if (of_property_read_u32(node, "allwinner,pull", &val)) + return -EINVAL; + + switch (val) { + case 1: + return PIN_CONFIG_BIAS_PULL_UP; + case 2: + return PIN_CONFIG_BIAS_PULL_DOWN; + } + + return -EINVAL; +} + +static int sunxi_pctrl_parse_drive_prop(struct device_node *node) +{ + u32 val; + + 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; + + 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; + + 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 +257,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 +318,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 +327,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); } -- cgit 1.4.1 From 42676fa4aa87eda4fc762df495d4bde2ddc4bfce Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:46:00 +0200 Subject: pinctrl: sunxi: Use macros from bindings header file for DT parsing Since we have some bindings header for our hardcoded flags, let's use them when we can. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index cf7eb799c6de..62a9d012b35f 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -28,6 +28,8 @@ #include #include +#include + #include "../core.h" #include "pinctrl-sunxi.h" @@ -163,9 +165,9 @@ static int sunxi_pctrl_parse_bias_prop(struct device_node *node) return -EINVAL; switch (val) { - case 1: + case SUN4I_PINCTRL_PULL_UP: return PIN_CONFIG_BIAS_PULL_UP; - case 2: + case SUN4I_PINCTRL_PULL_DOWN: return PIN_CONFIG_BIAS_PULL_DOWN; } -- cgit 1.4.1 From 07fe64ba213f36ca8f6ffd8c4d5893f022744fdb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 11 Oct 2016 17:46:01 +0200 Subject: pinctrl: sunxi: Handle bias disable So far, putting NO_PULL in allwinner,pull was ignored, behaving like if that property was not there at all. Obviously, this is not the right thing to do, and in that case, we really need to just disable the bias. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 62a9d012b35f..c44bf1320e08 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -165,6 +165,8 @@ static int sunxi_pctrl_parse_bias_prop(struct device_node *node) 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: @@ -401,6 +403,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); -- cgit 1.4.1 From 93f889b9657ff541417f498c2ee0f69775fe3cef Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 4 Oct 2016 15:41:46 +0200 Subject: pinctrl: oxnas: Move OX810SE specific function and structure as separate Add refactoring to move ox810se specific functions into specific ops structures an add support for the dt match data to get soc specific structures. Signed-off-by: Neil Armstrong Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-oxnas.c | 176 +++++++++++++++++++++++----------------- 1 file changed, 101 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 917a7d2535d7..218ad48f455a 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -37,15 +37,15 @@ #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 /* GPIO Registers */ #define INPUT_VALUE 0x00 @@ -87,8 +87,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 +95,12 @@ 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"), @@ -135,7 +138,7 @@ static const struct pinctrl_pin_desc oxnas_pins[] = { PINCTRL_PIN(34, "gpio34"), }; -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 +150,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", @@ -165,9 +168,9 @@ 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), }; #define OXNAS_PINCTRL_GROUP(_pin, _name, ...) \ @@ -185,7 +188,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)), @@ -352,8 +355,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 +374,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 +405,9 @@ 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_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 +418,18 @@ 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; @@ -498,17 +501,17 @@ 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 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 +524,8 @@ 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; @@ -538,8 +541,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 +565,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,20 +579,12 @@ 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 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 void oxnas_gpio_irq_ack(struct irq_data *data) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); @@ -699,10 +695,51 @@ 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_data oxnas_ox810se_pinctrl_data = { + .desc = &oxnas_ox810se_pinctrl_desc, + .pctl = &ox810se_pinctrl, +}; + +static const struct of_device_id oxnas_pinctrl_of_match[] = { + { .compatible = "oxsemi,ox810se-pinctrl", + .data = &oxnas_ox810se_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 +753,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); + 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; - oxnas_pinctrl_desc.pins = pctl->pins; - oxnas_pinctrl_desc.npins = pctl->npins; - - 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 +836,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", -- cgit 1.4.1 From 4b0c0c25fa7965f859b4489b3670e5a1e36ffab8 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 4 Oct 2016 15:41:47 +0200 Subject: pinctrl: oxnas: Add support for OX820 Add support for the Oxford Semiconductor OX820 which is similar as OX810 but has 50 pins and two registers banks to setup alternate functions. Add specific pins, groups and functions structures. Add DT match data to select corresponding support. Signed-off-by: Neil Armstrong Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-oxnas.c | 433 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 433 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-oxnas.c b/drivers/pinctrl/pinctrl-oxnas.c index 218ad48f455a..494ec9a7573a 100644 --- a/drivers/pinctrl/pinctrl-oxnas.c +++ b/drivers/pinctrl/pinctrl-oxnas.c @@ -47,6 +47,15 @@ #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 #define OUTPUT_EN 0x04 @@ -138,6 +147,59 @@ static const struct pinctrl_pin_desc oxnas_ox810se_pins[] = { 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"), + 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"), + 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_ox810se_fct0_group[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", @@ -161,6 +223,40 @@ static const char * const oxnas_ox810se_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, \ @@ -173,6 +269,13 @@ static const struct oxnas_function oxnas_ox810se_functions[] = { 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, ...) \ { \ .name = #_name, \ @@ -285,6 +388,140 @@ static const struct oxnas_pin_group oxnas_ox810se_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) { @@ -405,6 +642,61 @@ static int oxnas_ox810se_pinmux_enable(struct pinctrl_dev *pctldev, return -EINVAL; } +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) @@ -435,6 +727,37 @@ static int oxnas_ox810se_gpio_request_enable(struct pinctrl_dev *pctldev, 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; +} + static int oxnas_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { @@ -510,6 +833,15 @@ static const struct pinmux_ops oxnas_ox810se_pinmux_ops = { .gpio_set_direction = oxnas_gpio_set_direction, }; +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) { @@ -541,6 +873,36 @@ static int oxnas_ox810se_pinconf_get(struct pinctrl_dev *pctldev, 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; + + arg = !!(arg & mask); + break; + default: + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *configs, unsigned int num_configs) @@ -579,12 +941,55 @@ static int oxnas_ox810se_pinconf_set(struct pinctrl_dev *pctldev, return 0; } +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 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) { struct gpio_chip *chip = irq_data_get_irq_chip_data(data); @@ -714,15 +1119,42 @@ static struct pinctrl_desc oxnas_ox810se_pinctrl_desc = { .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, + }, { }, }; @@ -847,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", }, { }, }; -- cgit 1.4.1 From cefbf1a1b29531a970bc2908a50a75d6474fcc38 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 20 Oct 2016 15:49:03 +0200 Subject: pinctrl: sunxi: Support generic binding Our bindings are mostly irrelevant now that we have generic pinctrl bindings that cover exactly the same uses cases. Add support for the new ones, and obviously keep our old binding support in order to keep the ABI stable. Acked-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 48 +++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index c44bf1320e08..7e27204d3eea 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -149,18 +149,33 @@ static int sunxi_pctrl_get_group_pins(struct pinctrl_dev *pctldev, static bool sunxi_pctrl_has_bias_prop(struct device_node *node) { - return of_find_property(node, "allwinner,pull", NULL); + 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, "allwinner,drive", NULL); + 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; @@ -180,6 +195,21 @@ 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; @@ -191,6 +221,12 @@ 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; @@ -203,6 +239,14 @@ static const char *sunxi_pctrl_find_pins_prop(struct device_node *node, { 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; -- cgit 1.4.1 From 223decc457c992976e4d4e6936f6225d4b6dd99e Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 27 Oct 2016 07:59:52 -0700 Subject: pinctrl: single: Drop custom names >From tony Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 25 Oct 2016 08:33:34 -0700 Subject: [PATCHv2] pinctrl: single: Drop custom names We no longer need to allocate custom names as those are dynamically generated in pinctrl_register_one_pin() if no name is passed to pinctrl_register_pins(). Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 36 ++++++------------------------------ 1 file changed, 6 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index bfdf720db270..d125f3f502be 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -36,7 +36,6 @@ #define DRIVER_NAME "pinctrl-single" #define PCS_MUX_PINS_NAME "pinctrl-single,pins" #define PCS_MUX_BITS_NAME "pinctrl-single,bits" -#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 3) #define PCS_OFF_DISABLED ~0U /** @@ -141,20 +140,6 @@ struct pcs_data { int cur; }; -/** - * struct pcs_name - register name for a pin - * @name: name of the pinctrl register - * - * REVISIT: We may want to make names optional in the pinctrl - * framework as some drivers may not care about pin names to - * avoid kernel bloat. The pin names can be deciphered by user - * space tools using debugfs based on the register address and - * SoC packaging information. - */ -struct pcs_name { - char name[PCS_REG_NAME_LEN]; -}; - /** * struct pcs_soc_data - SoC specific settings * @flags: initial SoC specific PCS_FEAT_xxx values @@ -187,7 +172,6 @@ struct pcs_soc_data { * @foff: value to turn mux off * @fmax: max number of functions in fmask * @bits_per_pin:number of bits per pin - * @names: array of register names for pins * @pins: physical pins on the SoC * @pgtree: pingroup index radix tree * @ftree: function index radix tree @@ -223,7 +207,6 @@ struct pcs_device { unsigned fmax; bool bits_per_mux; unsigned bits_per_pin; - struct pcs_name *names; struct pcs_data pins; struct radix_tree_root pgtree; struct radix_tree_root ftree; @@ -354,13 +337,17 @@ static void pcs_pin_dbg_show(struct pinctrl_dev *pctldev, { struct pcs_device *pcs; unsigned val, mux_bytes; + unsigned long offset; + size_t pa; pcs = pinctrl_dev_get_drvdata(pctldev); mux_bytes = pcs->width / BITS_PER_BYTE; - val = pcs->read(pcs->base + pin * mux_bytes); + offset = pin * mux_bytes; + val = pcs->read(pcs->base + offset); + pa = pcs->res->start + offset; - seq_printf(s, "%08x %s " , val, DRIVER_NAME); + seq_printf(s, "%zx %08x %s ", pa, val, DRIVER_NAME); } static void pcs_dt_free_map(struct pinctrl_dev *pctldev, @@ -763,7 +750,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, { struct pcs_soc_data *pcs_soc = &pcs->socdata; struct pinctrl_pin_desc *pin; - struct pcs_name *pn; int i; i = pcs->pins.cur; @@ -786,10 +772,6 @@ static int pcs_add_pin(struct pcs_device *pcs, unsigned offset, } pin = &pcs->pins.pa[i]; - pn = &pcs->names[i]; - sprintf(pn->name, "%lx.%u", - (unsigned long)pcs->res->start + offset, pin_pos); - pin->name = pn->name; pin->number = i; pcs->pins.cur++; @@ -827,12 +809,6 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs) if (!pcs->pins.pa) return -ENOMEM; - pcs->names = devm_kzalloc(pcs->dev, - sizeof(struct pcs_name) * nr_pins, - GFP_KERNEL); - if (!pcs->names) - return -ENOMEM; - pcs->desc.pins = pcs->pins.pa; pcs->desc.npins = nr_pins; -- cgit 1.4.1 From cd23604a4b2575c7d6786a3d6cd29d79941a5542 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 25 Oct 2016 09:09:00 -0700 Subject: pinctrl: single: Drop pointless macro This is left over from initial experiments with more properties. It's only used in one place, so let's just get rid of it to make the code more readable. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index d125f3f502be..7cc9b7dc8656 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1472,15 +1472,6 @@ static void pcs_free_resources(struct pcs_device *pcs) pcs_free_pingroups(pcs); } -#define PCS_GET_PROP_U32(name, reg, err) \ - do { \ - ret = of_property_read_u32(np, name, reg); \ - if (ret) { \ - dev_err(pcs->dev, err); \ - return ret; \ - } \ - } while (0); - static const struct of_device_id pcs_of_match[]; static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs) @@ -1825,8 +1816,13 @@ static int pcs_probe(struct platform_device *pdev) pcs->flags = soc->flags; memcpy(&pcs->socdata, soc, sizeof(*soc)); - PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width, - "register width not specified\n"); + ret = of_property_read_u32(np, "pinctrl-single,register-width", + &pcs->width); + if (ret) { + dev_err(pcs->dev, "register width not specified\n"); + + return ret; + } ret = of_property_read_u32(np, "pinctrl-single,function-mask", &pcs->fmask); -- cgit 1.4.1 From 24d6a91c9df3f6b8096d2e59da31341fc35c9549 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 28 Oct 2016 10:19:05 +0200 Subject: pinctrl: max77620: add OF dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers using pinconf_generic_params tables cannot be built with CONFIG_OF disabled: drivers/pinctrl/pinctrl-max77620.c:53:44: error: array type has incomplete element type ‘struct pinconf_generic_params’ drivers/pinctrl/pinctrl-max77620.c:55:3: error: field name not in record or union initializer drivers/pinctrl/pinctrl-max77620.c:55:3: note: (near initialization for ‘max77620_cfg_params’) drivers/pinctrl/pinctrl-max77620.c:56:3: error: field name not in record or union initializer This adds a dependency for max77620 to disallow that configuration. Alternatively, we could rework the pinctrl infrastructure to make the configuration valid for compile-testing. Cc: Krzysztof Kozlowski Cc: Lee Jones Fixes: 453943dc8f45 ("mfd: Enable compile testing for max77620 and max77686") Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 801fa8bb05e1..3eea73937ce8 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -223,7 +223,7 @@ config PINCTRL_COH901 config PINCTRL_MAX77620 tristate "MAX77620/MAX20024 Pincontrol support" - depends on MFD_MAX77620 + depends on MFD_MAX77620 && OF select PINMUX select GENERIC_PINCONF help -- cgit 1.4.1 From e06c2ee5f13c55a982804d76ea526c630b21b383 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Fri, 28 Oct 2016 16:54:21 +0530 Subject: pinctrl: generic: Parse pinmux init nodes if node status is okay During pinmux registration, pinmux table is parsed from DT for making the pinmux table configuration of pins. Parse the only those node whose status is not disabled. This will help on reusing the pin configuration table across platform and disabling the node by status property if that node is not needed on given platform. Signed-off-by: Laxman Dewangan Signed-off-by: Linus Walleij --- drivers/pinctrl/pinconf-generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c index 5020ae534479..ce3335accb5b 100644 --- a/drivers/pinctrl/pinconf-generic.c +++ b/drivers/pinctrl/pinconf-generic.c @@ -381,7 +381,7 @@ int pinconf_generic_dt_node_to_map(struct pinctrl_dev *pctldev, if (ret < 0) goto exit; - for_each_child_of_node(np_config, np) { + for_each_available_child_of_node(np_config, np) { ret = pinconf_generic_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps, type); if (ret < 0) -- cgit 1.4.1 From b9aa65ba8efa810076a081fabd3f3477f751c4ac Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 27 Oct 2016 19:10:15 +0300 Subject: pinctrl: intel: merrifield: Add pin config group handlers Pin config get() and set() handlers for pin groups were previously not implemented by this driver. The pin_config_group_set() is particularly useful for applying a common config setting to all pins in a specified group with a single call, without the caller needing to reference each individual pin by name. Signed-off-by: Andy Shevchenko Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-merrifield.c | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c index 7826c7f0cb7c..b21896126f76 100644 --- a/drivers/pinctrl/intel/pinctrl-merrifield.c +++ b/drivers/pinctrl/intel/pinctrl-merrifield.c @@ -814,10 +814,51 @@ static int mrfld_config_set(struct pinctrl_dev *pctldev, unsigned int pin, return 0; } +static int mrfld_config_group_get(struct pinctrl_dev *pctldev, + unsigned int group, unsigned long *config) +{ + const unsigned int *pins; + unsigned int npins; + int ret; + + ret = mrfld_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + ret = mrfld_config_get(pctldev, pins[0], config); + if (ret) + return ret; + + return 0; +} + +static int mrfld_config_group_set(struct pinctrl_dev *pctldev, + unsigned int group, unsigned long *configs, + unsigned int num_configs) +{ + const unsigned int *pins; + unsigned int npins; + int i, ret; + + ret = mrfld_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; i++) { + ret = mrfld_config_set(pctldev, pins[i], configs, num_configs); + if (ret) + return ret; + } + + return 0; +} + static const struct pinconf_ops mrfld_pinconf_ops = { .is_generic = true, .pin_config_get = mrfld_config_get, .pin_config_set = mrfld_config_set, + .pin_config_group_get = mrfld_config_group_get, + .pin_config_group_set = mrfld_config_group_set, }; static const struct pinctrl_desc mrfld_pinctrl_desc = { -- cgit 1.4.1 From e11dee2e98f8abc99ad5336796576a827853ccfa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 20 Oct 2016 15:49:02 +0200 Subject: pinctrl: sunxi: Deal with configless pins Even though the our binding had the assumption that the allwinner,pull and allwinner,drive properties were optional, the code never took that into account. Fix that. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 51 +++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 7e27204d3eea..ebe2c73d211e 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -261,20 +261,29 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, { unsigned long *pinconfig; unsigned int configlen = 0, idx = 0; + int ret; if (sunxi_pctrl_has_drive_prop(node)) configlen++; if (sunxi_pctrl_has_bias_prop(node)) configlen++; + /* + * If we don't have any configuration, bail out + */ + if (!configlen) + return NULL; + pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL); if (!pinconfig) - return NULL; + return ERR_PTR(-ENOMEM); if (sunxi_pctrl_has_drive_prop(node)) { int drive = sunxi_pctrl_parse_drive_prop(node); - if (drive < 0) + if (drive < 0) { + ret = drive; goto err_free; + } pinconfig[idx++] = pinconf_to_config_packed(PIN_CONFIG_DRIVE_STRENGTH, drive); @@ -282,8 +291,10 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, if (sunxi_pctrl_has_bias_prop(node)) { int pull = sunxi_pctrl_parse_bias_prop(node); - if (pull < 0) + if (pull < 0) { + ret = pull; goto err_free; + } pinconfig[idx++] = pinconf_to_config_packed(pull, 0); } @@ -294,7 +305,7 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, err_free: kfree(pinconfig); - return NULL; + return ERR_PTR(ret); } static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, @@ -328,7 +339,10 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, /* * We have two maps for each pin: one for the function, one - * for the configuration (bias, strength, etc) + * for the configuration (bias, strength, etc). + * + * We might be slightly overshooting, since we might not have + * any configuration. */ nmaps = npins * 2; *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); @@ -336,8 +350,8 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, return -ENOMEM; pinconfig = sunxi_pctrl_build_pin_config(node, &configlen); - if (!pinconfig) { - ret = -EINVAL; + if (IS_ERR(pinconfig)) { + ret = PTR_ERR(pinconfig); goto err_free_map; } @@ -364,15 +378,24 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, i++; - (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; - (*map)[i].data.configs.group_or_pin = group; - (*map)[i].data.configs.configs = pinconfig; - (*map)[i].data.configs.num_configs = configlen; - - i++; + if (pinconfig) { + (*map)[i].type = PIN_MAP_TYPE_CONFIGS_GROUP; + (*map)[i].data.configs.group_or_pin = group; + (*map)[i].data.configs.configs = pinconfig; + (*map)[i].data.configs.num_configs = configlen; + i++; + } } - *num_maps = nmaps; + *num_maps = i; + + /* + * We know have the number of maps we need, we can resize our + * map array + */ + *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); + if (!map) + return -ENOMEM; return 0; -- cgit 1.4.1 From 96bb12deadac74ad1053d6bb704aaa33417b85a6 Mon Sep 17 00:00:00 2001 From: Boris BREZILLON Date: Fri, 28 Oct 2016 15:54:10 +0800 Subject: pinctrl: at91: add support for OUTPUT config Add support for pin output control through the pinctrl config: - support enabling/disabling output on a given pin - support output level setting (high or low) Signed-off-by: Boris BREZILLON Acked-by: Nicolas Ferre Signed-off-by: Wenyou Yang Signed-off-by: Linus Walleij --- .../bindings/pinctrl/atmel,at91-pinctrl.txt | 2 ++ drivers/pinctrl/pinctrl-at91.c | 21 +++++++++++++++++++++ include/dt-bindings/pinctrl/at91.h | 2 ++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt index b7a93e80a302..9a8a45d9d8ab 100644 --- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt @@ -98,6 +98,8 @@ DRIVE_STRENGTH (3 << 5): indicate the drive strength of the pin using the 01 - Low 10 - Medium 11 - High +OUTPUT (1 << 7): indicate this pin need to be configured as an output. +OUTPUT_VAL (1 << 8): output val (1 = high, 0 = low) DEBOUNCE (1 << 16): indicate this pin needs debounce. DEBOUNCE_VAL (0x3fff << 17): debounce value. diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 9f0904185909..569bc28cb909 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c @@ -56,6 +56,9 @@ static int gpio_banks; #define DRIVE_STRENGTH_SHIFT 5 #define DRIVE_STRENGTH_MASK 0x3 #define DRIVE_STRENGTH (DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT) +#define OUTPUT (1 << 7) +#define OUTPUT_VAL_SHIFT 8 +#define OUTPUT_VAL (0x1 << OUTPUT_VAL_SHIFT) #define DEBOUNCE (1 << 16) #define DEBOUNCE_VAL_SHIFT 17 #define DEBOUNCE_VAL (0x3fff << DEBOUNCE_VAL_SHIFT) @@ -375,6 +378,19 @@ static void at91_mux_set_pullup(void __iomem *pio, unsigned mask, bool on) writel_relaxed(mask, pio + (on ? PIO_PUER : PIO_PUDR)); } +static bool at91_mux_get_output(void __iomem *pio, unsigned int pin, bool *val) +{ + *val = (readl_relaxed(pio + PIO_ODSR) >> pin) & 0x1; + return (readl_relaxed(pio + PIO_OSR) >> pin) & 0x1; +} + +static void at91_mux_set_output(void __iomem *pio, unsigned int mask, + bool is_on, bool val) +{ + writel_relaxed(mask, pio + (val ? PIO_SODR : PIO_CODR)); + writel_relaxed(mask, pio + (is_on ? PIO_OER : PIO_ODR)); +} + static unsigned at91_mux_get_multidrive(void __iomem *pio, unsigned pin) { return (readl_relaxed(pio + PIO_MDSR) >> pin) & 0x1; @@ -848,6 +864,7 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, void __iomem *pio; unsigned pin; int div; + bool out; *config = 0; dev_dbg(info->dev, "%s:%d, pin_id=%d", __func__, __LINE__, pin_id); @@ -875,6 +892,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev, if (info->ops->get_drivestrength) *config |= (info->ops->get_drivestrength(pio, pin) << DRIVE_STRENGTH_SHIFT); + if (at91_mux_get_output(pio, pin, &out)) + *config |= OUTPUT | (out << OUTPUT_VAL_SHIFT); return 0; } @@ -907,6 +926,8 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev, if (config & PULL_UP && config & PULL_DOWN) return -EINVAL; + at91_mux_set_output(pio, mask, config & OUTPUT, + (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT); at91_mux_set_pullup(pio, mask, config & PULL_UP); at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE); if (info->ops->set_deglitch) diff --git a/include/dt-bindings/pinctrl/at91.h b/include/dt-bindings/pinctrl/at91.h index bbca3d038900..2732d6c0fb39 100644 --- a/include/dt-bindings/pinctrl/at91.h +++ b/include/dt-bindings/pinctrl/at91.h @@ -15,6 +15,8 @@ #define AT91_PINCTRL_DEGLITCH (1 << 2) #define AT91_PINCTRL_PULL_DOWN (1 << 3) #define AT91_PINCTRL_DIS_SCHMIT (1 << 4) +#define AT91_PINCTRL_OUTPUT (1 << 7) +#define AT91_PINCTRL_OUTPUT_VAL(x) ((x & 0x1) << 8) #define AT91_PINCTRL_DEBOUNCE (1 << 16) #define AT91_PINCTRL_DEBOUNCE_VAL(x) (x << 17) -- cgit 1.4.1 From 951f033d969a6deff668286ed4bf0783f905a413 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Wed, 26 Oct 2016 12:04:54 -0600 Subject: pinctrl: zynq: Add a 8 bit wide nand option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware supports a 16 and 8 bit wide NAND bus, let users pick either. Signed-off-by: Jason Gunthorpe Acked-by: Sören Brinkmann Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-zynq.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-zynq.c b/drivers/pinctrl/pinctrl-zynq.c index e0ecffcbe11f..b51a46dfdcc3 100644 --- a/drivers/pinctrl/pinctrl-zynq.c +++ b/drivers/pinctrl/pinctrl-zynq.c @@ -247,6 +247,8 @@ static const unsigned int smc0_nor_addr25_pins[] = {1}; static const unsigned int smc0_nand_pins[] = {0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 22, 23}; +static const unsigned int smc0_nand8_pins[] = {0, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14}; /* Note: CAN MIO clock inputs are modeled in the clock framework */ static const unsigned int can0_0_pins[] = {10, 11}; static const unsigned int can0_1_pins[] = {14, 15}; @@ -445,6 +447,7 @@ static const struct zynq_pctrl_group zynq_pctrl_groups[] = { DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_cs1), DEFINE_ZYNQ_PINCTRL_GRP(smc0_nor_addr25), DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand), + DEFINE_ZYNQ_PINCTRL_GRP(smc0_nand8), DEFINE_ZYNQ_PINCTRL_GRP(can0_0), DEFINE_ZYNQ_PINCTRL_GRP(can0_1), DEFINE_ZYNQ_PINCTRL_GRP(can0_2), @@ -709,7 +712,8 @@ static const char * const sdio1_wp_groups[] = {"gpio0_0_grp", static const char * const smc0_nor_groups[] = {"smc0_nor_grp"}; static const char * const smc0_nor_cs1_groups[] = {"smc0_nor_cs1_grp"}; static const char * const smc0_nor_addr25_groups[] = {"smc0_nor_addr25_grp"}; -static const char * const smc0_nand_groups[] = {"smc0_nand_grp"}; +static const char * const smc0_nand_groups[] = {"smc0_nand_grp", + "smc0_nand8_grp"}; static const char * const can0_groups[] = {"can0_0_grp", "can0_1_grp", "can0_2_grp", "can0_3_grp", "can0_4_grp", "can0_5_grp", "can0_6_grp", "can0_7_grp", "can0_8_grp", "can0_9_grp", -- cgit 1.4.1 From 684373eaa95fe6f85ef527281d87ff9ef07b084e Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Mon, 31 Oct 2016 16:57:34 +0200 Subject: pinctrl: cherryview: Drop ctrlX prefix from the pin debugfs output Printing the prefix does not provide any additional information. In addition this makes the output look more consistent with pinctrl-intel.c. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-cherryview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 30389f4ccab4..13644768ae1c 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -762,7 +762,7 @@ static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, seq_printf(s, "mode %d ", mode); } - seq_printf(s, "ctrl0 0x%08x ctrl1 0x%08x", ctrl0, ctrl1); + seq_printf(s, "0x%08x 0x%08x", ctrl0, ctrl1); if (locked) seq_puts(s, " [LOCKED]"); -- cgit 1.4.1 From b83bd893f3a04d35f5bfcf399c1034660e5b2403 Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Mon, 31 Oct 2016 13:21:33 +0000 Subject: pinctrl: bcm2835: reduce GPPUD set-up time Since the BCM2835 datasheet doesn't exactly specify the set-up time for the GPIO Pull-up/down Clock Registers there was an assumption of 150 cycles at a clock rate of 1 MHz. During a discussion [1] in the Raspberry Pi forum it turns out that clock rate refers to the VPU which has a rate of 250 MHz. So we can reduce the delay to a sensible value and update the comment above. I tested this optimization with a Raspberry Pi B and a multimeter. [1] - https://www.raspberrypi.org/forums/viewtopic.php?f=72&t=163352 Signed-off-by: Stefan Wahren Reviewed-by: Eric Anholt Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index fa77165fab2c..b2dd278f18b1 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -917,12 +917,14 @@ static int bcm2835_pinconf_set(struct pinctrl_dev *pctldev, bcm2835_gpio_wr(pc, GPPUD, arg & 3); /* - * Docs say to wait 150 cycles, but not of what. We assume a - * 1 MHz clock here, which is pretty slow... + * BCM2835 datasheet say to wait 150 cycles, but not of what. + * But the VideoCore firmware delay for this operation + * based nearly on the same amount of VPU cycles and this clock + * runs at 250 MHz. */ - udelay(150); + udelay(1); bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), BIT(bit)); - udelay(150); + udelay(1); bcm2835_gpio_wr(pc, GPPUDCLK0 + (off * 4), 0); } /* for each config */ -- cgit 1.4.1 From 42124bc598f64f84b3335d5a058304207695b84f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:47 -0700 Subject: pinctrl: Introduce generic #pinctrl-cells and pinctrl_parse_index_with_args Introduce #pinctrl-cells helper binding and generic helper functions pinctrl_count_index_with_args() and pinctrl_parse_index_with_args(). Acked-by: Rob Herring Signed-off-by: Tony Lindgren [Forward-declare of_phandle_args] Signed-off-by: Linus Walleij --- .../bindings/pinctrl/pinctrl-bindings.txt | 44 ++++++- drivers/pinctrl/devicetree.c | 144 +++++++++++++++++++++ drivers/pinctrl/devicetree.h | 23 ++++ 3 files changed, 210 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt index b73c96d24f59..bf3f7b014724 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt @@ -97,6 +97,11 @@ For example: }; == Pin controller devices == +Required properties: See the pin controller driver specific documentation + +Optional properties: +#pinctrl-cells: Number of pin control cells in addition to the index within the + pin controller device instance Pin controller devices should contain the pin configuration nodes that client devices reference. @@ -119,7 +124,8 @@ For example: The contents of each of those pin configuration child nodes is defined entirely by the binding for the individual pin controller device. There -exists no common standard for this content. +exists no common standard for this content. The pinctrl framework only +provides generic helper bindings that the pin controller driver can use. The pin configuration nodes need not be direct children of the pin controller device; they may be grandchildren, for example. Whether this is legal, and @@ -156,6 +162,42 @@ state_2_node_a { pins = "mfio29", "mfio30"; }; +Optionally an altenative binding can be used if more suitable depending on the +pin controller hardware. For hardaware where there is a large number of identical +pin controller instances, naming each pin and function can easily become +unmaintainable. This is especially the case if the same controller is used for +different pins and functions depending on the SoC revision and packaging. + +For cases like this, the pin controller driver may use pinctrl-pin-array helper +binding with a hardware based index and a number of pin configuration values: + +pincontroller { + ... /* Standard DT properties for the device itself elided */ + #pinctrl-cells = <2>; + + state_0_node_a { + pinctrl-pin-array = < + 0 A_DELAY_PS(0) G_DELAY_PS(120) + 4 A_DELAY_PS(0) G_DELAY_PS(360) + ... + >; + }; + ... +}; + +Above #pinctrl-cells specifies the number of value cells in addition to the +index of the registers. This is similar to the interrupts-extended binding with +one exception. There is no need to specify the phandle for each entry as that +is already known as the defined pins are always children of the pin controller +node. Further having the phandle pointing to another pin controller would not +currently work as the pinctrl framework uses named modes to group pins for each +pin control device. + +The index for pinctrl-pin-array must relate to the hardware for the pinctrl +registers, and must not be a virtual index of pin instances. The reason for +this is to avoid mapping of the index in the dts files and the pin controller +driver as it can change. + == Generic pin configuration node content == Many data items that are represented in a pin configuration node are common diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c index 54dad89fc9bf..260908480075 100644 --- a/drivers/pinctrl/devicetree.c +++ b/drivers/pinctrl/devicetree.c @@ -253,3 +253,147 @@ err: pinctrl_dt_free_maps(p); return ret; } + +/* + * For pinctrl binding, typically #pinctrl-cells is for the pin controller + * device, so either parent or grandparent. See pinctrl-bindings.txt. + */ +static int pinctrl_find_cells_size(const struct device_node *np) +{ + const char *cells_name = "#pinctrl-cells"; + int cells_size, error; + + error = of_property_read_u32(np->parent, cells_name, &cells_size); + if (error) { + error = of_property_read_u32(np->parent->parent, + cells_name, &cells_size); + if (error) + return -ENOENT; + } + + return cells_size; +} + +/** + * pinctrl_get_list_and_count - Gets the list and it's cell size and number + * @np: pointer to device node with the property + * @list_name: property that contains the list + * @list: pointer for the list found + * @cells_size: pointer for the cell size found + * @nr_elements: pointer for the number of elements found + * + * Typically np is a single pinctrl entry containing the list. + */ +static int pinctrl_get_list_and_count(const struct device_node *np, + const char *list_name, + const __be32 **list, + int *cells_size, + int *nr_elements) +{ + int size; + + *cells_size = 0; + *nr_elements = 0; + + *list = of_get_property(np, list_name, &size); + if (!*list) + return -ENOENT; + + *cells_size = pinctrl_find_cells_size(np); + if (*cells_size < 0) + return -ENOENT; + + /* First element is always the index within the pinctrl device */ + *nr_elements = (size / sizeof(**list)) / (*cells_size + 1); + + return 0; +} + +/** + * pinctrl_count_index_with_args - Count number of elements in a pinctrl entry + * @np: pointer to device node with the property + * @list_name: property that contains the list + * + * Counts the number of elements in a pinctrl array consisting of an index + * within the controller and a number of u32 entries specified for each + * entry. Note that device_node is always for the parent pin controller device. + */ +int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name) +{ + const __be32 *list; + int size, nr_cells, error; + + error = pinctrl_get_list_and_count(np, list_name, &list, + &nr_cells, &size); + if (error) + return error; + + return size; +} +EXPORT_SYMBOL_GPL(pinctrl_count_index_with_args); + +/** + * pinctrl_copy_args - Populates of_phandle_args based on index + * @np: pointer to device node with the property + * @list: pointer to a list with the elements + * @index: entry within the list of elements + * @nr_cells: number of cells in the list + * @nr_elem: number of elements for each entry in the list + * @out_args: returned values + * + * Populates the of_phandle_args based on the index in the list. + */ +static int pinctrl_copy_args(const struct device_node *np, + const __be32 *list, + int index, int nr_cells, int nr_elem, + struct of_phandle_args *out_args) +{ + int i; + + memset(out_args, 0, sizeof(*out_args)); + out_args->np = (struct device_node *)np; + out_args->args_count = nr_cells + 1; + + if (index >= nr_elem) + return -EINVAL; + + list += index * (nr_cells + 1); + + for (i = 0; i < nr_cells + 1; i++) + out_args->args[i] = be32_to_cpup(list++); + + return 0; +} + +/** + * pinctrl_parse_index_with_args - Find a node pointed by index in a list + * @np: pointer to device node with the property + * @list_name: property that contains the list + * @index: index within the list + * @out_arts: entries in the list pointed by index + * + * Finds the selected element in a pinctrl array consisting of an index + * within the controller and a number of u32 entries specified for each + * entry. Note that device_node is always for the parent pin controller device. + */ +int pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args) +{ + const __be32 *list; + int nr_elem, nr_cells, error; + + error = pinctrl_get_list_and_count(np, list_name, &list, + &nr_cells, &nr_elem); + if (error || !nr_cells) + return error; + + error = pinctrl_copy_args(np, list, index, nr_cells, nr_elem, + out_args); + if (error) + return error; + + return 0; +} +EXPORT_SYMBOL_GPL(pinctrl_parse_index_with_args); diff --git a/drivers/pinctrl/devicetree.h b/drivers/pinctrl/devicetree.h index 760bc4960f58..c2d1a5505850 100644 --- a/drivers/pinctrl/devicetree.h +++ b/drivers/pinctrl/devicetree.h @@ -16,11 +16,20 @@ * along with this program. If not, see . */ +struct of_phandle_args; + #ifdef CONFIG_OF void pinctrl_dt_free_maps(struct pinctrl *p); int pinctrl_dt_to_map(struct pinctrl *p); +int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name); + +int pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args); + #else static inline int pinctrl_dt_to_map(struct pinctrl *p) @@ -32,4 +41,18 @@ static inline void pinctrl_dt_free_maps(struct pinctrl *p) { } +static inline int pinctrl_count_index_with_args(const struct device_node *np, + const char *list_name) +{ + return -ENODEV; +} + +static inline int +pinctrl_parse_index_with_args(const struct device_node *np, + const char *list_name, int index, + struct of_phandle_args *out_args) +{ + return -ENODEV; +} + #endif -- cgit 1.4.1 From 4622215fb1dda40bcebab31553765ee9cacb476d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:48 -0700 Subject: pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,pins We can now use generic parser. To support the legacy binding without #pinctrl-cells, add pcs_quirk_missing_pinctrl_cells() and warn about missing #pinctrl-cells. Let's also update the documentation for struct pcs_soc_data while at it as that seems to be out of date. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 111 ++++++++++++++++++++++++++++++++------- 1 file changed, 93 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 7cc9b7dc8656..07c427367237 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -31,10 +31,10 @@ #include #include "core.h" +#include "devicetree.h" #include "pinconf.h" #define DRIVER_NAME "pinctrl-single" -#define PCS_MUX_PINS_NAME "pinctrl-single,pins" #define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_OFF_DISABLED ~0U @@ -162,8 +162,11 @@ struct pcs_soc_data { * @base: virtual address of the controller * @size: size of the ioremapped area * @dev: device entry + * @np: device tree node * @pctl: pin controller device * @flags: mask of PCS_FEAT_xxx values + * @missing_nr_pinctrl_cells: for legacy binding, may go away + * @socdata: soc specific data * @lock: spinlock for register access * @mutex: mutex protecting the lists * @width: bits per mux register @@ -171,7 +174,8 @@ struct pcs_soc_data { * @fshift: function register shift * @foff: value to turn mux off * @fmax: max number of functions in fmask - * @bits_per_pin:number of bits per pin + * @bits_per_mux: number of bits per mux + * @bits_per_pin: number of bits per pin * @pins: physical pins on the SoC * @pgtree: pingroup index radix tree * @ftree: function index radix tree @@ -192,11 +196,13 @@ struct pcs_device { void __iomem *base; unsigned size; struct device *dev; + struct device_node *np; struct pinctrl_dev *pctl; unsigned flags; #define PCS_QUIRK_SHARED_IRQ (1 << 2) #define PCS_FEAT_IRQ (1 << 1) #define PCS_FEAT_PINCONF (1 << 0) + struct property *missing_nr_pinctrl_cells; struct pcs_soc_data socdata; raw_spinlock_t lock; struct mutex mutex; @@ -1122,20 +1128,14 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, unsigned *num_maps, const char **pgnames) { + const char *name = "pinctrl-single,pins"; struct pcs_func_vals *vals; - const __be32 *mux; - int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; + int rows, *pins, found = 0, res = -ENOMEM, i; struct pcs_function *function; - mux = of_get_property(np, PCS_MUX_PINS_NAME, &size); - if ((!mux) || (size < sizeof(*mux) * 2)) { - dev_err(pcs->dev, "bad data for mux %s\n", - np->name); - return -EINVAL; - } - - size /= sizeof(*mux); /* Number of elements in array */ - rows = size / 2; + rows = pinctrl_count_index_with_args(np, name); + if (rows == -EINVAL) + return rows; vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); if (!vals) @@ -1145,14 +1145,28 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, if (!pins) goto free_vals; - while (index < size) { - unsigned offset, val; + for (i = 0; i < rows; i++) { + struct of_phandle_args pinctrl_spec; + unsigned int offset; int pin; - offset = be32_to_cpup(mux + index++); - val = be32_to_cpup(mux + index++); + res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec); + if (res) + return res; + + if (pinctrl_spec.args_count < 2) { + dev_err(pcs->dev, "invalid args_count for spec: %i\n", + pinctrl_spec.args_count); + break; + } + + /* Index plus one value cell */ + offset = pinctrl_spec.args[0]; vals[found].reg = pcs->base + offset; - vals[found].val = val; + vals[found].val = pinctrl_spec.args[1]; + + dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x\n", + pinctrl_spec.np->name, offset, pinctrl_spec.args[1]); pin = pcs_get_pin_by_offset(pcs, offset); if (pin < 0) { @@ -1470,6 +1484,10 @@ static void pcs_free_resources(struct pcs_device *pcs) pinctrl_unregister(pcs->pctl); pcs_free_funcs(pcs); pcs_free_pingroups(pcs); +#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE) + if (pcs->missing_nr_pinctrl_cells) + of_remove_property(pcs->np, pcs->missing_nr_pinctrl_cells); +#endif } static const struct of_device_id pcs_of_match[]; @@ -1787,6 +1805,55 @@ static int pinctrl_single_resume(struct platform_device *pdev) } #endif +/** + * pcs_quirk_missing_pinctrl_cells - handle legacy binding + * @pcs: pinctrl driver instance + * @np: device tree node + * @cells: number of cells + * + * Handle legacy binding with no #pinctrl-cells. This should be + * always two pinctrl-single,bit-per-mux and one for others. + * At some point we may want to consider removing this. + */ +static int pcs_quirk_missing_pinctrl_cells(struct pcs_device *pcs, + struct device_node *np, + int cells) +{ + struct property *p; + const char *name = "#pinctrl-cells"; + int error; + u32 val; + + error = of_property_read_u32(np, name, &val); + if (!error) + return 0; + + dev_warn(pcs->dev, "please update dts to use %s = <%i>\n", + name, cells); + + p = devm_kzalloc(pcs->dev, sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + p->length = sizeof(__be32); + p->value = devm_kzalloc(pcs->dev, sizeof(__be32), GFP_KERNEL); + if (!p->value) + return -ENOMEM; + *(__be32 *)p->value = cpu_to_be32(cells); + + p->name = devm_kstrdup(pcs->dev, name, GFP_KERNEL); + if (!p->name) + return -ENOMEM; + + pcs->missing_nr_pinctrl_cells = p; + +#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE) + error = of_add_property(np, pcs->missing_nr_pinctrl_cells); +#endif + + return error; +} + static int pcs_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1807,6 +1874,7 @@ static int pcs_probe(struct platform_device *pdev) return -ENOMEM; } pcs->dev = &pdev->dev; + pcs->np = np; raw_spin_lock_init(&pcs->lock); mutex_init(&pcs->mutex); INIT_LIST_HEAD(&pcs->pingroups); @@ -1843,6 +1911,13 @@ static int pcs_probe(struct platform_device *pdev) pcs->bits_per_mux = of_property_read_bool(np, "pinctrl-single,bit-per-mux"); + ret = pcs_quirk_missing_pinctrl_cells(pcs, np, + pcs->bits_per_mux ? 2 : 1); + if (ret) { + dev_err(&pdev->dev, "unable to patch #pinctrl-cells\n"); + + return ret; + } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { -- cgit 1.4.1 From 22d5127ec916e8eac607eebbbafc026ef59afb36 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 3 Nov 2016 09:35:49 -0700 Subject: pinctrl: single: Use generic parser and #pinctrl-cells for pinctrl-single,bits We can now use generic parser and keep things compatible with the old binding. Signed-off-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 07c427367237..539f31cd8e00 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -35,7 +35,6 @@ #include "pinconf.h" #define DRIVER_NAME "pinctrl-single" -#define PCS_MUX_BITS_NAME "pinctrl-single,bits" #define PCS_OFF_DISABLED ~0U /** @@ -1216,36 +1215,22 @@ free_vals: return res; } -#define PARAMS_FOR_BITS_PER_MUX 3 - static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, struct device_node *np, struct pinctrl_map **map, unsigned *num_maps, const char **pgnames) { + const char *name = "pinctrl-single,pins"; struct pcs_func_vals *vals; - const __be32 *mux; - int size, rows, *pins, index = 0, found = 0, res = -ENOMEM; + int rows, *pins, found = 0, res = -ENOMEM, i; int npins_in_row; struct pcs_function *function; - mux = of_get_property(np, PCS_MUX_BITS_NAME, &size); - - if (!mux) { - dev_err(pcs->dev, "no valid property for %s\n", np->name); - return -EINVAL; - } - - if (size < (sizeof(*mux) * PARAMS_FOR_BITS_PER_MUX)) { - dev_err(pcs->dev, "bad data for %s\n", np->name); - return -EINVAL; - } - - /* Number of elements in array */ - size /= sizeof(*mux); + rows = pinctrl_count_index_with_args(np, name); + if (rows == -EINVAL) + return rows; - rows = size / PARAMS_FOR_BITS_PER_MUX; npins_in_row = pcs->width / pcs->bits_per_pin; vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row, @@ -1258,15 +1243,30 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, if (!pins) goto free_vals; - while (index < size) { + for (i = 0; i < rows; i++) { + struct of_phandle_args pinctrl_spec; unsigned offset, val; unsigned mask, bit_pos, val_pos, mask_pos, submask; unsigned pin_num_from_lsb; int pin; - offset = be32_to_cpup(mux + index++); - val = be32_to_cpup(mux + index++); - mask = be32_to_cpup(mux + index++); + res = pinctrl_parse_index_with_args(np, name, i, &pinctrl_spec); + if (res) + return res; + + if (pinctrl_spec.args_count < 3) { + dev_err(pcs->dev, "invalid args_count for spec: %i\n", + pinctrl_spec.args_count); + break; + } + + /* Index plus two value cells */ + offset = pinctrl_spec.args[0]; + val = pinctrl_spec.args[1]; + mask = pinctrl_spec.args[2]; + + dev_dbg(pcs->dev, "%s index: 0x%x value: 0x%x mask: 0x%x\n", + pinctrl_spec.np->name, offset, val, mask); /* Parse pins in each row from LSB */ while (mask) { -- cgit 1.4.1 From 0f15f500ff2c67cc5fa8fa74b270d7352dff1dba Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Mon, 31 Oct 2016 17:32:11 +0100 Subject: pinctrl: meson: Add GXL pinctrl definitions Add support for the Amlogic Meson GXL SoC, this is a partially complete definition only based on the Amlogic Vendor tree. This definition differs a lot from the GXBB and needs a separate entry. Acked-by: Rob Herring Signed-off-by: Neil Armstrong Acked-by: Kevin Hilman Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/meson,pinctrl.txt | 2 + drivers/pinctrl/meson/Makefile | 3 +- drivers/pinctrl/meson/pinctrl-meson-gxl.c | 589 +++++++++++++++++++++ drivers/pinctrl/meson/pinctrl-meson.c | 8 + drivers/pinctrl/meson/pinctrl-meson.h | 2 + include/dt-bindings/gpio/meson-gxl-gpio.h | 131 +++++ 6 files changed, 734 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/meson/pinctrl-meson-gxl.c create mode 100644 include/dt-bindings/gpio/meson-gxl-gpio.h (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt index fe7fe0b03cfb..2392557ede27 100644 --- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt @@ -7,6 +7,8 @@ Required properties for the root node: "amlogic,meson8b-aobus-pinctrl" "amlogic,meson-gxbb-periphs-pinctrl" "amlogic,meson-gxbb-aobus-pinctrl" + "amlogic,meson-gxl-periphs-pinctrl" + "amlogic,meson-gxl-aobus-pinctrl" - reg: address and size of registers controlling irq functionality === GPIO sub-nodes === diff --git a/drivers/pinctrl/meson/Makefile b/drivers/pinctrl/meson/Makefile index 24434f139947..27c5b5126008 100644 --- a/drivers/pinctrl/meson/Makefile +++ b/drivers/pinctrl/meson/Makefile @@ -1,2 +1,3 @@ -obj-y += pinctrl-meson8.o pinctrl-meson8b.o pinctrl-meson-gxbb.o +obj-y += pinctrl-meson8.o pinctrl-meson8b.o +obj-y += pinctrl-meson-gxbb.o pinctrl-meson-gxl.o obj-y += pinctrl-meson.o diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c new file mode 100644 index 000000000000..25694f7094c7 --- /dev/null +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c @@ -0,0 +1,589 @@ +/* + * Pin controller and GPIO driver for Amlogic Meson GXL. + * + * Copyright (C) 2016 Endless Mobile, Inc. + * Author: Carlo Caione + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "pinctrl-meson.h" + +#define EE_OFF 10 + +static const struct pinctrl_pin_desc meson_gxl_periphs_pins[] = { + MESON_PIN(GPIOZ_0, EE_OFF), + MESON_PIN(GPIOZ_1, EE_OFF), + MESON_PIN(GPIOZ_2, EE_OFF), + MESON_PIN(GPIOZ_3, EE_OFF), + MESON_PIN(GPIOZ_4, EE_OFF), + MESON_PIN(GPIOZ_5, EE_OFF), + MESON_PIN(GPIOZ_6, EE_OFF), + MESON_PIN(GPIOZ_7, EE_OFF), + MESON_PIN(GPIOZ_8, EE_OFF), + MESON_PIN(GPIOZ_9, EE_OFF), + MESON_PIN(GPIOZ_10, EE_OFF), + MESON_PIN(GPIOZ_11, EE_OFF), + MESON_PIN(GPIOZ_12, EE_OFF), + MESON_PIN(GPIOZ_13, EE_OFF), + MESON_PIN(GPIOZ_14, EE_OFF), + MESON_PIN(GPIOZ_15, EE_OFF), + + MESON_PIN(GPIOH_0, EE_OFF), + MESON_PIN(GPIOH_1, EE_OFF), + MESON_PIN(GPIOH_2, EE_OFF), + MESON_PIN(GPIOH_3, EE_OFF), + MESON_PIN(GPIOH_4, EE_OFF), + MESON_PIN(GPIOH_5, EE_OFF), + MESON_PIN(GPIOH_6, EE_OFF), + MESON_PIN(GPIOH_7, EE_OFF), + MESON_PIN(GPIOH_8, EE_OFF), + MESON_PIN(GPIOH_9, EE_OFF), + + MESON_PIN(BOOT_0, EE_OFF), + MESON_PIN(BOOT_1, EE_OFF), + MESON_PIN(BOOT_2, EE_OFF), + MESON_PIN(BOOT_3, EE_OFF), + MESON_PIN(BOOT_4, EE_OFF), + MESON_PIN(BOOT_5, EE_OFF), + MESON_PIN(BOOT_6, EE_OFF), + MESON_PIN(BOOT_7, EE_OFF), + MESON_PIN(BOOT_8, EE_OFF), + MESON_PIN(BOOT_9, EE_OFF), + MESON_PIN(BOOT_10, EE_OFF), + MESON_PIN(BOOT_11, EE_OFF), + MESON_PIN(BOOT_12, EE_OFF), + MESON_PIN(BOOT_13, EE_OFF), + MESON_PIN(BOOT_14, EE_OFF), + MESON_PIN(BOOT_15, EE_OFF), + + MESON_PIN(CARD_0, EE_OFF), + MESON_PIN(CARD_1, EE_OFF), + MESON_PIN(CARD_2, EE_OFF), + MESON_PIN(CARD_3, EE_OFF), + MESON_PIN(CARD_4, EE_OFF), + MESON_PIN(CARD_5, EE_OFF), + MESON_PIN(CARD_6, EE_OFF), + + MESON_PIN(GPIODV_0, EE_OFF), + MESON_PIN(GPIODV_1, EE_OFF), + MESON_PIN(GPIODV_2, EE_OFF), + MESON_PIN(GPIODV_3, EE_OFF), + MESON_PIN(GPIODV_4, EE_OFF), + MESON_PIN(GPIODV_5, EE_OFF), + MESON_PIN(GPIODV_6, EE_OFF), + MESON_PIN(GPIODV_7, EE_OFF), + MESON_PIN(GPIODV_8, EE_OFF), + MESON_PIN(GPIODV_9, EE_OFF), + MESON_PIN(GPIODV_10, EE_OFF), + MESON_PIN(GPIODV_11, EE_OFF), + MESON_PIN(GPIODV_12, EE_OFF), + MESON_PIN(GPIODV_13, EE_OFF), + MESON_PIN(GPIODV_14, EE_OFF), + MESON_PIN(GPIODV_15, EE_OFF), + MESON_PIN(GPIODV_16, EE_OFF), + MESON_PIN(GPIODV_17, EE_OFF), + MESON_PIN(GPIODV_19, EE_OFF), + MESON_PIN(GPIODV_20, EE_OFF), + MESON_PIN(GPIODV_21, EE_OFF), + MESON_PIN(GPIODV_22, EE_OFF), + MESON_PIN(GPIODV_23, EE_OFF), + MESON_PIN(GPIODV_24, EE_OFF), + MESON_PIN(GPIODV_25, EE_OFF), + MESON_PIN(GPIODV_26, EE_OFF), + MESON_PIN(GPIODV_27, EE_OFF), + MESON_PIN(GPIODV_28, EE_OFF), + MESON_PIN(GPIODV_29, EE_OFF), + + MESON_PIN(GPIOX_0, EE_OFF), + MESON_PIN(GPIOX_1, EE_OFF), + MESON_PIN(GPIOX_2, EE_OFF), + MESON_PIN(GPIOX_3, EE_OFF), + MESON_PIN(GPIOX_4, EE_OFF), + MESON_PIN(GPIOX_5, EE_OFF), + MESON_PIN(GPIOX_6, EE_OFF), + MESON_PIN(GPIOX_7, EE_OFF), + MESON_PIN(GPIOX_8, EE_OFF), + MESON_PIN(GPIOX_9, EE_OFF), + MESON_PIN(GPIOX_10, EE_OFF), + MESON_PIN(GPIOX_11, EE_OFF), + MESON_PIN(GPIOX_12, EE_OFF), + MESON_PIN(GPIOX_13, EE_OFF), + MESON_PIN(GPIOX_14, EE_OFF), + MESON_PIN(GPIOX_15, EE_OFF), + MESON_PIN(GPIOX_16, EE_OFF), + MESON_PIN(GPIOX_17, EE_OFF), + MESON_PIN(GPIOX_18, EE_OFF), + + MESON_PIN(GPIOCLK_0, EE_OFF), + MESON_PIN(GPIOCLK_1, EE_OFF), + + MESON_PIN(GPIO_TEST_N, EE_OFF), +}; + +static const unsigned int emmc_nand_d07_pins[] = { + PIN(BOOT_0, EE_OFF), PIN(BOOT_1, EE_OFF), PIN(BOOT_2, EE_OFF), + PIN(BOOT_3, EE_OFF), PIN(BOOT_4, EE_OFF), PIN(BOOT_5, EE_OFF), + PIN(BOOT_6, EE_OFF), PIN(BOOT_7, EE_OFF), +}; +static const unsigned int emmc_clk_pins[] = { PIN(BOOT_8, EE_OFF) }; +static const unsigned int emmc_cmd_pins[] = { PIN(BOOT_10, EE_OFF) }; +static const unsigned int emmc_ds_pins[] = { PIN(BOOT_15, EE_OFF) }; + +static const unsigned int sdcard_d0_pins[] = { PIN(CARD_1, EE_OFF) }; +static const unsigned int sdcard_d1_pins[] = { PIN(CARD_0, EE_OFF) }; +static const unsigned int sdcard_d2_pins[] = { PIN(CARD_5, EE_OFF) }; +static const unsigned int sdcard_d3_pins[] = { PIN(CARD_4, EE_OFF) }; +static const unsigned int sdcard_cmd_pins[] = { PIN(CARD_3, EE_OFF) }; +static const unsigned int sdcard_clk_pins[] = { PIN(CARD_2, EE_OFF) }; + +static const unsigned int sdio_d0_pins[] = { PIN(GPIOX_0, EE_OFF) }; +static const unsigned int sdio_d1_pins[] = { PIN(GPIOX_1, EE_OFF) }; +static const unsigned int sdio_d2_pins[] = { PIN(GPIOX_2, EE_OFF) }; +static const unsigned int sdio_d3_pins[] = { PIN(GPIOX_3, EE_OFF) }; +static const unsigned int sdio_cmd_pins[] = { PIN(GPIOX_4, EE_OFF) }; +static const unsigned int sdio_clk_pins[] = { PIN(GPIOX_5, EE_OFF) }; +static const unsigned int sdio_irq_pins[] = { PIN(GPIOX_7, EE_OFF) }; + +static const unsigned int nand_ce0_pins[] = { PIN(BOOT_8, EE_OFF) }; +static const unsigned int nand_ce1_pins[] = { PIN(BOOT_9, EE_OFF) }; +static const unsigned int nand_rb0_pins[] = { PIN(BOOT_10, EE_OFF) }; +static const unsigned int nand_ale_pins[] = { PIN(BOOT_11, EE_OFF) }; +static const unsigned int nand_cle_pins[] = { PIN(BOOT_12, EE_OFF) }; +static const unsigned int nand_wen_clk_pins[] = { PIN(BOOT_13, EE_OFF) }; +static const unsigned int nand_ren_wr_pins[] = { PIN(BOOT_14, EE_OFF) }; +static const unsigned int nand_dqs_pins[] = { PIN(BOOT_15, EE_OFF) }; + +static const unsigned int uart_tx_a_pins[] = { PIN(GPIOX_12, EE_OFF) }; +static const unsigned int uart_rx_a_pins[] = { PIN(GPIOX_13, EE_OFF) }; +static const unsigned int uart_cts_a_pins[] = { PIN(GPIOX_14, EE_OFF) }; +static const unsigned int uart_rts_a_pins[] = { PIN(GPIOX_15, EE_OFF) }; + +static const unsigned int uart_tx_b_pins[] = { PIN(GPIODV_24, EE_OFF) }; +static const unsigned int uart_rx_b_pins[] = { PIN(GPIODV_25, EE_OFF) }; + +static const unsigned int uart_tx_c_pins[] = { PIN(GPIOX_8, EE_OFF) }; +static const unsigned int uart_rx_c_pins[] = { PIN(GPIOX_9, EE_OFF) }; + +static const unsigned int i2c_sck_a_pins[] = { PIN(GPIODV_25, EE_OFF) }; +static const unsigned int i2c_sda_a_pins[] = { PIN(GPIODV_24, EE_OFF) }; + +static const unsigned int i2c_sck_b_pins[] = { PIN(GPIODV_27, EE_OFF) }; +static const unsigned int i2c_sda_b_pins[] = { PIN(GPIODV_26, EE_OFF) }; + +static const unsigned int i2c_sck_c_pins[] = { PIN(GPIODV_29, EE_OFF) }; +static const unsigned int i2c_sda_c_pins[] = { PIN(GPIODV_28, EE_OFF) }; + +static const unsigned int eth_mdio_pins[] = { PIN(GPIOZ_0, EE_OFF) }; +static const unsigned int eth_mdc_pins[] = { PIN(GPIOZ_1, EE_OFF) }; +static const unsigned int eth_clk_rx_clk_pins[] = { PIN(GPIOZ_2, EE_OFF) }; +static const unsigned int eth_rx_dv_pins[] = { PIN(GPIOZ_3, EE_OFF) }; +static const unsigned int eth_rxd0_pins[] = { PIN(GPIOZ_4, EE_OFF) }; +static const unsigned int eth_rxd1_pins[] = { PIN(GPIOZ_5, EE_OFF) }; +static const unsigned int eth_rxd2_pins[] = { PIN(GPIOZ_6, EE_OFF) }; +static const unsigned int eth_rxd3_pins[] = { PIN(GPIOZ_7, EE_OFF) }; +static const unsigned int eth_rgmii_tx_clk_pins[] = { PIN(GPIOZ_8, EE_OFF) }; +static const unsigned int eth_tx_en_pins[] = { PIN(GPIOZ_9, EE_OFF) }; +static const unsigned int eth_txd0_pins[] = { PIN(GPIOZ_10, EE_OFF) }; +static const unsigned int eth_txd1_pins[] = { PIN(GPIOZ_11, EE_OFF) }; +static const unsigned int eth_txd2_pins[] = { PIN(GPIOZ_12, EE_OFF) }; +static const unsigned int eth_txd3_pins[] = { PIN(GPIOZ_13, EE_OFF) }; + +static const unsigned int pwm_e_pins[] = { PIN(GPIOX_16, EE_OFF) }; + +static const struct pinctrl_pin_desc meson_gxl_aobus_pins[] = { + MESON_PIN(GPIOAO_0, 0), + MESON_PIN(GPIOAO_1, 0), + MESON_PIN(GPIOAO_2, 0), + MESON_PIN(GPIOAO_3, 0), + MESON_PIN(GPIOAO_4, 0), + MESON_PIN(GPIOAO_5, 0), + MESON_PIN(GPIOAO_6, 0), + MESON_PIN(GPIOAO_7, 0), + MESON_PIN(GPIOAO_8, 0), + MESON_PIN(GPIOAO_9, 0), +}; + +static const unsigned int uart_tx_ao_a_pins[] = { PIN(GPIOAO_0, 0) }; +static const unsigned int uart_rx_ao_a_pins[] = { PIN(GPIOAO_1, 0) }; +static const unsigned int uart_cts_ao_a_pins[] = { PIN(GPIOAO_2, 0) }; +static const unsigned int uart_rts_ao_a_pins[] = { PIN(GPIOAO_3, 0) }; +static const unsigned int uart_tx_ao_b_pins[] = { PIN(GPIOAO_0, 0) }; +static const unsigned int uart_rx_ao_b_pins[] = { PIN(GPIOAO_1, 0), + PIN(GPIOAO_5, 0) }; +static const unsigned int uart_cts_ao_b_pins[] = { PIN(GPIOAO_2, 0) }; +static const unsigned int uart_rts_ao_b_pins[] = { PIN(GPIOAO_3, 0) }; + +static const unsigned int remote_input_ao_pins[] = {PIN(GPIOAO_7, 0) }; + +static struct meson_pmx_group meson_gxl_periphs_groups[] = { + GPIO_GROUP(GPIOZ_0, EE_OFF), + GPIO_GROUP(GPIOZ_1, EE_OFF), + GPIO_GROUP(GPIOZ_2, EE_OFF), + GPIO_GROUP(GPIOZ_3, EE_OFF), + GPIO_GROUP(GPIOZ_4, EE_OFF), + GPIO_GROUP(GPIOZ_5, EE_OFF), + GPIO_GROUP(GPIOZ_6, EE_OFF), + GPIO_GROUP(GPIOZ_7, EE_OFF), + GPIO_GROUP(GPIOZ_8, EE_OFF), + GPIO_GROUP(GPIOZ_9, EE_OFF), + GPIO_GROUP(GPIOZ_10, EE_OFF), + GPIO_GROUP(GPIOZ_11, EE_OFF), + GPIO_GROUP(GPIOZ_12, EE_OFF), + GPIO_GROUP(GPIOZ_13, EE_OFF), + GPIO_GROUP(GPIOZ_14, EE_OFF), + GPIO_GROUP(GPIOZ_15, EE_OFF), + + GPIO_GROUP(GPIOH_0, EE_OFF), + GPIO_GROUP(GPIOH_1, EE_OFF), + GPIO_GROUP(GPIOH_2, EE_OFF), + GPIO_GROUP(GPIOH_3, EE_OFF), + GPIO_GROUP(GPIOH_4, EE_OFF), + GPIO_GROUP(GPIOH_5, EE_OFF), + GPIO_GROUP(GPIOH_6, EE_OFF), + GPIO_GROUP(GPIOH_7, EE_OFF), + GPIO_GROUP(GPIOH_8, EE_OFF), + GPIO_GROUP(GPIOH_9, EE_OFF), + + GPIO_GROUP(BOOT_0, EE_OFF), + GPIO_GROUP(BOOT_1, EE_OFF), + GPIO_GROUP(BOOT_2, EE_OFF), + GPIO_GROUP(BOOT_3, EE_OFF), + GPIO_GROUP(BOOT_4, EE_OFF), + GPIO_GROUP(BOOT_5, EE_OFF), + GPIO_GROUP(BOOT_6, EE_OFF), + GPIO_GROUP(BOOT_7, EE_OFF), + GPIO_GROUP(BOOT_8, EE_OFF), + GPIO_GROUP(BOOT_9, EE_OFF), + GPIO_GROUP(BOOT_10, EE_OFF), + GPIO_GROUP(BOOT_11, EE_OFF), + GPIO_GROUP(BOOT_12, EE_OFF), + GPIO_GROUP(BOOT_13, EE_OFF), + GPIO_GROUP(BOOT_14, EE_OFF), + GPIO_GROUP(BOOT_15, EE_OFF), + + GPIO_GROUP(CARD_0, EE_OFF), + GPIO_GROUP(CARD_1, EE_OFF), + GPIO_GROUP(CARD_2, EE_OFF), + GPIO_GROUP(CARD_3, EE_OFF), + GPIO_GROUP(CARD_4, EE_OFF), + GPIO_GROUP(CARD_5, EE_OFF), + GPIO_GROUP(CARD_6, EE_OFF), + + GPIO_GROUP(GPIODV_0, EE_OFF), + GPIO_GROUP(GPIODV_1, EE_OFF), + GPIO_GROUP(GPIODV_2, EE_OFF), + GPIO_GROUP(GPIODV_3, EE_OFF), + GPIO_GROUP(GPIODV_4, EE_OFF), + GPIO_GROUP(GPIODV_5, EE_OFF), + GPIO_GROUP(GPIODV_6, EE_OFF), + GPIO_GROUP(GPIODV_7, EE_OFF), + GPIO_GROUP(GPIODV_8, EE_OFF), + GPIO_GROUP(GPIODV_9, EE_OFF), + GPIO_GROUP(GPIODV_10, EE_OFF), + GPIO_GROUP(GPIODV_11, EE_OFF), + GPIO_GROUP(GPIODV_12, EE_OFF), + GPIO_GROUP(GPIODV_13, EE_OFF), + GPIO_GROUP(GPIODV_14, EE_OFF), + GPIO_GROUP(GPIODV_15, EE_OFF), + GPIO_GROUP(GPIODV_16, EE_OFF), + GPIO_GROUP(GPIODV_17, EE_OFF), + GPIO_GROUP(GPIODV_19, EE_OFF), + GPIO_GROUP(GPIODV_20, EE_OFF), + GPIO_GROUP(GPIODV_21, EE_OFF), + GPIO_GROUP(GPIODV_22, EE_OFF), + GPIO_GROUP(GPIODV_23, EE_OFF), + GPIO_GROUP(GPIODV_24, EE_OFF), + GPIO_GROUP(GPIODV_25, EE_OFF), + GPIO_GROUP(GPIODV_26, EE_OFF), + GPIO_GROUP(GPIODV_27, EE_OFF), + GPIO_GROUP(GPIODV_28, EE_OFF), + GPIO_GROUP(GPIODV_29, EE_OFF), + + GPIO_GROUP(GPIOX_0, EE_OFF), + GPIO_GROUP(GPIOX_1, EE_OFF), + GPIO_GROUP(GPIOX_2, EE_OFF), + GPIO_GROUP(GPIOX_3, EE_OFF), + GPIO_GROUP(GPIOX_4, EE_OFF), + GPIO_GROUP(GPIOX_5, EE_OFF), + GPIO_GROUP(GPIOX_6, EE_OFF), + GPIO_GROUP(GPIOX_7, EE_OFF), + GPIO_GROUP(GPIOX_8, EE_OFF), + GPIO_GROUP(GPIOX_9, EE_OFF), + GPIO_GROUP(GPIOX_10, EE_OFF), + GPIO_GROUP(GPIOX_11, EE_OFF), + GPIO_GROUP(GPIOX_12, EE_OFF), + GPIO_GROUP(GPIOX_13, EE_OFF), + GPIO_GROUP(GPIOX_14, EE_OFF), + GPIO_GROUP(GPIOX_15, EE_OFF), + GPIO_GROUP(GPIOX_16, EE_OFF), + GPIO_GROUP(GPIOX_17, EE_OFF), + GPIO_GROUP(GPIOX_18, EE_OFF), + + GPIO_GROUP(GPIOCLK_0, EE_OFF), + GPIO_GROUP(GPIOCLK_1, EE_OFF), + + GPIO_GROUP(GPIO_TEST_N, EE_OFF), + + /* Bank X */ + GROUP(sdio_d0, 5, 31), + GROUP(sdio_d1, 5, 30), + GROUP(sdio_d2, 5, 29), + GROUP(sdio_d3, 5, 28), + GROUP(sdio_cmd, 5, 27), + GROUP(sdio_clk, 5, 26), + GROUP(sdio_irq, 5, 24), + GROUP(uart_tx_a, 5, 19), + GROUP(uart_rx_a, 5, 18), + GROUP(uart_cts_a, 5, 17), + GROUP(uart_rts_a, 5, 16), + GROUP(uart_tx_c, 5, 13), + GROUP(uart_rx_c, 5, 12), + GROUP(pwm_e, 5, 15), + + /* Bank Z */ + GROUP(eth_mdio, 4, 22), + GROUP(eth_mdc, 4, 23), + GROUP(eth_clk_rx_clk, 4, 21), + GROUP(eth_rx_dv, 4, 20), + GROUP(eth_rxd0, 4, 19), + GROUP(eth_rxd1, 4, 18), + GROUP(eth_rxd2, 4, 17), + GROUP(eth_rxd3, 4, 16), + GROUP(eth_rgmii_tx_clk, 4, 15), + GROUP(eth_tx_en, 4, 14), + GROUP(eth_txd0, 4, 13), + GROUP(eth_txd1, 4, 12), + GROUP(eth_txd2, 4, 11), + GROUP(eth_txd3, 4, 10), + + /* Bank DV */ + GROUP(uart_tx_b, 2, 16), + GROUP(uart_rx_b, 2, 15), + GROUP(i2c_sck_a, 1, 15), + GROUP(i2c_sda_a, 1, 14), + GROUP(i2c_sck_b, 1, 13), + GROUP(i2c_sda_b, 1, 12), + GROUP(i2c_sck_c, 1, 11), + GROUP(i2c_sda_c, 1, 10), + + /* Bank BOOT */ + GROUP(emmc_nand_d07, 7, 31), + GROUP(emmc_clk, 7, 30), + GROUP(emmc_cmd, 7, 29), + GROUP(emmc_ds, 7, 28), + GROUP(nand_ce0, 7, 7), + GROUP(nand_ce1, 7, 6), + GROUP(nand_rb0, 7, 5), + GROUP(nand_ale, 7, 4), + GROUP(nand_cle, 7, 3), + GROUP(nand_wen_clk, 7, 2), + GROUP(nand_ren_wr, 7, 1), + GROUP(nand_dqs, 7, 0), + + /* Bank CARD */ + GROUP(sdcard_d1, 6, 5), + GROUP(sdcard_d0, 6, 4), + GROUP(sdcard_d3, 6, 1), + GROUP(sdcard_d2, 6, 0), + GROUP(sdcard_cmd, 6, 2), + GROUP(sdcard_clk, 6, 3), +}; + +static struct meson_pmx_group meson_gxl_aobus_groups[] = { + GPIO_GROUP(GPIOAO_0, 0), + GPIO_GROUP(GPIOAO_1, 0), + GPIO_GROUP(GPIOAO_2, 0), + GPIO_GROUP(GPIOAO_3, 0), + GPIO_GROUP(GPIOAO_4, 0), + GPIO_GROUP(GPIOAO_5, 0), + GPIO_GROUP(GPIOAO_6, 0), + GPIO_GROUP(GPIOAO_7, 0), + GPIO_GROUP(GPIOAO_8, 0), + GPIO_GROUP(GPIOAO_9, 0), + + /* bank AO */ + GROUP(uart_tx_ao_b, 0, 26), + GROUP(uart_rx_ao_b, 0, 25), + GROUP(uart_tx_ao_a, 0, 12), + GROUP(uart_rx_ao_a, 0, 11), + GROUP(uart_cts_ao_a, 0, 10), + GROUP(uart_rts_ao_a, 0, 9), + GROUP(uart_cts_ao_b, 0, 8), + GROUP(uart_rts_ao_b, 0, 7), + GROUP(remote_input_ao, 0, 0), +}; + +static const char * const gpio_periphs_groups[] = { + "GPIOZ_0", "GPIOZ_1", "GPIOZ_2", "GPIOZ_3", "GPIOZ_4", + "GPIOZ_5", "GPIOZ_6", "GPIOZ_7", "GPIOZ_8", "GPIOZ_9", + "GPIOZ_10", "GPIOZ_11", "GPIOZ_12", "GPIOZ_13", "GPIOZ_14", + "GPIOZ_15", + + "GPIOH_0", "GPIOH_1", "GPIOH_2", "GPIOH_3", "GPIOH_4", + "GPIOH_5", "GPIOH_6", "GPIOH_7", "GPIOH_8", "GPIOH_9", + + "BOOT_0", "BOOT_1", "BOOT_2", "BOOT_3", "BOOT_4", + "BOOT_5", "BOOT_6", "BOOT_7", "BOOT_8", "BOOT_9", + "BOOT_10", "BOOT_11", "BOOT_12", "BOOT_13", "BOOT_14", + "BOOT_15", + + "CARD_0", "CARD_1", "CARD_2", "CARD_3", "CARD_4", + "CARD_5", "CARD_6", + + "GPIODV_0", "GPIODV_1", "GPIODV_2", "GPIODV_3", "GPIODV_4", + "GPIODV_5", "GPIODV_6", "GPIODV_7", "GPIODV_8", "GPIODV_9", + "GPIODV_10", "GPIODV_11", "GPIODV_12", "GPIODV_13", "GPIODV_14", + "GPIODV_15", "GPIODV_16", "GPIODV_17", "GPIODV_18", "GPIODV_19", + "GPIODV_20", "GPIODV_21", "GPIODV_22", "GPIODV_23", "GPIODV_24", + "GPIODV_25", "GPIODV_26", "GPIODV_27", "GPIODV_28", "GPIODV_29", + + "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3", "GPIOX_4", + "GPIOX_5", "GPIOX_6", "GPIOX_7", "GPIOX_8", "GPIOX_9", + "GPIOX_10", "GPIOX_11", "GPIOX_12", "GPIOX_13", "GPIOX_14", + "GPIOX_15", "GPIOX_16", "GPIOX_17", "GPIOX_18", + + "GPIO_TEST_N", +}; + +static const char * const emmc_groups[] = { + "emmc_nand_d07", "emmc_clk", "emmc_cmd", "emmc_ds", +}; + +static const char * const sdcard_groups[] = { + "sdcard_d0", "sdcard_d1", "sdcard_d2", "sdcard_d3", + "sdcard_cmd", "sdcard_clk", +}; + +static const char * const sdio_groups[] = { + "sdio_d0", "sdio_d1", "sdio_d2", "sdio_d3", + "sdio_cmd", "sdio_clk", "sdio_irq", +}; + +static const char * const nand_groups[] = { + "nand_ce0", "nand_ce1", "nand_rb0", "nand_ale", "nand_cle", + "nand_wen_clk", "nand_ren_wr", "nand_dqs", +}; + +static const char * const uart_a_groups[] = { + "uart_tx_a", "uart_rx_a", "uart_cts_a", "uart_rts_a", +}; + +static const char * const uart_b_groups[] = { + "uart_tx_b", "uart_rx_b", +}; + +static const char * const uart_c_groups[] = { + "uart_tx_c", "uart_rx_c", +}; + +static const char * const i2c_a_groups[] = { + "i2c_sck_a", "i2c_sda_a", +}; + +static const char * const i2c_b_groups[] = { + "i2c_sck_b", "i2c_sda_b", +}; + +static const char * const i2c_c_groups[] = { + "i2c_sck_c", "i2c_sda_c", +}; + +static const char * const eth_groups[] = { + "eth_mdio", "eth_mdc", "eth_clk_rx_clk", "eth_rx_dv", + "eth_rxd0", "eth_rxd1", "eth_rxd2", "eth_rxd3", + "eth_rgmii_tx_clk", "eth_tx_en", + "eth_txd0", "eth_txd1", "eth_txd2", "eth_txd3", +}; + +static const char * const pwm_e_groups[] = { + "pwm_e", +}; + +static const char * const gpio_aobus_groups[] = { + "GPIOAO_0", "GPIOAO_1", "GPIOAO_2", "GPIOAO_3", "GPIOAO_4", + "GPIOAO_5", "GPIOAO_6", "GPIOAO_7", "GPIOAO_8", "GPIOAO_9", +}; + +static const char * const uart_ao_groups[] = { + "uart_tx_ao_a", "uart_rx_ao_a", "uart_cts_ao_a", "uart_rts_ao_a", +}; + +static const char * const uart_ao_b_groups[] = { + "uart_tx_ao_b", "uart_rx_ao_b", "uart_cts_ao_b", "uart_rts_ao_b", +}; + +static const char * const remote_input_ao_groups[] = { + "remote_input_ao", +}; + +static struct meson_pmx_func meson_gxl_periphs_functions[] = { + FUNCTION(gpio_periphs), + FUNCTION(emmc), + FUNCTION(sdcard), + FUNCTION(sdio), + FUNCTION(nand), + FUNCTION(uart_a), + FUNCTION(uart_b), + FUNCTION(uart_c), + FUNCTION(i2c_a), + FUNCTION(i2c_b), + FUNCTION(i2c_c), + FUNCTION(eth), + FUNCTION(pwm_e), +}; + +static struct meson_pmx_func meson_gxl_aobus_functions[] = { + FUNCTION(gpio_aobus), + FUNCTION(uart_ao), + FUNCTION(uart_ao_b), + FUNCTION(remote_input_ao), +}; + +static struct meson_bank meson_gxl_periphs_banks[] = { + /* name first last pullen pull dir out in */ + BANK("X", PIN(GPIOX_0, EE_OFF), PIN(GPIOX_18, EE_OFF), 4, 0, 4, 0, 12, 0, 13, 0, 14, 0), + BANK("DV", PIN(GPIODV_0, EE_OFF), PIN(GPIODV_29, EE_OFF), 0, 0, 0, 0, 0, 0, 1, 0, 2, 0), + BANK("H", PIN(GPIOH_0, EE_OFF), PIN(GPIOH_9, EE_OFF), 1, 20, 1, 20, 3, 20, 4, 20, 5, 20), + BANK("Z", PIN(GPIOZ_0, EE_OFF), PIN(GPIOZ_15, EE_OFF), 3, 0, 3, 0, 9, 0, 10, 0, 11, 0), + BANK("CARD", PIN(CARD_0, EE_OFF), PIN(CARD_6, EE_OFF), 2, 20, 2, 20, 6, 20, 7, 20, 8, 20), + BANK("BOOT", PIN(BOOT_0, EE_OFF), PIN(BOOT_15, EE_OFF), 2, 0, 2, 0, 6, 0, 7, 0, 8, 0), + BANK("CLK", PIN(GPIOCLK_0, EE_OFF), PIN(GPIOCLK_1, EE_OFF), 3, 28, 3, 28, 9, 28, 10, 28, 11, 28), +}; + +static struct meson_bank meson_gxl_aobus_banks[] = { + /* name first last pullen pull dir out in */ + BANK("AO", PIN(GPIOAO_0, 0), PIN(GPIOAO_9, 0), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0), +}; + +struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = { + .name = "periphs-banks", + .pin_base = 10, + .pins = meson_gxl_periphs_pins, + .groups = meson_gxl_periphs_groups, + .funcs = meson_gxl_periphs_functions, + .banks = meson_gxl_periphs_banks, + .num_pins = ARRAY_SIZE(meson_gxl_periphs_pins), + .num_groups = ARRAY_SIZE(meson_gxl_periphs_groups), + .num_funcs = ARRAY_SIZE(meson_gxl_periphs_functions), + .num_banks = ARRAY_SIZE(meson_gxl_periphs_banks), +}; + +struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data = { + .name = "aobus-banks", + .pin_base = 0, + .pins = meson_gxl_aobus_pins, + .groups = meson_gxl_aobus_groups, + .funcs = meson_gxl_aobus_functions, + .banks = meson_gxl_aobus_banks, + .num_pins = ARRAY_SIZE(meson_gxl_aobus_pins), + .num_groups = ARRAY_SIZE(meson_gxl_aobus_groups), + .num_funcs = ARRAY_SIZE(meson_gxl_aobus_functions), + .num_banks = ARRAY_SIZE(meson_gxl_aobus_banks), +}; diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index 57122eda155a..a579126832af 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -524,6 +524,14 @@ static const struct of_device_id meson_pinctrl_dt_match[] = { .compatible = "amlogic,meson-gxbb-aobus-pinctrl", .data = &meson_gxbb_aobus_pinctrl_data, }, + { + .compatible = "amlogic,meson-gxl-periphs-pinctrl", + .data = &meson_gxl_periphs_pinctrl_data, + }, + { + .compatible = "amlogic,meson-gxl-aobus-pinctrl", + .data = &meson_gxl_aobus_pinctrl_data, + }, { }, }; diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h index 98b5080650c1..1aa871d5431e 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.h +++ b/drivers/pinctrl/meson/pinctrl-meson.h @@ -169,3 +169,5 @@ extern struct meson_pinctrl_data meson8b_cbus_pinctrl_data; extern struct meson_pinctrl_data meson8b_aobus_pinctrl_data; extern struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data; extern struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data; +extern struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data; +extern struct meson_pinctrl_data meson_gxl_aobus_pinctrl_data; diff --git a/include/dt-bindings/gpio/meson-gxl-gpio.h b/include/dt-bindings/gpio/meson-gxl-gpio.h new file mode 100644 index 000000000000..684d0d7add1c --- /dev/null +++ b/include/dt-bindings/gpio/meson-gxl-gpio.h @@ -0,0 +1,131 @@ +/* + * GPIO definitions for Amlogic Meson GXL SoCs + * + * Copyright (C) 2016 Endless Mobile, Inc. + * Author: Carlo Caione + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _DT_BINDINGS_MESON_GXL_GPIO_H +#define _DT_BINDINGS_MESON_GXL_GPIO_H + +#define GPIOAO_0 0 +#define GPIOAO_1 1 +#define GPIOAO_2 2 +#define GPIOAO_3 3 +#define GPIOAO_4 4 +#define GPIOAO_5 5 +#define GPIOAO_6 6 +#define GPIOAO_7 7 +#define GPIOAO_8 8 +#define GPIOAO_9 9 + +#define GPIOZ_0 0 +#define GPIOZ_1 1 +#define GPIOZ_2 2 +#define GPIOZ_3 3 +#define GPIOZ_4 4 +#define GPIOZ_5 5 +#define GPIOZ_6 6 +#define GPIOZ_7 7 +#define GPIOZ_8 8 +#define GPIOZ_9 9 +#define GPIOZ_10 10 +#define GPIOZ_11 11 +#define GPIOZ_12 12 +#define GPIOZ_13 13 +#define GPIOZ_14 14 +#define GPIOZ_15 15 +#define GPIOH_0 16 +#define GPIOH_1 17 +#define GPIOH_2 18 +#define GPIOH_3 19 +#define GPIOH_4 20 +#define GPIOH_5 21 +#define GPIOH_6 22 +#define GPIOH_7 23 +#define GPIOH_8 24 +#define GPIOH_9 25 +#define BOOT_0 26 +#define BOOT_1 27 +#define BOOT_2 28 +#define BOOT_3 29 +#define BOOT_4 30 +#define BOOT_5 31 +#define BOOT_6 32 +#define BOOT_7 33 +#define BOOT_8 34 +#define BOOT_9 35 +#define BOOT_10 36 +#define BOOT_11 37 +#define BOOT_12 38 +#define BOOT_13 39 +#define BOOT_14 40 +#define BOOT_15 41 +#define CARD_0 42 +#define CARD_1 43 +#define CARD_2 44 +#define CARD_3 45 +#define CARD_4 46 +#define CARD_5 47 +#define CARD_6 48 +#define GPIODV_0 49 +#define GPIODV_1 50 +#define GPIODV_2 51 +#define GPIODV_3 52 +#define GPIODV_4 53 +#define GPIODV_5 54 +#define GPIODV_6 55 +#define GPIODV_7 56 +#define GPIODV_8 57 +#define GPIODV_9 58 +#define GPIODV_10 59 +#define GPIODV_11 60 +#define GPIODV_12 61 +#define GPIODV_13 62 +#define GPIODV_14 63 +#define GPIODV_15 64 +#define GPIODV_16 65 +#define GPIODV_17 66 +#define GPIODV_18 67 +#define GPIODV_19 68 +#define GPIODV_20 69 +#define GPIODV_21 70 +#define GPIODV_22 71 +#define GPIODV_23 72 +#define GPIODV_24 73 +#define GPIODV_25 74 +#define GPIODV_26 75 +#define GPIODV_27 76 +#define GPIODV_28 77 +#define GPIODV_29 78 +#define GPIOX_0 79 +#define GPIOX_1 80 +#define GPIOX_2 81 +#define GPIOX_3 82 +#define GPIOX_4 83 +#define GPIOX_5 84 +#define GPIOX_6 85 +#define GPIOX_7 86 +#define GPIOX_8 87 +#define GPIOX_9 88 +#define GPIOX_10 89 +#define GPIOX_11 90 +#define GPIOX_12 91 +#define GPIOX_13 92 +#define GPIOX_14 93 +#define GPIOX_15 94 +#define GPIOX_16 95 +#define GPIOX_17 96 +#define GPIOX_18 97 +#define GPIOCLK_0 98 +#define GPIOCLK_1 99 +#define GPIO_TEST_N 100 + +#endif -- cgit 1.4.1 From 0c8c6ba00cbf2c0a6164aa41d43d017d65caf321 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Sat, 29 Oct 2016 20:00:30 -0400 Subject: pinctrl: sunxi: make bool drivers explicitly non-modular None of the Kconfigs for any of these drivers are tristate, meaning that they currently are not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the drivers there is no doubt they are builtin-only. All drivers get essentially the same change, so they are handled in batch. Changes are (1) use builtin_platform_driver, (2) use init.h header (3) delete module_exit related code, (4) delete MODULE_DEVICE_TABLE, and (5) delete MODULE_LICENCE/MODULE_AUTHOR and associated tags. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We do delete the MODULE_LICENSE etc. tags since all that information is already contained at the top of each file in the comments. Cc: Boris Brezillon Cc: Chen-Yu Tsai Cc: Hans de Goede Cc: Linus Walleij Cc: Patrice Chotard Cc: Hongzhou Yang Cc: Fabian Frederick Cc: Maxime Coquelin Cc: Vishnu Patekar Cc: Mylene Josserand Cc: linux-gpio@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-gr8.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun4i-a10.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun5i-a10s.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun5i-a13.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31-r.c | 10 ++-------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun6i-a31s.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun8i-a23-r.c | 11 ++--------- drivers/pinctrl/sunxi/pinctrl-sun8i-a23.c | 10 ++-------- drivers/pinctrl/sunxi/pinctrl-sun8i-a33.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c | 9 ++------- drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c | 9 ++------- 13 files changed, 26 insertions(+), 95 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-gr8.c b/drivers/pinctrl/sunxi/pinctrl-gr8.c index 2904d2b7378b..2f232c3a0579 100644 --- a/drivers/pinctrl/sunxi/pinctrl-gr8.c +++ b/drivers/pinctrl/sunxi/pinctrl-gr8.c @@ -12,7 +12,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -525,7 +525,6 @@ static const struct of_device_id sun5i_gr8_pinctrl_match[] = { { .compatible = "nextthing,gr8-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_gr8_pinctrl_match); static struct platform_driver sun5i_gr8_pinctrl_driver = { .probe = sun5i_gr8_pinctrl_probe, @@ -534,8 +533,4 @@ static struct platform_driver sun5i_gr8_pinctrl_driver = { .of_match_table = sun5i_gr8_pinctrl_match, }, }; -module_platform_driver(sun5i_gr8_pinctrl_driver); - -MODULE_AUTHOR("Mylene Josserand +#include #include #include #include @@ -1035,7 +1035,6 @@ static const struct of_device_id sun4i_a10_pinctrl_match[] = { { .compatible = "allwinner,sun4i-a10-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun4i_a10_pinctrl_match); static struct platform_driver sun4i_a10_pinctrl_driver = { .probe = sun4i_a10_pinctrl_probe, @@ -1044,8 +1043,4 @@ static struct platform_driver sun4i_a10_pinctrl_driver = { .of_match_table = sun4i_a10_pinctrl_match, }, }; -module_platform_driver(sun4i_a10_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -674,7 +674,6 @@ static const struct of_device_id sun5i_a10s_pinctrl_match[] = { { .compatible = "allwinner,sun5i-a10s-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_a10s_pinctrl_match); static struct platform_driver sun5i_a10s_pinctrl_driver = { .probe = sun5i_a10s_pinctrl_probe, @@ -683,8 +682,4 @@ static struct platform_driver sun5i_a10s_pinctrl_driver = { .of_match_table = sun5i_a10s_pinctrl_match, }, }; -module_platform_driver(sun5i_a10s_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -392,7 +392,6 @@ static const struct of_device_id sun5i_a13_pinctrl_match[] = { { .compatible = "allwinner,sun5i-a13-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun5i_a13_pinctrl_match); static struct platform_driver sun5i_a13_pinctrl_driver = { .probe = sun5i_a13_pinctrl_probe, @@ -401,8 +400,4 @@ static struct platform_driver sun5i_a13_pinctrl_driver = { .of_match_table = sun5i_a13_pinctrl_match, }, }; -module_platform_driver(sun5i_a13_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -136,7 +136,6 @@ static const struct of_device_id sun6i_a31_r_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31-r-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31_r_pinctrl_match); static struct platform_driver sun6i_a31_r_pinctrl_driver = { .probe = sun6i_a31_r_pinctrl_probe, @@ -145,9 +144,4 @@ static struct platform_driver sun6i_a31_r_pinctrl_driver = { .of_match_table = sun6i_a31_r_pinctrl_match, }, }; -module_platform_driver(sun6i_a31_r_pinctrl_driver); - -MODULE_AUTHOR("Boris Brezillon +#include #include #include #include @@ -934,7 +934,6 @@ static const struct of_device_id sun6i_a31_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31_pinctrl_match); static struct platform_driver sun6i_a31_pinctrl_driver = { .probe = sun6i_a31_pinctrl_probe, @@ -943,8 +942,4 @@ static struct platform_driver sun6i_a31_pinctrl_driver = { .of_match_table = sun6i_a31_pinctrl_match, }, }; -module_platform_driver(sun6i_a31_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -798,7 +798,6 @@ static const struct of_device_id sun6i_a31s_pinctrl_match[] = { { .compatible = "allwinner,sun6i-a31s-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun6i_a31s_pinctrl_match); static struct platform_driver sun6i_a31s_pinctrl_driver = { .probe = sun6i_a31s_pinctrl_probe, @@ -807,8 +806,4 @@ static struct platform_driver sun6i_a31s_pinctrl_driver = { .of_match_table = sun6i_a31s_pinctrl_match, }, }; -module_platform_driver(sun6i_a31s_pinctrl_driver); - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("Allwinner A31s pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun6i_a31s_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c index 435ad30f45db..b6f4c68ffb39 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun7i-a20.c @@ -10,7 +10,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -1045,7 +1045,6 @@ static const struct of_device_id sun7i_a20_pinctrl_match[] = { { .compatible = "allwinner,sun7i-a20-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun7i_a20_pinctrl_match); static struct platform_driver sun7i_a20_pinctrl_driver = { .probe = sun7i_a20_pinctrl_probe, @@ -1054,8 +1053,4 @@ static struct platform_driver sun7i_a20_pinctrl_driver = { .of_match_table = sun7i_a20_pinctrl_match, }, }; -module_platform_driver(sun7i_a20_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -123,7 +123,6 @@ static const struct of_device_id sun8i_a23_r_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a23-r-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a23_r_pinctrl_match); static struct platform_driver sun8i_a23_r_pinctrl_driver = { .probe = sun8i_a23_r_pinctrl_probe, @@ -132,10 +131,4 @@ static struct platform_driver sun8i_a23_r_pinctrl_driver = { .of_match_table = sun8i_a23_r_pinctrl_match, }, }; -module_platform_driver(sun8i_a23_r_pinctrl_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_AUTHOR("Boris Brezillon +#include #include #include #include @@ -575,7 +575,6 @@ static const struct of_device_id sun8i_a23_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a23-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a23_pinctrl_match); static struct platform_driver sun8i_a23_pinctrl_driver = { .probe = sun8i_a23_pinctrl_probe, @@ -584,9 +583,4 @@ static struct platform_driver sun8i_a23_pinctrl_driver = { .of_match_table = sun8i_a23_pinctrl_match, }, }; -module_platform_driver(sun8i_a23_pinctrl_driver); - -MODULE_AUTHOR("Chen-Yu Tsai "); -MODULE_AUTHOR("Maxime Ripard +#include #include #include #include @@ -498,7 +498,6 @@ static const struct of_device_id sun8i_a33_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a33-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a33_pinctrl_match); static struct platform_driver sun8i_a33_pinctrl_driver = { .probe = sun8i_a33_pinctrl_probe, @@ -507,8 +506,4 @@ static struct platform_driver sun8i_a33_pinctrl_driver = { .of_match_table = sun8i_a33_pinctrl_match, }, }; -module_platform_driver(sun8i_a33_pinctrl_driver); - -MODULE_AUTHOR("Vishnu Patekar "); -MODULE_DESCRIPTION("Allwinner a33 pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun8i_a33_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c index 90b973e15982..9aec1d2232dd 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-a83t.c @@ -12,7 +12,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -587,7 +587,6 @@ static const struct of_device_id sun8i_a83t_pinctrl_match[] = { { .compatible = "allwinner,sun8i-a83t-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun8i_a83t_pinctrl_match); static struct platform_driver sun8i_a83t_pinctrl_driver = { .probe = sun8i_a83t_pinctrl_probe, @@ -596,8 +595,4 @@ static struct platform_driver sun8i_a83t_pinctrl_driver = { .of_match_table = sun8i_a83t_pinctrl_match, }, }; -module_platform_driver(sun8i_a83t_pinctrl_driver); - -MODULE_AUTHOR("Vishnu Patekar "); -MODULE_DESCRIPTION("Allwinner a83t pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun8i_a83t_pinctrl_driver); diff --git a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c index 1b580ba76453..bc14e954d7a2 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c +++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80.c @@ -10,7 +10,7 @@ * warranty of any kind, whether express or implied. */ -#include +#include #include #include #include @@ -733,7 +733,6 @@ static const struct of_device_id sun9i_a80_pinctrl_match[] = { { .compatible = "allwinner,sun9i-a80-pinctrl", }, {} }; -MODULE_DEVICE_TABLE(of, sun9i_a80_pinctrl_match); static struct platform_driver sun9i_a80_pinctrl_driver = { .probe = sun9i_a80_pinctrl_probe, @@ -742,8 +741,4 @@ static struct platform_driver sun9i_a80_pinctrl_driver = { .of_match_table = sun9i_a80_pinctrl_match, }, }; -module_platform_driver(sun9i_a80_pinctrl_driver); - -MODULE_AUTHOR("Maxime Ripard "); -MODULE_DESCRIPTION("Allwinner A80 pinctrl driver"); -MODULE_LICENSE("GPL"); +builtin_platform_driver(sun9i_a80_pinctrl_driver); -- cgit 1.4.1 From 465e42180cd1065039c09df337efd0a58f007c50 Mon Sep 17 00:00:00 2001 From: Michael Scott Date: Thu, 3 Nov 2016 14:15:26 -0700 Subject: pinctrl: qcom: Add msm8994 pinctrl driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial pinctrl driver for QCOM msm8994 platforms. In order to continue the initial board support for QCOM msm8994/msm8992 presented in patches from Jeremy McNicoll , let's put a proper pinctrl driver in place. Currently, the DT for these platforms uses the msm8x74 pinctrl driver to enable basic UART. Beyond the first few pins the rest are different enough to justify it's own driver. Note: This driver is also used by QCOM's msm8992 platform as it's TLM block is the same. - Initial formatting and style was taken from the msm8x74 pinctrl driver added by Björn Andersson - Data was then adjusted per QCOM MSM8994v2 documentation for Top Level Multiplexing - Bindings documentation was based on qcom,msm8996-pinctrl.txt by Joonwoo Park and then modified for msm8994 content Signed-off-by: Michael Scott Tested-by: Jeremy McNicoll Acked-by: Bjorn Andersson Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/qcom,msm8994-pinctrl.txt | 177 +++ drivers/pinctrl/qcom/Kconfig | 9 + drivers/pinctrl/qcom/Makefile | 1 + drivers/pinctrl/qcom/pinctrl-msm8994.c | 1379 ++++++++++++++++++++ 4 files changed, 1566 insertions(+) create mode 100644 Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt create mode 100644 drivers/pinctrl/qcom/pinctrl-msm8994.c (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt new file mode 100644 index 000000000000..13cd629f896e --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt @@ -0,0 +1,177 @@ +Qualcomm MSM8994 TLMM block + +This binding describes the Top Level Mode Multiplexer block found in the +MSM8994 platform. + +- compatible: + Usage: required + Value type: + Definition: Should contain one of: + "qcom,msm8992-pinctrl", + "qcom,msm8994-pinctrl". + +- reg: + Usage: required + Value type: + Definition: the base address and size of the TLMM register space. + +- interrupts: + Usage: required + Value type: + Definition: should specify the TLMM summary IRQ. + +- interrupt-controller: + Usage: required + Value type: + Definition: identifies this node as an interrupt controller + +- #interrupt-cells: + Usage: required + Value type: + Definition: must be 2. Specifying the pin number and flags, as defined + in + +- gpio-controller: + Usage: required + Value type: + Definition: identifies this node as a gpio controller + +- #gpio-cells: + Usage: required + Value type: + Definition: must be 2. Specifying the pin number and flags, as defined + in + +Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for +a general description of GPIO and interrupt bindings. + +Please refer to pinctrl-bindings.txt in this directory for details of the +common pinctrl bindings used by client devices, including the meaning of the +phrase "pin configuration node". + +The pin configuration nodes act as a container for an arbitrary number of +subnodes. Each of these subnodes represents some desired configuration for a +pin, a group, or a list of pins or groups. This configuration can include the +mux function to select on those pin(s)/group(s), and various pin configuration +parameters, such as pull-up, drive strength, etc. + + +PIN CONFIGURATION NODES: + +The name of each subnode is not important; all subnodes should be enumerated +and processed purely based on their content. + +Each subnode only affects those parameters that are explicitly listed. In +other words, a subnode that lists a mux function but no pin configuration +parameters implies no information about any pin configuration parameters. +Similarly, a pin subnode that describes a pullup parameter implies no +information about e.g. the mux function. + + +The following generic properties as defined in pinctrl-bindings.txt are valid +to specify in a pin configuration subnode: + +- pins: + Usage: required + Value type: + Definition: List of gpio pins affected by the properties specified in + this subnode. + + Valid pins are: + gpio0-gpio145 + Supports mux, bias and drive-strength + + sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk, + sdc2_cmd, sdc2_data + Supports bias and drive-strength + +- function: + Usage: required + Value type: + Definition: Specify the alternative function to be configured for the + specified pins. Functions are only valid for gpio pins. + Valid values are: + + audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5, + blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11, + blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3, + blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3, + blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9, + blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11, + blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5, + blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11, + blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5, + blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11, + blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b, + blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3, + cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1, + cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, + gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a, + gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk, + gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv, + mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a, + qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d, + qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c, + qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, + qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0, + pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1, + tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio + +- bias-disable: + Usage: optional + Value type: + Definition: The specified pins should be configued as no pull. + +- bias-pull-down: + Usage: optional + Value type: + Definition: The specified pins should be configued as pull down. + +- bias-pull-up: + Usage: optional + Value type: + Definition: The specified pins should be configued as pull up. + +- output-high: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + high. + Not valid for sdc pins. + +- output-low: + Usage: optional + Value type: + Definition: The specified pins are configured in output mode, driven + low. + Not valid for sdc pins. + +- drive-strength: + Usage: optional + Value type: + Definition: Selects the drive strength for the specified pins, in mA. + Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16 + +Example: + + msmgpio: pinctrl@fd510000 { + compatible = "qcom,msm8994-pinctrl"; + reg = <0xfd510000 0x4000>; + interrupts = ; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + + blsp1_uart2_default: blsp1_uart2_default { + pinmux { + pins = "gpio4", "gpio5"; + function = "blsp_uart2"; + }; + pinconf { + pins = "gpio4", "gpio5"; + drive-strength = <16>; + bias-disable; + }; + }; + }; diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig index 93ef268d5ccd..3ebdc01f53c0 100644 --- a/drivers/pinctrl/qcom/Kconfig +++ b/drivers/pinctrl/qcom/Kconfig @@ -79,6 +79,15 @@ config PINCTRL_MSM8916 This is the pinctrl, pinmux, pinconf and gpiolib driver for the Qualcomm TLMM block found on the Qualcomm 8916 platform. +config PINCTRL_MSM8994 + tristate "Qualcomm 8994 pin controller driver" + depends on GPIOLIB && OF + select PINCTRL_MSM + help + This is the pinctrl, pinmux, pinconf and gpiolib driver for the + Qualcomm TLMM block found in the Qualcomm 8994 platform. The + Qualcomm 8992 platform is also supported by this driver. + config PINCTRL_MSM8996 tristate "Qualcomm MSM8996 pin controller driver" depends on GPIOLIB && OF diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile index 8319e11cecb5..ab47764dbc5c 100644 --- a/drivers/pinctrl/qcom/Makefile +++ b/drivers/pinctrl/qcom/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o +obj-$(CONFIG_PINCTRL_MSM8994) += pinctrl-msm8994.o obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o obj-$(CONFIG_PINCTRL_MDM9615) += pinctrl-mdm9615.o diff --git a/drivers/pinctrl/qcom/pinctrl-msm8994.c b/drivers/pinctrl/qcom/pinctrl-msm8994.c new file mode 100644 index 000000000000..8e16d9ae0c39 --- /dev/null +++ b/drivers/pinctrl/qcom/pinctrl-msm8994.c @@ -0,0 +1,1379 @@ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "pinctrl-msm.h" + +#define FUNCTION(fname) \ + [MSM_MUX_##fname] = { \ + .name = #fname, \ + .groups = fname##_groups, \ + .ngroups = ARRAY_SIZE(fname##_groups), \ + } + +#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11) \ + { \ + .name = "gpio" #id, \ + .pins = gpio##id##_pins, \ + .npins = ARRAY_SIZE(gpio##id##_pins), \ + .funcs = (int[]){ \ + MSM_MUX_gpio, \ + MSM_MUX_##f1, \ + MSM_MUX_##f2, \ + MSM_MUX_##f3, \ + MSM_MUX_##f4, \ + MSM_MUX_##f5, \ + MSM_MUX_##f6, \ + MSM_MUX_##f7, \ + MSM_MUX_##f8, \ + MSM_MUX_##f9, \ + MSM_MUX_##f10, \ + MSM_MUX_##f11 \ + }, \ + .nfuncs = 12, \ + .ctl_reg = 0x1000 + 0x10 * id, \ + .io_reg = 0x1004 + 0x10 * id, \ + .intr_cfg_reg = 0x1008 + 0x10 * id, \ + .intr_status_reg = 0x100c + 0x10 * id, \ + .intr_target_reg = 0x1008 + 0x10 * id, \ + .mux_bit = 2, \ + .pull_bit = 0, \ + .drv_bit = 6, \ + .oe_bit = 9, \ + .in_bit = 0, \ + .out_bit = 1, \ + .intr_enable_bit = 0, \ + .intr_status_bit = 0, \ + .intr_target_bit = 5, \ + .intr_target_kpss_val = 4, \ + .intr_raw_status_bit = 4, \ + .intr_polarity_bit = 1, \ + .intr_detection_bit = 2, \ + .intr_detection_width = 2, \ + } + +#define SDC_PINGROUP(pg_name, ctl, pull, drv) \ + { \ + .name = #pg_name, \ + .pins = pg_name##_pins, \ + .npins = ARRAY_SIZE(pg_name##_pins), \ + .ctl_reg = ctl, \ + .io_reg = 0, \ + .intr_cfg_reg = 0, \ + .intr_status_reg = 0, \ + .intr_target_reg = 0, \ + .mux_bit = -1, \ + .pull_bit = pull, \ + .drv_bit = drv, \ + .oe_bit = -1, \ + .in_bit = -1, \ + .out_bit = -1, \ + .intr_enable_bit = -1, \ + .intr_status_bit = -1, \ + .intr_target_bit = -1, \ + .intr_target_kpss_val = -1, \ + .intr_raw_status_bit = -1, \ + .intr_polarity_bit = -1, \ + .intr_detection_bit = -1, \ + .intr_detection_width = -1, \ + } +static const struct pinctrl_pin_desc msm8994_pins[] = { + PINCTRL_PIN(0, "GPIO_0"), + PINCTRL_PIN(1, "GPIO_1"), + PINCTRL_PIN(2, "GPIO_2"), + PINCTRL_PIN(3, "GPIO_3"), + PINCTRL_PIN(4, "GPIO_4"), + PINCTRL_PIN(5, "GPIO_5"), + PINCTRL_PIN(6, "GPIO_6"), + PINCTRL_PIN(7, "GPIO_7"), + PINCTRL_PIN(8, "GPIO_8"), + PINCTRL_PIN(9, "GPIO_9"), + PINCTRL_PIN(10, "GPIO_10"), + PINCTRL_PIN(11, "GPIO_11"), + PINCTRL_PIN(12, "GPIO_12"), + PINCTRL_PIN(13, "GPIO_13"), + PINCTRL_PIN(14, "GPIO_14"), + PINCTRL_PIN(15, "GPIO_15"), + PINCTRL_PIN(16, "GPIO_16"), + PINCTRL_PIN(17, "GPIO_17"), + PINCTRL_PIN(18, "GPIO_18"), + PINCTRL_PIN(19, "GPIO_19"), + PINCTRL_PIN(20, "GPIO_20"), + PINCTRL_PIN(21, "GPIO_21"), + PINCTRL_PIN(22, "GPIO_22"), + PINCTRL_PIN(23, "GPIO_23"), + PINCTRL_PIN(24, "GPIO_24"), + PINCTRL_PIN(25, "GPIO_25"), + PINCTRL_PIN(26, "GPIO_26"), + PINCTRL_PIN(27, "GPIO_27"), + PINCTRL_PIN(28, "GPIO_28"), + PINCTRL_PIN(29, "GPIO_29"), + PINCTRL_PIN(30, "GPIO_30"), + PINCTRL_PIN(31, "GPIO_31"), + PINCTRL_PIN(32, "GPIO_32"), + PINCTRL_PIN(33, "GPIO_33"), + PINCTRL_PIN(34, "GPIO_34"), + PINCTRL_PIN(35, "GPIO_35"), + PINCTRL_PIN(36, "GPIO_36"), + PINCTRL_PIN(37, "GPIO_37"), + PINCTRL_PIN(38, "GPIO_38"), + PINCTRL_PIN(39, "GPIO_39"), + PINCTRL_PIN(40, "GPIO_40"), + PINCTRL_PIN(41, "GPIO_41"), + PINCTRL_PIN(42, "GPIO_42"), + PINCTRL_PIN(43, "GPIO_43"), + PINCTRL_PIN(44, "GPIO_44"), + PINCTRL_PIN(45, "GPIO_45"), + PINCTRL_PIN(46, "GPIO_46"), + PINCTRL_PIN(47, "GPIO_47"), + PINCTRL_PIN(48, "GPIO_48"), + PINCTRL_PIN(49, "GPIO_49"), + PINCTRL_PIN(50, "GPIO_50"), + PINCTRL_PIN(51, "GPIO_51"), + PINCTRL_PIN(52, "GPIO_52"), + PINCTRL_PIN(53, "GPIO_53"), + PINCTRL_PIN(54, "GPIO_54"), + PINCTRL_PIN(55, "GPIO_55"), + PINCTRL_PIN(56, "GPIO_56"), + PINCTRL_PIN(57, "GPIO_57"), + PINCTRL_PIN(58, "GPIO_58"), + PINCTRL_PIN(59, "GPIO_59"), + PINCTRL_PIN(60, "GPIO_60"), + PINCTRL_PIN(61, "GPIO_61"), + PINCTRL_PIN(62, "GPIO_62"), + PINCTRL_PIN(63, "GPIO_63"), + PINCTRL_PIN(64, "GPIO_64"), + PINCTRL_PIN(65, "GPIO_65"), + PINCTRL_PIN(66, "GPIO_66"), + PINCTRL_PIN(67, "GPIO_67"), + PINCTRL_PIN(68, "GPIO_68"), + PINCTRL_PIN(69, "GPIO_69"), + PINCTRL_PIN(70, "GPIO_70"), + PINCTRL_PIN(71, "GPIO_71"), + PINCTRL_PIN(72, "GPIO_72"), + PINCTRL_PIN(73, "GPIO_73"), + PINCTRL_PIN(74, "GPIO_74"), + PINCTRL_PIN(75, "GPIO_75"), + PINCTRL_PIN(76, "GPIO_76"), + PINCTRL_PIN(77, "GPIO_77"), + PINCTRL_PIN(78, "GPIO_78"), + PINCTRL_PIN(79, "GPIO_79"), + PINCTRL_PIN(80, "GPIO_80"), + PINCTRL_PIN(81, "GPIO_81"), + PINCTRL_PIN(82, "GPIO_82"), + PINCTRL_PIN(83, "GPIO_83"), + PINCTRL_PIN(84, "GPIO_84"), + PINCTRL_PIN(85, "GPIO_85"), + PINCTRL_PIN(86, "GPIO_86"), + PINCTRL_PIN(87, "GPIO_87"), + PINCTRL_PIN(88, "GPIO_88"), + PINCTRL_PIN(89, "GPIO_89"), + PINCTRL_PIN(90, "GPIO_90"), + PINCTRL_PIN(91, "GPIO_91"), + PINCTRL_PIN(92, "GPIO_92"), + PINCTRL_PIN(93, "GPIO_93"), + PINCTRL_PIN(94, "GPIO_94"), + PINCTRL_PIN(95, "GPIO_95"), + PINCTRL_PIN(96, "GPIO_96"), + PINCTRL_PIN(97, "GPIO_97"), + PINCTRL_PIN(98, "GPIO_98"), + PINCTRL_PIN(99, "GPIO_99"), + PINCTRL_PIN(100, "GPIO_100"), + PINCTRL_PIN(101, "GPIO_101"), + PINCTRL_PIN(102, "GPIO_102"), + PINCTRL_PIN(103, "GPIO_103"), + PINCTRL_PIN(104, "GPIO_104"), + PINCTRL_PIN(105, "GPIO_105"), + PINCTRL_PIN(106, "GPIO_106"), + PINCTRL_PIN(107, "GPIO_107"), + PINCTRL_PIN(108, "GPIO_108"), + PINCTRL_PIN(109, "GPIO_109"), + PINCTRL_PIN(110, "GPIO_110"), + PINCTRL_PIN(111, "GPIO_111"), + PINCTRL_PIN(112, "GPIO_112"), + PINCTRL_PIN(113, "GPIO_113"), + PINCTRL_PIN(114, "GPIO_114"), + PINCTRL_PIN(115, "GPIO_115"), + PINCTRL_PIN(116, "GPIO_116"), + PINCTRL_PIN(117, "GPIO_117"), + PINCTRL_PIN(118, "GPIO_118"), + PINCTRL_PIN(119, "GPIO_119"), + PINCTRL_PIN(120, "GPIO_120"), + PINCTRL_PIN(121, "GPIO_121"), + PINCTRL_PIN(122, "GPIO_122"), + PINCTRL_PIN(123, "GPIO_123"), + PINCTRL_PIN(124, "GPIO_124"), + PINCTRL_PIN(125, "GPIO_125"), + PINCTRL_PIN(126, "GPIO_126"), + PINCTRL_PIN(127, "GPIO_127"), + PINCTRL_PIN(128, "GPIO_128"), + PINCTRL_PIN(129, "GPIO_129"), + PINCTRL_PIN(130, "GPIO_130"), + PINCTRL_PIN(131, "GPIO_131"), + PINCTRL_PIN(132, "GPIO_132"), + PINCTRL_PIN(133, "GPIO_133"), + PINCTRL_PIN(134, "GPIO_134"), + PINCTRL_PIN(135, "GPIO_135"), + PINCTRL_PIN(136, "GPIO_136"), + PINCTRL_PIN(137, "GPIO_137"), + PINCTRL_PIN(138, "GPIO_138"), + PINCTRL_PIN(139, "GPIO_139"), + PINCTRL_PIN(140, "GPIO_140"), + PINCTRL_PIN(141, "GPIO_141"), + PINCTRL_PIN(142, "GPIO_142"), + PINCTRL_PIN(143, "GPIO_143"), + PINCTRL_PIN(144, "GPIO_144"), + PINCTRL_PIN(145, "GPIO_145"), + PINCTRL_PIN(146, "SDC1_RCLK"), + PINCTRL_PIN(147, "SDC1_CLK"), + PINCTRL_PIN(148, "SDC1_CMD"), + PINCTRL_PIN(149, "SDC1_DATA"), + PINCTRL_PIN(150, "SDC2_CLK"), + PINCTRL_PIN(151, "SDC2_CMD"), + PINCTRL_PIN(152, "SDC2_DATA"), + PINCTRL_PIN(153, "SDC3_CLK"), + PINCTRL_PIN(154, "SDC3_CMD"), + PINCTRL_PIN(155, "SDC3_DATA"), +}; + +#define DECLARE_MSM_GPIO_PINS(pin) \ + static const unsigned int gpio##pin##_pins[] = { pin } +DECLARE_MSM_GPIO_PINS(0); +DECLARE_MSM_GPIO_PINS(1); +DECLARE_MSM_GPIO_PINS(2); +DECLARE_MSM_GPIO_PINS(3); +DECLARE_MSM_GPIO_PINS(4); +DECLARE_MSM_GPIO_PINS(5); +DECLARE_MSM_GPIO_PINS(6); +DECLARE_MSM_GPIO_PINS(7); +DECLARE_MSM_GPIO_PINS(8); +DECLARE_MSM_GPIO_PINS(9); +DECLARE_MSM_GPIO_PINS(10); +DECLARE_MSM_GPIO_PINS(11); +DECLARE_MSM_GPIO_PINS(12); +DECLARE_MSM_GPIO_PINS(13); +DECLARE_MSM_GPIO_PINS(14); +DECLARE_MSM_GPIO_PINS(15); +DECLARE_MSM_GPIO_PINS(16); +DECLARE_MSM_GPIO_PINS(17); +DECLARE_MSM_GPIO_PINS(18); +DECLARE_MSM_GPIO_PINS(19); +DECLARE_MSM_GPIO_PINS(20); +DECLARE_MSM_GPIO_PINS(21); +DECLARE_MSM_GPIO_PINS(22); +DECLARE_MSM_GPIO_PINS(23); +DECLARE_MSM_GPIO_PINS(24); +DECLARE_MSM_GPIO_PINS(25); +DECLARE_MSM_GPIO_PINS(26); +DECLARE_MSM_GPIO_PINS(27); +DECLARE_MSM_GPIO_PINS(28); +DECLARE_MSM_GPIO_PINS(29); +DECLARE_MSM_GPIO_PINS(30); +DECLARE_MSM_GPIO_PINS(31); +DECLARE_MSM_GPIO_PINS(32); +DECLARE_MSM_GPIO_PINS(33); +DECLARE_MSM_GPIO_PINS(34); +DECLARE_MSM_GPIO_PINS(35); +DECLARE_MSM_GPIO_PINS(36); +DECLARE_MSM_GPIO_PINS(37); +DECLARE_MSM_GPIO_PINS(38); +DECLARE_MSM_GPIO_PINS(39); +DECLARE_MSM_GPIO_PINS(40); +DECLARE_MSM_GPIO_PINS(41); +DECLARE_MSM_GPIO_PINS(42); +DECLARE_MSM_GPIO_PINS(43); +DECLARE_MSM_GPIO_PINS(44); +DECLARE_MSM_GPIO_PINS(45); +DECLARE_MSM_GPIO_PINS(46); +DECLARE_MSM_GPIO_PINS(47); +DECLARE_MSM_GPIO_PINS(48); +DECLARE_MSM_GPIO_PINS(49); +DECLARE_MSM_GPIO_PINS(50); +DECLARE_MSM_GPIO_PINS(51); +DECLARE_MSM_GPIO_PINS(52); +DECLARE_MSM_GPIO_PINS(53); +DECLARE_MSM_GPIO_PINS(54); +DECLARE_MSM_GPIO_PINS(55); +DECLARE_MSM_GPIO_PINS(56); +DECLARE_MSM_GPIO_PINS(57); +DECLARE_MSM_GPIO_PINS(58); +DECLARE_MSM_GPIO_PINS(59); +DECLARE_MSM_GPIO_PINS(60); +DECLARE_MSM_GPIO_PINS(61); +DECLARE_MSM_GPIO_PINS(62); +DECLARE_MSM_GPIO_PINS(63); +DECLARE_MSM_GPIO_PINS(64); +DECLARE_MSM_GPIO_PINS(65); +DECLARE_MSM_GPIO_PINS(66); +DECLARE_MSM_GPIO_PINS(67); +DECLARE_MSM_GPIO_PINS(68); +DECLARE_MSM_GPIO_PINS(69); +DECLARE_MSM_GPIO_PINS(70); +DECLARE_MSM_GPIO_PINS(71); +DECLARE_MSM_GPIO_PINS(72); +DECLARE_MSM_GPIO_PINS(73); +DECLARE_MSM_GPIO_PINS(74); +DECLARE_MSM_GPIO_PINS(75); +DECLARE_MSM_GPIO_PINS(76); +DECLARE_MSM_GPIO_PINS(77); +DECLARE_MSM_GPIO_PINS(78); +DECLARE_MSM_GPIO_PINS(79); +DECLARE_MSM_GPIO_PINS(80); +DECLARE_MSM_GPIO_PINS(81); +DECLARE_MSM_GPIO_PINS(82); +DECLARE_MSM_GPIO_PINS(83); +DECLARE_MSM_GPIO_PINS(84); +DECLARE_MSM_GPIO_PINS(85); +DECLARE_MSM_GPIO_PINS(86); +DECLARE_MSM_GPIO_PINS(87); +DECLARE_MSM_GPIO_PINS(88); +DECLARE_MSM_GPIO_PINS(89); +DECLARE_MSM_GPIO_PINS(90); +DECLARE_MSM_GPIO_PINS(91); +DECLARE_MSM_GPIO_PINS(92); +DECLARE_MSM_GPIO_PINS(93); +DECLARE_MSM_GPIO_PINS(94); +DECLARE_MSM_GPIO_PINS(95); +DECLARE_MSM_GPIO_PINS(96); +DECLARE_MSM_GPIO_PINS(97); +DECLARE_MSM_GPIO_PINS(98); +DECLARE_MSM_GPIO_PINS(99); +DECLARE_MSM_GPIO_PINS(100); +DECLARE_MSM_GPIO_PINS(101); +DECLARE_MSM_GPIO_PINS(102); +DECLARE_MSM_GPIO_PINS(103); +DECLARE_MSM_GPIO_PINS(104); +DECLARE_MSM_GPIO_PINS(105); +DECLARE_MSM_GPIO_PINS(106); +DECLARE_MSM_GPIO_PINS(107); +DECLARE_MSM_GPIO_PINS(108); +DECLARE_MSM_GPIO_PINS(109); +DECLARE_MSM_GPIO_PINS(110); +DECLARE_MSM_GPIO_PINS(111); +DECLARE_MSM_GPIO_PINS(112); +DECLARE_MSM_GPIO_PINS(113); +DECLARE_MSM_GPIO_PINS(114); +DECLARE_MSM_GPIO_PINS(115); +DECLARE_MSM_GPIO_PINS(116); +DECLARE_MSM_GPIO_PINS(117); +DECLARE_MSM_GPIO_PINS(118); +DECLARE_MSM_GPIO_PINS(119); +DECLARE_MSM_GPIO_PINS(120); +DECLARE_MSM_GPIO_PINS(121); +DECLARE_MSM_GPIO_PINS(122); +DECLARE_MSM_GPIO_PINS(123); +DECLARE_MSM_GPIO_PINS(124); +DECLARE_MSM_GPIO_PINS(125); +DECLARE_MSM_GPIO_PINS(126); +DECLARE_MSM_GPIO_PINS(127); +DECLARE_MSM_GPIO_PINS(128); +DECLARE_MSM_GPIO_PINS(129); +DECLARE_MSM_GPIO_PINS(130); +DECLARE_MSM_GPIO_PINS(131); +DECLARE_MSM_GPIO_PINS(132); +DECLARE_MSM_GPIO_PINS(133); +DECLARE_MSM_GPIO_PINS(134); +DECLARE_MSM_GPIO_PINS(135); +DECLARE_MSM_GPIO_PINS(136); +DECLARE_MSM_GPIO_PINS(137); +DECLARE_MSM_GPIO_PINS(138); +DECLARE_MSM_GPIO_PINS(139); +DECLARE_MSM_GPIO_PINS(140); +DECLARE_MSM_GPIO_PINS(141); +DECLARE_MSM_GPIO_PINS(142); +DECLARE_MSM_GPIO_PINS(143); +DECLARE_MSM_GPIO_PINS(144); +DECLARE_MSM_GPIO_PINS(145); + +static const unsigned int sdc1_rclk_pins[] = { 146 }; +static const unsigned int sdc1_clk_pins[] = { 147 }; +static const unsigned int sdc1_cmd_pins[] = { 148 }; +static const unsigned int sdc1_data_pins[] = { 149 }; +static const unsigned int sdc2_clk_pins[] = { 150 }; +static const unsigned int sdc2_cmd_pins[] = { 151 }; +static const unsigned int sdc2_data_pins[] = { 152 }; +static const unsigned int sdc3_clk_pins[] = { 153 }; +static const unsigned int sdc3_cmd_pins[] = { 154 }; +static const unsigned int sdc3_data_pins[] = { 155 }; + +enum msm8994_functions { + MSM_MUX_audio_ref_clk, + MSM_MUX_blsp_i2c1, + MSM_MUX_blsp_i2c2, + MSM_MUX_blsp_i2c3, + MSM_MUX_blsp_i2c4, + MSM_MUX_blsp_i2c5, + MSM_MUX_blsp_i2c6, + MSM_MUX_blsp_i2c7, + MSM_MUX_blsp_i2c8, + MSM_MUX_blsp_i2c9, + MSM_MUX_blsp_i2c10, + MSM_MUX_blsp_i2c11, + MSM_MUX_blsp_i2c12, + MSM_MUX_blsp_spi1, + MSM_MUX_blsp_spi1_cs1, + MSM_MUX_blsp_spi1_cs2, + MSM_MUX_blsp_spi1_cs3, + MSM_MUX_blsp_spi2, + MSM_MUX_blsp_spi2_cs1, + MSM_MUX_blsp_spi2_cs2, + MSM_MUX_blsp_spi2_cs3, + MSM_MUX_blsp_spi3, + MSM_MUX_blsp_spi4, + MSM_MUX_blsp_spi5, + MSM_MUX_blsp_spi6, + MSM_MUX_blsp_spi7, + MSM_MUX_blsp_spi8, + MSM_MUX_blsp_spi9, + MSM_MUX_blsp_spi10, + MSM_MUX_blsp_spi10_cs1, + MSM_MUX_blsp_spi10_cs2, + MSM_MUX_blsp_spi10_cs3, + MSM_MUX_blsp_spi11, + MSM_MUX_blsp_spi12, + MSM_MUX_blsp_uart1, + MSM_MUX_blsp_uart2, + MSM_MUX_blsp_uart3, + MSM_MUX_blsp_uart4, + MSM_MUX_blsp_uart5, + MSM_MUX_blsp_uart6, + MSM_MUX_blsp_uart7, + MSM_MUX_blsp_uart8, + MSM_MUX_blsp_uart9, + MSM_MUX_blsp_uart10, + MSM_MUX_blsp_uart11, + MSM_MUX_blsp_uart12, + MSM_MUX_blsp_uim1, + MSM_MUX_blsp_uim2, + MSM_MUX_blsp_uim3, + MSM_MUX_blsp_uim4, + MSM_MUX_blsp_uim5, + MSM_MUX_blsp_uim6, + MSM_MUX_blsp_uim7, + MSM_MUX_blsp_uim8, + MSM_MUX_blsp_uim9, + MSM_MUX_blsp_uim10, + MSM_MUX_blsp_uim11, + MSM_MUX_blsp_uim12, + MSM_MUX_blsp11_i2c_scl_b, + MSM_MUX_blsp11_i2c_sda_b, + MSM_MUX_blsp11_uart_rx_b, + MSM_MUX_blsp11_uart_tx_b, + MSM_MUX_cam_mclk0, + MSM_MUX_cam_mclk1, + MSM_MUX_cam_mclk2, + MSM_MUX_cam_mclk3, + MSM_MUX_cci_async_in0, + MSM_MUX_cci_async_in1, + MSM_MUX_cci_async_in2, + MSM_MUX_cci_i2c0, + MSM_MUX_cci_i2c1, + MSM_MUX_cci_timer0, + MSM_MUX_cci_timer1, + MSM_MUX_cci_timer2, + MSM_MUX_cci_timer3, + MSM_MUX_cci_timer4, + MSM_MUX_gcc_gp1_clk_a, + MSM_MUX_gcc_gp1_clk_b, + MSM_MUX_gcc_gp2_clk_a, + MSM_MUX_gcc_gp2_clk_b, + MSM_MUX_gcc_gp3_clk_a, + MSM_MUX_gcc_gp3_clk_b, + MSM_MUX_gp_mn, + MSM_MUX_gp_pdm0, + MSM_MUX_gp_pdm1, + MSM_MUX_gp_pdm2, + MSM_MUX_gp0_clk, + MSM_MUX_gp1_clk, + MSM_MUX_gps_tx, + MSM_MUX_gsm_tx, + MSM_MUX_hdmi_cec, + MSM_MUX_hdmi_ddc, + MSM_MUX_hdmi_hpd, + MSM_MUX_hdmi_rcv, + MSM_MUX_mdp_vsync, + MSM_MUX_mss_lte, + MSM_MUX_nav_pps, + MSM_MUX_nav_tsync, + MSM_MUX_qdss_cti_trig_in_a, + MSM_MUX_qdss_cti_trig_in_b, + MSM_MUX_qdss_cti_trig_in_c, + MSM_MUX_qdss_cti_trig_in_d, + MSM_MUX_qdss_cti_trig_out_a, + MSM_MUX_qdss_cti_trig_out_b, + MSM_MUX_qdss_cti_trig_out_c, + MSM_MUX_qdss_cti_trig_out_d, + MSM_MUX_qdss_traceclk_a, + MSM_MUX_qdss_traceclk_b, + MSM_MUX_qdss_tracectl_a, + MSM_MUX_qdss_tracectl_b, + MSM_MUX_qdss_tracedata_a, + MSM_MUX_qdss_tracedata_b, + MSM_MUX_qua_mi2s, + MSM_MUX_pci_e0, + MSM_MUX_pci_e1, + MSM_MUX_pri_mi2s, + MSM_MUX_sdc4, + MSM_MUX_sec_mi2s, + MSM_MUX_slimbus, + MSM_MUX_spkr_i2s, + MSM_MUX_ter_mi2s, + MSM_MUX_tsif1, + MSM_MUX_tsif2, + MSM_MUX_uim1, + MSM_MUX_uim2, + MSM_MUX_uim3, + MSM_MUX_uim4, + MSM_MUX_uim_batt_alarm, + MSM_MUX_gpio, + MSM_MUX_NA, +}; + +static const char * const gpio_groups[] = { + "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", + "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56", + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70", + "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77", + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84", + "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91", + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98", + "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104", + "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110", + "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116", + "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122", + "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128", + "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134", + "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140", + "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", +}; + +static const char * const blsp_spi1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_uart1_groups[] = { + "gpio0", "gpio1", "gpio2", "gpio3" +}; +static const char * const blsp_uim1_groups[] = { + "gpio0", "gpio1" +}; +static const char * const hdmi_rcv_groups[] = { + "gpio0" +}; +static const char * const blsp_i2c1_groups[] = { + "gpio2", "gpio3" +}; +static const char * const blsp_spi2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uart2_groups[] = { + "gpio4", "gpio5", "gpio6", "gpio7" +}; +static const char * const blsp_uim2_groups[] = { + "gpio4", "gpio5" +}; +static const char * const qdss_cti_trig_out_b_groups[] = { + "gpio4", +}; +static const char * const qdss_cti_trig_in_b_groups[] = { + "gpio5", +}; +static const char * const blsp_i2c2_groups[] = { + "gpio6", "gpio7" +}; +static const char * const blsp_spi3_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_uart3_groups[] = { + "gpio8", "gpio9", "gpio10", "gpio11" +}; +static const char * const blsp_uim3_groups[] = { + "gpio8", "gpio9" +}; +static const char * const blsp_spi1_cs1_groups[] = { + "gpio8" +}; +static const char * const blsp_spi1_cs2_groups[] = { + "gpio9", "gpio11" +}; +static const char * const mdp_vsync_groups[] = { + "gpio10", "gpio11", "gpio12" +}; +static const char * const blsp_i2c3_groups[] = { + "gpio10", "gpio11" +}; +static const char * const blsp_spi1_cs3_groups[] = { + "gpio10" +}; +static const char * const qdss_tracedata_b_groups[] = { + "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", + "gpio19", "gpio21", "gpio22", "gpio23", "gpio25", "gpio26", + "gpio57", "gpio58", "gpio92", "gpio93", +}; +static const char * const cam_mclk0_groups[] = { + "gpio13" +}; +static const char * const cam_mclk1_groups[] = { + "gpio14" +}; +static const char * const cam_mclk2_groups[] = { + "gpio15" +}; +static const char * const cam_mclk3_groups[] = { + "gpio16" +}; +static const char * const cci_i2c0_groups[] = { + "gpio17", "gpio18" +}; +static const char * const blsp_spi4_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20" +}; +static const char * const blsp_uart4_groups[] = { + "gpio17", "gpio18", "gpio19", "gpio20" +}; +static const char * const blsp_uim4_groups[] = { + "gpio17", "gpio18" +}; +static const char * const cci_i2c1_groups[] = { + "gpio19", "gpio20" +}; +static const char * const blsp_i2c4_groups[] = { + "gpio19", "gpio20" +}; +static const char * const cci_timer0_groups[] = { + "gpio21" +}; +static const char * const blsp_spi5_groups[] = { + "gpio21", "gpio22", "gpio23", "gpio24" +}; +static const char * const blsp_uart5_groups[] = { + "gpio21", "gpio22", "gpio23", "gpio24" +}; +static const char * const blsp_uim5_groups[] = { + "gpio21", "gpio22" +}; +static const char * const cci_timer1_groups[] = { + "gpio22" +}; +static const char * const cci_timer2_groups[] = { + "gpio23" +}; +static const char * const blsp_i2c5_groups[] = { + "gpio23", "gpio24" +}; +static const char * const cci_timer3_groups[] = { + "gpio24" +}; +static const char * const cci_async_in1_groups[] = { + "gpio24" +}; +static const char * const cci_timer4_groups[] = { + "gpio25" +}; +static const char * const cci_async_in2_groups[] = { + "gpio25" +}; +static const char * const blsp_spi6_groups[] = { + "gpio25", "gpio26", "gpio27", "gpio28" +}; +static const char * const blsp_uart6_groups[] = { + "gpio25", "gpio26", "gpio27", "gpio28" +}; +static const char * const blsp_uim6_groups[] = { + "gpio25", "gpio26" +}; +static const char * const cci_async_in0_groups[] = { + "gpio26" +}; +static const char * const gp0_clk_groups[] = { + "gpio26" +}; +static const char * const gp1_clk_groups[] = { + "gpio27", "gpio57", "gpio78" +}; +static const char * const blsp_i2c6_groups[] = { + "gpio27", "gpio28" +}; +static const char * const qdss_tracectl_a_groups[] = { + "gpio27", +}; +static const char * const qdss_traceclk_a_groups[] = { + "gpio28", +}; +static const char * const gp_mn_groups[] = { + "gpio29" +}; +static const char * const hdmi_cec_groups[] = { + "gpio31" +}; +static const char * const hdmi_ddc_groups[] = { + "gpio32", "gpio33" +}; +static const char * const hdmi_hpd_groups[] = { + "gpio34" +}; +static const char * const uim3_groups[] = { + "gpio35", "gpio36", "gpio37", "gpio38" +}; +static const char * const pci_e1_groups[] = { + "gpio35", "gpio36", +}; +static const char * const blsp_spi7_groups[] = { + "gpio41", "gpio42", "gpio43", "gpio44" +}; +static const char * const blsp_uart7_groups[] = { + "gpio41", "gpio42", "gpio43", "gpio44" +}; +static const char * const blsp_uim7_groups[] = { + "gpio41", "gpio42" +}; +static const char * const qdss_cti_trig_out_c_groups[] = { + "gpio41", +}; +static const char * const qdss_cti_trig_in_c_groups[] = { + "gpio42", +}; +static const char * const blsp_i2c7_groups[] = { + "gpio43", "gpio44" +}; +static const char * const blsp_spi8_groups[] = { + "gpio45", "gpio46", "gpio47", "gpio48" +}; +static const char * const blsp_uart8_groups[] = { + "gpio45", "gpio46", "gpio47", "gpio48" +}; +static const char * const blsp_uim8_groups[] = { + "gpio45", "gpio46" +}; +static const char * const blsp_i2c8_groups[] = { + "gpio47", "gpio48" +}; +static const char * const blsp_spi10_cs1_groups[] = { + "gpio47", "gpio67" +}; +static const char * const blsp_spi10_cs2_groups[] = { + "gpio48", "gpio68" +}; +static const char * const uim2_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_spi9_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_uart9_groups[] = { + "gpio49", "gpio50", "gpio51", "gpio52" +}; +static const char * const blsp_uim9_groups[] = { + "gpio49", "gpio50" +}; +static const char * const blsp_i2c9_groups[] = { + "gpio51", "gpio52" +}; +static const char * const pci_e0_groups[] = { + "gpio53", "gpio54", +}; +static const char * const uim4_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_spi10_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_uart10_groups[] = { + "gpio53", "gpio54", "gpio55", "gpio56" +}; +static const char * const blsp_uim10_groups[] = { + "gpio53", "gpio54" +}; +static const char * const qdss_tracedata_a_groups[] = { + "gpio53", "gpio54", "gpio63", "gpio64", "gpio65", + "gpio66", "gpio67", "gpio74", "gpio75", "gpio76", + "gpio77", "gpio85", "gpio86", "gpio87", "gpio89", + "gpio90" +}; +static const char * const gp_pdm0_groups[] = { + "gpio54", "gpio95" +}; +static const char * const blsp_i2c10_groups[] = { + "gpio55", "gpio56" +}; +static const char * const qdss_cti_trig_in_a_groups[] = { + "gpio55", +}; +static const char * const qdss_cti_trig_out_a_groups[] = { + "gpio56", +}; +static const char * const qua_mi2s_groups[] = { + "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63", +}; +static const char * const gcc_gp1_clk_a_groups[] = { + "gpio57" +}; +static const char * const gcc_gp2_clk_a_groups[] = { + "gpio58" +}; +static const char * const gcc_gp3_clk_a_groups[] = { + "gpio59" +}; +static const char * const blsp_spi2_cs1_groups[] = { + "gpio62" +}; +static const char * const blsp_spi2_cs2_groups[] = { + "gpio63" +}; +static const char * const gp_pdm2_groups[] = { + "gpio63", "gpio79" +}; +static const char * const pri_mi2s_groups[] = { + "gpio64", "gpio65", "gpio66", "gpio67", "gpio68" +}; +static const char * const blsp_spi2_cs3_groups[] = { + "gpio66" +}; +static const char * const spkr_i2s_groups[] = { + "gpio69", "gpio70", "gpio71", "gpio72" +}; +static const char * const audio_ref_clk_groups[] = { + "gpio69" +}; +static const char * const slimbus_groups[] = { + "gpio70", "gpio71" +}; +static const char * const ter_mi2s_groups[] = { + "gpio73", "gpio74", "gpio75", "gpio76", "gpio77" +}; +static const char * const gp_pdm1_groups[] = { + "gpio74", "gpio86" +}; +static const char * const sec_mi2s_groups[] = { + "gpio78", "gpio79", "gpio80", "gpio81", "gpio82" +}; +static const char * const gcc_gp1_clk_b_groups[] = { + "gpio78" +}; +static const char * const blsp_spi11_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84" +}; +static const char * const blsp_uart11_groups[] = { + "gpio81", "gpio82", "gpio83", "gpio84" +}; +static const char * const blsp_uim11_groups[] = { + "gpio81", "gpio82" +}; +static const char * const gcc_gp2_clk_b_groups[] = { + "gpio81" +}; +static const char * const gcc_gp3_clk_b_groups[] = { + "gpio82" +}; +static const char * const blsp_i2c11_groups[] = { + "gpio83", "gpio84" +}; +static const char * const blsp_uart12_groups[] = { + "gpio85", "gpio86", "gpio87", "gpio88" +}; +static const char * const blsp_uim12_groups[] = { + "gpio85", "gpio86" +}; +static const char * const blsp_i2c12_groups[] = { + "gpio87", "gpio88" +}; +static const char * const blsp_spi12_groups[] = { + "gpio85", "gpio86", "gpio87", "gpio88" +}; +static const char * const tsif1_groups[] = { + "gpio89", "gpio90", "gpio91", "gpio110", "gpio111" +}; +static const char * const blsp_spi10_cs3_groups[] = { + "gpio90" +}; +static const char * const sdc4_groups[] = { + "gpio91", "gpio92", "gpio93", "gpio94", "gpio95", "gpio96" +}; +static const char * const qdss_traceclk_b_groups[] = { + "gpio91", +}; +static const char * const tsif2_groups[] = { + "gpio92", "gpio93", "gpio94", "gpio95", "gpio96" +}; +static const char * const qdss_tracectl_b_groups[] = { + "gpio94", +}; +static const char * const qdss_cti_trig_out_d_groups[] = { + "gpio95", +}; +static const char * const qdss_cti_trig_in_d_groups[] = { + "gpio96", +}; +static const char * const uim1_groups[] = { + "gpio97", "gpio98", "gpio99", "gpio100" +}; +static const char * const uim_batt_alarm_groups[] = { + "gpio101" +}; +static const char * const blsp11_uart_tx_b_groups[] = { + "gpio111" +}; +static const char * const blsp11_uart_rx_b_groups[] = { + "gpio112" +}; +static const char * const blsp11_i2c_sda_b_groups[] = { + "gpio113" +}; +static const char * const blsp11_i2c_scl_b_groups[] = { + "gpio114" +}; +static const char * const gsm_tx_groups[] = { + "gpio126", "gpio131", "gpio132", "gpio133" +}; +static const char * const nav_tsync_groups[] = { + "gpio127" +}; +static const char * const nav_pps_groups[] = { + "gpio127" +}; +static const char * const gps_tx_groups[] = { + "gpio130" +}; +static const char * const mss_lte_groups[] = { + "gpio134", "gpio135" +}; + +static const struct msm_function msm8994_functions[] = { + FUNCTION(audio_ref_clk), + FUNCTION(blsp_i2c1), + FUNCTION(blsp_i2c2), + FUNCTION(blsp_i2c3), + FUNCTION(blsp_i2c4), + FUNCTION(blsp_i2c5), + FUNCTION(blsp_i2c6), + FUNCTION(blsp_i2c7), + FUNCTION(blsp_i2c8), + FUNCTION(blsp_i2c9), + FUNCTION(blsp_i2c10), + FUNCTION(blsp_i2c11), + FUNCTION(blsp_i2c12), + FUNCTION(blsp_spi1), + FUNCTION(blsp_spi1_cs1), + FUNCTION(blsp_spi1_cs2), + FUNCTION(blsp_spi1_cs3), + FUNCTION(blsp_spi2), + FUNCTION(blsp_spi2_cs1), + FUNCTION(blsp_spi2_cs2), + FUNCTION(blsp_spi2_cs3), + FUNCTION(blsp_spi3), + FUNCTION(blsp_spi4), + FUNCTION(blsp_spi5), + FUNCTION(blsp_spi6), + FUNCTION(blsp_spi7), + FUNCTION(blsp_spi8), + FUNCTION(blsp_spi9), + FUNCTION(blsp_spi10), + FUNCTION(blsp_spi10_cs1), + FUNCTION(blsp_spi10_cs2), + FUNCTION(blsp_spi10_cs3), + FUNCTION(blsp_spi11), + FUNCTION(blsp_spi12), + FUNCTION(blsp_uart1), + FUNCTION(blsp_uart2), + FUNCTION(blsp_uart3), + FUNCTION(blsp_uart4), + FUNCTION(blsp_uart5), + FUNCTION(blsp_uart6), + FUNCTION(blsp_uart7), + FUNCTION(blsp_uart8), + FUNCTION(blsp_uart9), + FUNCTION(blsp_uart10), + FUNCTION(blsp_uart11), + FUNCTION(blsp_uart12), + FUNCTION(blsp_uim1), + FUNCTION(blsp_uim2), + FUNCTION(blsp_uim3), + FUNCTION(blsp_uim4), + FUNCTION(blsp_uim5), + FUNCTION(blsp_uim6), + FUNCTION(blsp_uim7), + FUNCTION(blsp_uim8), + FUNCTION(blsp_uim9), + FUNCTION(blsp_uim10), + FUNCTION(blsp_uim11), + FUNCTION(blsp_uim12), + FUNCTION(blsp11_i2c_scl_b), + FUNCTION(blsp11_i2c_sda_b), + FUNCTION(blsp11_uart_rx_b), + FUNCTION(blsp11_uart_tx_b), + FUNCTION(cam_mclk0), + FUNCTION(cam_mclk1), + FUNCTION(cam_mclk2), + FUNCTION(cam_mclk3), + FUNCTION(cci_async_in0), + FUNCTION(cci_async_in1), + FUNCTION(cci_async_in2), + FUNCTION(cci_i2c0), + FUNCTION(cci_i2c1), + FUNCTION(cci_timer0), + FUNCTION(cci_timer1), + FUNCTION(cci_timer2), + FUNCTION(cci_timer3), + FUNCTION(cci_timer4), + FUNCTION(gcc_gp1_clk_a), + FUNCTION(gcc_gp1_clk_b), + FUNCTION(gcc_gp2_clk_a), + FUNCTION(gcc_gp2_clk_b), + FUNCTION(gcc_gp3_clk_a), + FUNCTION(gcc_gp3_clk_b), + FUNCTION(gp_mn), + FUNCTION(gp_pdm0), + FUNCTION(gp_pdm1), + FUNCTION(gp_pdm2), + FUNCTION(gp0_clk), + FUNCTION(gp1_clk), + FUNCTION(gps_tx), + FUNCTION(gsm_tx), + FUNCTION(hdmi_cec), + FUNCTION(hdmi_ddc), + FUNCTION(hdmi_hpd), + FUNCTION(hdmi_rcv), + FUNCTION(mdp_vsync), + FUNCTION(mss_lte), + FUNCTION(nav_pps), + FUNCTION(nav_tsync), + FUNCTION(qdss_cti_trig_in_a), + FUNCTION(qdss_cti_trig_in_b), + FUNCTION(qdss_cti_trig_in_c), + FUNCTION(qdss_cti_trig_in_d), + FUNCTION(qdss_cti_trig_out_a), + FUNCTION(qdss_cti_trig_out_b), + FUNCTION(qdss_cti_trig_out_c), + FUNCTION(qdss_cti_trig_out_d), + FUNCTION(qdss_traceclk_a), + FUNCTION(qdss_traceclk_b), + FUNCTION(qdss_tracectl_a), + FUNCTION(qdss_tracectl_b), + FUNCTION(qdss_tracedata_a), + FUNCTION(qdss_tracedata_b), + FUNCTION(qua_mi2s), + FUNCTION(pci_e0), + FUNCTION(pci_e1), + FUNCTION(pri_mi2s), + FUNCTION(sdc4), + FUNCTION(sec_mi2s), + FUNCTION(slimbus), + FUNCTION(spkr_i2s), + FUNCTION(ter_mi2s), + FUNCTION(tsif1), + FUNCTION(tsif2), + FUNCTION(uim_batt_alarm), + FUNCTION(uim1), + FUNCTION(uim2), + FUNCTION(uim3), + FUNCTION(uim4), + FUNCTION(gpio), +}; + +static const struct msm_pingroup msm8994_groups[] = { + PINGROUP(0, blsp_spi1, blsp_uart1, blsp_uim1, hdmi_rcv, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(1, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_out_b, + NA, NA, NA, NA, NA, NA), + PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti_trig_in_b, + NA, NA, NA, NA, NA, NA), + PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(8, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs1, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(9, blsp_spi3, blsp_uart3, blsp_uim3, blsp_spi1_cs2, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(10, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3, + blsp_spi1_cs3, NA, NA, NA, NA, NA, NA), + PINGROUP(11, mdp_vsync, blsp_spi3, blsp_uart3, blsp_i2c3, + blsp_spi1_cs2, NA, NA, NA, NA, NA, NA), + PINGROUP(12, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(13, cam_mclk0, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(14, cam_mclk1, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(15, cam_mclk2, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(16, cam_mclk3, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(17, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(18, cci_i2c0, blsp_spi4, blsp_uart4, blsp_uim4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(19, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(20, cci_i2c1, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(21, cci_timer0, blsp_spi5, blsp_uart5, blsp_uim5, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(22, cci_timer1, blsp_spi5, blsp_uart5, blsp_uim5, NA, + qdss_tracedata_b, NA, NA, NA, NA, NA), + PINGROUP(23, cci_timer2, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, + qdss_tracedata_b, NA, NA, NA, NA), + PINGROUP(24, cci_timer3, cci_async_in1, blsp_spi5, blsp_uart5, + blsp_i2c5, NA, NA, NA, NA, NA, NA), + PINGROUP(25, cci_timer4, cci_async_in2, blsp_spi6, blsp_uart6, + blsp_uim6, NA, NA, qdss_tracedata_b, NA, NA, NA), + PINGROUP(26, cci_async_in0, blsp_spi6, blsp_uart6, blsp_uim6, gp0_clk, + NA, qdss_tracedata_b, NA, NA, NA, NA), + PINGROUP(27, blsp_spi6, blsp_uart6, blsp_i2c6, gp1_clk, + qdss_tracectl_a, NA, NA, NA, NA, NA, NA), + PINGROUP(28, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_a, NA, + NA, NA, NA, NA, NA, NA), + PINGROUP(29, gp_mn, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(30, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(31, hdmi_cec, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(32, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(33, hdmi_ddc, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(34, hdmi_hpd, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(35, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(36, uim3, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(37, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(38, uim3, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(39, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(40, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(41, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_out_c, + NA, NA, NA, NA, NA, NA, NA), + PINGROUP(42, blsp_spi7, blsp_uart7, blsp_uim7, qdss_cti_trig_in_c, NA, + NA, NA, NA, NA, NA, NA), + PINGROUP(43, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(44, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(45, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(46, blsp_spi8, blsp_uart8, blsp_uim8, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(47, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs1, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(48, blsp_spi8, blsp_uart8, blsp_i2c8, blsp_spi10_cs2, NA, NA, + NA, NA, NA, NA, NA), + PINGROUP(49, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(50, uim2, blsp_spi9, blsp_uart9, blsp_uim9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(51, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(52, uim2, blsp_spi9, blsp_uart9, blsp_i2c9, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(53, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, NA, + NA, qdss_tracedata_a, NA, NA, NA), + PINGROUP(54, uim4, pci_e0, blsp_spi10, blsp_uart10, blsp_uim10, + gp_pdm0, NA, NA, qdss_tracedata_a, NA, NA), + PINGROUP(55, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, NA, + qdss_cti_trig_in_a, NA, NA, NA), + PINGROUP(56, uim4, blsp_spi10, blsp_uart10, blsp_i2c10, NA, NA, + qdss_cti_trig_out_a, NA, NA, NA, NA), + PINGROUP(57, qua_mi2s, gcc_gp1_clk_a, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA, NA, NA), + PINGROUP(58, qua_mi2s, gcc_gp2_clk_a, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA, NA, NA), + PINGROUP(59, qua_mi2s, gcc_gp3_clk_a, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(60, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(61, qua_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(62, qua_mi2s, blsp_spi2_cs1, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(63, qua_mi2s, blsp_spi2_cs2, gp_pdm2, NA, NA, NA, NA, NA, + qdss_tracedata_a, NA, NA), + PINGROUP(64, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA), + PINGROUP(65, pri_mi2s, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA), + PINGROUP(66, pri_mi2s, blsp_spi2_cs3, NA, NA, NA, qdss_tracedata_a, + NA, NA, NA, NA, NA), + PINGROUP(67, pri_mi2s, blsp_spi10_cs1, NA, NA, NA, qdss_tracedata_a, + NA, NA, NA, NA, NA), + PINGROUP(68, pri_mi2s, blsp_spi10_cs2, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(69, spkr_i2s, audio_ref_clk, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(70, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(71, slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(72, spkr_i2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(73, ter_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(74, ter_mi2s, gp_pdm1, NA, NA, NA, qdss_tracedata_a, NA, NA, + NA, NA, NA), + PINGROUP(75, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(76, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(77, ter_mi2s, NA, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(78, sec_mi2s, gcc_gp1_clk_b, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(79, sec_mi2s, gp_pdm2, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(80, sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(81, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, + gcc_gp2_clk_b, NA, NA, NA, NA, NA, NA), + PINGROUP(82, sec_mi2s, blsp_spi11, blsp_uart11, blsp_uim11, + gcc_gp3_clk_b, NA, NA, NA, NA, NA, NA), + PINGROUP(83, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(84, blsp_spi11, blsp_uart11, blsp_i2c11, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(85, blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA), + PINGROUP(86, blsp_spi12, blsp_uart12, blsp_uim12, gp_pdm1, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA), + PINGROUP(87, blsp_spi12, blsp_uart12, blsp_i2c12, NA, + qdss_tracedata_a, NA, NA, NA, NA, NA, NA), + PINGROUP(88, blsp_spi12, blsp_uart12, blsp_i2c12, NA, NA, NA, NA, NA, + NA, NA, NA), + PINGROUP(89, tsif1, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(90, tsif1, blsp_spi10_cs3, qdss_tracedata_a, NA, NA, NA, NA, + NA, NA, NA, NA), + PINGROUP(91, tsif1, sdc4, NA, NA, NA, NA, qdss_traceclk_b, NA, NA, NA, + NA), + PINGROUP(92, tsif2, sdc4, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, + NA, NA), + PINGROUP(93, tsif2, sdc4, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, + NA, NA), + PINGROUP(94, tsif2, sdc4, NA, NA, NA, NA, qdss_tracectl_b, NA, NA, NA, + NA), + PINGROUP(95, tsif2, sdc4, gp_pdm0, NA, NA, NA, qdss_cti_trig_out_d, + NA, NA, NA, NA), + PINGROUP(96, tsif2, sdc4, qdss_cti_trig_in_d, NA, NA, NA, NA, NA, NA, + NA, NA), + PINGROUP(97, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(98, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(99, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(100, uim1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(101, uim_batt_alarm, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(110, tsif1, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(111, tsif1, blsp11_uart_tx_b, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(112, blsp11_uart_rx_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(113, blsp11_i2c_sda_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(114, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(115, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(118, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(121, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(122, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(123, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(126, NA, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(127, NA, nav_tsync, nav_pps, NA, NA, NA, NA, NA, NA, NA, + NA), + PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(130, gps_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(131, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(132, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(133, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(134, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(135, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(137, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(138, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(139, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(140, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(141, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(142, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(143, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(144, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + PINGROUP(145, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), + SDC_PINGROUP(sdc1_rclk, 0x2044, 15, 0), + SDC_PINGROUP(sdc1_clk, 0x2044, 13, 6), + SDC_PINGROUP(sdc1_cmd, 0x2044, 11, 3), + SDC_PINGROUP(sdc1_data, 0x2044, 9, 0), + SDC_PINGROUP(sdc2_clk, 0x2048, 14, 6), + SDC_PINGROUP(sdc2_cmd, 0x2048, 11, 3), + SDC_PINGROUP(sdc2_data, 0x2048, 9, 0), + SDC_PINGROUP(sdc3_clk, 0x206c, 14, 6), + SDC_PINGROUP(sdc3_cmd, 0x206c, 11, 3), + SDC_PINGROUP(sdc3_data, 0x206c, 9, 0), +}; + +#define NUM_GPIO_PINGROUPS 146 + +static const struct msm_pinctrl_soc_data msm8994_pinctrl = { + .pins = msm8994_pins, + .npins = ARRAY_SIZE(msm8994_pins), + .functions = msm8994_functions, + .nfunctions = ARRAY_SIZE(msm8994_functions), + .groups = msm8994_groups, + .ngroups = ARRAY_SIZE(msm8994_groups), + .ngpios = NUM_GPIO_PINGROUPS, +}; + +static int msm8994_pinctrl_probe(struct platform_device *pdev) +{ + return msm_pinctrl_probe(pdev, &msm8994_pinctrl); +} + +static const struct of_device_id msm8994_pinctrl_of_match[] = { + { .compatible = "qcom,msm8992-pinctrl", }, + { .compatible = "qcom,msm8994-pinctrl", }, + { } +}; + +static struct platform_driver msm8994_pinctrl_driver = { + .driver = { + .name = "msm8994-pinctrl", + .of_match_table = msm8994_pinctrl_of_match, + }, + .probe = msm8994_pinctrl_probe, + .remove = msm_pinctrl_remove, +}; + +static int __init msm8994_pinctrl_init(void) +{ + return platform_driver_register(&msm8994_pinctrl_driver); +} +arch_initcall(msm8994_pinctrl_init); + +static void __exit msm8994_pinctrl_exit(void) +{ + platform_driver_unregister(&msm8994_pinctrl_driver); +} +module_exit(msm8994_pinctrl_exit); + +MODULE_DESCRIPTION("Qualcomm MSM8994 pinctrl driver"); +MODULE_LICENSE("GPL v2"); +MODULE_DEVICE_TABLE(of, msm8994_pinctrl_of_match); -- cgit 1.4.1 From 0f866a9679215838328e1c0ed1892224672bb396 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 21 Oct 2016 17:30:59 +0200 Subject: pinctrl: sh-pfc: r8a7796: Fix GPSR definitions for SDHI2/3 Fix off-by-one (row and/or register) errors in links to Peripheral Function Select Register bitfields from GPIO/Peripheral Function Select Register 4 macros for SDHI2 and SDHI3 pins. Based on rev. 0.52E of the R-Car Gen3 User's Manual. Signed-off-by: Geert Uytterhoeven Tested-by: Simon Horman --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index dd23198492b5..57ddd394f8c5 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -122,22 +122,22 @@ #define GPSR3_0 F_(SD0_CLK, IP7_19_16) /* GPSR4 */ -#define GPSR4_17 F_(SD3_DS, IP11_11_8) -#define GPSR4_16 F_(SD3_DAT7, IP10_7_4) -#define GPSR4_15 F_(SD3_DAT6, IP10_3_0) -#define GPSR4_14 F_(SD3_DAT5, IP9_31_28) -#define GPSR4_13 F_(SD3_DAT4, IP9_27_24) +#define GPSR4_17 F_(SD3_DS, IP11_7_4) +#define GPSR4_16 F_(SD3_DAT7, IP11_3_0) +#define GPSR4_15 F_(SD3_DAT6, IP10_31_28) +#define GPSR4_14 F_(SD3_DAT5, IP10_27_24) +#define GPSR4_13 F_(SD3_DAT4, IP10_23_20) #define GPSR4_12 F_(SD3_DAT3, IP10_19_16) #define GPSR4_11 F_(SD3_DAT2, IP10_15_12) #define GPSR4_10 F_(SD3_DAT1, IP10_11_8) #define GPSR4_9 F_(SD3_DAT0, IP10_7_4) #define GPSR4_8 F_(SD3_CMD, IP10_3_0) #define GPSR4_7 F_(SD3_CLK, IP9_31_28) -#define GPSR4_6 F_(SD2_DS, IP9_23_20) -#define GPSR4_5 F_(SD2_DAT3, IP9_19_16) -#define GPSR4_4 F_(SD2_DAT2, IP9_15_12) -#define GPSR4_3 F_(SD2_DAT1, IP9_11_8) -#define GPSR4_2 F_(SD2_DAT0, IP9_7_4) +#define GPSR4_6 F_(SD2_DS, IP9_27_24) +#define GPSR4_5 F_(SD2_DAT3, IP9_23_20) +#define GPSR4_4 F_(SD2_DAT2, IP9_19_16) +#define GPSR4_3 F_(SD2_DAT1, IP9_15_12) +#define GPSR4_2 F_(SD2_DAT0, IP9_11_8) #define GPSR4_1 F_(SD2_CMD, IP9_7_4) #define GPSR4_0 F_(SD2_CLK, IP9_3_0) -- cgit 1.4.1 From e3ba812068117180f4dde11cc30f8bc5f83250ae Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:09 -0800 Subject: pinctrl-sx150x: Improve OF device matching code Add proper device specific information to of_device_id table of the driver and add code to match against and fetch said data from it. Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index d2d4211e615e..0523f5a1c6a4 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -862,10 +863,10 @@ static const struct i2c_device_id sx150x_id[] = { }; static const struct of_device_id sx150x_of_match[] = { - { .compatible = "semtech,sx1508q" }, - { .compatible = "semtech,sx1509q" }, - { .compatible = "semtech,sx1506q" }, - { .compatible = "semtech,sx1502q" }, + { .compatible = "semtech,sx1508q", .data = &sx1508q_device_data }, + { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data }, + { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data }, + { .compatible = "semtech,sx1502q", .data = &sx1502q_device_data }, {}, }; @@ -956,9 +957,6 @@ static int sx150x_probe(struct i2c_client *client, struct sx150x_pinctrl *pctl; int ret; - if (!id->driver_data) - return -EINVAL; - if (!i2c_check_functionality(client->adapter, i2c_funcs)) return -ENOSYS; @@ -968,7 +966,14 @@ static int sx150x_probe(struct i2c_client *client, pctl->dev = dev; pctl->client = client; - pctl->data = (void *)id->driver_data; + + if (dev->of_node) + pctl->data = of_device_get_match_data(dev); + else + pctl->data = (struct sx150x_device_data *)id->driver_data; + + if (!pctl->data) + return -EINVAL; mutex_init(&pctl->lock); -- cgit 1.4.1 From 6697546d650dac14db48a7d191f644f5c4fd555a Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:10 -0800 Subject: pinctrl-sx150x: Add SX1503 specific data Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 0523f5a1c6a4..94667770051e 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -230,6 +230,29 @@ static const struct sx150x_device_data sx1502q_device_data = { .npins = 8, /* oscio not available */ }; +static const struct sx150x_device_data sx1503q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x05, + .reg_pulldn = 0x07, + .reg_dir = 0x03, + .reg_data = 0x01, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0f, + .reg_sense = 0x07, + .pri.x123 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table1 = 0x12, + .reg_pld_table2 = 0x13, + .reg_pld_table3 = 0x14, + .reg_pld_table4 = 0x15, + .reg_advance = 0xad, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = 16, /* oscio not available */ +}; + static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) { s32 err = i2c_smbus_write_byte_data(client, reg, val); @@ -859,6 +882,7 @@ static const struct i2c_device_id sx150x_id[] = { {"sx1509q", (kernel_ulong_t) &sx1509q_device_data }, {"sx1506q", (kernel_ulong_t) &sx1506q_device_data }, {"sx1502q", (kernel_ulong_t) &sx1502q_device_data }, + {"sx1503q", (kernel_ulong_t) &sx1503q_device_data }, {} }; @@ -867,6 +891,7 @@ static const struct of_device_id sx150x_of_match[] = { { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data }, { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data }, { .compatible = "semtech,sx1502q", .data = &sx1502q_device_data }, + { .compatible = "semtech,sx1503q", .data = &sx1503q_device_data }, {}, }; -- cgit 1.4.1 From 7d68a79acfd56eea1351fc56d9e454e07912a8ec Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:12 -0800 Subject: pinctrl-sx150x: Replace magic number in sx150x_init_hw Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 94667770051e..3ccd04840ab7 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -43,6 +43,9 @@ enum { SX150X_456, SX150X_789, }; +enum { + SX150X_789_REG_MISC_AUTOCLEAR_OFF = 1 << 0, +}; struct sx150x_123_pri { u8 reg_pld_mode; @@ -935,7 +938,7 @@ static int sx150x_init_hw(struct sx150x_pinctrl *pctl) if (pctl->data->model == SX150X_789) err = sx150x_i2c_write(pctl->client, pctl->data->pri.x789.reg_misc, - 0x01); + SX150X_789_REG_MISC_AUTOCLEAR_OFF); else if (pctl->data->model == SX150X_456) err = sx150x_i2c_write(pctl->client, pctl->data->pri.x456.reg_advance, -- cgit 1.4.1 From 9af2ca82b33f82dfb015706696a9cdf55b8feaa0 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:13 -0800 Subject: pinctrl-sx150x: Fix incorrect constant in sx150x_init_hw According to the datasheet for SX1504/5/6, RegAdvanced's "Autoclear NINT" bit that turns the feature when set and disables it when cleared, so writing 0x04 to the register will have the opposite from desirable effect. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 3ccd04840ab7..0e3e1daeeb72 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -942,7 +942,7 @@ static int sx150x_init_hw(struct sx150x_pinctrl *pctl) else if (pctl->data->model == SX150X_456) err = sx150x_i2c_write(pctl->client, pctl->data->pri.x456.reg_advance, - 0x04); + 0x00); else err = sx150x_i2c_write(pctl->client, pctl->data->pri.x123.reg_advance, -- cgit 1.4.1 From 310cdfa0097a94d8cc3c0c314d64d6eb1cc69bf8 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:14 -0800 Subject: pinctrl-sx150x: Move some code out of sx150x_init_hw Move the code configuring explicit IRQ acking into a standalone function to declutter sx150x_init_hw a bit and make that code somewhat less repetitious. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 0e3e1daeeb72..27194e700d2f 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -924,6 +924,31 @@ static int sx150x_reset(struct sx150x_pinctrl *pctl) return err; } +static int sx150x_init_misc(struct sx150x_pinctrl *pctl) +{ + u8 reg, value; + + switch (pctl->data->model) { + case SX150X_789: + reg = pctl->data->pri.x789.reg_misc; + value = SX150X_789_REG_MISC_AUTOCLEAR_OFF; + break; + case SX150X_456: + reg = pctl->data->pri.x456.reg_advance; + value = 0x00; + break; + case SX150X_123: + reg = pctl->data->pri.x123.reg_advance; + value = 0x00; + break; + default: + WARN(1, "Unknown chip model %d\n", pctl->data->model); + return -EINVAL; + } + + return sx150x_i2c_write(pctl->client, reg, value); +} + static int sx150x_init_hw(struct sx150x_pinctrl *pctl) { int err; @@ -935,18 +960,7 @@ static int sx150x_init_hw(struct sx150x_pinctrl *pctl) return err; } - if (pctl->data->model == SX150X_789) - err = sx150x_i2c_write(pctl->client, - pctl->data->pri.x789.reg_misc, - SX150X_789_REG_MISC_AUTOCLEAR_OFF); - else if (pctl->data->model == SX150X_456) - err = sx150x_i2c_write(pctl->client, - pctl->data->pri.x456.reg_advance, - 0x00); - else - err = sx150x_i2c_write(pctl->client, - pctl->data->pri.x123.reg_advance, - 0x00); + err = sx150x_init_misc(pctl); if (err < 0) return err; -- cgit 1.4.1 From b30d31e40e2d650c0183d1b46f70cb41618d3592 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:15 -0800 Subject: pinctrl-sx150x: Improve sx150x_init_misc for SX1504/5/6 For Sx1504/5/6 only SX1506 has RegAdvanced, so put some code in place to account for that. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 27194e700d2f..d51ec73092c2 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -936,6 +936,13 @@ static int sx150x_init_misc(struct sx150x_pinctrl *pctl) case SX150X_456: reg = pctl->data->pri.x456.reg_advance; value = 0x00; + + /* + * Only SX1506 has RegAdvanced, SX1504/5 are expected + * to initialize this offset to zero + */ + if (!reg) + return 0; break; case SX150X_123: reg = pctl->data->pri.x123.reg_advance; -- cgit 1.4.1 From 0db0f26c2c5d439e07883cd8e7f22fe24e6a0101 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:16 -0800 Subject: pinctrl-sx150x: Convert driver to use regmap API To allow for future code simplification Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/pinctrl-sx150x.c | 102 +++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 3eea73937ce8..5f40ad64e8f5 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -171,6 +171,7 @@ config PINCTRL_SX150X select PINCONF select GENERIC_PINCONF select GPIOLIB_IRQCHIP + select REGMAP help Say yes here to provide support for Semtech SX150x-series I2C GPIO expanders as pinctrl module. diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index d51ec73092c2..2eb233fe218b 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -18,6 +18,7 @@ * GNU General Public License for more details. */ +#include #include #include #include @@ -45,6 +46,7 @@ enum { }; enum { SX150X_789_REG_MISC_AUTOCLEAR_OFF = 1 << 0, + SX150X_MAX_REGISTER = 0xad, }; struct sx150x_123_pri { @@ -102,6 +104,7 @@ struct sx150x_pinctrl { struct pinctrl_desc pinctrl_desc; struct gpio_chip gpio; struct irq_chip irq_chip; + struct regmap *regmap; struct { int update; u32 sense; @@ -256,30 +259,6 @@ static const struct sx150x_device_data sx1503q_device_data = { .npins = 16, /* oscio not available */ }; -static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) -{ - s32 err = i2c_smbus_write_byte_data(client, reg, val); - - if (err < 0) - dev_warn(&client->dev, - "i2c write fail: can't write %02x to %02x: %d\n", - val, reg, err); - return err; -} - -static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) -{ - s32 err = i2c_smbus_read_byte_data(client, reg); - - if (err >= 0) - *val = err; - else - dev_warn(&client->dev, - "i2c read fail: can't read from %02x: %d\n", - reg, err); - return err; -} - /* * These utility functions solve the common problem of locating and setting * configuration bits. Configuration bits are grouped into registers @@ -312,30 +291,32 @@ static int sx150x_write_cfg(struct i2c_client *client, u8 offset, u8 width, u8 reg, u8 val) { u8 mask; - u8 data; + unsigned int data; u8 shift; int err; + struct sx150x_pinctrl *pctl = i2c_get_clientdata(client); sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = sx150x_i2c_read(client, reg, &data); + err = regmap_read(pctl->regmap, reg, &data); if (err < 0) return err; data &= ~mask; data |= (val << shift) & mask; - return sx150x_i2c_write(client, reg, data); + return regmap_write(pctl->regmap, reg, data); } static int sx150x_read_cfg(struct i2c_client *client, u8 offset, u8 width, u8 reg) { u8 mask; - u8 data; + unsigned int data; u8 shift; int err; + struct sx150x_pinctrl *pctl = i2c_get_clientdata(client); sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = sx150x_i2c_read(client, reg, &data); + err = regmap_read(pctl->regmap, reg, &data); if (err < 0) return err; @@ -463,11 +444,10 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); if (sx150x_pin_is_oscio(pctl, offset)) { - mutex_lock(&pctl->lock); - sx150x_i2c_write(pctl->client, - pctl->data->pri.x789.reg_clock, - (value ? 0x1f : 0x10)); + regmap_write(pctl->regmap, + pctl->data->pri.x789.reg_clock, + (value ? 0x1f : 0x10)); mutex_unlock(&pctl->lock); } else { mutex_lock(&pctl->lock); @@ -567,19 +547,19 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) unsigned int sub_irq; unsigned int n; s32 err; - u8 val; + unsigned int val; int i; for (i = (pctl->data->ngpios / 8) - 1; i >= 0; --i) { - err = sx150x_i2c_read(pctl->client, - pctl->data->reg_irq_src - i, - &val); + err = regmap_read(pctl->regmap, + pctl->data->reg_irq_src - i, + &val); if (err < 0) continue; - err = sx150x_i2c_write(pctl->client, - pctl->data->reg_irq_src - i, - val); + err = regmap_write(pctl->regmap, + pctl->data->reg_irq_src - i, + val); if (err < 0) continue; @@ -650,15 +630,15 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, u32 arg; if (sx150x_pin_is_oscio(pctl, pin)) { - u8 data; + unsigned int data; switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_OUTPUT: mutex_lock(&pctl->lock); - ret = sx150x_i2c_read(pctl->client, - pctl->data->pri.x789.reg_clock, - &data); + ret = regmap_read(pctl->regmap, + pctl->data->pri.x789.reg_clock, + &data); mutex_unlock(&pctl->lock); if (ret < 0) @@ -904,7 +884,7 @@ static int sx150x_init_io(struct sx150x_pinctrl *pctl, u8 base, u16 cfg) unsigned int n; for (n = 0; err >= 0 && n < (pctl->data->ngpios / 8); ++n) - err = sx150x_i2c_write(pctl->client, base - n, cfg >> (n * 8)); + err = regmap_write(pctl->regmap, base - n, cfg >> (n * 8)); return err; } @@ -953,7 +933,7 @@ static int sx150x_init_misc(struct sx150x_pinctrl *pctl) return -EINVAL; } - return sx150x_i2c_write(pctl->client, reg, value); + return i2c_smbus_write_byte_data(pctl->client, reg, value); } static int sx150x_init_hw(struct sx150x_pinctrl *pctl) @@ -997,6 +977,26 @@ static int sx150x_init_hw(struct sx150x_pinctrl *pctl) return 0; } +static bool sx150x_reg_volatile(struct device *dev, unsigned int reg) +{ + struct sx150x_pinctrl *pctl = i2c_get_clientdata(to_i2c_client(dev)); + + return reg == pctl->data->reg_irq_src || + reg == pctl->data->reg_irq_src - 1 || + reg == pctl->data->reg_data || + reg == pctl->data->reg_data - 1; +} + +const struct regmap_config sx150x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + + .cache_type = REGCACHE_RBTREE, + + .max_register = SX150X_MAX_REGISTER, + .volatile_reg = sx150x_reg_volatile, +}; + static int sx150x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -1013,6 +1013,8 @@ static int sx150x_probe(struct i2c_client *client, if (!pctl) return -ENOMEM; + i2c_set_clientdata(client, pctl); + pctl->dev = dev; pctl->client = client; @@ -1024,6 +1026,14 @@ static int sx150x_probe(struct i2c_client *client, if (!pctl->data) return -EINVAL; + pctl->regmap = devm_regmap_init_i2c(client, &sx150x_regmap_config); + if (IS_ERR(pctl->regmap)) { + ret = PTR_ERR(pctl->regmap); + dev_err(dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + mutex_init(&pctl->lock); ret = sx150x_init_hw(pctl); -- cgit 1.4.1 From 6489677f86c330404ae47703bf59d30ec4c46de9 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:17 -0800 Subject: pinctrl-sx150x: Replace sx150x_*_cfg by means of regmap API The difference between 8 and 16 pin GPIO expanders can be accomodated by the means of regmap API without resorting to using driver-specific read/write accessors. This change, IMHO, brings the following benefits: - Replaces driver's idiosyncratic way of dealing with mult-register fields with regmap API, which, hopefuly, makes the code a bit easier for a new reader to understand - Removes various multi-read for-loop register read logic from various places in the code and puts it in a signle place - Removes ad-hoc IRQ register caching code in sx150x_irq_bus_sync_unlock, since that functionality is provided by regmap Besided aforementioned benefits this change also implements necessary RegSense byte swap necessary for SX1503 and SX1506 variants of the chip. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 527 +++++++++++++++++++++------------------ 1 file changed, 284 insertions(+), 243 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 2eb233fe218b..4725fac3ede5 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -106,11 +106,8 @@ struct sx150x_pinctrl { struct irq_chip irq_chip; struct regmap *regmap; struct { - int update; u32 sense; u32 masked; - u32 dev_sense; - u32 dev_masked; } irq; struct mutex lock; const struct sx150x_device_data *data; @@ -171,16 +168,16 @@ static const struct sx150x_device_data sx1508q_device_data = { static const struct sx150x_device_data sx1509q_device_data = { .model = SX150X_789, - .reg_pullup = 0x07, - .reg_pulldn = 0x09, - .reg_dir = 0x0f, - .reg_data = 0x11, - .reg_irq_mask = 0x13, - .reg_irq_src = 0x19, - .reg_sense = 0x17, + .reg_pullup = 0x06, + .reg_pulldn = 0x08, + .reg_dir = 0x0e, + .reg_data = 0x10, + .reg_irq_mask = 0x12, + .reg_irq_src = 0x18, + .reg_sense = 0x14, .pri.x789 = { - .reg_drain = 0x0b, - .reg_polarity = 0x0d, + .reg_drain = 0x0a, + .reg_polarity = 0x0c, .reg_clock = 0x1e, .reg_misc = 0x1f, .reg_reset = 0x7d, @@ -192,20 +189,20 @@ static const struct sx150x_device_data sx1509q_device_data = { static const struct sx150x_device_data sx1506q_device_data = { .model = SX150X_456, - .reg_pullup = 0x05, - .reg_pulldn = 0x07, - .reg_dir = 0x03, - .reg_data = 0x01, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0f, - .reg_sense = 0x0d, + .reg_pullup = 0x04, + .reg_pulldn = 0x06, + .reg_dir = 0x02, + .reg_data = 0x00, + .reg_irq_mask = 0x08, + .reg_irq_src = 0x0e, + .reg_sense = 0x0a, .pri.x456 = { - .reg_pld_mode = 0x21, - .reg_pld_table0 = 0x23, - .reg_pld_table1 = 0x25, - .reg_pld_table2 = 0x27, - .reg_pld_table3 = 0x29, - .reg_pld_table4 = 0x2b, + .reg_pld_mode = 0x20, + .reg_pld_table0 = 0x22, + .reg_pld_table1 = 0x24, + .reg_pld_table2 = 0x26, + .reg_pld_table3 = 0x28, + .reg_pld_table4 = 0x2a, .reg_advance = 0xad, }, .ngpios = 16, @@ -238,20 +235,20 @@ static const struct sx150x_device_data sx1502q_device_data = { static const struct sx150x_device_data sx1503q_device_data = { .model = SX150X_123, - .reg_pullup = 0x05, - .reg_pulldn = 0x07, - .reg_dir = 0x03, - .reg_data = 0x01, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0f, - .reg_sense = 0x07, + .reg_pullup = 0x04, + .reg_pulldn = 0x06, + .reg_dir = 0x02, + .reg_data = 0x00, + .reg_irq_mask = 0x08, + .reg_irq_src = 0x0e, + .reg_sense = 0x0a, .pri.x123 = { - .reg_pld_mode = 0x10, - .reg_pld_table0 = 0x11, - .reg_pld_table1 = 0x12, - .reg_pld_table2 = 0x13, - .reg_pld_table3 = 0x14, - .reg_pld_table4 = 0x15, + .reg_pld_mode = 0x20, + .reg_pld_table0 = 0x22, + .reg_pld_table1 = 0x24, + .reg_pld_table2 = 0x26, + .reg_pld_table3 = 0x28, + .reg_pld_table4 = 0x2a, .reg_advance = 0xad, }, .ngpios = 16, @@ -259,70 +256,6 @@ static const struct sx150x_device_data sx1503q_device_data = { .npins = 16, /* oscio not available */ }; -/* - * These utility functions solve the common problem of locating and setting - * configuration bits. Configuration bits are grouped into registers - * whose indexes increase downwards. For example, with eight-bit registers, - * sixteen gpios would have their config bits grouped in the following order: - * REGISTER N-1 [ f e d c b a 9 8 ] - * N [ 7 6 5 4 3 2 1 0 ] - * - * For multi-bit configurations, the pattern gets wider: - * REGISTER N-3 [ f f e e d d c c ] - * N-2 [ b b a a 9 9 8 8 ] - * N-1 [ 7 7 6 6 5 5 4 4 ] - * N [ 3 3 2 2 1 1 0 0 ] - * - * Given the address of the starting register 'N', the index of the gpio - * whose configuration we seek to change, and the width in bits of that - * configuration, these functions allow us to locate the correct - * register and mask the correct bits. - */ -static inline void sx150x_find_cfg(u8 offset, u8 width, - u8 *reg, u8 *mask, u8 *shift) -{ - *reg -= offset * width / 8; - *mask = (1 << width) - 1; - *shift = (offset * width) % 8; - *mask <<= *shift; -} - -static int sx150x_write_cfg(struct i2c_client *client, - u8 offset, u8 width, u8 reg, u8 val) -{ - u8 mask; - unsigned int data; - u8 shift; - int err; - struct sx150x_pinctrl *pctl = i2c_get_clientdata(client); - - sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = regmap_read(pctl->regmap, reg, &data); - if (err < 0) - return err; - - data &= ~mask; - data |= (val << shift) & mask; - return regmap_write(pctl->regmap, reg, data); -} - -static int sx150x_read_cfg(struct i2c_client *client, - u8 offset, u8 width, u8 reg) -{ - u8 mask; - unsigned int data; - u8 shift; - int err; - struct sx150x_pinctrl *pctl = i2c_get_clientdata(client); - - sx150x_find_cfg(offset, width, ®, &mask, &shift); - err = regmap_read(pctl->regmap, reg, &data); - if (err < 0) - return err; - - return (data & mask); -} - static int sx150x_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) { return 0; @@ -368,31 +301,33 @@ static int sx150x_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); - int status; + unsigned int value; + int ret; if (sx150x_pin_is_oscio(pctl, offset)) return false; - status = sx150x_read_cfg(pctl->client, offset, 1, pctl->data->reg_dir); - if (status >= 0) - status = !!status; + ret = regmap_read(pctl->regmap, pctl->data->reg_dir, &value); + if (ret < 0) + return ret; - return status; + return !!(value & BIT(offset)); } static int sx150x_gpio_get(struct gpio_chip *chip, unsigned int offset) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); - int status; + unsigned int value; + int ret; if (sx150x_pin_is_oscio(pctl, offset)) return -EINVAL; - status = sx150x_read_cfg(pctl->client, offset, 1, pctl->data->reg_data); - if (status >= 0) - status = !!status; + ret = regmap_read(pctl->regmap, pctl->data->reg_data, &value); + if (ret < 0) + return ret; - return status; + return !!(value & BIT(offset)); } static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, @@ -409,9 +344,9 @@ static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, return 0; mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->pri.x789.reg_drain, - 0); + ret = regmap_write_bits(pctl->regmap, + pctl->data->pri.x789.reg_drain, + BIT(offset), 0); mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -423,9 +358,9 @@ static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, return -ENOTSUPP; mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->pri.x789.reg_drain, - 1); + ret = regmap_write_bits(pctl->regmap, + pctl->data->pri.x789.reg_drain, + BIT(offset), BIT(offset)); mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -438,6 +373,13 @@ static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, return 0; } +static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset, + int value) +{ + return regmap_write_bits(pctl->regmap, pctl->data->reg_data, + BIT(offset), value ? BIT(offset) : 0); +} + static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { @@ -451,9 +393,7 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, mutex_unlock(&pctl->lock); } else { mutex_lock(&pctl->lock); - sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->reg_data, - (value ? 1 : 0)); + __sx150x_gpio_set(pctl, offset, value); mutex_unlock(&pctl->lock); } } @@ -468,8 +408,9 @@ static int sx150x_gpio_direction_input(struct gpio_chip *chip, return -EINVAL; mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->reg_dir, 1); + ret = regmap_write_bits(pctl->regmap, + pctl->data->reg_dir, + BIT(offset), BIT(offset)); mutex_unlock(&pctl->lock); return ret; @@ -487,12 +428,11 @@ static int sx150x_gpio_direction_output(struct gpio_chip *chip, } mutex_lock(&pctl->lock); - status = sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->reg_data, - (value ? 1 : 0)); + status = __sx150x_gpio_set(pctl, offset, value); if (status >= 0) - status = sx150x_write_cfg(pctl->client, offset, 1, - pctl->data->reg_dir, 0); + status = regmap_write_bits(pctl->regmap, + pctl->data->reg_dir, + BIT(offset), 0); mutex_unlock(&pctl->lock); return status; @@ -504,8 +444,7 @@ static void sx150x_irq_mask(struct irq_data *d) gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned int n = d->hwirq; - pctl->irq.masked |= (1 << n); - pctl->irq.update = n; + pctl->irq.masked |= BIT(n); } static void sx150x_irq_unmask(struct irq_data *d) @@ -514,8 +453,7 @@ static void sx150x_irq_unmask(struct irq_data *d) gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned int n = d->hwirq; - pctl->irq.masked &= ~(1 << n); - pctl->irq.update = n; + pctl->irq.masked &= ~BIT(n); } static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) @@ -536,7 +474,6 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) pctl->irq.sense &= ~(3UL << (n * 2)); pctl->irq.sense |= val << (n * 2); - pctl->irq.update = n; return 0; } @@ -548,29 +485,20 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) unsigned int n; s32 err; unsigned int val; - int i; - for (i = (pctl->data->ngpios / 8) - 1; i >= 0; --i) { - err = regmap_read(pctl->regmap, - pctl->data->reg_irq_src - i, - &val); - if (err < 0) - continue; + err = regmap_read(pctl->regmap, pctl->data->reg_irq_src, &val); + if (err < 0) + return IRQ_NONE; - err = regmap_write(pctl->regmap, - pctl->data->reg_irq_src - i, - val); - if (err < 0) - continue; - - for (n = 0; n < 8; ++n) { - if (val & (1 << n)) { - sub_irq = irq_find_mapping( - pctl->gpio.irqdomain, - (i * 8) + n); - handle_nested_irq(sub_irq); - ++nhandled; - } + err = regmap_write(pctl->regmap, pctl->data->reg_irq_src, val); + if (err < 0) + return IRQ_NONE; + + for (n = 0; n < pctl->data->ngpios; ++n) { + if (val & BIT(n)) { + sub_irq = irq_find_mapping(pctl->gpio.irqdomain, n); + handle_nested_irq(sub_irq); + ++nhandled; } } @@ -589,35 +517,9 @@ static void sx150x_irq_bus_sync_unlock(struct irq_data *d) { struct sx150x_pinctrl *pctl = gpiochip_get_data(irq_data_get_irq_chip_data(d)); - unsigned int n; - - if (pctl->irq.update < 0) - goto out; - n = pctl->irq.update; - pctl->irq.update = -1; - - /* Avoid updates if nothing changed */ - if (pctl->irq.dev_sense == pctl->irq.sense && - pctl->irq.dev_masked == pctl->irq.masked) - goto out; - - pctl->irq.dev_sense = pctl->irq.sense; - pctl->irq.dev_masked = pctl->irq.masked; - - if (pctl->irq.masked & (1 << n)) { - sx150x_write_cfg(pctl->client, n, 1, - pctl->data->reg_irq_mask, 1); - sx150x_write_cfg(pctl->client, n, 2, - pctl->data->reg_sense, 0); - } else { - sx150x_write_cfg(pctl->client, n, 1, - pctl->data->reg_irq_mask, 0); - sx150x_write_cfg(pctl->client, n, 2, - pctl->data->reg_sense, - pctl->irq.sense >> (n * 2)); - } -out: + regmap_write(pctl->regmap, pctl->data->reg_irq_mask, pctl->irq.masked); + regmap_write(pctl->regmap, pctl->data->reg_sense, pctl->irq.sense); mutex_unlock(&pctl->lock); } @@ -628,10 +530,9 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned int param = pinconf_to_config_param(*config); int ret; u32 arg; + unsigned int data; if (sx150x_pin_is_oscio(pctl, pin)) { - unsigned int data; - switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_OUTPUT: @@ -666,8 +567,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, switch (param) { case PIN_CONFIG_BIAS_PULL_DOWN: mutex_lock(&pctl->lock); - ret = sx150x_read_cfg(pctl->client, pin, 1, - pctl->data->reg_pulldn); + ret = regmap_read(pctl->regmap, + pctl->data->reg_pulldn, + &data); + data &= BIT(pin); mutex_unlock(&pctl->lock); if (ret < 0) @@ -681,8 +584,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_UP: mutex_lock(&pctl->lock); - ret = sx150x_read_cfg(pctl->client, pin, 1, - pctl->data->reg_pullup); + ret = regmap_read(pctl->regmap, + pctl->data->reg_pullup, + &data); + data &= BIT(pin); mutex_unlock(&pctl->lock); if (ret < 0) @@ -699,14 +604,16 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, return -ENOTSUPP; mutex_lock(&pctl->lock); - ret = sx150x_read_cfg(pctl->client, pin, 1, - pctl->data->pri.x789.reg_drain); + ret = regmap_read(pctl->regmap, + pctl->data->pri.x789.reg_drain, + &data); + data &= BIT(pin); mutex_unlock(&pctl->lock); if (ret < 0) return ret; - if (!ret) + if (!data) return -EINVAL; arg = 1; @@ -717,14 +624,16 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, arg = true; else { mutex_lock(&pctl->lock); - ret = sx150x_read_cfg(pctl->client, pin, 1, - pctl->data->pri.x789.reg_drain); + ret = regmap_read(pctl->regmap, + pctl->data->pri.x789.reg_drain, + &data); + data &= BIT(pin); mutex_unlock(&pctl->lock); if (ret < 0) return ret; - if (ret) + if (data) return -EINVAL; arg = 1; @@ -785,15 +694,17 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_DISABLE: mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, pin, 1, - pctl->data->reg_pulldn, 0); + ret = regmap_write_bits(pctl->regmap, + pctl->data->reg_pulldn, + BIT(pin), 0); mutex_unlock(&pctl->lock); if (ret < 0) return ret; mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, pin, 1, - pctl->data->reg_pullup, 0); + ret = regmap_write_bits(pctl->regmap, + pctl->data->reg_pullup, + BIT(pin), 0); mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -802,9 +713,9 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_UP: mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, pin, 1, - pctl->data->reg_pullup, - 1); + ret = regmap_write_bits(pctl->regmap, + pctl->data->reg_pullup, + BIT(pin), BIT(pin)); mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -813,9 +724,9 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, case PIN_CONFIG_BIAS_PULL_DOWN: mutex_lock(&pctl->lock); - ret = sx150x_write_cfg(pctl->client, pin, 1, - pctl->data->reg_pulldn, - 1); + ret = regmap_write_bits(pctl->regmap, + pctl->data->reg_pulldn, + BIT(pin), BIT(pin)); mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -878,16 +789,6 @@ static const struct of_device_id sx150x_of_match[] = { {}, }; -static int sx150x_init_io(struct sx150x_pinctrl *pctl, u8 base, u16 cfg) -{ - int err = 0; - unsigned int n; - - for (n = 0; err >= 0 && n < (pctl->data->ngpios / 8); ++n) - err = regmap_write(pctl->regmap, base - n, cfg >> (n * 8)); - return err; -} - static int sx150x_reset(struct sx150x_pinctrl *pctl) { int err; @@ -933,11 +834,16 @@ static int sx150x_init_misc(struct sx150x_pinctrl *pctl) return -EINVAL; } - return i2c_smbus_write_byte_data(pctl->client, reg, value); + return regmap_write(pctl->regmap, reg, value); } static int sx150x_init_hw(struct sx150x_pinctrl *pctl) { + const u8 reg[] = { + [SX150X_789] = pctl->data->pri.x789.reg_polarity, + [SX150X_456] = pctl->data->pri.x456.reg_pld_mode, + [SX150X_123] = pctl->data->pri.x123.reg_pld_mode, + }; int err; if (pctl->data->model == SX150X_789 && @@ -952,28 +858,165 @@ static int sx150x_init_hw(struct sx150x_pinctrl *pctl) return err; /* Set all pins to work in normal mode */ - if (pctl->data->model == SX150X_789) { - err = sx150x_init_io(pctl, - pctl->data->pri.x789.reg_polarity, - 0); - if (err < 0) - return err; - } else if (pctl->data->model == SX150X_456) { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(pctl, - pctl->data->pri.x456.reg_pld_mode, - 0); - if (err < 0) - return err; + return regmap_write(pctl->regmap, reg[pctl->data->model], 0); +} + +static int sx150x_regmap_reg_width(struct sx150x_pinctrl *pctl, + unsigned int reg) +{ + const struct sx150x_device_data *data = pctl->data; + + if (reg == data->reg_sense) { + /* + * RegSense packs two bits of configuration per GPIO, + * so we'd need to read twice as many bits as there + * are GPIO in our chip + */ + return 2 * data->ngpios; + } else if ((data->model == SX150X_789 && + (reg == data->pri.x789.reg_misc || + reg == data->pri.x789.reg_clock || + reg == data->pri.x789.reg_reset)) + || + (data->model == SX150X_123 && + reg == data->pri.x123.reg_advance) + || + (data->model == SX150X_456 && + reg == data->pri.x456.reg_advance)) { + return 8; } else { - /* Set all pins to work in normal mode */ - err = sx150x_init_io(pctl, - pctl->data->pri.x123.reg_pld_mode, - 0); - if (err < 0) - return err; + return data->ngpios; + } +} + +static unsigned int sx150x_maybe_swizzle(struct sx150x_pinctrl *pctl, + unsigned int reg, unsigned int val) +{ + unsigned int a, b; + const struct sx150x_device_data *data = pctl->data; + + /* + * Whereas SX1509 presents RegSense in a simple layout as such: + * reg [ f f e e d d c c ] + * reg + 1 [ b b a a 9 9 8 8 ] + * reg + 2 [ 7 7 6 6 5 5 4 4 ] + * reg + 3 [ 3 3 2 2 1 1 0 0 ] + * + * SX1503 and SX1506 deviate from that data layout, instead storing + * thier contents as follows: + * + * reg [ f f e e d d c c ] + * reg + 1 [ 7 7 6 6 5 5 4 4 ] + * reg + 2 [ b b a a 9 9 8 8 ] + * reg + 3 [ 3 3 2 2 1 1 0 0 ] + * + * so, taking that into account, we swap two + * inner bytes of a 4-byte result + */ + + if (reg == data->reg_sense && + data->ngpios == 16 && + (data->model == SX150X_123 || + data->model == SX150X_456)) { + a = val & 0x00ff0000; + b = val & 0x0000ff00; + + val &= 0xff0000ff; + val |= b << 8; + val |= a >> 8; } + return val; +} + +/* + * In order to mask the differences between 16 and 8 bit expander + * devices we set up a sligthly ficticious regmap that pretends to be + * a set of 32-bit (to accomodate RegSenseLow/RegSenseHigh + * pair/quartet) registers and transparently reconstructs those + * registers via multiple I2C/SMBus reads + * + * This way the rest of the driver code, interfacing with the chip via + * regmap API, can work assuming that each GPIO pin is represented by + * a group of bits at an offset proportioan to GPIO number within a + * given register. + * + */ +static int sx150x_regmap_reg_read(void *context, unsigned int reg, + unsigned int *result) +{ + int ret, n; + struct sx150x_pinctrl *pctl = context; + struct i2c_client *i2c = pctl->client; + const int width = sx150x_regmap_reg_width(pctl, reg); + unsigned int idx, val; + + /* + * There are four potential cases coverd by this function: + * + * 1) 8-pin chip, single configuration bit register + * + * This is trivial the code below just needs to read: + * reg [ 7 6 5 4 3 2 1 0 ] + * + * 2) 8-pin chip, double configuration bit register (RegSense) + * + * The read will be done as follows: + * reg [ 7 7 6 6 5 5 4 4 ] + * reg + 1 [ 3 3 2 2 1 1 0 0 ] + * + * 3) 16-pin chip, single configuration bit register + * + * The read will be done as follows: + * reg [ f e d c b a 9 8 ] + * reg + 1 [ 7 6 5 4 3 2 1 0 ] + * + * 4) 16-pin chip, double configuration bit register (RegSense) + * + * The read will be done as follows: + * reg [ f f e e d d c c ] + * reg + 1 [ b b a a 9 9 8 8 ] + * reg + 2 [ 7 7 6 6 5 5 4 4 ] + * reg + 3 [ 3 3 2 2 1 1 0 0 ] + */ + + for (n = width, val = 0, idx = reg; n > 0; n -= 8, idx++) { + val <<= 8; + + ret = i2c_smbus_read_byte_data(i2c, idx); + if (ret < 0) + return ret; + + val |= ret; + } + + *result = sx150x_maybe_swizzle(pctl, reg, val); + + return 0; +} + +static int sx150x_regmap_reg_write(void *context, unsigned int reg, + unsigned int val) +{ + int ret, n; + struct sx150x_pinctrl *pctl = context; + struct i2c_client *i2c = pctl->client; + const int width = sx150x_regmap_reg_width(pctl, reg); + + val = sx150x_maybe_swizzle(pctl, reg, val); + + n = width - 8; + do { + const u8 byte = (val >> n) & 0xff; + + ret = i2c_smbus_write_byte_data(i2c, reg, byte); + if (ret < 0) + return ret; + + reg++; + n -= 8; + } while (n >= 0); + return 0; } @@ -981,18 +1024,18 @@ static bool sx150x_reg_volatile(struct device *dev, unsigned int reg) { struct sx150x_pinctrl *pctl = i2c_get_clientdata(to_i2c_client(dev)); - return reg == pctl->data->reg_irq_src || - reg == pctl->data->reg_irq_src - 1 || - reg == pctl->data->reg_data || - reg == pctl->data->reg_data - 1; + return reg == pctl->data->reg_irq_src || reg == pctl->data->reg_data; } const struct regmap_config sx150x_regmap_config = { .reg_bits = 8, - .val_bits = 8, + .val_bits = 32, .cache_type = REGCACHE_RBTREE, + .reg_read = sx150x_regmap_reg_read, + .reg_write = sx150x_regmap_reg_write, + .max_register = SX150X_MAX_REGISTER, .volatile_reg = sx150x_reg_volatile, }; @@ -1026,7 +1069,8 @@ static int sx150x_probe(struct i2c_client *client, if (!pctl->data) return -EINVAL; - pctl->regmap = devm_regmap_init_i2c(client, &sx150x_regmap_config); + pctl->regmap = devm_regmap_init(dev, NULL, pctl, + &sx150x_regmap_config); if (IS_ERR(pctl->regmap)) { ret = PTR_ERR(pctl->regmap); dev_err(dev, "Failed to allocate register map: %d\n", @@ -1072,9 +1116,6 @@ static int sx150x_probe(struct i2c_client *client, pctl->irq.masked = ~0; pctl->irq.sense = 0; - pctl->irq.dev_masked = ~0; - pctl->irq.dev_sense = 0; - pctl->irq.update = -1; ret = gpiochip_irqchip_add(&pctl->gpio, &pctl->irq_chip, 0, -- cgit 1.4.1 From d977a876c655f176d9faf87fe55148ca2676d3fb Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:18 -0800 Subject: pinctrl-sx150x: Remove excessive locking Gpiochip and irqchip aspects of this driver do not access any shared registers on the chip itself and atomicity of various regmap operations is ensured by that API's implementation, so there doesn't seem to be a reason to hold the lock in as many places as it is held now. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 70 +++++++++------------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 4725fac3ede5..c339800a396b 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -343,13 +343,9 @@ static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, sx150x_pin_is_oscio(pctl, offset)) return 0; - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->pri.x789.reg_drain, BIT(offset), 0); - mutex_unlock(&pctl->lock); - if (ret < 0) - return ret; break; case LINE_MODE_OPEN_DRAIN: @@ -357,20 +353,16 @@ static int sx150x_gpio_set_single_ended(struct gpio_chip *chip, sx150x_pin_is_oscio(pctl, offset)) return -ENOTSUPP; - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->pri.x789.reg_drain, BIT(offset), BIT(offset)); - mutex_unlock(&pctl->lock); - if (ret < 0) - return ret; break; - default: - return -ENOTSUPP; + ret = -ENOTSUPP; + break; } - return 0; + return ret; } static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset, @@ -385,57 +377,46 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); - if (sx150x_pin_is_oscio(pctl, offset)) { - mutex_lock(&pctl->lock); + if (sx150x_pin_is_oscio(pctl, offset)) regmap_write(pctl->regmap, pctl->data->pri.x789.reg_clock, (value ? 0x1f : 0x10)); - mutex_unlock(&pctl->lock); - } else { - mutex_lock(&pctl->lock); + else __sx150x_gpio_set(pctl, offset, value); - mutex_unlock(&pctl->lock); - } + } static int sx150x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); - int ret; if (sx150x_pin_is_oscio(pctl, offset)) return -EINVAL; - mutex_lock(&pctl->lock); - ret = regmap_write_bits(pctl->regmap, - pctl->data->reg_dir, - BIT(offset), BIT(offset)); - mutex_unlock(&pctl->lock); - - return ret; + return regmap_write_bits(pctl->regmap, + pctl->data->reg_dir, + BIT(offset), BIT(offset)); } static int sx150x_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, int value) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); - int status; + int ret; if (sx150x_pin_is_oscio(pctl, offset)) { sx150x_gpio_set(chip, offset, value); return 0; } - mutex_lock(&pctl->lock); - status = __sx150x_gpio_set(pctl, offset, value); - if (status >= 0) - status = regmap_write_bits(pctl->regmap, - pctl->data->reg_dir, - BIT(offset), 0); - mutex_unlock(&pctl->lock); + ret = __sx150x_gpio_set(pctl, offset, value); + if (ret < 0) + return ret; - return status; + return regmap_write_bits(pctl->regmap, + pctl->data->reg_dir, + BIT(offset), 0); } static void sx150x_irq_mask(struct irq_data *d) @@ -536,12 +517,9 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, switch (param) { case PIN_CONFIG_DRIVE_PUSH_PULL: case PIN_CONFIG_OUTPUT: - mutex_lock(&pctl->lock); ret = regmap_read(pctl->regmap, pctl->data->pri.x789.reg_clock, &data); - mutex_unlock(&pctl->lock); - if (ret < 0) return ret; @@ -566,12 +544,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, switch (param) { case PIN_CONFIG_BIAS_PULL_DOWN: - mutex_lock(&pctl->lock); ret = regmap_read(pctl->regmap, pctl->data->reg_pulldn, &data); data &= BIT(pin); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -583,12 +559,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, break; case PIN_CONFIG_BIAS_PULL_UP: - mutex_lock(&pctl->lock); ret = regmap_read(pctl->regmap, pctl->data->reg_pullup, &data); data &= BIT(pin); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -603,12 +577,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (pctl->data->model != SX150X_789) return -ENOTSUPP; - mutex_lock(&pctl->lock); ret = regmap_read(pctl->regmap, pctl->data->pri.x789.reg_drain, &data); data &= BIT(pin); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -623,12 +595,10 @@ static int sx150x_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, if (pctl->data->model != SX150X_789) arg = true; else { - mutex_lock(&pctl->lock); ret = regmap_read(pctl->regmap, pctl->data->pri.x789.reg_drain, &data); data &= BIT(pin); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; @@ -693,41 +663,33 @@ static int sx150x_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, switch (param) { case PIN_CONFIG_BIAS_PULL_PIN_DEFAULT: case PIN_CONFIG_BIAS_DISABLE: - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->reg_pulldn, BIT(pin), 0); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->reg_pullup, BIT(pin), 0); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; break; case PIN_CONFIG_BIAS_PULL_UP: - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->reg_pullup, BIT(pin), BIT(pin)); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; break; case PIN_CONFIG_BIAS_PULL_DOWN: - mutex_lock(&pctl->lock); ret = regmap_write_bits(pctl->regmap, pctl->data->reg_pulldn, BIT(pin), BIT(pin)); - mutex_unlock(&pctl->lock); if (ret < 0) return ret; -- cgit 1.4.1 From ab5bd035445932397bfe351403ce52246096a261 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:19 -0800 Subject: pinctrl-sx150x: Improve oscio GPIO functions Move actual code that configures oscio pin into a separate function and use it instead of calling sx150x_gpio_set to avoid calling sx150x_pin_is_oscio twice and correctly propagte error code in sx150x_gpio_direction_output. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index c339800a396b..f2ec072a2134 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -372,15 +372,21 @@ static int __sx150x_gpio_set(struct sx150x_pinctrl *pctl, unsigned int offset, BIT(offset), value ? BIT(offset) : 0); } +static int sx150x_gpio_oscio_set(struct sx150x_pinctrl *pctl, + int value) +{ + return regmap_write(pctl->regmap, + pctl->data->pri.x789.reg_clock, + (value ? 0x1f : 0x10)); +} + static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); if (sx150x_pin_is_oscio(pctl, offset)) - regmap_write(pctl->regmap, - pctl->data->pri.x789.reg_clock, - (value ? 0x1f : 0x10)); + sx150x_gpio_oscio_set(pctl, value); else __sx150x_gpio_set(pctl, offset, value); @@ -405,10 +411,8 @@ static int sx150x_gpio_direction_output(struct gpio_chip *chip, struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); int ret; - if (sx150x_pin_is_oscio(pctl, offset)) { - sx150x_gpio_set(chip, offset, value); - return 0; - } + if (sx150x_pin_is_oscio(pctl, offset)) + return sx150x_gpio_oscio_set(pctl, value); ret = __sx150x_gpio_set(pctl, offset, value); if (ret < 0) -- cgit 1.4.1 From 05a90cc7293878aa5b914e380a02ea9b65e2336d Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:20 -0800 Subject: pinctrl-sx150x: Simplify interrupt handler Make use of for_each_set_bit macro and reduce boilerplate code. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index f2ec072a2134..78e15c9a73a2 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -465,11 +465,9 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) { struct sx150x_pinctrl *pctl = (struct sx150x_pinctrl *)dev_id; - unsigned int nhandled = 0; - unsigned int sub_irq; - unsigned int n; - s32 err; + unsigned long n, status; unsigned int val; + int err; err = regmap_read(pctl->regmap, pctl->data->reg_irq_src, &val); if (err < 0) @@ -479,15 +477,11 @@ static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) if (err < 0) return IRQ_NONE; - for (n = 0; n < pctl->data->ngpios; ++n) { - if (val & BIT(n)) { - sub_irq = irq_find_mapping(pctl->gpio.irqdomain, n); - handle_nested_irq(sub_irq); - ++nhandled; - } - } + status = val; + for_each_set_bit(n, &status, pctl->data->ngpios) + handle_nested_irq(irq_find_mapping(pctl->gpio.irqdomain, n)); - return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); + return IRQ_HANDLED; } static void sx150x_irq_bus_lock(struct irq_data *d) -- cgit 1.4.1 From 080c489dde6355dedd7dc5a93821199d0bbf9279 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:21 -0800 Subject: pinctrl-sx150x: Use handle_bad_irq instead of handle_edge_irq Althought the function passed as a "handler" during GPIO chip instantiation is not going to ever be called, specifying handle_edge_irq there makes for a rather confusing read, both because no "ack" callback in specified for irqchip and because there's no acking action is necessary. Specify handle_bad_irq instead a make a note of the situation. This commit should be a no-op behaviour wise. Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 78e15c9a73a2..798a8bb143c1 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -1077,9 +1077,20 @@ static int sx150x_probe(struct i2c_client *client, pctl->irq.masked = ~0; pctl->irq.sense = 0; + /* + * Because sx150x_irq_threaded_fn invokes all of the + * nested interrrupt handlers via handle_nested_irq, + * any "handler" passed to gpiochip_irqchip_add() + * below is going to be ignored, so the choice of the + * function does not matter that much. + * + * We set it to handle_bad_irq to avoid confusion, + * plus it will be instantly noticeable if it is ever + * called (should not happen) + */ ret = gpiochip_irqchip_add(&pctl->gpio, &pctl->irq_chip, 0, - handle_edge_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "could not connect irqchip to gpiochip\n"); return ret; -- cgit 1.4.1 From fd931f2373662a7de8c255e7a86c1e79e8e0baa0 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:22 -0800 Subject: pinctrl-sx150x: Remove magic numbers from sx150x_irq_set_type Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 798a8bb143c1..56abe36071ed 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -47,6 +47,8 @@ enum { enum { SX150X_789_REG_MISC_AUTOCLEAR_OFF = 1 << 0, SX150X_MAX_REGISTER = 0xad, + SX150X_IRQ_TYPE_EDGE_RISING = 0x1, + SX150X_IRQ_TYPE_EDGE_FALLING = 0x2, }; struct sx150x_123_pri { @@ -441,6 +443,21 @@ static void sx150x_irq_unmask(struct irq_data *d) pctl->irq.masked &= ~BIT(n); } +static void sx150x_irq_set_sense(struct sx150x_pinctrl *pctl, + unsigned int line, unsigned int sense) +{ + /* + * Every interrupt line is represented by two bits shifted + * proportionally to the line number + */ + const unsigned int n = line * 2; + const unsigned int mask = ~((SX150X_IRQ_TYPE_EDGE_RISING | + SX150X_IRQ_TYPE_EDGE_FALLING) << n); + + pctl->irq.sense &= mask; + pctl->irq.sense |= sense << n; +} + static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct sx150x_pinctrl *pctl = @@ -453,12 +470,11 @@ static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) n = d->hwirq; if (flow_type & IRQ_TYPE_EDGE_RISING) - val |= 0x1; + val |= SX150X_IRQ_TYPE_EDGE_RISING; if (flow_type & IRQ_TYPE_EDGE_FALLING) - val |= 0x2; + val |= SX150X_IRQ_TYPE_EDGE_FALLING; - pctl->irq.sense &= ~(3UL << (n * 2)); - pctl->irq.sense |= val << (n * 2); + sx150x_irq_set_sense(pctl, n, val); return 0; } -- cgit 1.4.1 From f9038d603a64dd0f42a3773c96c72809382066de Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Mon, 7 Nov 2016 08:53:23 -0800 Subject: pinctrl-sx150x: Remove magic numbers from sx150x_reset Tested-by: Neil Armstrong Acked-by: Neil Armstrong Signed-off-by: Andrey Smirnov Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 56abe36071ed..dc1341fdc73d 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -49,6 +49,8 @@ enum { SX150X_MAX_REGISTER = 0xad, SX150X_IRQ_TYPE_EDGE_RISING = 0x1, SX150X_IRQ_TYPE_EDGE_FALLING = 0x2, + SX150X_789_RESET_KEY1 = 0x12, + SX150X_789_RESET_KEY2 = 0x34, }; struct sx150x_123_pri { @@ -771,13 +773,13 @@ static int sx150x_reset(struct sx150x_pinctrl *pctl) err = i2c_smbus_write_byte_data(pctl->client, pctl->data->pri.x789.reg_reset, - 0x12); + SX150X_789_RESET_KEY1); if (err < 0) return err; err = i2c_smbus_write_byte_data(pctl->client, pctl->data->pri.x789.reg_reset, - 0x34); + SX150X_789_RESET_KEY2); return err; } -- cgit 1.4.1 From fc669d13cb7700c67ebe55563642c84900fa43c9 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 8 Nov 2016 10:25:42 +0100 Subject: pinctrl: sx150x: fix up headers Include rather than Drop . Cc: Andrey Smirnov Cc: Neil Armstrong Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index dc1341fdc73d..63778058eec7 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -27,8 +27,7 @@ #include #include #include -#include -#include +#include #include #include #include -- cgit 1.4.1 From fdcf83552ab1051f3a0b71a7d5c2e242f97b4157 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Nov 2016 15:25:15 +0100 Subject: pinctrl: st: st_pinconf_dbg_show wrong format string function is defined as unsigned int. So we need %u to print it. Signed-off-by: Heinrich Schuchardt Acked-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index 99da4cf91031..b926c744193b 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -1006,7 +1006,7 @@ static void st_pinconf_dbg_show(struct pinctrl_dev *pctldev, function = st_pctl_get_pin_function(pc, offset); if (function) - snprintf(f, 10, "Alt Fn %d", function); + snprintf(f, 10, "Alt Fn %u", function); else snprintf(f, 5, "GPIO"); -- cgit 1.4.1 From 95bdb0ea3668d86513376e0e88e88f5c0202acba Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 5 Nov 2016 15:35:15 +0100 Subject: pinctrl: st: st_pctl_dt_parse_groups simplify expression for_each_property_of_node(pins, pp) checks that pp is not NULL. So there is no need to check it inside the loop. Signed-off-by: Heinrich Schuchardt Acked-by: Patrice Chotard Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c index b926c744193b..4f0998b33660 100644 --- a/drivers/pinctrl/pinctrl-st.c +++ b/drivers/pinctrl/pinctrl-st.c @@ -1181,7 +1181,7 @@ static int st_pctl_dt_parse_groups(struct device_node *np, if (!strcmp(pp->name, "name")) continue; - if (pp && (pp->length/sizeof(__be32)) >= OF_GPIO_ARGS_MIN) { + if (pp->length / sizeof(__be32) >= OF_GPIO_ARGS_MIN) { npins++; } else { pr_warn("Invalid st,pins in %s node\n", np->name); -- cgit 1.4.1 From de7416bcee3f7c9004fff92795a03a46f3f40316 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Wed, 9 Nov 2016 15:54:00 +0100 Subject: pinctrl: single: check for any error when getting rows pinctrl_count_index_with_args returns -ENOENT not -EINVAL. The return check would pass, and we would try to kzalloc with a negative error size throwing a warning. Instead of checking for -EINVAL specifically, lets check for any error and avoid negative size allocations. Signed-off-by: Axel Haslam Acked-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 539f31cd8e00..f36a9f1f3949 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1133,8 +1133,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, struct pcs_function *function; rows = pinctrl_count_index_with_args(np, name); - if (rows == -EINVAL) - return rows; + if (rows <= 0) { + dev_err(pcs->dev, "Ivalid number of rows: %d\n", rows); + return -EINVAL; + } vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL); if (!vals) @@ -1228,8 +1230,10 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, struct pcs_function *function; rows = pinctrl_count_index_with_args(np, name); - if (rows == -EINVAL) - return rows; + if (rows <= 0) { + dev_err(pcs->dev, "Invalid number of rows: %d\n", rows); + return -EINVAL; + } npins_in_row = pcs->width / pcs->bits_per_pin; -- cgit 1.4.1 From dd68a526c7ec0ee3eab13848f6f97bddd3346066 Mon Sep 17 00:00:00 2001 From: Axel Haslam Date: Wed, 9 Nov 2016 15:54:01 +0100 Subject: pinctrl: single: search for the bits property when parsing bits The pcs_parse_bits_in_pinctrl_entry function should search for the "pinctrl-single,bits" and not "pinctrl-single,pins" Signed-off-by: Axel Haslam Acked-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index f36a9f1f3949..2b196e53d937 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1223,7 +1223,7 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, unsigned *num_maps, const char **pgnames) { - const char *name = "pinctrl-single,pins"; + const char *name = "pinctrl-single,bits"; struct pcs_func_vals *vals; int rows, *pins, found = 0, res = -ENOMEM, i; int npins_in_row; -- cgit 1.4.1 From 00445b5d5866c7b31bcfc59e907c9062100b4b0a Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 24 Feb 2015 13:40:50 +0000 Subject: pinctrl: bcm2835: Fix ints for GPIOs 28-31 & 46-53 Contrary to the documentation, the BCM2835 GPIO controller actually has four interrupt lines - one each for the three IRQ groups and one common. Confusingly, the GPIO interrupt groups don't correspond directly with the GPIO control banks. Instead, GPIOs 0-27 generate IRQ GPIO0, 28-45 IRQ GPIO1 and 46-53 IRQ GPIO2. Awkwardly, the GPIOs for IRQ GPIO1 straddle two 32-entry GPIO banks, so split out a function to process the interrupts for a single GPIO bank. Cc: Stefan Wahren Cc: Stephen Warren Signed-off-by: Phil Elwell Acked-by: Eric Anholt Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 50 ++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index b2dd278f18b1..9587d678f7c4 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -47,6 +47,7 @@ #define MODULE_NAME "pinctrl-bcm2835" #define BCM2835_NUM_GPIOS 54 #define BCM2835_NUM_BANKS 2 +#define BCM2835_NUM_IRQS 3 #define BCM2835_PIN_BITMAP_SZ \ DIV_ROUND_UP(BCM2835_NUM_GPIOS, sizeof(unsigned long) * 8) @@ -88,13 +89,13 @@ enum bcm2835_pinconf_pull { struct bcm2835_gpio_irqdata { struct bcm2835_pinctrl *pc; - int bank; + int irqgroup; }; struct bcm2835_pinctrl { struct device *dev; void __iomem *base; - int irq[BCM2835_NUM_BANKS]; + int irq[BCM2835_NUM_IRQS]; /* note: locking assumes each bank will have its own unsigned long */ unsigned long enabled_irq_map[BCM2835_NUM_BANKS]; @@ -105,7 +106,7 @@ struct bcm2835_pinctrl { struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; - struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_BANKS]; + struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS]; spinlock_t irq_lock[BCM2835_NUM_BANKS]; }; @@ -391,17 +392,16 @@ static struct gpio_chip bcm2835_gpio_chip = { .can_sleep = false, }; -static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, + unsigned int bank, u32 mask) { - struct bcm2835_gpio_irqdata *irqdata = dev_id; - struct bcm2835_pinctrl *pc = irqdata->pc; - int bank = irqdata->bank; unsigned long events; unsigned offset; unsigned gpio; unsigned int type; events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4); + events &= mask; events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; @@ -409,7 +409,30 @@ static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); } - return events ? IRQ_HANDLED : IRQ_NONE; + + return (events != 0); +} + +static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +{ + struct bcm2835_gpio_irqdata *irqdata = dev_id; + struct bcm2835_pinctrl *pc = irqdata->pc; + int handled = 0; + + switch (irqdata->irqgroup) { + case 0: /* IRQ0 covers GPIOs 0-27 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff); + break; + case 1: /* IRQ1 covers GPIOs 28-45 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) | + bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); + break; + case 2: /* IRQ2 covers GPIOs 46-53 */ + handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); + break; + } + + return handled ? IRQ_HANDLED : IRQ_NONE; } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, @@ -1000,8 +1023,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; - int len; - char *name; /* clear event detection flags */ bcm2835_gpio_wr(pc, GPREN0 + i * 4, 0); @@ -1016,10 +1037,15 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) for_each_set_bit(offset, &events, 32) bcm2835_gpio_wr(pc, GPEDS0 + i * 4, BIT(offset)); + spin_lock_init(&pc->irq_lock[i]); + } + + for (i = 0; i < BCM2835_NUM_IRQS; i++) { + int len; + char *name; pc->irq[i] = irq_of_parse_and_map(np, i); pc->irq_data[i].pc = pc; - pc->irq_data[i].bank = i; - spin_lock_init(&pc->irq_lock[i]); + pc->irq_data[i].irqgroup = i; len = strlen(dev_name(pc->dev)) + 16; name = devm_kzalloc(pc->dev, len, GFP_KERNEL); -- cgit 1.4.1 From ccca1ad5db0e97710b69f9a3895e03290c47898b Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Fri, 6 May 2016 12:32:47 +0100 Subject: pinctrl: bcm2835: Return pins to inputs when freed When dynamically unloading overlays, it is important that freed pins are restored to being inputs to prevent functions from being enabled in multiple places at once. Cc: Stefan Wahren Cc: Stephen Warren Signed-off-by: Phil Elwell Acked-by: Eric Anholt Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/pinctrl-bcm2835.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 9587d678f7c4..6128359d3281 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -844,6 +844,16 @@ static const struct pinctrl_ops bcm2835_pctl_ops = { .dt_free_map = bcm2835_pctl_dt_free_map, }; +static int bcm2835_pmx_free(struct pinctrl_dev *pctldev, + unsigned offset) +{ + struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); + + /* disable by setting to GPIO_IN */ + bcm2835_pinctrl_fsel_set(pc, offset, BCM2835_FSEL_GPIO_IN); + return 0; +} + static int bcm2835_pmx_get_functions_count(struct pinctrl_dev *pctldev) { return BCM2835_FSEL_COUNT; @@ -903,6 +913,7 @@ static int bcm2835_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, } static const struct pinmux_ops bcm2835_pmx_ops = { + .free = bcm2835_pmx_free, .get_functions_count = bcm2835_pmx_get_functions_count, .get_function_name = bcm2835_pmx_get_function_name, .get_function_groups = bcm2835_pmx_get_function_groups, -- cgit 1.4.1 From 8b1bd11c1f8f529057369c5b3702d13fd24e2765 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 9 Nov 2016 17:40:10 +0900 Subject: pinctrl: samsung: Add the support the multiple IORESOURCE_MEM for one pin-bank This patch supports the multiple IORESOURCE_MEM resources for one pin-bank. In the pre-existing Exynos series, the registers of the gpio bank are included in the one memory map. But, some gpio bank need to support the one more memory map (IORESOURCE_MEM) because the registers of gpio bank are separated into the different memory map. For example, The both ALIVE and IMEM domain have the different memory base address. The GFP[1-5] of exynos5433 are composed as following: - ALIVE domain : WEINT_* registers - IMEM domain : CON/DAT/PUD/DRV/CONPDN/PUDPDN register Cc: Linus Walleij Cc: Rob Herring Cc: Mark Rutland Cc: Tomasz Figa Cc: Krzysztof Kozlowski Cc: Sylwester Nawrocki Cc: Kukjin Kim Cc: linux-gpio@vger.kernel.org Suggested-by: Tomasz Figa Signed-off-by: Chanwoo Choi Reviewed-by: Krzysztof Kozlowski Signed-off-by: Linus Walleij --- drivers/pinctrl/samsung/pinctrl-exynos.c | 39 +++++++++++++----------------- drivers/pinctrl/samsung/pinctrl-exynos.h | 11 +++++++++ drivers/pinctrl/samsung/pinctrl-s3c24xx.c | 37 +++++++++++++--------------- drivers/pinctrl/samsung/pinctrl-s3c64xx.c | 40 +++++++++++++++++-------------- drivers/pinctrl/samsung/pinctrl-samsung.c | 40 ++++++++++++++++++++----------- drivers/pinctrl/samsung/pinctrl-samsung.h | 10 ++++++-- 6 files changed, 99 insertions(+), 78 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index d32fa2b5ff82..d657b52dfdb5 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -61,16 +61,15 @@ static void exynos_irq_mask(struct irq_data *irqd) struct irq_chip *chip = irq_data_get_irq_chip(irqd); struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; unsigned long mask; unsigned long flags; spin_lock_irqsave(&bank->slock, flags); - mask = readl(d->virt_base + reg_mask); + mask = readl(bank->eint_base + reg_mask); mask |= 1 << irqd->hwirq; - writel(mask, d->virt_base + reg_mask); + writel(mask, bank->eint_base + reg_mask); spin_unlock_irqrestore(&bank->slock, flags); } @@ -80,10 +79,9 @@ static void exynos_irq_ack(struct irq_data *irqd) struct irq_chip *chip = irq_data_get_irq_chip(irqd); struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long reg_pend = our_chip->eint_pend + bank->eint_offset; - writel(1 << irqd->hwirq, d->virt_base + reg_pend); + writel(1 << irqd->hwirq, bank->eint_base + reg_pend); } static void exynos_irq_unmask(struct irq_data *irqd) @@ -91,7 +89,6 @@ static void exynos_irq_unmask(struct irq_data *irqd) struct irq_chip *chip = irq_data_get_irq_chip(irqd); struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long reg_mask = our_chip->eint_mask + bank->eint_offset; unsigned long mask; unsigned long flags; @@ -109,9 +106,9 @@ static void exynos_irq_unmask(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - mask = readl(d->virt_base + reg_mask); + mask = readl(bank->eint_base + reg_mask); mask &= ~(1 << irqd->hwirq); - writel(mask, d->virt_base + reg_mask); + writel(mask, bank->eint_base + reg_mask); spin_unlock_irqrestore(&bank->slock, flags); } @@ -121,7 +118,6 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type) struct irq_chip *chip = irq_data_get_irq_chip(irqd); struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned int con, trig_type; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; @@ -152,10 +148,10 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type) else irq_set_handler_locked(irqd, handle_level_irq); - con = readl(d->virt_base + reg_con); + con = readl(bank->eint_base + reg_con); con &= ~(EXYNOS_EINT_CON_MASK << shift); con |= trig_type << shift; - writel(con, d->virt_base + reg_con); + writel(con, bank->eint_base + reg_con); return 0; } @@ -166,7 +162,6 @@ static int exynos_irq_request_resources(struct irq_data *irqd) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); const struct samsung_pin_bank_type *bank_type = bank->type; - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; unsigned long flags; @@ -188,10 +183,10 @@ static int exynos_irq_request_resources(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - con = readl(d->virt_base + reg_con); + con = readl(bank->eint_base + reg_con); con &= ~(mask << shift); con |= EXYNOS_EINT_FUNC << shift; - writel(con, d->virt_base + reg_con); + writel(con, bank->eint_base + reg_con); spin_unlock_irqrestore(&bank->slock, flags); @@ -206,7 +201,6 @@ static void exynos_irq_release_resources(struct irq_data *irqd) struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip); struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); const struct samsung_pin_bank_type *bank_type = bank->type; - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq; unsigned long reg_con = our_chip->eint_con + bank->eint_offset; unsigned long flags; @@ -221,10 +215,10 @@ static void exynos_irq_release_resources(struct irq_data *irqd) spin_lock_irqsave(&bank->slock, flags); - con = readl(d->virt_base + reg_con); + con = readl(bank->eint_base + reg_con); con &= ~(mask << shift); con |= FUNC_INPUT << shift; - writel(con, d->virt_base + reg_con); + writel(con, bank->eint_base + reg_con); spin_unlock_irqrestore(&bank->slock, flags); @@ -274,7 +268,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data) struct samsung_pin_bank *bank = d->pin_banks; unsigned int svc, group, pin, virq; - svc = readl(d->virt_base + EXYNOS_SVC_OFFSET); + svc = readl(bank->eint_base + EXYNOS_SVC_OFFSET); group = EXYNOS_SVC_GROUP(svc); pin = svc & EXYNOS_SVC_NUM_MASK; @@ -452,7 +446,6 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct exynos_muxed_weint_data *eintd = irq_desc_get_handler_data(desc); - struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata; unsigned long pend; unsigned long mask; int i; @@ -461,9 +454,9 @@ static void exynos_irq_demux_eint16_31(struct irq_desc *desc) for (i = 0; i < eintd->nr_banks; ++i) { struct samsung_pin_bank *b = eintd->banks[i]; - pend = readl(d->virt_base + b->irq_chip->eint_pend + pend = readl(b->eint_base + b->irq_chip->eint_pend + b->eint_offset); - mask = readl(d->virt_base + b->irq_chip->eint_mask + mask = readl(b->eint_base + b->irq_chip->eint_mask + b->eint_offset); exynos_irq_demux_eint(pend & ~mask, b->irq_domain); } @@ -581,7 +574,7 @@ static void exynos_pinctrl_suspend_bank( struct samsung_pin_bank *bank) { struct exynos_eint_gpio_save *save = bank->soc_priv; - void __iomem *regs = drvdata->virt_base; + void __iomem *regs = bank->eint_base; save->eint_con = readl(regs + EXYNOS_GPIO_ECON_OFFSET + bank->eint_offset); @@ -610,7 +603,7 @@ static void exynos_pinctrl_resume_bank( struct samsung_pin_bank *bank) { struct exynos_eint_gpio_save *save = bank->soc_priv; - void __iomem *regs = drvdata->virt_base; + void __iomem *regs = bank->eint_base; pr_debug("%s: con %#010x => %#010x\n", bank->name, readl(regs + EXYNOS_GPIO_ECON_OFFSET diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.h b/drivers/pinctrl/samsung/pinctrl-exynos.h index 0f0f7cedb2dc..5821525a2c84 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.h +++ b/drivers/pinctrl/samsung/pinctrl-exynos.h @@ -79,6 +79,17 @@ .name = id \ } +#define EXYNOS_PIN_BANK_EINTW_EXT(pins, reg, id, offs, pctl_idx) \ + { \ + .type = &bank_type_alive, \ + .pctl_offset = reg, \ + .nr_pins = pins, \ + .eint_type = EINT_TYPE_WKUP, \ + .eint_offset = offs, \ + .name = id, \ + .pctl_res_idx = pctl_idx, \ + } \ + /** * struct exynos_weint_data: irq specific data for all the wakeup interrupts * generated by the external wakeup interrupt controller. diff --git a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c index 3d92f827da7a..b82a003546ae 100644 --- a/drivers/pinctrl/samsung/pinctrl-s3c24xx.c +++ b/drivers/pinctrl/samsung/pinctrl-s3c24xx.c @@ -151,7 +151,7 @@ static void s3c24xx_eint_set_function(struct samsung_pinctrl_drv_data *d, u32 val; /* Make sure that pin is configured as interrupt */ - reg = d->virt_base + bank->pctl_offset; + reg = bank->pctl_base + bank->pctl_offset; shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC]; mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1; @@ -184,7 +184,7 @@ static int s3c24xx_eint_type(struct irq_data *data, unsigned int type) s3c24xx_eint_set_handler(data, type); /* Set up interrupt trigger */ - reg = d->virt_base + EINT_REG(index); + reg = bank->eint_base + EINT_REG(index); shift = EINT_OFFS(index); val = readl(reg); @@ -259,32 +259,29 @@ static void s3c2410_demux_eint0_3(struct irq_desc *desc) static void s3c2412_eint0_3_ack(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long bitval = 1UL << data->hwirq; - writel(bitval, d->virt_base + EINTPEND_REG); + writel(bitval, bank->eint_base + EINTPEND_REG); } static void s3c2412_eint0_3_mask(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long mask; - mask = readl(d->virt_base + EINTMASK_REG); + mask = readl(bank->eint_base + EINTMASK_REG); mask |= (1UL << data->hwirq); - writel(mask, d->virt_base + EINTMASK_REG); + writel(mask, bank->eint_base + EINTMASK_REG); } static void s3c2412_eint0_3_unmask(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned long mask; - mask = readl(d->virt_base + EINTMASK_REG); + mask = readl(bank->eint_base + EINTMASK_REG); mask &= ~(1UL << data->hwirq); - writel(mask, d->virt_base + EINTMASK_REG); + writel(mask, bank->eint_base + EINTMASK_REG); } static struct irq_chip s3c2412_eint0_3_chip = { @@ -319,34 +316,31 @@ static void s3c2412_demux_eint0_3(struct irq_desc *desc) static void s3c24xx_eint_ack(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned char index = bank->eint_offset + data->hwirq; - writel(1UL << index, d->virt_base + EINTPEND_REG); + writel(1UL << index, bank->eint_base + EINTPEND_REG); } static void s3c24xx_eint_mask(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned char index = bank->eint_offset + data->hwirq; unsigned long mask; - mask = readl(d->virt_base + EINTMASK_REG); + mask = readl(bank->eint_base + EINTMASK_REG); mask |= (1UL << index); - writel(mask, d->virt_base + EINTMASK_REG); + writel(mask, bank->eint_base + EINTMASK_REG); } static void s3c24xx_eint_unmask(struct irq_data *data) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(data); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned char index = bank->eint_offset + data->hwirq; unsigned long mask; - mask = readl(d->virt_base + EINTMASK_REG); + mask = readl(bank->eint_base + EINTMASK_REG); mask &= ~(1UL << index); - writel(mask, d->virt_base + EINTMASK_REG); + writel(mask, bank->eint_base + EINTMASK_REG); } static struct irq_chip s3c24xx_eint_chip = { @@ -362,13 +356,14 @@ static inline void s3c24xx_demux_eint(struct irq_desc *desc, { struct s3c24xx_eint_data *data = irq_desc_get_handler_data(desc); struct irq_chip *chip = irq_desc_get_chip(desc); - struct samsung_pinctrl_drv_data *d = data->drvdata; + struct irq_data *irqd = irq_desc_get_irq_data(desc); + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); unsigned int pend, mask; chained_irq_enter(chip, desc); - pend = readl(d->virt_base + EINTPEND_REG); - mask = readl(d->virt_base + EINTMASK_REG); + pend = readl(bank->eint_base + EINTPEND_REG); + mask = readl(bank->eint_base + EINTMASK_REG); pend &= ~mask; pend &= range; diff --git a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c index 43407ab248f5..4c632812ccff 100644 --- a/drivers/pinctrl/samsung/pinctrl-s3c64xx.c +++ b/drivers/pinctrl/samsung/pinctrl-s3c64xx.c @@ -280,7 +280,7 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d, u32 val; /* Make sure that pin is configured as interrupt */ - reg = d->virt_base + bank->pctl_offset; + reg = bank->pctl_base + bank->pctl_offset; shift = pin; if (bank_type->fld_width[PINCFG_TYPE_FUNC] * shift >= 32) { /* 4-bit bank type with 2 con regs */ @@ -308,9 +308,8 @@ static void s3c64xx_irq_set_function(struct samsung_pinctrl_drv_data *d, static inline void s3c64xx_gpio_irq_set_mask(struct irq_data *irqd, bool mask) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; - void __iomem *reg = d->virt_base + EINTMASK_REG(bank->eint_offset); + void __iomem *reg = bank->eint_base + EINTMASK_REG(bank->eint_offset); u32 val; val = readl(reg); @@ -334,9 +333,8 @@ static void s3c64xx_gpio_irq_mask(struct irq_data *irqd) static void s3c64xx_gpio_irq_ack(struct irq_data *irqd) { struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = bank->drvdata; unsigned char index = EINT_OFFS(bank->eint_offset) + irqd->hwirq; - void __iomem *reg = d->virt_base + EINTPEND_REG(bank->eint_offset); + void __iomem *reg = bank->eint_base + EINTPEND_REG(bank->eint_offset); writel(1 << index, reg); } @@ -359,7 +357,7 @@ static int s3c64xx_gpio_irq_set_type(struct irq_data *irqd, unsigned int type) s3c64xx_irq_set_handler(irqd, type); /* Set up interrupt trigger */ - reg = d->virt_base + EINTCON_REG(bank->eint_offset); + reg = bank->eint_base + EINTCON_REG(bank->eint_offset); shift = EINT_OFFS(bank->eint_offset) + irqd->hwirq; shift = 4 * (shift / 4); /* 4 EINTs per trigger selector */ @@ -411,7 +409,8 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc) { struct irq_chip *chip = irq_desc_get_chip(desc); struct s3c64xx_eint_gpio_data *data = irq_desc_get_handler_data(desc); - struct samsung_pinctrl_drv_data *drvdata = data->drvdata; + struct irq_data *irqd = irq_desc_get_irq_data(desc); + struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd); chained_irq_enter(chip, desc); @@ -421,7 +420,7 @@ static void s3c64xx_eint_gpio_irq(struct irq_desc *desc) unsigned int pin; unsigned int virq; - svc = readl(drvdata->virt_base + SERVICE_REG); + svc = readl(bank->eint_base + SERVICE_REG); group = SVC_GROUP(svc); pin = svc & SVC_NUM_MASK; @@ -518,15 +517,15 @@ static inline void s3c64xx_eint0_irq_set_mask(struct irq_data *irqd, bool mask) { struct s3c64xx_eint0_domain_data *ddata = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; + struct samsung_pin_bank *bank = ddata->bank; u32 val; - val = readl(d->virt_base + EINT0MASK_REG); + val = readl(bank->eint_base + EINT0MASK_REG); if (mask) val |= 1 << ddata->eints[irqd->hwirq]; else val &= ~(1 << ddata->eints[irqd->hwirq]); - writel(val, d->virt_base + EINT0MASK_REG); + writel(val, bank->eint_base + EINT0MASK_REG); } static void s3c64xx_eint0_irq_unmask(struct irq_data *irqd) @@ -543,10 +542,10 @@ static void s3c64xx_eint0_irq_ack(struct irq_data *irqd) { struct s3c64xx_eint0_domain_data *ddata = irq_data_get_irq_chip_data(irqd); - struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; + struct samsung_pin_bank *bank = ddata->bank; writel(1 << ddata->eints[irqd->hwirq], - d->virt_base + EINT0PEND_REG); + bank->eint_base + EINT0PEND_REG); } static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type) @@ -554,7 +553,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type) struct s3c64xx_eint0_domain_data *ddata = irq_data_get_irq_chip_data(irqd); struct samsung_pin_bank *bank = ddata->bank; - struct samsung_pinctrl_drv_data *d = bank->drvdata; + struct samsung_pinctrl_drv_data *d = ddata->bank->drvdata; void __iomem *reg; int trigger; u8 shift; @@ -569,7 +568,7 @@ static int s3c64xx_eint0_irq_set_type(struct irq_data *irqd, unsigned int type) s3c64xx_irq_set_handler(irqd, type); /* Set up interrupt trigger */ - reg = d->virt_base + EINT0CON0_REG; + reg = bank->eint_base + EINT0CON0_REG; shift = ddata->eints[irqd->hwirq]; if (shift >= EINT_MAX_PER_REG) { reg += 4; @@ -601,14 +600,19 @@ static struct irq_chip s3c64xx_eint0_irq_chip = { static inline void s3c64xx_irq_demux_eint(struct irq_desc *desc, u32 range) { struct irq_chip *chip = irq_desc_get_chip(desc); + struct irq_data *irqd = irq_desc_get_irq_data(desc); + struct s3c64xx_eint0_domain_data *ddata = + irq_data_get_irq_chip_data(irqd); + struct samsung_pin_bank *bank = ddata->bank; + struct s3c64xx_eint0_data *data = irq_desc_get_handler_data(desc); - struct samsung_pinctrl_drv_data *drvdata = data->drvdata; + unsigned int pend, mask; chained_irq_enter(chip, desc); - pend = readl(drvdata->virt_base + EINT0PEND_REG); - mask = readl(drvdata->virt_base + EINT0MASK_REG); + pend = readl(bank->eint_base + EINT0PEND_REG); + mask = readl(bank->eint_base + EINT0MASK_REG); pend = pend & range & ~mask; pend &= range; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 620727fabe64..41e62391c33c 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -33,6 +33,9 @@ #include "../core.h" #include "pinctrl-samsung.h" +/* maximum number of the memory resources */ +#define SAMSUNG_PINCTRL_NUM_RESOURCES 2 + /* list of all possible config options supported */ static struct pin_config { const char *property; @@ -345,7 +348,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, ((b->pin_base + b->nr_pins - 1) < pin)) b++; - *reg = drvdata->virt_base + b->pctl_offset; + *reg = b->pctl_base + b->pctl_offset; *offset = pin - b->pin_base; if (bank) *bank = b; @@ -526,7 +529,7 @@ static void samsung_gpio_set_value(struct gpio_chip *gc, void __iomem *reg; u32 data; - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->pctl_base + bank->pctl_offset; data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data &= ~(1 << offset); @@ -554,7 +557,7 @@ static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) struct samsung_pin_bank *bank = gpiochip_get_data(gc); const struct samsung_pin_bank_type *type = bank->type; - reg = bank->drvdata->virt_base + bank->pctl_offset; + reg = bank->pctl_base + bank->pctl_offset; data = readl(reg + type->reg_offset[PINCFG_TYPE_DAT]); data >>= offset; @@ -581,8 +584,8 @@ static int samsung_gpio_set_direction(struct gpio_chip *gc, type = bank->type; drvdata = bank->drvdata; - reg = drvdata->virt_base + bank->pctl_offset + - type->reg_offset[PINCFG_TYPE_FUNC]; + reg = bank->pctl_base + bank->pctl_offset + + type->reg_offset[PINCFG_TYPE_FUNC]; mask = (1 << type->fld_width[PINCFG_TYPE_FUNC]) - 1; shift = offset * type->fld_width[PINCFG_TYPE_FUNC]; @@ -979,6 +982,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, const struct samsung_pin_bank_data *bdata; const struct samsung_pin_ctrl *ctrl; struct samsung_pin_bank *bank; + struct resource *res; + void __iomem *virt_base[SAMSUNG_PINCTRL_NUM_RESOURCES]; int i; id = of_alias_get_id(node, "pinctrl"); @@ -997,6 +1002,17 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, if (!d->pin_banks) return ERR_PTR(-ENOMEM); + if (ctrl->nr_ext_resources + 1 > SAMSUNG_PINCTRL_NUM_RESOURCES) + return ERR_PTR(-EINVAL); + + for (i = 0; i < ctrl->nr_ext_resources + 1; i++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + virt_base[i] = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (IS_ERR(virt_base[i])) + return ERR_PTR(-EIO); + } + bank = d->pin_banks; bdata = ctrl->pin_banks; for (i = 0; i < ctrl->nr_banks; ++i, ++bdata, ++bank) { @@ -1013,6 +1029,9 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, bank->drvdata = d; bank->pin_base = d->nr_pins; d->nr_pins += bank->nr_pins; + + bank->eint_base = virt_base[0]; + bank->pctl_base = virt_base[bdata->pctl_res_idx]; } for_each_child_of_node(node, np) { @@ -1052,11 +1071,6 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) } drvdata->dev = dev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - drvdata->virt_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(drvdata->virt_base)) - return PTR_ERR(drvdata->virt_base); - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (res) drvdata->irq = res->start; @@ -1094,12 +1108,11 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) static void samsung_pinctrl_suspend_dev( struct samsung_pinctrl_drv_data *drvdata) { - void __iomem *virt_base = drvdata->virt_base; int i; for (i = 0; i < drvdata->nr_banks; i++) { struct samsung_pin_bank *bank = &drvdata->pin_banks[i]; - void __iomem *reg = virt_base + bank->pctl_offset; + void __iomem *reg = bank->pctl_base + bank->pctl_offset; const u8 *offs = bank->type->reg_offset; const u8 *widths = bank->type->fld_width; enum pincfg_type type; @@ -1140,7 +1153,6 @@ static void samsung_pinctrl_suspend_dev( */ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) { - void __iomem *virt_base = drvdata->virt_base; int i; if (drvdata->resume) @@ -1148,7 +1160,7 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) for (i = 0; i < drvdata->nr_banks; i++) { struct samsung_pin_bank *bank = &drvdata->pin_banks[i]; - void __iomem *reg = virt_base + bank->pctl_offset; + void __iomem *reg = bank->pctl_base + bank->pctl_offset; const u8 *offs = bank->type->reg_offset; const u8 *widths = bank->type->fld_width; enum pincfg_type type; diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h index cd31bfaf62cb..043cb6c11180 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.h +++ b/drivers/pinctrl/samsung/pinctrl-samsung.h @@ -116,6 +116,7 @@ struct samsung_pin_bank_type { * struct samsung_pin_bank_data: represent a controller pin-bank (init data). * @type: type of the bank (register offsets and bitfield widths) * @pctl_offset: starting offset of the pin-bank registers. + * @pctl_res_idx: index of base address for pin-bank registers. * @nr_pins: number of pins included in this bank. * @eint_func: function to set in CON register to configure pin as EINT. * @eint_type: type of the external interrupt supported by the bank. @@ -126,6 +127,7 @@ struct samsung_pin_bank_type { struct samsung_pin_bank_data { const struct samsung_pin_bank_type *type; u32 pctl_offset; + u8 pctl_res_idx; u8 nr_pins; u8 eint_func; enum eint_type eint_type; @@ -137,8 +139,10 @@ struct samsung_pin_bank_data { /** * struct samsung_pin_bank: represent a controller pin-bank. * @type: type of the bank (register offsets and bitfield widths) + * @pctl_base: base address of the pin-bank registers * @pctl_offset: starting offset of the pin-bank registers. * @nr_pins: number of pins included in this bank. + * @eint_base: base address of the pin-bank EINT registers. * @eint_func: function to set in CON register to configure pin as EINT. * @eint_type: type of the external interrupt supported by the bank. * @eint_mask: bit mask of pins which support EINT function. @@ -157,8 +161,10 @@ struct samsung_pin_bank_data { */ struct samsung_pin_bank { const struct samsung_pin_bank_type *type; + void __iomem *pctl_base; u32 pctl_offset; u8 nr_pins; + void __iomem *eint_base; u8 eint_func; enum eint_type eint_type; u32 eint_mask; @@ -182,6 +188,7 @@ struct samsung_pin_bank { * struct samsung_pin_ctrl: represent a pin controller. * @pin_banks: list of pin banks included in this controller. * @nr_banks: number of pin banks. + * @nr_ext_resources: number of the extra base address for pin banks. * @eint_gpio_init: platform specific callback to setup the external gpio * interrupts for the controller. * @eint_wkup_init: platform specific callback to setup the external wakeup @@ -190,6 +197,7 @@ struct samsung_pin_bank { struct samsung_pin_ctrl { const struct samsung_pin_bank_data *pin_banks; u32 nr_banks; + int nr_ext_resources; int (*eint_gpio_init)(struct samsung_pinctrl_drv_data *); int (*eint_wkup_init)(struct samsung_pinctrl_drv_data *); @@ -200,7 +208,6 @@ struct samsung_pin_ctrl { /** * struct samsung_pinctrl_drv_data: wrapper for holding driver data together. * @node: global list node - * @virt_base: register base address of the controller. * @dev: device instance representing the controller. * @irq: interrpt number used by the controller to notify gpio interrupts. * @ctrl: pin controller instance managed by the driver. @@ -215,7 +222,6 @@ struct samsung_pin_ctrl { */ struct samsung_pinctrl_drv_data { struct list_head node; - void __iomem *virt_base; struct device *dev; int irq; -- cgit 1.4.1 From ac8130e94c94a7afd779cf158d684807dab18ce5 Mon Sep 17 00:00:00 2001 From: Chanwoo Choi Date: Wed, 9 Nov 2016 17:40:11 +0900 Subject: pinctrl: samsung: Add GPF support for Exynos5433 This patch add the support of GPF[1-5] pin of Exynos5433 SoC. The GPFx need to support the multiple memory map because the registers of GPFx are located in the different domain. Cc: Linus Walleij Cc: Rob Herring Cc: Mark Rutland Cc: Tomasz Figa Cc: Krzysztof Kozlowski Cc: Sylwester Nawrocki Cc: Kukjin Kim Cc: linux-gpio@vger.kernel.org Signed-off-by: Joonyoung Shim Signed-off-by: Chanwoo Choi Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/samsung-pinctrl.txt | 19 +++++++++++++++++++ drivers/pinctrl/samsung/pinctrl-exynos.c | 6 ++++++ 2 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt index d49e22d2a8b5..1baf19eecabf 100644 --- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt @@ -19,11 +19,30 @@ Required Properties: - "samsung,exynos5260-pinctrl": for Exynos5260 compatible pin-controller. - "samsung,exynos5410-pinctrl": for Exynos5410 compatible pin-controller. - "samsung,exynos5420-pinctrl": for Exynos5420 compatible pin-controller. + - "samsung,exynos5433-pinctrl": for Exynos5433 compatible pin-controller. - "samsung,exynos7-pinctrl": for Exynos7 compatible pin-controller. - reg: Base address of the pin controller hardware module and length of the address space it occupies. + - reg: Second base address of the pin controller if the specific registers + of the pin controller are separated into the different base address. + + Eg: GPF[1-5] of Exynos5433 are separated into the two base address. + - First base address is for GPAx and GPF[1-5] external interrupt + registers. + - Second base address is for GPF[1-5] pinctrl registers. + + pinctrl_0: pinctrl@10580000 { + compatible = "samsung,exynos5433-pinctrl"; + reg = <0x10580000 0x1a20>, <0x11090000 0x100>; + + wakeup-interrupt-controller { + compatible = "samsung,exynos7-wakeup-eint"; + interrupts = <0 16 0>; + }; + }; + - Pin banks as child nodes: Pin banks of the controller are represented by child nodes of the controller node. Bank name is taken from name of the node. Each bank node must contain following properties: diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c index d657b52dfdb5..12f7d1eb65bc 100644 --- a/drivers/pinctrl/samsung/pinctrl-exynos.c +++ b/drivers/pinctrl/samsung/pinctrl-exynos.c @@ -1339,6 +1339,11 @@ static const struct samsung_pin_bank_data exynos5433_pin_banks0[] = { EXYNOS_PIN_BANK_EINTW(8, 0x020, "gpa1", 0x04), EXYNOS_PIN_BANK_EINTW(8, 0x040, "gpa2", 0x08), EXYNOS_PIN_BANK_EINTW(8, 0x060, "gpa3", 0x0c), + EXYNOS_PIN_BANK_EINTW_EXT(8, 0x020, "gpf1", 0x1004, 1), + EXYNOS_PIN_BANK_EINTW_EXT(4, 0x040, "gpf2", 0x1008, 1), + EXYNOS_PIN_BANK_EINTW_EXT(4, 0x060, "gpf3", 0x100c, 1), + EXYNOS_PIN_BANK_EINTW_EXT(8, 0x080, "gpf4", 0x1010, 1), + EXYNOS_PIN_BANK_EINTW_EXT(8, 0x0a0, "gpf5", 0x1014, 1), }; /* pin banks of exynos5433 pin-controller - AUD */ @@ -1420,6 +1425,7 @@ const struct samsung_pin_ctrl exynos5433_pin_ctrl[] = { .eint_wkup_init = exynos_eint_wkup_init, .suspend = exynos_pinctrl_suspend, .resume = exynos_pinctrl_resume, + .nr_ext_resources = 1, }, { /* pin-controller instance 1 data */ .pin_banks = exynos5433_pin_banks1, -- cgit 1.4.1 From 23d511f6fe3fb7d869539abbd1c0638b745e6560 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 9 Nov 2016 10:45:58 -0500 Subject: pinctrl: vt8500: make bool drivers explicitly non-modular None of the Kconfigs for any of these drivers are tristate, meaning that they currently are not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the drivers there is no doubt they are builtin-only. All drivers get the exact same change, so they are handled in batch. Changes are (1) use builtin_platform_driver, (2) use init.h header (3) delete module_exit related code, (4) delete MODULE_DEVICE_TABLE, (5) delete MODULE_LICENCE/MODULE_AUTHOR and associated tags and (6) drop ".remove" code and prevent sysfs unbind attempts to call ".remove". Once this is done, the shared remove function in wmt.[ch] is no longer used and hence it is removed as well. Since module_platform_driver() uses the same init level priority as builtin_platform_driver() the init ordering remains unchanged with this commit. Also note that MODULE_DEVICE_TABLE is a no-op for non-modular code. We also delete the MODULE_LICENSE etc. tags since all that information is already contained at the top of each file in the comments. Cc: Tony Prisk Cc: Linus Walleij Cc: linux-gpio@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: Linus Walleij --- drivers/pinctrl/vt8500/pinctrl-vt8500.c | 17 +++-------------- drivers/pinctrl/vt8500/pinctrl-wm8505.c | 17 +++-------------- drivers/pinctrl/vt8500/pinctrl-wm8650.c | 17 +++-------------- drivers/pinctrl/vt8500/pinctrl-wm8750.c | 17 +++-------------- drivers/pinctrl/vt8500/pinctrl-wm8850.c | 17 +++-------------- drivers/pinctrl/vt8500/pinctrl-wmt.c | 10 ---------- drivers/pinctrl/vt8500/pinctrl-wmt.h | 1 - 7 files changed, 15 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/vt8500/pinctrl-vt8500.c b/drivers/pinctrl/vt8500/pinctrl-vt8500.c index ca946b3dbdb4..767f340d6b11 100644 --- a/drivers/pinctrl/vt8500/pinctrl-vt8500.c +++ b/drivers/pinctrl/vt8500/pinctrl-vt8500.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -473,11 +473,6 @@ static int vt8500_pinctrl_probe(struct platform_device *pdev) return wmt_pinctrl_probe(pdev, data); } -static int vt8500_pinctrl_remove(struct platform_device *pdev) -{ - return wmt_pinctrl_remove(pdev); -} - static const struct of_device_id wmt_pinctrl_of_match[] = { { .compatible = "via,vt8500-pinctrl" }, { /* sentinel */ }, @@ -485,16 +480,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = { static struct platform_driver wmt_pinctrl_driver = { .probe = vt8500_pinctrl_probe, - .remove = vt8500_pinctrl_remove, .driver = { .name = "pinctrl-vt8500", .of_match_table = wmt_pinctrl_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(wmt_pinctrl_driver); - -MODULE_AUTHOR("Tony Prisk "); -MODULE_DESCRIPTION("VIA VT8500 Pincontrol driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); +builtin_platform_driver(wmt_pinctrl_driver); diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8505.c b/drivers/pinctrl/vt8500/pinctrl-wm8505.c index 626fc7ec0174..a56fdbd87e42 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wm8505.c +++ b/drivers/pinctrl/vt8500/pinctrl-wm8505.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -504,11 +504,6 @@ static int wm8505_pinctrl_probe(struct platform_device *pdev) return wmt_pinctrl_probe(pdev, data); } -static int wm8505_pinctrl_remove(struct platform_device *pdev) -{ - return wmt_pinctrl_remove(pdev); -} - static const struct of_device_id wmt_pinctrl_of_match[] = { { .compatible = "wm,wm8505-pinctrl" }, { /* sentinel */ }, @@ -516,16 +511,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = { static struct platform_driver wmt_pinctrl_driver = { .probe = wm8505_pinctrl_probe, - .remove = wm8505_pinctrl_remove, .driver = { .name = "pinctrl-wm8505", .of_match_table = wmt_pinctrl_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(wmt_pinctrl_driver); - -MODULE_AUTHOR("Tony Prisk "); -MODULE_DESCRIPTION("Wondermedia WM8505 Pincontrol driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); +builtin_platform_driver(wmt_pinctrl_driver); diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8650.c b/drivers/pinctrl/vt8500/pinctrl-wm8650.c index 8953aba8bfc2..270dd491f5a1 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wm8650.c +++ b/drivers/pinctrl/vt8500/pinctrl-wm8650.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -342,11 +342,6 @@ static int wm8650_pinctrl_probe(struct platform_device *pdev) return wmt_pinctrl_probe(pdev, data); } -static int wm8650_pinctrl_remove(struct platform_device *pdev) -{ - return wmt_pinctrl_remove(pdev); -} - static const struct of_device_id wmt_pinctrl_of_match[] = { { .compatible = "wm,wm8650-pinctrl" }, { /* sentinel */ }, @@ -354,16 +349,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = { static struct platform_driver wmt_pinctrl_driver = { .probe = wm8650_pinctrl_probe, - .remove = wm8650_pinctrl_remove, .driver = { .name = "pinctrl-wm8650", .of_match_table = wmt_pinctrl_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(wmt_pinctrl_driver); - -MODULE_AUTHOR("Tony Prisk "); -MODULE_DESCRIPTION("Wondermedia WM8650 Pincontrol driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); +builtin_platform_driver(wmt_pinctrl_driver); diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8750.c b/drivers/pinctrl/vt8500/pinctrl-wm8750.c index c79053d430db..74f7b3a18f3a 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wm8750.c +++ b/drivers/pinctrl/vt8500/pinctrl-wm8750.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -381,11 +381,6 @@ static int wm8750_pinctrl_probe(struct platform_device *pdev) return wmt_pinctrl_probe(pdev, data); } -static int wm8750_pinctrl_remove(struct platform_device *pdev) -{ - return wmt_pinctrl_remove(pdev); -} - static const struct of_device_id wmt_pinctrl_of_match[] = { { .compatible = "wm,wm8750-pinctrl" }, { /* sentinel */ }, @@ -393,16 +388,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = { static struct platform_driver wmt_pinctrl_driver = { .probe = wm8750_pinctrl_probe, - .remove = wm8750_pinctrl_remove, .driver = { .name = "pinctrl-wm8750", .of_match_table = wmt_pinctrl_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(wmt_pinctrl_driver); - -MODULE_AUTHOR("Tony Prisk "); -MODULE_DESCRIPTION("Wondermedia WM8750 Pincontrol driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); +builtin_platform_driver(wmt_pinctrl_driver); diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8850.c b/drivers/pinctrl/vt8500/pinctrl-wm8850.c index f232b163c735..45792aa7a06e 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wm8850.c +++ b/drivers/pinctrl/vt8500/pinctrl-wm8850.c @@ -14,7 +14,7 @@ */ #include -#include +#include #include #include #include @@ -360,11 +360,6 @@ static int wm8850_pinctrl_probe(struct platform_device *pdev) return wmt_pinctrl_probe(pdev, data); } -static int wm8850_pinctrl_remove(struct platform_device *pdev) -{ - return wmt_pinctrl_remove(pdev); -} - static const struct of_device_id wmt_pinctrl_of_match[] = { { .compatible = "wm,wm8850-pinctrl" }, { /* sentinel */ }, @@ -372,16 +367,10 @@ static const struct of_device_id wmt_pinctrl_of_match[] = { static struct platform_driver wmt_pinctrl_driver = { .probe = wm8850_pinctrl_probe, - .remove = wm8850_pinctrl_remove, .driver = { .name = "pinctrl-wm8850", .of_match_table = wmt_pinctrl_of_match, + .suppress_bind_attrs = true, }, }; - -module_platform_driver(wmt_pinctrl_driver); - -MODULE_AUTHOR("Tony Prisk "); -MODULE_DESCRIPTION("Wondermedia WM8850 Pincontrol driver"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); +builtin_platform_driver(wmt_pinctrl_driver); diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c index cbc638631678..270ca2a47a8c 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.c +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -608,12 +607,3 @@ fail_range: gpiochip_remove(&data->gpio_chip); return err; } - -int wmt_pinctrl_remove(struct platform_device *pdev) -{ - struct wmt_pinctrl_data *data = platform_get_drvdata(pdev); - - gpiochip_remove(&data->gpio_chip); - - return 0; -} diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.h b/drivers/pinctrl/vt8500/pinctrl-wmt.h index 41f5f2deb5d6..885613396fe7 100644 --- a/drivers/pinctrl/vt8500/pinctrl-wmt.h +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.h @@ -76,4 +76,3 @@ struct wmt_pinctrl_data { int wmt_pinctrl_probe(struct platform_device *pdev, struct wmt_pinctrl_data *data); -int wmt_pinctrl_remove(struct platform_device *pdev); -- cgit 1.4.1 From 88f01a1bd0e0dbd01b65907023dbe53cf524ea2a Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 11 Nov 2016 10:35:10 +0800 Subject: pinctrl: sunxi: Free configs in pinctrl_map only if it is a config map In the recently refactored sunxi pinctrl library, we are only allocating one set of pin configs for each pinmux setting node. When the pinctrl_map structure is freed, the pin configs should also be freed. However the code assumed the first map would contain the configs, which actually never happens, as the mux function map gets added first. The proper way to do this is to look through all the maps and free the first one whose type is actually PIN_MAP_TYPE_CONFIGS_GROUP. Also slightly expand the comment explaining this. Fixes: f233dbca6227 ("pinctrl: sunxi: Rework the pin config building code") Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index ebe2c73d211e..e199d95af8c0 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -408,8 +408,21 @@ static void sunxi_pctrl_dt_free_map(struct pinctrl_dev *pctldev, struct pinctrl_map *map, unsigned num_maps) { - /* All the maps have the same pin config, free only the first one */ - kfree(map[0].data.configs.configs); + int i; + + /* pin config is never in the first map */ + for (i = 1; i < num_maps; i++) { + if (map[i].type != PIN_MAP_TYPE_CONFIGS_GROUP) + continue; + + /* + * All the maps share the same pin config, + * free only the first one we find. + */ + kfree(map[i].data.configs.configs); + break; + } + kfree(map); } -- cgit 1.4.1 From 223dba00b4072efc590c7d648f230db1b44186b9 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 11 Nov 2016 17:50:34 +0800 Subject: pinctrl: sunxi: Fix PIN_CONFIG_BIAS_PULL_{DOWN,UP} argument According to pinconf-generic.h, the argument for PIN_CONFIG_BIAS_PULL_{DOWN,UP} is non-zero if the bias is enabled with a pull up/down resistor, zero if it is directly connected to VDD or ground. Since Allwinner hardware uses a weak pull resistor internally, the argument should be 1. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index e199d95af8c0..e04edda8629d 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -291,12 +291,16 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node, if (sunxi_pctrl_has_bias_prop(node)) { int pull = sunxi_pctrl_parse_bias_prop(node); + int arg = 0; if (pull < 0) { ret = pull; goto err_free; } - pinconfig[idx++] = pinconf_to_config_packed(pull, 0); + if (pull != PIN_CONFIG_BIAS_DISABLE) + arg = 1; /* hardware uses weak pull resistors */ + + pinconfig[idx++] = pinconf_to_config_packed(pull, arg); } -- cgit 1.4.1 From c5fda170e87a4bdaeb278f7e50f7a1f654e94eb5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 11 Nov 2016 17:50:35 +0800 Subject: pinctrl: sunxi: Add support for fetching pinconf settings from hardware The sunxi pinctrl driver only caches whatever pinconf setting was last set on a given pingroup. This is not particularly helpful, nor is it correct. Fix this by actually reading the hardware registers and returning the correct results or error codes. Also filter out unsupported pinconf settings. Since this driver has a peculiar setup of 1 pin per group, we can support both pin and pingroup pinconf setting read back with the same code. The sunxi_pconf_reg helper and code structure is inspired by pinctrl-msm. With this done we can also claim to support generic pinconf, by setting .is_generic = true in pinconf_ops. Also remove the cached config value. The behavior of this was never correct, as it only cached 1 setting instead of all of them. Since we can now read back settings directly from the hardware, it is no longer required. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 86 +++++++++++++++++++++++++++++++++-- drivers/pinctrl/sunxi/pinctrl-sunxi.h | 1 - 2 files changed, 81 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index e04edda8629d..ed71bff39869 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -438,15 +438,91 @@ static const struct pinctrl_ops sunxi_pctrl_ops = { .get_group_pins = sunxi_pctrl_get_group_pins, }; +static int sunxi_pconf_reg(unsigned pin, enum pin_config_param param, + u32 *offset, u32 *shift, u32 *mask) +{ + switch (param) { + case PIN_CONFIG_DRIVE_STRENGTH: + *offset = sunxi_dlevel_reg(pin); + *shift = sunxi_dlevel_offset(pin); + *mask = DLEVEL_PINS_MASK; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + case PIN_CONFIG_BIAS_DISABLE: + *offset = sunxi_pull_reg(pin); + *shift = sunxi_pull_offset(pin); + *mask = PULL_PINS_MASK; + break; + + default: + return -ENOTSUPP; + } + + return 0; +} + +static int sunxi_pconf_get(struct pinctrl_dev *pctldev, unsigned pin, + unsigned long *config) +{ + struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param = pinconf_to_config_param(*config); + u32 offset, shift, mask, val; + u16 arg; + int ret; + + pin -= pctl->desc->pin_base; + + ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); + if (ret < 0) + return ret; + + val = (readl(pctl->membase + offset) >> shift) & mask; + + switch (pinconf_to_config_param(*config)) { + case PIN_CONFIG_DRIVE_STRENGTH: + arg = (val + 1) * 10; + break; + + case PIN_CONFIG_BIAS_PULL_UP: + if (val != SUN4I_PINCTRL_PULL_UP) + return -EINVAL; + arg = 1; /* hardware is weak pull-up */ + break; + + case PIN_CONFIG_BIAS_PULL_DOWN: + if (val != SUN4I_PINCTRL_PULL_DOWN) + return -EINVAL; + arg = 1; /* hardware is weak pull-down */ + break; + + case PIN_CONFIG_BIAS_DISABLE: + if (val != SUN4I_PINCTRL_NO_PULL) + return -EINVAL; + arg = 0; + break; + + default: + /* sunxi_pconf_reg should catch anything unsupported */ + WARN_ON(1); + return -ENOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + static int sunxi_pconf_group_get(struct pinctrl_dev *pctldev, unsigned group, unsigned long *config) { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); + struct sunxi_pinctrl_group *g = &pctl->groups[group]; - *config = pctl->groups[group].config; - - return 0; + /* We only support 1 pin per group. Chain it to the pin callback */ + return sunxi_pconf_get(pctldev, g->pin, config); } static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, @@ -508,8 +584,6 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, default: break; } - /* cache the config value */ - g->config = configs[i]; } /* for each config */ spin_unlock_irqrestore(&pctl->lock, flags); @@ -518,6 +592,8 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, } static const struct pinconf_ops sunxi_pconf_ops = { + .is_generic = true, + .pin_config_get = sunxi_pconf_get, .pin_config_group_get = sunxi_pconf_group_get, .pin_config_group_set = sunxi_pconf_group_set, }; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index 0afce1ab12d0..a7efb31d6523 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -109,7 +109,6 @@ struct sunxi_pinctrl_function { struct sunxi_pinctrl_group { const char *name; - unsigned long config; unsigned pin; }; -- cgit 1.4.1 From 51814827190214986c452a166718bf12d32211c7 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Fri, 11 Nov 2016 17:50:36 +0800 Subject: pinctrl: sunxi: Make sunxi_pconf_group_set use sunxi_pconf_reg helper The sunxi_pconf_reg helper introduced in the last patch gives us the chance to rework sunxi_pconf_group_set to have it match the structure of sunxi_pconf_(group_)get and make it easier to understand. For each config to set, it: 1. checks if the parameter is supported. 2. checks if the argument is within limits. 3. converts argument to the register value. 4. writes to the register with spinlock held. As a result the function now blocks unsupported config parameters, instead of silently ignoring them. Signed-off-by: Chen-Yu Tsai Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 64 +++++++++++++++++------------------ 1 file changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index ed71bff39869..fa11a3100346 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -532,23 +532,27 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, { struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); struct sunxi_pinctrl_group *g = &pctl->groups[group]; - unsigned long flags; unsigned pin = g->pin - pctl->desc->pin_base; - u32 val, mask; - u16 strength; - u8 dlevel; int i; - spin_lock_irqsave(&pctl->lock, flags); - for (i = 0; i < num_configs; i++) { - switch (pinconf_to_config_param(configs[i])) { + enum pin_config_param param; + unsigned long flags; + u32 offset, shift, mask, reg; + u16 arg, val; + int ret; + + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + ret = sunxi_pconf_reg(pin, param, &offset, &shift, &mask); + if (ret < 0) + return ret; + + switch (param) { case PIN_CONFIG_DRIVE_STRENGTH: - strength = pinconf_to_config_argument(configs[i]); - if (strength > 40) { - spin_unlock_irqrestore(&pctl->lock, flags); + if (arg < 10 || arg > 40) return -EINVAL; - } /* * We convert from mA to what the register expects: * 0: 10mA @@ -556,37 +560,33 @@ static int sunxi_pconf_group_set(struct pinctrl_dev *pctldev, * 2: 30mA * 3: 40mA */ - dlevel = strength / 10 - 1; - val = readl(pctl->membase + sunxi_dlevel_reg(pin)); - mask = DLEVEL_PINS_MASK << sunxi_dlevel_offset(pin); - writel((val & ~mask) - | dlevel << sunxi_dlevel_offset(pin), - pctl->membase + sunxi_dlevel_reg(pin)); + val = arg / 10 - 1; 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)); + val = 0; break; case PIN_CONFIG_BIAS_PULL_UP: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); - writel((val & ~mask) | 1 << sunxi_pull_offset(pin), - pctl->membase + sunxi_pull_reg(pin)); + if (arg == 0) + return -EINVAL; + val = 1; break; case PIN_CONFIG_BIAS_PULL_DOWN: - val = readl(pctl->membase + sunxi_pull_reg(pin)); - mask = PULL_PINS_MASK << sunxi_pull_offset(pin); - writel((val & ~mask) | 2 << sunxi_pull_offset(pin), - pctl->membase + sunxi_pull_reg(pin)); + if (arg == 0) + return -EINVAL; + val = 2; break; default: - break; + /* sunxi_pconf_reg should catch anything unsupported */ + WARN_ON(1); + return -ENOTSUPP; } - } /* for each config */ - spin_unlock_irqrestore(&pctl->lock, flags); + spin_lock_irqsave(&pctl->lock, flags); + reg = readl(pctl->membase + offset); + reg &= ~(mask << shift); + writel(reg | val << shift, pctl->membase + offset); + spin_unlock_irqrestore(&pctl->lock, flags); + } /* for each config */ return 0; } -- cgit 1.4.1 From 7c926492d38a3feef4b4b29c91b7c03eb1b8b546 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 14 Nov 2016 21:53:03 +0100 Subject: pinctrl: sunxi: Add support for interrupt debouncing The pin controller found in the Allwinner SoCs has support for interrupts debouncing. However, this is not done per-pin, preventing us from using the generic pinconf binding for that, but per irq bank, which, depending on the SoC, ranges from one to five. Introduce a device-wide property to deal with this using a microsecond resolution. We can re-use the per-pin input-debounce property for that, so let's do it! Signed-off-by: Maxime Ripard Acked-by: Rob Herring Signed-off-by: Linus Walleij --- .../bindings/pinctrl/allwinner,sunxi-pinctrl.txt | 14 ++++ drivers/pinctrl/sunxi/pinctrl-sunxi.c | 84 ++++++++++++++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 7 ++ 3 files changed, 105 insertions(+) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt index 35eef433e518..de1378b4efad 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sunxi-pinctrl.txt @@ -28,6 +28,20 @@ Required properties: - reg: Should contain the register physical address and length for the pin controller. +- clocks: phandle to the clocks feeding the pin controller: + - "apb": the gated APB parent clock + - "hosc": the high frequency oscillator in the system + - "losc": the low frequency oscillator in the system + +Note: For backward compatibility reasons, the hosc and losc clocks are only +required if you need to use the optional input-debounce property. Any new +device tree should set them. + +Optional properties: + - input-debounce: Array of debouncing periods in microseconds. One period per + irq bank found in the controller. 0 if no setup required. + + Please refer to pinctrl-bindings.txt in this directory for details of the common pinctrl bindings used by client devices. diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index fa11a3100346..2339d4718b4d 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1122,6 +1122,88 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) return 0; } +static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff) +{ + unsigned long clock = clk_get_rate(clk); + unsigned int best_diff = ~0, best_div; + int i; + + for (i = 0; i < 8; i++) { + int cur_diff = abs(freq - (clock >> i)); + + if (cur_diff < best_diff) { + best_diff = cur_diff; + best_div = i; + } + } + + *diff = best_diff; + return best_div; +} + +static int sunxi_pinctrl_setup_debounce(struct sunxi_pinctrl *pctl, + struct device_node *node) +{ + unsigned int hosc_diff, losc_diff; + unsigned int hosc_div, losc_div; + struct clk *hosc, *losc; + u8 div, src; + int i, ret; + + /* Deal with old DTs that didn't have the oscillators */ + if (of_count_phandle_with_args(node, "clocks", "#clock-cells") != 3) + return 0; + + /* If we don't have any setup, bail out */ + if (!of_find_property(node, "input-debounce", NULL)) + return 0; + + losc = devm_clk_get(pctl->dev, "losc"); + if (IS_ERR(losc)) + return PTR_ERR(losc); + + hosc = devm_clk_get(pctl->dev, "hosc"); + if (IS_ERR(hosc)) + return PTR_ERR(hosc); + + for (i = 0; i < pctl->desc->irq_banks; i++) { + unsigned long debounce_freq; + u32 debounce; + + ret = of_property_read_u32_index(node, "input-debounce", + i, &debounce); + if (ret) + return ret; + + if (!debounce) + continue; + + debounce_freq = DIV_ROUND_CLOSEST(USEC_PER_SEC, debounce); + losc_div = sunxi_pinctrl_get_debounce_div(losc, + debounce_freq, + &losc_diff); + + hosc_div = sunxi_pinctrl_get_debounce_div(hosc, + debounce_freq, + &hosc_diff); + + if (hosc_diff < losc_diff) { + div = hosc_div; + src = 1; + } else { + div = losc_div; + src = 0; + } + + writel(src | div << 4, + pctl->membase + + sunxi_irq_debounce_reg_from_bank(i, + pctl->desc->irq_bank_base)); + } + + return 0; +} + int sunxi_pinctrl_init(struct platform_device *pdev, const struct sunxi_pinctrl_desc *desc) { @@ -1284,6 +1366,8 @@ int sunxi_pinctrl_init(struct platform_device *pdev, pctl); } + sunxi_pinctrl_setup_debounce(pctl, node); + dev_info(&pdev->dev, "initialized sunXi PIO driver\n"); return 0; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a7efb31d6523..f78a44a03189 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -69,6 +69,8 @@ #define IRQ_STATUS_IRQ_BITS 1 #define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1) +#define IRQ_DEBOUNCE_REG 0x218 + #define IRQ_MEM_SIZE 0x20 #define IRQ_EDGE_RISING 0x00 @@ -265,6 +267,11 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq) return irq_num * IRQ_CTRL_IRQ_BITS; } +static inline u32 sunxi_irq_debounce_reg_from_bank(u8 bank, unsigned bank_base) +{ + return IRQ_DEBOUNCE_REG + (bank_base + bank) * IRQ_MEM_SIZE; +} + static inline u32 sunxi_irq_status_reg_from_bank(u8 bank, unsigned bank_base) { return IRQ_STATUS_REG + (bank_base + bank) * IRQ_MEM_SIZE; -- cgit 1.4.1 From 9c99a63ec74f34f7afef6a475a89062caf14bd86 Mon Sep 17 00:00:00 2001 From: Takeshi Kihara Date: Wed, 16 Mar 2016 11:44:19 +0900 Subject: pinctrl: sh-pfc: r8a7796: Add EtherAVB pins, groups and functions This patch adds AVB_LINK, AVB_MAGIC, AVB_PHY_INT, AVB_MDC, AVB_AVTP_PPS, AVB_AVTP_MATCH, AVB_AVTP_CAPTURE pins, groups and functions to R8A7796 SoC. Signed-off-by: Takeshi Kihara Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 87 ++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 57ddd394f8c5..593b3a67b1fd 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1490,6 +1490,71 @@ static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), }; +/* - EtherAVB --------------------------------------------------------------- */ +static const unsigned int avb_link_pins[] = { + /* AVB_LINK */ + RCAR_GP_PIN(2, 12), +}; +static const unsigned int avb_link_mux[] = { + AVB_LINK_MARK, +}; +static const unsigned int avb_magic_pins[] = { + /* AVB_MAGIC_ */ + RCAR_GP_PIN(2, 10), +}; +static const unsigned int avb_magic_mux[] = { + AVB_MAGIC_MARK, +}; +static const unsigned int avb_phy_int_pins[] = { + /* AVB_PHY_INT */ + RCAR_GP_PIN(2, 11), +}; +static const unsigned int avb_phy_int_mux[] = { + AVB_PHY_INT_MARK, +}; +static const unsigned int avb_mdc_pins[] = { + /* AVB_MDC */ + RCAR_GP_PIN(2, 9), +}; +static const unsigned int avb_mdc_mux[] = { + AVB_MDC_MARK, +}; +static const unsigned int avb_avtp_pps_pins[] = { + /* AVB_AVTP_PPS */ + RCAR_GP_PIN(2, 6), +}; +static const unsigned int avb_avtp_pps_mux[] = { + AVB_AVTP_PPS_MARK, +}; +static const unsigned int avb_avtp_match_a_pins[] = { + /* AVB_AVTP_MATCH_A */ + RCAR_GP_PIN(2, 13), +}; +static const unsigned int avb_avtp_match_a_mux[] = { + AVB_AVTP_MATCH_A_MARK, +}; +static const unsigned int avb_avtp_capture_a_pins[] = { + /* AVB_AVTP_CAPTURE_A */ + RCAR_GP_PIN(2, 14), +}; +static const unsigned int avb_avtp_capture_a_mux[] = { + AVB_AVTP_CAPTURE_A_MARK, +}; +static const unsigned int avb_avtp_match_b_pins[] = { + /* AVB_AVTP_MATCH_B */ + RCAR_GP_PIN(1, 8), +}; +static const unsigned int avb_avtp_match_b_mux[] = { + AVB_AVTP_MATCH_B_MARK, +}; +static const unsigned int avb_avtp_capture_b_pins[] = { + /* AVB_AVTP_CAPTURE_B */ + RCAR_GP_PIN(1, 11), +}; +static const unsigned int avb_avtp_capture_b_mux[] = { + AVB_AVTP_CAPTURE_B_MARK, +}; + /* - DRIF0 --------------------------------------------------------------- */ static const unsigned int drif0_ctrl_a_pins[] = { /* CLK, SYNC */ @@ -2178,6 +2243,15 @@ static const unsigned int sdhi3_ds_mux[] = { }; static const struct sh_pfc_pin_group pinmux_groups[] = { + SH_PFC_PIN_GROUP(avb_link), + SH_PFC_PIN_GROUP(avb_magic), + SH_PFC_PIN_GROUP(avb_phy_int), + SH_PFC_PIN_GROUP(avb_mdc), + SH_PFC_PIN_GROUP(avb_avtp_pps), + SH_PFC_PIN_GROUP(avb_avtp_match_a), + SH_PFC_PIN_GROUP(avb_avtp_capture_a), + SH_PFC_PIN_GROUP(avb_avtp_match_b), + SH_PFC_PIN_GROUP(avb_avtp_capture_b), SH_PFC_PIN_GROUP(drif0_ctrl_a), SH_PFC_PIN_GROUP(drif0_data0_a), SH_PFC_PIN_GROUP(drif0_data1_a), @@ -2272,6 +2346,18 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(sdhi3_ds), }; +static const char * const avb_groups[] = { + "avb_link", + "avb_magic", + "avb_phy_int", + "avb_mdc", + "avb_avtp_pps", + "avb_avtp_match_a", + "avb_avtp_capture_a", + "avb_avtp_match_b", + "avb_avtp_capture_b", +}; + static const char * const drif0_groups[] = { "drif0_ctrl_a", "drif0_data0_a", @@ -2419,6 +2505,7 @@ static const char * const sdhi3_groups[] = { }; static const struct sh_pfc_function pinmux_functions[] = { + SH_PFC_FUNCTION(avb), SH_PFC_FUNCTION(drif0), SH_PFC_FUNCTION(drif1), SH_PFC_FUNCTION(drif2), -- cgit 1.4.1 From cccc618a0b74867efb2211be6573ecf729a56ed0 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 11 Nov 2016 21:40:03 +0100 Subject: pinctrl: sh-pfc: r8a7796: Add DU support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only the DU parallel RGB output signals are included, HDMI and TCON pins will be added in separate groups. Based on a similar patch from Laurent Pinchart for the r8a7795 PFC driver. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7796.c | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c index 593b3a67b1fd..7e16545a2c3c 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7796.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7796.c @@ -1770,6 +1770,87 @@ static const unsigned int drif3_data1_b_mux[] = { RIF3_D1_B_MARK, }; +/* - DU --------------------------------------------------------------------- */ +static const unsigned int du_rgb666_pins[] = { + /* R[7:2], G[7:2], B[7:2] */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), + RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13), + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 19), RCAR_GP_PIN(1, 18), + RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 2), +}; +static const unsigned int du_rgb666_mux[] = { + DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK, + DU_DR3_MARK, DU_DR2_MARK, + DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK, + DU_DG3_MARK, DU_DG2_MARK, + DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK, + DU_DB3_MARK, DU_DB2_MARK, +}; +static const unsigned int du_rgb888_pins[] = { + /* R[7:0], G[7:0], B[7:0] */ + RCAR_GP_PIN(0, 15), RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 13), + RCAR_GP_PIN(0, 12), RCAR_GP_PIN(0, 11), RCAR_GP_PIN(0, 10), + RCAR_GP_PIN(0, 9), RCAR_GP_PIN(0, 8), + RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14), RCAR_GP_PIN(1, 13), + RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 19), RCAR_GP_PIN(1, 18), + RCAR_GP_PIN(1, 17), RCAR_GP_PIN(1, 16), + RCAR_GP_PIN(1, 7), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 5), + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 3), RCAR_GP_PIN(1, 2), + RCAR_GP_PIN(1, 1), RCAR_GP_PIN(1, 0), +}; +static const unsigned int du_rgb888_mux[] = { + DU_DR7_MARK, DU_DR6_MARK, DU_DR5_MARK, DU_DR4_MARK, + DU_DR3_MARK, DU_DR2_MARK, DU_DR1_MARK, DU_DR0_MARK, + DU_DG7_MARK, DU_DG6_MARK, DU_DG5_MARK, DU_DG4_MARK, + DU_DG3_MARK, DU_DG2_MARK, DU_DG1_MARK, DU_DG0_MARK, + DU_DB7_MARK, DU_DB6_MARK, DU_DB5_MARK, DU_DB4_MARK, + DU_DB3_MARK, DU_DB2_MARK, DU_DB1_MARK, DU_DB0_MARK, +}; +static const unsigned int du_clk_out_0_pins[] = { + /* CLKOUT */ + RCAR_GP_PIN(1, 27), +}; +static const unsigned int du_clk_out_0_mux[] = { + DU_DOTCLKOUT0_MARK +}; +static const unsigned int du_clk_out_1_pins[] = { + /* CLKOUT */ + RCAR_GP_PIN(2, 3), +}; +static const unsigned int du_clk_out_1_mux[] = { + DU_DOTCLKOUT1_MARK +}; +static const unsigned int du_sync_pins[] = { + /* EXVSYNC/VSYNC, EXHSYNC/HSYNC */ + RCAR_GP_PIN(2, 5), RCAR_GP_PIN(2, 4), +}; +static const unsigned int du_sync_mux[] = { + DU_EXVSYNC_DU_VSYNC_MARK, DU_EXHSYNC_DU_HSYNC_MARK +}; +static const unsigned int du_oddf_pins[] = { + /* EXDISP/EXODDF/EXCDE */ + RCAR_GP_PIN(2, 2), +}; +static const unsigned int du_oddf_mux[] = { + DU_EXODDF_DU_ODDF_DISP_CDE_MARK, +}; +static const unsigned int du_cde_pins[] = { + /* CDE */ + RCAR_GP_PIN(2, 0), +}; +static const unsigned int du_cde_mux[] = { + DU_CDE_MARK, +}; +static const unsigned int du_disp_pins[] = { + /* DISP */ + RCAR_GP_PIN(2, 1), +}; +static const unsigned int du_disp_mux[] = { + DU_DISP_MARK, +}; + /* - I2C -------------------------------------------------------------------- */ static const unsigned int i2c1_a_pins[] = { /* SDA, SCL */ @@ -2282,6 +2363,14 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(drif3_ctrl_b), SH_PFC_PIN_GROUP(drif3_data0_b), SH_PFC_PIN_GROUP(drif3_data1_b), + SH_PFC_PIN_GROUP(du_rgb666), + SH_PFC_PIN_GROUP(du_rgb888), + SH_PFC_PIN_GROUP(du_clk_out_0), + SH_PFC_PIN_GROUP(du_clk_out_1), + SH_PFC_PIN_GROUP(du_sync), + SH_PFC_PIN_GROUP(du_oddf), + SH_PFC_PIN_GROUP(du_cde), + SH_PFC_PIN_GROUP(du_disp), SH_PFC_PIN_GROUP(i2c1_a), SH_PFC_PIN_GROUP(i2c1_b), SH_PFC_PIN_GROUP(i2c2_a), @@ -2400,6 +2489,17 @@ static const char * const drif3_groups[] = { "drif3_data1_b", }; +static const char * const du_groups[] = { + "du_rgb666", + "du_rgb888", + "du_clk_out_0", + "du_clk_out_1", + "du_sync", + "du_oddf", + "du_cde", + "du_disp", +}; + static const char * const i2c1_groups[] = { "i2c1_a", "i2c1_b", @@ -2510,6 +2610,7 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(drif1), SH_PFC_FUNCTION(drif2), SH_PFC_FUNCTION(drif3), + SH_PFC_FUNCTION(du), SH_PFC_FUNCTION(i2c1), SH_PFC_FUNCTION(i2c2), SH_PFC_FUNCTION(i2c6), -- cgit 1.4.1 From 5d7400c4acbf7fe633a976a89ee845f7333de3e4 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:24 +0100 Subject: pinctrl: sh-pfc: Do not unconditionally support PIN_CONFIG_BIAS_DISABLE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always stating PIN_CONFIG_BIAS_DISABLE is supported gives untrue output when examining /sys/kernel/debug/pinctrl/e6060000.pfc/pinconf-pins if the operation get_bias() is implemented but the pin is not handled by the get_bias() implementation. In that case the output will state that "input bias disabled" indicating that this pin has bias control support. Make support for PIN_CONFIG_BIAS_DISABLE depend on that the pin either supports SH_PFC_PIN_CFG_PULL_UP or SH_PFC_PIN_CFG_PULL_DOWN. This also solves the issue where SoC specific implementations print error messages if their particular implementation of {set,get}_bias() is called with a pin it does not know about. Signed-off-by: Niklas Söderlund Acked-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pinctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c index c5772584594c..fcacfa73ef6e 100644 --- a/drivers/pinctrl/sh-pfc/pinctrl.c +++ b/drivers/pinctrl/sh-pfc/pinctrl.c @@ -570,7 +570,8 @@ static bool sh_pfc_pinconf_validate(struct sh_pfc *pfc, unsigned int _pin, switch (param) { case PIN_CONFIG_BIAS_DISABLE: - return true; + return pin->configs & + (SH_PFC_PIN_CFG_PULL_UP | SH_PFC_PIN_CFG_PULL_DOWN); case PIN_CONFIG_BIAS_PULL_UP: return pin->configs & SH_PFC_PIN_CFG_PULL_UP; -- cgit 1.4.1 From c314c9f15aa5f43f0e5c0e2602cc65798dbd1598 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:25 +0100 Subject: pinctrl: sh-pfc: Add helper to handle bias lookup table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some SoC there are no simple mapping of pins to bias register bits and a lookup table is needed. This logic is already implemented in some SoC specific drivers that could benefit from a generic implementation. Add helpers to deal with the lookup which later can be used by the SoC specific drivers. The logic used to lookup are different from the one it aims to replace, this is intentional. This new method reduces the memory consumption at the cost of increased CPU usage and fix a bug where a WARN() would incorrectly be triggered if the register offset is 0. Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/core.c | 15 +++++++++++++++ drivers/pinctrl/sh-pfc/core.h | 4 ++++ drivers/pinctrl/sh-pfc/sh_pfc.h | 6 ++++++ 3 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c index f3a8897d4e8f..cf80ce1dd7ce 100644 --- a/drivers/pinctrl/sh-pfc/core.c +++ b/drivers/pinctrl/sh-pfc/core.c @@ -389,6 +389,21 @@ int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type) return 0; } +const struct sh_pfc_bias_info * +sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info, + unsigned int num, unsigned int pin) +{ + unsigned int i; + + for (i = 0; i < num; i++) + if (info[i].pin == pin) + return &info[i]; + + WARN_ONCE(1, "Pin %u is not in bias info list\n", pin); + + return NULL; +} + static int sh_pfc_init_ranges(struct sh_pfc *pfc) { struct sh_pfc_pin_range *range; diff --git a/drivers/pinctrl/sh-pfc/core.h b/drivers/pinctrl/sh-pfc/core.h index 0bbdea5849f4..6d598dd63720 100644 --- a/drivers/pinctrl/sh-pfc/core.h +++ b/drivers/pinctrl/sh-pfc/core.h @@ -33,4 +33,8 @@ void sh_pfc_write_reg(struct sh_pfc *pfc, u32 reg, unsigned int width, int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin); int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type); +const struct sh_pfc_bias_info * +sh_pfc_pin_to_bias_info(const struct sh_pfc_bias_info *info, + unsigned int num, unsigned int pin); + #endif /* __SH_PFC_CORE_H__ */ diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 2345421103db..9556c172e3d2 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -189,6 +189,12 @@ struct sh_pfc_window { unsigned long size; }; +struct sh_pfc_bias_info { + u16 pin; + u16 reg : 11; + u16 bit : 5; +}; + struct sh_pfc_pin_range; struct sh_pfc { -- cgit 1.4.1 From 42831cf96531bf4dd9035fb8a94afe8e1fc235b3 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:26 +0100 Subject: pinctrl: sh-pfc: r8a7795: Simplify get bias logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last else statement is missing braces, and the indentation level can be reduced. Suggested-by: Laurent Pinchart Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 2e8cc2adbed7..6c585634a928 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -5367,13 +5367,12 @@ static unsigned int r8a7795_pinmux_get_bias(struct sh_pfc *pfc, reg = pullups[pin].reg; bit = BIT(pullups[pin].bit); - if (sh_pfc_read_reg(pfc, PUEN + reg, 32) & bit) { - if (sh_pfc_read_reg(pfc, PUD + reg, 32) & bit) - return PIN_CONFIG_BIAS_PULL_UP; - else - return PIN_CONFIG_BIAS_PULL_DOWN; - } else + if (!(sh_pfc_read_reg(pfc, PUEN + reg, 32) & bit)) return PIN_CONFIG_BIAS_DISABLE; + else if (sh_pfc_read_reg(pfc, PUD + reg, 32) & bit) + return PIN_CONFIG_BIAS_PULL_UP; + else + return PIN_CONFIG_BIAS_PULL_DOWN; } static void r8a7795_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, -- cgit 1.4.1 From d3b861bccdee2fa9963a2b6c64f74a8d752b9315 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:27 +0100 Subject: pinctrl: sh-pfc: r8a7795: Use lookup function for bias data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a bug in the r8a7795 bias code where a WARN() is trigged anytime a pin from PUEN0/PUD0 is accessed. # cat /sys/kernel/debug/pinctrl/e6060000.pfc/pinconf-pins WARNING: CPU: 2 PID: 2391 at drivers/pinctrl/sh-pfc/pfc-r8a7795.c:5364 r8a7795_pinmux_get_bias+0xbc/0xc8 [..] Call trace: [] r8a7795_pinmux_get_bias+0xbc/0xc8 [] sh_pfc_pinconf_get+0x194/0x270 [] pin_config_get_for_pin+0x20/0x30 [] pinconf_generic_dump_one+0x168/0x188 [] pinconf_generic_dump_pins+0x5c/0x98 [] pinconf_pins_show+0xc8/0x128 [] seq_read+0x16c/0x420 [] full_proxy_read+0x58/0x88 [] __vfs_read+0x1c/0xf8 [] vfs_read+0x84/0x148 [] SyS_read+0x44/0xa0 [] __sys_trace_return+0x0/0x4 This is due to the WARN() check if the reg field of the pullups struct is zero, and this should be 0 for pins controlled by the PUEN0/PUD0 registers since PU0 is defined as 0. Change the data structure and use the generic sh_pfc_pin_to_bias_info() function to get the register offset and bit information. Fixes: 560655247b627ac7 ("pinctrl: sh-pfc: r8a7795: Add bias pinconf support") Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 343 ++++++++++++++++++----------------- 1 file changed, 172 insertions(+), 171 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 6c585634a928..2891c3b63e88 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -5188,184 +5188,183 @@ static int r8a7795_pin_to_pocctrl(struct sh_pfc *pfc, unsigned int pin, u32 *poc #define PU5 0x14 #define PU6 0x18 -static const struct { - u16 reg : 11; - u16 bit : 5; -} pullups[] = { - [RCAR_GP_PIN(2, 11)] = { PU0, 31 }, /* AVB_PHY_INT */ - [RCAR_GP_PIN(2, 10)] = { PU0, 30 }, /* AVB_MAGIC */ - [RCAR_GP_PIN(2, 9)] = { PU0, 29 }, /* AVB_MDC */ - - [RCAR_GP_PIN(1, 19)] = { PU1, 31 }, /* A19 */ - [RCAR_GP_PIN(1, 18)] = { PU1, 30 }, /* A18 */ - [RCAR_GP_PIN(1, 17)] = { PU1, 29 }, /* A17 */ - [RCAR_GP_PIN(1, 16)] = { PU1, 28 }, /* A16 */ - [RCAR_GP_PIN(1, 15)] = { PU1, 27 }, /* A15 */ - [RCAR_GP_PIN(1, 14)] = { PU1, 26 }, /* A14 */ - [RCAR_GP_PIN(1, 13)] = { PU1, 25 }, /* A13 */ - [RCAR_GP_PIN(1, 12)] = { PU1, 24 }, /* A12 */ - [RCAR_GP_PIN(1, 11)] = { PU1, 23 }, /* A11 */ - [RCAR_GP_PIN(1, 10)] = { PU1, 22 }, /* A10 */ - [RCAR_GP_PIN(1, 9)] = { PU1, 21 }, /* A9 */ - [RCAR_GP_PIN(1, 8)] = { PU1, 20 }, /* A8 */ - [RCAR_GP_PIN(1, 7)] = { PU1, 19 }, /* A7 */ - [RCAR_GP_PIN(1, 6)] = { PU1, 18 }, /* A6 */ - [RCAR_GP_PIN(1, 5)] = { PU1, 17 }, /* A5 */ - [RCAR_GP_PIN(1, 4)] = { PU1, 16 }, /* A4 */ - [RCAR_GP_PIN(1, 3)] = { PU1, 15 }, /* A3 */ - [RCAR_GP_PIN(1, 2)] = { PU1, 14 }, /* A2 */ - [RCAR_GP_PIN(1, 1)] = { PU1, 13 }, /* A1 */ - [RCAR_GP_PIN(1, 0)] = { PU1, 12 }, /* A0 */ - [RCAR_GP_PIN(2, 8)] = { PU1, 11 }, /* PWM2_A */ - [RCAR_GP_PIN(2, 7)] = { PU1, 10 }, /* PWM1_A */ - [RCAR_GP_PIN(2, 6)] = { PU1, 9 }, /* PWM0 */ - [RCAR_GP_PIN(2, 5)] = { PU1, 8 }, /* IRQ5 */ - [RCAR_GP_PIN(2, 4)] = { PU1, 7 }, /* IRQ4 */ - [RCAR_GP_PIN(2, 3)] = { PU1, 6 }, /* IRQ3 */ - [RCAR_GP_PIN(2, 2)] = { PU1, 5 }, /* IRQ2 */ - [RCAR_GP_PIN(2, 1)] = { PU1, 4 }, /* IRQ1 */ - [RCAR_GP_PIN(2, 0)] = { PU1, 3 }, /* IRQ0 */ - [RCAR_GP_PIN(2, 14)] = { PU1, 2 }, /* AVB_AVTP_CAPTURE_A */ - [RCAR_GP_PIN(2, 13)] = { PU1, 1 }, /* AVB_AVTP_MATCH_A */ - [RCAR_GP_PIN(2, 12)] = { PU1, 0 }, /* AVB_LINK */ - - [RCAR_GP_PIN(7, 3)] = { PU2, 29 }, /* HDMI1_CEC */ - [RCAR_GP_PIN(7, 2)] = { PU2, 28 }, /* HDMI0_CEC */ - [RCAR_GP_PIN(7, 1)] = { PU2, 27 }, /* AVS2 */ - [RCAR_GP_PIN(7, 0)] = { PU2, 26 }, /* AVS1 */ - [RCAR_GP_PIN(0, 15)] = { PU2, 25 }, /* D15 */ - [RCAR_GP_PIN(0, 14)] = { PU2, 24 }, /* D14 */ - [RCAR_GP_PIN(0, 13)] = { PU2, 23 }, /* D13 */ - [RCAR_GP_PIN(0, 12)] = { PU2, 22 }, /* D12 */ - [RCAR_GP_PIN(0, 11)] = { PU2, 21 }, /* D11 */ - [RCAR_GP_PIN(0, 10)] = { PU2, 20 }, /* D10 */ - [RCAR_GP_PIN(0, 9)] = { PU2, 19 }, /* D9 */ - [RCAR_GP_PIN(0, 8)] = { PU2, 18 }, /* D8 */ - [RCAR_GP_PIN(0, 7)] = { PU2, 17 }, /* D7 */ - [RCAR_GP_PIN(0, 6)] = { PU2, 16 }, /* D6 */ - [RCAR_GP_PIN(0, 5)] = { PU2, 15 }, /* D5 */ - [RCAR_GP_PIN(0, 4)] = { PU2, 14 }, /* D4 */ - [RCAR_GP_PIN(0, 3)] = { PU2, 13 }, /* D3 */ - [RCAR_GP_PIN(0, 2)] = { PU2, 12 }, /* D2 */ - [RCAR_GP_PIN(0, 1)] = { PU2, 11 }, /* D1 */ - [RCAR_GP_PIN(0, 0)] = { PU2, 10 }, /* D0 */ - [RCAR_GP_PIN(1, 27)] = { PU2, 8 }, /* EX_WAIT0_A */ - [RCAR_GP_PIN(1, 26)] = { PU2, 7 }, /* WE1_N */ - [RCAR_GP_PIN(1, 25)] = { PU2, 6 }, /* WE0_N */ - [RCAR_GP_PIN(1, 24)] = { PU2, 5 }, /* RD_WR_N */ - [RCAR_GP_PIN(1, 23)] = { PU2, 4 }, /* RD_N */ - [RCAR_GP_PIN(1, 22)] = { PU2, 3 }, /* BS_N */ - [RCAR_GP_PIN(1, 21)] = { PU2, 2 }, /* CS1_N_A26 */ - [RCAR_GP_PIN(1, 20)] = { PU2, 1 }, /* CS0_N */ - - [RCAR_GP_PIN(4, 9)] = { PU3, 31 }, /* SD3_DAT0 */ - [RCAR_GP_PIN(4, 8)] = { PU3, 30 }, /* SD3_CMD */ - [RCAR_GP_PIN(4, 7)] = { PU3, 29 }, /* SD3_CLK */ - [RCAR_GP_PIN(4, 6)] = { PU3, 28 }, /* SD2_DS */ - [RCAR_GP_PIN(4, 5)] = { PU3, 27 }, /* SD2_DAT3 */ - [RCAR_GP_PIN(4, 4)] = { PU3, 26 }, /* SD2_DAT2 */ - [RCAR_GP_PIN(4, 3)] = { PU3, 25 }, /* SD2_DAT1 */ - [RCAR_GP_PIN(4, 2)] = { PU3, 24 }, /* SD2_DAT0 */ - [RCAR_GP_PIN(4, 1)] = { PU3, 23 }, /* SD2_CMD */ - [RCAR_GP_PIN(4, 0)] = { PU3, 22 }, /* SD2_CLK */ - [RCAR_GP_PIN(3, 11)] = { PU3, 21 }, /* SD1_DAT3 */ - [RCAR_GP_PIN(3, 10)] = { PU3, 20 }, /* SD1_DAT2 */ - [RCAR_GP_PIN(3, 9)] = { PU3, 19 }, /* SD1_DAT1 */ - [RCAR_GP_PIN(3, 8)] = { PU3, 18 }, /* SD1_DAT0 */ - [RCAR_GP_PIN(3, 7)] = { PU3, 17 }, /* SD1_CMD */ - [RCAR_GP_PIN(3, 6)] = { PU3, 16 }, /* SD1_CLK */ - [RCAR_GP_PIN(3, 5)] = { PU3, 15 }, /* SD0_DAT3 */ - [RCAR_GP_PIN(3, 4)] = { PU3, 14 }, /* SD0_DAT2 */ - [RCAR_GP_PIN(3, 3)] = { PU3, 13 }, /* SD0_DAT1 */ - [RCAR_GP_PIN(3, 2)] = { PU3, 12 }, /* SD0_DAT0 */ - [RCAR_GP_PIN(3, 1)] = { PU3, 11 }, /* SD0_CMD */ - [RCAR_GP_PIN(3, 0)] = { PU3, 10 }, /* SD0_CLK */ - - [RCAR_GP_PIN(5, 19)] = { PU4, 31 }, /* MSIOF0_SS1 */ - [RCAR_GP_PIN(5, 18)] = { PU4, 30 }, /* MSIOF0_SYNC */ - [RCAR_GP_PIN(5, 17)] = { PU4, 29 }, /* MSIOF0_SCK */ - [RCAR_GP_PIN(5, 16)] = { PU4, 28 }, /* HRTS0_N */ - [RCAR_GP_PIN(5, 15)] = { PU4, 27 }, /* HCTS0_N */ - [RCAR_GP_PIN(5, 14)] = { PU4, 26 }, /* HTX0 */ - [RCAR_GP_PIN(5, 13)] = { PU4, 25 }, /* HRX0 */ - [RCAR_GP_PIN(5, 12)] = { PU4, 24 }, /* HSCK0 */ - [RCAR_GP_PIN(5, 11)] = { PU4, 23 }, /* RX2_A */ - [RCAR_GP_PIN(5, 10)] = { PU4, 22 }, /* TX2_A */ - [RCAR_GP_PIN(5, 9)] = { PU4, 21 }, /* SCK2 */ - [RCAR_GP_PIN(5, 8)] = { PU4, 20 }, /* RTS1_N_TANS */ - [RCAR_GP_PIN(5, 7)] = { PU4, 19 }, /* CTS1_N */ - [RCAR_GP_PIN(5, 6)] = { PU4, 18 }, /* TX1_A */ - [RCAR_GP_PIN(5, 5)] = { PU4, 17 }, /* RX1_A */ - [RCAR_GP_PIN(5, 4)] = { PU4, 16 }, /* RTS0_N_TANS */ - [RCAR_GP_PIN(5, 3)] = { PU4, 15 }, /* CTS0_N */ - [RCAR_GP_PIN(5, 2)] = { PU4, 14 }, /* TX0 */ - [RCAR_GP_PIN(5, 1)] = { PU4, 13 }, /* RX0 */ - [RCAR_GP_PIN(5, 0)] = { PU4, 12 }, /* SCK0 */ - [RCAR_GP_PIN(3, 15)] = { PU4, 11 }, /* SD1_WP */ - [RCAR_GP_PIN(3, 14)] = { PU4, 10 }, /* SD1_CD */ - [RCAR_GP_PIN(3, 13)] = { PU4, 9 }, /* SD0_WP */ - [RCAR_GP_PIN(3, 12)] = { PU4, 8 }, /* SD0_CD */ - [RCAR_GP_PIN(4, 17)] = { PU4, 7 }, /* SD3_DS */ - [RCAR_GP_PIN(4, 16)] = { PU4, 6 }, /* SD3_DAT7 */ - [RCAR_GP_PIN(4, 15)] = { PU4, 5 }, /* SD3_DAT6 */ - [RCAR_GP_PIN(4, 14)] = { PU4, 4 }, /* SD3_DAT5 */ - [RCAR_GP_PIN(4, 13)] = { PU4, 3 }, /* SD3_DAT4 */ - [RCAR_GP_PIN(4, 12)] = { PU4, 2 }, /* SD3_DAT3 */ - [RCAR_GP_PIN(4, 11)] = { PU4, 1 }, /* SD3_DAT2 */ - [RCAR_GP_PIN(4, 10)] = { PU4, 0 }, /* SD3_DAT1 */ - - [RCAR_GP_PIN(6, 24)] = { PU5, 31 }, /* USB0_PWEN */ - [RCAR_GP_PIN(6, 23)] = { PU5, 30 }, /* AUDIO_CLKB_B */ - [RCAR_GP_PIN(6, 22)] = { PU5, 29 }, /* AUDIO_CLKA_A */ - [RCAR_GP_PIN(6, 21)] = { PU5, 28 }, /* SSI_SDATA9_A */ - [RCAR_GP_PIN(6, 20)] = { PU5, 27 }, /* SSI_SDATA8 */ - [RCAR_GP_PIN(6, 19)] = { PU5, 26 }, /* SSI_SDATA7 */ - [RCAR_GP_PIN(6, 18)] = { PU5, 25 }, /* SSI_WS78 */ - [RCAR_GP_PIN(6, 17)] = { PU5, 24 }, /* SSI_SCK78 */ - [RCAR_GP_PIN(6, 16)] = { PU5, 23 }, /* SSI_SDATA6 */ - [RCAR_GP_PIN(6, 15)] = { PU5, 22 }, /* SSI_WS6 */ - [RCAR_GP_PIN(6, 14)] = { PU5, 21 }, /* SSI_SCK6 */ - [RCAR_GP_PIN(6, 13)] = { PU5, 20 }, /* SSI_SDATA5 */ - [RCAR_GP_PIN(6, 12)] = { PU5, 19 }, /* SSI_WS5 */ - [RCAR_GP_PIN(6, 11)] = { PU5, 18 }, /* SSI_SCK5 */ - [RCAR_GP_PIN(6, 10)] = { PU5, 17 }, /* SSI_SDATA4 */ - [RCAR_GP_PIN(6, 9)] = { PU5, 16 }, /* SSI_WS4 */ - [RCAR_GP_PIN(6, 8)] = { PU5, 15 }, /* SSI_SCK4 */ - [RCAR_GP_PIN(6, 7)] = { PU5, 14 }, /* SSI_SDATA3 */ - [RCAR_GP_PIN(6, 6)] = { PU5, 13 }, /* SSI_WS34 */ - [RCAR_GP_PIN(6, 5)] = { PU5, 12 }, /* SSI_SCK34 */ - [RCAR_GP_PIN(6, 4)] = { PU5, 11 }, /* SSI_SDATA2_A */ - [RCAR_GP_PIN(6, 3)] = { PU5, 10 }, /* SSI_SDATA1_A */ - [RCAR_GP_PIN(6, 2)] = { PU5, 9 }, /* SSI_SDATA0 */ - [RCAR_GP_PIN(6, 1)] = { PU5, 8 }, /* SSI_WS01239 */ - [RCAR_GP_PIN(6, 0)] = { PU5, 7 }, /* SSI_SCK01239 */ - [RCAR_GP_PIN(5, 25)] = { PU5, 5 }, /* MLB_DAT */ - [RCAR_GP_PIN(5, 24)] = { PU5, 4 }, /* MLB_SIG */ - [RCAR_GP_PIN(5, 23)] = { PU5, 3 }, /* MLB_CLK */ - [RCAR_GP_PIN(5, 22)] = { PU5, 2 }, /* MSIOF0_RXD */ - [RCAR_GP_PIN(5, 21)] = { PU5, 1 }, /* MSIOF0_SS2 */ - [RCAR_GP_PIN(5, 20)] = { PU5, 0 }, /* MSIOF0_TXD */ - - [RCAR_GP_PIN(6, 31)] = { PU6, 6 }, /* USB31_OVC */ - [RCAR_GP_PIN(6, 30)] = { PU6, 5 }, /* USB31_PWEN */ - [RCAR_GP_PIN(6, 29)] = { PU6, 4 }, /* USB30_OVC */ - [RCAR_GP_PIN(6, 28)] = { PU6, 3 }, /* USB30_PWEN */ - [RCAR_GP_PIN(6, 27)] = { PU6, 2 }, /* USB1_OVC */ - [RCAR_GP_PIN(6, 26)] = { PU6, 1 }, /* USB1_PWEN */ - [RCAR_GP_PIN(6, 25)] = { PU6, 0 }, /* USB0_OVC */ +static const struct sh_pfc_bias_info bias_info[] = { + { RCAR_GP_PIN(2, 11), PU0, 31 }, /* AVB_PHY_INT */ + { RCAR_GP_PIN(2, 10), PU0, 30 }, /* AVB_MAGIC */ + { RCAR_GP_PIN(2, 9), PU0, 29 }, /* AVB_MDC */ + + { RCAR_GP_PIN(1, 19), PU1, 31 }, /* A19 */ + { RCAR_GP_PIN(1, 18), PU1, 30 }, /* A18 */ + { RCAR_GP_PIN(1, 17), PU1, 29 }, /* A17 */ + { RCAR_GP_PIN(1, 16), PU1, 28 }, /* A16 */ + { RCAR_GP_PIN(1, 15), PU1, 27 }, /* A15 */ + { RCAR_GP_PIN(1, 14), PU1, 26 }, /* A14 */ + { RCAR_GP_PIN(1, 13), PU1, 25 }, /* A13 */ + { RCAR_GP_PIN(1, 12), PU1, 24 }, /* A12 */ + { RCAR_GP_PIN(1, 11), PU1, 23 }, /* A11 */ + { RCAR_GP_PIN(1, 10), PU1, 22 }, /* A10 */ + { RCAR_GP_PIN(1, 9), PU1, 21 }, /* A9 */ + { RCAR_GP_PIN(1, 8), PU1, 20 }, /* A8 */ + { RCAR_GP_PIN(1, 7), PU1, 19 }, /* A7 */ + { RCAR_GP_PIN(1, 6), PU1, 18 }, /* A6 */ + { RCAR_GP_PIN(1, 5), PU1, 17 }, /* A5 */ + { RCAR_GP_PIN(1, 4), PU1, 16 }, /* A4 */ + { RCAR_GP_PIN(1, 3), PU1, 15 }, /* A3 */ + { RCAR_GP_PIN(1, 2), PU1, 14 }, /* A2 */ + { RCAR_GP_PIN(1, 1), PU1, 13 }, /* A1 */ + { RCAR_GP_PIN(1, 0), PU1, 12 }, /* A0 */ + { RCAR_GP_PIN(2, 8), PU1, 11 }, /* PWM2_A */ + { RCAR_GP_PIN(2, 7), PU1, 10 }, /* PWM1_A */ + { RCAR_GP_PIN(2, 6), PU1, 9 }, /* PWM0 */ + { RCAR_GP_PIN(2, 5), PU1, 8 }, /* IRQ5 */ + { RCAR_GP_PIN(2, 4), PU1, 7 }, /* IRQ4 */ + { RCAR_GP_PIN(2, 3), PU1, 6 }, /* IRQ3 */ + { RCAR_GP_PIN(2, 2), PU1, 5 }, /* IRQ2 */ + { RCAR_GP_PIN(2, 1), PU1, 4 }, /* IRQ1 */ + { RCAR_GP_PIN(2, 0), PU1, 3 }, /* IRQ0 */ + { RCAR_GP_PIN(2, 14), PU1, 2 }, /* AVB_AVTP_CAPTURE_A */ + { RCAR_GP_PIN(2, 13), PU1, 1 }, /* AVB_AVTP_MATCH_A */ + { RCAR_GP_PIN(2, 12), PU1, 0 }, /* AVB_LINK */ + + { RCAR_GP_PIN(7, 3), PU2, 29 }, /* HDMI1_CEC */ + { RCAR_GP_PIN(7, 2), PU2, 28 }, /* HDMI0_CEC */ + { RCAR_GP_PIN(7, 1), PU2, 27 }, /* AVS2 */ + { RCAR_GP_PIN(7, 0), PU2, 26 }, /* AVS1 */ + { RCAR_GP_PIN(0, 15), PU2, 25 }, /* D15 */ + { RCAR_GP_PIN(0, 14), PU2, 24 }, /* D14 */ + { RCAR_GP_PIN(0, 13), PU2, 23 }, /* D13 */ + { RCAR_GP_PIN(0, 12), PU2, 22 }, /* D12 */ + { RCAR_GP_PIN(0, 11), PU2, 21 }, /* D11 */ + { RCAR_GP_PIN(0, 10), PU2, 20 }, /* D10 */ + { RCAR_GP_PIN(0, 9), PU2, 19 }, /* D9 */ + { RCAR_GP_PIN(0, 8), PU2, 18 }, /* D8 */ + { RCAR_GP_PIN(0, 7), PU2, 17 }, /* D7 */ + { RCAR_GP_PIN(0, 6), PU2, 16 }, /* D6 */ + { RCAR_GP_PIN(0, 5), PU2, 15 }, /* D5 */ + { RCAR_GP_PIN(0, 4), PU2, 14 }, /* D4 */ + { RCAR_GP_PIN(0, 3), PU2, 13 }, /* D3 */ + { RCAR_GP_PIN(0, 2), PU2, 12 }, /* D2 */ + { RCAR_GP_PIN(0, 1), PU2, 11 }, /* D1 */ + { RCAR_GP_PIN(0, 0), PU2, 10 }, /* D0 */ + { RCAR_GP_PIN(1, 27), PU2, 8 }, /* EX_WAIT0_A */ + { RCAR_GP_PIN(1, 26), PU2, 7 }, /* WE1_N */ + { RCAR_GP_PIN(1, 25), PU2, 6 }, /* WE0_N */ + { RCAR_GP_PIN(1, 24), PU2, 5 }, /* RD_WR_N */ + { RCAR_GP_PIN(1, 23), PU2, 4 }, /* RD_N */ + { RCAR_GP_PIN(1, 22), PU2, 3 }, /* BS_N */ + { RCAR_GP_PIN(1, 21), PU2, 2 }, /* CS1_N_A26 */ + { RCAR_GP_PIN(1, 20), PU2, 1 }, /* CS0_N */ + + { RCAR_GP_PIN(4, 9), PU3, 31 }, /* SD3_DAT0 */ + { RCAR_GP_PIN(4, 8), PU3, 30 }, /* SD3_CMD */ + { RCAR_GP_PIN(4, 7), PU3, 29 }, /* SD3_CLK */ + { RCAR_GP_PIN(4, 6), PU3, 28 }, /* SD2_DS */ + { RCAR_GP_PIN(4, 5), PU3, 27 }, /* SD2_DAT3 */ + { RCAR_GP_PIN(4, 4), PU3, 26 }, /* SD2_DAT2 */ + { RCAR_GP_PIN(4, 3), PU3, 25 }, /* SD2_DAT1 */ + { RCAR_GP_PIN(4, 2), PU3, 24 }, /* SD2_DAT0 */ + { RCAR_GP_PIN(4, 1), PU3, 23 }, /* SD2_CMD */ + { RCAR_GP_PIN(4, 0), PU3, 22 }, /* SD2_CLK */ + { RCAR_GP_PIN(3, 11), PU3, 21 }, /* SD1_DAT3 */ + { RCAR_GP_PIN(3, 10), PU3, 20 }, /* SD1_DAT2 */ + { RCAR_GP_PIN(3, 9), PU3, 19 }, /* SD1_DAT1 */ + { RCAR_GP_PIN(3, 8), PU3, 18 }, /* SD1_DAT0 */ + { RCAR_GP_PIN(3, 7), PU3, 17 }, /* SD1_CMD */ + { RCAR_GP_PIN(3, 6), PU3, 16 }, /* SD1_CLK */ + { RCAR_GP_PIN(3, 5), PU3, 15 }, /* SD0_DAT3 */ + { RCAR_GP_PIN(3, 4), PU3, 14 }, /* SD0_DAT2 */ + { RCAR_GP_PIN(3, 3), PU3, 13 }, /* SD0_DAT1 */ + { RCAR_GP_PIN(3, 2), PU3, 12 }, /* SD0_DAT0 */ + { RCAR_GP_PIN(3, 1), PU3, 11 }, /* SD0_CMD */ + { RCAR_GP_PIN(3, 0), PU3, 10 }, /* SD0_CLK */ + + { RCAR_GP_PIN(5, 19), PU4, 31 }, /* MSIOF0_SS1 */ + { RCAR_GP_PIN(5, 18), PU4, 30 }, /* MSIOF0_SYNC */ + { RCAR_GP_PIN(5, 17), PU4, 29 }, /* MSIOF0_SCK */ + { RCAR_GP_PIN(5, 16), PU4, 28 }, /* HRTS0_N */ + { RCAR_GP_PIN(5, 15), PU4, 27 }, /* HCTS0_N */ + { RCAR_GP_PIN(5, 14), PU4, 26 }, /* HTX0 */ + { RCAR_GP_PIN(5, 13), PU4, 25 }, /* HRX0 */ + { RCAR_GP_PIN(5, 12), PU4, 24 }, /* HSCK0 */ + { RCAR_GP_PIN(5, 11), PU4, 23 }, /* RX2_A */ + { RCAR_GP_PIN(5, 10), PU4, 22 }, /* TX2_A */ + { RCAR_GP_PIN(5, 9), PU4, 21 }, /* SCK2 */ + { RCAR_GP_PIN(5, 8), PU4, 20 }, /* RTS1_N_TANS */ + { RCAR_GP_PIN(5, 7), PU4, 19 }, /* CTS1_N */ + { RCAR_GP_PIN(5, 6), PU4, 18 }, /* TX1_A */ + { RCAR_GP_PIN(5, 5), PU4, 17 }, /* RX1_A */ + { RCAR_GP_PIN(5, 4), PU4, 16 }, /* RTS0_N_TANS */ + { RCAR_GP_PIN(5, 3), PU4, 15 }, /* CTS0_N */ + { RCAR_GP_PIN(5, 2), PU4, 14 }, /* TX0 */ + { RCAR_GP_PIN(5, 1), PU4, 13 }, /* RX0 */ + { RCAR_GP_PIN(5, 0), PU4, 12 }, /* SCK0 */ + { RCAR_GP_PIN(3, 15), PU4, 11 }, /* SD1_WP */ + { RCAR_GP_PIN(3, 14), PU4, 10 }, /* SD1_CD */ + { RCAR_GP_PIN(3, 13), PU4, 9 }, /* SD0_WP */ + { RCAR_GP_PIN(3, 12), PU4, 8 }, /* SD0_CD */ + { RCAR_GP_PIN(4, 17), PU4, 7 }, /* SD3_DS */ + { RCAR_GP_PIN(4, 16), PU4, 6 }, /* SD3_DAT7 */ + { RCAR_GP_PIN(4, 15), PU4, 5 }, /* SD3_DAT6 */ + { RCAR_GP_PIN(4, 14), PU4, 4 }, /* SD3_DAT5 */ + { RCAR_GP_PIN(4, 13), PU4, 3 }, /* SD3_DAT4 */ + { RCAR_GP_PIN(4, 12), PU4, 2 }, /* SD3_DAT3 */ + { RCAR_GP_PIN(4, 11), PU4, 1 }, /* SD3_DAT2 */ + { RCAR_GP_PIN(4, 10), PU4, 0 }, /* SD3_DAT1 */ + + { RCAR_GP_PIN(6, 24), PU5, 31 }, /* USB0_PWEN */ + { RCAR_GP_PIN(6, 23), PU5, 30 }, /* AUDIO_CLKB_B */ + { RCAR_GP_PIN(6, 22), PU5, 29 }, /* AUDIO_CLKA_A */ + { RCAR_GP_PIN(6, 21), PU5, 28 }, /* SSI_SDATA9_A */ + { RCAR_GP_PIN(6, 20), PU5, 27 }, /* SSI_SDATA8 */ + { RCAR_GP_PIN(6, 19), PU5, 26 }, /* SSI_SDATA7 */ + { RCAR_GP_PIN(6, 18), PU5, 25 }, /* SSI_WS78 */ + { RCAR_GP_PIN(6, 17), PU5, 24 }, /* SSI_SCK78 */ + { RCAR_GP_PIN(6, 16), PU5, 23 }, /* SSI_SDATA6 */ + { RCAR_GP_PIN(6, 15), PU5, 22 }, /* SSI_WS6 */ + { RCAR_GP_PIN(6, 14), PU5, 21 }, /* SSI_SCK6 */ + { RCAR_GP_PIN(6, 13), PU5, 20 }, /* SSI_SDATA5 */ + { RCAR_GP_PIN(6, 12), PU5, 19 }, /* SSI_WS5 */ + { RCAR_GP_PIN(6, 11), PU5, 18 }, /* SSI_SCK5 */ + { RCAR_GP_PIN(6, 10), PU5, 17 }, /* SSI_SDATA4 */ + { RCAR_GP_PIN(6, 9), PU5, 16 }, /* SSI_WS4 */ + { RCAR_GP_PIN(6, 8), PU5, 15 }, /* SSI_SCK4 */ + { RCAR_GP_PIN(6, 7), PU5, 14 }, /* SSI_SDATA3 */ + { RCAR_GP_PIN(6, 6), PU5, 13 }, /* SSI_WS34 */ + { RCAR_GP_PIN(6, 5), PU5, 12 }, /* SSI_SCK34 */ + { RCAR_GP_PIN(6, 4), PU5, 11 }, /* SSI_SDATA2_A */ + { RCAR_GP_PIN(6, 3), PU5, 10 }, /* SSI_SDATA1_A */ + { RCAR_GP_PIN(6, 2), PU5, 9 }, /* SSI_SDATA0 */ + { RCAR_GP_PIN(6, 1), PU5, 8 }, /* SSI_WS01239 */ + { RCAR_GP_PIN(6, 0), PU5, 7 }, /* SSI_SCK01239 */ + { RCAR_GP_PIN(5, 25), PU5, 5 }, /* MLB_DAT */ + { RCAR_GP_PIN(5, 24), PU5, 4 }, /* MLB_SIG */ + { RCAR_GP_PIN(5, 23), PU5, 3 }, /* MLB_CLK */ + { RCAR_GP_PIN(5, 22), PU5, 2 }, /* MSIOF0_RXD */ + { RCAR_GP_PIN(5, 21), PU5, 1 }, /* MSIOF0_SS2 */ + { RCAR_GP_PIN(5, 20), PU5, 0 }, /* MSIOF0_TXD */ + + { RCAR_GP_PIN(6, 31), PU6, 6 }, /* USB31_OVC */ + { RCAR_GP_PIN(6, 30), PU6, 5 }, /* USB31_PWEN */ + { RCAR_GP_PIN(6, 29), PU6, 4 }, /* USB30_OVC */ + { RCAR_GP_PIN(6, 28), PU6, 3 }, /* USB30_PWEN */ + { RCAR_GP_PIN(6, 27), PU6, 2 }, /* USB1_OVC */ + { RCAR_GP_PIN(6, 26), PU6, 1 }, /* USB1_PWEN */ + { RCAR_GP_PIN(6, 25), PU6, 0 }, /* USB0_OVC */ }; static unsigned int r8a7795_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) { + const struct sh_pfc_bias_info *info; u32 reg; u32 bit; - if (WARN_ON_ONCE(!pullups[pin].reg)) + info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin); + if (!info) return PIN_CONFIG_BIAS_DISABLE; - reg = pullups[pin].reg; - bit = BIT(pullups[pin].bit); + reg = info->reg; + bit = BIT(info->bit); if (!(sh_pfc_read_reg(pfc, PUEN + reg, 32) & bit)) return PIN_CONFIG_BIAS_DISABLE; @@ -5378,15 +5377,17 @@ static unsigned int r8a7795_pinmux_get_bias(struct sh_pfc *pfc, static void r8a7795_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, unsigned int bias) { + const struct sh_pfc_bias_info *info; u32 enable, updown; u32 reg; u32 bit; - if (WARN_ON_ONCE(!pullups[pin].reg)) + info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin); + if (!info) return; - reg = pullups[pin].reg; - bit = BIT(pullups[pin].bit); + reg = info->reg; + bit = BIT(info->bit); enable = sh_pfc_read_reg(pfc, PUEN + reg, 32) & ~bit; if (bias != PIN_CONFIG_BIAS_DISABLE) -- cgit 1.4.1 From 5c296f69ab71c9a91bc7992b549eda824dfc4a43 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:28 +0100 Subject: pinctrl: sh-pfc: r8a7778: Use lookup function for bias data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the data structure and use the generic sh_pfc_pin_to_bias_info() function to get the register offset and bit information. Suggested-by: Laurent Pinchart Signed-off-by: Niklas Söderlund Reviewed-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7778.c | 342 ++++++++++++++++++----------------- 1 file changed, 172 insertions(+), 170 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c index 18ef7042b3d1..c3af9ebee4af 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c @@ -24,6 +24,7 @@ #include #include +#include "core.h" #include "sh_pfc.h" #define PORT_GP_PUP_1(bank, pin, fn, sfx) \ @@ -2918,183 +2919,182 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { #define PUPR4 0x110 #define PUPR5 0x114 -static const struct { - u16 reg : 11; - u16 bit : 5; -} pullups[] = { - [RCAR_GP_PIN(0, 6)] = { PUPR0, 0 }, /* A0 */ - [RCAR_GP_PIN(0, 7)] = { PUPR0, 1 }, /* A1 */ - [RCAR_GP_PIN(0, 8)] = { PUPR0, 2 }, /* A2 */ - [RCAR_GP_PIN(0, 9)] = { PUPR0, 3 }, /* A3 */ - [RCAR_GP_PIN(0, 10)] = { PUPR0, 4 }, /* A4 */ - [RCAR_GP_PIN(0, 11)] = { PUPR0, 5 }, /* A5 */ - [RCAR_GP_PIN(0, 12)] = { PUPR0, 6 }, /* A6 */ - [RCAR_GP_PIN(0, 13)] = { PUPR0, 7 }, /* A7 */ - [RCAR_GP_PIN(0, 14)] = { PUPR0, 8 }, /* A8 */ - [RCAR_GP_PIN(0, 15)] = { PUPR0, 9 }, /* A9 */ - [RCAR_GP_PIN(0, 16)] = { PUPR0, 10 }, /* A10 */ - [RCAR_GP_PIN(0, 17)] = { PUPR0, 11 }, /* A11 */ - [RCAR_GP_PIN(0, 18)] = { PUPR0, 12 }, /* A12 */ - [RCAR_GP_PIN(0, 19)] = { PUPR0, 13 }, /* A13 */ - [RCAR_GP_PIN(0, 20)] = { PUPR0, 14 }, /* A14 */ - [RCAR_GP_PIN(0, 21)] = { PUPR0, 15 }, /* A15 */ - [RCAR_GP_PIN(0, 22)] = { PUPR0, 16 }, /* A16 */ - [RCAR_GP_PIN(0, 23)] = { PUPR0, 17 }, /* A17 */ - [RCAR_GP_PIN(0, 24)] = { PUPR0, 18 }, /* A18 */ - [RCAR_GP_PIN(0, 25)] = { PUPR0, 19 }, /* A19 */ - [RCAR_GP_PIN(0, 26)] = { PUPR0, 20 }, /* A20 */ - [RCAR_GP_PIN(0, 27)] = { PUPR0, 21 }, /* A21 */ - [RCAR_GP_PIN(0, 28)] = { PUPR0, 22 }, /* A22 */ - [RCAR_GP_PIN(0, 29)] = { PUPR0, 23 }, /* A23 */ - [RCAR_GP_PIN(0, 30)] = { PUPR0, 24 }, /* A24 */ - [RCAR_GP_PIN(0, 31)] = { PUPR0, 25 }, /* A25 */ - [RCAR_GP_PIN(1, 3)] = { PUPR0, 26 }, /* /EX_CS0 */ - [RCAR_GP_PIN(1, 4)] = { PUPR0, 27 }, /* /EX_CS1 */ - [RCAR_GP_PIN(1, 5)] = { PUPR0, 28 }, /* /EX_CS2 */ - [RCAR_GP_PIN(1, 6)] = { PUPR0, 29 }, /* /EX_CS3 */ - [RCAR_GP_PIN(1, 7)] = { PUPR0, 30 }, /* /EX_CS4 */ - [RCAR_GP_PIN(1, 8)] = { PUPR0, 31 }, /* /EX_CS5 */ - - [RCAR_GP_PIN(0, 0)] = { PUPR1, 0 }, /* /PRESETOUT */ - [RCAR_GP_PIN(0, 5)] = { PUPR1, 1 }, /* /BS */ - [RCAR_GP_PIN(1, 0)] = { PUPR1, 2 }, /* RD//WR */ - [RCAR_GP_PIN(1, 1)] = { PUPR1, 3 }, /* /WE0 */ - [RCAR_GP_PIN(1, 2)] = { PUPR1, 4 }, /* /WE1 */ - [RCAR_GP_PIN(1, 11)] = { PUPR1, 5 }, /* EX_WAIT0 */ - [RCAR_GP_PIN(1, 9)] = { PUPR1, 6 }, /* DREQ0 */ - [RCAR_GP_PIN(1, 10)] = { PUPR1, 7 }, /* DACK0 */ - [RCAR_GP_PIN(1, 12)] = { PUPR1, 8 }, /* IRQ0 */ - [RCAR_GP_PIN(1, 13)] = { PUPR1, 9 }, /* IRQ1 */ - - [RCAR_GP_PIN(1, 22)] = { PUPR2, 0 }, /* DU0_DR0 */ - [RCAR_GP_PIN(1, 23)] = { PUPR2, 1 }, /* DU0_DR1 */ - [RCAR_GP_PIN(1, 24)] = { PUPR2, 2 }, /* DU0_DR2 */ - [RCAR_GP_PIN(1, 25)] = { PUPR2, 3 }, /* DU0_DR3 */ - [RCAR_GP_PIN(1, 26)] = { PUPR2, 4 }, /* DU0_DR4 */ - [RCAR_GP_PIN(1, 27)] = { PUPR2, 5 }, /* DU0_DR5 */ - [RCAR_GP_PIN(1, 28)] = { PUPR2, 6 }, /* DU0_DR6 */ - [RCAR_GP_PIN(1, 29)] = { PUPR2, 7 }, /* DU0_DR7 */ - [RCAR_GP_PIN(1, 30)] = { PUPR2, 8 }, /* DU0_DG0 */ - [RCAR_GP_PIN(1, 31)] = { PUPR2, 9 }, /* DU0_DG1 */ - [RCAR_GP_PIN(2, 0)] = { PUPR2, 10 }, /* DU0_DG2 */ - [RCAR_GP_PIN(2, 1)] = { PUPR2, 11 }, /* DU0_DG3 */ - [RCAR_GP_PIN(2, 2)] = { PUPR2, 12 }, /* DU0_DG4 */ - [RCAR_GP_PIN(2, 3)] = { PUPR2, 13 }, /* DU0_DG5 */ - [RCAR_GP_PIN(2, 4)] = { PUPR2, 14 }, /* DU0_DG6 */ - [RCAR_GP_PIN(2, 5)] = { PUPR2, 15 }, /* DU0_DG7 */ - [RCAR_GP_PIN(2, 6)] = { PUPR2, 16 }, /* DU0_DB0 */ - [RCAR_GP_PIN(2, 7)] = { PUPR2, 17 }, /* DU0_DB1 */ - [RCAR_GP_PIN(2, 8)] = { PUPR2, 18 }, /* DU0_DB2 */ - [RCAR_GP_PIN(2, 9)] = { PUPR2, 19 }, /* DU0_DB3 */ - [RCAR_GP_PIN(2, 10)] = { PUPR2, 20 }, /* DU0_DB4 */ - [RCAR_GP_PIN(2, 11)] = { PUPR2, 21 }, /* DU0_DB5 */ - [RCAR_GP_PIN(2, 12)] = { PUPR2, 22 }, /* DU0_DB6 */ - [RCAR_GP_PIN(2, 13)] = { PUPR2, 23 }, /* DU0_DB7 */ - [RCAR_GP_PIN(2, 14)] = { PUPR2, 24 }, /* DU0_DOTCLKIN */ - [RCAR_GP_PIN(2, 15)] = { PUPR2, 25 }, /* DU0_DOTCLKOUT0 */ - [RCAR_GP_PIN(2, 17)] = { PUPR2, 26 }, /* DU0_HSYNC */ - [RCAR_GP_PIN(2, 18)] = { PUPR2, 27 }, /* DU0_VSYNC */ - [RCAR_GP_PIN(2, 19)] = { PUPR2, 28 }, /* DU0_EXODDF */ - [RCAR_GP_PIN(2, 20)] = { PUPR2, 29 }, /* DU0_DISP */ - [RCAR_GP_PIN(2, 21)] = { PUPR2, 30 }, /* DU0_CDE */ - [RCAR_GP_PIN(2, 16)] = { PUPR2, 31 }, /* DU0_DOTCLKOUT1 */ - - [RCAR_GP_PIN(3, 24)] = { PUPR3, 0 }, /* VI0_CLK */ - [RCAR_GP_PIN(3, 25)] = { PUPR3, 1 }, /* VI0_CLKENB */ - [RCAR_GP_PIN(3, 26)] = { PUPR3, 2 }, /* VI0_FIELD */ - [RCAR_GP_PIN(3, 27)] = { PUPR3, 3 }, /* /VI0_HSYNC */ - [RCAR_GP_PIN(3, 28)] = { PUPR3, 4 }, /* /VI0_VSYNC */ - [RCAR_GP_PIN(3, 29)] = { PUPR3, 5 }, /* VI0_DATA0 */ - [RCAR_GP_PIN(3, 30)] = { PUPR3, 6 }, /* VI0_DATA1 */ - [RCAR_GP_PIN(3, 31)] = { PUPR3, 7 }, /* VI0_DATA2 */ - [RCAR_GP_PIN(4, 0)] = { PUPR3, 8 }, /* VI0_DATA3 */ - [RCAR_GP_PIN(4, 1)] = { PUPR3, 9 }, /* VI0_DATA4 */ - [RCAR_GP_PIN(4, 2)] = { PUPR3, 10 }, /* VI0_DATA5 */ - [RCAR_GP_PIN(4, 3)] = { PUPR3, 11 }, /* VI0_DATA6 */ - [RCAR_GP_PIN(4, 4)] = { PUPR3, 12 }, /* VI0_DATA7 */ - [RCAR_GP_PIN(4, 5)] = { PUPR3, 13 }, /* VI0_G2 */ - [RCAR_GP_PIN(4, 6)] = { PUPR3, 14 }, /* VI0_G3 */ - [RCAR_GP_PIN(4, 7)] = { PUPR3, 15 }, /* VI0_G4 */ - [RCAR_GP_PIN(4, 8)] = { PUPR3, 16 }, /* VI0_G5 */ - [RCAR_GP_PIN(4, 21)] = { PUPR3, 17 }, /* VI1_DATA12 */ - [RCAR_GP_PIN(4, 22)] = { PUPR3, 18 }, /* VI1_DATA13 */ - [RCAR_GP_PIN(4, 23)] = { PUPR3, 19 }, /* VI1_DATA14 */ - [RCAR_GP_PIN(4, 24)] = { PUPR3, 20 }, /* VI1_DATA15 */ - [RCAR_GP_PIN(4, 9)] = { PUPR3, 21 }, /* ETH_REF_CLK */ - [RCAR_GP_PIN(4, 10)] = { PUPR3, 22 }, /* ETH_TXD0 */ - [RCAR_GP_PIN(4, 11)] = { PUPR3, 23 }, /* ETH_TXD1 */ - [RCAR_GP_PIN(4, 12)] = { PUPR3, 24 }, /* ETH_CRS_DV */ - [RCAR_GP_PIN(4, 13)] = { PUPR3, 25 }, /* ETH_TX_EN */ - [RCAR_GP_PIN(4, 14)] = { PUPR3, 26 }, /* ETH_RX_ER */ - [RCAR_GP_PIN(4, 15)] = { PUPR3, 27 }, /* ETH_RXD0 */ - [RCAR_GP_PIN(4, 16)] = { PUPR3, 28 }, /* ETH_RXD1 */ - [RCAR_GP_PIN(4, 17)] = { PUPR3, 29 }, /* ETH_MDC */ - [RCAR_GP_PIN(4, 18)] = { PUPR3, 30 }, /* ETH_MDIO */ - [RCAR_GP_PIN(4, 19)] = { PUPR3, 31 }, /* ETH_LINK */ - - [RCAR_GP_PIN(3, 6)] = { PUPR4, 0 }, /* SSI_SCK012 */ - [RCAR_GP_PIN(3, 7)] = { PUPR4, 1 }, /* SSI_WS012 */ - [RCAR_GP_PIN(3, 10)] = { PUPR4, 2 }, /* SSI_SDATA0 */ - [RCAR_GP_PIN(3, 9)] = { PUPR4, 3 }, /* SSI_SDATA1 */ - [RCAR_GP_PIN(3, 8)] = { PUPR4, 4 }, /* SSI_SDATA2 */ - [RCAR_GP_PIN(3, 2)] = { PUPR4, 5 }, /* SSI_SCK34 */ - [RCAR_GP_PIN(3, 3)] = { PUPR4, 6 }, /* SSI_WS34 */ - [RCAR_GP_PIN(3, 5)] = { PUPR4, 7 }, /* SSI_SDATA3 */ - [RCAR_GP_PIN(3, 4)] = { PUPR4, 8 }, /* SSI_SDATA4 */ - [RCAR_GP_PIN(2, 31)] = { PUPR4, 9 }, /* SSI_SCK5 */ - [RCAR_GP_PIN(3, 0)] = { PUPR4, 10 }, /* SSI_WS5 */ - [RCAR_GP_PIN(3, 1)] = { PUPR4, 11 }, /* SSI_SDATA5 */ - [RCAR_GP_PIN(2, 28)] = { PUPR4, 12 }, /* SSI_SCK6 */ - [RCAR_GP_PIN(2, 29)] = { PUPR4, 13 }, /* SSI_WS6 */ - [RCAR_GP_PIN(2, 30)] = { PUPR4, 14 }, /* SSI_SDATA6 */ - [RCAR_GP_PIN(2, 24)] = { PUPR4, 15 }, /* SSI_SCK78 */ - [RCAR_GP_PIN(2, 25)] = { PUPR4, 16 }, /* SSI_WS78 */ - [RCAR_GP_PIN(2, 27)] = { PUPR4, 17 }, /* SSI_SDATA7 */ - [RCAR_GP_PIN(2, 26)] = { PUPR4, 18 }, /* SSI_SDATA8 */ - [RCAR_GP_PIN(3, 23)] = { PUPR4, 19 }, /* TCLK0 */ - [RCAR_GP_PIN(3, 11)] = { PUPR4, 20 }, /* SD0_CLK */ - [RCAR_GP_PIN(3, 12)] = { PUPR4, 21 }, /* SD0_CMD */ - [RCAR_GP_PIN(3, 13)] = { PUPR4, 22 }, /* SD0_DAT0 */ - [RCAR_GP_PIN(3, 14)] = { PUPR4, 23 }, /* SD0_DAT1 */ - [RCAR_GP_PIN(3, 15)] = { PUPR4, 24 }, /* SD0_DAT2 */ - [RCAR_GP_PIN(3, 16)] = { PUPR4, 25 }, /* SD0_DAT3 */ - [RCAR_GP_PIN(3, 17)] = { PUPR4, 26 }, /* SD0_CD */ - [RCAR_GP_PIN(3, 18)] = { PUPR4, 27 }, /* SD0_WP */ - [RCAR_GP_PIN(2, 22)] = { PUPR4, 28 }, /* AUDIO_CLKA */ - [RCAR_GP_PIN(2, 23)] = { PUPR4, 29 }, /* AUDIO_CLKB */ - [RCAR_GP_PIN(1, 14)] = { PUPR4, 30 }, /* IRQ2 */ - [RCAR_GP_PIN(1, 15)] = { PUPR4, 31 }, /* IRQ3 */ - - [RCAR_GP_PIN(0, 1)] = { PUPR5, 0 }, /* PENC0 */ - [RCAR_GP_PIN(0, 2)] = { PUPR5, 1 }, /* PENC1 */ - [RCAR_GP_PIN(0, 3)] = { PUPR5, 2 }, /* USB_OVC0 */ - [RCAR_GP_PIN(0, 4)] = { PUPR5, 3 }, /* USB_OVC1 */ - [RCAR_GP_PIN(1, 16)] = { PUPR5, 4 }, /* SCIF_CLK */ - [RCAR_GP_PIN(1, 17)] = { PUPR5, 5 }, /* TX0 */ - [RCAR_GP_PIN(1, 18)] = { PUPR5, 6 }, /* RX0 */ - [RCAR_GP_PIN(1, 19)] = { PUPR5, 7 }, /* SCK0 */ - [RCAR_GP_PIN(1, 20)] = { PUPR5, 8 }, /* /CTS0 */ - [RCAR_GP_PIN(1, 21)] = { PUPR5, 9 }, /* /RTS0 */ - [RCAR_GP_PIN(3, 19)] = { PUPR5, 10 }, /* HSPI_CLK0 */ - [RCAR_GP_PIN(3, 20)] = { PUPR5, 11 }, /* /HSPI_CS0 */ - [RCAR_GP_PIN(3, 21)] = { PUPR5, 12 }, /* HSPI_RX0 */ - [RCAR_GP_PIN(3, 22)] = { PUPR5, 13 }, /* HSPI_TX0 */ - [RCAR_GP_PIN(4, 20)] = { PUPR5, 14 }, /* ETH_MAGIC */ - [RCAR_GP_PIN(4, 25)] = { PUPR5, 15 }, /* AVS1 */ - [RCAR_GP_PIN(4, 26)] = { PUPR5, 16 }, /* AVS2 */ +static const struct sh_pfc_bias_info bias_info[] = { + { RCAR_GP_PIN(0, 6), PUPR0, 0 }, /* A0 */ + { RCAR_GP_PIN(0, 7), PUPR0, 1 }, /* A1 */ + { RCAR_GP_PIN(0, 8), PUPR0, 2 }, /* A2 */ + { RCAR_GP_PIN(0, 9), PUPR0, 3 }, /* A3 */ + { RCAR_GP_PIN(0, 10), PUPR0, 4 }, /* A4 */ + { RCAR_GP_PIN(0, 11), PUPR0, 5 }, /* A5 */ + { RCAR_GP_PIN(0, 12), PUPR0, 6 }, /* A6 */ + { RCAR_GP_PIN(0, 13), PUPR0, 7 }, /* A7 */ + { RCAR_GP_PIN(0, 14), PUPR0, 8 }, /* A8 */ + { RCAR_GP_PIN(0, 15), PUPR0, 9 }, /* A9 */ + { RCAR_GP_PIN(0, 16), PUPR0, 10 }, /* A10 */ + { RCAR_GP_PIN(0, 17), PUPR0, 11 }, /* A11 */ + { RCAR_GP_PIN(0, 18), PUPR0, 12 }, /* A12 */ + { RCAR_GP_PIN(0, 19), PUPR0, 13 }, /* A13 */ + { RCAR_GP_PIN(0, 20), PUPR0, 14 }, /* A14 */ + { RCAR_GP_PIN(0, 21), PUPR0, 15 }, /* A15 */ + { RCAR_GP_PIN(0, 22), PUPR0, 16 }, /* A16 */ + { RCAR_GP_PIN(0, 23), PUPR0, 17 }, /* A17 */ + { RCAR_GP_PIN(0, 24), PUPR0, 18 }, /* A18 */ + { RCAR_GP_PIN(0, 25), PUPR0, 19 }, /* A19 */ + { RCAR_GP_PIN(0, 26), PUPR0, 20 }, /* A20 */ + { RCAR_GP_PIN(0, 27), PUPR0, 21 }, /* A21 */ + { RCAR_GP_PIN(0, 28), PUPR0, 22 }, /* A22 */ + { RCAR_GP_PIN(0, 29), PUPR0, 23 }, /* A23 */ + { RCAR_GP_PIN(0, 30), PUPR0, 24 }, /* A24 */ + { RCAR_GP_PIN(0, 31), PUPR0, 25 }, /* A25 */ + { RCAR_GP_PIN(1, 3), PUPR0, 26 }, /* /EX_CS0 */ + { RCAR_GP_PIN(1, 4), PUPR0, 27 }, /* /EX_CS1 */ + { RCAR_GP_PIN(1, 5), PUPR0, 28 }, /* /EX_CS2 */ + { RCAR_GP_PIN(1, 6), PUPR0, 29 }, /* /EX_CS3 */ + { RCAR_GP_PIN(1, 7), PUPR0, 30 }, /* /EX_CS4 */ + { RCAR_GP_PIN(1, 8), PUPR0, 31 }, /* /EX_CS5 */ + + { RCAR_GP_PIN(0, 0), PUPR1, 0 }, /* /PRESETOUT */ + { RCAR_GP_PIN(0, 5), PUPR1, 1 }, /* /BS */ + { RCAR_GP_PIN(1, 0), PUPR1, 2 }, /* RD//WR */ + { RCAR_GP_PIN(1, 1), PUPR1, 3 }, /* /WE0 */ + { RCAR_GP_PIN(1, 2), PUPR1, 4 }, /* /WE1 */ + { RCAR_GP_PIN(1, 11), PUPR1, 5 }, /* EX_WAIT0 */ + { RCAR_GP_PIN(1, 9), PUPR1, 6 }, /* DREQ0 */ + { RCAR_GP_PIN(1, 10), PUPR1, 7 }, /* DACK0 */ + { RCAR_GP_PIN(1, 12), PUPR1, 8 }, /* IRQ0 */ + { RCAR_GP_PIN(1, 13), PUPR1, 9 }, /* IRQ1 */ + + { RCAR_GP_PIN(1, 22), PUPR2, 0 }, /* DU0_DR0 */ + { RCAR_GP_PIN(1, 23), PUPR2, 1 }, /* DU0_DR1 */ + { RCAR_GP_PIN(1, 24), PUPR2, 2 }, /* DU0_DR2 */ + { RCAR_GP_PIN(1, 25), PUPR2, 3 }, /* DU0_DR3 */ + { RCAR_GP_PIN(1, 26), PUPR2, 4 }, /* DU0_DR4 */ + { RCAR_GP_PIN(1, 27), PUPR2, 5 }, /* DU0_DR5 */ + { RCAR_GP_PIN(1, 28), PUPR2, 6 }, /* DU0_DR6 */ + { RCAR_GP_PIN(1, 29), PUPR2, 7 }, /* DU0_DR7 */ + { RCAR_GP_PIN(1, 30), PUPR2, 8 }, /* DU0_DG0 */ + { RCAR_GP_PIN(1, 31), PUPR2, 9 }, /* DU0_DG1 */ + { RCAR_GP_PIN(2, 0), PUPR2, 10 }, /* DU0_DG2 */ + { RCAR_GP_PIN(2, 1), PUPR2, 11 }, /* DU0_DG3 */ + { RCAR_GP_PIN(2, 2), PUPR2, 12 }, /* DU0_DG4 */ + { RCAR_GP_PIN(2, 3), PUPR2, 13 }, /* DU0_DG5 */ + { RCAR_GP_PIN(2, 4), PUPR2, 14 }, /* DU0_DG6 */ + { RCAR_GP_PIN(2, 5), PUPR2, 15 }, /* DU0_DG7 */ + { RCAR_GP_PIN(2, 6), PUPR2, 16 }, /* DU0_DB0 */ + { RCAR_GP_PIN(2, 7), PUPR2, 17 }, /* DU0_DB1 */ + { RCAR_GP_PIN(2, 8), PUPR2, 18 }, /* DU0_DB2 */ + { RCAR_GP_PIN(2, 9), PUPR2, 19 }, /* DU0_DB3 */ + { RCAR_GP_PIN(2, 10), PUPR2, 20 }, /* DU0_DB4 */ + { RCAR_GP_PIN(2, 11), PUPR2, 21 }, /* DU0_DB5 */ + { RCAR_GP_PIN(2, 12), PUPR2, 22 }, /* DU0_DB6 */ + { RCAR_GP_PIN(2, 13), PUPR2, 23 }, /* DU0_DB7 */ + { RCAR_GP_PIN(2, 14), PUPR2, 24 }, /* DU0_DOTCLKIN */ + { RCAR_GP_PIN(2, 15), PUPR2, 25 }, /* DU0_DOTCLKOUT0 */ + { RCAR_GP_PIN(2, 17), PUPR2, 26 }, /* DU0_HSYNC */ + { RCAR_GP_PIN(2, 18), PUPR2, 27 }, /* DU0_VSYNC */ + { RCAR_GP_PIN(2, 19), PUPR2, 28 }, /* DU0_EXODDF */ + { RCAR_GP_PIN(2, 20), PUPR2, 29 }, /* DU0_DISP */ + { RCAR_GP_PIN(2, 21), PUPR2, 30 }, /* DU0_CDE */ + { RCAR_GP_PIN(2, 16), PUPR2, 31 }, /* DU0_DOTCLKOUT1 */ + + { RCAR_GP_PIN(3, 24), PUPR3, 0 }, /* VI0_CLK */ + { RCAR_GP_PIN(3, 25), PUPR3, 1 }, /* VI0_CLKENB */ + { RCAR_GP_PIN(3, 26), PUPR3, 2 }, /* VI0_FIELD */ + { RCAR_GP_PIN(3, 27), PUPR3, 3 }, /* /VI0_HSYNC */ + { RCAR_GP_PIN(3, 28), PUPR3, 4 }, /* /VI0_VSYNC */ + { RCAR_GP_PIN(3, 29), PUPR3, 5 }, /* VI0_DATA0 */ + { RCAR_GP_PIN(3, 30), PUPR3, 6 }, /* VI0_DATA1 */ + { RCAR_GP_PIN(3, 31), PUPR3, 7 }, /* VI0_DATA2 */ + { RCAR_GP_PIN(4, 0), PUPR3, 8 }, /* VI0_DATA3 */ + { RCAR_GP_PIN(4, 1), PUPR3, 9 }, /* VI0_DATA4 */ + { RCAR_GP_PIN(4, 2), PUPR3, 10 }, /* VI0_DATA5 */ + { RCAR_GP_PIN(4, 3), PUPR3, 11 }, /* VI0_DATA6 */ + { RCAR_GP_PIN(4, 4), PUPR3, 12 }, /* VI0_DATA7 */ + { RCAR_GP_PIN(4, 5), PUPR3, 13 }, /* VI0_G2 */ + { RCAR_GP_PIN(4, 6), PUPR3, 14 }, /* VI0_G3 */ + { RCAR_GP_PIN(4, 7), PUPR3, 15 }, /* VI0_G4 */ + { RCAR_GP_PIN(4, 8), PUPR3, 16 }, /* VI0_G5 */ + { RCAR_GP_PIN(4, 21), PUPR3, 17 }, /* VI1_DATA12 */ + { RCAR_GP_PIN(4, 22), PUPR3, 18 }, /* VI1_DATA13 */ + { RCAR_GP_PIN(4, 23), PUPR3, 19 }, /* VI1_DATA14 */ + { RCAR_GP_PIN(4, 24), PUPR3, 20 }, /* VI1_DATA15 */ + { RCAR_GP_PIN(4, 9), PUPR3, 21 }, /* ETH_REF_CLK */ + { RCAR_GP_PIN(4, 10), PUPR3, 22 }, /* ETH_TXD0 */ + { RCAR_GP_PIN(4, 11), PUPR3, 23 }, /* ETH_TXD1 */ + { RCAR_GP_PIN(4, 12), PUPR3, 24 }, /* ETH_CRS_DV */ + { RCAR_GP_PIN(4, 13), PUPR3, 25 }, /* ETH_TX_EN */ + { RCAR_GP_PIN(4, 14), PUPR3, 26 }, /* ETH_RX_ER */ + { RCAR_GP_PIN(4, 15), PUPR3, 27 }, /* ETH_RXD0 */ + { RCAR_GP_PIN(4, 16), PUPR3, 28 }, /* ETH_RXD1 */ + { RCAR_GP_PIN(4, 17), PUPR3, 29 }, /* ETH_MDC */ + { RCAR_GP_PIN(4, 18), PUPR3, 30 }, /* ETH_MDIO */ + { RCAR_GP_PIN(4, 19), PUPR3, 31 }, /* ETH_LINK */ + + { RCAR_GP_PIN(3, 6), PUPR4, 0 }, /* SSI_SCK012 */ + { RCAR_GP_PIN(3, 7), PUPR4, 1 }, /* SSI_WS012 */ + { RCAR_GP_PIN(3, 10), PUPR4, 2 }, /* SSI_SDATA0 */ + { RCAR_GP_PIN(3, 9), PUPR4, 3 }, /* SSI_SDATA1 */ + { RCAR_GP_PIN(3, 8), PUPR4, 4 }, /* SSI_SDATA2 */ + { RCAR_GP_PIN(3, 2), PUPR4, 5 }, /* SSI_SCK34 */ + { RCAR_GP_PIN(3, 3), PUPR4, 6 }, /* SSI_WS34 */ + { RCAR_GP_PIN(3, 5), PUPR4, 7 }, /* SSI_SDATA3 */ + { RCAR_GP_PIN(3, 4), PUPR4, 8 }, /* SSI_SDATA4 */ + { RCAR_GP_PIN(2, 31), PUPR4, 9 }, /* SSI_SCK5 */ + { RCAR_GP_PIN(3, 0), PUPR4, 10 }, /* SSI_WS5 */ + { RCAR_GP_PIN(3, 1), PUPR4, 11 }, /* SSI_SDATA5 */ + { RCAR_GP_PIN(2, 28), PUPR4, 12 }, /* SSI_SCK6 */ + { RCAR_GP_PIN(2, 29), PUPR4, 13 }, /* SSI_WS6 */ + { RCAR_GP_PIN(2, 30), PUPR4, 14 }, /* SSI_SDATA6 */ + { RCAR_GP_PIN(2, 24), PUPR4, 15 }, /* SSI_SCK78 */ + { RCAR_GP_PIN(2, 25), PUPR4, 16 }, /* SSI_WS78 */ + { RCAR_GP_PIN(2, 27), PUPR4, 17 }, /* SSI_SDATA7 */ + { RCAR_GP_PIN(2, 26), PUPR4, 18 }, /* SSI_SDATA8 */ + { RCAR_GP_PIN(3, 23), PUPR4, 19 }, /* TCLK0 */ + { RCAR_GP_PIN(3, 11), PUPR4, 20 }, /* SD0_CLK */ + { RCAR_GP_PIN(3, 12), PUPR4, 21 }, /* SD0_CMD */ + { RCAR_GP_PIN(3, 13), PUPR4, 22 }, /* SD0_DAT0 */ + { RCAR_GP_PIN(3, 14), PUPR4, 23 }, /* SD0_DAT1 */ + { RCAR_GP_PIN(3, 15), PUPR4, 24 }, /* SD0_DAT2 */ + { RCAR_GP_PIN(3, 16), PUPR4, 25 }, /* SD0_DAT3 */ + { RCAR_GP_PIN(3, 17), PUPR4, 26 }, /* SD0_CD */ + { RCAR_GP_PIN(3, 18), PUPR4, 27 }, /* SD0_WP */ + { RCAR_GP_PIN(2, 22), PUPR4, 28 }, /* AUDIO_CLKA */ + { RCAR_GP_PIN(2, 23), PUPR4, 29 }, /* AUDIO_CLKB */ + { RCAR_GP_PIN(1, 14), PUPR4, 30 }, /* IRQ2 */ + { RCAR_GP_PIN(1, 15), PUPR4, 31 }, /* IRQ3 */ + + { RCAR_GP_PIN(0, 1), PUPR5, 0 }, /* PENC0 */ + { RCAR_GP_PIN(0, 2), PUPR5, 1 }, /* PENC1 */ + { RCAR_GP_PIN(0, 3), PUPR5, 2 }, /* USB_OVC0 */ + { RCAR_GP_PIN(0, 4), PUPR5, 3 }, /* USB_OVC1 */ + { RCAR_GP_PIN(1, 16), PUPR5, 4 }, /* SCIF_CLK */ + { RCAR_GP_PIN(1, 17), PUPR5, 5 }, /* TX0 */ + { RCAR_GP_PIN(1, 18), PUPR5, 6 }, /* RX0 */ + { RCAR_GP_PIN(1, 19), PUPR5, 7 }, /* SCK0 */ + { RCAR_GP_PIN(1, 20), PUPR5, 8 }, /* /CTS0 */ + { RCAR_GP_PIN(1, 21), PUPR5, 9 }, /* /RTS0 */ + { RCAR_GP_PIN(3, 19), PUPR5, 10 }, /* HSPI_CLK0 */ + { RCAR_GP_PIN(3, 20), PUPR5, 11 }, /* /HSPI_CS0 */ + { RCAR_GP_PIN(3, 21), PUPR5, 12 }, /* HSPI_RX0 */ + { RCAR_GP_PIN(3, 22), PUPR5, 13 }, /* HSPI_TX0 */ + { RCAR_GP_PIN(4, 20), PUPR5, 14 }, /* ETH_MAGIC */ + { RCAR_GP_PIN(4, 25), PUPR5, 15 }, /* AVS1 */ + { RCAR_GP_PIN(4, 26), PUPR5, 16 }, /* AVS2 */ }; static unsigned int r8a7778_pinmux_get_bias(struct sh_pfc *pfc, unsigned int pin) { + const struct sh_pfc_bias_info *info; void __iomem *addr; - if (WARN_ON_ONCE(!pullups[pin].reg)) + info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin); + if (!info) return PIN_CONFIG_BIAS_DISABLE; - addr = pfc->windows->virt + pullups[pin].reg; + addr = pfc->windows->virt + info->reg; - if (ioread32(addr) & BIT(pullups[pin].bit)) + if (ioread32(addr) & BIT(info->bit)) return PIN_CONFIG_BIAS_PULL_UP; else return PIN_CONFIG_BIAS_DISABLE; @@ -3103,15 +3103,17 @@ static unsigned int r8a7778_pinmux_get_bias(struct sh_pfc *pfc, static void r8a7778_pinmux_set_bias(struct sh_pfc *pfc, unsigned int pin, unsigned int bias) { + const struct sh_pfc_bias_info *info; void __iomem *addr; u32 value; u32 bit; - if (WARN_ON_ONCE(!pullups[pin].reg)) + info = sh_pfc_pin_to_bias_info(bias_info, ARRAY_SIZE(bias_info), pin); + if (!info) return; - addr = pfc->windows->virt + pullups[pin].reg; - bit = BIT(pullups[pin].bit); + addr = pfc->windows->virt + info->reg; + bit = BIT(info->bit); value = ioread32(addr) & ~bit; if (bias == PIN_CONFIG_BIAS_PULL_UP) -- cgit 1.4.1 From 1ce56aea7cf4002f77891808ca4e06aa4e2b4ca6 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Sat, 12 Nov 2016 17:04:29 +0100 Subject: pinctrl: sh-pfc: Support named pins with custom configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pins not associated with a GPIO port can still have other configuration parameters. Add a new macro SH_PFC_PIN_NAMED_CFG which allows for named pins to be declared with a set of configurations. The new macro is an modification of SH_PFC_PIN_NAMED to allow for optional configuration to be assigned. The flag SH_PFC_PIN_CFG_NO_GPIO is still enforced as this should only be used to define pins not associated with a GPIO port. Signed-off-by: Niklas Söderlund Acked-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/sh_pfc.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h index 9556c172e3d2..e42cc7a8d10e 100644 --- a/drivers/pinctrl/sh-pfc/sh_pfc.h +++ b/drivers/pinctrl/sh-pfc/sh_pfc.h @@ -546,6 +546,14 @@ extern const struct sh_pfc_soc_info shx3_pinmux_info; .configs = SH_PFC_PIN_CFG_NO_GPIO, \ } +/* SH_PFC_PIN_NAMED_CFG - Expand to a sh_pfc_pin entry with the given name */ +#define SH_PFC_PIN_NAMED_CFG(row, col, _name, cfgs) \ + { \ + .pin = PIN_NUMBER(row, col), \ + .name = __stringify(PIN_##_name), \ + .configs = SH_PFC_PIN_CFG_NO_GPIO | cfgs, \ + } + /* PINMUX_DATA_ALL - Expand to a list of PORT_name_DATA, PORT_name_FN0, * PORT_name_OUT, PORT_name_IN marks */ -- cgit 1.4.1 From ea9c740583c6857b07ffc310eca967bc39ff6a21 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 11 Nov 2016 21:33:39 +0100 Subject: pinctrl: sh-pfc: r8a7795: Support none GPIO pins with configurable drive-strength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are pins on the r8a7795 which are not part of a GPIO bank nor can be muxed between different functions. They do however allow for the drive-strength to be configured. Add those pins to the list of pins and to the drive-strength configuration registers. The pins can now be referred to in DT by function names and their drive-strength modified. Signed-off-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 163 +++++++++++++++++++++++++++++++---- 1 file changed, 148 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index 2891c3b63e88..a69c5dce89a4 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -523,6 +523,22 @@ MOD_SEL0_2_1 MOD_SEL1_2 \ MOD_SEL1_1 \ MOD_SEL1_0 MOD_SEL2_0 +/* + * These pins are not able to be muxed but have other properties + * that can be set, such as drive-strength or pull-up/pull-down enable. + */ +#define PINMUX_STATIC \ + FM(QSPI0_SPCLK) FM(QSPI0_SSL) FM(QSPI0_MOSI_IO0) FM(QSPI0_MISO_IO1) \ + FM(QSPI0_IO2) FM(QSPI0_IO3) \ + FM(QSPI1_SPCLK) FM(QSPI1_SSL) FM(QSPI1_MOSI_IO0) FM(QSPI1_MISO_IO1) \ + FM(QSPI1_IO2) FM(QSPI1_IO3) \ + FM(RPC_INT) FM(RPC_WP) FM(RPC_RESET) \ + FM(AVB_TX_CTL) FM(AVB_TXC) FM(AVB_TD0) FM(AVB_TD1) FM(AVB_TD2) FM(AVB_TD3) \ + FM(AVB_RX_CTL) FM(AVB_RXC) FM(AVB_RD0) FM(AVB_RD1) FM(AVB_RD2) FM(AVB_RD3) \ + FM(AVB_TXCREFCLK) FM(AVB_MDIO) \ + FM(CLKOUT) FM(PRESETOUT) \ + FM(DU_DOTCLKIN0) FM(DU_DOTCLKIN1) FM(DU_DOTCLKIN2) FM(DU_DOTCLKIN3) \ + FM(TMS) FM(TDO) FM(ASEBRK) FM(MLB_REF) enum { PINMUX_RESERVED = 0, @@ -548,6 +564,7 @@ enum { PINMUX_GPSR PINMUX_IPSR PINMUX_MOD_SELS + PINMUX_STATIC PINMUX_MARK_END, #undef F_ #undef FM @@ -1412,10 +1429,78 @@ static const u16 pinmux_data[] = { PINMUX_IPSR_MSEL(IP17_7_4, STP_ISSYNC_0_E, SEL_SSP1_0_4), PINMUX_IPSR_MSEL(IP17_7_4, RIF2_D1_B, SEL_DRIF2_1), PINMUX_IPSR_GPSR(IP17_7_4, TPU0TO3), + +/* + * Static pins can not be muxed between different functions but + * still needs a mark entry in the pinmux list. Add each static + * pin to the list without an associated function. The sh-pfc + * core will do the right thing and skip trying to mux then pin + * while still applying configuration to it + */ +#define FM(x) PINMUX_DATA(x##_MARK, 0), + PINMUX_STATIC +#undef FM }; +/* + * R8A7795 has 8 banks with 32 PGIOS in each => 256 GPIOs. + * Physical layout rows: A - AW, cols: 1 - 39. + */ +#define ROW_GROUP_A(r) ('Z' - 'A' + 1 + (r)) +#define PIN_NUMBER(r, c) (((r) - 'A') * 39 + (c) + 300) +#define PIN_A_NUMBER(r, c) PIN_NUMBER(ROW_GROUP_A(r), c) + static const struct sh_pfc_pin pinmux_pins[] = { PINMUX_GPIO_GP_ALL(), + + /* + * Pins not associated with a GPIO port. + * + * The pin positions are different between different r8a7795 + * packages, all that is needed for the pfc driver is a unique + * number for each pin. To this end use the pin layout from + * R-Car H3SiP to calculate a unique number for each pin. + */ + SH_PFC_PIN_NAMED_CFG('A', 8, AVB_TX_CTL, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 9, AVB_MDIO, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 12, AVB_TXCREFCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 13, AVB_RD0, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 14, AVB_RD2, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 16, AVB_RX_CTL, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 17, AVB_TD2, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 18, AVB_TD0, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('A', 19, AVB_TXC, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('B', 13, AVB_RD1, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('B', 14, AVB_RD3, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('B', 17, AVB_TD3, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('B', 18, AVB_TD1, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('B', 19, AVB_RXC, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('C', 1, PRESETOUT#, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('F', 1, CLKOUT, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('H', 37, MLB_REF, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('V', 3, QSPI1_SPCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('V', 5, QSPI1_SSL, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('V', 6, RPC_WP#, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('V', 7, RPC_RESET#, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('W', 3, QSPI0_SPCLK, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('Y', 3, QSPI0_SSL, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('Y', 6, QSPI0_IO2, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG('Y', 7, RPC_INT#, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 4, QSPI0_MISO_IO1, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('B'), 6, QSPI0_IO3, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 3, QSPI1_IO3, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 5, QSPI0_MOSI_IO0, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('C'), 7, QSPI1_MOSI_IO0, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('D'), 38, FSCLKST#, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 4, QSPI1_IO2, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('E'), 5, QSPI1_MISO_IO1, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 7, DU_DOTCLKIN0, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('P'), 8, DU_DOTCLKIN1, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 7, DU_DOTCLKIN2, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 8, DU_DOTCLKIN3, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('R'), 30, TMS, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 28, TDO, SH_PFC_PIN_CFG_DRIVE_STRENGTH), + SH_PFC_PIN_NAMED_CFG(ROW_GROUP_A('T'), 30, ASEBRK, SH_PFC_PIN_CFG_DRIVE_STRENGTH), }; /* - AUDIO CLOCK ------------------------------------------------------------ */ @@ -4962,10 +5047,45 @@ static const struct pinmux_cfg_reg pinmux_config_regs[] = { }; static const struct pinmux_drive_reg pinmux_drive_regs[] = { + { PINMUX_DRIVE_REG("DRVCTRL0", 0xe6060300) { + { PIN_NUMBER('W', 3), 28, 2 }, /* QSPI0_SPCLK */ + { PIN_A_NUMBER('C', 5), 24, 2 }, /* QSPI0_MOSI_IO0 */ + { PIN_A_NUMBER('B', 4), 20, 2 }, /* QSPI0_MISO_IO1 */ + { PIN_NUMBER('Y', 6), 16, 2 }, /* QSPI0_IO2 */ + { PIN_A_NUMBER('B', 6), 12, 2 }, /* QSPI0_IO3 */ + { PIN_NUMBER('Y', 3), 8, 2 }, /* QSPI0_SSL */ + { PIN_NUMBER('V', 3), 4, 2 }, /* QSPI1_SPCLK */ + { PIN_A_NUMBER('C', 7), 0, 2 }, /* QSPI1_MOSI_IO0 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL1", 0xe6060304) { + { PIN_A_NUMBER('E', 5), 28, 2 }, /* QSPI1_MISO_IO1 */ + { PIN_A_NUMBER('E', 4), 24, 2 }, /* QSPI1_IO2 */ + { PIN_A_NUMBER('C', 3), 20, 2 }, /* QSPI1_IO3 */ + { PIN_NUMBER('V', 5), 16, 2 }, /* QSPI1_SSL */ + { PIN_NUMBER('Y', 7), 12, 2 }, /* RPC_INT# */ + { PIN_NUMBER('V', 6), 8, 2 }, /* RPC_WP# */ + { PIN_NUMBER('V', 7), 4, 2 }, /* RPC_RESET# */ + { PIN_NUMBER('A', 16), 0, 3 }, /* AVB_RX_CTL */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL2", 0xe6060308) { + { PIN_NUMBER('B', 19), 28, 3 }, /* AVB_RXC */ + { PIN_NUMBER('A', 13), 24, 3 }, /* AVB_RD0 */ + { PIN_NUMBER('B', 13), 20, 3 }, /* AVB_RD1 */ + { PIN_NUMBER('A', 14), 16, 3 }, /* AVB_RD2 */ + { PIN_NUMBER('B', 14), 12, 3 }, /* AVB_RD3 */ + { PIN_NUMBER('A', 8), 8, 3 }, /* AVB_TX_CTL */ + { PIN_NUMBER('A', 19), 4, 3 }, /* AVB_TXC */ + { PIN_NUMBER('A', 18), 0, 3 }, /* AVB_TD0 */ + } }, { PINMUX_DRIVE_REG("DRVCTRL3", 0xe606030c) { - { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */ - { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */ - { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */ + { PIN_NUMBER('B', 18), 28, 3 }, /* AVB_TD1 */ + { PIN_NUMBER('A', 17), 24, 3 }, /* AVB_TD2 */ + { PIN_NUMBER('B', 17), 20, 3 }, /* AVB_TD3 */ + { PIN_NUMBER('A', 12), 16, 3 }, /* AVB_TXCREFCLK */ + { PIN_NUMBER('A', 9), 12, 3 }, /* AVB_MDIO */ + { RCAR_GP_PIN(2, 9), 8, 3 }, /* AVB_MDC */ + { RCAR_GP_PIN(2, 10), 4, 3 }, /* AVB_MAGIC */ + { RCAR_GP_PIN(2, 11), 0, 3 }, /* AVB_PHY_INT */ } }, { PINMUX_DRIVE_REG("DRVCTRL4", 0xe6060310) { { RCAR_GP_PIN(2, 12), 28, 3 }, /* AVB_LINK */ @@ -5008,6 +5128,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = { { RCAR_GP_PIN(1, 19), 0, 3 }, /* A19 */ } }, { PINMUX_DRIVE_REG("DRVCTRL8", 0xe6060320) { + { PIN_NUMBER('F', 1), 28, 3 }, /* CLKOUT */ { RCAR_GP_PIN(1, 20), 24, 3 }, /* CS0 */ { RCAR_GP_PIN(1, 21), 20, 3 }, /* CS1_A26 */ { RCAR_GP_PIN(1, 22), 16, 3 }, /* BS */ @@ -5018,6 +5139,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = { } }, { PINMUX_DRIVE_REG("DRVCTRL9", 0xe6060324) { { RCAR_GP_PIN(1, 27), 28, 3 }, /* EX_WAIT0 */ + { PIN_NUMBER('C', 1), 24, 3 }, /* PRESETOUT# */ { RCAR_GP_PIN(0, 0), 20, 3 }, /* D0 */ { RCAR_GP_PIN(0, 1), 16, 3 }, /* D1 */ { RCAR_GP_PIN(0, 2), 12, 3 }, /* D2 */ @@ -5036,20 +5158,30 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = { { RCAR_GP_PIN(0, 13), 0, 3 }, /* D13 */ } }, { PINMUX_DRIVE_REG("DRVCTRL11", 0xe606032c) { - { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */ - { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */ - { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */ - { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */ - { RCAR_GP_PIN(7, 2), 12, 3 }, /* HDMI0_CEC */ - { RCAR_GP_PIN(7, 3), 8, 3 }, /* HDMI1_CEC */ + { RCAR_GP_PIN(0, 14), 28, 3 }, /* D14 */ + { RCAR_GP_PIN(0, 15), 24, 3 }, /* D15 */ + { RCAR_GP_PIN(7, 0), 20, 3 }, /* AVS1 */ + { RCAR_GP_PIN(7, 1), 16, 3 }, /* AVS2 */ + { RCAR_GP_PIN(7, 2), 12, 3 }, /* HDMI0_CEC */ + { RCAR_GP_PIN(7, 3), 8, 3 }, /* HDMI1_CEC */ + { PIN_A_NUMBER('P', 7), 4, 2 }, /* DU_DOTCLKIN0 */ + { PIN_A_NUMBER('P', 8), 0, 2 }, /* DU_DOTCLKIN1 */ + } }, + { PINMUX_DRIVE_REG("DRVCTRL12", 0xe6060330) { + { PIN_A_NUMBER('R', 7), 28, 2 }, /* DU_DOTCLKIN2 */ + { PIN_A_NUMBER('R', 8), 24, 2 }, /* DU_DOTCLKIN3 */ + { PIN_A_NUMBER('D', 38), 20, 2 }, /* FSCLKST# */ + { PIN_A_NUMBER('R', 30), 4, 2 }, /* TMS */ } }, { PINMUX_DRIVE_REG("DRVCTRL13", 0xe6060334) { - { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */ - { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */ - { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */ - { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */ - { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */ - { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */ + { PIN_A_NUMBER('T', 28), 28, 2 }, /* TDO */ + { PIN_A_NUMBER('T', 30), 24, 2 }, /* ASEBRK */ + { RCAR_GP_PIN(3, 0), 20, 3 }, /* SD0_CLK */ + { RCAR_GP_PIN(3, 1), 16, 3 }, /* SD0_CMD */ + { RCAR_GP_PIN(3, 2), 12, 3 }, /* SD0_DAT0 */ + { RCAR_GP_PIN(3, 3), 8, 3 }, /* SD0_DAT1 */ + { RCAR_GP_PIN(3, 4), 4, 3 }, /* SD0_DAT2 */ + { RCAR_GP_PIN(3, 5), 0, 3 }, /* SD0_DAT3 */ } }, { PINMUX_DRIVE_REG("DRVCTRL14", 0xe6060338) { { RCAR_GP_PIN(3, 6), 28, 3 }, /* SD1_CLK */ @@ -5118,6 +5250,7 @@ static const struct pinmux_drive_reg pinmux_drive_regs[] = { { RCAR_GP_PIN(5, 23), 16, 3 }, /* MLB_CLK */ { RCAR_GP_PIN(5, 24), 12, 3 }, /* MLB_SIG */ { RCAR_GP_PIN(5, 25), 8, 3 }, /* MLB_DAT */ + { PIN_NUMBER('H', 37), 4, 3 }, /* MLB_REF */ { RCAR_GP_PIN(6, 0), 0, 3 }, /* SSI_SCK01239 */ } }, { PINMUX_DRIVE_REG("DRVCTRL21", 0xe6060354) { -- cgit 1.4.1 From b25719eb938eb39aeaaa9535f7b70405d6ff2700 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 11 Nov 2016 21:33:40 +0100 Subject: pinctrl: sh-pfc: r8a7795: Add group for AVB MDIO and MII pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group the AVB pins into similar groups found in other sh-pfc drivers. The pins can not be muxed between functions other then AVB but their drive strength can be controlled. The group avb_mdc containing ADV_MDC and ADV_MDIO are on other SoCs called avb_mdio. In pfc-r8a7795 the avb_mdc group already existed and is in use in DT. Therefore add the ADV_MDIO pin to the existing group instead of renaming it. Signed-off-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index a69c5dce89a4..d9923c6096d2 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -1648,11 +1648,33 @@ static const unsigned int avb_phy_int_mux[] = { AVB_PHY_INT_MARK, }; static const unsigned int avb_mdc_pins[] = { - /* AVB_MDC */ - RCAR_GP_PIN(2, 9), + /* AVB_MDC, AVB_MDIO */ + RCAR_GP_PIN(2, 9), PIN_NUMBER('A', 9), }; static const unsigned int avb_mdc_mux[] = { - AVB_MDC_MARK, + AVB_MDC_MARK, AVB_MDIO_MARK, +}; +static const unsigned int avb_mii_pins[] = { + /* + * AVB_TX_CTL, AVB_TXC, AVB_TD0, + * AVB_TD1, AVB_TD2, AVB_TD3, + * AVB_RX_CTL, AVB_RXC, AVB_RD0, + * AVB_RD1, AVB_RD2, AVB_RD3, + * AVB_TXCREFCLK + */ + PIN_NUMBER('A', 8), PIN_NUMBER('A', 19), PIN_NUMBER('A', 18), + PIN_NUMBER('B', 18), PIN_NUMBER('A', 17), PIN_NUMBER('B', 17), + PIN_NUMBER('A', 16), PIN_NUMBER('B', 19), PIN_NUMBER('A', 13), + PIN_NUMBER('B', 13), PIN_NUMBER('A', 14), PIN_NUMBER('B', 14), + PIN_NUMBER('A', 12), + +}; +static const unsigned int avb_mii_mux[] = { + AVB_TX_CTL_MARK, AVB_TXC_MARK, AVB_TD0_MARK, + AVB_TD1_MARK, AVB_TD2_MARK, AVB_TD3_MARK, + AVB_RX_CTL_MARK, AVB_RXC_MARK, AVB_RD0_MARK, + AVB_RD1_MARK, AVB_RD2_MARK, AVB_RD3_MARK, + AVB_TXCREFCLK_MARK, }; static const unsigned int avb_avtp_pps_pins[] = { /* AVB_AVTP_PPS */ @@ -3720,6 +3742,7 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(avb_magic), SH_PFC_PIN_GROUP(avb_phy_int), SH_PFC_PIN_GROUP(avb_mdc), + SH_PFC_PIN_GROUP(avb_mii), SH_PFC_PIN_GROUP(avb_avtp_pps), SH_PFC_PIN_GROUP(avb_avtp_match_a), SH_PFC_PIN_GROUP(avb_avtp_capture_a), @@ -4024,6 +4047,7 @@ static const char * const avb_groups[] = { "avb_magic", "avb_phy_int", "avb_mdc", + "avb_mii", "avb_avtp_pps", "avb_avtp_match_a", "avb_avtp_capture_a", -- cgit 1.4.1 From 1fa1522f61f1fa53b2518c82bb3c667161836e10 Mon Sep 17 00:00:00 2001 From: Niklas Söderlund Date: Fri, 11 Nov 2016 21:33:41 +0100 Subject: pinctrl: sh-pfc: r8a7795: Add group for QSPI0 and QSPI1 pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Group the QSPI0 and QSPI1 pins into similar groups found in other sh-pfc drivers. The pins can not be muxed between functions other than QSPI, but their drive strength can be controlled. Signed-off-by: Niklas Söderlund Signed-off-by: Geert Uytterhoeven --- drivers/pinctrl/sh-pfc/pfc-r8a7795.c | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c index d9923c6096d2..135ed5cbeb44 100644 --- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c @@ -3720,6 +3720,55 @@ static const unsigned int usb2_mux[] = { USB2_PWEN_MARK, USB2_OVC_MARK, }; +/* - QSPI0 ------------------------------------------------------------------ */ +static const unsigned int qspi0_ctrl_pins[] = { + /* QSPI0_SPCLK, QSPI0_SSL */ + PIN_NUMBER('W', 3), PIN_NUMBER('Y', 3), +}; +static const unsigned int qspi0_ctrl_mux[] = { + QSPI0_SPCLK_MARK, QSPI0_SSL_MARK, +}; +static const unsigned int qspi0_data2_pins[] = { + /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1 */ + PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4), +}; +static const unsigned int qspi0_data2_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, +}; +static const unsigned int qspi0_data4_pins[] = { + /* QSPI0_MOSI_IO0, QSPI0_MISO_IO1, QSPI0_IO2, QSPI0_IO3 */ + PIN_A_NUMBER('C', 5), PIN_A_NUMBER('B', 4), + PIN_NUMBER('Y', 6), PIN_A_NUMBER('B', 6), +}; +static const unsigned int qspi0_data4_mux[] = { + QSPI0_MOSI_IO0_MARK, QSPI0_MISO_IO1_MARK, + QSPI0_IO2_MARK, QSPI0_IO3_MARK, +}; +/* - QSPI1 ------------------------------------------------------------------ */ +static const unsigned int qspi1_ctrl_pins[] = { + /* QSPI1_SPCLK, QSPI1_SSL */ + PIN_NUMBER('V', 3), PIN_NUMBER('V', 5), +}; +static const unsigned int qspi1_ctrl_mux[] = { + QSPI1_SPCLK_MARK, QSPI1_SSL_MARK, +}; +static const unsigned int qspi1_data2_pins[] = { + /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1 */ + PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5), +}; +static const unsigned int qspi1_data2_mux[] = { + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, +}; +static const unsigned int qspi1_data4_pins[] = { + /* QSPI1_MOSI_IO0, QSPI1_MISO_IO1, QSPI1_IO2, QSPI1_IO3 */ + PIN_A_NUMBER('C', 7), PIN_A_NUMBER('E', 5), + PIN_A_NUMBER('E', 4), PIN_A_NUMBER('C', 3), +}; +static const unsigned int qspi1_data4_mux[] = { + QSPI1_MOSI_IO0_MARK, QSPI1_MISO_IO1_MARK, + QSPI1_IO2_MARK, QSPI1_IO3_MARK, +}; + static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(audio_clk_a_a), SH_PFC_PIN_GROUP(audio_clk_a_b), @@ -4020,6 +4069,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = { SH_PFC_PIN_GROUP(usb0), SH_PFC_PIN_GROUP(usb1), SH_PFC_PIN_GROUP(usb2), + SH_PFC_PIN_GROUP(qspi0_ctrl), + SH_PFC_PIN_GROUP(qspi0_data2), + SH_PFC_PIN_GROUP(qspi0_data4), + SH_PFC_PIN_GROUP(qspi1_ctrl), + SH_PFC_PIN_GROUP(qspi1_data2), + SH_PFC_PIN_GROUP(qspi1_data4), }; static const char * const audio_clk_groups[] = { @@ -4465,6 +4520,18 @@ static const char * const usb2_groups[] = { "usb2", }; +static const char * const qspi0_groups[] = { + "qspi0_ctrl", + "qspi0_data2", + "qspi0_data4", +}; + +static const char * const qspi1_groups[] = { + "qspi1_ctrl", + "qspi1_data2", + "qspi1_data4", +}; + static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(audio_clk), SH_PFC_FUNCTION(avb), @@ -4514,6 +4581,8 @@ static const struct sh_pfc_function pinmux_functions[] = { SH_PFC_FUNCTION(usb0), SH_PFC_FUNCTION(usb1), SH_PFC_FUNCTION(usb2), + SH_PFC_FUNCTION(qspi0), + SH_PFC_FUNCTION(qspi1), }; static const struct pinmux_cfg_reg pinmux_config_regs[] = { -- cgit 1.4.1 From 688daf234fa3b61019efa2beea544a3e173a251d Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 15 Nov 2016 18:02:43 +0800 Subject: pinctrl: rockchip: add support for rk1108 This add pinctrl support for Rockchip RK1108 Soc. Signed-off-by: Andy Yan Reviewed-by: Heiko Stuebner Series-changes: 2 - add pull and drive-strength functionality Series-changes: 3 - two minor CodingStyle fixes adviced by Heiko Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 86 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index 49bf7dcb7ed8..08765f58253c 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -59,6 +59,7 @@ #define GPIO_LS_SYNC 0x60 enum rockchip_pinctrl_type { + RK1108, RK2928, RK3066B, RK3188, @@ -624,6 +625,65 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) return ret; } +#define RK1108_PULL_PMU_OFFSET 0x10 +#define RK1108_PULL_OFFSET 0x110 +#define RK1108_PULL_PINS_PER_REG 8 +#define RK1108_PULL_BITS_PER_PIN 2 +#define RK1108_PULL_BANK_STRIDE 16 + +static void rk1108_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + + /* The first 24 pins of the first bank are located in PMU */ + if (bank->bank_num == 0) { + *regmap = info->regmap_pmu; + *reg = RK1108_PULL_PMU_OFFSET; + } else { + *reg = RK1108_PULL_OFFSET; + *regmap = info->regmap_base; + /* correct the offset, as we're starting with the 2nd bank */ + *reg -= 0x10; + *reg += bank->bank_num * RK1108_PULL_BANK_STRIDE; + } + + *reg += ((pin_num / RK1108_PULL_PINS_PER_REG) * 4); + *bit = (pin_num % RK1108_PULL_PINS_PER_REG); + *bit *= RK1108_PULL_BITS_PER_PIN; +} + +#define RK1108_DRV_PMU_OFFSET 0x20 +#define RK1108_DRV_GRF_OFFSET 0x210 +#define RK1108_DRV_BITS_PER_PIN 2 +#define RK1108_DRV_PINS_PER_REG 8 +#define RK1108_DRV_BANK_STRIDE 16 + +static void rk1108_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl *info = bank->drvdata; + + /* The first 24 pins of the first bank are located in PMU */ + if (bank->bank_num == 0) { + *regmap = info->regmap_pmu; + *reg = RK1108_DRV_PMU_OFFSET; + } else { + *regmap = info->regmap_base; + *reg = RK1108_DRV_GRF_OFFSET; + + /* correct the offset, as we're starting with the 2nd bank */ + *reg -= 0x10; + *reg += bank->bank_num * RK1108_DRV_BANK_STRIDE; + } + + *reg += ((pin_num / RK1108_DRV_PINS_PER_REG) * 4); + *bit = pin_num % RK1108_DRV_PINS_PER_REG; + *bit *= RK1108_DRV_BITS_PER_PIN; +} + #define RK2928_PULL_OFFSET 0x118 #define RK2928_PULL_PINS_PER_REG 16 #define RK2928_PULL_BANK_STRIDE 8 @@ -1123,6 +1183,7 @@ static int rockchip_get_pull(struct rockchip_pin_bank *bank, int pin_num) return !(data & BIT(bit)) ? PIN_CONFIG_BIAS_PULL_PIN_DEFAULT : PIN_CONFIG_BIAS_DISABLE; + case RK1108: case RK3188: case RK3288: case RK3368: @@ -1169,6 +1230,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank, spin_unlock_irqrestore(&bank->slock, flags); break; + case RK1108: case RK3188: case RK3288: case RK3368: @@ -1358,6 +1420,7 @@ static bool rockchip_pinconf_pull_valid(struct rockchip_pin_ctrl *ctrl, pull == PIN_CONFIG_BIAS_DISABLE); case RK3066B: return pull ? false : true; + case RK1108: case RK3188: case RK3288: case RK3368: @@ -2455,6 +2518,27 @@ static int rockchip_pinctrl_probe(struct platform_device *pdev) return 0; } +static struct rockchip_pin_bank rk1108_pin_banks[] = { + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_SOURCE_PMU, + IOMUX_SOURCE_PMU, + IOMUX_SOURCE_PMU, + IOMUX_SOURCE_PMU), + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", 0, 0, 0, 0), + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", 0, 0, 0, 0), + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", 0, 0, 0, 0), +}; + +static struct rockchip_pin_ctrl rk1108_pin_ctrl = { + .pin_banks = rk1108_pin_banks, + .nr_banks = ARRAY_SIZE(rk1108_pin_banks), + .label = "RK1108-GPIO", + .type = RK1108, + .grf_mux_offset = 0x10, + .pmu_mux_offset = 0x0, + .pull_calc_reg = rk1108_calc_pull_reg_and_bit, + .drv_calc_reg = rk1108_calc_drv_reg_and_bit, +}; + static struct rockchip_pin_bank rk2928_pin_banks[] = { PIN_BANK(0, 32, "gpio0"), PIN_BANK(1, 32, "gpio1"), @@ -2684,6 +2768,8 @@ static struct rockchip_pin_ctrl rk3399_pin_ctrl = { }; static const struct of_device_id rockchip_pinctrl_dt_match[] = { + { .compatible = "rockchip,rk1108-pinctrl", + .data = (void *)&rk1108_pin_ctrl }, { .compatible = "rockchip,rk2928-pinctrl", .data = (void *)&rk2928_pin_ctrl }, { .compatible = "rockchip,rk3036-pinctrl", -- cgit 1.4.1 From d8a22212737314cc02692cc90eda7d844fa20257 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 16 Nov 2016 15:18:18 +0100 Subject: pinctrl: sunxi: fix theoretical uninitialized variable access gcc warns about a way that it could use an uninitialized variable: drivers/pinctrl/sunxi/pinctrl-sunxi.c: In function 'sunxi_pinctrl_init': drivers/pinctrl/sunxi/pinctrl-sunxi.c:1191:8: error: 'best_div' may be used uninitialized in this function [-Werror=maybe-uninitialized] This cannot really happen except if 'freq' is UINT_MAX and 'clock' is zero, and both of these are forbidden. To shut up the warning anyway, this changes the logic to initialize the return code to the first divider value before looking at the others. Fixes: 7c926492d38a ("pinctrl: sunxi: Add support for interrupt debouncing") Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 2339d4718b4d..6b7953da4228 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1125,10 +1125,13 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev) static int sunxi_pinctrl_get_debounce_div(struct clk *clk, int freq, int *diff) { unsigned long clock = clk_get_rate(clk); - unsigned int best_diff = ~0, best_div; + unsigned int best_diff, best_div; int i; - for (i = 0; i < 8; i++) { + best_diff = abs(freq - clock); + best_div = 0; + + for (i = 1; i < 8; i++) { int cur_diff = abs(freq - (clock >> i)); if (cur_diff < best_diff) { -- cgit 1.4.1 From 712778d02d5c24e0bb5cfb9ccb9213496853a57f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Nov 2016 14:41:51 +0300 Subject: pinctrl: single: Fix a couple error codes We should return -ENOMEM instead of success if pcs_add_function() fails. Signed-off-by: Dan Carpenter Acked-by: Tony Lindgren Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-single.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 2b196e53d937..a5a0392ab817 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -1181,8 +1181,10 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, pgnames[0] = np->name; function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1); - if (!function) + if (!function) { + res = -ENOMEM; goto free_pins; + } res = pcs_add_pingroup(pcs, np, np->name, pins, found); if (res < 0) @@ -1313,8 +1315,10 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs, pgnames[0] = np->name; function = pcs_add_function(pcs, np, np->name, vals, found, pgnames, 1); - if (!function) + if (!function) { + res = -ENOMEM; goto free_pins; + } res = pcs_add_pingroup(pcs, np, np->name, pins, found); if (res < 0) -- cgit 1.4.1 From 04d02c7a5ec68debdab8eb71bffe8a9381cb1b1a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 17 Nov 2016 09:47:03 +0100 Subject: pinctrl: nomadik: split up and comments MC0 pins When debugging it helps to see exactly which pin goes where, so make it very detailed. Signed-off-by: Linus Walleij --- drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c index 8392083514fb..af4814479eb0 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c @@ -379,13 +379,24 @@ static const unsigned msp0txrx_a_1_pins[] = { DB8500_PIN_AC4, DB8500_PIN_AC3 }; static const unsigned msp0tfstck_a_1_pins[] = { DB8500_PIN_AF3, DB8500_PIN_AE3 }; static const unsigned msp0rfsrck_a_1_pins[] = { DB8500_PIN_AD3, DB8500_PIN_AD4 }; /* Basic pins of the MMC/SD card 0 interface */ -static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, DB8500_PIN_AC1, - DB8500_PIN_AB4, DB8500_PIN_AA3, DB8500_PIN_AA4, DB8500_PIN_AB2, - DB8500_PIN_Y4, DB8500_PIN_Y2, DB8500_PIN_AA2, DB8500_PIN_AA1 }; +static const unsigned mc0_a_1_pins[] = { DB8500_PIN_AC2, /* MC0_CMDDIR */ + DB8500_PIN_AC1, /* MC0_DAT0DIR */ + DB8500_PIN_AB4, /* MC0_DAT2DIR */ + DB8500_PIN_AA3, /* MC0_FBCLK */ + DB8500_PIN_AA4, /* MC0_CLK */ + DB8500_PIN_AB2, /* MC0_CMD */ + DB8500_PIN_Y4, /* MC0_DAT0 */ + DB8500_PIN_Y2, /* MC0_DAT1 */ + DB8500_PIN_AA2, /* MC0_DAT2 */ + DB8500_PIN_AA1 /* MC0_DAT3 */ +}; /* Often only 4 bits are used, then these are not needed (only used for MMC) */ -static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, DB8500_PIN_W3, - DB8500_PIN_V3, DB8500_PIN_V2}; -static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 }; +static const unsigned mc0_dat47_a_1_pins[] = { DB8500_PIN_W2, /* MC0_DAT4 */ + DB8500_PIN_W3, /* MC0_DAT5 */ + DB8500_PIN_V3, /* MC0_DAT6 */ + DB8500_PIN_V2 /* MC0_DAT7 */ +}; +static const unsigned mc0dat31dir_a_1_pins[] = { DB8500_PIN_AB3 }; /* MC0_DAT31DIR */ /* MSP1 can only be on these pins, but TXD and RXD can be flipped */ static const unsigned msp1txrx_a_1_pins[] = { DB8500_PIN_AF2, DB8500_PIN_AG2 }; static const unsigned msp1_a_1_pins[] = { DB8500_PIN_AE1, DB8500_PIN_AE2 }; -- cgit 1.4.1 From b3cde198b17f504643cc1eeffc4623f03326f436 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 18 Nov 2016 14:35:57 +0300 Subject: pinctrl: sunxi: Testing the wrong variable Smatch complains that we dereference "map" before testing it for NULL which is true. We should be testing "*map" instead. Also on the error path, we should free *map and set it to NULL. Signed-off-by: Dan Carpenter Acked-by: Maxime Ripard Signed-off-by: Linus Walleij --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 6b7953da4228..0eb51e33cb1b 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -398,13 +398,14 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev, * map array */ *map = krealloc(*map, i * sizeof(struct pinctrl_map), GFP_KERNEL); - if (!map) + if (!*map) return -ENOMEM; return 0; err_free_map: - kfree(map); + kfree(*map); + *map = NULL; return ret; } -- cgit 1.4.1 From 5b209efa3fe809831e1e043657536cc3353ce5e9 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Nov 2016 22:12:30 +0800 Subject: pinctrl: stm32: use builtin_platform_driver Use builtin_platform_driver() helper to simplify the code. Signed-off-by: Geliang Tang Signed-off-by: Linus Walleij --- drivers/pinctrl/stm32/pinctrl-stm32f429.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/stm32/pinctrl-stm32f429.c b/drivers/pinctrl/stm32/pinctrl-stm32f429.c index e9b15dc0654b..990b867b9625 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32f429.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32f429.c @@ -1584,8 +1584,4 @@ static struct platform_driver stm32f429_pinctrl_driver = { }, }; -static int __init stm32f429_pinctrl_init(void) -{ - return platform_driver_register(&stm32f429_pinctrl_driver); -} -device_initcall(stm32f429_pinctrl_init); +builtin_platform_driver(stm32f429_pinctrl_driver); -- cgit 1.4.1 From 4ecb65fb87b6591f90e1baef52c7f22757c30a2d Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Fri, 18 Nov 2016 22:12:29 +0800 Subject: pinctrl: mediatek: use builtin_platform_driver Use builtin_platform_driver() helper to simplify the code. Signed-off-by: Geliang Tang Acked-by: Hongzhou Yang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mt6397.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mt6397.c b/drivers/pinctrl/mediatek/pinctrl-mt6397.c index 6eccb85c02cd..afcede7e2222 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mt6397.c +++ b/drivers/pinctrl/mediatek/pinctrl-mt6397.c @@ -64,8 +64,4 @@ static struct platform_driver mtk_pinctrl_driver = { }, }; -static int __init mtk_pinctrl_init(void) -{ - return platform_driver_register(&mtk_pinctrl_driver); -} -device_initcall(mtk_pinctrl_init); +builtin_platform_driver(mtk_pinctrl_driver); -- cgit 1.4.1 From 7bd474963a4826af91a72bf12bb57cc79f8b6ad7 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 23 Nov 2016 11:18:50 +0100 Subject: pinctrl: sx150x: various spelling fixes and some white-space cleanup Acked-by: Neil Armstrong Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 63778058eec7..ef4ef88e0ee9 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -384,7 +384,7 @@ static int sx150x_gpio_oscio_set(struct sx150x_pinctrl *pctl, } static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) + int value) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); @@ -396,7 +396,7 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, } static int sx150x_gpio_direction_input(struct gpio_chip *chip, - unsigned int offset) + unsigned int offset) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); @@ -409,7 +409,7 @@ static int sx150x_gpio_direction_input(struct gpio_chip *chip, } static int sx150x_gpio_direction_output(struct gpio_chip *chip, - unsigned int offset, int value) + unsigned int offset, int value) { struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); int ret; @@ -880,7 +880,7 @@ static unsigned int sx150x_maybe_swizzle(struct sx150x_pinctrl *pctl, * reg + 3 [ 3 3 2 2 1 1 0 0 ] * * SX1503 and SX1506 deviate from that data layout, instead storing - * thier contents as follows: + * their contents as follows: * * reg [ f f e e d d c c ] * reg + 1 [ 7 7 6 6 5 5 4 4 ] @@ -915,9 +915,8 @@ static unsigned int sx150x_maybe_swizzle(struct sx150x_pinctrl *pctl, * * This way the rest of the driver code, interfacing with the chip via * regmap API, can work assuming that each GPIO pin is represented by - * a group of bits at an offset proportioan to GPIO number within a + * a group of bits at an offset proportional to GPIO number within a * given register. - * */ static int sx150x_regmap_reg_read(void *context, unsigned int reg, unsigned int *result) @@ -929,7 +928,7 @@ static int sx150x_regmap_reg_read(void *context, unsigned int reg, unsigned int idx, val; /* - * There are four potential cases coverd by this function: + * There are four potential cases covered by this function: * * 1) 8-pin chip, single configuration bit register * -- cgit 1.4.1 From ec61168bc0bc03a6e7da3802ac41a113ed6c8160 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Wed, 23 Nov 2016 11:18:51 +0100 Subject: pinctrl: sx150x: support setting multiple pins at once If the chip does not have an oscio pin, all pins are configured in the same regmap register making it trivial to update all pins at once, so do that. If an oscio pin is present, there needs to be more locking in place to handle all cases correctly, so this is skipped. Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index ef4ef88e0ee9..f9e559e22537 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -395,6 +395,15 @@ static void sx150x_gpio_set(struct gpio_chip *chip, unsigned int offset, } +static void sx150x_gpio_set_multiple(struct gpio_chip *chip, + unsigned long *mask, + unsigned long *bits) +{ + struct sx150x_pinctrl *pctl = gpiochip_get_data(chip); + + regmap_write_bits(pctl->regmap, pctl->data->reg_data, *mask, *bits); +} + static int sx150x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) { @@ -1075,6 +1084,14 @@ static int sx150x_probe(struct i2c_client *client, pctl->gpio.of_node = dev->of_node; #endif pctl->gpio.can_sleep = true; + /* + * Setting multiple pins is not safe when all pins are not + * handled by the same regmap register. The oscio pin (present + * on the SX150X_789 chips) lives in its own register, so + * would require locking that is not in place at this time. + */ + if (pctl->data->model != SX150X_789) + pctl->gpio.set_multiple = sx150x_gpio_set_multiple; ret = devm_gpiochip_add_data(dev, &pctl->gpio, pctl); if (ret) -- cgit 1.4.1 From 8f5983ad6b81070376db9487ce81000c85a16027 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Thu, 24 Nov 2016 19:11:51 +0100 Subject: pinctrl: imx: fix imx_pinctrl_desc initialization Fixes: 6e408ed8be0e ("pinctrl: imx: fix initialization of imx_pinctrl_desc") Reviewed-by: Vladimir Zapolskiy Reviewed-by: Peng Fan Signed-off-by: Gary Bisson Signed-off-by: Linus Walleij --- drivers/pinctrl/freescale/pinctrl-imx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c index 47613201269a..97e9ddc84467 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx.c +++ b/drivers/pinctrl/freescale/pinctrl-imx.c @@ -777,10 +777,10 @@ int imx_pinctrl_probe(struct platform_device *pdev, imx_pinctrl_desc->name = dev_name(&pdev->dev); imx_pinctrl_desc->pins = info->pins; imx_pinctrl_desc->npins = info->npins; - imx_pinctrl_desc->pctlops = &imx_pctrl_ops, - imx_pinctrl_desc->pmxops = &imx_pmx_ops, - imx_pinctrl_desc->confops = &imx_pinconf_ops, - imx_pinctrl_desc->owner = THIS_MODULE, + imx_pinctrl_desc->pctlops = &imx_pctrl_ops; + imx_pinctrl_desc->pmxops = &imx_pmx_ops; + imx_pinctrl_desc->confops = &imx_pinconf_ops; + imx_pinctrl_desc->owner = THIS_MODULE; ret = imx_pinctrl_probe_dt(pdev, info); if (ret) { -- cgit 1.4.1 From 1663682cf090b94bd8531a0b9be812e10477143f Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 24 Nov 2016 21:45:18 +0100 Subject: pinctrl: sx150x: use correct registers for reg_sense (sx1502 and sx1508) All other registers on these chips are 8-bit, but reg_sense is 16-bits and therefore needs to be moved down one notch. This was apparently overlooked in the conversion to regmap, which only updated the register locations for the 16-bit chips. Fixes: 6489677f86c3 ("pinctrl-sx150x: Replace sx150x_*_cfg by means of regmap API") Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index f9e559e22537..a19c814843aa 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -156,7 +156,7 @@ static const struct sx150x_device_data sx1508q_device_data = { .reg_data = 0x08, .reg_irq_mask = 0x09, .reg_irq_src = 0x0c, - .reg_sense = 0x0b, + .reg_sense = 0x0a, .pri.x789 = { .reg_drain = 0x05, .reg_polarity = 0x06, @@ -221,7 +221,7 @@ static const struct sx150x_device_data sx1502q_device_data = { .reg_data = 0x00, .reg_irq_mask = 0x05, .reg_irq_src = 0x08, - .reg_sense = 0x07, + .reg_sense = 0x06, .pri.x123 = { .reg_pld_mode = 0x10, .reg_pld_table0 = 0x11, -- cgit 1.4.1 From bba709bd7ad7075e68af8029483e1dd8c8480890 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 24 Nov 2016 21:45:19 +0100 Subject: pinctrl: sx150x: sort chips by part number Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/pinctrl-sx150x.txt | 6 +- drivers/pinctrl/pinctrl-sx150x.c | 142 ++++++++++----------- 2 files changed, 74 insertions(+), 74 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt index 25b4ec80c759..83f8d5c449ba 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt @@ -6,11 +6,11 @@ pin controller, GPIO, and interrupt bindings. Required properties: - compatible: should be one of : + "semtech,sx1502q", + "semtech,sx1503q", "semtech,sx1506q", "semtech,sx1508q", - "semtech,sx1509q", - "semtech,sx1502q", - "semtech,sx1503q". + "semtech,sx1509q". - reg: The I2C slave address for this device. diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index a19c814843aa..97df9302e84b 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -148,71 +148,6 @@ static const struct pinctrl_pin_desc sx150x_16_pins[] = { PINCTRL_PIN(16, "oscio"), }; -static const struct sx150x_device_data sx1508q_device_data = { - .model = SX150X_789, - .reg_pullup = 0x03, - .reg_pulldn = 0x04, - .reg_dir = 0x07, - .reg_data = 0x08, - .reg_irq_mask = 0x09, - .reg_irq_src = 0x0c, - .reg_sense = 0x0a, - .pri.x789 = { - .reg_drain = 0x05, - .reg_polarity = 0x06, - .reg_clock = 0x0f, - .reg_misc = 0x10, - .reg_reset = 0x7d, - }, - .ngpios = 8, - .pins = sx150x_8_pins, - .npins = ARRAY_SIZE(sx150x_8_pins), -}; - -static const struct sx150x_device_data sx1509q_device_data = { - .model = SX150X_789, - .reg_pullup = 0x06, - .reg_pulldn = 0x08, - .reg_dir = 0x0e, - .reg_data = 0x10, - .reg_irq_mask = 0x12, - .reg_irq_src = 0x18, - .reg_sense = 0x14, - .pri.x789 = { - .reg_drain = 0x0a, - .reg_polarity = 0x0c, - .reg_clock = 0x1e, - .reg_misc = 0x1f, - .reg_reset = 0x7d, - }, - .ngpios = 16, - .pins = sx150x_16_pins, - .npins = ARRAY_SIZE(sx150x_16_pins), -}; - -static const struct sx150x_device_data sx1506q_device_data = { - .model = SX150X_456, - .reg_pullup = 0x04, - .reg_pulldn = 0x06, - .reg_dir = 0x02, - .reg_data = 0x00, - .reg_irq_mask = 0x08, - .reg_irq_src = 0x0e, - .reg_sense = 0x0a, - .pri.x456 = { - .reg_pld_mode = 0x20, - .reg_pld_table0 = 0x22, - .reg_pld_table1 = 0x24, - .reg_pld_table2 = 0x26, - .reg_pld_table3 = 0x28, - .reg_pld_table4 = 0x2a, - .reg_advance = 0xad, - }, - .ngpios = 16, - .pins = sx150x_16_pins, - .npins = 16, /* oscio not available */ -}; - static const struct sx150x_device_data sx1502q_device_data = { .model = SX150X_123, .reg_pullup = 0x02, @@ -259,6 +194,71 @@ static const struct sx150x_device_data sx1503q_device_data = { .npins = 16, /* oscio not available */ }; +static const struct sx150x_device_data sx1506q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x04, + .reg_pulldn = 0x06, + .reg_dir = 0x02, + .reg_data = 0x00, + .reg_irq_mask = 0x08, + .reg_irq_src = 0x0e, + .reg_sense = 0x0a, + .pri.x456 = { + .reg_pld_mode = 0x20, + .reg_pld_table0 = 0x22, + .reg_pld_table1 = 0x24, + .reg_pld_table2 = 0x26, + .reg_pld_table3 = 0x28, + .reg_pld_table4 = 0x2a, + .reg_advance = 0xad, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = 16, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1508q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x03, + .reg_pulldn = 0x04, + .reg_dir = 0x07, + .reg_data = 0x08, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0c, + .reg_sense = 0x0a, + .pri.x789 = { + .reg_drain = 0x05, + .reg_polarity = 0x06, + .reg_clock = 0x0f, + .reg_misc = 0x10, + .reg_reset = 0x7d, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = ARRAY_SIZE(sx150x_8_pins), +}; + +static const struct sx150x_device_data sx1509q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x06, + .reg_pulldn = 0x08, + .reg_dir = 0x0e, + .reg_data = 0x10, + .reg_irq_mask = 0x12, + .reg_irq_src = 0x18, + .reg_sense = 0x14, + .pri.x789 = { + .reg_drain = 0x0a, + .reg_polarity = 0x0c, + .reg_clock = 0x1e, + .reg_misc = 0x1f, + .reg_reset = 0x7d, + }, + .ngpios = 16, + .pins = sx150x_16_pins, + .npins = ARRAY_SIZE(sx150x_16_pins), +}; + static int sx150x_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) { return 0; @@ -758,20 +758,20 @@ static const struct pinconf_ops sx150x_pinconf_ops = { }; static const struct i2c_device_id sx150x_id[] = { - {"sx1508q", (kernel_ulong_t) &sx1508q_device_data }, - {"sx1509q", (kernel_ulong_t) &sx1509q_device_data }, - {"sx1506q", (kernel_ulong_t) &sx1506q_device_data }, {"sx1502q", (kernel_ulong_t) &sx1502q_device_data }, {"sx1503q", (kernel_ulong_t) &sx1503q_device_data }, + {"sx1506q", (kernel_ulong_t) &sx1506q_device_data }, + {"sx1508q", (kernel_ulong_t) &sx1508q_device_data }, + {"sx1509q", (kernel_ulong_t) &sx1509q_device_data }, {} }; static const struct of_device_id sx150x_of_match[] = { - { .compatible = "semtech,sx1508q", .data = &sx1508q_device_data }, - { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data }, - { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data }, { .compatible = "semtech,sx1502q", .data = &sx1502q_device_data }, { .compatible = "semtech,sx1503q", .data = &sx1503q_device_data }, + { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data }, + { .compatible = "semtech,sx1508q", .data = &sx1508q_device_data }, + { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data }, {}, }; -- cgit 1.4.1 From 4f5ac8cf0a1121144432fd0175fac9ec31f58cd0 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Thu, 24 Nov 2016 21:45:20 +0100 Subject: pinctrl: sx150x: add support for sx1501, sx1504, sx1505 and sx1507 Untested, register offsets carefully copied from datasheets. Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- .../devicetree/bindings/pinctrl/pinctrl-sx150x.txt | 8 +- drivers/pinctrl/pinctrl-sx150x.c | 98 ++++++++++++++++++++++ 2 files changed, 104 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt index 83f8d5c449ba..bf76867168e9 100644 --- a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt +++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt @@ -6,9 +6,13 @@ pin controller, GPIO, and interrupt bindings. Required properties: - compatible: should be one of : + "semtech,sx1501q", "semtech,sx1502q", "semtech,sx1503q", + "semtech,sx1504q", + "semtech,sx1505q", "semtech,sx1506q", + "semtech,sx1507q", "semtech,sx1508q", "semtech,sx1509q". @@ -28,7 +32,7 @@ Optional properties : - interrupt-controller: Marks the device as a interrupt controller. - semtech,probe-reset: Will trigger a reset of the GPIO expander on probe, - only for sx1508q and sx1509q + only for sx1507q, sx1508q and sx1509q The GPIO expander can optionally be used as an interrupt controller, in which case it uses the default two cell specifier. @@ -43,7 +47,7 @@ Optional properties for pin configuration sub-nodes: - bias-pull-down: pull down the pin, except the OSCIO pin - bias-pull-pin-default: use pin-default pull state, except the OSCIO pin - drive-push-pull: drive actively high and low - - drive-open-drain: drive with open drain only for sx1508q and sx1509q and except the OSCIO pin + - drive-open-drain: drive with open drain only for sx1507q, sx1508q and sx1509q and except the OSCIO pin - output-low: set the pin to output mode with low level - output-high: set the pin to output mode with high level diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 97df9302e84b..1a1c8b51a992 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -116,6 +116,14 @@ struct sx150x_pinctrl { const struct sx150x_device_data *data; }; +static const struct pinctrl_pin_desc sx150x_4_pins[] = { + PINCTRL_PIN(0, "gpio0"), + PINCTRL_PIN(1, "gpio1"), + PINCTRL_PIN(2, "gpio2"), + PINCTRL_PIN(3, "gpio3"), + PINCTRL_PIN(4, "oscio"), +}; + static const struct pinctrl_pin_desc sx150x_8_pins[] = { PINCTRL_PIN(0, "gpio0"), PINCTRL_PIN(1, "gpio1"), @@ -148,6 +156,26 @@ static const struct pinctrl_pin_desc sx150x_16_pins[] = { PINCTRL_PIN(16, "oscio"), }; +static const struct sx150x_device_data sx1501q_device_data = { + .model = SX150X_123, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x07, + .pri.x123 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table2 = 0x13, + .reg_advance = 0xad, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = 4, /* oscio not available */ +}; + static const struct sx150x_device_data sx1502q_device_data = { .model = SX150X_123, .reg_pullup = 0x02, @@ -194,6 +222,47 @@ static const struct sx150x_device_data sx1503q_device_data = { .npins = 16, /* oscio not available */ }; +static const struct sx150x_device_data sx1504q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x07, + .pri.x456 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table2 = 0x13, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = 4, /* oscio not available */ +}; + +static const struct sx150x_device_data sx1505q_device_data = { + .model = SX150X_456, + .reg_pullup = 0x02, + .reg_pulldn = 0x03, + .reg_dir = 0x01, + .reg_data = 0x00, + .reg_irq_mask = 0x05, + .reg_irq_src = 0x08, + .reg_sense = 0x06, + .pri.x456 = { + .reg_pld_mode = 0x10, + .reg_pld_table0 = 0x11, + .reg_pld_table1 = 0x12, + .reg_pld_table2 = 0x13, + .reg_pld_table3 = 0x14, + .reg_pld_table4 = 0x15, + }, + .ngpios = 8, + .pins = sx150x_8_pins, + .npins = 8, /* oscio not available */ +}; + static const struct sx150x_device_data sx1506q_device_data = { .model = SX150X_456, .reg_pullup = 0x04, @@ -217,6 +286,27 @@ static const struct sx150x_device_data sx1506q_device_data = { .npins = 16, /* oscio not available */ }; +static const struct sx150x_device_data sx1507q_device_data = { + .model = SX150X_789, + .reg_pullup = 0x03, + .reg_pulldn = 0x04, + .reg_dir = 0x07, + .reg_data = 0x08, + .reg_irq_mask = 0x09, + .reg_irq_src = 0x0b, + .reg_sense = 0x0a, + .pri.x789 = { + .reg_drain = 0x05, + .reg_polarity = 0x06, + .reg_clock = 0x0d, + .reg_misc = 0x0e, + .reg_reset = 0x7d, + }, + .ngpios = 4, + .pins = sx150x_4_pins, + .npins = ARRAY_SIZE(sx150x_4_pins), +}; + static const struct sx150x_device_data sx1508q_device_data = { .model = SX150X_789, .reg_pullup = 0x03, @@ -758,18 +848,26 @@ static const struct pinconf_ops sx150x_pinconf_ops = { }; static const struct i2c_device_id sx150x_id[] = { + {"sx1501q", (kernel_ulong_t) &sx1501q_device_data }, {"sx1502q", (kernel_ulong_t) &sx1502q_device_data }, {"sx1503q", (kernel_ulong_t) &sx1503q_device_data }, + {"sx1504q", (kernel_ulong_t) &sx1504q_device_data }, + {"sx1505q", (kernel_ulong_t) &sx1505q_device_data }, {"sx1506q", (kernel_ulong_t) &sx1506q_device_data }, + {"sx1507q", (kernel_ulong_t) &sx1507q_device_data }, {"sx1508q", (kernel_ulong_t) &sx1508q_device_data }, {"sx1509q", (kernel_ulong_t) &sx1509q_device_data }, {} }; static const struct of_device_id sx150x_of_match[] = { + { .compatible = "semtech,sx1501q", .data = &sx1501q_device_data }, { .compatible = "semtech,sx1502q", .data = &sx1502q_device_data }, { .compatible = "semtech,sx1503q", .data = &sx1503q_device_data }, + { .compatible = "semtech,sx1504q", .data = &sx1504q_device_data }, + { .compatible = "semtech,sx1505q", .data = &sx1505q_device_data }, { .compatible = "semtech,sx1506q", .data = &sx1506q_device_data }, + { .compatible = "semtech,sx1507q", .data = &sx1507q_device_data }, { .compatible = "semtech,sx1508q", .data = &sx1508q_device_data }, { .compatible = "semtech,sx1509q", .data = &sx1509q_device_data }, {}, -- cgit 1.4.1 From 3ae02c14d964499da76b5ef4d8912710902e64f8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 25 Nov 2016 13:31:16 +0200 Subject: pinctrl: intel: set default handler to be handle_bad_irq() We switch the default handler to be handle_bad_irq() instead of handle_simple_irq() (which was not correct anyway). Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/intel/pinctrl-baytrail.c | 2 +- drivers/pinctrl/intel/pinctrl-intel.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c index 71bbeb9321ba..37300634b7d2 100644 --- a/drivers/pinctrl/intel/pinctrl-baytrail.c +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -1703,7 +1703,7 @@ static int byt_gpio_probe(struct byt_gpio *vg) if (irq_rc && irq_rc->start) { byt_gpio_irq_init_hw(vg); ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(&vg->pdev->dev, "failed to add irqchip\n"); goto fail; diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 01443762e570..1e139672f1af 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -911,7 +911,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq) } ret = gpiochip_irqchip_add(&pctrl->chip, &intel_gpio_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); + handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "failed to add irqchip\n"); goto fail; -- cgit 1.4.1 From 1ff91f0ae3361f17e42448f6fc7181926ef21587 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 28 Nov 2016 10:40:25 -0600 Subject: pinctrl: New driver for TI DA850/OMAP-L138/AM18XX pinconf This adds a new driver for pinconf on TI DA850/OMAP-L138/AM18XX. These SoCs have a separate controller for controlling pullup/pulldown groups. Signed-off-by: David Lechner Reviewed-by: Sekhar Nori Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 9 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-da850-pupd.c | 210 +++++++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-da850-pupd.c (limited to 'drivers') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 5f40ad64e8f5..54044a8ecbd7 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -93,6 +93,15 @@ config PINCTRL_AMD Requires ACPI/FDT device enumeration code to set up a platform device. +config PINCTRL_DA850_PUPD + tristate "TI DA850/OMAP-L138/AM18XX pullup/pulldown groups" + depends on OF && (ARCH_DAVINCI_DA850 || COMPILE_TEST) + select PINCONF + select GENERIC_PINCONF + help + Driver for TI DA850/OMAP-L138/AM18XX pinconf. Used to control + pullup/pulldown pin groups. + config PINCTRL_DIGICOLOR bool depends on OF && (ARCH_DIGICOLOR || COMPILE_TEST) diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 3b8e6f726acb..25d50a86981d 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_AT91PIO4) += pinctrl-at91-pio4.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o +obj-$(CONFIG_PINCTRL_DA850_PUPD) += pinctrl-da850-pupd.o obj-$(CONFIG_PINCTRL_DIGICOLOR) += pinctrl-digicolor.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_MAX77620) += pinctrl-max77620.o diff --git a/drivers/pinctrl/pinctrl-da850-pupd.c b/drivers/pinctrl/pinctrl-da850-pupd.c new file mode 100644 index 000000000000..b36a90a3f3e4 --- /dev/null +++ b/drivers/pinctrl/pinctrl-da850-pupd.c @@ -0,0 +1,210 @@ +/* + * Pinconf driver for TI DA850/OMAP-L138/AM18XX pullup/pulldown groups + * + * Copyright (C) 2016 David Lechner + * + * 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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DA850_PUPD_ENA 0x00 +#define DA850_PUPD_SEL 0x04 + +struct da850_pupd_data { + void __iomem *base; + struct pinctrl_desc desc; + struct pinctrl_dev *pinctrl; +}; + +static const char * const da850_pupd_group_names[] = { + "cp0", "cp1", "cp2", "cp3", "cp4", "cp5", "cp6", "cp7", + "cp8", "cp9", "cp10", "cp11", "cp12", "cp13", "cp14", "cp15", + "cp16", "cp17", "cp18", "cp19", "cp20", "cp21", "cp22", "cp23", + "cp24", "cp25", "cp26", "cp27", "cp28", "cp29", "cp30", "cp31", +}; + +static int da850_pupd_get_groups_count(struct pinctrl_dev *pctldev) +{ + return ARRAY_SIZE(da850_pupd_group_names); +} + +static const char *da850_pupd_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return da850_pupd_group_names[selector]; +} + +static int da850_pupd_get_group_pins(struct pinctrl_dev *pctldev, + unsigned int selector, + const unsigned int **pins, + unsigned int *num_pins) +{ + *num_pins = 0; + + return 0; +} + +static const struct pinctrl_ops da850_pupd_pctlops = { + .get_groups_count = da850_pupd_get_groups_count, + .get_group_name = da850_pupd_get_group_name, + .get_group_pins = da850_pupd_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_group, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static int da850_pupd_pin_config_group_get(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *config) +{ + struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev); + enum pin_config_param param = pinconf_to_config_param(*config); + u32 val; + u16 arg; + + val = readl(data->base + DA850_PUPD_ENA); + arg = !!(~val & BIT(selector)); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + break; + case PIN_CONFIG_BIAS_PULL_UP: + case PIN_CONFIG_BIAS_PULL_DOWN: + if (arg) { + /* bias is disabled */ + arg = 0; + break; + } + val = readl(data->base + DA850_PUPD_SEL); + if (param == PIN_CONFIG_BIAS_PULL_DOWN) + val = ~val; + arg = !!(val & BIT(selector)); + break; + default: + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int da850_pupd_pin_config_group_set(struct pinctrl_dev *pctldev, + unsigned int selector, + unsigned long *configs, + unsigned int num_configs) +{ + struct da850_pupd_data *data = pinctrl_dev_get_drvdata(pctldev); + u32 ena, sel; + enum pin_config_param param; + u16 arg; + int i; + + ena = readl(data->base + DA850_PUPD_ENA); + sel = readl(data->base + DA850_PUPD_SEL); + + 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_DISABLE: + ena &= ~BIT(selector); + break; + case PIN_CONFIG_BIAS_PULL_UP: + ena |= BIT(selector); + sel |= BIT(selector); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + ena |= BIT(selector); + sel &= ~BIT(selector); + break; + default: + return -EINVAL; + } + } + + writel(sel, data->base + DA850_PUPD_SEL); + writel(ena, data->base + DA850_PUPD_ENA); + + return 0; +} + +static const struct pinconf_ops da850_pupd_confops = { + .is_generic = true, + .pin_config_group_get = da850_pupd_pin_config_group_get, + .pin_config_group_set = da850_pupd_pin_config_group_set, +}; + +static int da850_pupd_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct da850_pupd_data *data; + struct resource *res; + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->base = devm_ioremap_resource(dev, res); + if (IS_ERR(data->base)) { + dev_err(dev, "Could not map resource\n"); + return PTR_ERR(data->base); + } + + data->desc.name = dev_name(dev); + data->desc.pctlops = &da850_pupd_pctlops; + data->desc.confops = &da850_pupd_confops; + data->desc.owner = THIS_MODULE; + + data->pinctrl = devm_pinctrl_register(dev, &data->desc, data); + if (IS_ERR(data->pinctrl)) { + dev_err(dev, "Failed to register pinctrl\n"); + return PTR_ERR(data->pinctrl); + } + + platform_set_drvdata(pdev, data); + + return 0; +} + +static int da850_pupd_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id da850_pupd_of_match[] = { + { .compatible = "ti,da850-pupd" }, + { } +}; + +static struct platform_driver da850_pupd_driver = { + .driver = { + .name = "ti-da850-pupd", + .of_match_table = da850_pupd_of_match, + }, + .probe = da850_pupd_probe, + .remove = da850_pupd_remove, +}; +module_platform_driver(da850_pupd_driver); + +MODULE_AUTHOR("David Lechner "); +MODULE_DESCRIPTION("TI DA850/OMAP-L138/AM18XX pullup/pulldown configuration"); +MODULE_LICENSE("GPL"); -- cgit 1.4.1 From 85ae9e512f437cd09bf61564bdba29ab88bab3e3 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 14 Nov 2016 18:48:19 +0100 Subject: pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP It should be possible to use the GPIOLIB_IRQCHIP helper library with the BCM2835 driver since it is a pretty straight forward cascaded irqchip. The only difference from other drivers is that the BCM2835 has several banks for a single gpiochip, and each bank has a separate IRQ line. Instead of creating one gpiochip per bank, a single gpiochip covers all banks GPIO lines. This makes it necessary to resolve the bank ID in the IRQ handler. The GPIOLIB_IRQCHIP allows several IRQs to be cascaded off the same gpiochip by calling gpiochip_set_chained_irqchip() repeatedly, but we have been a bit short on examples for how this should be handled in practice, so this is intended as an example of how this can be achieved. The old code did not model the chip as a chained interrupt handler, but this patch also rectifies that situation. Cc: Stephen Warren Tested-by: Stefan Wahren Tested-by: Eric Anholt Acked-by: Eric Anholt Signed-off-by: Linus Walleij --- drivers/pinctrl/bcm/Kconfig | 1 + drivers/pinctrl/bcm/pinctrl-bcm2835.c | 140 ++++++++++++++++------------------ 2 files changed, 65 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig index 63246770bd74..8968dd7aebed 100644 --- a/drivers/pinctrl/bcm/Kconfig +++ b/drivers/pinctrl/bcm/Kconfig @@ -20,6 +20,7 @@ config PINCTRL_BCM2835 bool select PINMUX select PINCONF + select GPIOLIB_IRQCHIP config PINCTRL_IPROC_GPIO bool "Broadcom iProc GPIO (with PINCONF) driver" diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 6128359d3281..1bb38d0493eb 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -24,11 +24,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -87,11 +85,6 @@ enum bcm2835_pinconf_pull { #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16) #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff) -struct bcm2835_gpio_irqdata { - struct bcm2835_pinctrl *pc; - int irqgroup; -}; - struct bcm2835_pinctrl { struct device *dev; void __iomem *base; @@ -102,16 +95,13 @@ struct bcm2835_pinctrl { unsigned int irq_type[BCM2835_NUM_GPIOS]; struct pinctrl_dev *pctl_dev; - struct irq_domain *irq_domain; struct gpio_chip gpio_chip; struct pinctrl_gpio_range gpio_range; - struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS]; + int irq_group[BCM2835_NUM_IRQS]; spinlock_t irq_lock[BCM2835_NUM_BANKS]; }; -static struct lock_class_key gpio_lock_class; - /* pins are just named GPIO0..GPIO53 */ #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a) static struct pinctrl_pin_desc bcm2835_gpio_pins[] = { @@ -369,13 +359,6 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip, return pinctrl_gpio_direction_output(chip->base + offset); } -static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); - - return irq_linear_revmap(pc->irq_domain, offset); -} - static struct gpio_chip bcm2835_gpio_chip = { .label = MODULE_NAME, .owner = THIS_MODULE, @@ -386,14 +369,13 @@ static struct gpio_chip bcm2835_gpio_chip = { .get_direction = bcm2835_gpio_get_direction, .get = bcm2835_gpio_get, .set = bcm2835_gpio_set, - .to_irq = bcm2835_gpio_to_irq, .base = -1, .ngpio = BCM2835_NUM_GPIOS, .can_sleep = false, }; -static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, - unsigned int bank, u32 mask) +static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, + unsigned int bank, u32 mask) { unsigned long events; unsigned offset; @@ -405,34 +387,49 @@ static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; + /* FIXME: no clue why the code looks up the type here */ type = pc->irq_type[gpio]; - generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio)); + generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain, + gpio)); } - - return (events != 0); } -static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id) +static void bcm2835_gpio_irq_handler(struct irq_desc *desc) { - struct bcm2835_gpio_irqdata *irqdata = dev_id; - struct bcm2835_pinctrl *pc = irqdata->pc; - int handled = 0; + struct gpio_chip *chip = irq_desc_get_handler_data(desc); + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + int irq = irq_desc_get_irq(desc); + int group; + int i; + + for (i = 0; i < ARRAY_SIZE(pc->irq); i++) { + if (pc->irq[i] == irq) { + group = pc->irq_group[i]; + break; + } + } + /* This should not happen, every IRQ has a bank */ + if (i == ARRAY_SIZE(pc->irq)) + BUG(); - switch (irqdata->irqgroup) { + chained_irq_enter(host_chip, desc); + + switch (group) { case 0: /* IRQ0 covers GPIOs 0-27 */ - handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff); + bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff); break; case 1: /* IRQ1 covers GPIOs 28-45 */ - handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) | - bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); + bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000); + bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff); break; case 2: /* IRQ2 covers GPIOs 46-53 */ - handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); + bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000); break; } - return handled ? IRQ_HANDLED : IRQ_NONE; + chained_irq_exit(host_chip, desc); } static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, @@ -478,7 +475,8 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc, static void bcm2835_gpio_irq_enable(struct irq_data *data) { - struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); unsigned gpio = irqd_to_hwirq(data); unsigned offset = GPIO_REG_SHIFT(gpio); unsigned bank = GPIO_REG_OFFSET(gpio); @@ -492,7 +490,8 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data) static void bcm2835_gpio_irq_disable(struct irq_data *data) { - struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); unsigned gpio = irqd_to_hwirq(data); unsigned offset = GPIO_REG_SHIFT(gpio); unsigned bank = GPIO_REG_OFFSET(gpio); @@ -598,7 +597,8 @@ static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc, static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type) { - struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); unsigned gpio = irqd_to_hwirq(data); unsigned offset = GPIO_REG_SHIFT(gpio); unsigned bank = GPIO_REG_OFFSET(gpio); @@ -624,7 +624,8 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type) static void bcm2835_gpio_irq_ack(struct irq_data *data) { - struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data); + struct gpio_chip *chip = irq_data_get_irq_chip_data(data); + struct bcm2835_pinctrl *pc = gpiochip_get_data(chip); unsigned gpio = irqd_to_hwirq(data); bcm2835_gpio_set_bit(pc, GPEDS0, gpio); @@ -667,10 +668,11 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev, unsigned offset) { struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev); + struct gpio_chip *chip = &pc->gpio_chip; enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset); const char *fname = bcm2835_functions[fsel]; int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset); - int irq = irq_find_mapping(pc->irq_domain, offset); + int irq = irq_find_mapping(chip->irqdomain, offset); seq_printf(s, "function %s in %s; irq %d (%s)", fname, value ? "hi" : "lo", @@ -1016,21 +1018,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) pc->gpio_chip.parent = dev; pc->gpio_chip.of_node = np; - pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS, - &irq_domain_simple_ops, NULL); - if (!pc->irq_domain) { - dev_err(dev, "could not create IRQ domain\n"); - return -ENOMEM; - } - - for (i = 0; i < BCM2835_NUM_GPIOS; i++) { - int irq = irq_create_mapping(pc->irq_domain, i); - irq_set_lockdep_class(irq, &gpio_lock_class); - irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip, - handle_level_irq); - irq_set_chip_data(irq, pc); - } - for (i = 0; i < BCM2835_NUM_BANKS; i++) { unsigned long events; unsigned offset; @@ -1051,34 +1038,35 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev) spin_lock_init(&pc->irq_lock[i]); } - for (i = 0; i < BCM2835_NUM_IRQS; i++) { - int len; - char *name; - pc->irq[i] = irq_of_parse_and_map(np, i); - pc->irq_data[i].pc = pc; - pc->irq_data[i].irqgroup = i; - - len = strlen(dev_name(pc->dev)) + 16; - name = devm_kzalloc(pc->dev, len, GFP_KERNEL); - if (!name) - return -ENOMEM; - snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i); - - err = devm_request_irq(dev, pc->irq[i], - bcm2835_gpio_irq_handler, IRQF_SHARED, - name, &pc->irq_data[i]); - if (err) { - dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]); - return err; - } - } - err = gpiochip_add_data(&pc->gpio_chip, pc); if (err) { dev_err(dev, "could not add GPIO chip\n"); return err; } + err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip, + 0, handle_level_irq, IRQ_TYPE_NONE); + if (err) { + dev_info(dev, "could not add irqchip\n"); + return err; + } + + for (i = 0; i < BCM2835_NUM_IRQS; i++) { + pc->irq[i] = irq_of_parse_and_map(np, i); + pc->irq_group[i] = i; + /* + * Use the same handler for all groups: this is necessary + * since we use one gpiochip to cover all lines - the + * irq handler then needs to figure out which group and + * bank that was firing the IRQ and look up the per-group + * and bank data. + */ + gpiochip_set_chained_irqchip(&pc->gpio_chip, + &bcm2835_gpio_irq_chip, + pc->irq[i], + bcm2835_gpio_irq_handler); + } + pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc); if (IS_ERR(pc->pctl_dev)) { gpiochip_remove(&pc->gpio_chip); -- cgit 1.4.1 From 222ed59e8dace1c325c30dbee1b0161cf7eff2c7 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Wed, 30 Nov 2016 10:21:31 +0800 Subject: pinctrl: mt8173: set GPIO16 to usb iddig mode the default mode of GPIO16 pin is gpio, when set EINT16 to IRQ_TYPE_LEVEL_HIGH, no interrupt is triggered, it can be fixed when set its default mode as usb iddig. Signed-off-by: Chunfeng Yun Acked-by: Hongzhou Yang Signed-off-by: Linus Walleij --- drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h index 13e5b68bfe1b..9b018fdbeb51 100644 --- a/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h +++ b/drivers/pinctrl/mediatek/pinctrl-mtk-mt8173.h @@ -201,7 +201,7 @@ static const struct mtk_desc_pin mtk_pins_mt8173[] = { MTK_PIN( PINCTRL_PIN(16, "IDDIG"), NULL, "mt8173", - MTK_EINT_FUNCTION(0, 16), + MTK_EINT_FUNCTION(1, 16), MTK_FUNCTION(0, "GPIO16"), MTK_FUNCTION(1, "IDDIG"), MTK_FUNCTION(2, "CMFLASH"), -- cgit 1.4.1 From 6c4ef627d8c458fe8880ccd2e2cd581de0d9b42f Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 2 Dec 2016 11:51:14 +0100 Subject: pinctrl: sx150x: access the correct bits in the 4-bit regs of sx150[147] The code assumes 8-bit or 16-bit width registers, but three of the chips (sx1501/sx1504/sx1507) are 4-bit. So, try to handle 4-bit chips as well, they leave the high part of each register unused. Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 1a1c8b51a992..a121819ffc92 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -5,6 +5,7 @@ * Copyright (c) 2010, Code Aurora Forum. All rights reserved. * * Driver for Semtech SX150X I2C GPIO Expanders + * The handling of the 4-bit chips (SX1501/SX1504/SX1507) is untested. * * Author: Gregory Bean * @@ -1088,7 +1089,7 @@ static int sx150x_regmap_reg_write(void *context, unsigned int reg, val = sx150x_maybe_swizzle(pctl, reg, val); - n = width - 8; + n = (width - 1) & ~7; do { const u8 byte = (val >> n) & 0xff; -- cgit 1.4.1 From c9d26f1aab007a7083f509b4be263bc904ddb0d3 Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 2 Dec 2016 11:51:15 +0100 Subject: pinctrl: sx150x: rename 'reg_advance' to 'reg_advanced' This matches the datasheets and is less confusing since the register has nothing to with advancing anything. Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index a121819ffc92..37b8737e61a9 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -60,7 +60,7 @@ struct sx150x_123_pri { u8 reg_pld_table2; u8 reg_pld_table3; u8 reg_pld_table4; - u8 reg_advance; + u8 reg_advanced; }; struct sx150x_456_pri { @@ -70,7 +70,7 @@ struct sx150x_456_pri { u8 reg_pld_table2; u8 reg_pld_table3; u8 reg_pld_table4; - u8 reg_advance; + u8 reg_advanced; }; struct sx150x_789_pri { @@ -170,7 +170,7 @@ static const struct sx150x_device_data sx1501q_device_data = { .reg_pld_mode = 0x10, .reg_pld_table0 = 0x11, .reg_pld_table2 = 0x13, - .reg_advance = 0xad, + .reg_advanced = 0xad, }, .ngpios = 4, .pins = sx150x_4_pins, @@ -193,7 +193,7 @@ static const struct sx150x_device_data sx1502q_device_data = { .reg_pld_table2 = 0x13, .reg_pld_table3 = 0x14, .reg_pld_table4 = 0x15, - .reg_advance = 0xad, + .reg_advanced = 0xad, }, .ngpios = 8, .pins = sx150x_8_pins, @@ -216,7 +216,7 @@ static const struct sx150x_device_data sx1503q_device_data = { .reg_pld_table2 = 0x26, .reg_pld_table3 = 0x28, .reg_pld_table4 = 0x2a, - .reg_advance = 0xad, + .reg_advanced = 0xad, }, .ngpios = 16, .pins = sx150x_16_pins, @@ -280,7 +280,7 @@ static const struct sx150x_device_data sx1506q_device_data = { .reg_pld_table2 = 0x26, .reg_pld_table3 = 0x28, .reg_pld_table4 = 0x2a, - .reg_advance = 0xad, + .reg_advanced = 0xad, }, .ngpios = 16, .pins = sx150x_16_pins, @@ -900,7 +900,7 @@ static int sx150x_init_misc(struct sx150x_pinctrl *pctl) value = SX150X_789_REG_MISC_AUTOCLEAR_OFF; break; case SX150X_456: - reg = pctl->data->pri.x456.reg_advance; + reg = pctl->data->pri.x456.reg_advanced; value = 0x00; /* @@ -911,7 +911,7 @@ static int sx150x_init_misc(struct sx150x_pinctrl *pctl) return 0; break; case SX150X_123: - reg = pctl->data->pri.x123.reg_advance; + reg = pctl->data->pri.x123.reg_advanced; value = 0x00; break; default: @@ -964,10 +964,10 @@ static int sx150x_regmap_reg_width(struct sx150x_pinctrl *pctl, reg == data->pri.x789.reg_reset)) || (data->model == SX150X_123 && - reg == data->pri.x123.reg_advance) + reg == data->pri.x123.reg_advanced) || (data->model == SX150X_456 && - reg == data->pri.x456.reg_advance)) { + reg == data->pri.x456.reg_advanced)) { return 8; } else { return data->ngpios; -- cgit 1.4.1 From 283dc0be75b2fd870ae32a080a568f67c9ac9a4e Mon Sep 17 00:00:00 2001 From: Peter Rosin Date: Fri, 2 Dec 2016 11:51:16 +0100 Subject: pinctrl: sx150x: handle missing 'advanced' reg in sx1504 and sx1505 This fixes a problem where sx150x_regmap_reg_width() returns 8 for the data register (reg 0) for sx1504 where it should return 4, and return a correct 8 for sx1505 but for the wrong reason (both chips lack the 'advanced' register). This is not a real problem, since nothing depends on the function returning 4 or 8, and certainly not if it is returning 8 for the wrong reason. But fix this to avoid nasty surprises down the line. Signed-off-by: Peter Rosin Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index 37b8737e61a9..bdb7ea3d9911 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -967,6 +967,7 @@ static int sx150x_regmap_reg_width(struct sx150x_pinctrl *pctl, reg == data->pri.x123.reg_advanced) || (data->model == SX150X_456 && + data->pri.x456.reg_advanced && reg == data->pri.x456.reg_advanced)) { return 8; } else { -- cgit 1.4.1 From f821444508743a3e56320d0cb2b8c4603637660c Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 25 Nov 2016 15:16:11 +0100 Subject: pinctrl: sx150x: use new nested IRQ infrastructure Use the new gpiochip_irqchip_add_nested() and gpiochip_set_nested_irqchip() calls to properly created a nested irqchip and mark all child irqs properly with their parent IRQ. Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-sx150x.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c index bdb7ea3d9911..29fb7403d24e 100644 --- a/drivers/pinctrl/pinctrl-sx150x.c +++ b/drivers/pinctrl/pinctrl-sx150x.c @@ -1221,9 +1221,9 @@ static int sx150x_probe(struct i2c_client *client, * plus it will be instantly noticeable if it is ever * called (should not happen) */ - ret = gpiochip_irqchip_add(&pctl->gpio, - &pctl->irq_chip, 0, - handle_bad_irq, IRQ_TYPE_NONE); + ret = gpiochip_irqchip_add_nested(&pctl->gpio, + &pctl->irq_chip, 0, + handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(dev, "could not connect irqchip to gpiochip\n"); return ret; @@ -1236,6 +1236,10 @@ static int sx150x_probe(struct i2c_client *client, pctl->irq_chip.name, pctl); if (ret < 0) return ret; + + gpiochip_set_nested_irqchip(&pctl->gpio, + &pctl->irq_chip, + client->irq); } /* Pinctrl_desc */ -- cgit 1.4.1