diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2012-04-26 23:57:25 +0200 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2012-05-11 11:14:14 +0200 |
commit | e98ea774c8d210364379329f042e7596f83ecc58 (patch) | |
tree | 95833bd464ee36b68abe4e3c5612dc7e804f771c /drivers/pinctrl/pinctrl-nomadik.c | |
parent | pinctrl/nomadik: !CONFIG_OF build error (diff) | |
download | linux-e98ea774c8d210364379329f042e7596f83ecc58.tar.xz linux-e98ea774c8d210364379329f042e7596f83ecc58.zip |
pinctrl/nomadik: basic Nomadik pinctrl interface
This adds a scratch pin control interface to the Nomadik pinctrl
driver, and defines the pins and groups in the DB8500 ASIC. We
define GPIO ranges to cover the pins exposed. The DB8500 has
more pins than this but we restrict the driver to the pins that
can be controlled from the combined GPIO and pin control hardware
to begin with.
ChangeLog v1->v2:
- Base on the latest pinctrl development from
pinctrl-mergebase-20120418 so we can get rid of legacy
group count mechanism. Also drop the range checks for group
index, this is handled by the core now.
Acked-by: Stephen Warren <swarren@wwwdotorg.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/pinctrl/pinctrl-nomadik.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-nomadik.c | 122 |
1 files changed, 121 insertions, 1 deletions
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index 1352f3368444..7d5484fee5f3 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c @@ -24,12 +24,15 @@ #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/slab.h> +#include <linux/pinctrl/pinctrl.h> #include <asm/mach/irq.h> #include <plat/pincfg.h> #include <plat/gpio-nomadik.h> +#include "pinctrl-nomadik.h" + /* * The GPIO module in the Nomadik family of Systems-on-Chip is an * AMBA device, managing 32 pins and alternate functions. The logic block @@ -64,6 +67,12 @@ struct nmk_gpio_chip { u32 lowemi; }; +struct nmk_pinctrl { + struct device *dev; + struct pinctrl_dev *pctl; + const struct nmk_pinctrl_soc_data *soc; +}; + static struct nmk_gpio_chip * nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; @@ -1282,6 +1291,98 @@ out: return ret; } +static int nmk_get_groups_cnt(struct pinctrl_dev *pctldev) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->ngroups; +} + +static const char *nmk_get_group_name(struct pinctrl_dev *pctldev, + unsigned selector) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + return npct->soc->groups[selector].name; +} + +static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, + const unsigned **pins, + unsigned *num_pins) +{ + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + + *pins = npct->soc->groups[selector].pins; + *num_pins = npct->soc->groups[selector].npins; + return 0; +} + +static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, + unsigned offset) +{ + seq_printf(s, " Nomadik GPIO"); +} + +static struct pinctrl_ops nmk_pinctrl_ops = { + .get_groups_count = nmk_get_groups_cnt, + .get_group_name = nmk_get_group_name, + .get_group_pins = nmk_get_group_pins, + .pin_dbg_show = nmk_pin_dbg_show, +}; + +static struct pinctrl_desc nmk_pinctrl_desc = { + .name = "pinctrl-nomadik", + .pctlops = &nmk_pinctrl_ops, + .owner = THIS_MODULE, +}; + +static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) +{ + const struct platform_device_id *platid = platform_get_device_id(pdev); + struct nmk_pinctrl *npct; + int i; + + npct = devm_kzalloc(&pdev->dev, sizeof(*npct), GFP_KERNEL); + if (!npct) + return -ENOMEM; + + /* Poke in other ASIC variants here */ + if (platid->driver_data == PINCTRL_NMK_DB8500) + nmk_pinctrl_db8500_init(&npct->soc); + + /* + * We need all the GPIO drivers to probe FIRST, or we will not be able + * to obtain references to the struct gpio_chip * for them, and we + * need this to proceed. + */ + for (i = 0; i < npct->soc->gpio_num_ranges; i++) { + if (!nmk_gpio_chips[i]) { + dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); + devm_kfree(&pdev->dev, npct); + return -EPROBE_DEFER; + } + npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[i]->chip; + } + + nmk_pinctrl_desc.pins = npct->soc->pins; + nmk_pinctrl_desc.npins = npct->soc->npins; + npct->dev = &pdev->dev; + npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct); + if (!npct->pctl) { + dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n"); + return -EINVAL; + } + + /* We will handle a range of GPIO pins */ + for (i = 0; i < npct->soc->gpio_num_ranges; i++) + pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]); + + platform_set_drvdata(pdev, npct); + dev_info(&pdev->dev, "initialized Nomadik pin control driver\n"); + + return 0; +} + static const struct of_device_id nmk_gpio_match[] = { { .compatible = "st,nomadik-gpio", }, {} @@ -1296,9 +1397,28 @@ static struct platform_driver nmk_gpio_driver = { .probe = nmk_gpio_probe, }; +static const struct platform_device_id nmk_pinctrl_id[] = { + { "pinctrl-stn8815", PINCTRL_NMK_STN8815 }, + { "pinctrl-db8500", PINCTRL_NMK_DB8500 }, +}; + +static struct platform_driver nmk_pinctrl_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pinctrl-nomadik", + }, + .probe = nmk_pinctrl_probe, + .id_table = nmk_pinctrl_id, +}; + static int __init nmk_gpio_init(void) { - return platform_driver_register(&nmk_gpio_driver); + int ret; + + ret = platform_driver_register(&nmk_gpio_driver); + if (ret) + return ret; + return platform_driver_register(&nmk_pinctrl_driver); } core_initcall(nmk_gpio_init); |