]> Git Repo - u-boot.git/blame - drivers/pinctrl/pinctrl-at91-pio4.c
Merge tag 'efi-2022-07-rc1' of https://source.denx.de/u-boot/custodians/u-boot-efi
[u-boot.git] / drivers / pinctrl / pinctrl-at91-pio4.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
ac72e174
WY
2/*
3 * Atmel PIO4 pinctrl driver
4 *
5 * Copyright (C) 2016 Atmel Corporation
6 * Wenyou.Yang <[email protected]>
ac72e174
WY
7 */
8
9#include <common.h>
9d922450 10#include <dm.h>
401d1c4f 11#include <asm/global_data.h>
ac72e174 12#include <dm/pinctrl.h>
cd93d625 13#include <linux/bitops.h>
ac72e174
WY
14#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
8a8d24bd 26struct atmel_pio4_plat {
ac72e174 27 struct atmel_pio4_port *reg_base;
8bad34a7 28 unsigned int slew_rate_support;
ac72e174
WY
29};
30
31static 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 },
417eca09 39 { "atmel,drive-strength", PIN_CONFIG_DRIVE_STRENGTH, 0 },
8bad34a7 40 { "slew-rate", PIN_CONFIG_SLEW_RATE, 0},
ac72e174
WY
41};
42
8bad34a7
CB
43static u32 atmel_pinctrl_get_pinconf(struct udevice *config,
44 struct atmel_pio4_plat *plat)
ac72e174
WY
45{
46 const struct pinconf_param *params;
47 u32 param, arg, conf = 0;
48 u32 i;
417eca09 49 u32 val;
ac72e174
WY
50
51 for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
52 params = &conf_params[i];
864a4144 53 if (!dev_read_prop(config, params->property, NULL))
ac72e174
WY
54 continue;
55
56 param = params->param;
57 arg = params->default_value;
58
8bad34a7
CB
59 /* Keep slew rate enabled by default. */
60 if (plat->slew_rate_support)
61 conf |= ATMEL_PIO_SR;
62
ac72e174
WY
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;
417eca09
EH
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;
8bad34a7
CB
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;
ac72e174
WY
110 default:
111 printf("%s: Unsupported configuration parameter: %u\n",
112 __func__, param);
113 break;
114 }
115 }
116
117 return conf;
118}
119
120static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
121 u32 bank)
122{
8a8d24bd 123 struct atmel_pio4_plat *plat = dev_get_plat(dev);
ac72e174
WY
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
133static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
134{
8bad34a7 135 struct atmel_pio4_plat *plat = dev_get_plat(dev);
ac72e174
WY
136 struct atmel_pio4_port *bank_base;
137 const void *blob = gd->fdt_blob;
e160f7d4 138 int node = dev_of_offset(config);
ac72e174
WY
139 u32 offset, func, bank, line;
140 u32 cells[MAX_PINMUX_ENTRIES];
141 u32 i, conf;
142 int count;
143
8bad34a7 144 conf = atmel_pinctrl_get_pinconf(config, plat);
ac72e174
WY
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
177const struct pinctrl_ops atmel_pinctrl_ops = {
178 .set_state = atmel_pinctrl_set_state,
179};
180
181static int atmel_pinctrl_probe(struct udevice *dev)
182{
8a8d24bd 183 struct atmel_pio4_plat *plat = dev_get_plat(dev);
8bad34a7 184 ulong priv = dev_get_driver_data(dev);
ac72e174
WY
185 fdt_addr_t addr_base;
186
187 dev = dev_get_parent(dev);
2548493a 188 addr_base = dev_read_addr(dev);
ac72e174
WY
189 if (addr_base == FDT_ADDR_T_NONE)
190 return -EINVAL;
191
192 plat->reg_base = (struct atmel_pio4_port *)addr_base;
8bad34a7 193 plat->slew_rate_support = priv;
ac72e174
WY
194
195 return 0;
196}
197
198static const struct udevice_id atmel_pinctrl_match[] = {
199 { .compatible = "atmel,sama5d2-pinctrl" },
8bad34a7
CB
200 { .compatible = "microchip,sama7g5-pinctrl",
201 .data = (ulong)1, },
ac72e174
WY
202 {}
203};
204
205U_BOOT_DRIVER(atmel_pinctrl) = {
206 .name = "pinctrl_atmel_pio4",
207 .id = UCLASS_PINCTRL,
208 .of_match = atmel_pinctrl_match,
209 .probe = atmel_pinctrl_probe,
8a8d24bd 210 .plat_auto = sizeof(struct atmel_pio4_plat),
ac72e174
WY
211 .ops = &atmel_pinctrl_ops,
212};
This page took 0.200039 seconds and 4 git commands to generate.