1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2016 - Beniamino Galvani <b.galvani@gmail.com>
9 #include <dm/device-internal.h>
10 #include <dm/device_compat.h>
12 #include <dm/pinctrl.h>
13 #include <fdt_support.h>
14 #include <linux/err.h>
16 #include <linux/sizes.h>
19 #include "pinctrl-meson.h"
21 DECLARE_GLOBAL_DATA_PTR
;
23 static const char *meson_pinctrl_dummy_name
= "_dummy";
25 static char pin_name
[PINNAME_SIZE
];
27 int meson_pinctrl_get_groups_count(struct udevice
*dev
)
29 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
31 return priv
->data
->num_groups
;
34 const char *meson_pinctrl_get_group_name(struct udevice
*dev
,
35 unsigned int selector
)
37 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
39 if (!priv
->data
->groups
[selector
].name
)
40 return meson_pinctrl_dummy_name
;
42 return priv
->data
->groups
[selector
].name
;
45 int meson_pinctrl_get_pins_count(struct udevice
*dev
)
47 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
49 return priv
->data
->num_pins
;
52 const char *meson_pinctrl_get_pin_name(struct udevice
*dev
,
53 unsigned int selector
)
55 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
57 if (selector
> priv
->data
->num_pins
||
58 selector
> priv
->data
->funcs
[0].num_groups
)
59 snprintf(pin_name
, PINNAME_SIZE
, "Error");
61 snprintf(pin_name
, PINNAME_SIZE
, "%s",
62 priv
->data
->funcs
[0].groups
[selector
]);
67 int meson_pinmux_get_functions_count(struct udevice
*dev
)
69 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
71 return priv
->data
->num_funcs
;
74 const char *meson_pinmux_get_function_name(struct udevice
*dev
,
75 unsigned int selector
)
77 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
79 return priv
->data
->funcs
[selector
].name
;
82 static int meson_gpio_calc_reg_and_bit(struct udevice
*dev
, unsigned int offset
,
83 enum meson_reg_type reg_type
,
84 unsigned int *reg
, unsigned int *bit
)
86 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
87 struct meson_bank
*bank
= NULL
;
88 struct meson_reg_desc
*desc
;
92 pin
= priv
->data
->pin_base
+ offset
;
94 for (i
= 0; i
< priv
->data
->num_banks
; i
++) {
95 if (pin
>= priv
->data
->banks
[i
].first
&&
96 pin
<= priv
->data
->banks
[i
].last
) {
97 bank
= &priv
->data
->banks
[i
];
105 desc
= &bank
->regs
[reg_type
];
106 *reg
= desc
->reg
* 4;
107 *bit
= desc
->bit
+ pin
- bank
->first
;
112 int meson_gpio_get(struct udevice
*dev
, unsigned int offset
)
114 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
115 unsigned int reg
, bit
;
118 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_IN
, ®
,
123 return !!(readl(priv
->reg_gpio
+ reg
) & BIT(bit
));
126 int meson_gpio_set(struct udevice
*dev
, unsigned int offset
, int value
)
128 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
129 unsigned int reg
, bit
;
132 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_OUT
, ®
,
137 clrsetbits_le32(priv
->reg_gpio
+ reg
, BIT(bit
), value
? BIT(bit
) : 0);
142 int meson_gpio_get_direction(struct udevice
*dev
, unsigned int offset
)
144 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
145 unsigned int reg
, bit
, val
;
148 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_DIR
, ®
,
153 val
= readl(priv
->reg_gpio
+ reg
);
155 return (val
& BIT(bit
)) ? GPIOF_INPUT
: GPIOF_OUTPUT
;
158 int meson_gpio_direction_input(struct udevice
*dev
, unsigned int offset
)
160 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
161 unsigned int reg
, bit
;
164 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_DIR
, ®
,
169 setbits_le32(priv
->reg_gpio
+ reg
, BIT(bit
));
174 int meson_gpio_direction_output(struct udevice
*dev
,
175 unsigned int offset
, int value
)
177 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
178 unsigned int reg
, bit
;
181 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_DIR
, ®
,
186 clrbits_le32(priv
->reg_gpio
+ reg
, BIT(bit
));
188 ret
= meson_gpio_calc_reg_and_bit(dev
->parent
, offset
, REG_OUT
, ®
,
193 clrsetbits_le32(priv
->reg_gpio
+ reg
, BIT(bit
), value
? BIT(bit
) : 0);
198 static int meson_pinconf_bias_set(struct udevice
*dev
, unsigned int pin
,
201 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
202 unsigned int offset
= pin
- priv
->data
->pin_base
;
203 unsigned int reg
, bit
;
206 ret
= meson_gpio_calc_reg_and_bit(dev
, offset
, REG_PULLEN
, ®
, &bit
);
210 if (param
== PIN_CONFIG_BIAS_DISABLE
) {
211 clrsetbits_le32(priv
->reg_pullen
+ reg
, BIT(bit
), 0);
215 /* othewise, enable the bias and select level */
216 clrsetbits_le32(priv
->reg_pullen
+ reg
, BIT(bit
), 1);
217 ret
= meson_gpio_calc_reg_and_bit(dev
, offset
, REG_PULL
, ®
, &bit
);
221 clrsetbits_le32(priv
->reg_pull
+ reg
, BIT(bit
),
222 param
== PIN_CONFIG_BIAS_PULL_UP
);
227 static int meson_pinconf_drive_strength_set(struct udevice
*dev
,
229 unsigned int drive_strength_ua
)
231 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
232 unsigned int offset
= pin
- priv
->data
->pin_base
;
233 unsigned int reg
, bit
;
238 dev_err(dev
, "drive-strength-microamp not supported\n");
242 ret
= meson_gpio_calc_reg_and_bit(dev
, offset
, REG_DS
, ®
, &bit
);
248 if (drive_strength_ua
<= 500) {
249 ds_val
= MESON_PINCONF_DRV_500UA
;
250 } else if (drive_strength_ua
<= 2500) {
251 ds_val
= MESON_PINCONF_DRV_2500UA
;
252 } else if (drive_strength_ua
<= 3000) {
253 ds_val
= MESON_PINCONF_DRV_3000UA
;
254 } else if (drive_strength_ua
<= 4000) {
255 ds_val
= MESON_PINCONF_DRV_4000UA
;
258 "pin %u: invalid drive-strength-microamp : %d , default to 4mA\n",
259 pin
, drive_strength_ua
);
260 ds_val
= MESON_PINCONF_DRV_4000UA
;
263 clrsetbits_le32(priv
->reg_ds
+ reg
, 0x3 << bit
, ds_val
<< bit
);
268 int meson_pinconf_set(struct udevice
*dev
, unsigned int pin
,
269 unsigned int param
, unsigned int arg
)
274 case PIN_CONFIG_BIAS_DISABLE
:
275 case PIN_CONFIG_BIAS_PULL_UP
:
276 case PIN_CONFIG_BIAS_PULL_DOWN
:
277 ret
= meson_pinconf_bias_set(dev
, pin
, param
);
279 case PIN_CONFIG_DRIVE_STRENGTH_UA
:
280 ret
= meson_pinconf_drive_strength_set(dev
, pin
, arg
);
283 dev_err(dev
, "unsupported configuration parameter %u\n", param
);
290 int meson_pinconf_group_set(struct udevice
*dev
,
291 unsigned int group_selector
,
292 unsigned int param
, unsigned int arg
)
294 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
295 struct meson_pmx_group
*grp
= &priv
->data
->groups
[group_selector
];
298 for (i
= 0; i
< grp
->num_pins
; i
++) {
299 ret
= meson_pinconf_set(dev
, grp
->pins
[i
], param
, arg
);
307 int meson_gpio_probe(struct udevice
*dev
)
309 struct meson_pinctrl
*priv
= dev_get_priv(dev
->parent
);
310 struct gpio_dev_priv
*uc_priv
;
312 uc_priv
= dev_get_uclass_priv(dev
);
313 uc_priv
->bank_name
= priv
->data
->name
;
314 uc_priv
->gpio_count
= priv
->data
->num_pins
;
319 static fdt_addr_t
parse_address(int offset
, const char *name
, int na
, int ns
)
324 index
= fdt_stringlist_search(gd
->fdt_blob
, offset
, "reg-names", name
);
326 return FDT_ADDR_T_NONE
;
328 reg
= fdt_getprop(gd
->fdt_blob
, offset
, "reg", &len
);
329 if (!reg
|| (len
<= (index
* sizeof(fdt32_t
) * (na
+ ns
))))
330 return FDT_ADDR_T_NONE
;
332 reg
+= index
* (na
+ ns
);
334 return fdt_translate_address((void *)gd
->fdt_blob
, offset
, reg
);
337 int meson_pinctrl_probe(struct udevice
*dev
)
339 struct meson_pinctrl
*priv
= dev_get_priv(dev
);
340 struct uclass_driver
*drv
;
341 struct udevice
*gpio_dev
;
343 int node
, gpio
= -1, len
;
347 na
= fdt_address_cells(gd
->fdt_blob
, dev_of_offset(dev
->parent
));
349 debug("bad #address-cells\n");
353 ns
= fdt_size_cells(gd
->fdt_blob
, dev_of_offset(dev
->parent
));
355 debug("bad #size-cells\n");
359 fdt_for_each_subnode(node
, gd
->fdt_blob
, dev_of_offset(dev
)) {
360 if (fdt_getprop(gd
->fdt_blob
, node
, "gpio-controller", &len
)) {
367 debug("gpio node not found\n");
371 addr
= parse_address(gpio
, "mux", na
, ns
);
372 if (addr
== FDT_ADDR_T_NONE
) {
373 debug("mux address not found\n");
376 priv
->reg_mux
= (void __iomem
*)addr
;
378 addr
= parse_address(gpio
, "gpio", na
, ns
);
379 if (addr
== FDT_ADDR_T_NONE
) {
380 debug("gpio address not found\n");
383 priv
->reg_gpio
= (void __iomem
*)addr
;
385 addr
= parse_address(gpio
, "pull", na
, ns
);
386 /* Use gpio region if pull one is not present */
387 if (addr
== FDT_ADDR_T_NONE
)
388 priv
->reg_pull
= priv
->reg_gpio
;
390 priv
->reg_pull
= (void __iomem
*)addr
;
392 addr
= parse_address(gpio
, "pull-enable", na
, ns
);
393 /* Use pull region if pull-enable one is not present */
394 if (addr
== FDT_ADDR_T_NONE
)
395 priv
->reg_pullen
= priv
->reg_pull
;
397 priv
->reg_pullen
= (void __iomem
*)addr
;
399 addr
= parse_address(gpio
, "ds", na
, ns
);
400 /* Drive strength region is optional */
401 if (addr
== FDT_ADDR_T_NONE
)
404 priv
->reg_ds
= (void __iomem
*)addr
;
406 priv
->data
= (struct meson_pinctrl_data
*)dev_get_driver_data(dev
);
408 /* Lookup GPIO driver */
409 drv
= lists_uclass_lookup(UCLASS_GPIO
);
411 puts("Cannot find GPIO driver\n");
415 name
= calloc(1, 32);
416 sprintf(name
, "meson-gpio");
418 /* Create child device UCLASS_GPIO and bind it */
419 device_bind(dev
, priv
->data
->gpio_driver
, name
, NULL
, gpio
, &gpio_dev
);
420 dev_set_of_offset(gpio_dev
, gpio
);