2 * Atmel PIO4 pinctrl driver
4 * Copyright (C) 2016 Atmel Corporation
5 * Wenyou.Yang <wenyou.yang@atmel.com>
7 * SPDX-License-Identifier: GPL-2.0+
12 #include <dm/pinctrl.h>
14 #include <linux/err.h>
15 #include <mach/atmel_pio4.h>
17 DECLARE_GLOBAL_DATA_PTR
;
21 * In order to not introduce confusion between Atmel PIO groups and pinctrl
22 * framework groups, Atmel PIO groups will be called banks.
25 struct atmel_pio4_platdata
{
26 struct atmel_pio4_port
*reg_base
;
29 static const struct pinconf_param conf_params
[] = {
30 { "bias-disable", PIN_CONFIG_BIAS_DISABLE
, 0 },
31 { "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP
, 1 },
32 { "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN
, 1 },
33 { "drive-open-drain", PIN_CONFIG_DRIVE_OPEN_DRAIN
, 0 },
34 { "input-schmitt-disable", PIN_CONFIG_INPUT_SCHMITT_ENABLE
, 0 },
35 { "input-schmitt-enable", PIN_CONFIG_INPUT_SCHMITT_ENABLE
, 1 },
36 { "input-debounce", PIN_CONFIG_INPUT_DEBOUNCE
, 0 },
39 static u32
atmel_pinctrl_get_pinconf(const void *blob
, int node
)
41 const struct pinconf_param
*params
;
42 u32 param
, arg
, conf
= 0;
45 for (i
= 0; i
< ARRAY_SIZE(conf_params
); i
++) {
46 params
= &conf_params
[i
];
47 if (!fdt_get_property(blob
, node
, params
->property
, NULL
))
50 param
= params
->param
;
51 arg
= params
->default_value
;
54 case PIN_CONFIG_BIAS_DISABLE
:
55 conf
&= (~ATMEL_PIO_PUEN_MASK
);
56 conf
&= (~ATMEL_PIO_PDEN_MASK
);
58 case PIN_CONFIG_BIAS_PULL_UP
:
59 conf
|= ATMEL_PIO_PUEN_MASK
;
61 case PIN_CONFIG_BIAS_PULL_DOWN
:
62 conf
|= ATMEL_PIO_PDEN_MASK
;
64 case PIN_CONFIG_DRIVE_OPEN_DRAIN
:
66 conf
&= (~ATMEL_PIO_OPD_MASK
);
68 conf
|= ATMEL_PIO_OPD_MASK
;
70 case PIN_CONFIG_INPUT_SCHMITT_ENABLE
:
72 conf
|= ATMEL_PIO_SCHMITT_MASK
;
74 conf
&= (~ATMEL_PIO_SCHMITT_MASK
);
76 case PIN_CONFIG_INPUT_DEBOUNCE
:
78 conf
&= (~ATMEL_PIO_IFEN_MASK
);
79 conf
&= (~ATMEL_PIO_IFSCEN_MASK
);
81 conf
|= ATMEL_PIO_IFEN_MASK
;
82 conf
|= ATMEL_PIO_IFSCEN_MASK
;
86 printf("%s: Unsupported configuration parameter: %u\n",
95 static inline struct atmel_pio4_port
*atmel_pio4_bank_base(struct udevice
*dev
,
98 struct atmel_pio4_platdata
*plat
= dev_get_platdata(dev
);
99 struct atmel_pio4_port
*bank_base
=
100 (struct atmel_pio4_port
*)((u32
)plat
->reg_base
+
101 ATMEL_PIO_BANK_OFFSET
* bank
);
106 #define MAX_PINMUX_ENTRIES 40
108 static int atmel_pinctrl_set_state(struct udevice
*dev
, struct udevice
*config
)
110 struct atmel_pio4_port
*bank_base
;
111 const void *blob
= gd
->fdt_blob
;
112 int node
= dev_of_offset(config
);
113 u32 offset
, func
, bank
, line
;
114 u32 cells
[MAX_PINMUX_ENTRIES
];
118 conf
= atmel_pinctrl_get_pinconf(blob
, node
);
120 count
= fdtdec_get_int_array_count(blob
, node
, "pinmux",
121 cells
, ARRAY_SIZE(cells
));
123 printf("%s: bad pinmux array %d\n", __func__
, count
);
127 if (count
> MAX_PINMUX_ENTRIES
) {
128 printf("%s: unsupported pinmux array count %d\n",
133 for (i
= 0 ; i
< count
; i
++) {
134 offset
= ATMEL_GET_PIN_NO(cells
[i
]);
135 func
= ATMEL_GET_PIN_FUNC(cells
[i
]);
137 bank
= ATMEL_PIO_BANK(offset
);
138 line
= ATMEL_PIO_LINE(offset
);
140 bank_base
= atmel_pio4_bank_base(dev
, bank
);
142 writel(BIT(line
), &bank_base
->mskr
);
143 conf
&= (~ATMEL_PIO_CFGR_FUNC_MASK
);
144 conf
|= (func
& ATMEL_PIO_CFGR_FUNC_MASK
);
145 writel(conf
, &bank_base
->cfgr
);
151 const struct pinctrl_ops atmel_pinctrl_ops
= {
152 .set_state
= atmel_pinctrl_set_state
,
155 static int atmel_pinctrl_probe(struct udevice
*dev
)
157 struct atmel_pio4_platdata
*plat
= dev_get_platdata(dev
);
158 fdt_addr_t addr_base
;
160 dev
= dev_get_parent(dev
);
161 addr_base
= dev_get_addr(dev
);
162 if (addr_base
== FDT_ADDR_T_NONE
)
165 plat
->reg_base
= (struct atmel_pio4_port
*)addr_base
;
170 static const struct udevice_id atmel_pinctrl_match
[] = {
171 { .compatible
= "atmel,sama5d2-pinctrl" },
175 U_BOOT_DRIVER(atmel_pinctrl
) = {
176 .name
= "pinctrl_atmel_pio4",
177 .id
= UCLASS_PINCTRL
,
178 .of_match
= atmel_pinctrl_match
,
179 .probe
= atmel_pinctrl_probe
,
180 .platdata_auto_alloc_size
= sizeof(struct atmel_pio4_platdata
),
181 .ops
= &atmel_pinctrl_ops
,