diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-u300.c')
-rw-r--r-- | drivers/pinctrl/pinctrl-u300.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/drivers/pinctrl/pinctrl-u300.c b/drivers/pinctrl/pinctrl-u300.c index c8d02f1c2b5..26eb8ccd72d 100644 --- a/drivers/pinctrl/pinctrl-u300.c +++ b/drivers/pinctrl/pinctrl-u300.c @@ -19,6 +19,9 @@ #include <linux/err.h> #include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinmux.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> +#include "pinctrl-coh901.h" /* * Register definitions for the U300 Padmux control registers in the @@ -162,7 +165,7 @@ #define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100 #define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200 -#define DRIVER_NAME "pinmux-u300" +#define DRIVER_NAME "pinctrl-u300" /* * The DB3350 has 467 pads, I have enumerated the pads clockwise around the @@ -1044,22 +1047,82 @@ static struct pinctrl_gpio_range u300_gpio_ranges[] = { U300_GPIO_RANGE(25, 181, 1), }; +static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) { + struct pinctrl_gpio_range *range; + + range = &u300_gpio_ranges[i]; + if (pin >= range->pin_base && + pin <= (range->pin_base + range->npins - 1)) + return range; + } + return NULL; +} + +int u300_pin_config_get(struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long *config) +{ + struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); + + /* We get config for those pins we CAN get it for and that's it */ + if (!range) + return -ENOTSUPP; + + return u300_gpio_config_get(range->gc, + (pin - range->pin_base + range->base), + config); +} + +int u300_pin_config_set(struct pinctrl_dev *pctldev, + unsigned pin, + unsigned long config) +{ + struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); + int ret; + + if (!range) + return -EINVAL; + + /* Note: none of these configurations take any argument */ + ret = u300_gpio_config_set(range->gc, + (pin - range->pin_base + range->base), + pinconf_to_config_param(config)); + if (ret) + return ret; + + return 0; +} + +static struct pinconf_ops u300_pconf_ops = { + .is_generic = true, + .pin_config_get = u300_pin_config_get, + .pin_config_set = u300_pin_config_set, +}; + static struct pinctrl_desc u300_pmx_desc = { .name = DRIVER_NAME, .pins = u300_pads, .npins = ARRAY_SIZE(u300_pads), .pctlops = &u300_pctrl_ops, .pmxops = &u300_pmx_ops, + .confops = &u300_pconf_ops, .owner = THIS_MODULE, }; -static int __init u300_pmx_probe(struct platform_device *pdev) +static int __devinit u300_pmx_probe(struct platform_device *pdev) { struct u300_pmx *upmx; struct resource *res; + struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev); int ret; int i; + pr_err("U300 PMX PROBE\n"); + /* Create state holders etc for this driver */ upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); if (!upmx) @@ -1095,12 +1158,14 @@ static int __init u300_pmx_probe(struct platform_device *pdev) } /* We will handle a range of GPIO pins */ - for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) + for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) { + u300_gpio_ranges[i].gc = gpio_chip; pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_ranges[i]); + } platform_set_drvdata(pdev, upmx); - dev_info(&pdev->dev, "initialized U300 pinmux driver\n"); + dev_info(&pdev->dev, "initialized U300 pin control driver\n"); return 0; @@ -1115,7 +1180,7 @@ out_no_resource: return ret; } -static int __exit u300_pmx_remove(struct platform_device *pdev) +static int __devexit u300_pmx_remove(struct platform_device *pdev) { struct u300_pmx *upmx = platform_get_drvdata(pdev); int i; @@ -1136,12 +1201,13 @@ static struct platform_driver u300_pmx_driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, }, - .remove = __exit_p(u300_pmx_remove), + .probe = u300_pmx_probe, + .remove = __devexit_p(u300_pmx_remove), }; static int __init u300_pmx_init(void) { - return platform_driver_probe(&u300_pmx_driver, u300_pmx_probe); + return platform_driver_register(&u300_pmx_driver); } arch_initcall(u300_pmx_init); |