spi: nxp_fspi: Ensure width is respected in spi-mem operations
[platform/kernel/u-boot.git] / drivers / pinctrl / pinctrl-at91-pio4.c
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         unsigned int slew_rate_support;
29 };
30
31 static const struct pinconf_param conf_params[] = {
32         { "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
33         { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
34         { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
35         { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
36         { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
37         { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
38         { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
39         { "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
40         { "slew-rate", PIN_CONFIG_SLEW_RATE, 0},
41 };
42
43 static u32 atmel_pinctrl_get_pinconf(struct udevice *config,
44                                      struct atmel_pio4_plat *plat)
45 {
46         const struct pinconf_param *params;
47         u32 param, arg, conf = 0;
48         u32 i;
49         u32 val;
50
51         for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
52                 params = &conf_params[i];
53                 if (!dev_read_prop(config, params->property, NULL))
54                         continue;
55
56                 param = params->param;
57                 arg = params->default_value;
58
59                 /* Keep slew rate enabled by default. */
60                 if (plat->slew_rate_support)
61                         conf |= ATMEL_PIO_SR;
62
63                 switch (param) {
64                 case PIN_CONFIG_BIAS_DISABLE:
65                         conf &= (~ATMEL_PIO_PUEN_MASK);
66                         conf &= (~ATMEL_PIO_PDEN_MASK);
67                         break;
68                 case PIN_CONFIG_BIAS_PULL_UP:
69                         conf |= ATMEL_PIO_PUEN_MASK;
70                         break;
71                 case PIN_CONFIG_BIAS_PULL_DOWN:
72                         conf |= ATMEL_PIO_PDEN_MASK;
73                         break;
74                 case PIN_CONFIG_DRIVE_OPEN_DRAIN:
75                         if (arg == 0)
76                                 conf &= (~ATMEL_PIO_OPD_MASK);
77                         else
78                                 conf |= ATMEL_PIO_OPD_MASK;
79                         break;
80                 case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
81                         if (arg == 0)
82                                 conf |= ATMEL_PIO_SCHMITT_MASK;
83                         else
84                                 conf &= (~ATMEL_PIO_SCHMITT_MASK);
85                         break;
86                 case PIN_CONFIG_INPUT_DEBOUNCE:
87                         if (arg == 0) {
88                                 conf &= (~ATMEL_PIO_IFEN_MASK);
89                                 conf &= (~ATMEL_PIO_IFSCEN_MASK);
90                         } else {
91                                 conf |= ATMEL_PIO_IFEN_MASK;
92                                 conf |= ATMEL_PIO_IFSCEN_MASK;
93                         }
94                         break;
95                 case PIN_CONFIG_DRIVE_STRENGTH:
96                         dev_read_u32(config, params->property, &val);
97                         conf &= (~ATMEL_PIO_DRVSTR_MASK);
98                         conf |= (val << ATMEL_PIO_DRVSTR_OFFSET)
99                                 & ATMEL_PIO_DRVSTR_MASK;
100                         break;
101                 case PIN_CONFIG_SLEW_RATE:
102                         if (!plat->slew_rate_support)
103                                 break;
104
105                         dev_read_u32(config, params->property, &val);
106                         /* And disable it if requested. */
107                         if (val == 0)
108                                 conf &= ~ATMEL_PIO_SR;
109                         break;
110                 default:
111                         printf("%s: Unsupported configuration parameter: %u\n",
112                                __func__, param);
113                         break;
114                 }
115         }
116
117         return conf;
118 }
119
120 static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
121                                                            u32 bank)
122 {
123         struct atmel_pio4_plat *plat = dev_get_plat(dev);
124         struct atmel_pio4_port *bank_base =
125                         (struct atmel_pio4_port *)((u32)plat->reg_base +
126                         ATMEL_PIO_BANK_OFFSET * bank);
127
128         return bank_base;
129 }
130
131 #define MAX_PINMUX_ENTRIES      40
132
133 static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
134 {
135         struct atmel_pio4_plat *plat = dev_get_plat(dev);
136         struct atmel_pio4_port *bank_base;
137         const void *blob = gd->fdt_blob;
138         int node = dev_of_offset(config);
139         u32 offset, func, bank, line;
140         u32 cells[MAX_PINMUX_ENTRIES];
141         u32 i, conf;
142         int count;
143
144         conf = atmel_pinctrl_get_pinconf(config, plat);
145
146         count = fdtdec_get_int_array_count(blob, node, "pinmux",
147                                            cells, ARRAY_SIZE(cells));
148         if (count < 0) {
149                 printf("%s: bad pinmux array %d\n", __func__, count);
150                 return -EINVAL;
151         }
152
153         if (count > MAX_PINMUX_ENTRIES) {
154                 printf("%s: unsupported pinmux array count %d\n",
155                        __func__, count);
156                 return -EINVAL;
157         }
158
159         for (i = 0 ; i < count; i++) {
160                 offset = ATMEL_GET_PIN_NO(cells[i]);
161                 func = ATMEL_GET_PIN_FUNC(cells[i]);
162
163                 bank = ATMEL_PIO_BANK(offset);
164                 line = ATMEL_PIO_LINE(offset);
165
166                 bank_base = atmel_pio4_bank_base(dev, bank);
167
168                 writel(BIT(line), &bank_base->mskr);
169                 conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
170                 conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
171                 writel(conf, &bank_base->cfgr);
172         }
173
174         return 0;
175 }
176
177 const struct pinctrl_ops atmel_pinctrl_ops  = {
178         .set_state = atmel_pinctrl_set_state,
179 };
180
181 static int atmel_pinctrl_probe(struct udevice *dev)
182 {
183         struct atmel_pio4_plat *plat = dev_get_plat(dev);
184         ulong priv = dev_get_driver_data(dev);
185         fdt_addr_t addr_base;
186
187         dev = dev_get_parent(dev);
188         addr_base = dev_read_addr(dev);
189         if (addr_base == FDT_ADDR_T_NONE)
190                 return -EINVAL;
191
192         plat->reg_base = (struct atmel_pio4_port *)addr_base;
193         plat->slew_rate_support = priv;
194
195         return 0;
196 }
197
198 static const struct udevice_id atmel_pinctrl_match[] = {
199         { .compatible = "atmel,sama5d2-pinctrl" },
200         { .compatible = "microchip,sama7g5-pinctrl",
201           .data = (ulong)1, },
202         {}
203 };
204
205 U_BOOT_DRIVER(atmel_pinctrl) = {
206         .name = "pinctrl_atmel_pio4",
207         .id = UCLASS_PINCTRL,
208         .of_match = atmel_pinctrl_match,
209         .probe = atmel_pinctrl_probe,
210         .plat_auto      = sizeof(struct atmel_pio4_plat),
211         .ops = &atmel_pinctrl_ops,
212 };