1 /*
2  * Copyright (c) 2024 DNDG srl
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/devicetree.h>
9 #include <zephyr/device.h>
10 #include <zephyr/init.h>
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
13 #include <soc.h>
14 #include <errno.h>
15 #include <stdint.h>
16 #include "board.h"
17 
18 #define AT25SF128_READ_SECURITY_REGISTERS 0x48
19 
20 static struct opta_board_info info;
21 static char serial_number[OPTA_SERIAL_NUMBER_SIZE + 1];
22 
23 #if defined(CONFIG_FLASH_STM32_QSPI_GENERIC_READ)
24 
25 const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(qspi_flash));
26 
board_info(void)27 static int board_info(void)
28 {
29 	QSPI_CommandTypeDef cmd = {
30 		.Instruction = AT25SF128_READ_SECURITY_REGISTERS,
31 		.InstructionMode = QSPI_INSTRUCTION_1_LINE,
32 		.Address = (1 << 13),
33 		.AddressSize = QSPI_ADDRESS_24_BITS,
34 		.AddressMode = QSPI_ADDRESS_1_LINE,
35 		.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE,
36 		.DataMode = QSPI_DATA_1_LINE,
37 		.NbData = sizeof(struct opta_board_info),
38 		.DummyCycles = 8,
39 	};
40 
41 	if (!device_is_ready(dev)) {
42 		return -ENODEV;
43 	}
44 
45 	int ret = flash_ex_op(dev, FLASH_STM32_QSPI_EX_OP_GENERIC_READ, (uintptr_t)&cmd, &info);
46 
47 	if (ret != 0) {
48 		return -EIO;
49 	}
50 
51 	return 0;
52 }
53 
54 SYS_INIT(board_info, APPLICATION, 0);
55 
56 #endif /* CONFIG_FLASH_STM32_QSPI_GENERIC_READ */
57 
uint32tohex(char * dst,uint32_t value)58 static void uint32tohex(char *dst, uint32_t value)
59 {
60 	int v;
61 
62 	for (int i = 0; i < 8; i++) {
63 		v = (value >> ((8 - i - 1) * 4)) & 0x0F;
64 		dst[i] = v <= 9 ? (0x30 + v) : (0x40 + v - 9);
65 	}
66 }
67 
opta_get_board_info(void)68 const struct opta_board_info *const opta_get_board_info(void)
69 {
70 	if (info.magic == OPTA_OTP_MAGIC) {
71 		return &info;
72 	}
73 	return NULL;
74 }
75 
opta_get_serial_number(void)76 const char *const opta_get_serial_number(void)
77 {
78 	if (serial_number[0] == 0) {
79 		uint32tohex(&serial_number[0], HAL_GetUIDw0());
80 		uint32tohex(&serial_number[8], HAL_GetUIDw1());
81 		uint32tohex(&serial_number[16], HAL_GetUIDw2());
82 	}
83 	return serial_number;
84 }
85