1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Copyright (C) 2023 PHYTEC Messtechnik GmbH
4  * Author: Teresa Remmet <t.remmet@phytec.de>
5  */
6 
7 #ifndef _PHYTEC_SOM_DETECTION_H
8 #define _PHYTEC_SOM_DETECTION_H
9 
10 #include "phytec_som_detection_blocks.h"
11 #include <fdtdec.h>
12 
13 #define PHYTEC_MAX_OPTIONS	17
14 #define PHYTEC_EEPROM_INVAL	0xff
15 
16 #define PHYTEC_API2_DATA_LEN	32
17 
18 #define PHYTEC_GET_OPTION(option) \
19 	(((option) > '9') ? (option) - 'A' + 10 : (option) - '0')
20 
21 #define PHYTEC_PRODUCT_NAME_STD_LEN	7	// PCx-000
22 #define PHYTEC_PRODUCT_NAME_KSP_LEN	8	// KSP-0000
23 #define PHYTEC_PRODUCT_NAME_MAX_LEN	PHYTEC_PRODUCT_NAME_KSP_LEN
24 #define PHYTEC_PART_NUMBER_STD_LEN	11	// PCx-000-\w{1,17}.Ax
25 #define PHYTEC_PART_NUMBER_KSP_LEN	11	// KSP-0000.Ax
26 #define PHYTEC_PART_NUMBER_STD_KSP_LEN	16	// PCx-000-KSx00.Ax
27 #define PHYTEC_PART_NUMBER_MAX_LEN	PHYTEC_PRODUCT_NAME_MAX_LEN + 21
28 
29 enum {
30 	PHYTEC_API_REV0 = 0,
31 	PHYTEC_API_REV1,
32 	PHYTEC_API_REV2,
33 	PHYTEC_API_REV3,
34 };
35 
36 enum phytec_som_type_str {
37 	SOM_TYPE_PCM = 0,
38 	SOM_TYPE_PCL,
39 	SOM_TYPE_KSM,
40 	SOM_TYPE_KSP,
41 };
42 
43 static const char * const phytec_som_type_str[] = {
44 	"PCM",
45 	"PCL",
46 	"KSM",
47 	"KSP",
48 };
49 
50 struct phytec_api0_data {
51 	u8 pcb_rev;		/* PCB revision of SoM */
52 	u8 som_type;		/* SoM type */
53 	u8 ksp_no;		/* KSP no */
54 	char opt[16];		/* SoM options */
55 	u8 mac[6];		/* MAC address (optional) */
56 	u8 pad[5];		/* padding */
57 	u8 cksum;		/* checksum */
58 } __packed;
59 
60 struct phytec_api2_data {
61 	u8 pcb_rev;		/* PCB revision of SoM */
62 	u8 pcb_sub_opt_rev;	/* PCB subrevision and opt revision */
63 	u8 som_type;		/* SoM type */
64 	u8 som_no;		/* SoM number */
65 	u8 ksp_no;		/* KSP information */
66 	char opt[PHYTEC_MAX_OPTIONS]; /* SoM options */
67 	char bom_rev[2];	/* BOM revision */
68 	u8 mac[6];		/* MAC address (optional) */
69 	u8 crc8;		/* checksum */
70 } __packed;
71 
72 struct phytec_eeprom_payload {
73 	u8 api_rev;
74 	union {
75 		struct phytec_api0_data data_api0;
76 		struct phytec_api2_data data_api2;
77 	} data;
78 	struct phytec_api3_element *block_head;
79 } __packed;
80 
81 struct phytec_eeprom_data {
82 	struct phytec_eeprom_payload payload;
83 	bool valid;
84 };
85 
86 int phytec_eeprom_data_setup_fallback(struct phytec_eeprom_data *data,
87 				      int bus_num, int addr,
88 				      int addr_fallback);
89 int phytec_eeprom_data_setup(struct phytec_eeprom_data *data,
90 			     int bus_num, int addr);
91 int phytec_eeprom_data_init(struct phytec_eeprom_data *data, int bus_num,
92 			    int addr);
93 void __maybe_unused phytec_print_som_info(struct phytec_eeprom_data *data);
94 
95 char * __maybe_unused phytec_get_opt(struct phytec_eeprom_data *data);
96 u8 __maybe_unused phytec_get_rev(struct phytec_eeprom_data *data);
97 u8 __maybe_unused phytec_get_som_type(struct phytec_eeprom_data *data);
98 #if IS_ENABLED(CONFIG_OF_LIBFDT)
99 int phytec_ft_board_fixup(struct phytec_eeprom_data *data, void *blob);
100 #endif /* IS_ENABLED(CONFIG_OF_LIBFDT) */
101 
102 #if IS_ENABLED(CONFIG_CMD_EXTENSION)
103 struct extension *phytec_add_extension(const char *name, const char *overlay,
104 				       const char *other);
105 #endif /* IS_ENABLED(CONFIG_CMD_EXTENSION) */
106 
107 struct phytec_api3_element *
108 	__maybe_unused phytec_get_block_head(struct phytec_eeprom_data *data);
109 
110 #endif /* _PHYTEC_SOM_DETECTION_H */
111