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