xref: /rk3399_rockchip-uboot/drivers/pinctrl/pinctrl-at91-pio4.c (revision a821c4af79e4f5ce9b629b20473863397bbe9b10)
1ac72e174SWenyou Yang /*
2ac72e174SWenyou Yang  * Atmel PIO4 pinctrl driver
3ac72e174SWenyou Yang  *
4ac72e174SWenyou Yang  * Copyright (C) 2016 Atmel Corporation
5ac72e174SWenyou Yang  *               Wenyou.Yang <wenyou.yang@atmel.com>
6ac72e174SWenyou Yang  *
7ac72e174SWenyou Yang  * SPDX-License-Identifier:	GPL-2.0+
8ac72e174SWenyou Yang  */
9ac72e174SWenyou Yang 
10ac72e174SWenyou Yang #include <common.h>
119d922450SSimon Glass #include <dm.h>
12ac72e174SWenyou Yang #include <dm/pinctrl.h>
13ac72e174SWenyou Yang #include <linux/io.h>
14ac72e174SWenyou Yang #include <linux/err.h>
15ac72e174SWenyou Yang #include <mach/atmel_pio4.h>
16ac72e174SWenyou Yang 
17ac72e174SWenyou Yang DECLARE_GLOBAL_DATA_PTR;
18ac72e174SWenyou Yang 
19ac72e174SWenyou Yang /*
20ac72e174SWenyou Yang  * Warning:
21ac72e174SWenyou Yang  * In order to not introduce confusion between Atmel PIO groups and pinctrl
22ac72e174SWenyou Yang  * framework groups, Atmel PIO groups will be called banks.
23ac72e174SWenyou Yang  */
24ac72e174SWenyou Yang 
25ac72e174SWenyou Yang struct atmel_pio4_platdata {
26ac72e174SWenyou Yang 	struct atmel_pio4_port *reg_base;
27ac72e174SWenyou Yang };
28ac72e174SWenyou Yang 
29ac72e174SWenyou Yang static const struct pinconf_param conf_params[] = {
30ac72e174SWenyou Yang 	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
31ac72e174SWenyou Yang 	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
32ac72e174SWenyou Yang 	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
33ac72e174SWenyou Yang 	{ "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN, 0 },
34ac72e174SWenyou Yang 	{ "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 0 },
35ac72e174SWenyou Yang 	{ "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE, 1 },
36ac72e174SWenyou Yang 	{ "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE, 0 },
37ac72e174SWenyou Yang };
38ac72e174SWenyou Yang 
atmel_pinctrl_get_pinconf(const void * blob,int node)39ac72e174SWenyou Yang static u32 atmel_pinctrl_get_pinconf(const void *blob, int node)
40ac72e174SWenyou Yang {
41ac72e174SWenyou Yang 	const struct pinconf_param *params;
42ac72e174SWenyou Yang 	u32 param, arg, conf = 0;
43ac72e174SWenyou Yang 	u32 i;
44ac72e174SWenyou Yang 
45ac72e174SWenyou Yang 	for (i = 0; i < ARRAY_SIZE(conf_params); i++) {
46ac72e174SWenyou Yang 		params = &conf_params[i];
47ac72e174SWenyou Yang 		if (!fdt_get_property(blob, node, params->property, NULL))
48ac72e174SWenyou Yang 			continue;
49ac72e174SWenyou Yang 
50ac72e174SWenyou Yang 		param = params->param;
51ac72e174SWenyou Yang 		arg = params->default_value;
52ac72e174SWenyou Yang 
53ac72e174SWenyou Yang 		switch (param) {
54ac72e174SWenyou Yang 		case PIN_CONFIG_BIAS_DISABLE:
55ac72e174SWenyou Yang 			conf &= (~ATMEL_PIO_PUEN_MASK);
56ac72e174SWenyou Yang 			conf &= (~ATMEL_PIO_PDEN_MASK);
57ac72e174SWenyou Yang 			break;
58ac72e174SWenyou Yang 		case PIN_CONFIG_BIAS_PULL_UP:
59ac72e174SWenyou Yang 			conf |= ATMEL_PIO_PUEN_MASK;
60ac72e174SWenyou Yang 			break;
61ac72e174SWenyou Yang 		case PIN_CONFIG_BIAS_PULL_DOWN:
62ac72e174SWenyou Yang 			conf |= ATMEL_PIO_PDEN_MASK;
63ac72e174SWenyou Yang 			break;
64ac72e174SWenyou Yang 		case PIN_CONFIG_DRIVE_OPEN_DRAIN:
65ac72e174SWenyou Yang 			if (arg == 0)
66ac72e174SWenyou Yang 				conf &= (~ATMEL_PIO_OPD_MASK);
67ac72e174SWenyou Yang 			else
68ac72e174SWenyou Yang 				conf |= ATMEL_PIO_OPD_MASK;
69ac72e174SWenyou Yang 			break;
70ac72e174SWenyou Yang 		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
71ac72e174SWenyou Yang 			if (arg == 0)
72ac72e174SWenyou Yang 				conf |= ATMEL_PIO_SCHMITT_MASK;
73ac72e174SWenyou Yang 			else
74ac72e174SWenyou Yang 				conf &= (~ATMEL_PIO_SCHMITT_MASK);
75ac72e174SWenyou Yang 			break;
76ac72e174SWenyou Yang 		case PIN_CONFIG_INPUT_DEBOUNCE:
77ac72e174SWenyou Yang 			if (arg == 0) {
78ac72e174SWenyou Yang 				conf &= (~ATMEL_PIO_IFEN_MASK);
79ac72e174SWenyou Yang 				conf &= (~ATMEL_PIO_IFSCEN_MASK);
80ac72e174SWenyou Yang 			} else {
81ac72e174SWenyou Yang 				conf |= ATMEL_PIO_IFEN_MASK;
82ac72e174SWenyou Yang 				conf |= ATMEL_PIO_IFSCEN_MASK;
83ac72e174SWenyou Yang 			}
84ac72e174SWenyou Yang 			break;
85ac72e174SWenyou Yang 		default:
86ac72e174SWenyou Yang 			printf("%s: Unsupported configuration parameter: %u\n",
87ac72e174SWenyou Yang 			       __func__, param);
88ac72e174SWenyou Yang 			break;
89ac72e174SWenyou Yang 		}
90ac72e174SWenyou Yang 	}
91ac72e174SWenyou Yang 
92ac72e174SWenyou Yang 	return conf;
93ac72e174SWenyou Yang }
94ac72e174SWenyou Yang 
atmel_pio4_bank_base(struct udevice * dev,u32 bank)95ac72e174SWenyou Yang static inline struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev,
96ac72e174SWenyou Yang 							   u32 bank)
97ac72e174SWenyou Yang {
98ac72e174SWenyou Yang 	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
99ac72e174SWenyou Yang 	struct atmel_pio4_port *bank_base =
100ac72e174SWenyou Yang 			(struct atmel_pio4_port *)((u32)plat->reg_base +
101ac72e174SWenyou Yang 			ATMEL_PIO_BANK_OFFSET * bank);
102ac72e174SWenyou Yang 
103ac72e174SWenyou Yang 	return bank_base;
104ac72e174SWenyou Yang }
105ac72e174SWenyou Yang 
106ac72e174SWenyou Yang #define MAX_PINMUX_ENTRIES	40
107ac72e174SWenyou Yang 
atmel_pinctrl_set_state(struct udevice * dev,struct udevice * config)108ac72e174SWenyou Yang static int atmel_pinctrl_set_state(struct udevice *dev, struct udevice *config)
109ac72e174SWenyou Yang {
110ac72e174SWenyou Yang 	struct atmel_pio4_port *bank_base;
111ac72e174SWenyou Yang 	const void *blob = gd->fdt_blob;
112e160f7d4SSimon Glass 	int node = dev_of_offset(config);
113ac72e174SWenyou Yang 	u32 offset, func, bank, line;
114ac72e174SWenyou Yang 	u32 cells[MAX_PINMUX_ENTRIES];
115ac72e174SWenyou Yang 	u32 i, conf;
116ac72e174SWenyou Yang 	int count;
117ac72e174SWenyou Yang 
118ac72e174SWenyou Yang 	conf = atmel_pinctrl_get_pinconf(blob, node);
119ac72e174SWenyou Yang 
120ac72e174SWenyou Yang 	count = fdtdec_get_int_array_count(blob, node, "pinmux",
121ac72e174SWenyou Yang 					   cells, ARRAY_SIZE(cells));
122ac72e174SWenyou Yang 	if (count < 0) {
123ac72e174SWenyou Yang 		printf("%s: bad pinmux array %d\n", __func__, count);
124ac72e174SWenyou Yang 		return -EINVAL;
125ac72e174SWenyou Yang 	}
126ac72e174SWenyou Yang 
127ac72e174SWenyou Yang 	if (count > MAX_PINMUX_ENTRIES) {
128ac72e174SWenyou Yang 		printf("%s: unsupported pinmux array count %d\n",
129ac72e174SWenyou Yang 		       __func__, count);
130ac72e174SWenyou Yang 		return -EINVAL;
131ac72e174SWenyou Yang 	}
132ac72e174SWenyou Yang 
133ac72e174SWenyou Yang 	for (i = 0 ; i < count; i++) {
134ac72e174SWenyou Yang 		offset = ATMEL_GET_PIN_NO(cells[i]);
135ac72e174SWenyou Yang 		func = ATMEL_GET_PIN_FUNC(cells[i]);
136ac72e174SWenyou Yang 
137ac72e174SWenyou Yang 		bank = ATMEL_PIO_BANK(offset);
138ac72e174SWenyou Yang 		line = ATMEL_PIO_LINE(offset);
139ac72e174SWenyou Yang 
140ac72e174SWenyou Yang 		bank_base = atmel_pio4_bank_base(dev, bank);
141ac72e174SWenyou Yang 
142ac72e174SWenyou Yang 		writel(BIT(line), &bank_base->mskr);
143ac72e174SWenyou Yang 		conf &= (~ATMEL_PIO_CFGR_FUNC_MASK);
144ac72e174SWenyou Yang 		conf |= (func & ATMEL_PIO_CFGR_FUNC_MASK);
145ac72e174SWenyou Yang 		writel(conf, &bank_base->cfgr);
146ac72e174SWenyou Yang 	}
147ac72e174SWenyou Yang 
148ac72e174SWenyou Yang 	return 0;
149ac72e174SWenyou Yang }
150ac72e174SWenyou Yang 
151ac72e174SWenyou Yang const struct pinctrl_ops atmel_pinctrl_ops  = {
152ac72e174SWenyou Yang 	.set_state = atmel_pinctrl_set_state,
153ac72e174SWenyou Yang };
154ac72e174SWenyou Yang 
atmel_pinctrl_probe(struct udevice * dev)155ac72e174SWenyou Yang static int atmel_pinctrl_probe(struct udevice *dev)
156ac72e174SWenyou Yang {
157ac72e174SWenyou Yang 	struct atmel_pio4_platdata *plat = dev_get_platdata(dev);
158ac72e174SWenyou Yang 	fdt_addr_t addr_base;
159ac72e174SWenyou Yang 
160ac72e174SWenyou Yang 	dev = dev_get_parent(dev);
161*a821c4afSSimon Glass 	addr_base = devfdt_get_addr(dev);
162ac72e174SWenyou Yang 	if (addr_base == FDT_ADDR_T_NONE)
163ac72e174SWenyou Yang 		return -EINVAL;
164ac72e174SWenyou Yang 
165ac72e174SWenyou Yang 	plat->reg_base = (struct atmel_pio4_port *)addr_base;
166ac72e174SWenyou Yang 
167ac72e174SWenyou Yang 	return 0;
168ac72e174SWenyou Yang }
169ac72e174SWenyou Yang 
170ac72e174SWenyou Yang static const struct udevice_id atmel_pinctrl_match[] = {
171ac72e174SWenyou Yang 	{ .compatible = "atmel,sama5d2-pinctrl" },
172ac72e174SWenyou Yang 	{}
173ac72e174SWenyou Yang };
174ac72e174SWenyou Yang 
175ac72e174SWenyou Yang U_BOOT_DRIVER(atmel_pinctrl) = {
176ac72e174SWenyou Yang 	.name = "pinctrl_atmel_pio4",
177ac72e174SWenyou Yang 	.id = UCLASS_PINCTRL,
178ac72e174SWenyou Yang 	.of_match = atmel_pinctrl_match,
179ac72e174SWenyou Yang 	.probe = atmel_pinctrl_probe,
180ac72e174SWenyou Yang 	.platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata),
181ac72e174SWenyou Yang 	.ops = &atmel_pinctrl_ops,
182ac72e174SWenyou Yang };
183