Merge tag 'parisc-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/parisc-2.6
[linux-block.git] / drivers / pinctrl / pinctrl-pxa3xx.c
CommitLineData
f4e66983
HZ
1/*
2 * linux/drivers/pinctrl/pinctrl-pxa3xx.c
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * publishhed by the Free Software Foundation.
7 *
8 * Copyright (C) 2011, Marvell Technology Group Ltd.
9 *
10 * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/io.h>
17#include <linux/platform_device.h>
18#include <linux/slab.h>
19#include "pinctrl-pxa3xx.h"
20
21static struct pinctrl_gpio_range pxa3xx_pinctrl_gpio_range = {
22 .name = "PXA3xx GPIO",
23 .id = 0,
24 .base = 0,
25 .pin_base = 0,
26};
27
28static int pxa3xx_list_groups(struct pinctrl_dev *pctrldev, unsigned selector)
29{
30 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
31 if (selector >= info->num_grps)
32 return -EINVAL;
33 return 0;
34}
35
36static const char *pxa3xx_get_group_name(struct pinctrl_dev *pctrldev,
37 unsigned selector)
38{
39 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
40 if (selector >= info->num_grps)
41 return NULL;
42 return info->grps[selector].name;
43}
44
45static int pxa3xx_get_group_pins(struct pinctrl_dev *pctrldev,
46 unsigned selector,
47 const unsigned **pins,
48 unsigned *num_pins)
49{
50 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
51 if (selector >= info->num_grps)
52 return -EINVAL;
53 *pins = info->grps[selector].pins;
54 *num_pins = info->grps[selector].npins;
55 return 0;
56}
57
58static struct pinctrl_ops pxa3xx_pctrl_ops = {
59 .list_groups = pxa3xx_list_groups,
60 .get_group_name = pxa3xx_get_group_name,
61 .get_group_pins = pxa3xx_get_group_pins,
62};
63
64static int pxa3xx_pmx_list_func(struct pinctrl_dev *pctrldev, unsigned func)
65{
66 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
67 if (func >= info->num_funcs)
68 return -EINVAL;
69 return 0;
70}
71
72static const char *pxa3xx_pmx_get_func_name(struct pinctrl_dev *pctrldev,
73 unsigned func)
74{
75 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
76 return info->funcs[func].name;
77}
78
79static int pxa3xx_pmx_get_groups(struct pinctrl_dev *pctrldev, unsigned func,
80 const char * const **groups,
81 unsigned * const num_groups)
82{
83 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
84 *groups = info->funcs[func].groups;
85 *num_groups = info->funcs[func].num_groups;
86 return 0;
87}
88
89/* Return function number. If failure, return negative value. */
90static int match_mux(struct pxa3xx_mfp_pin *mfp, unsigned mux)
91{
92 int i;
93 for (i = 0; i < PXA3xx_MAX_MUX; i++) {
94 if (mfp->func[i] == mux)
95 break;
96 }
97 if (i >= PXA3xx_MAX_MUX)
98 return -EINVAL;
99 return i;
100}
101
102/* check whether current pin configuration is valid. Negative for failure */
103static int match_group_mux(struct pxa3xx_pin_group *grp,
104 struct pxa3xx_pinmux_info *info,
105 unsigned mux)
106{
107 int i, pin, ret = 0;
108 for (i = 0; i < grp->npins; i++) {
109 pin = grp->pins[i];
110 ret = match_mux(&info->mfp[pin], mux);
111 if (ret < 0) {
112 dev_err(info->dev, "Can't find mux %d on pin%d\n",
113 mux, pin);
114 break;
115 }
116 }
117 return ret;
118}
119
120static int pxa3xx_pmx_enable(struct pinctrl_dev *pctrldev, unsigned func,
121 unsigned group)
122{
123 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
124 struct pxa3xx_pin_group *pin_grp = &info->grps[group];
125 unsigned int data;
126 int i, mfpr, pin, pin_func;
127
128 if (!pin_grp->npins ||
129 (match_group_mux(pin_grp, info, pin_grp->mux) < 0)) {
130 dev_err(info->dev, "Failed to set the pin group: %d\n", group);
131 return -EINVAL;
132 }
133 for (i = 0; i < pin_grp->npins; i++) {
134 pin = pin_grp->pins[i];
135 pin_func = match_mux(&info->mfp[pin], pin_grp->mux);
136 mfpr = info->mfp[pin].mfpr;
137 data = readl_relaxed(info->virt_base + mfpr);
138 data &= ~MFPR_FUNC_MASK;
139 data |= pin_func;
140 writel_relaxed(data, info->virt_base + mfpr);
141 }
142 return 0;
143}
144
145static void pxa3xx_pmx_disable(struct pinctrl_dev *pctrldev, unsigned func,
146 unsigned group)
147{
148}
149
150static int pxa3xx_pmx_request_gpio(struct pinctrl_dev *pctrldev,
151 struct pinctrl_gpio_range *range,
152 unsigned pin)
153{
154 struct pxa3xx_pinmux_info *info = pinctrl_dev_get_drvdata(pctrldev);
155 unsigned int data;
156 int pin_func, mfpr;
157
158 pin_func = match_mux(&info->mfp[pin], PXA3xx_MUX_GPIO);
159 if (pin_func < 0) {
160 dev_err(info->dev, "No GPIO function on pin%d (%s)\n",
161 pin, info->pads[pin].name);
162 return -EINVAL;
163 }
164 mfpr = info->mfp[pin].mfpr;
165 /* write gpio function into mfpr register */
166 data = readl_relaxed(info->virt_base + mfpr) & ~MFPR_FUNC_MASK;
167 data |= pin_func;
168 writel_relaxed(data, info->virt_base + mfpr);
169 return 0;
170}
171
172static struct pinmux_ops pxa3xx_pmx_ops = {
173 .list_functions = pxa3xx_pmx_list_func,
174 .get_function_name = pxa3xx_pmx_get_func_name,
175 .get_function_groups = pxa3xx_pmx_get_groups,
176 .enable = pxa3xx_pmx_enable,
177 .disable = pxa3xx_pmx_disable,
178 .gpio_request_enable = pxa3xx_pmx_request_gpio,
179};
180
181int pxa3xx_pinctrl_register(struct platform_device *pdev,
182 struct pxa3xx_pinmux_info *info)
183{
184 struct pinctrl_desc *desc;
185 struct resource *res;
186 int ret = 0;
187
188 if (!info || !info->cputype)
189 return -EINVAL;
190 desc = info->desc;
191 desc->pins = info->pads;
192 desc->npins = info->num_pads;
193 desc->pctlops = &pxa3xx_pctrl_ops;
194 desc->pmxops = &pxa3xx_pmx_ops;
195 info->dev = &pdev->dev;
196 pxa3xx_pinctrl_gpio_range.npins = info->num_gpio;
197
198 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
199 if (!res)
200 return -ENOENT;
201 info->phy_base = res->start;
202 info->phy_size = resource_size(res);
203 info->virt_base = ioremap(info->phy_base, info->phy_size);
204 if (!info->virt_base)
205 return -ENOMEM;
206 info->pctrl = pinctrl_register(desc, &pdev->dev, info);
207 if (!info->pctrl) {
208 dev_err(&pdev->dev, "failed to register PXA pinmux driver\n");
209 ret = -EINVAL;
210 goto err;
211 }
212 pinctrl_add_gpio_range(info->pctrl, &pxa3xx_pinctrl_gpio_range);
213 platform_set_drvdata(pdev, info);
214 return 0;
215err:
216 iounmap(info->virt_base);
217 return ret;
218}
219
220int pxa3xx_pinctrl_unregister(struct platform_device *pdev)
221{
222 struct pxa3xx_pinmux_info *info = platform_get_drvdata(pdev);
223
224 pinctrl_unregister(info->pctrl);
225 iounmap(info->virt_base);
226 platform_set_drvdata(pdev, NULL);
227 return 0;
228}
229
230static int __init pxa3xx_pinctrl_init(void)
231{
232 pr_info("pxa3xx-pinctrl: PXA3xx pinctrl driver initializing\n");
233 return 0;
234}
235core_initcall_sync(pxa3xx_pinctrl_init);
236
237static void __exit pxa3xx_pinctrl_exit(void)
238{
239}
240module_exit(pxa3xx_pinctrl_exit);
241
242MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
243MODULE_DESCRIPTION("PXA3xx pin control driver");
244MODULE_LICENSE("GPL v2");