123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- /*
- * Marvell PXA2xx family pin control
- *
- * Copyright (C) 2015 Robert Jarzmik
- *
- * 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.
- *
- */
- #include <linux/bitops.h>
- #include <linux/io.h>
- #include <linux/of.h>
- #include <linux/of_address.h>
- #include <linux/module.h>
- #include <linux/pinctrl/pinconf.h>
- #include <linux/pinctrl/pinconf-generic.h>
- #include <linux/pinctrl/pinmux.h>
- #include <linux/pinctrl/pinctrl.h>
- #include <linux/platform_device.h>
- #include <linux/slab.h>
- #include "../pinctrl-utils.h"
- #include "pinctrl-pxa2xx.h"
- static int pxa2xx_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- return pctl->ngroups;
- }
- static const char *pxa2xx_pctrl_get_group_name(struct pinctrl_dev *pctldev,
- unsigned tgroup)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_group *group = pctl->groups + tgroup;
- return group->name;
- }
- static int pxa2xx_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
- unsigned tgroup,
- const unsigned **pins,
- unsigned *num_pins)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_group *group = pctl->groups + tgroup;
- *pins = (unsigned *)&group->pin;
- *num_pins = 1;
- return 0;
- }
- static const struct pinctrl_ops pxa2xx_pctl_ops = {
- #ifdef CONFIG_OF
- .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
- .dt_free_map = pinctrl_utils_free_map,
- #endif
- .get_groups_count = pxa2xx_pctrl_get_groups_count,
- .get_group_name = pxa2xx_pctrl_get_group_name,
- .get_group_pins = pxa2xx_pctrl_get_group_pins,
- };
- static struct pxa_desc_function *
- pxa_desc_by_func_group(struct pxa_pinctrl *pctl, const char *pin_name,
- const char *func_name)
- {
- int i;
- struct pxa_desc_function *df;
- for (i = 0; i < pctl->npins; i++) {
- const struct pxa_desc_pin *pin = pctl->ppins + i;
- if (!strcmp(pin->pin.name, pin_name))
- for (df = pin->functions; df->name; df++)
- if (!strcmp(df->name, func_name))
- return df;
- }
- return NULL;
- }
- static int pxa2xx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range,
- unsigned pin,
- bool input)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- unsigned long flags;
- uint32_t val;
- void __iomem *gpdr;
- gpdr = pctl->base_gpdr[pin / 32];
- dev_dbg(pctl->dev, "set_direction(pin=%d): dir=%d\n",
- pin, !input);
- spin_lock_irqsave(&pctl->lock, flags);
- val = readl_relaxed(gpdr);
- val = (val & ~BIT(pin % 32)) | (input ? 0 : BIT(pin % 32));
- writel_relaxed(val, gpdr);
- spin_unlock_irqrestore(&pctl->lock, flags);
- return 0;
- }
- static const char *pxa2xx_pmx_get_func_name(struct pinctrl_dev *pctldev,
- unsigned function)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_function *pf = pctl->functions + function;
- return pf->name;
- }
- static int pxa2xx_get_functions_count(struct pinctrl_dev *pctldev)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- return pctl->nfuncs;
- }
- static int pxa2xx_pmx_get_func_groups(struct pinctrl_dev *pctldev,
- unsigned function,
- const char * const **groups,
- unsigned * const num_groups)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_function *pf = pctl->functions + function;
- *groups = pf->groups;
- *num_groups = pf->ngroups;
- return 0;
- }
- static int pxa2xx_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned function,
- unsigned tgroup)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_group *group = pctl->groups + tgroup;
- struct pxa_desc_function *df;
- int pin, shift;
- unsigned long flags;
- void __iomem *gafr, *gpdr;
- u32 val;
- df = pxa_desc_by_func_group(pctl, group->name,
- (pctl->functions + function)->name);
- if (!df)
- return -EINVAL;
- pin = group->pin;
- gafr = pctl->base_gafr[pin / 16];
- gpdr = pctl->base_gpdr[pin / 32];
- shift = (pin % 16) << 1;
- dev_dbg(pctl->dev, "set_mux(pin=%d): af=%d dir=%d\n",
- pin, df->muxval >> 1, df->muxval & 0x1);
- spin_lock_irqsave(&pctl->lock, flags);
- val = readl_relaxed(gafr);
- val = (val & ~(0x3 << shift)) | ((df->muxval >> 1) << shift);
- writel_relaxed(val, gafr);
- val = readl_relaxed(gpdr);
- val = (val & ~BIT(pin % 32)) | ((df->muxval & 1) ? BIT(pin % 32) : 0);
- writel_relaxed(val, gpdr);
- spin_unlock_irqrestore(&pctl->lock, flags);
- return 0;
- }
- static const struct pinmux_ops pxa2xx_pinmux_ops = {
- .get_functions_count = pxa2xx_get_functions_count,
- .get_function_name = pxa2xx_pmx_get_func_name,
- .get_function_groups = pxa2xx_pmx_get_func_groups,
- .set_mux = pxa2xx_pmx_set_mux,
- .gpio_set_direction = pxa2xx_pmx_gpio_set_direction,
- };
- static int pxa2xx_pconf_group_get(struct pinctrl_dev *pctldev,
- unsigned group,
- unsigned long *config)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_group *g = pctl->groups + group;
- unsigned long flags;
- unsigned pin = g->pin;
- void __iomem *pgsr = pctl->base_pgsr[pin / 32];
- u32 val;
- spin_lock_irqsave(&pctl->lock, flags);
- val = readl_relaxed(pgsr) & BIT(pin % 32);
- *config = val ? PIN_CONFIG_LOW_POWER_MODE : 0;
- spin_unlock_irqrestore(&pctl->lock, flags);
- dev_dbg(pctl->dev, "get sleep gpio state(pin=%d) %d\n",
- pin, !!val);
- return 0;
- }
- static int pxa2xx_pconf_group_set(struct pinctrl_dev *pctldev,
- unsigned group,
- unsigned long *configs,
- unsigned num_configs)
- {
- struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
- struct pxa_pinctrl_group *g = pctl->groups + group;
- unsigned long flags;
- unsigned pin = g->pin;
- void __iomem *pgsr = pctl->base_pgsr[pin / 32];
- int i, is_set = 0;
- u32 val;
- for (i = 0; i < num_configs; i++) {
- switch (pinconf_to_config_param(configs[i])) {
- case PIN_CONFIG_LOW_POWER_MODE:
- is_set = pinconf_to_config_argument(configs[i]);
- break;
- default:
- return -EINVAL;
- }
- }
- dev_dbg(pctl->dev, "set sleep gpio state(pin=%d) %d\n",
- pin, is_set);
- spin_lock_irqsave(&pctl->lock, flags);
- val = readl_relaxed(pgsr);
- val = (val & ~BIT(pin % 32)) | (is_set ? BIT(pin % 32) : 0);
- writel_relaxed(val, pgsr);
- spin_unlock_irqrestore(&pctl->lock, flags);
- return 0;
- }
- static const struct pinconf_ops pxa2xx_pconf_ops = {
- .pin_config_group_get = pxa2xx_pconf_group_get,
- .pin_config_group_set = pxa2xx_pconf_group_set,
- .is_generic = true,
- };
- static struct pinctrl_desc pxa2xx_pinctrl_desc = {
- .confops = &pxa2xx_pconf_ops,
- .pctlops = &pxa2xx_pctl_ops,
- .pmxops = &pxa2xx_pinmux_ops,
- };
- static const struct pxa_pinctrl_function *
- pxa2xx_find_function(struct pxa_pinctrl *pctl, const char *fname,
- const struct pxa_pinctrl_function *functions)
- {
- const struct pxa_pinctrl_function *func;
- for (func = functions; func->name; func++)
- if (!strcmp(fname, func->name))
- return func;
- return NULL;
- }
- static int pxa2xx_build_functions(struct pxa_pinctrl *pctl)
- {
- int i;
- struct pxa_pinctrl_function *functions;
- struct pxa_desc_function *df;
- /*
- * Each pin can have at most 6 alternate functions, and 2 gpio functions
- * which are common to each pin. As there are more than 2 pins without
- * alternate function, 6 * npins is an absolute high limit of the number
- * of functions.
- */
- functions = devm_kcalloc(pctl->dev, pctl->npins * 6,
- sizeof(*functions), GFP_KERNEL);
- if (!functions)
- return -ENOMEM;
- for (i = 0; i < pctl->npins; i++)
- for (df = pctl->ppins[i].functions; df->name; df++)
- if (!pxa2xx_find_function(pctl, df->name, functions))
- (functions + pctl->nfuncs++)->name = df->name;
- pctl->functions = devm_kmemdup(pctl->dev, functions,
- pctl->nfuncs * sizeof(*functions),
- GFP_KERNEL);
- if (!pctl->functions)
- return -ENOMEM;
- devm_kfree(pctl->dev, functions);
- return 0;
- }
- static int pxa2xx_build_groups(struct pxa_pinctrl *pctl)
- {
- int i, j, ngroups;
- struct pxa_pinctrl_function *func;
- struct pxa_desc_function *df;
- char **gtmp;
- gtmp = devm_kmalloc_array(pctl->dev, pctl->npins, sizeof(*gtmp),
- GFP_KERNEL);
- if (!gtmp)
- return -ENOMEM;
- for (i = 0; i < pctl->nfuncs; i++) {
- ngroups = 0;
- for (j = 0; j < pctl->npins; j++)
- for (df = pctl->ppins[j].functions; df->name;
- df++)
- if (!strcmp(pctl->functions[i].name,
- df->name))
- gtmp[ngroups++] = (char *)
- pctl->ppins[j].pin.name;
- func = pctl->functions + i;
- func->ngroups = ngroups;
- func->groups =
- devm_kmalloc_array(pctl->dev, ngroups,
- sizeof(char *), GFP_KERNEL);
- if (!func->groups)
- return -ENOMEM;
- memcpy(func->groups, gtmp, ngroups * sizeof(*gtmp));
- }
- devm_kfree(pctl->dev, gtmp);
- return 0;
- }
- static int pxa2xx_build_state(struct pxa_pinctrl *pctl,
- const struct pxa_desc_pin *ppins, int npins)
- {
- struct pxa_pinctrl_group *group;
- struct pinctrl_pin_desc *pins;
- int ret, i;
- pctl->npins = npins;
- pctl->ppins = ppins;
- pctl->ngroups = npins;
- pctl->desc.npins = npins;
- pins = devm_kcalloc(pctl->dev, npins, sizeof(*pins), GFP_KERNEL);
- if (!pins)
- return -ENOMEM;
- pctl->desc.pins = pins;
- for (i = 0; i < npins; i++)
- pins[i] = ppins[i].pin;
- pctl->groups = devm_kmalloc_array(pctl->dev, pctl->ngroups,
- sizeof(*pctl->groups), GFP_KERNEL);
- if (!pctl->groups)
- return -ENOMEM;
- for (i = 0; i < npins; i++) {
- group = pctl->groups + i;
- group->name = ppins[i].pin.name;
- group->pin = ppins[i].pin.number;
- }
- ret = pxa2xx_build_functions(pctl);
- if (ret)
- return ret;
- ret = pxa2xx_build_groups(pctl);
- if (ret)
- return ret;
- return 0;
- }
- int pxa2xx_pinctrl_init(struct platform_device *pdev,
- const struct pxa_desc_pin *ppins, int npins,
- void __iomem *base_gafr[], void __iomem *base_gpdr[],
- void __iomem *base_pgsr[])
- {
- struct pxa_pinctrl *pctl;
- int ret, i, maxpin = 0;
- for (i = 0; i < npins; i++)
- maxpin = max_t(int, ppins[i].pin.number, maxpin);
- pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
- if (!pctl)
- return -ENOMEM;
- pctl->base_gafr = devm_kcalloc(&pdev->dev, roundup(maxpin, 16),
- sizeof(*pctl->base_gafr), GFP_KERNEL);
- pctl->base_gpdr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32),
- sizeof(*pctl->base_gpdr), GFP_KERNEL);
- pctl->base_pgsr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32),
- sizeof(*pctl->base_pgsr), GFP_KERNEL);
- if (!pctl->base_gafr || !pctl->base_gpdr || !pctl->base_pgsr)
- return -ENOMEM;
- platform_set_drvdata(pdev, pctl);
- spin_lock_init(&pctl->lock);
- pctl->dev = &pdev->dev;
- pctl->desc = pxa2xx_pinctrl_desc;
- pctl->desc.name = dev_name(&pdev->dev);
- pctl->desc.owner = THIS_MODULE;
- for (i = 0; i < roundup(maxpin, 16); i += 16)
- pctl->base_gafr[i / 16] = base_gafr[i / 16];
- for (i = 0; i < roundup(maxpin, 32); i += 32) {
- pctl->base_gpdr[i / 32] = base_gpdr[i / 32];
- pctl->base_pgsr[i / 32] = base_pgsr[i / 32];
- }
- ret = pxa2xx_build_state(pctl, ppins, npins);
- if (ret)
- return ret;
- pctl->pctl_dev = devm_pinctrl_register(&pdev->dev, &pctl->desc, pctl);
- if (IS_ERR(pctl->pctl_dev)) {
- dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
- return PTR_ERR(pctl->pctl_dev);
- }
- dev_info(&pdev->dev, "initialized pxa2xx pinctrl driver\n");
- return 0;
- }
- EXPORT_SYMBOL_GPL(pxa2xx_pinctrl_init);
- int pxa2xx_pinctrl_exit(struct platform_device *pdev)
- {
- struct pxa_pinctrl *pctl = platform_get_drvdata(pdev);
- pinctrl_unregister(pctl->pctl_dev);
- return 0;
- }
- EXPORT_SYMBOL_GPL(pxa2xx_pinctrl_exit);
- MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
- MODULE_DESCRIPTION("Marvell PXA2xx pinctrl driver");
- MODULE_LICENSE("GPL v2");
|