xref: /OK3568_Linux_fs/kernel/include/linux/bcm963xx_nvram.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef __LINUX_BCM963XX_NVRAM_H__
3*4882a593Smuzhiyun #define __LINUX_BCM963XX_NVRAM_H__
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <linux/crc32.h>
6*4882a593Smuzhiyun #include <linux/if_ether.h>
7*4882a593Smuzhiyun #include <linux/sizes.h>
8*4882a593Smuzhiyun #include <linux/types.h>
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun /*
11*4882a593Smuzhiyun  * Broadcom BCM963xx SoC board nvram data structure.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * The nvram structure varies in size depending on the SoC board version. Use
14*4882a593Smuzhiyun  * the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
15*4882a593Smuzhiyun  * you need instead of sizeof(struct bcm963xx_nvram) as this may change.
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #define BCM963XX_NVRAM_V4_SIZE		300
19*4882a593Smuzhiyun #define BCM963XX_NVRAM_V5_SIZE		(1 * SZ_1K)
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define BCM963XX_DEFAULT_PSI_SIZE	64
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun enum bcm963xx_nvram_nand_part {
24*4882a593Smuzhiyun 	BCM963XX_NVRAM_NAND_PART_BOOT = 0,
25*4882a593Smuzhiyun 	BCM963XX_NVRAM_NAND_PART_ROOTFS_1,
26*4882a593Smuzhiyun 	BCM963XX_NVRAM_NAND_PART_ROOTFS_2,
27*4882a593Smuzhiyun 	BCM963XX_NVRAM_NAND_PART_DATA,
28*4882a593Smuzhiyun 	BCM963XX_NVRAM_NAND_PART_BBT,
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	__BCM963XX_NVRAM_NAND_NR_PARTS
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct bcm963xx_nvram {
34*4882a593Smuzhiyun 	u32	version;
35*4882a593Smuzhiyun 	char	bootline[256];
36*4882a593Smuzhiyun 	char	name[16];
37*4882a593Smuzhiyun 	u32	main_tp_number;
38*4882a593Smuzhiyun 	u32	psi_size;
39*4882a593Smuzhiyun 	u32	mac_addr_count;
40*4882a593Smuzhiyun 	u8	mac_addr_base[ETH_ALEN];
41*4882a593Smuzhiyun 	u8	__reserved1[2];
42*4882a593Smuzhiyun 	u32	checksum_v4;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	u8	__reserved2[292];
45*4882a593Smuzhiyun 	u32	nand_part_offset[__BCM963XX_NVRAM_NAND_NR_PARTS];
46*4882a593Smuzhiyun 	u32	nand_part_size[__BCM963XX_NVRAM_NAND_NR_PARTS];
47*4882a593Smuzhiyun 	u8	__reserved3[388];
48*4882a593Smuzhiyun 	u32	checksum_v5;
49*4882a593Smuzhiyun };
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define BCM963XX_NVRAM_NAND_PART_OFFSET(nvram, part) \
52*4882a593Smuzhiyun 	bcm963xx_nvram_nand_part_offset(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
53*4882a593Smuzhiyun 
bcm963xx_nvram_nand_part_offset(const struct bcm963xx_nvram * nvram,enum bcm963xx_nvram_nand_part part)54*4882a593Smuzhiyun static inline u64 __pure bcm963xx_nvram_nand_part_offset(
55*4882a593Smuzhiyun 	const struct bcm963xx_nvram *nvram,
56*4882a593Smuzhiyun 	enum bcm963xx_nvram_nand_part part)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	return nvram->nand_part_offset[part] * SZ_1K;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define BCM963XX_NVRAM_NAND_PART_SIZE(nvram, part) \
62*4882a593Smuzhiyun 	bcm963xx_nvram_nand_part_size(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
63*4882a593Smuzhiyun 
bcm963xx_nvram_nand_part_size(const struct bcm963xx_nvram * nvram,enum bcm963xx_nvram_nand_part part)64*4882a593Smuzhiyun static inline u64 __pure bcm963xx_nvram_nand_part_size(
65*4882a593Smuzhiyun 	const struct bcm963xx_nvram *nvram,
66*4882a593Smuzhiyun 	enum bcm963xx_nvram_nand_part part)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun 	return nvram->nand_part_size[part] * SZ_1K;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun /*
72*4882a593Smuzhiyun  * bcm963xx_nvram_checksum - Verify nvram checksum
73*4882a593Smuzhiyun  *
74*4882a593Smuzhiyun  * @nvram: pointer to full size nvram data structure
75*4882a593Smuzhiyun  * @expected_out: optional pointer to store expected checksum value
76*4882a593Smuzhiyun  * @actual_out: optional pointer to store actual checksum value
77*4882a593Smuzhiyun  *
78*4882a593Smuzhiyun  * Return: 0 if the checksum is valid, otherwise -EINVAL
79*4882a593Smuzhiyun  */
bcm963xx_nvram_checksum(const struct bcm963xx_nvram * nvram,u32 * expected_out,u32 * actual_out)80*4882a593Smuzhiyun static int __maybe_unused bcm963xx_nvram_checksum(
81*4882a593Smuzhiyun 	const struct bcm963xx_nvram *nvram,
82*4882a593Smuzhiyun 	u32 *expected_out, u32 *actual_out)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	u32 expected, actual;
85*4882a593Smuzhiyun 	size_t len;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (nvram->version <= 4) {
88*4882a593Smuzhiyun 		expected = nvram->checksum_v4;
89*4882a593Smuzhiyun 		len = BCM963XX_NVRAM_V4_SIZE - sizeof(u32);
90*4882a593Smuzhiyun 	} else {
91*4882a593Smuzhiyun 		expected = nvram->checksum_v5;
92*4882a593Smuzhiyun 		len = BCM963XX_NVRAM_V5_SIZE - sizeof(u32);
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	/*
96*4882a593Smuzhiyun 	 * Calculate the CRC32 value for the nvram with a checksum value
97*4882a593Smuzhiyun 	 * of 0 without modifying or copying the nvram by combining:
98*4882a593Smuzhiyun 	 * - The CRC32 of the nvram without the checksum value
99*4882a593Smuzhiyun 	 * - The CRC32 of a zero checksum value (which is also 0)
100*4882a593Smuzhiyun 	 */
101*4882a593Smuzhiyun 	actual = crc32_le_combine(
102*4882a593Smuzhiyun 		crc32_le(~0, (u8 *)nvram, len), 0, sizeof(u32));
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	if (expected_out)
105*4882a593Smuzhiyun 		*expected_out = expected;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	if (actual_out)
108*4882a593Smuzhiyun 		*actual_out = actual;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	return expected == actual ? 0 : -EINVAL;
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #endif /* __LINUX_BCM963XX_NVRAM_H__ */
114