2 * Exynos pinctrl driver common code.
3 * Copyright (C) 2016 Samsung Electronics
4 * Thomas Abraham <thomas.ab@samsung.com>
6 * SPDX-License-Identifier: GPL-2.0+
13 #include "pinctrl-exynos.h"
15 DECLARE_GLOBAL_DATA_PTR
;
18 * exynos_pinctrl_setup_peri: setup pinctrl for a peripheral.
19 * conf: soc specific pin configuration data array
20 * num_conf: number of configurations in the conf array.
21 * base: base address of the pin controller.
23 void exynos_pinctrl_setup_peri(struct exynos_pinctrl_config_data
*conf
,
24 unsigned int num_conf
, unsigned long base
)
26 unsigned int idx
, val
;
28 for (idx
= 0; idx
< num_conf
; idx
++) {
29 val
= readl(base
+ conf
[idx
].offset
);
30 val
&= ~(conf
[idx
].mask
);
31 val
|= conf
[idx
].value
;
32 writel(val
, base
+ conf
[idx
].offset
);
36 /* given a pin-name, return the address of pin config registers */
37 static unsigned long pin_to_bank_base(struct udevice
*dev
, const char *pin_name
,
40 struct exynos_pinctrl_priv
*priv
= dev_get_priv(dev
);
41 const struct samsung_pin_ctrl
*pin_ctrl
= priv
->pin_ctrl
;
42 const struct samsung_pin_bank_data
*bank_data
= pin_ctrl
->pin_banks
;
43 u32 nr_banks
= pin_ctrl
->nr_banks
, idx
= 0;
47 * The format of the pin name is <bank name>-<pin_number>.
48 * Example: gpa0-4 (gpa0 is the bank name and 4 is the pin number.
50 while (pin_name
[idx
] != '-') {
51 bank
[idx
] = pin_name
[idx
];
55 *pin
= pin_name
[++idx
] - '0';
57 /* lookup the pin bank data using the pin bank name */
58 for (idx
= 0; idx
< nr_banks
; idx
++)
59 if (!strcmp(bank
, bank_data
[idx
].name
))
62 return priv
->base
+ bank_data
[idx
].offset
;
66 * exynos_pinctrl_set_state: configure a pin state.
67 * dev: the pinctrl device to be configured.
68 * config: the state to be configured.
70 int exynos_pinctrl_set_state(struct udevice
*dev
, struct udevice
*config
)
72 const void *fdt
= gd
->fdt_blob
;
73 int node
= dev_of_offset(config
);
74 unsigned int count
, idx
, pin_num
;
75 unsigned int pinfunc
, pinpud
, pindrv
;
76 unsigned long reg
, value
;
80 * refer to the following document for the pinctrl bindings
81 * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
83 count
= fdt_stringlist_count(fdt
, node
, "samsung,pins");
87 pinfunc
= fdtdec_get_int(fdt
, node
, "samsung,pin-function", -1);
88 pinpud
= fdtdec_get_int(fdt
, node
, "samsung,pin-pud", -1);
89 pindrv
= fdtdec_get_int(fdt
, node
, "samsung,pin-drv", -1);
91 for (idx
= 0; idx
< count
; idx
++) {
92 name
= fdt_stringlist_get(fdt
, node
, "samsung,pins", idx
, NULL
);
95 reg
= pin_to_bank_base(dev
, name
, &pin_num
);
98 value
= readl(reg
+ PIN_CON
);
99 value
&= ~(0xf << (pin_num
<< 2));
100 value
|= (pinfunc
<< (pin_num
<< 2));
101 writel(value
, reg
+ PIN_CON
);
105 value
= readl(reg
+ PIN_PUD
);
106 value
&= ~(0x3 << (pin_num
<< 1));
107 value
|= (pinpud
<< (pin_num
<< 1));
108 writel(value
, reg
+ PIN_PUD
);
112 value
= readl(reg
+ PIN_DRV
);
113 value
&= ~(0x3 << (pin_num
<< 1));
114 value
|= (pindrv
<< (pin_num
<< 1));
115 writel(value
, reg
+ PIN_DRV
);
122 int exynos_pinctrl_probe(struct udevice
*dev
)
124 struct exynos_pinctrl_priv
*priv
;
127 priv
= dev_get_priv(dev
);
131 base
= devfdt_get_addr(dev
);
132 if (base
== FDT_ADDR_T_NONE
)
136 priv
->pin_ctrl
= (struct samsung_pin_ctrl
*)dev_get_driver_data(dev
) +