stm32mp1: add syscfg initialization
[platform/kernel/u-boot.git] / board / st / stm32mp1 / stm32mp1.c
1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4  */
5 #include <config.h>
6 #include <clk.h>
7 #include <common.h>
8 #include <dm.h>
9 #include <generic-phy.h>
10 #include <led.h>
11 #include <misc.h>
12 #include <phy.h>
13 #include <reset.h>
14 #include <syscon.h>
15 #include <usb.h>
16 #include <asm/io.h>
17 #include <asm/gpio.h>
18 #include <asm/arch/stm32.h>
19 #include <power/regulator.h>
20 #include <usb/dwc2_udc.h>
21
22 /* SYSCFG registers */
23 #define SYSCFG_BOOTR            0x00
24 #define SYSCFG_PMCSETR          0x04
25 #define SYSCFG_IOCTRLSETR       0x18
26 #define SYSCFG_ICNR             0x1C
27 #define SYSCFG_CMPCR            0x20
28 #define SYSCFG_CMPENSETR        0x24
29 #define SYSCFG_PMCCLRR          0x44
30
31 #define SYSCFG_BOOTR_BOOT_MASK          GENMASK(2, 0)
32 #define SYSCFG_BOOTR_BOOTPD_SHIFT       4
33
34 #define SYSCFG_IOCTRLSETR_HSLVEN_TRACE          BIT(0)
35 #define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI        BIT(1)
36 #define SYSCFG_IOCTRLSETR_HSLVEN_ETH            BIT(2)
37 #define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC          BIT(3)
38 #define SYSCFG_IOCTRLSETR_HSLVEN_SPI            BIT(4)
39
40 #define SYSCFG_CMPCR_SW_CTRL            BIT(1)
41 #define SYSCFG_CMPCR_READY              BIT(8)
42
43 #define SYSCFG_CMPENSETR_MPU_EN         BIT(0)
44
45 #define SYSCFG_PMCSETR_ETH_CLK_SEL      BIT(16)
46 #define SYSCFG_PMCSETR_ETH_REF_CLK_SEL  BIT(17)
47
48 #define SYSCFG_PMCSETR_ETH_SELMII       BIT(20)
49
50 #define SYSCFG_PMCSETR_ETH_SEL_MASK     GENMASK(23, 21)
51 #define SYSCFG_PMCSETR_ETH_SEL_GMII_MII (0 << 21)
52 #define SYSCFG_PMCSETR_ETH_SEL_RGMII    (1 << 21)
53 #define SYSCFG_PMCSETR_ETH_SEL_RMII     (4 << 21)
54
55 /*
56  * Get a global data pointer
57  */
58 DECLARE_GLOBAL_DATA_PTR;
59
60 #define STM32MP_GUSBCFG 0x40002407
61
62 #define STM32MP_GGPIO 0x38
63 #define STM32MP_GGPIO_VBUS_SENSING BIT(21)
64
65 int checkboard(void)
66 {
67         int ret;
68         char *mode;
69         u32 otp;
70         struct udevice *dev;
71         const char *fdt_compat;
72         int fdt_compat_len;
73
74         if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
75                 mode = "trusted";
76         else
77                 mode = "basic";
78
79         printf("Board: stm32mp1 in %s mode", mode);
80         fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
81                                  &fdt_compat_len);
82         if (fdt_compat && fdt_compat_len)
83                 printf(" (%s)", fdt_compat);
84         puts("\n");
85
86         ret = uclass_get_device_by_driver(UCLASS_MISC,
87                                           DM_GET_DRIVER(stm32mp_bsec),
88                                           &dev);
89
90         if (!ret)
91                 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
92                                 &otp, sizeof(otp));
93         if (!ret && otp) {
94                 printf("Board: MB%04x Var%d Rev.%c-%02d\n",
95                        otp >> 16,
96                        (otp >> 12) & 0xF,
97                        ((otp >> 8) & 0xF) - 1 + 'A',
98                        otp & 0xF);
99         }
100
101         return 0;
102 }
103
104 static void board_key_check(void)
105 {
106 #if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
107         ofnode node;
108         struct gpio_desc gpio;
109         enum forced_boot_mode boot_mode = BOOT_NORMAL;
110
111         node = ofnode_path("/config");
112         if (!ofnode_valid(node)) {
113                 debug("%s: no /config node?\n", __func__);
114                 return;
115         }
116 #ifdef CONFIG_FASTBOOT
117         if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
118                                        &gpio, GPIOD_IS_IN)) {
119                 debug("%s: could not find a /config/st,fastboot-gpios\n",
120                       __func__);
121         } else {
122                 if (dm_gpio_get_value(&gpio)) {
123                         puts("Fastboot key pressed, ");
124                         boot_mode = BOOT_FASTBOOT;
125                 }
126
127                 dm_gpio_free(NULL, &gpio);
128         }
129 #endif
130 #ifdef CONFIG_CMD_STM32PROG
131         if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
132                                        &gpio, GPIOD_IS_IN)) {
133                 debug("%s: could not find a /config/st,stm32prog-gpios\n",
134                       __func__);
135         } else {
136                 if (dm_gpio_get_value(&gpio)) {
137                         puts("STM32Programmer key pressed, ");
138                         boot_mode = BOOT_STM32PROG;
139                 }
140                 dm_gpio_free(NULL, &gpio);
141         }
142 #endif
143
144         if (boot_mode != BOOT_NORMAL) {
145                 puts("entering download mode...\n");
146                 clrsetbits_le32(TAMP_BOOT_CONTEXT,
147                                 TAMP_BOOT_FORCED_MASK,
148                                 boot_mode);
149         }
150 #endif
151 }
152
153 static struct dwc2_plat_otg_data stm32mp_otg_data = {
154         .usb_gusbcfg = STM32MP_GUSBCFG,
155 };
156
157 static struct reset_ctl usbotg_reset;
158
159 int board_usb_init(int index, enum usb_init_type init)
160 {
161         struct fdtdec_phandle_args args;
162         struct udevice *dev;
163         const void *blob = gd->fdt_blob;
164         struct clk clk;
165         struct phy phy;
166         int node;
167         int phy_provider;
168         int ret;
169
170         /* find the usb otg node */
171         node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2");
172         if (node < 0) {
173                 debug("Not found usb_otg device\n");
174                 return -ENODEV;
175         }
176
177         if (!fdtdec_get_is_enabled(blob, node)) {
178                 debug("stm32 usbotg is disabled in the device tree\n");
179                 return -ENODEV;
180         }
181
182         /* Enable clock */
183         ret = fdtdec_parse_phandle_with_args(blob, node, "clocks",
184                                              "#clock-cells", 0, 0, &args);
185         if (ret) {
186                 debug("usbotg has no clocks defined in the device tree\n");
187                 return ret;
188         }
189
190         ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev);
191         if (ret)
192                 return ret;
193
194         if (args.args_count != 1) {
195                 debug("Can't find clock ID in the device tree\n");
196                 return -ENODATA;
197         }
198
199         clk.dev = dev;
200         clk.id = args.args[0];
201
202         ret = clk_enable(&clk);
203         if (ret) {
204                 debug("Failed to enable usbotg clock\n");
205                 return ret;
206         }
207
208         /* Reset */
209         ret = fdtdec_parse_phandle_with_args(blob, node, "resets",
210                                              "#reset-cells", 0, 0, &args);
211         if (ret) {
212                 debug("usbotg has no resets defined in the device tree\n");
213                 goto clk_err;
214         }
215
216         ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev);
217         if (ret || args.args_count != 1)
218                 goto clk_err;
219
220         usbotg_reset.dev = dev;
221         usbotg_reset.id = args.args[0];
222
223         reset_assert(&usbotg_reset);
224         udelay(2);
225         reset_deassert(&usbotg_reset);
226
227         /* Get USB PHY */
228         ret = fdtdec_parse_phandle_with_args(blob, node, "phys",
229                                              "#phy-cells", 0, 0, &args);
230         if (!ret) {
231                 phy_provider = fdt_parent_offset(blob, args.node);
232                 ret = uclass_get_device_by_of_offset(UCLASS_PHY,
233                                                      phy_provider, &dev);
234                 if (ret)
235                         goto clk_err;
236
237                 phy.dev = dev;
238                 phy.id = fdtdec_get_uint(blob, args.node, "reg", -1);
239
240                 ret = generic_phy_power_on(&phy);
241                 if (ret) {
242                         debug("unable to power on the phy\n");
243                         goto clk_err;
244                 }
245
246                 ret = generic_phy_init(&phy);
247                 if (ret) {
248                         debug("failed to init usb phy\n");
249                         goto phy_power_err;
250                 }
251         }
252
253         /* Parse and store data needed for gadget */
254         stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
255         if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) {
256                 debug("usbotg: can't get base address\n");
257                 ret = -ENODATA;
258                 goto phy_init_err;
259         }
260
261         stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node,
262                                                      "g-rx-fifo-size", 0);
263         stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node,
264                                                         "g-np-tx-fifo-size", 0);
265         stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node,
266                                                      "g-tx-fifo-size", 0);
267         /* Enable voltage level detector */
268         if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply",
269                                              NULL, 0, 0, &args))) {
270                 if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR,
271                                                     args.node, &dev)) {
272                         ret = regulator_set_enable(dev, true);
273                         if (ret) {
274                                 debug("Failed to enable usb33d\n");
275                                 goto phy_init_err;
276                         }
277                 }
278         }
279                 /* Enable vbus sensing */
280         setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO,
281                      STM32MP_GGPIO_VBUS_SENSING);
282
283         return dwc2_udc_probe(&stm32mp_otg_data);
284
285 phy_init_err:
286         generic_phy_exit(&phy);
287
288 phy_power_err:
289         generic_phy_power_off(&phy);
290
291 clk_err:
292         clk_disable(&clk);
293
294         return ret;
295 }
296
297 int board_usb_cleanup(int index, enum usb_init_type init)
298 {
299         /* Reset usbotg */
300         reset_assert(&usbotg_reset);
301         udelay(2);
302         reset_deassert(&usbotg_reset);
303
304         return 0;
305 }
306
307 static void sysconf_init(void)
308 {
309 #ifndef CONFIG_STM32MP1_TRUSTED
310         u8 *syscfg;
311 #ifdef CONFIG_DM_REGULATOR
312         struct udevice *pwr_dev;
313         struct udevice *pwr_reg;
314         struct udevice *dev;
315         int ret;
316         u32 otp = 0;
317 #endif
318         u32 bootr;
319
320         syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
321
322         /* interconnect update : select master using the port 1 */
323         /* LTDC = AXI_M9 */
324         /* GPU  = AXI_M8 */
325         /* today information is hardcoded in U-Boot */
326         writel(BIT(9), syscfg + SYSCFG_ICNR);
327
328         /* disable Pull-Down for boot pin connected to VDD */
329         bootr = readl(syscfg + SYSCFG_BOOTR);
330         bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
331         bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
332         writel(bootr, syscfg + SYSCFG_BOOTR);
333
334 #ifdef CONFIG_DM_REGULATOR
335         /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
336          * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
337          * The customer will have to disable this for low frequencies
338          * or if AFMUX is selected but the function not used, typically for
339          * TRACE. Otherwise, impact on power consumption.
340          *
341          * WARNING:
342          *   enabling High Speed mode while VDD>2.7V
343          *   with the OTP product_below_2v5 (OTP 18, BIT 13)
344          *   erroneously set to 1 can damage the IC!
345          *   => U-Boot set the register only if VDD < 2.7V (in DT)
346          *      but this value need to be consistent with board design
347          */
348         ret = syscon_get_by_driver_data(STM32MP_SYSCON_PWR, &pwr_dev);
349         if (!ret) {
350                 ret = uclass_get_device_by_driver(UCLASS_MISC,
351                                                   DM_GET_DRIVER(stm32mp_bsec),
352                                                   &dev);
353                 if (ret) {
354                         pr_err("Can't find stm32mp_bsec driver\n");
355                         return;
356                 }
357
358                 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
359                 if (!ret)
360                         otp = otp & BIT(13);
361
362                 /* get VDD = pwr-supply */
363                 ret = device_get_supply_regulator(pwr_dev, "pwr-supply",
364                                                   &pwr_reg);
365
366                 /* check if VDD is Low Voltage */
367                 if (!ret) {
368                         if (regulator_get_value(pwr_reg) < 2700000) {
369                                 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
370                                        SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
371                                        SYSCFG_IOCTRLSETR_HSLVEN_ETH |
372                                        SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
373                                        SYSCFG_IOCTRLSETR_HSLVEN_SPI,
374                                        syscfg + SYSCFG_IOCTRLSETR);
375
376                                 if (!otp)
377                                         pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
378                         } else {
379                                 if (otp)
380                                         pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
381                         }
382                 } else {
383                         debug("VDD unknown");
384                 }
385         }
386 #endif
387
388         /* activate automatic I/O compensation
389          * warning: need to ensure CSI enabled and ready in clock driver
390          */
391         writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
392
393         while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
394                 ;
395         clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
396 #endif
397 }
398
399 /* board dependent setup after realloc */
400 int board_init(void)
401 {
402         /* address of boot parameters */
403         gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
404
405         board_key_check();
406
407         sysconf_init();
408
409         if (IS_ENABLED(CONFIG_LED))
410                 led_default_state();
411
412         return 0;
413 }
414
415 int board_late_init(void)
416 {
417 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
418         const void *fdt_compat;
419         int fdt_compat_len;
420
421         fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
422                                  &fdt_compat_len);
423         if (fdt_compat && fdt_compat_len) {
424                 if (strncmp(fdt_compat, "st,", 3) != 0)
425                         env_set("board_name", fdt_compat);
426                 else
427                         env_set("board_name", fdt_compat + 3);
428         }
429 #endif
430
431         return 0;
432 }