aboutsummaryrefslogtreecommitdiffstats
path: root/include/configs/snow.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/configs/snow.h')
-rw-r--r--include/configs/snow.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/configs/snow.h b/include/configs/snow.h
index 7eaa58697e4..ce6676eae7f 100644
--- a/include/configs/snow.h
+++ b/include/configs/snow.h
@@ -22,6 +22,7 @@
#define CONFIG_CROS_EC_I2C /* Support CROS_EC over I2C */
#define CONFIG_POWER_TPS65090_I2C
+#define CONFIG_DM_CROS_EC
#define CONFIG_BOARD_COMMON
#define CONFIG_ARCH_EARLY_INIT_R
um_groups = pct->soc->functions[function].ngroups; return 0; } static int abx500_pmx_enable(struct pinctrl_dev *pctldev, unsigned function, unsigned group) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pct->chip; const struct abx500_pingroup *g; int i; int ret = 0; g = &pct->soc->groups[group]; if (g->altsetting < 0) return -EINVAL; dev_dbg(pct->dev, "enable group %s, %u pins\n", g->name, g->npins); for (i = 0; i < g->npins; i++) { dev_dbg(pct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting); ret = abx500_set_mode(pctldev, chip, g->pins[i], g->altsetting); } if (ret < 0) dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); return ret; } static int abx500_gpio_request_enable(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); const struct abx500_pinrange *p; int ret; int i; /* * Different ranges have different ways to enable GPIO function on a * pin, so refer back to our local range type, where we handily define * what altfunc enables GPIO for a certain pin. */ for (i = 0; i < pct->soc->gpio_num_ranges; i++) { p = &pct->soc->gpio_ranges[i]; if ((offset >= p->offset) && (offset < (p->offset + p->npins))) break; } if (i == pct->soc->gpio_num_ranges) { dev_err(pct->dev, "%s failed to locate range\n", __func__); return -ENODEV; } dev_dbg(pct->dev, "enable GPIO by altfunc %d at gpio %d\n", p->altfunc, offset); ret = abx500_set_mode(pct->pctldev, &pct->chip, offset, p->altfunc); if (ret < 0) dev_err(pct->dev, "%s setting altfunc failed\n", __func__); return ret; } static void abx500_gpio_disable_free(struct pinctrl_dev *pctldev, struct pinctrl_gpio_range *range, unsigned offset) { } static const struct pinmux_ops abx500_pinmux_ops = { .get_functions_count = abx500_pmx_get_funcs_cnt, .get_function_name = abx500_pmx_get_func_name, .get_function_groups = abx500_pmx_get_func_groups, .enable = abx500_pmx_enable, .gpio_request_enable = abx500_gpio_request_enable, .gpio_disable_free = abx500_gpio_disable_free, }; static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); return pct->soc->ngroups; } static const char *abx500_get_group_name(struct pinctrl_dev *pctldev, unsigned selector) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); return pct->soc->groups[selector].name; } static int abx500_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, const unsigned **pins, unsigned *num_pins) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); *pins = pct->soc->groups[selector].pins; *num_pins = pct->soc->groups[selector].npins; return 0; } static void abx500_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pct->chip; abx500_gpio_dbg_show_one(s, pctldev, chip, offset, chip->base + offset - 1); } static void abx500_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_PIN) kfree(map[i].data.configs.configs); kfree(map); } static int abx500_dt_reserve_map(struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps, unsigned reserve) { unsigned old_num = *reserved_maps; unsigned new_num = *num_maps + reserve; struct pinctrl_map *new_map; if (old_num >= new_num) return 0; new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); if (!new_map) return -ENOMEM; memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); *map = new_map; *reserved_maps = new_num; return 0; } static int abx500_dt_add_map_mux(struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps, const char *group, const char *function) { if (*num_maps == *reserved_maps) return -ENOSPC; (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP; (*map)[*num_maps].data.mux.group = group; (*map)[*num_maps].data.mux.function = function; (*num_maps)++; return 0; } static int abx500_dt_add_map_configs(struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps, const char *group, unsigned long *configs, unsigned num_configs) { unsigned long *dup_configs; if (*num_maps == *reserved_maps) return -ENOSPC; dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), GFP_KERNEL); if (!dup_configs) return -ENOMEM; (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_PIN; (*map)[*num_maps].data.configs.group_or_pin = group; (*map)[*num_maps].data.configs.configs = dup_configs; (*map)[*num_maps].data.configs.num_configs = num_configs; (*num_maps)++; return 0; } static const char *abx500_find_pin_name(struct pinctrl_dev *pctldev, const char *pin_name) { int i, pin_number; struct abx500_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); if (sscanf((char *)pin_name, "GPIO%d", &pin_number) == 1) for (i = 0; i < npct->soc->npins; i++) if (npct->soc->pins[i].number == pin_number) return npct->soc->pins[i].name; return NULL; } static int abx500_dt_subnode_to_map(struct pinctrl_dev *pctldev, struct device_node *np, struct pinctrl_map **map, unsigned *reserved_maps, unsigned *num_maps) { int ret; const char *function = NULL; unsigned long *configs; unsigned int nconfigs = 0; bool has_config = 0; unsigned reserve = 0; struct property *prop; const char *group, *gpio_name; struct device_node *np_config; ret = of_property_read_string(np, "ste,function", &function); if (ret >= 0) reserve = 1; ret = pinconf_generic_parse_dt_config(np, &configs, &nconfigs); if (nconfigs) has_config = 1; np_config = of_parse_phandle(np, "ste,config", 0); if (np_config) { ret = pinconf_generic_parse_dt_config(np_config, &configs, &nconfigs); if (ret) goto exit; has_config |= nconfigs; } ret = of_property_count_strings(np, "ste,pins"); if (ret < 0) goto exit; if (has_config) reserve++; reserve *= ret; ret = abx500_dt_reserve_map(map, reserved_maps, num_maps, reserve); if (ret < 0) goto exit; of_property_for_each_string(np, "ste,pins", prop, group) { if (function) { ret = abx500_dt_add_map_mux(map, reserved_maps, num_maps, group, function); if (ret < 0) goto exit; } if (has_config) { gpio_name = abx500_find_pin_name(pctldev, group); ret = abx500_dt_add_map_configs(map, reserved_maps, num_maps, gpio_name, configs, 1); if (ret < 0) goto exit; } } exit: return ret; } static int abx500_dt_node_to_map(struct pinctrl_dev *pctldev, struct device_node *np_config, struct pinctrl_map **map, unsigned *num_maps) { unsigned reserved_maps; struct device_node *np; int ret; reserved_maps = 0; *map = NULL; *num_maps = 0; for_each_child_of_node(np_config, np) { ret = abx500_dt_subnode_to_map(pctldev, np, map, &reserved_maps, num_maps); if (ret < 0) { abx500_dt_free_map(pctldev, *map, *num_maps); return ret; } } return 0; } static const struct pinctrl_ops abx500_pinctrl_ops = { .get_groups_count = abx500_get_groups_cnt, .get_group_name = abx500_get_group_name, .get_group_pins = abx500_get_group_pins, .pin_dbg_show = abx500_pin_dbg_show, .dt_node_to_map = abx500_dt_node_to_map, .dt_free_map = abx500_dt_free_map, }; static int abx500_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *config) { return -ENOSYS; } static int abx500_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, unsigned long *configs, unsigned num_configs) { struct abx500_pinctrl *pct = pinctrl_dev_get_drvdata(pctldev); struct gpio_chip *chip = &pct->chip; unsigned offset; int ret = -EINVAL; int i; enum pin_config_param param; enum pin_config_param argument; for (i = 0; i < num_configs; i++) { param = pinconf_to_config_param(configs[i]); argument = pinconf_to_config_argument(configs[i]); dev_dbg(chip->dev, "pin %d [%#lx]: %s %s\n", pin, configs[i], (param == PIN_CONFIG_OUTPUT) ? "output " : "input", (param == PIN_CONFIG_OUTPUT) ? (argument ? "high" : "low") : (argument ? "pull up" : "pull down")); /* on ABx500, there is no GPIO0, so adjust the offset */ offset = pin - 1; switch (param) { case PIN_CONFIG_BIAS_DISABLE: ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out; /* * Some chips only support pull down, while some * actually support both pull up and pull down. Such * chips have a "pullud" range specified for the pins * that support both features. If the pin is not * within that range, we fall back to the old bit set * that only support pull down. */ if (abx500_pullud_supported(chip, pin)) ret = abx500_set_pull_updown(pct, pin, ABX500_GPIO_PULL_NONE); else /* Chip only supports pull down */ ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, ABX500_GPIO_PULL_NONE); break; case PIN_CONFIG_BIAS_PULL_DOWN: ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out; /* * if argument = 1 set the pull down * else clear the pull down * Some chips only support pull down, while some * actually support both pull up and pull down. Such * chips have a "pullud" range specified for the pins * that support both features. If the pin is not * within that range, we fall back to the old bit set * that only support pull down. */ if (abx500_pullud_supported(chip, pin)) ret = abx500_set_pull_updown(pct, pin, argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE); else /* Chip only supports pull down */ ret = abx500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, argument ? ABX500_GPIO_PULL_DOWN : ABX500_GPIO_PULL_NONE); break; case PIN_CONFIG_BIAS_PULL_UP: ret = abx500_gpio_direction_input(chip, offset); if (ret < 0) goto out; /* * if argument = 1 set the pull up * else clear the pull up */ ret = abx500_gpio_direction_input(chip, offset); /* * Some chips only support pull down, while some * actually support both pull up and pull down. Such * chips have a "pullud" range specified for the pins * that support both features. If the pin is not * within that range, do nothing */ if (abx500_pullud_supported(chip, pin)) ret = abx500_set_pull_updown(pct, pin, argument ? ABX500_GPIO_PULL_UP : ABX500_GPIO_PULL_NONE); break; case PIN_CONFIG_OUTPUT: ret = abx500_gpio_direction_output(chip, offset, argument); break; default: dev_err(chip->dev, "illegal configuration requested\n"); } } /* for each config */ out: if (ret < 0) dev_err(pct->dev, "%s failed (%d)\n", __func__, ret); return ret; } static const struct pinconf_ops abx500_pinconf_ops = { .pin_config_get = abx500_pin_config_get, .pin_config_set = abx500_pin_config_set, }; static struct pinctrl_desc abx500_pinctrl_desc = { .name = "pinctrl-abx500", .pctlops = &abx500_pinctrl_ops, .pmxops = &abx500_pinmux_ops, .confops = &abx500_pinconf_ops, .owner = THIS_MODULE, }; static int abx500_get_gpio_num(struct abx500_pinctrl_soc_data *soc) { unsigned int lowest = 0; unsigned int highest = 0; unsigned int npins = 0; int i; /* * Compute number of GPIOs from the last SoC gpio range descriptors * These ranges may include "holes" but the GPIO number space shall * still be homogeneous, so we need to detect and account for any * such holes so that these are included in the number of GPIO pins. */ for (i = 0; i < soc->gpio_num_ranges; i++) { unsigned gstart; unsigned gend; const struct abx500_pinrange *p; p = &soc->gpio_ranges[i]; gstart = p->offset; gend = p->offset + p->npins - 1; if (i == 0) { /* First iteration, set start values */ lowest = gstart; highest = gend; } else { if (gstart < lowest) lowest = gstart; if (gend > highest) highest = gend; } } /* this gives the absolute number of pins */ npins = highest - lowest + 1; return npins; } static const struct of_device_id abx500_gpio_match[] = { { .compatible = "stericsson,ab8500-gpio", .data = (void *)PINCTRL_AB8500, }, { .compatible = "stericsson,ab8505-gpio", .data = (void *)PINCTRL_AB8505, }, { .compatible = "stericsson,ab8540-gpio", .data = (void *)PINCTRL_AB8540, }, { .compatible = "stericsson,ab9540-gpio", .data = (void *)PINCTRL_AB9540, }, { } }; static int abx500_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; const struct of_device_id *match; struct abx500_pinctrl *pct; unsigned int id = -1; int ret, err; int i; if (!np) { dev_err(&pdev->dev, "gpio dt node missing\n"); return -ENODEV; } pct = devm_kzalloc(&pdev->dev, sizeof(struct abx500_pinctrl), GFP_KERNEL); if (pct == NULL) { dev_err(&pdev->dev, "failed to allocate memory for pct\n"); return -ENOMEM; } pct->dev = &pdev->dev; pct->parent = dev_get_drvdata(pdev->dev.parent); pct->chip = abx500gpio_chip; pct->chip.dev = &pdev->dev; pct->chip.base = -1; /* Dynamic allocation */ match = of_match_device(abx500_gpio_match, &pdev->dev); if (!match) { dev_err(&pdev->dev, "gpio dt not matching\n"); return -ENODEV; } id = (unsigned long)match->data; /* Poke in other ASIC variants here */ switch (id) { case PINCTRL_AB8500: abx500_pinctrl_ab8500_init(&pct->soc); break; case PINCTRL_AB8540: abx500_pinctrl_ab8540_init(&pct->soc); break; case PINCTRL_AB9540: abx500_pinctrl_ab9540_init(&pct->soc); break; case PINCTRL_AB8505: abx500_pinctrl_ab8505_init(&pct->soc); break; default: dev_err(&pdev->dev, "Unsupported pinctrl sub driver (%d)\n", id); return -EINVAL; } if (!pct->soc) { dev_err(&pdev->dev, "Invalid SOC data\n"); return -EINVAL; } pct->chip.ngpio = abx500_get_gpio_num(pct->soc); pct->irq_cluster = pct->soc->gpio_irq_cluster; pct->irq_cluster_size = pct->soc->ngpio_irq_cluster; ret = gpiochip_add(&pct->chip); if (ret) { dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); return ret; } dev_info(&pdev->dev, "added gpiochip\n"); abx500_pinctrl_desc.pins = pct->soc->pins; abx500_pinctrl_desc.npins = pct->soc->npins; pct->pctldev = pinctrl_register(&abx500_pinctrl_desc, &pdev->dev, pct); if (!pct->pctldev) { dev_err(&pdev->dev, "could not register abx500 pinctrl driver\n"); ret = -EINVAL; goto out_rem_chip; } dev_info(&pdev->dev, "registered pin controller\n"); /* We will handle a range of GPIO pins */ for (i = 0; i < pct->soc->gpio_num_ranges; i++) { const struct abx500_pinrange *p = &pct->soc->gpio_ranges[i]; ret = gpiochip_add_pin_range(&pct->chip, dev_name(&pdev->dev), p->offset - 1, p->offset, p->npins); if (ret < 0) goto out_rem_chip; } platform_set_drvdata(pdev, pct); dev_info(&pdev->dev, "initialized abx500 pinctrl driver\n"); return 0; out_rem_chip: err = gpiochip_remove(&pct->chip); if (err) dev_info(&pdev->dev, "failed to remove gpiochip\n"); return ret; } /** * abx500_gpio_remove() - remove Ab8500-gpio driver * @pdev: Platform device registered */ static int abx500_gpio_remove(struct platform_device *pdev) { struct abx500_pinctrl *pct = platform_get_drvdata(pdev); int ret; ret = gpiochip_remove(&pct->chip); if (ret < 0) { dev_err(pct->dev, "unable to remove gpiochip: %d\n", ret); return ret; } return 0; } static struct platform_driver abx500_gpio_driver = { .driver = { .name = "abx500-gpio", .owner = THIS_MODULE, .of_match_table = abx500_gpio_match, }, .probe = abx500_gpio_probe, .remove = abx500_gpio_remove, }; static int __init abx500_gpio_init(void) { return platform_driver_register(&abx500_gpio_driver); } core_initcall(abx500_gpio_init); MODULE_AUTHOR("Patrice Chotard <patrice.chotard@st.com>"); MODULE_DESCRIPTION("Driver allows to use AxB5xx unused pins to be used as GPIO"); MODULE_ALIAS("platform:abx500-gpio"); MODULE_LICENSE("GPL v2");