Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / pinctrl / mvebu / pinctrl-mvebu.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2016 Marvell International Ltd.
4  * https://spdx.org/licenses
5  */
6
7 #include <common.h>
8 #include <config.h>
9 #include <fdtdec.h>
10 #include <errno.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <asm/global_data.h>
14 #include <dm/pinctrl.h>
15 #include <dm/root.h>
16 #include <asm/system.h>
17 #include <asm/io.h>
18 #include <asm/arch-armada8k/soc-info.h>
19 #include <linux/bitops.h>
20 #include "pinctrl-mvebu.h"
21
22 #define AP_EMMC_PHY_CTRL_REG            0x100
23 #define CP_EMMC_PHY_CTRL_REG            0x424
24 #define EMMC_PHY_CTRL_SDPHY_EN          BIT(0)
25
26 #define AP806_EMMC_CLK_PIN_ID           0
27 #define AP806_EMMC_CLK_FUNC             0x1
28 #define CP110_EMMC_CLK_PIN_ID           56
29 #define CP110_EMMC_CLK_FUNC             0xe
30
31 DECLARE_GLOBAL_DATA_PTR;
32
33 /* mvebu_pinctl_emmc_set_mux: configure sd/mmc PHY mux
34  * To enable SDIO/eMMC in Armada-APN806/CP110, need to configure PHY mux.
35  * eMMC/SD PHY register responsible for muxing between MPPs and SD/eMMC
36  * controller:
37  * - Bit0 enabled SDIO/eMMC PHY is used as a MPP muxltiplexer,
38  * - Bit0 disabled SDIO/eMMC PHY is connected to SDIO/eMMC controller
39  * If pin function is set to eMMC/SD, then configure the eMMC/SD PHY
40  * muxltiplexer register to be on SDIO/eMMC controller
41  */
42 void mvebu_pinctl_emmc_set_mux(struct udevice *dev, u32 pin, u32 func)
43 {
44         const void *blob = gd->fdt_blob;
45         int node = dev_of_offset(dev);
46         struct mvebu_pinctrl_priv *priv = dev_get_priv(dev);
47
48         if (!fdt_node_check_compatible(blob, node, "marvell,ap806-pinctrl")) {
49                 if ((pin == AP806_EMMC_CLK_PIN_ID) &&
50                     (func == AP806_EMMC_CLK_FUNC)) {
51                         clrbits_le32(priv->base_reg + AP_EMMC_PHY_CTRL_REG,
52                                      EMMC_PHY_CTRL_SDPHY_EN);
53                 }
54         } else if (!fdt_node_check_compatible(blob, node,
55                                         "marvell,armada-8k-cpm-pinctrl") ||
56                    !fdt_node_check_compatible(blob, node,
57                                         "marvell,armada-7k-pinctrl")) {
58                 if ((pin == CP110_EMMC_CLK_PIN_ID) &&
59                     (func == CP110_EMMC_CLK_FUNC)) {
60                         clrbits_le32(priv->base_reg + CP_EMMC_PHY_CTRL_REG,
61                                      EMMC_PHY_CTRL_SDPHY_EN);
62                 }
63         }
64 }
65
66 /*
67  * mvebu_pinctrl_set_state: configure pin functions.
68  * @dev: the pinctrl device to be configured.
69  * @config: the state to be configured.
70  * @return: 0 in success
71  */
72 int mvebu_pinctrl_set_state(struct udevice *dev, struct udevice *config)
73 {
74         const void *blob = gd->fdt_blob;
75         int node = dev_of_offset(config);
76         struct mvebu_pinctrl_priv *priv;
77         u32 pin_arr[MVEBU_MAX_PINS_PER_BANK];
78         u32 function;
79         int i, pin_count;
80
81         priv = dev_get_priv(dev);
82
83         pin_count = fdtdec_get_int_array_count(blob, node,
84                                                "marvell,pins",
85                                                pin_arr,
86                                                MVEBU_MAX_PINS_PER_BANK);
87         if (pin_count <= 0) {
88                 debug("Failed reading pins array for pinconfig %s (%d)\n",
89                       config->name, pin_count);
90                 return -EINVAL;
91         }
92
93         function = fdtdec_get_int(blob, node, "marvell,function", 0xff);
94
95         /*
96          * Check if setup of PHY mux is needed for this pins group.
97          * Only the first pin id in array is tested, all the rest use the same
98          * pin function.
99          */
100         mvebu_pinctl_emmc_set_mux(dev, pin_arr[0], function);
101
102         for (i = 0; i < pin_count; i++) {
103                 int reg_offset;
104                 int field_offset;
105                 int pin = pin_arr[i];
106
107                 if (function > priv->max_func) {
108                         debug("Illegal function %d for pinconfig %s\n",
109                               function, config->name);
110                         return -EINVAL;
111                 }
112
113                 /* Calculate register address and bit in register */
114                 reg_offset   = priv->reg_direction * 4 *
115                                         (pin >> (PIN_REG_SHIFT));
116                 field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
117
118                 clrsetbits_le32(priv->base_reg + reg_offset,
119                                 PIN_FUNC_MASK << field_offset,
120                                 (function & PIN_FUNC_MASK) << field_offset);
121         }
122
123         return 0;
124 }
125
126 /*
127  * mvebu_pinctrl_set_state_all: configure the entire bank pin functions.
128  * @dev: the pinctrl device to be configured.
129  * @config: the state to be configured.
130  * @return: 0 in success
131  */
132 static int mvebu_pinctrl_set_state_all(struct udevice *dev,
133                                        struct udevice *config)
134 {
135         const void *blob = gd->fdt_blob;
136         int node = dev_of_offset(config);
137         struct mvebu_pinctrl_priv *priv;
138         u32 func_arr[MVEBU_MAX_PINS_PER_BANK];
139         int pin, err;
140
141         priv = dev_get_priv(dev);
142
143         err = fdtdec_get_int_array(blob, node, "pin-func",
144                                    func_arr, priv->pin_cnt);
145         if (err) {
146                 debug("Failed reading pin functions for bank %s\n",
147                       priv->bank_name);
148                 return -EINVAL;
149         }
150
151         /* Check if setup of PHY mux is needed for this pins group. */
152         if (priv->pin_cnt < CP110_EMMC_CLK_PIN_ID)
153                 mvebu_pinctl_emmc_set_mux(dev, AP806_EMMC_CLK_PIN_ID,
154                                           func_arr[AP806_EMMC_CLK_PIN_ID]);
155         else
156                 mvebu_pinctl_emmc_set_mux(dev, CP110_EMMC_CLK_PIN_ID,
157                                           func_arr[CP110_EMMC_CLK_PIN_ID]);
158
159         for (pin = 0; pin < priv->pin_cnt; pin++) {
160                 int reg_offset;
161                 int field_offset;
162                 u32 func = func_arr[pin];
163
164                 /* Bypass pins with function 0xFF */
165                 if (func == 0xff) {
166                         debug("Warning: pin %d value is not modified ", pin);
167                         debug("(kept as default)\n");
168                         continue;
169                 } else if (func > priv->max_func) {
170                         debug("Illegal function %d for pin %d\n", func, pin);
171                         return -EINVAL;
172                 }
173
174                 /* Calculate register address and bit in register */
175                 reg_offset   = priv->reg_direction * 4 *
176                                         (pin >> (PIN_REG_SHIFT));
177                 field_offset = (BITS_PER_PIN) * (pin & PIN_FIELD_MASK);
178
179                 clrsetbits_le32(priv->base_reg + reg_offset,
180                                 PIN_FUNC_MASK << field_offset,
181                                 (func & PIN_FUNC_MASK) << field_offset);
182         }
183
184         return 0;
185 }
186
187 int mvebu_pinctl_probe(struct udevice *dev)
188 {
189         const void *blob = gd->fdt_blob;
190         int node = dev_of_offset(dev);
191         struct mvebu_pinctrl_priv *priv;
192
193         priv = dev_get_priv(dev);
194         if (!priv) {
195                 debug("%s: Failed to get private\n", __func__);
196                 return -EINVAL;
197         }
198
199         priv->base_reg = dev_read_addr_ptr(dev);
200         if (!priv->base_reg) {
201                 debug("%s: Failed to get base address\n", __func__);
202                 return -EINVAL;
203         }
204
205         priv->pin_cnt   = fdtdec_get_int(blob, node, "pin-count",
206                                         MVEBU_MAX_PINS_PER_BANK);
207         priv->max_func  = fdtdec_get_int(blob, node, "max-func",
208                                          MVEBU_MAX_FUNC);
209         priv->bank_name = fdt_getprop(blob, node, "bank-name", NULL);
210
211         priv->reg_direction = 1;
212         if (fdtdec_get_bool(blob, node, "reverse-reg"))
213                 priv->reg_direction = -1;
214
215         return mvebu_pinctrl_set_state_all(dev, dev);
216 }
217
218 static struct pinctrl_ops mvebu_pinctrl_ops = {
219         .set_state      = mvebu_pinctrl_set_state
220 };
221
222 static const struct udevice_id mvebu_pinctrl_ids[] = {
223         { .compatible = "marvell,mvebu-pinctrl" },
224         { .compatible = "marvell,ap806-pinctrl" },
225         { .compatible = "marvell,armada-7k-pinctrl" },
226         { .compatible = "marvell,armada-8k-cpm-pinctrl" },
227         { .compatible = "marvell,armada-8k-cps-pinctrl" },
228         { }
229 };
230
231 U_BOOT_DRIVER(pinctrl_mvebu) = {
232         .name           = "mvebu_pinctrl",
233         .id             = UCLASS_PINCTRL,
234         .of_match       = mvebu_pinctrl_ids,
235         .priv_auto      = sizeof(struct mvebu_pinctrl_priv),
236         .ops            = &mvebu_pinctrl_ops,
237         .probe          = mvebu_pinctl_probe
238 };