blob: 4dd0098c6e8ab1ce6bd035ffbf79db95b82c8505 [file] [log] [blame]
Tom Rini4549e782018-05-06 18:27:01 -04001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
Patrick Delaunayf8598d92018-03-12 10:46:18 +01002/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
Patrick Delaunayf8598d92018-03-12 10:46:18 +01004 */
Patrice Chotard395f1292019-02-12 16:50:40 +01005#include <common.h>
6#include <adc.h>
Patrick Delaunay8e194772019-06-21 15:26:40 +02007#include <bootm.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +02008#include <clk.h>
Patrick Delaunayd1a597f2019-07-30 19:16:44 +02009#include <config.h>
Patrick Delaunaye968c392020-01-28 10:44:12 +010010#include <dfu.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020011#include <dm.h>
Simon Glass3a7d5572019-08-01 09:46:42 -060012#include <env.h>
Simon Glassf3998fd2019-08-02 09:44:25 -060013#include <env_internal.h>
Patrick Delaunayc31000c2019-03-29 15:42:23 +010014#include <g_dnl.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020015#include <generic-phy.h>
Simon Glassdb41d652019-12-28 10:45:07 -070016#include <hang.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010017#include <i2c.h>
Simon Glass52559322019-11-14 12:57:46 -070018#include <init.h>
Patrick Delaunayd461f102019-02-12 11:44:41 +010019#include <led.h>
Simon Glass336d4612020-02-03 07:36:16 -070020#include <malloc.h>
Patrick Delaunayf6031d62019-10-14 09:28:09 +020021#include <memalign.h>
Patrick Delaunayd461f102019-02-12 11:44:41 +010022#include <misc.h>
Patrick Delaunaye81f8d12019-07-02 13:26:07 +020023#include <mtd.h>
24#include <mtd_node.h>
Patrick Delaunay53e3d522019-08-01 11:29:03 +020025#include <netdev.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020026#include <phy.h>
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +020027#include <remoteproc.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020028#include <reset.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010029#include <syscon.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010030#include <usb.h>
Patrick Delaunaydd281082019-07-30 19:16:39 +020031#include <watchdog.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020032#include <asm/io.h>
Patrick Delaunay842ebb52019-02-27 17:01:18 +010033#include <asm/gpio.h>
Patrick Delaunay45459742019-02-27 17:01:24 +010034#include <asm/arch/stm32.h>
Patrice Chotard7f90cd62019-05-02 18:36:01 +020035#include <asm/arch/sys_proto.h>
Patrick Delaunaye81f8d12019-07-02 13:26:07 +020036#include <jffs2/load_kernel.h>
Simon Glass61b29b82020-02-03 07:36:15 -070037#include <linux/err.h>
Patrice Chotard4c834b92018-08-10 17:12:14 +020038#include <power/regulator.h>
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +010039#include <usb/dwc2_udc.h>
Patrick Delaunayf8598d92018-03-12 10:46:18 +010040
Patrick Delaunay45459742019-02-27 17:01:24 +010041/* SYSCFG registers */
42#define SYSCFG_BOOTR 0x00
43#define SYSCFG_PMCSETR 0x04
44#define SYSCFG_IOCTRLSETR 0x18
45#define SYSCFG_ICNR 0x1C
46#define SYSCFG_CMPCR 0x20
47#define SYSCFG_CMPENSETR 0x24
48#define SYSCFG_PMCCLRR 0x44
49
50#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0)
51#define SYSCFG_BOOTR_BOOTPD_SHIFT 4
52
53#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0)
54#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1)
55#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2)
56#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3)
57#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4)
58
59#define SYSCFG_CMPCR_SW_CTRL BIT(1)
60#define SYSCFG_CMPCR_READY BIT(8)
61
62#define SYSCFG_CMPENSETR_MPU_EN BIT(0)
63
64#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
65#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
66
67#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
68
69#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
Christophe Roullieredacf262019-05-17 15:08:43 +020070#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0
71#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21)
72#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23)
Patrick Delaunay45459742019-02-27 17:01:24 +010073
Patrick Delaunayf8598d92018-03-12 10:46:18 +010074/*
75 * Get a global data pointer
76 */
77DECLARE_GLOBAL_DATA_PTR;
78
Patrice Chotard28c064e2019-04-30 18:09:38 +020079#define USB_LOW_THRESHOLD_UV 200000
Patrice Chotard395f1292019-02-12 16:50:40 +010080#define USB_WARNING_LOW_THRESHOLD_UV 660000
81#define USB_START_LOW_THRESHOLD_UV 1230000
Patrice Chotard28c064e2019-04-30 18:09:38 +020082#define USB_START_HIGH_THRESHOLD_UV 2150000
Patrice Chotard395f1292019-02-12 16:50:40 +010083
Patrick Delaunayd461f102019-02-12 11:44:41 +010084int checkboard(void)
85{
86 int ret;
87 char *mode;
88 u32 otp;
89 struct udevice *dev;
90 const char *fdt_compat;
91 int fdt_compat_len;
92
Patrick Delaunay152c84b2019-07-02 13:26:06 +020093 if (IS_ENABLED(CONFIG_STM32MP1_OPTEE))
94 mode = "trusted with OP-TEE";
95 else if (IS_ENABLED(CONFIG_STM32MP1_TRUSTED))
Patrick Delaunayd461f102019-02-12 11:44:41 +010096 mode = "trusted";
97 else
98 mode = "basic";
99
100 printf("Board: stm32mp1 in %s mode", mode);
101 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
102 &fdt_compat_len);
103 if (fdt_compat && fdt_compat_len)
104 printf(" (%s)", fdt_compat);
105 puts("\n");
106
Patrick Delaunay888dc682020-03-24 09:05:00 +0100107 /* display the STMicroelectronics board identification */
Patrick Delaunayd461f102019-02-12 11:44:41 +0100108 ret = uclass_get_device_by_driver(UCLASS_MISC,
109 DM_GET_DRIVER(stm32mp_bsec),
110 &dev);
111
112 if (!ret)
113 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
114 &otp, sizeof(otp));
Patrick Delaunay19efa392019-08-02 13:08:05 +0200115 if (ret > 0 && otp) {
Patrick Delaunay888dc682020-03-24 09:05:00 +0100116 printf("Board: MB%04x Var%d.%d Rev.%c-%02d\n",
Patrick Delaunayd461f102019-02-12 11:44:41 +0100117 otp >> 16,
118 (otp >> 12) & 0xF,
Patrick Delaunay888dc682020-03-24 09:05:00 +0100119 (otp >> 4) & 0xF,
Patrick Delaunayd461f102019-02-12 11:44:41 +0100120 ((otp >> 8) & 0xF) - 1 + 'A',
121 otp & 0xF);
122 }
123
124 return 0;
125}
126
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100127static void board_key_check(void)
128{
129#if defined(CONFIG_FASTBOOT) || defined(CONFIG_CMD_STM32PROG)
130 ofnode node;
131 struct gpio_desc gpio;
132 enum forced_boot_mode boot_mode = BOOT_NORMAL;
133
134 node = ofnode_path("/config");
135 if (!ofnode_valid(node)) {
136 debug("%s: no /config node?\n", __func__);
137 return;
138 }
139#ifdef CONFIG_FASTBOOT
140 if (gpio_request_by_name_nodev(node, "st,fastboot-gpios", 0,
141 &gpio, GPIOD_IS_IN)) {
142 debug("%s: could not find a /config/st,fastboot-gpios\n",
143 __func__);
144 } else {
145 if (dm_gpio_get_value(&gpio)) {
146 puts("Fastboot key pressed, ");
147 boot_mode = BOOT_FASTBOOT;
148 }
149
150 dm_gpio_free(NULL, &gpio);
151 }
152#endif
153#ifdef CONFIG_CMD_STM32PROG
154 if (gpio_request_by_name_nodev(node, "st,stm32prog-gpios", 0,
155 &gpio, GPIOD_IS_IN)) {
156 debug("%s: could not find a /config/st,stm32prog-gpios\n",
157 __func__);
158 } else {
159 if (dm_gpio_get_value(&gpio)) {
160 puts("STM32Programmer key pressed, ");
161 boot_mode = BOOT_STM32PROG;
162 }
163 dm_gpio_free(NULL, &gpio);
164 }
165#endif
166
167 if (boot_mode != BOOT_NORMAL) {
168 puts("entering download mode...\n");
169 clrsetbits_le32(TAMP_BOOT_CONTEXT,
170 TAMP_BOOT_FORCED_MASK,
171 boot_mode);
172 }
173#endif
174}
175
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100176#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
Patrice Chotard4c834b92018-08-10 17:12:14 +0200177
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100178/* STMicroelectronics STUSB1600 Type-C controller */
179#define STUSB1600_CC_CONNECTION_STATUS 0x0E
180
181/* STUSB1600_CC_CONNECTION_STATUS bitfields */
182#define STUSB1600_CC_ATTACH BIT(0)
183
184static int stusb1600_init(struct udevice **dev_stusb1600)
185{
186 ofnode node;
187 struct udevice *dev, *bus;
188 int ret;
189 u32 chip_addr;
190
191 *dev_stusb1600 = NULL;
192
193 /* if node stusb1600 is present, means DK1 or DK2 board */
194 node = ofnode_by_compatible(ofnode_null(), "st,stusb1600");
195 if (!ofnode_valid(node))
196 return -ENODEV;
197
198 ret = ofnode_read_u32(node, "reg", &chip_addr);
199 if (ret)
200 return -EINVAL;
201
202 ret = uclass_get_device_by_ofnode(UCLASS_I2C, ofnode_get_parent(node),
203 &bus);
204 if (ret) {
205 printf("bus for stusb1600 not found\n");
206 return -ENODEV;
207 }
208
209 ret = dm_i2c_probe(bus, chip_addr, 0, &dev);
210 if (!ret)
211 *dev_stusb1600 = dev;
212
213 return ret;
214}
215
216static int stusb1600_cable_connected(struct udevice *dev)
217{
218 u8 status;
219
220 if (dm_i2c_read(dev, STUSB1600_CC_CONNECTION_STATUS, &status, 1))
221 return 0;
222
223 return status & STUSB1600_CC_ATTACH;
224}
225
226#include <usb/dwc2_udc.h>
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100227int g_dnl_board_usb_cable_connected(void)
Patrice Chotard4c834b92018-08-10 17:12:14 +0200228{
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100229 struct udevice *stusb1600;
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100230 struct udevice *dwc2_udc_otg;
Patrice Chotard4c834b92018-08-10 17:12:14 +0200231 int ret;
232
Patrick Delaunay6fe7dd32019-03-29 15:42:24 +0100233 if (!stusb1600_init(&stusb1600))
234 return stusb1600_cable_connected(stusb1600);
235
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100236 ret = uclass_get_device_by_driver(UCLASS_USB_GADGET_GENERIC,
237 DM_GET_DRIVER(dwc2_udc_otg),
238 &dwc2_udc_otg);
239 if (!ret)
240 debug("dwc2_udc_otg init failed\n");
Patrice Chotard4c834b92018-08-10 17:12:14 +0200241
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100242 return dwc2_udc_B_session_valid(dwc2_udc_otg);
Patrice Chotard4c834b92018-08-10 17:12:14 +0200243}
Patrick Delaunayfb90fcf2019-09-13 15:24:17 +0200244
245#define STM32MP1_G_DNL_DFU_PRODUCT_NUM 0xdf11
246#define STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM 0x0afb
247
248int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
249{
250 if (!strcmp(name, "usb_dnl_dfu"))
251 put_unaligned(STM32MP1_G_DNL_DFU_PRODUCT_NUM, &dev->idProduct);
252 else if (!strcmp(name, "usb_dnl_fastboot"))
253 put_unaligned(STM32MP1_G_DNL_FASTBOOT_PRODUCT_NUM,
254 &dev->idProduct);
255 else
256 put_unaligned(CONFIG_USB_GADGET_PRODUCT_NUM, &dev->idProduct);
257
258 return 0;
259}
260
Patrick Delaunayc31000c2019-03-29 15:42:23 +0100261#endif /* CONFIG_USB_GADGET */
Patrice Chotard4c834b92018-08-10 17:12:14 +0200262
Patrick Delaunaydd281082019-07-30 19:16:39 +0200263#ifdef CONFIG_LED
Patrice Chotard395f1292019-02-12 16:50:40 +0100264static int get_led(struct udevice **dev, char *led_string)
265{
266 char *led_name;
267 int ret;
268
269 led_name = fdtdec_get_config_string(gd->fdt_blob, led_string);
270 if (!led_name) {
271 pr_debug("%s: could not find %s config string\n",
272 __func__, led_string);
273 return -ENOENT;
274 }
275 ret = led_get_by_label(led_name, dev);
276 if (ret) {
277 debug("%s: get=%d\n", __func__, ret);
278 return ret;
279 }
280
281 return 0;
282}
283
284static int setup_led(enum led_state_t cmd)
285{
286 struct udevice *dev;
287 int ret;
288
289 ret = get_led(&dev, "u-boot,boot-led");
290 if (ret)
291 return ret;
292
293 ret = led_set_state(dev, cmd);
294 return ret;
295}
Patrick Delaunaydd281082019-07-30 19:16:39 +0200296#endif
297
298static void __maybe_unused led_error_blink(u32 nb_blink)
299{
300#ifdef CONFIG_LED
301 int ret;
302 struct udevice *led;
303 u32 i;
304#endif
305
306 if (!nb_blink)
307 return;
308
309#ifdef CONFIG_LED
310 ret = get_led(&led, "u-boot,error-led");
311 if (!ret) {
312 /* make u-boot,error-led blinking */
313 /* if U32_MAX and 125ms interval, for 17.02 years */
314 for (i = 0; i < 2 * nb_blink; i++) {
315 led_set_state(led, LEDST_TOGGLE);
316 mdelay(125);
317 WATCHDOG_RESET();
318 }
319 }
320#endif
321
322 /* infinite: the boot process must be stopped */
323 if (nb_blink == U32_MAX)
324 hang();
325}
Patrice Chotard395f1292019-02-12 16:50:40 +0100326
Patrick Delaunay41542472019-07-30 19:16:43 +0200327#ifdef CONFIG_ADC
Patrice Chotard395f1292019-02-12 16:50:40 +0100328static int board_check_usb_power(void)
329{
330 struct ofnode_phandle_args adc_args;
331 struct udevice *adc;
Patrice Chotard395f1292019-02-12 16:50:40 +0100332 ofnode node;
333 unsigned int raw;
334 int max_uV = 0;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200335 int min_uV = USB_START_HIGH_THRESHOLD_UV;
Patrice Chotard395f1292019-02-12 16:50:40 +0100336 int ret, uV, adc_count;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200337 u32 nb_blink;
338 u8 i;
Patrice Chotard395f1292019-02-12 16:50:40 +0100339 node = ofnode_path("/config");
340 if (!ofnode_valid(node)) {
341 debug("%s: no /config node?\n", __func__);
342 return -ENOENT;
343 }
344
345 /*
346 * Retrieve the ADC channels devices and get measurement
347 * for each of them
348 */
349 adc_count = ofnode_count_phandle_with_args(node, "st,adc_usb_pd",
350 "#io-channel-cells");
351 if (adc_count < 0) {
352 if (adc_count == -ENOENT)
353 return 0;
354
355 pr_err("%s: can't find adc channel (%d)\n", __func__,
356 adc_count);
357
358 return adc_count;
359 }
360
361 for (i = 0; i < adc_count; i++) {
362 if (ofnode_parse_phandle_with_args(node, "st,adc_usb_pd",
363 "#io-channel-cells", 0, i,
364 &adc_args)) {
365 pr_debug("%s: can't find /config/st,adc_usb_pd\n",
366 __func__);
367 return 0;
368 }
369
370 ret = uclass_get_device_by_ofnode(UCLASS_ADC, adc_args.node,
371 &adc);
372
373 if (ret) {
374 pr_err("%s: Can't get adc device(%d)\n", __func__,
375 ret);
376 return ret;
377 }
378
379 ret = adc_channel_single_shot(adc->name, adc_args.args[0],
380 &raw);
381 if (ret) {
382 pr_err("%s: single shot failed for %s[%d]!\n",
383 __func__, adc->name, adc_args.args[0]);
384 return ret;
385 }
386 /* Convert to uV */
387 if (!adc_raw_to_uV(adc, raw, &uV)) {
388 if (uV > max_uV)
389 max_uV = uV;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200390 if (uV < min_uV)
391 min_uV = uV;
Patrice Chotard395f1292019-02-12 16:50:40 +0100392 pr_debug("%s: %s[%02d] = %u, %d uV\n", __func__,
393 adc->name, adc_args.args[0], raw, uV);
394 } else {
395 pr_err("%s: Can't get uV value for %s[%d]\n",
396 __func__, adc->name, adc_args.args[0]);
397 }
398 }
399
400 /*
401 * If highest value is inside 1.23 Volts and 2.10 Volts, that means
402 * board is plugged on an USB-C 3A power supply and boot process can
403 * continue.
404 */
405 if (max_uV > USB_START_LOW_THRESHOLD_UV &&
Patrice Chotard28c064e2019-04-30 18:09:38 +0200406 max_uV <= USB_START_HIGH_THRESHOLD_UV &&
407 min_uV <= USB_LOW_THRESHOLD_UV)
Patrice Chotard395f1292019-02-12 16:50:40 +0100408 return 0;
409
Patrice Chotard28c064e2019-04-30 18:09:38 +0200410 pr_err("****************************************************\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100411
Patrice Chotard28c064e2019-04-30 18:09:38 +0200412 /*
413 * If highest and lowest value are either both below
414 * USB_LOW_THRESHOLD_UV or both above USB_LOW_THRESHOLD_UV, that
415 * means USB TYPE-C is in unattached mode, this is an issue, make
416 * u-boot,error-led blinking and stop boot process.
417 */
418 if ((max_uV > USB_LOW_THRESHOLD_UV &&
419 min_uV > USB_LOW_THRESHOLD_UV) ||
420 (max_uV <= USB_LOW_THRESHOLD_UV &&
421 min_uV <= USB_LOW_THRESHOLD_UV)) {
422 pr_err("* ERROR USB TYPE-C connection in unattached mode *\n");
423 pr_err("* Check that USB TYPE-C cable is correctly plugged *\n");
424 /* with 125ms interval, led will blink for 17.02 years ....*/
425 nb_blink = U32_MAX;
426 }
427
428 if (max_uV > USB_LOW_THRESHOLD_UV &&
429 max_uV <= USB_WARNING_LOW_THRESHOLD_UV &&
430 min_uV <= USB_LOW_THRESHOLD_UV) {
431 pr_err("* WARNING 500mA power supply detected *\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100432 nb_blink = 2;
Patrice Chotard28c064e2019-04-30 18:09:38 +0200433 }
434
435 if (max_uV > USB_WARNING_LOW_THRESHOLD_UV &&
436 max_uV <= USB_START_LOW_THRESHOLD_UV &&
437 min_uV <= USB_LOW_THRESHOLD_UV) {
438 pr_err("* WARNING 1.5mA power supply detected *\n");
Patrice Chotard395f1292019-02-12 16:50:40 +0100439 nb_blink = 3;
440 }
441
Patrice Chotard28c064e2019-04-30 18:09:38 +0200442 /*
443 * If highest value is above 2.15 Volts that means that the USB TypeC
444 * supplies more than 3 Amp, this is not compliant with TypeC specification
445 */
446 if (max_uV > USB_START_HIGH_THRESHOLD_UV) {
447 pr_err("* USB TYPE-C charger not compliant with *\n");
448 pr_err("* specification *\n");
449 pr_err("****************************************************\n\n");
450 /* with 125ms interval, led will blink for 17.02 years ....*/
451 nb_blink = U32_MAX;
452 } else {
453 pr_err("* Current too low, use a 3A power supply! *\n");
454 pr_err("****************************************************\n\n");
455 }
Patrice Chotard395f1292019-02-12 16:50:40 +0100456
Patrick Delaunaydd281082019-07-30 19:16:39 +0200457 led_error_blink(nb_blink);
Patrice Chotard395f1292019-02-12 16:50:40 +0100458
459 return 0;
460}
Patrick Delaunay41542472019-07-30 19:16:43 +0200461#endif /* CONFIG_ADC */
Patrice Chotard395f1292019-02-12 16:50:40 +0100462
Patrick Delaunay45459742019-02-27 17:01:24 +0100463static void sysconf_init(void)
464{
465#ifndef CONFIG_STM32MP1_TRUSTED
466 u8 *syscfg;
467#ifdef CONFIG_DM_REGULATOR
468 struct udevice *pwr_dev;
469 struct udevice *pwr_reg;
470 struct udevice *dev;
471 int ret;
472 u32 otp = 0;
473#endif
474 u32 bootr;
475
476 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
477
478 /* interconnect update : select master using the port 1 */
479 /* LTDC = AXI_M9 */
480 /* GPU = AXI_M8 */
481 /* today information is hardcoded in U-Boot */
482 writel(BIT(9), syscfg + SYSCFG_ICNR);
483
484 /* disable Pull-Down for boot pin connected to VDD */
485 bootr = readl(syscfg + SYSCFG_BOOTR);
486 bootr &= ~(SYSCFG_BOOTR_BOOT_MASK << SYSCFG_BOOTR_BOOTPD_SHIFT);
487 bootr |= (bootr & SYSCFG_BOOTR_BOOT_MASK) << SYSCFG_BOOTR_BOOTPD_SHIFT;
488 writel(bootr, syscfg + SYSCFG_BOOTR);
489
490#ifdef CONFIG_DM_REGULATOR
491 /* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI
492 * and TRACE. Needed above ~50MHz and conditioned by AFMUX selection.
493 * The customer will have to disable this for low frequencies
494 * or if AFMUX is selected but the function not used, typically for
495 * TRACE. Otherwise, impact on power consumption.
496 *
497 * WARNING:
498 * enabling High Speed mode while VDD>2.7V
499 * with the OTP product_below_2v5 (OTP 18, BIT 13)
500 * erroneously set to 1 can damage the IC!
501 * => U-Boot set the register only if VDD < 2.7V (in DT)
502 * but this value need to be consistent with board design
503 */
Patrick Delaunay5e959ab2019-07-30 19:16:42 +0200504 ret = uclass_get_device_by_driver(UCLASS_PMIC,
505 DM_GET_DRIVER(stm32mp_pwr_pmic),
506 &pwr_dev);
Patrick Delaunay45459742019-02-27 17:01:24 +0100507 if (!ret) {
508 ret = uclass_get_device_by_driver(UCLASS_MISC,
509 DM_GET_DRIVER(stm32mp_bsec),
510 &dev);
511 if (ret) {
512 pr_err("Can't find stm32mp_bsec driver\n");
513 return;
514 }
515
516 ret = misc_read(dev, STM32_BSEC_SHADOW(18), &otp, 4);
Patrick Delaunayff6618e2019-08-02 13:08:06 +0200517 if (ret > 0)
Patrick Delaunay45459742019-02-27 17:01:24 +0100518 otp = otp & BIT(13);
519
Patrick Delaunay5e959ab2019-07-30 19:16:42 +0200520 /* get VDD = vdd-supply */
521 ret = device_get_supply_regulator(pwr_dev, "vdd-supply",
Patrick Delaunay45459742019-02-27 17:01:24 +0100522 &pwr_reg);
523
524 /* check if VDD is Low Voltage */
525 if (!ret) {
526 if (regulator_get_value(pwr_reg) < 2700000) {
527 writel(SYSCFG_IOCTRLSETR_HSLVEN_TRACE |
528 SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI |
529 SYSCFG_IOCTRLSETR_HSLVEN_ETH |
530 SYSCFG_IOCTRLSETR_HSLVEN_SDMMC |
531 SYSCFG_IOCTRLSETR_HSLVEN_SPI,
532 syscfg + SYSCFG_IOCTRLSETR);
533
534 if (!otp)
535 pr_err("product_below_2v5=0: HSLVEN protected by HW\n");
536 } else {
537 if (otp)
538 pr_err("product_below_2v5=1: HSLVEN update is destructive, no update as VDD>2.7V\n");
539 }
540 } else {
541 debug("VDD unknown");
542 }
543 }
544#endif
545
546 /* activate automatic I/O compensation
547 * warning: need to ensure CSI enabled and ready in clock driver
548 */
549 writel(SYSCFG_CMPENSETR_MPU_EN, syscfg + SYSCFG_CMPENSETR);
550
551 while (!(readl(syscfg + SYSCFG_CMPCR) & SYSCFG_CMPCR_READY))
552 ;
553 clrbits_le32(syscfg + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL);
554#endif
555}
556
Patrick Delaunayd573e462019-07-30 19:16:38 +0200557#ifdef CONFIG_DM_REGULATOR
558/* Fix to make I2C1 usable on DK2 for touchscreen usage in kernel */
559static int dk2_i2c1_fix(void)
560{
561 ofnode node;
562 struct gpio_desc hdmi, audio;
563 int ret = 0;
564
565 node = ofnode_path("/soc/i2c@40012000/hdmi-transmitter@39");
566 if (!ofnode_valid(node)) {
567 pr_debug("%s: no hdmi-transmitter@39 ?\n", __func__);
568 return -ENOENT;
569 }
570
571 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
572 &hdmi, GPIOD_IS_OUT)) {
573 pr_debug("%s: could not find reset-gpios\n",
574 __func__);
575 return -ENOENT;
576 }
577
578 node = ofnode_path("/soc/i2c@40012000/cs42l51@4a");
579 if (!ofnode_valid(node)) {
580 pr_debug("%s: no cs42l51@4a ?\n", __func__);
581 return -ENOENT;
582 }
583
584 if (gpio_request_by_name_nodev(node, "reset-gpios", 0,
585 &audio, GPIOD_IS_OUT)) {
586 pr_debug("%s: could not find reset-gpios\n",
587 __func__);
588 return -ENOENT;
589 }
590
591 /* before power up, insure that HDMI and AUDIO IC is under reset */
592 ret = dm_gpio_set_value(&hdmi, 1);
593 if (ret) {
594 pr_err("%s: can't set_value for hdmi_nrst gpio", __func__);
595 goto error;
596 }
597 ret = dm_gpio_set_value(&audio, 1);
598 if (ret) {
599 pr_err("%s: can't set_value for audio_nrst gpio", __func__);
600 goto error;
601 }
602
603 /* power-up audio IC */
604 regulator_autoset_by_name("v1v8_audio", NULL);
605
606 /* power-up HDMI IC */
607 regulator_autoset_by_name("v1v2_hdmi", NULL);
608 regulator_autoset_by_name("v3v3_hdmi", NULL);
609
610error:
611 return ret;
612}
613
614static bool board_is_dk2(void)
615{
Patrick Delaunay84625482020-01-13 15:17:42 +0100616 if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
Patrick Delaunayd573e462019-07-30 19:16:38 +0200617 of_machine_is_compatible("st,stm32mp157c-dk2"))
618 return true;
619
620 return false;
621}
622#endif
623
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100624/* board dependent setup after realloc */
625int board_init(void)
626{
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100627 struct udevice *dev;
628
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100629 /* address of boot parameters */
630 gd->bd->bi_boot_params = STM32_DDR_BASE + 0x100;
631
Patrice Chotard8b4afe82019-03-11 11:13:17 +0100632 /* probe all PINCTRL for hog */
633 for (uclass_first_device(UCLASS_PINCTRL, &dev);
634 dev;
635 uclass_next_device(&dev)) {
636 pr_debug("probe pincontrol = %s\n", dev->name);
637 }
638
Patrick Delaunay9a2ba282019-02-27 17:01:20 +0100639 board_key_check();
640
Patrick Delaunayf59ad452019-07-05 17:20:09 +0200641#ifdef CONFIG_DM_REGULATOR
Patrick Delaunayd573e462019-07-30 19:16:38 +0200642 if (board_is_dk2())
643 dk2_i2c1_fix();
644
Patrick Delaunayf59ad452019-07-05 17:20:09 +0200645 regulators_enable_boot_on(_DEBUG);
646#endif
647
Patrick Delaunay45459742019-02-27 17:01:24 +0100648 sysconf_init();
649
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200650 if (CONFIG_IS_ENABLED(CONFIG_LED))
Patrick Delaunay1f5118b2018-07-27 16:37:08 +0200651 led_default_state();
652
Patrick Delaunayf8598d92018-03-12 10:46:18 +0100653 return 0;
654}
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100655
656int board_late_init(void)
657{
Patrick Delaunay55f9cd22019-07-30 19:16:41 +0200658 char *boot_device;
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100659#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
660 const void *fdt_compat;
661 int fdt_compat_len;
Patrick Delaunay8b8b3d62019-07-30 19:16:37 +0200662 int ret;
663 u32 otp;
664 struct udevice *dev;
665 char buf[10];
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100666
667 fdt_compat = fdt_getprop(gd->fdt_blob, 0, "compatible",
668 &fdt_compat_len);
669 if (fdt_compat && fdt_compat_len) {
670 if (strncmp(fdt_compat, "st,", 3) != 0)
671 env_set("board_name", fdt_compat);
672 else
673 env_set("board_name", fdt_compat + 3);
674 }
Patrick Delaunay8b8b3d62019-07-30 19:16:37 +0200675 ret = uclass_get_device_by_driver(UCLASS_MISC,
676 DM_GET_DRIVER(stm32mp_bsec),
677 &dev);
678
679 if (!ret)
680 ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_BOARD),
681 &otp, sizeof(otp));
682 if (!ret && otp) {
683 snprintf(buf, sizeof(buf), "0x%04x", otp >> 16);
684 env_set("board_id", buf);
685
686 snprintf(buf, sizeof(buf), "0x%04x",
687 ((otp >> 8) & 0xF) - 1 + 0xA);
688 env_set("board_rev", buf);
689 }
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100690#endif
691
Patrick Delaunay41542472019-07-30 19:16:43 +0200692#ifdef CONFIG_ADC
Patrice Chotard395f1292019-02-12 16:50:40 +0100693 /* for DK1/DK2 boards */
694 board_check_usb_power();
Patrick Delaunay41542472019-07-30 19:16:43 +0200695#endif /* CONFIG_ADC */
Patrice Chotard395f1292019-02-12 16:50:40 +0100696
Patrick Delaunay55f9cd22019-07-30 19:16:41 +0200697 /* Check the boot-source to disable bootdelay */
698 boot_device = env_get("boot_device");
699 if (!strcmp(boot_device, "serial") || !strcmp(boot_device, "usb"))
700 env_set("bootdelay", "0");
701
Patrick Delaunayb4ae34b2019-02-27 17:01:11 +0100702 return 0;
703}
Patrice Chotard395f1292019-02-12 16:50:40 +0100704
705void board_quiesce_devices(void)
706{
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200707#ifdef CONFIG_LED
Patrice Chotard395f1292019-02-12 16:50:40 +0100708 setup_led(LEDST_OFF);
Patrick Delaunay4616ff42019-07-30 19:16:40 +0200709#endif
Patrice Chotard395f1292019-02-12 16:50:40 +0100710}
Patrice Chotard87471642019-05-02 18:07:14 +0200711
Patrick Delaunay53e3d522019-08-01 11:29:03 +0200712/* eth init function : weak called in eqos driver */
713int board_interface_eth_init(struct udevice *dev,
714 phy_interface_t interface_type)
Christophe Roullieredacf262019-05-17 15:08:43 +0200715{
716 u8 *syscfg;
717 u32 value;
Patrick Delaunay53e3d522019-08-01 11:29:03 +0200718 bool eth_clk_sel_reg = false;
719 bool eth_ref_clk_sel_reg = false;
720
721 /* Gigabit Ethernet 125MHz clock selection. */
722 eth_clk_sel_reg = dev_read_bool(dev, "st,eth_clk_sel");
723
724 /* Ethernet 50Mhz RMII clock selection */
725 eth_ref_clk_sel_reg =
726 dev_read_bool(dev, "st,eth_ref_clk_sel");
Christophe Roullieredacf262019-05-17 15:08:43 +0200727
728 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
729
730 if (!syscfg)
731 return -ENODEV;
732
733 switch (interface_type) {
734 case PHY_INTERFACE_MODE_MII:
735 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
736 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
737 debug("%s: PHY_INTERFACE_MODE_MII\n", __func__);
738 break;
739 case PHY_INTERFACE_MODE_GMII:
740 if (eth_clk_sel_reg)
741 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
742 SYSCFG_PMCSETR_ETH_CLK_SEL;
743 else
744 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
745 debug("%s: PHY_INTERFACE_MODE_GMII\n", __func__);
746 break;
747 case PHY_INTERFACE_MODE_RMII:
748 if (eth_ref_clk_sel_reg)
749 value = SYSCFG_PMCSETR_ETH_SEL_RMII |
750 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
751 else
752 value = SYSCFG_PMCSETR_ETH_SEL_RMII;
753 debug("%s: PHY_INTERFACE_MODE_RMII\n", __func__);
754 break;
755 case PHY_INTERFACE_MODE_RGMII:
756 case PHY_INTERFACE_MODE_RGMII_ID:
757 case PHY_INTERFACE_MODE_RGMII_RXID:
758 case PHY_INTERFACE_MODE_RGMII_TXID:
759 if (eth_clk_sel_reg)
760 value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
761 SYSCFG_PMCSETR_ETH_CLK_SEL;
762 else
763 value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
764 debug("%s: PHY_INTERFACE_MODE_RGMII\n", __func__);
765 break;
766 default:
767 debug("%s: Do not manage %d interface\n",
768 __func__, interface_type);
769 /* Do not manage others interfaces */
770 return -EINVAL;
771 }
772
773 /* clear and set ETH configuration bits */
774 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
775 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
776 syscfg + SYSCFG_PMCCLRR);
777 writel(value, syscfg + SYSCFG_PMCSETR);
778
779 return 0;
780}
781
Patrice Chotard8f24b1a2019-05-02 18:28:05 +0200782enum env_location env_get_location(enum env_operation op, int prio)
783{
784 u32 bootmode = get_bootmode();
785
786 if (prio)
787 return ENVL_UNKNOWN;
788
789 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
790#ifdef CONFIG_ENV_IS_IN_EXT4
791 case BOOT_FLASH_SD:
792 case BOOT_FLASH_EMMC:
793 return ENVL_EXT4;
794#endif
795#ifdef CONFIG_ENV_IS_IN_UBI
796 case BOOT_FLASH_NAND:
797 return ENVL_UBI;
798#endif
Patrice Chotarde5c38fd2019-05-09 14:25:36 +0200799#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
800 case BOOT_FLASH_NOR:
801 return ENVL_SPI_FLASH;
802#endif
Patrice Chotard8f24b1a2019-05-02 18:28:05 +0200803 default:
804 return ENVL_NOWHERE;
805 }
806}
807
Patrice Chotard7f90cd62019-05-02 18:36:01 +0200808#if defined(CONFIG_ENV_IS_IN_EXT4)
809const char *env_ext4_get_intf(void)
810{
811 u32 bootmode = get_bootmode();
812
813 switch (bootmode & TAMP_BOOT_DEVICE_MASK) {
814 case BOOT_FLASH_SD:
815 case BOOT_FLASH_EMMC:
816 return "mmc";
817 default:
818 return "";
819 }
820}
821
822const char *env_ext4_get_dev_part(void)
823{
824 static char *const dev_part[] = {"0:auto", "1:auto", "2:auto"};
825 u32 bootmode = get_bootmode();
826
827 return dev_part[(bootmode & TAMP_BOOT_INSTANCE_MASK) - 1];
828}
829#endif
830
Patrice Chotard87471642019-05-02 18:07:14 +0200831#ifdef CONFIG_SYS_MTDPARTS_RUNTIME
832
833#define MTDPARTS_LEN 256
834#define MTDIDS_LEN 128
835
836/**
837 * The mtdparts_nand0 and mtdparts_nor0 variable tends to be long.
838 * If we need to access it before the env is relocated, then we need
839 * to use our own stack buffer. gd->env_buf will be too small.
840 *
841 * @param buf temporary buffer pointer MTDPARTS_LEN long
842 * @return mtdparts variable string, NULL if not found
843 */
844static const char *env_get_mtdparts(const char *str, char *buf)
845{
846 if (gd->flags & GD_FLG_ENV_READY)
847 return env_get(str);
848 if (env_get_f(str, buf, MTDPARTS_LEN) != -1)
849 return buf;
850
851 return NULL;
852}
853
854/**
855 * update the variables "mtdids" and "mtdparts" with content of mtdparts_<dev>
856 */
857static void board_get_mtdparts(const char *dev,
858 char *mtdids,
859 char *mtdparts)
860{
861 char env_name[32] = "mtdparts_";
862 char tmp_mtdparts[MTDPARTS_LEN];
863 const char *tmp;
864
865 /* name of env variable to read = mtdparts_<dev> */
866 strcat(env_name, dev);
867 tmp = env_get_mtdparts(env_name, tmp_mtdparts);
868 if (tmp) {
869 /* mtdids: "<dev>=<dev>, ...." */
870 if (mtdids[0] != '\0')
871 strcat(mtdids, ",");
872 strcat(mtdids, dev);
873 strcat(mtdids, "=");
874 strcat(mtdids, dev);
875
876 /* mtdparts: "mtdparts=<dev>:<mtdparts_<dev>>;..." */
877 if (mtdparts[0] != '\0')
878 strncat(mtdparts, ";", MTDPARTS_LEN);
879 else
880 strcat(mtdparts, "mtdparts=");
881 strncat(mtdparts, dev, MTDPARTS_LEN);
882 strncat(mtdparts, ":", MTDPARTS_LEN);
883 strncat(mtdparts, tmp, MTDPARTS_LEN);
884 }
885}
886
887void board_mtdparts_default(const char **mtdids, const char **mtdparts)
888{
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200889 struct mtd_info *mtd;
Patrice Chotard87471642019-05-02 18:07:14 +0200890 struct udevice *dev;
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200891 static char parts[3 * MTDPARTS_LEN + 1];
Patrice Chotard87471642019-05-02 18:07:14 +0200892 static char ids[MTDIDS_LEN + 1];
893 static bool mtd_initialized;
894
895 if (mtd_initialized) {
896 *mtdids = ids;
897 *mtdparts = parts;
898 return;
899 }
900
901 memset(parts, 0, sizeof(parts));
902 memset(ids, 0, sizeof(ids));
903
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200904 /* probe all MTD devices */
905 for (uclass_first_device(UCLASS_MTD, &dev);
906 dev;
907 uclass_next_device(&dev)) {
908 pr_debug("mtd device = %s\n", dev->name);
909 }
910
911 mtd = get_mtd_device_nm("nand0");
912 if (!IS_ERR_OR_NULL(mtd)) {
Patrice Chotard87471642019-05-02 18:07:14 +0200913 board_get_mtdparts("nand0", ids, parts);
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200914 put_mtd_device(mtd);
915 }
916
917 mtd = get_mtd_device_nm("spi-nand0");
918 if (!IS_ERR_OR_NULL(mtd)) {
919 board_get_mtdparts("spi-nand0", ids, parts);
920 put_mtd_device(mtd);
921 }
Patrice Chotard87471642019-05-02 18:07:14 +0200922
923 if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
924 board_get_mtdparts("nor0", ids, parts);
925
926 mtd_initialized = true;
927 *mtdids = ids;
928 *mtdparts = parts;
929 debug("%s:mtdids=%s & mtdparts=%s\n", __func__, ids, parts);
930}
931#endif
Patrick Delaunaye81f8d12019-07-02 13:26:07 +0200932
933#if defined(CONFIG_OF_BOARD_SETUP)
934int ft_board_setup(void *blob, bd_t *bd)
935{
936#ifdef CONFIG_FDT_FIXUP_PARTITIONS
937 struct node_info nodes[] = {
938 { "st,stm32f469-qspi", MTD_DEV_TYPE_NOR, },
939 { "st,stm32mp15-fmc2", MTD_DEV_TYPE_NAND, },
940 };
941 fdt_fixup_mtdparts(blob, nodes, ARRAY_SIZE(nodes));
942#endif
943
944 return 0;
945}
946#endif
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +0200947
Patrick Delaunayf6031d62019-10-14 09:28:09 +0200948#ifdef CONFIG_SET_DFU_ALT_INFO
949#define DFU_ALT_BUF_LEN SZ_1K
950
951static void board_get_alt_info(const char *dev, char *buff)
952{
953 char var_name[32] = "dfu_alt_info_";
954 int ret;
955
956 ALLOC_CACHE_ALIGN_BUFFER(char, tmp_alt, DFU_ALT_BUF_LEN);
957
958 /* name of env variable to read = dfu_alt_info_<dev> */
959 strcat(var_name, dev);
960 ret = env_get_f(var_name, tmp_alt, DFU_ALT_BUF_LEN);
961 if (ret) {
962 if (buff[0] != '\0')
963 strcat(buff, "&");
964 strncat(buff, tmp_alt, DFU_ALT_BUF_LEN);
965 }
966}
967
968void set_dfu_alt_info(char *interface, char *devstr)
969{
970 struct udevice *dev;
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200971 struct mtd_info *mtd;
Patrick Delaunayf6031d62019-10-14 09:28:09 +0200972
973 ALLOC_CACHE_ALIGN_BUFFER(char, buf, DFU_ALT_BUF_LEN);
974
975 if (env_get("dfu_alt_info"))
976 return;
977
978 memset(buf, 0, sizeof(buf));
979
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200980 /* probe all MTD devices */
981 mtd_probe_devices();
982
Patrick Delaunayf6031d62019-10-14 09:28:09 +0200983 board_get_alt_info("ram", buf);
984
985 if (!uclass_get_device(UCLASS_MMC, 0, &dev))
986 board_get_alt_info("mmc0", buf);
987
988 if (!uclass_get_device(UCLASS_MMC, 1, &dev))
989 board_get_alt_info("mmc1", buf);
990
991 if (!uclass_get_device(UCLASS_SPI_FLASH, 0, &dev))
992 board_get_alt_info("nor0", buf);
993
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200994 mtd = get_mtd_device_nm("nand0");
995 if (!IS_ERR_OR_NULL(mtd))
Patrick Delaunayf6031d62019-10-14 09:28:09 +0200996 board_get_alt_info("nand0", buf);
997
Patrick Delaunayfd399a12019-10-14 09:28:11 +0200998 mtd = get_mtd_device_nm("spi-nand0");
999 if (!IS_ERR_OR_NULL(mtd))
1000 board_get_alt_info("spi-nand0", buf);
1001
Patrick Delaunayb4fee162019-10-14 09:28:12 +02001002#ifdef CONFIG_DFU_VIRT
1003 strncat(buf, "&virt 0=OTP", DFU_ALT_BUF_LEN);
1004
1005 if (IS_ENABLED(CONFIG_PMIC_STPMIC1))
1006 strncat(buf, "&virt 1=PMIC", DFU_ALT_BUF_LEN);
1007#endif
1008
Patrick Delaunayf6031d62019-10-14 09:28:09 +02001009 env_set("dfu_alt_info", buf);
1010 puts("DFU alt info setting: done\n");
1011}
Patrick Delaunayb4fee162019-10-14 09:28:12 +02001012
1013#if CONFIG_IS_ENABLED(DFU_VIRT)
1014#include <dfu.h>
1015#include <power/stpmic1.h>
1016
Patrick Delaunay167a6032020-01-28 10:44:13 +01001017static int dfu_otp_read(u64 offset, u8 *buffer, long *size)
Patrick Delaunayb4fee162019-10-14 09:28:12 +02001018{
1019 struct udevice *dev;
1020 int ret;
1021
1022 ret = uclass_get_device_by_driver(UCLASS_MISC,
1023 DM_GET_DRIVER(stm32mp_bsec),
1024 &dev);
1025 if (ret)
1026 return ret;
1027
1028 ret = misc_read(dev, offset + STM32_BSEC_OTP_OFFSET, buffer, *size);
1029 if (ret >= 0) {
1030 *size = ret;
1031 ret = 0;
1032 }
1033
1034 return 0;
1035}
1036
Patrick Delaunay167a6032020-01-28 10:44:13 +01001037static int dfu_pmic_read(u64 offset, u8 *buffer, long *size)
Patrick Delaunayb4fee162019-10-14 09:28:12 +02001038{
1039 int ret;
1040#ifdef CONFIG_PMIC_STPMIC1
1041 struct udevice *dev;
1042
1043 ret = uclass_get_device_by_driver(UCLASS_MISC,
1044 DM_GET_DRIVER(stpmic1_nvm),
1045 &dev);
1046 if (ret)
1047 return ret;
1048
1049 ret = misc_read(dev, 0xF8 + offset, buffer, *size);
1050 if (ret >= 0) {
1051 *size = ret;
1052 ret = 0;
1053 }
1054 if (ret == -EACCES) {
1055 *size = 0;
1056 ret = 0;
1057 }
1058#else
1059 pr_err("PMIC update not supported");
1060 ret = -EOPNOTSUPP;
1061#endif
1062
1063 return ret;
1064}
1065
1066int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset,
1067 void *buf, long *len)
1068{
1069 switch (dfu->data.virt.dev_num) {
1070 case 0x0:
1071 return dfu_otp_read(offset, buf, len);
1072 case 0x1:
1073 return dfu_pmic_read(offset, buf, len);
1074 }
1075 *len = 0;
1076 return 0;
1077}
1078
1079int __weak dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size)
1080{
1081 *size = SZ_1K;
1082
1083 return 0;
1084}
1085
1086#endif
1087
Patrick Delaunayf6031d62019-10-14 09:28:09 +02001088#endif
1089
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +02001090static void board_copro_image_process(ulong fw_image, size_t fw_size)
1091{
1092 int ret, id = 0; /* Copro id fixed to 0 as only one coproc on mp1 */
1093
1094 if (!rproc_is_initialized())
1095 if (rproc_init()) {
1096 printf("Remote Processor %d initialization failed\n",
1097 id);
1098 return;
1099 }
1100
1101 ret = rproc_load(id, fw_image, fw_size);
1102 printf("Load Remote Processor %d with data@addr=0x%08lx %u bytes:%s\n",
1103 id, fw_image, fw_size, ret ? " Failed!" : " Success!");
1104
Fabien Dessenne790d5b32019-10-30 14:38:32 +01001105 if (!ret)
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +02001106 rproc_start(id);
Patrick Delaunaya68ae8d2019-08-02 15:07:20 +02001107}
1108
1109U_BOOT_FIT_LOADABLE_HANDLER(IH_TYPE_COPRO, board_copro_image_process);