1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Atmel PIO4 pinctrl driver
4 *
5 * Copyright (C) 2016 Atmel Corporation
6 * Wenyou.Yang <wenyou.yang@atmel.com>
7 */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <asm/global_data.h>
12 #include <dm/pinctrl.h>
13 #include <linux/bitops.h>
14 #include <linux/io.h>
15 #include <linux/err.h>
16 #include <mach/atmel_pio4.h>
17
18 DECLARE_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
26 struct atmel_pio4_plat {
27 struct atmel_pio4_port *reg_base;
28 };
29
30 static 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 },
38 { "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
39 };
40
atmel_pinctrl_get_pinconf(struct udevice * config)41 static u32 atmel_pinctrl_get_pinconf(struct udevice *config)
42 {
43 const struct pinconf_param *params;
44 u32 param, arg, conf = 0;
45 u32 i;
46 u32 val;
47
48 for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
49 params = &conf_params[i];
50 if (!dev_read_prop(config, params->property, NULL))
51 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;
88 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;
94 default:
95 printf("%s: Unsupported configuration parameter: %u\n",
96 __func__, param);
97 break;
98 }
99 }
100
101 return conf;
102 }
103
atmel_pio4_bank_base(struct udevice * dev,u32 bank)104 static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
105 u32 bank)
106 {
107 struct atmel_pio4_plat *plat = dev_get_plat(dev);
108 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
atmel_pinctrl_set_state(struct udevice * dev,struct udevice * config)117 static 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;
121 int node = dev_of_offset(config);
122 u32 offset, func, bank, line;
123 u32 cells[MAX_PINMUX_ENTRIES];
124 u32 i, conf;
125 int count;
126
127 conf = atmel_pinctrl_get_pinconf(config);
128
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
160 const struct pinctrl_ops atmel_pinctrl_ops = {
161 .set_state = atmel_pinctrl_set_state,
162 };
163
atmel_pinctrl_probe(struct udevice * dev)164 static int atmel_pinctrl_probe(struct udevice *dev)
165 {
166 struct atmel_pio4_plat *plat = dev_get_plat(dev);
167 fdt_addr_t addr_base;
168
169 dev = dev_get_parent(dev);
170 addr_base = dev_read_addr(dev);
171 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
179 static const struct udevice_id atmel_pinctrl_match[] = {
180 { .compatible = "atmel,sama5d2-pinctrl" },
181 { .compatible = "microchip,sama7g5-pinctrl" },
182 {}
183 };
184
185 U_BOOT_DRIVER(atmel_pinctrl) = {
186 .name = "pinctrl_atmel_pio4",
187 .id = UCLASS_PINCTRL,
188 .of_match = atmel_pinctrl_match,
189 .probe = atmel_pinctrl_probe,
190 .plat_auto = sizeof(struct atmel_pio4_plat),
191 .ops = &atmel_pinctrl_ops,
192 };
193