stm32mp1: display board information
[oweals/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 <usb.h>
15 #include <asm/arch/stm32.h>
16 #include <asm/io.h>
17 #include <power/regulator.h>
18 #include <usb/dwc2_udc.h>
19
20 /*
21  * Get a global data pointer
22  */
23 DECLARE_GLOBAL_DATA_PTR;
24
25 #define STM32MP_GUSBCFG 0x40002407
26
27 #define STM32MP_GGPIO 0x38
28 #define STM32MP_GGPIO_VBUS_SENSING BIT(21)
29
30 int checkboard(void)
31 {
32         int ret;
33         char *mode;
34         u32 otp;
35         struct udevice *dev;
36         const char *fdt_compat;
37         int fdt_compat_len;
38
39         if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
40                 mode = "trusted";
41         else
42                 mode = "basic";
43
44         printf("Board: stm32mp1 in %s mode", mode);
45         fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
46                                  &fdt_compat_len);
47         if (fdt_compat && fdt_compat_len)
48                 printf(" (%s)", fdt_compat);
49         puts("\n");
50
51         ret = uclass_get_device_by_driver(UCLASS_MISC,
52                                           DM_GET_DRIVER(stm32mp_bsec),
53                                           &dev);
54
55         if (!ret)
56                 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
57                                 &otp, sizeof(otp));
58         if (!ret && otp) {
59                 printf("Board: MB%04x Var%d Rev.%c-%02d\n",
60                        otp >> 16,
61                        (otp >> 12) & 0xF,
62                        ((otp >> 8) & 0xF) - 1 + 'A',
63                        otp & 0xF);
64         }
65
66         return 0;
67 }
68
69 static struct dwc2_plat_otg_data stm32mp_otg_data = {
70         .usb_gusbcfg = STM32MP_GUSBCFG,
71 };
72
73 static struct reset_ctl usbotg_reset;
74
75 int board_usb_init(int index, enum usb_init_type init)
76 {
77         struct fdtdec_phandle_args args;
78         struct udevice *dev;
79         const void *blob = gd->fdt_blob;
80         struct clk clk;
81         struct phy phy;
82         int node;
83         int phy_provider;
84         int ret;
85
86         /* find the usb otg node */
87         node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2");
88         if (node < 0) {
89                 debug("Not found usb_otg device\n");
90                 return -ENODEV;
91         }
92
93         if (!fdtdec_get_is_enabled(blob, node)) {
94                 debug("stm32 usbotg is disabled in the device tree\n");
95                 return -ENODEV;
96         }
97
98         /* Enable clock */
99         ret = fdtdec_parse_phandle_with_args(blob, node, "clocks",
100                                              "#clock-cells", 0, 0, &args);
101         if (ret) {
102                 debug("usbotg has no clocks defined in the device tree\n");
103                 return ret;
104         }
105
106         ret = uclass_get_device_by_of_offset(UCLASS_CLK, args.node, &dev);
107         if (ret)
108                 return ret;
109
110         if (args.args_count != 1) {
111                 debug("Can't find clock ID in the device tree\n");
112                 return -ENODATA;
113         }
114
115         clk.dev = dev;
116         clk.id = args.args[0];
117
118         ret = clk_enable(&clk);
119         if (ret) {
120                 debug("Failed to enable usbotg clock\n");
121                 return ret;
122         }
123
124         /* Reset */
125         ret = fdtdec_parse_phandle_with_args(blob, node, "resets",
126                                              "#reset-cells", 0, 0, &args);
127         if (ret) {
128                 debug("usbotg has no resets defined in the device tree\n");
129                 goto clk_err;
130         }
131
132         ret = uclass_get_device_by_of_offset(UCLASS_RESET, args.node, &dev);
133         if (ret || args.args_count != 1)
134                 goto clk_err;
135
136         usbotg_reset.dev = dev;
137         usbotg_reset.id = args.args[0];
138
139         reset_assert(&usbotg_reset);
140         udelay(2);
141         reset_deassert(&usbotg_reset);
142
143         /* Get USB PHY */
144         ret = fdtdec_parse_phandle_with_args(blob, node, "phys",
145                                              "#phy-cells", 0, 0, &args);
146         if (!ret) {
147                 phy_provider = fdt_parent_offset(blob, args.node);
148                 ret = uclass_get_device_by_of_offset(UCLASS_PHY,
149                                                      phy_provider, &dev);
150                 if (ret)
151                         goto clk_err;
152
153                 phy.dev = dev;
154                 phy.id = fdtdec_get_uint(blob, args.node, "reg", -1);
155
156                 ret = generic_phy_power_on(&phy);
157                 if (ret) {
158                         debug("unable to power on the phy\n");
159                         goto clk_err;
160                 }
161
162                 ret = generic_phy_init(&phy);
163                 if (ret) {
164                         debug("failed to init usb phy\n");
165                         goto phy_power_err;
166                 }
167         }
168
169         /* Parse and store data needed for gadget */
170         stm32mp_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
171         if (stm32mp_otg_data.regs_otg == FDT_ADDR_T_NONE) {
172                 debug("usbotg: can't get base address\n");
173                 ret = -ENODATA;
174                 goto phy_init_err;
175         }
176
177         stm32mp_otg_data.rx_fifo_sz = fdtdec_get_int(blob, node,
178                                                      "g-rx-fifo-size", 0);
179         stm32mp_otg_data.np_tx_fifo_sz = fdtdec_get_int(blob, node,
180                                                         "g-np-tx-fifo-size", 0);
181         stm32mp_otg_data.tx_fifo_sz = fdtdec_get_int(blob, node,
182                                                      "g-tx-fifo-size", 0);
183         /* Enable voltage level detector */
184         if (!(fdtdec_parse_phandle_with_args(blob, node, "usb33d-supply",
185                                              NULL, 0, 0, &args))) {
186                 if (!uclass_get_device_by_of_offset(UCLASS_REGULATOR,
187                                                     args.node, &dev)) {
188                         ret = regulator_set_enable(dev, true);
189                         if (ret) {
190                                 debug("Failed to enable usb33d\n");
191                                 goto phy_init_err;
192                         }
193                 }
194         }
195                 /* Enable vbus sensing */
196         setbits_le32(stm32mp_otg_data.regs_otg + STM32MP_GGPIO,
197                      STM32MP_GGPIO_VBUS_SENSING);
198
199         return dwc2_udc_probe(&stm32mp_otg_data);
200
201 phy_init_err:
202         generic_phy_exit(&phy);
203
204 phy_power_err:
205         generic_phy_power_off(&phy);
206
207 clk_err:
208         clk_disable(&clk);
209
210         return ret;
211 }
212
213 int board_usb_cleanup(int index, enum usb_init_type init)
214 {
215         /* Reset usbotg */
216         reset_assert(&usbotg_reset);
217         udelay(2);
218         reset_deassert(&usbotg_reset);
219
220         return 0;
221 }
222
223 int board_late_init(void)
224 {
225         return 0;
226 }
227
228 /* board dependent setup after realloc */
229 int board_init(void)
230 {
231         /* address of boot parameters */
232         gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
233
234         if (IS_ENABLED(CONFIG_LED))
235                 led_default_state();
236
237         return 0;
238 }