blob: b7ae2f6adab241ff88fac14db1fffe5a255074fd [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Wenyou Yang309686c2016-07-20 17:16:27 +08002/*
3 * Atmel PIO4 pinctrl driver
4 *
5 * Copyright (C) 2016 Atmel Corporation
6 * Wenyou.Yang <wenyou.yang@atmel.com>
Wenyou Yang309686c2016-07-20 17:16:27 +08007 */
8
9#include <common.h>
Simon Glass11c89f32017-05-17 17:18:03 -060010#include <dm.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060011#include <asm/global_data.h>
Wenyou Yang309686c2016-07-20 17:16:27 +080012#include <dm/pinctrl.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060013#include <linux/bitops.h>
Wenyou Yang309686c2016-07-20 17:16:27 +080014#include <linux/io.h>
15#include <linux/err.h>
16#include <mach/atmel_pio4.h>
17
18DECLARE_GLOBAL_DATA_PTR;
19
20/*
21 * Warning:
22 * In order to not introduce confusion between Atmel PIO groups and pinctrl
23 * framework groups, Atmel PIO groups will be called banks.
24 */
25
Simon Glassb75b15b2020-12-03 16:55:23 -070026struct atmel_pio4_plat {
Wenyou Yang309686c2016-07-20 17:16:27 +080027 struct atmel_pio4_port *reg_base;
28};
29
30static const struct pinconf_param conf_params[] = {
31 { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
32 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
33 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
34 { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
35 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
36 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
37 { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
Eugen Hristev90add2b2021-01-05 10:54:01 +020038 { "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
Wenyou Yang309686c2016-07-20 17:16:27 +080039};
40
Eugen Hristeve58dc842021-01-05 10:51:53 +020041static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
Wenyou Yang309686c2016-07-20 17:16:27 +080042{
43 const struct pinconf_param *params;
44 u32 param, arg, conf = 0;
45 u32 i;
Eugen Hristev90add2b2021-01-05 10:54:01 +020046 u32 val;
Wenyou Yang309686c2016-07-20 17:16:27 +080047
48 for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
49 params = &conf_params[i];
Eugen Hristeve58dc842021-01-05 10:51:53 +020050 if (!dev_read_prop(config, params->property, NULL))
Wenyou Yang309686c2016-07-20 17:16:27 +080051 continue;
52
53 param = params->param;
54 arg = params->default_value;
55
56 switch (param) {
57 case PIN_CONFIG_BIAS_DISABLE:
58 conf &= (~ATMEL_PIO_PUEN_MASK);
59 conf &= (~ATMEL_PIO_PDEN_MASK);
60 break;
61 case PIN_CONFIG_BIAS_PULL_UP:
62 conf |= ATMEL_PIO_PUEN_MASK;
63 break;
64 case PIN_CONFIG_BIAS_PULL_DOWN:
65 conf |= ATMEL_PIO_PDEN_MASK;
66 break;
67 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
68 if (arg == 0)
69 conf &= (~ATMEL_PIO_OPD_MASK);
70 else
71 conf |= ATMEL_PIO_OPD_MASK;
72 break;
73 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
74 if (arg == 0)
75 conf |= ATMEL_PIO_SCHMITT_MASK;
76 else
77 conf &= (~ATMEL_PIO_SCHMITT_MASK);
78 break;
79 case PIN_CONFIG_INPUT_DEBOUNCE:
80 if (arg == 0) {
81 conf &= (~ATMEL_PIO_IFEN_MASK);
82 conf &= (~ATMEL_PIO_IFSCEN_MASK);
83 } else {
84 conf |= ATMEL_PIO_IFEN_MASK;
85 conf |= ATMEL_PIO_IFSCEN_MASK;
86 }
87 break;
Eugen Hristev90add2b2021-01-05 10:54:01 +020088 case PIN_CONFIG_DRIVE_STRENGTH:
89 dev_read_u32(config, params->property, &val);
90 conf &= (~ATMEL_PIO_DRVSTR_MASK);
91 conf |= (val << ATMEL_PIO_DRVSTR_OFFSET)
92 & ATMEL_PIO_DRVSTR_MASK;
93 break;
Wenyou Yang309686c2016-07-20 17:16:27 +080094 default:
95 printf("%s: Unsupported configuration parameter: %u\n",
96 __func__, param);
97 break;
98 }
99 }
100
101 return conf;
102}
103
104static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
105 u32 bank)
106{
Simon Glassb75b15b2020-12-03 16:55:23 -0700107 struct atmel_pio4_plat *plat = dev_get_plat(dev);
Wenyou Yang309686c2016-07-20 17:16:27 +0800108 struct atmel_pio4_port *bank_base =
109 (struct atmel_pio4_port *)((u32)plat->reg_base +
110 ATMEL_PIO_BANK_OFFSET * bank);
111
112 return bank_base;
113}
114
115#define MAX_PINMUX_ENTRIES 40
116
117static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
118{
119 struct atmel_pio4_port *bank_base;
120 const void *blob = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700121 int node = dev_of_offset(config);
Wenyou Yang309686c2016-07-20 17:16:27 +0800122 u32 offset, func, bank, line;
123 u32 cells[MAX_PINMUX_ENTRIES];
124 u32 i, conf;
125 int count;
126
Eugen Hristeve58dc842021-01-05 10:51:53 +0200127 conf = atmel_pinctrl_get_pinconf(config);
Wenyou Yang309686c2016-07-20 17:16:27 +0800128
129 count = fdtdec_get_int_array_count(blob, node, "pinmux",
130 cells, ARRAY_SIZE(cells));
131 if (count < 0) {
132 printf("%s: bad pinmux array %d\n", __func__, count);
133 return -EINVAL;
134 }
135
136 if (count > MAX_PINMUX_ENTRIES) {
137 printf("%s: unsupported pinmux array count %d\n",
138 __func__, count);
139 return -EINVAL;
140 }
141
142 for (i = 0 ; i < count; i++) {
143 offset = ATMEL_GET_PIN_NO(cells[i]);
144 func = ATMEL_GET_PIN_FUNC(cells[i]);
145
146 bank = ATMEL_PIO_BANK(offset);
147 line = ATMEL_PIO_LINE(offset);
148
149 bank_base = atmel_pio4_bank_base(dev, bank);
150
151 writel(BIT(line), &bank_base->mskr);
152 conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
153 conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
154 writel(conf, &bank_base->cfgr);
155 }
156
157 return 0;
158}
159
160const struct pinctrl_ops atmel_pinctrl_ops = {
161 .set_state = atmel_pinctrl_set_state,
162};
163
164static int atmel_pinctrl_probe(struct udevice *dev)
165{
Simon Glassb75b15b2020-12-03 16:55:23 -0700166 struct atmel_pio4_plat *plat = dev_get_plat(dev);
Wenyou Yang309686c2016-07-20 17:16:27 +0800167 fdt_addr_t addr_base;
168
169 dev = dev_get_parent(dev);
Masahiro Yamadaa89b4de2020-07-17 14:36:48 +0900170 addr_base = dev_read_addr(dev);
Wenyou Yang309686c2016-07-20 17:16:27 +0800171 if (addr_base == FDT_ADDR_T_NONE)
172 return -EINVAL;
173
174 plat->reg_base = (struct atmel_pio4_port *)addr_base;
175
176 return 0;
177}
178
179static const struct udevice_id atmel_pinctrl_match[] = {
180 { .compatible = "atmel,sama5d2-pinctrl" },
Eugen Hristevd05b43d2020-08-27 12:04:40 +0300181 { .compatible = "microchip,sama7g5-pinctrl" },
Wenyou Yang309686c2016-07-20 17:16:27 +0800182 {}
183};
184
185U_BOOT_DRIVER(atmel_pinctrl) = {
186 .name = "pinctrl_atmel_pio4",
187 .id = UCLASS_PINCTRL,
188 .of_match = atmel_pinctrl_match,
189 .probe = atmel_pinctrl_probe,
Simon Glassb75b15b2020-12-03 16:55:23 -0700190 .plat_auto = sizeof(struct atmel_pio4_plat),
Wenyou Yang309686c2016-07-20 17:16:27 +0800191 .ops = &atmel_pinctrl_ops,
192};