1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (c) 2020 TOSHIBA CORPORATION |
4 | * Copyright (c) 2020 Toshiba Electronic Devices & Storage Corporation |
5 | * Copyright (c) 2020 Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp> |
6 | */ |
7 | |
8 | #include <linux/init.h> |
9 | #include <linux/of.h> |
10 | #include <linux/io.h> |
11 | #include <linux/platform_device.h> |
12 | #include <linux/pinctrl/pinctrl.h> |
13 | #include <linux/pinctrl/pinmux.h> |
14 | #include <linux/pinctrl/pinconf.h> |
15 | #include <linux/pinctrl/pinconf-generic.h> |
16 | #include "pinctrl-common.h" |
17 | #include "../core.h" |
18 | #include "../pinconf.h" |
19 | #include "../pinctrl-utils.h" |
20 | |
21 | #define DSEL_MASK GENMASK(3, 0) |
22 | |
23 | /* private data */ |
24 | struct visconti_pinctrl { |
25 | void __iomem *base; |
26 | struct device *dev; |
27 | struct pinctrl_dev *pctl; |
28 | struct pinctrl_desc pctl_desc; |
29 | |
30 | const struct visconti_pinctrl_devdata *devdata; |
31 | |
32 | spinlock_t lock; /* protect pinctrl register */ |
33 | }; |
34 | |
35 | /* pinconf */ |
36 | static int visconti_pin_config_set(struct pinctrl_dev *pctldev, |
37 | unsigned int _pin, |
38 | unsigned long *configs, |
39 | unsigned int num_configs) |
40 | { |
41 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
42 | const struct visconti_desc_pin *pin = &priv->devdata->pins[_pin]; |
43 | enum pin_config_param param; |
44 | unsigned int arg; |
45 | int i, ret = 0; |
46 | unsigned int val, set_val, pude_val; |
47 | unsigned long flags; |
48 | |
49 | dev_dbg(priv->dev, "%s: pin = %d (%s)\n" , __func__, _pin, pin->pin.name); |
50 | |
51 | spin_lock_irqsave(&priv->lock, flags); |
52 | |
53 | for (i = 0; i < num_configs; i++) { |
54 | set_val = 0; |
55 | pude_val = 0; |
56 | |
57 | param = pinconf_to_config_param(config: configs[i]); |
58 | switch (param) { |
59 | case PIN_CONFIG_BIAS_PULL_UP: |
60 | set_val = 1; |
61 | fallthrough; |
62 | case PIN_CONFIG_BIAS_PULL_DOWN: |
63 | /* update pudsel setting */ |
64 | val = readl(addr: priv->base + pin->pudsel_offset); |
65 | val &= ~BIT(pin->pud_shift); |
66 | val |= set_val << pin->pud_shift; |
67 | writel(val, addr: priv->base + pin->pudsel_offset); |
68 | pude_val = 1; |
69 | fallthrough; |
70 | case PIN_CONFIG_BIAS_DISABLE: |
71 | /* update pude setting */ |
72 | val = readl(addr: priv->base + pin->pude_offset); |
73 | val &= ~BIT(pin->pud_shift); |
74 | val |= pude_val << pin->pud_shift; |
75 | writel(val, addr: priv->base + pin->pude_offset); |
76 | dev_dbg(priv->dev, "BIAS(%d): off = 0x%x val = 0x%x\n" , |
77 | param, pin->pude_offset, val); |
78 | break; |
79 | |
80 | case PIN_CONFIG_DRIVE_STRENGTH: |
81 | arg = pinconf_to_config_argument(config: configs[i]); |
82 | dev_dbg(priv->dev, "DRV_STR arg = %d\n" , arg); |
83 | switch (arg) { |
84 | case 2: |
85 | case 4: |
86 | case 8: |
87 | case 16: |
88 | case 24: |
89 | case 32: |
90 | /* |
91 | * I/O drive capacity setting: |
92 | * 2mA: 0 |
93 | * 4mA: 1 |
94 | * 8mA: 3 |
95 | * 16mA: 7 |
96 | * 24mA: 11 |
97 | * 32mA: 15 |
98 | */ |
99 | set_val = DIV_ROUND_CLOSEST(arg, 2) - 1; |
100 | break; |
101 | default: |
102 | ret = -EINVAL; |
103 | goto err; |
104 | } |
105 | /* update drive setting */ |
106 | val = readl(addr: priv->base + pin->dsel_offset); |
107 | val &= ~(DSEL_MASK << pin->dsel_shift); |
108 | val |= set_val << pin->dsel_shift; |
109 | writel(val, addr: priv->base + pin->dsel_offset); |
110 | break; |
111 | |
112 | default: |
113 | ret = -EOPNOTSUPP; |
114 | goto err; |
115 | } |
116 | } |
117 | err: |
118 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
119 | return ret; |
120 | } |
121 | |
122 | static int visconti_pin_config_group_set(struct pinctrl_dev *pctldev, |
123 | unsigned int selector, |
124 | unsigned long *configs, |
125 | unsigned int num_configs) |
126 | { |
127 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
128 | const unsigned int *pins; |
129 | unsigned int num_pins; |
130 | int i, ret; |
131 | |
132 | pins = priv->devdata->groups[selector].pins; |
133 | num_pins = priv->devdata->groups[selector].nr_pins; |
134 | |
135 | dev_dbg(priv->dev, "%s: select = %d, n_pin = %d, n_config = %d\n" , |
136 | __func__, selector, num_pins, num_configs); |
137 | |
138 | for (i = 0; i < num_pins; i++) { |
139 | ret = visconti_pin_config_set(pctldev, pin: pins[i], |
140 | configs, num_configs); |
141 | if (ret) |
142 | return ret; |
143 | } |
144 | |
145 | return 0; |
146 | } |
147 | static const struct pinconf_ops visconti_pinconf_ops = { |
148 | .is_generic = true, |
149 | .pin_config_set = visconti_pin_config_set, |
150 | .pin_config_group_set = visconti_pin_config_group_set, |
151 | .pin_config_config_dbg_show = pinconf_generic_dump_config, |
152 | }; |
153 | |
154 | /* pinctrl */ |
155 | static int visconti_get_groups_count(struct pinctrl_dev *pctldev) |
156 | { |
157 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
158 | |
159 | return priv->devdata->nr_groups; |
160 | } |
161 | |
162 | static const char *visconti_get_group_name(struct pinctrl_dev *pctldev, |
163 | unsigned int selector) |
164 | { |
165 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
166 | |
167 | return priv->devdata->groups[selector].name; |
168 | } |
169 | |
170 | static int visconti_get_group_pins(struct pinctrl_dev *pctldev, |
171 | unsigned int selector, |
172 | const unsigned int **pins, |
173 | unsigned int *num_pins) |
174 | { |
175 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
176 | |
177 | *pins = priv->devdata->groups[selector].pins; |
178 | *num_pins = priv->devdata->groups[selector].nr_pins; |
179 | |
180 | return 0; |
181 | } |
182 | |
183 | static const struct pinctrl_ops visconti_pinctrl_ops = { |
184 | .get_groups_count = visconti_get_groups_count, |
185 | .get_group_name = visconti_get_group_name, |
186 | .get_group_pins = visconti_get_group_pins, |
187 | .dt_node_to_map = pinconf_generic_dt_node_to_map_group, |
188 | .dt_free_map = pinctrl_utils_free_map, |
189 | }; |
190 | |
191 | /* pinmux */ |
192 | static int visconti_get_functions_count(struct pinctrl_dev *pctldev) |
193 | { |
194 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
195 | |
196 | return priv->devdata->nr_functions; |
197 | } |
198 | |
199 | static const char *visconti_get_function_name(struct pinctrl_dev *pctldev, |
200 | unsigned int selector) |
201 | { |
202 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
203 | |
204 | return priv->devdata->functions[selector].name; |
205 | } |
206 | |
207 | static int visconti_get_function_groups(struct pinctrl_dev *pctldev, |
208 | unsigned int selector, |
209 | const char * const **groups, |
210 | unsigned * const num_groups) |
211 | { |
212 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
213 | |
214 | *groups = priv->devdata->functions[selector].groups; |
215 | *num_groups = priv->devdata->functions[selector].nr_groups; |
216 | |
217 | return 0; |
218 | } |
219 | |
220 | static int visconti_set_mux(struct pinctrl_dev *pctldev, |
221 | unsigned int function, unsigned int group) |
222 | { |
223 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
224 | const struct visconti_pin_function *func = &priv->devdata->functions[function]; |
225 | const struct visconti_pin_group *grp = &priv->devdata->groups[group]; |
226 | const struct visconti_mux *mux = &grp->mux; |
227 | unsigned int val; |
228 | unsigned long flags; |
229 | |
230 | dev_dbg(priv->dev, "%s: function = %d(%s) group = %d(%s)\n" , __func__, |
231 | function, func->name, group, grp->name); |
232 | |
233 | spin_lock_irqsave(&priv->lock, flags); |
234 | |
235 | /* update mux */ |
236 | val = readl(addr: priv->base + mux->offset); |
237 | val &= ~mux->mask; |
238 | val |= mux->val; |
239 | writel(val, addr: priv->base + mux->offset); |
240 | |
241 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
242 | |
243 | dev_dbg(priv->dev, "[%x]: 0x%x\n" , mux->offset, val); |
244 | |
245 | return 0; |
246 | } |
247 | |
248 | static int visconti_gpio_request_enable(struct pinctrl_dev *pctldev, |
249 | struct pinctrl_gpio_range *range, |
250 | unsigned int pin) |
251 | { |
252 | struct visconti_pinctrl *priv = pinctrl_dev_get_drvdata(pctldev); |
253 | const struct visconti_mux *gpio_mux = &priv->devdata->gpio_mux[pin]; |
254 | unsigned long flags; |
255 | unsigned int val; |
256 | |
257 | dev_dbg(priv->dev, "%s: pin = %d\n" , __func__, pin); |
258 | |
259 | /* update mux */ |
260 | spin_lock_irqsave(&priv->lock, flags); |
261 | val = readl(addr: priv->base + gpio_mux->offset); |
262 | val &= ~gpio_mux->mask; |
263 | val |= gpio_mux->val; |
264 | writel(val, addr: priv->base + gpio_mux->offset); |
265 | spin_unlock_irqrestore(lock: &priv->lock, flags); |
266 | |
267 | return 0; |
268 | } |
269 | |
270 | static const struct pinmux_ops visconti_pinmux_ops = { |
271 | .get_functions_count = visconti_get_functions_count, |
272 | .get_function_name = visconti_get_function_name, |
273 | .get_function_groups = visconti_get_function_groups, |
274 | .set_mux = visconti_set_mux, |
275 | .gpio_request_enable = visconti_gpio_request_enable, |
276 | .strict = true, |
277 | }; |
278 | |
279 | int visconti_pinctrl_probe(struct platform_device *pdev, |
280 | const struct visconti_pinctrl_devdata *devdata) |
281 | { |
282 | struct device *dev = &pdev->dev; |
283 | struct visconti_pinctrl *priv; |
284 | struct pinctrl_pin_desc *pins; |
285 | int i, ret; |
286 | |
287 | priv = devm_kzalloc(dev, size: sizeof(*priv), GFP_KERNEL); |
288 | if (!priv) |
289 | return -ENOMEM; |
290 | |
291 | priv->dev = dev; |
292 | priv->devdata = devdata; |
293 | spin_lock_init(&priv->lock); |
294 | |
295 | priv->base = devm_platform_ioremap_resource(pdev, index: 0); |
296 | if (IS_ERR(ptr: priv->base)) { |
297 | dev_err(dev, "unable to map I/O space\n" ); |
298 | return PTR_ERR(ptr: priv->base); |
299 | } |
300 | |
301 | pins = devm_kcalloc(dev, n: devdata->nr_pins, |
302 | size: sizeof(*pins), GFP_KERNEL); |
303 | if (!pins) |
304 | return -ENOMEM; |
305 | |
306 | for (i = 0; i < devdata->nr_pins; i++) |
307 | pins[i] = devdata->pins[i].pin; |
308 | |
309 | priv->pctl_desc.name = dev_name(dev); |
310 | priv->pctl_desc.owner = THIS_MODULE; |
311 | priv->pctl_desc.pins = pins; |
312 | priv->pctl_desc.npins = devdata->nr_pins; |
313 | priv->pctl_desc.confops = &visconti_pinconf_ops; |
314 | priv->pctl_desc.pctlops = &visconti_pinctrl_ops; |
315 | priv->pctl_desc.pmxops = &visconti_pinmux_ops; |
316 | |
317 | ret = devm_pinctrl_register_and_init(dev, pctldesc: &priv->pctl_desc, |
318 | driver_data: priv, pctldev: &priv->pctl); |
319 | if (ret) { |
320 | dev_err(dev, "couldn't register pinctrl: %d\n" , ret); |
321 | return ret; |
322 | } |
323 | |
324 | if (devdata->unlock) |
325 | devdata->unlock(priv->base); |
326 | |
327 | return pinctrl_enable(pctldev: priv->pctl); |
328 | } |
329 | |