Commit 16ac90c7ee6fe973ee86fa9b08f876e5c33751bc
Committed by
Tom Rini
1 parent
b9ea0c3a20
Exists in
v2017.01-smarct4x
and in
37 other branches
KM/IVM: split the IVM reading and parsing in 2 parts
This allows to first read the IVM content (earlier in the boot sequence) and define the ethaddr env variable thanks to the ivm_read_eepromi(). Later, the IVM content can be parsed and used to define some hush variables, when the hush subsystem is available thanks to ivm_analyze_eeprom(). To avoid the HW read to happen twice, the buffer passed to ivm_read_eeprom() has to be reused by ivm_analyze_eeprom (and thus allocated before calling ivm_read_eeprom()). Signed-off-by: Valentin Longchamp <valentin.longchamp@keymile.com>
Showing 2 changed files with 63 additions and 25 deletions Inline Diff
board/keymile/common/common.h
1 | /* | 1 | /* |
2 | * (C) Copyright 2008 | 2 | * (C) Copyright 2008 |
3 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. | 3 | * Heiko Schocher, DENX Software Engineering, hs@denx.de. |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #ifndef __KEYMILE_COMMON_H | 8 | #ifndef __KEYMILE_COMMON_H |
9 | #define __KEYMILE_COMMON_H | 9 | #define __KEYMILE_COMMON_H |
10 | 10 | ||
11 | #define WRG_RESET 0x80 | 11 | #define WRG_RESET 0x80 |
12 | #define H_OPORTS_14 0x40 | 12 | #define H_OPORTS_14 0x40 |
13 | #define WRG_LED 0x02 | 13 | #define WRG_LED 0x02 |
14 | #define WRL_BOOT 0x01 | 14 | #define WRL_BOOT 0x01 |
15 | 15 | ||
16 | #define OPRTL_XBUFENA 0x20 | 16 | #define OPRTL_XBUFENA 0x20 |
17 | 17 | ||
18 | #define H_OPORTS_SCC4_ENA 0x10 | 18 | #define H_OPORTS_SCC4_ENA 0x10 |
19 | #define H_OPORTS_SCC4_FD_ENA 0x04 | 19 | #define H_OPORTS_SCC4_FD_ENA 0x04 |
20 | #define H_OPORTS_FCC1_PW_DWN 0x01 | 20 | #define H_OPORTS_FCC1_PW_DWN 0x01 |
21 | 21 | ||
22 | #define PIGGY_PRESENT 0x80 | 22 | #define PIGGY_PRESENT 0x80 |
23 | 23 | ||
24 | struct km_bec_fpga { | 24 | struct km_bec_fpga { |
25 | unsigned char id; | 25 | unsigned char id; |
26 | unsigned char rev; | 26 | unsigned char rev; |
27 | unsigned char oprth; | 27 | unsigned char oprth; |
28 | unsigned char oprtl; | 28 | unsigned char oprtl; |
29 | unsigned char res1[3]; | 29 | unsigned char res1[3]; |
30 | unsigned char bprth; | 30 | unsigned char bprth; |
31 | unsigned char bprtl; | 31 | unsigned char bprtl; |
32 | unsigned char gprt3; | 32 | unsigned char gprt3; |
33 | unsigned char gprt2; | 33 | unsigned char gprt2; |
34 | unsigned char gprt1; | 34 | unsigned char gprt1; |
35 | unsigned char gprt0; | 35 | unsigned char gprt0; |
36 | unsigned char res2[2]; | 36 | unsigned char res2[2]; |
37 | unsigned char prst; | 37 | unsigned char prst; |
38 | unsigned char res3[0xfff0]; | 38 | unsigned char res3[0xfff0]; |
39 | unsigned char pgy_id; | 39 | unsigned char pgy_id; |
40 | unsigned char pgy_rev; | 40 | unsigned char pgy_rev; |
41 | unsigned char pgy_outputs; | 41 | unsigned char pgy_outputs; |
42 | unsigned char pgy_eth; | 42 | unsigned char pgy_eth; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | #define BFTICU_DIPSWITCH_MASK 0x0f | 45 | #define BFTICU_DIPSWITCH_MASK 0x0f |
46 | 46 | ||
47 | /* | 47 | /* |
48 | * BFTICU FPGA iomap | 48 | * BFTICU FPGA iomap |
49 | * BFTICU is used on mgcoge and mgocge3ne | 49 | * BFTICU is used on mgcoge and mgocge3ne |
50 | */ | 50 | */ |
51 | struct bfticu_iomap { | 51 | struct bfticu_iomap { |
52 | u8 xi_ena; /* General defect enable */ | 52 | u8 xi_ena; /* General defect enable */ |
53 | u8 pack1[3]; | 53 | u8 pack1[3]; |
54 | u8 en_csn; | 54 | u8 en_csn; |
55 | u8 pack2; | 55 | u8 pack2; |
56 | u8 safe_mem; | 56 | u8 safe_mem; |
57 | u8 pack3; | 57 | u8 pack3; |
58 | u8 id; | 58 | u8 id; |
59 | u8 pack4; | 59 | u8 pack4; |
60 | u8 rev; | 60 | u8 rev; |
61 | u8 build; | 61 | u8 build; |
62 | u8 p_frc; | 62 | u8 p_frc; |
63 | u8 p_msk; | 63 | u8 p_msk; |
64 | u8 pack5[2]; | 64 | u8 pack5[2]; |
65 | u8 xg_int; | 65 | u8 xg_int; |
66 | u8 pack6[15]; | 66 | u8 pack6[15]; |
67 | u8 s_conf; | 67 | u8 s_conf; |
68 | u8 pack7; | 68 | u8 pack7; |
69 | u8 dmx_conf12; | 69 | u8 dmx_conf12; |
70 | u8 pack8; | 70 | u8 pack8; |
71 | u8 s_clkslv; | 71 | u8 s_clkslv; |
72 | u8 pack9[11]; | 72 | u8 pack9[11]; |
73 | u8 d_conf; | 73 | u8 d_conf; |
74 | u8 d_mask_ca; | 74 | u8 d_mask_ca; |
75 | u8 d_pll_del; | 75 | u8 d_pll_del; |
76 | u8 pack10[16]; | 76 | u8 pack10[16]; |
77 | u8 t_conf_ca; | 77 | u8 t_conf_ca; |
78 | u8 t_mask_ca; | 78 | u8 t_mask_ca; |
79 | u8 pack11[13]; | 79 | u8 pack11[13]; |
80 | u8 m_def0; | 80 | u8 m_def0; |
81 | u8 m_def1; | 81 | u8 m_def1; |
82 | u8 m_def2; | 82 | u8 m_def2; |
83 | u8 m_def3; | 83 | u8 m_def3; |
84 | u8 m_def4; | 84 | u8 m_def4; |
85 | u8 m_def5; | 85 | u8 m_def5; |
86 | u8 m_def_trap0; | 86 | u8 m_def_trap0; |
87 | u8 m_def_trap1; | 87 | u8 m_def_trap1; |
88 | u8 m_def_trap2; | 88 | u8 m_def_trap2; |
89 | u8 m_def_trap3; | 89 | u8 m_def_trap3; |
90 | u8 m_def_trap4; | 90 | u8 m_def_trap4; |
91 | u8 m_def_trap5; | 91 | u8 m_def_trap5; |
92 | u8 m_mask_def0; | 92 | u8 m_mask_def0; |
93 | u8 m_mask_def1; | 93 | u8 m_mask_def1; |
94 | u8 m_mask_def2; | 94 | u8 m_mask_def2; |
95 | u8 m_mask_def3; | 95 | u8 m_mask_def3; |
96 | u8 m_mask_def4; | 96 | u8 m_mask_def4; |
97 | u8 m_mask_def5; | 97 | u8 m_mask_def5; |
98 | u8 m_def_mask0; | 98 | u8 m_def_mask0; |
99 | u8 m_def_mask1; | 99 | u8 m_def_mask1; |
100 | u8 m_def_mask2; | 100 | u8 m_def_mask2; |
101 | u8 m_def_mask3; | 101 | u8 m_def_mask3; |
102 | u8 m_def_mask4; | 102 | u8 m_def_mask4; |
103 | u8 m_def_mask5; | 103 | u8 m_def_mask5; |
104 | u8 m_def_pri; | 104 | u8 m_def_pri; |
105 | u8 pack12[11]; | 105 | u8 pack12[11]; |
106 | u8 hw_status; | 106 | u8 hw_status; |
107 | u8 pack13; | 107 | u8 pack13; |
108 | u8 hw_control1; | 108 | u8 hw_control1; |
109 | u8 hw_control2; | 109 | u8 hw_control2; |
110 | u8 hw_control3; | 110 | u8 hw_control3; |
111 | u8 pack14[7]; | 111 | u8 pack14[7]; |
112 | u8 led_on; /* Leds */ | 112 | u8 led_on; /* Leds */ |
113 | u8 pack15; | 113 | u8 pack15; |
114 | u8 sfp_control; /* SFP modules */ | 114 | u8 sfp_control; /* SFP modules */ |
115 | u8 pack16; | 115 | u8 pack16; |
116 | u8 alarm_control; /* Alarm output */ | 116 | u8 alarm_control; /* Alarm output */ |
117 | u8 pack17; | 117 | u8 pack17; |
118 | u8 icps; /* ICN clock pulse shaping */ | 118 | u8 icps; /* ICN clock pulse shaping */ |
119 | u8 mswitch; /* Read mode switch */ | 119 | u8 mswitch; /* Read mode switch */ |
120 | u8 pack18[6]; | 120 | u8 pack18[6]; |
121 | u8 pb_dbug; | 121 | u8 pb_dbug; |
122 | }; | 122 | }; |
123 | 123 | ||
124 | #if !defined(CONFIG_PIGGY_MAC_ADRESS_OFFSET) | 124 | #if !defined(CONFIG_PIGGY_MAC_ADRESS_OFFSET) |
125 | #define CONFIG_PIGGY_MAC_ADRESS_OFFSET 0 | 125 | #define CONFIG_PIGGY_MAC_ADRESS_OFFSET 0 |
126 | #endif | 126 | #endif |
127 | 127 | ||
128 | int ethernet_present(void); | 128 | int ethernet_present(void); |
129 | int ivm_read_eeprom(void); | 129 | int ivm_read_eeprom(void); |
130 | int ivm_simple_read_eeprom(unsigned char *buf, int len); | ||
131 | int ivm_analyze_eeprom(unsigned char *buf, int len); | ||
130 | 132 | ||
131 | int trigger_fpga_config(void); | 133 | int trigger_fpga_config(void); |
132 | int wait_for_fpga_config(void); | 134 | int wait_for_fpga_config(void); |
133 | int fpga_reset(void); | 135 | int fpga_reset(void); |
134 | int toggle_eeprom_spi_bus(void); | 136 | int toggle_eeprom_spi_bus(void); |
135 | 137 | ||
136 | int set_km_env(void); | 138 | int set_km_env(void); |
137 | int fdt_set_node_and_value(void *blob, | 139 | int fdt_set_node_and_value(void *blob, |
138 | char *nodename, | 140 | char *nodename, |
139 | char *regname, | 141 | char *regname, |
140 | void *var, | 142 | void *var, |
141 | int size); | 143 | int size); |
142 | int fdt_get_node_and_value(void *blob, | 144 | int fdt_get_node_and_value(void *blob, |
143 | char *nodename, | 145 | char *nodename, |
144 | char *propname, | 146 | char *propname, |
145 | void **var); | 147 | void **var); |
146 | 148 | ||
147 | #define DELAY_ABORT_SEQ 62 /* @200kHz 9 clocks = 44us, 62us is ok */ | 149 | #define DELAY_ABORT_SEQ 62 /* @200kHz 9 clocks = 44us, 62us is ok */ |
148 | #define DELAY_HALF_PERIOD (500 / (CONFIG_SYS_I2C_SPEED / 1000)) | 150 | #define DELAY_HALF_PERIOD (500 / (CONFIG_SYS_I2C_SPEED / 1000)) |
149 | 151 | ||
150 | int i2c_soft_read_pin(void); | 152 | int i2c_soft_read_pin(void); |
151 | int i2c_make_abort(void); | 153 | int i2c_make_abort(void); |
152 | #endif /* __KEYMILE_COMMON_H */ | 154 | #endif /* __KEYMILE_COMMON_H */ |
153 | 155 |
board/keymile/common/ivm.c
1 | /* | 1 | /* |
2 | * (C) Copyright 2011 | 2 | * (C) Copyright 2011 |
3 | * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com | 3 | * Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | 5 | * SPDX-License-Identifier: GPL-2.0+ |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <common.h> | 8 | #include <common.h> |
9 | #include <cli_hush.h> | 9 | #include <cli_hush.h> |
10 | #include <i2c.h> | 10 | #include <i2c.h> |
11 | #include "common.h" | 11 | #include "common.h" |
12 | 12 | ||
13 | #define MAC_STR_SZ 20 | ||
14 | |||
13 | static int ivm_calc_crc(unsigned char *buf, int len) | 15 | static int ivm_calc_crc(unsigned char *buf, int len) |
14 | { | 16 | { |
15 | const unsigned short crc_tab[16] = { | 17 | const unsigned short crc_tab[16] = { |
16 | 0x0000, 0xCC01, 0xD801, 0x1400, | 18 | 0x0000, 0xCC01, 0xD801, 0x1400, |
17 | 0xF001, 0x3C00, 0x2800, 0xE401, | 19 | 0xF001, 0x3C00, 0x2800, 0xE401, |
18 | 0xA001, 0x6C00, 0x7800, 0xB401, | 20 | 0xA001, 0x6C00, 0x7800, 0xB401, |
19 | 0x5000, 0x9C01, 0x8801, 0x4400}; | 21 | 0x5000, 0x9C01, 0x8801, 0x4400}; |
20 | 22 | ||
21 | unsigned short crc = 0; /* final result */ | 23 | unsigned short crc = 0; /* final result */ |
22 | unsigned short r1 = 0; /* temp */ | 24 | unsigned short r1 = 0; /* temp */ |
23 | unsigned char byte = 0; /* input buffer */ | 25 | unsigned char byte = 0; /* input buffer */ |
24 | int i; | 26 | int i; |
25 | 27 | ||
26 | /* calculate CRC from array data */ | 28 | /* calculate CRC from array data */ |
27 | for (i = 0; i < len; i++) { | 29 | for (i = 0; i < len; i++) { |
28 | byte = buf[i]; | 30 | byte = buf[i]; |
29 | 31 | ||
30 | /* lower 4 bits */ | 32 | /* lower 4 bits */ |
31 | r1 = crc_tab[crc & 0xF]; | 33 | r1 = crc_tab[crc & 0xF]; |
32 | crc = ((crc) >> 4) & 0x0FFF; | 34 | crc = ((crc) >> 4) & 0x0FFF; |
33 | crc = crc ^ r1 ^ crc_tab[byte & 0xF]; | 35 | crc = crc ^ r1 ^ crc_tab[byte & 0xF]; |
34 | 36 | ||
35 | /* upper 4 bits */ | 37 | /* upper 4 bits */ |
36 | r1 = crc_tab[crc & 0xF]; | 38 | r1 = crc_tab[crc & 0xF]; |
37 | crc = (crc >> 4) & 0x0FFF; | 39 | crc = (crc >> 4) & 0x0FFF; |
38 | crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF]; | 40 | crc = crc ^ r1 ^ crc_tab[(byte >> 4) & 0xF]; |
39 | } | 41 | } |
40 | return crc; | 42 | return crc; |
41 | } | 43 | } |
42 | 44 | ||
43 | static int ivm_set_value(char *name, char *value) | 45 | static int ivm_set_value(char *name, char *value) |
44 | { | 46 | { |
45 | char tempbuf[256]; | 47 | char tempbuf[256]; |
46 | 48 | ||
47 | if (value != NULL) { | 49 | if (value != NULL) { |
48 | sprintf(tempbuf, "%s=%s", name, value); | 50 | sprintf(tempbuf, "%s=%s", name, value); |
49 | return set_local_var(tempbuf, 0); | 51 | return set_local_var(tempbuf, 0); |
50 | } else { | 52 | } else { |
51 | unset_local_var(name); | 53 | unset_local_var(name); |
52 | } | 54 | } |
53 | return 0; | 55 | return 0; |
54 | } | 56 | } |
55 | 57 | ||
56 | static int ivm_get_value(unsigned char *buf, int len, char *name, int off, | 58 | static int ivm_get_value(unsigned char *buf, int len, char *name, int off, |
57 | int check) | 59 | int check) |
58 | { | 60 | { |
59 | unsigned short val; | 61 | unsigned short val; |
60 | unsigned char valbuf[30]; | 62 | unsigned char valbuf[30]; |
61 | 63 | ||
62 | if ((buf[off + 0] != buf[off + 2]) && | 64 | if ((buf[off + 0] != buf[off + 2]) && |
63 | (buf[off + 2] != buf[off + 4])) { | 65 | (buf[off + 2] != buf[off + 4])) { |
64 | printf("%s Error corrupted %s\n", __func__, name); | 66 | printf("%s Error corrupted %s\n", __func__, name); |
65 | val = -1; | 67 | val = -1; |
66 | } else { | 68 | } else { |
67 | val = buf[off + 0] + (buf[off + 1] << 8); | 69 | val = buf[off + 0] + (buf[off + 1] << 8); |
68 | if ((val == 0) && (check == 1)) | 70 | if ((val == 0) && (check == 1)) |
69 | val = -1; | 71 | val = -1; |
70 | } | 72 | } |
71 | sprintf((char *)valbuf, "%x", val); | 73 | sprintf((char *)valbuf, "%x", val); |
72 | ivm_set_value(name, (char *)valbuf); | 74 | ivm_set_value(name, (char *)valbuf); |
73 | return val; | 75 | return val; |
74 | } | 76 | } |
75 | 77 | ||
76 | #define INV_BLOCKSIZE 0x100 | 78 | #define INV_BLOCKSIZE 0x100 |
77 | #define INV_DATAADDRESS 0x21 | 79 | #define INV_DATAADDRESS 0x21 |
78 | #define INVENTORYDATASIZE (INV_BLOCKSIZE - INV_DATAADDRESS - 3) | 80 | #define INVENTORYDATASIZE (INV_BLOCKSIZE - INV_DATAADDRESS - 3) |
79 | 81 | ||
80 | #define IVM_POS_SHORT_TEXT 0 | 82 | #define IVM_POS_SHORT_TEXT 0 |
81 | #define IVM_POS_MANU_ID 1 | 83 | #define IVM_POS_MANU_ID 1 |
82 | #define IVM_POS_MANU_SERIAL 2 | 84 | #define IVM_POS_MANU_SERIAL 2 |
83 | #define IVM_POS_PART_NUMBER 3 | 85 | #define IVM_POS_PART_NUMBER 3 |
84 | #define IVM_POS_BUILD_STATE 4 | 86 | #define IVM_POS_BUILD_STATE 4 |
85 | #define IVM_POS_SUPPLIER_PART_NUMBER 5 | 87 | #define IVM_POS_SUPPLIER_PART_NUMBER 5 |
86 | #define IVM_POS_DELIVERY_DATE 6 | 88 | #define IVM_POS_DELIVERY_DATE 6 |
87 | #define IVM_POS_SUPPLIER_BUILD_STATE 7 | 89 | #define IVM_POS_SUPPLIER_BUILD_STATE 7 |
88 | #define IVM_POS_CUSTOMER_ID 8 | 90 | #define IVM_POS_CUSTOMER_ID 8 |
89 | #define IVM_POS_CUSTOMER_PROD_ID 9 | 91 | #define IVM_POS_CUSTOMER_PROD_ID 9 |
90 | #define IVM_POS_HISTORY 10 | 92 | #define IVM_POS_HISTORY 10 |
91 | #define IVM_POS_SYMBOL_ONLY 11 | 93 | #define IVM_POS_SYMBOL_ONLY 11 |
92 | 94 | ||
93 | static char convert_char(char c) | 95 | static char convert_char(char c) |
94 | { | 96 | { |
95 | return (c < ' ' || c > '~') ? '.' : c; | 97 | return (c < ' ' || c > '~') ? '.' : c; |
96 | } | 98 | } |
97 | 99 | ||
98 | static int ivm_findinventorystring(int type, | 100 | static int ivm_findinventorystring(int type, |
99 | unsigned char *const string, | 101 | unsigned char *const string, |
100 | unsigned long maxlen, | 102 | unsigned long maxlen, |
101 | unsigned char *buf) | 103 | unsigned char *buf) |
102 | { | 104 | { |
103 | int xcode = 0; | 105 | int xcode = 0; |
104 | unsigned long cr = 0; | 106 | unsigned long cr = 0; |
105 | unsigned long addr = INV_DATAADDRESS; | 107 | unsigned long addr = INV_DATAADDRESS; |
106 | unsigned long size = 0; | 108 | unsigned long size = 0; |
107 | unsigned long nr = type; | 109 | unsigned long nr = type; |
108 | int stop = 0; /* stop on semicolon */ | 110 | int stop = 0; /* stop on semicolon */ |
109 | 111 | ||
110 | memset(string, '\0', maxlen); | 112 | memset(string, '\0', maxlen); |
111 | switch (type) { | 113 | switch (type) { |
112 | case IVM_POS_SYMBOL_ONLY: | 114 | case IVM_POS_SYMBOL_ONLY: |
113 | nr = 0; | 115 | nr = 0; |
114 | stop = 1; | 116 | stop = 1; |
115 | break; | 117 | break; |
116 | default: | 118 | default: |
117 | nr = type; | 119 | nr = type; |
118 | stop = 0; | 120 | stop = 0; |
119 | } | 121 | } |
120 | 122 | ||
121 | /* Look for the requested number of CR. */ | 123 | /* Look for the requested number of CR. */ |
122 | while ((cr != nr) && (addr < INVENTORYDATASIZE)) { | 124 | while ((cr != nr) && (addr < INVENTORYDATASIZE)) { |
123 | if (buf[addr] == '\r') | 125 | if (buf[addr] == '\r') |
124 | cr++; | 126 | cr++; |
125 | addr++; | 127 | addr++; |
126 | } | 128 | } |
127 | 129 | ||
128 | /* | 130 | /* |
129 | * the expected number of CR was found until the end of the IVM | 131 | * the expected number of CR was found until the end of the IVM |
130 | * content --> fill string | 132 | * content --> fill string |
131 | */ | 133 | */ |
132 | if (addr < INVENTORYDATASIZE) { | 134 | if (addr < INVENTORYDATASIZE) { |
133 | /* Copy the IVM string in the corresponding string */ | 135 | /* Copy the IVM string in the corresponding string */ |
134 | for (; (buf[addr] != '\r') && | 136 | for (; (buf[addr] != '\r') && |
135 | ((buf[addr] != ';') || (!stop)) && | 137 | ((buf[addr] != ';') || (!stop)) && |
136 | (size < (maxlen - 1) && | 138 | (size < (maxlen - 1) && |
137 | (addr < INVENTORYDATASIZE)); addr++) { | 139 | (addr < INVENTORYDATASIZE)); addr++) { |
138 | size += sprintf((char *)string + size, "%c", | 140 | size += sprintf((char *)string + size, "%c", |
139 | convert_char (buf[addr])); | 141 | convert_char (buf[addr])); |
140 | } | 142 | } |
141 | 143 | ||
142 | /* | 144 | /* |
143 | * copy phase is done: check if everything is ok. If not, | 145 | * copy phase is done: check if everything is ok. If not, |
144 | * the inventory data is most probably corrupted: tell | 146 | * the inventory data is most probably corrupted: tell |
145 | * the world there is a problem! | 147 | * the world there is a problem! |
146 | */ | 148 | */ |
147 | if (addr == INVENTORYDATASIZE) { | 149 | if (addr == INVENTORYDATASIZE) { |
148 | xcode = -1; | 150 | xcode = -1; |
149 | printf("Error end of string not found\n"); | 151 | printf("Error end of string not found\n"); |
150 | } else if ((size > (maxlen - 1)) && | 152 | } else if ((size > (maxlen - 1)) && |
151 | (buf[addr] != '\r')) { | 153 | (buf[addr] != '\r')) { |
152 | xcode = -1; | 154 | xcode = -1; |
153 | printf("string too long till next CR\n"); | 155 | printf("string too long till next CR\n"); |
154 | } | 156 | } |
155 | } else { | 157 | } else { |
156 | /* | 158 | /* |
157 | * some CR are missing... | 159 | * some CR are missing... |
158 | * the inventory data is most probably corrupted | 160 | * the inventory data is most probably corrupted |
159 | */ | 161 | */ |
160 | xcode = -1; | 162 | xcode = -1; |
161 | printf("not enough cr found\n"); | 163 | printf("not enough cr found\n"); |
162 | } | 164 | } |
163 | return xcode; | 165 | return xcode; |
164 | } | 166 | } |
165 | 167 | ||
166 | #define GET_STRING(name, which, len) \ | 168 | #define GET_STRING(name, which, len) \ |
167 | if (ivm_findinventorystring(which, valbuf, len, buf) == 0) { \ | 169 | if (ivm_findinventorystring(which, valbuf, len, buf) == 0) { \ |
168 | ivm_set_value(name, (char *)valbuf); \ | 170 | ivm_set_value(name, (char *)valbuf); \ |
169 | } | 171 | } |
170 | 172 | ||
171 | static int ivm_check_crc(unsigned char *buf, int block) | 173 | static int ivm_check_crc(unsigned char *buf, int block) |
172 | { | 174 | { |
173 | unsigned long crc; | 175 | unsigned long crc; |
174 | unsigned long crceeprom; | 176 | unsigned long crceeprom; |
175 | 177 | ||
176 | crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2); | 178 | crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2); |
177 | crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \ | 179 | crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \ |
178 | buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256); | 180 | buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256); |
179 | if (crc != crceeprom) { | 181 | if (crc != crceeprom) { |
180 | if (block == 0) | 182 | if (block == 0) |
181 | printf("Error CRC Block: %d EEprom: calculated: \ | 183 | printf("Error CRC Block: %d EEprom: calculated: \ |
182 | %lx EEprom: %lx\n", block, crc, crceeprom); | 184 | %lx EEprom: %lx\n", block, crc, crceeprom); |
183 | return -1; | 185 | return -1; |
184 | } | 186 | } |
185 | return 0; | 187 | return 0; |
186 | } | 188 | } |
187 | 189 | ||
188 | static int calculate_mac_offset(unsigned char *valbuf, unsigned char *buf, | 190 | /* take care of the possible MAC address offset and the IVM content offset */ |
191 | static int process_mac(unsigned char *valbuf, unsigned char *buf, | ||
189 | int offset) | 192 | int offset) |
190 | { | 193 | { |
194 | unsigned char mac[6]; | ||
191 | unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6]; | 195 | unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6]; |
192 | 196 | ||
193 | if (offset == 0) | 197 | /* use an intermediate buffer, to not change IVM content |
194 | return 0; | 198 | * MAC address is at offset 1 |
199 | */ | ||
200 | memcpy(mac, buf+1, 6); | ||
195 | 201 | ||
196 | val += offset; | 202 | if (offset) { |
197 | buf[4] = (val >> 16) & 0xff; | 203 | val += offset; |
198 | buf[5] = (val >> 8) & 0xff; | 204 | mac[3] = (val >> 16) & 0xff; |
199 | buf[6] = val & 0xff; | 205 | mac[4] = (val >> 8) & 0xff; |
200 | sprintf((char *)valbuf, "%pM", buf + 1); | 206 | mac[5] = val & 0xff; |
207 | } | ||
208 | |||
209 | sprintf((char *)valbuf, "%pM", mac); | ||
201 | return 0; | 210 | return 0; |
202 | } | 211 | } |
203 | 212 | ||
204 | static int ivm_analyze_block2(unsigned char *buf, int len) | 213 | static int ivm_analyze_block2(unsigned char *buf, int len) |
205 | { | 214 | { |
206 | unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN]; | 215 | unsigned char valbuf[MAC_STR_SZ]; |
207 | unsigned long count; | 216 | unsigned long count; |
208 | 217 | ||
209 | /* IVM_MAC Adress begins at offset 1 */ | 218 | /* IVM_MAC Adress begins at offset 1 */ |
210 | sprintf((char *)valbuf, "%pM", buf + 1); | 219 | sprintf((char *)valbuf, "%pM", buf + 1); |
211 | ivm_set_value("IVM_MacAddress", (char *)valbuf); | 220 | ivm_set_value("IVM_MacAddress", (char *)valbuf); |
212 | /* if an offset is defined, add it */ | ||
213 | calculate_mac_offset(buf, valbuf, CONFIG_PIGGY_MAC_ADRESS_OFFSET); | ||
214 | #ifdef MACH_TYPE_KM_KIRKWOOD | ||
215 | setenv((char *)"ethaddr", (char *)valbuf); | ||
216 | #else | ||
217 | if (getenv("ethaddr") == NULL) | ||
218 | setenv((char *)"ethaddr", (char *)valbuf); | ||
219 | #endif | ||
220 | #ifdef CONFIG_KMVECT1 | ||
221 | /* KMVECT1 has two ethernet interfaces */ | ||
222 | if (getenv("eth1addr") == NULL) { | ||
223 | calculate_mac_offset(buf, valbuf, 1); | ||
224 | setenv((char *)"eth1addr", (char *)valbuf); | ||
225 | } | ||
226 | #endif | ||
227 | /* IVM_MacCount */ | 221 | /* IVM_MacCount */ |
228 | count = (buf[10] << 24) + | 222 | count = (buf[10] << 24) + |
229 | (buf[11] << 16) + | 223 | (buf[11] << 16) + |
230 | (buf[12] << 8) + | 224 | (buf[12] << 8) + |
231 | buf[13]; | 225 | buf[13]; |
232 | if (count == 0xffffffff) | 226 | if (count == 0xffffffff) |
233 | count = 1; | 227 | count = 1; |
234 | sprintf((char *)valbuf, "%lx", count); | 228 | sprintf((char *)valbuf, "%lx", count); |
235 | ivm_set_value("IVM_MacCount", (char *)valbuf); | 229 | ivm_set_value("IVM_MacCount", (char *)valbuf); |
236 | return 0; | 230 | return 0; |
237 | } | 231 | } |
238 | 232 | ||
239 | static int ivm_analyze_eeprom(unsigned char *buf, int len) | 233 | int ivm_analyze_eeprom(unsigned char *buf, int len) |
240 | { | 234 | { |
241 | unsigned short val; | 235 | unsigned short val; |
242 | unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN]; | 236 | unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN]; |
243 | unsigned char *tmp; | 237 | unsigned char *tmp; |
244 | 238 | ||
245 | if (ivm_check_crc(buf, 0) != 0) | 239 | if (ivm_check_crc(buf, 0) != 0) |
246 | return -1; | 240 | return -1; |
247 | 241 | ||
248 | ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, | 242 | ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, |
249 | "IVM_BoardId", 0, 1); | 243 | "IVM_BoardId", 0, 1); |
250 | val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, | 244 | val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, |
251 | "IVM_HWKey", 6, 1); | 245 | "IVM_HWKey", 6, 1); |
252 | if (val != 0xffff) { | 246 | if (val != 0xffff) { |
253 | sprintf((char *)valbuf, "%x", ((val / 100) % 10)); | 247 | sprintf((char *)valbuf, "%x", ((val / 100) % 10)); |
254 | ivm_set_value("IVM_HWVariant", (char *)valbuf); | 248 | ivm_set_value("IVM_HWVariant", (char *)valbuf); |
255 | sprintf((char *)valbuf, "%x", (val % 100)); | 249 | sprintf((char *)valbuf, "%x", (val % 100)); |
256 | ivm_set_value("IVM_HWVersion", (char *)valbuf); | 250 | ivm_set_value("IVM_HWVersion", (char *)valbuf); |
257 | } | 251 | } |
258 | ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, | 252 | ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN, |
259 | "IVM_Functions", 12, 0); | 253 | "IVM_Functions", 12, 0); |
260 | 254 | ||
261 | GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8) | 255 | GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8) |
262 | GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64) | 256 | GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64) |
263 | tmp = (unsigned char *) getenv("IVM_DeviceName"); | 257 | tmp = (unsigned char *) getenv("IVM_DeviceName"); |
264 | if (tmp) { | 258 | if (tmp) { |
265 | int len = strlen((char *)tmp); | 259 | int len = strlen((char *)tmp); |
266 | int i = 0; | 260 | int i = 0; |
267 | 261 | ||
268 | while (i < len) { | 262 | while (i < len) { |
269 | if (tmp[i] == ';') { | 263 | if (tmp[i] == ';') { |
270 | ivm_set_value("IVM_ShortText", | 264 | ivm_set_value("IVM_ShortText", |
271 | (char *)&tmp[i + 1]); | 265 | (char *)&tmp[i + 1]); |
272 | break; | 266 | break; |
273 | } | 267 | } |
274 | i++; | 268 | i++; |
275 | } | 269 | } |
276 | if (i >= len) | 270 | if (i >= len) |
277 | ivm_set_value("IVM_ShortText", NULL); | 271 | ivm_set_value("IVM_ShortText", NULL); |
278 | } else { | 272 | } else { |
279 | ivm_set_value("IVM_ShortText", NULL); | 273 | ivm_set_value("IVM_ShortText", NULL); |
280 | } | 274 | } |
281 | GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32) | 275 | GET_STRING("IVM_ManufacturerID", IVM_POS_MANU_ID, 32) |
282 | GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20) | 276 | GET_STRING("IVM_ManufacturerSerialNumber", IVM_POS_MANU_SERIAL, 20) |
283 | GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32) | 277 | GET_STRING("IVM_ManufacturerPartNumber", IVM_POS_PART_NUMBER, 32) |
284 | GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32) | 278 | GET_STRING("IVM_ManufacturerBuildState", IVM_POS_BUILD_STATE, 32) |
285 | GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32) | 279 | GET_STRING("IVM_SupplierPartNumber", IVM_POS_SUPPLIER_PART_NUMBER, 32) |
286 | GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32) | 280 | GET_STRING("IVM_DelieveryDate", IVM_POS_DELIVERY_DATE, 32) |
287 | GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32) | 281 | GET_STRING("IVM_SupplierBuildState", IVM_POS_SUPPLIER_BUILD_STATE, 32) |
288 | GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32) | 282 | GET_STRING("IVM_CustomerID", IVM_POS_CUSTOMER_ID, 32) |
289 | GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32) | 283 | GET_STRING("IVM_CustomerProductID", IVM_POS_CUSTOMER_PROD_ID, 32) |
290 | 284 | ||
291 | if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0) | 285 | if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0) |
292 | return 0; | 286 | return 0; |
293 | ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], | 287 | ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], |
294 | CONFIG_SYS_IVM_EEPROM_PAGE_LEN); | 288 | CONFIG_SYS_IVM_EEPROM_PAGE_LEN); |
295 | 289 | ||
296 | return 0; | 290 | return 0; |
291 | } | ||
292 | |||
293 | static int ivm_populate_env(unsigned char *buf, int len) | ||
294 | { | ||
295 | unsigned char *page2; | ||
296 | unsigned char valbuf[MAC_STR_SZ]; | ||
297 | |||
298 | /* do we have the page 2 filled ? if not return */ | ||
299 | if (ivm_check_crc(buf, 2)) | ||
300 | return 0; | ||
301 | page2 = &buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN*2]; | ||
302 | |||
303 | /* if an offset is defined, add it */ | ||
304 | process_mac(valbuf, page2, CONFIG_PIGGY_MAC_ADRESS_OFFSET); | ||
305 | if (getenv("ethaddr") == NULL) | ||
306 | setenv((char *)"ethaddr", (char *)valbuf); | ||
307 | #ifdef CONFIG_KMVECT1 | ||
308 | /* KMVECT1 has two ethernet interfaces */ | ||
309 | if (getenv("eth1addr") == NULL) { | ||
310 | process_mac(valbuf, page2, 1); | ||
311 | setenv((char *)"eth1addr", (char *)valbuf); | ||
312 | } | ||
313 | #endif | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | int ivm_simple_read_eeprom(unsigned char *buf, int len) | ||
319 | { | ||
320 | int ret; | ||
321 | |||
322 | i2c_set_bus_num(CONFIG_KM_IVM_BUS); | ||
323 | /* add deblocking here */ | ||
324 | i2c_make_abort(); | ||
325 | |||
326 | ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, buf, len); | ||
327 | if (ret != 0) { | ||
328 | printf("Error reading EEprom\n"); | ||
329 | return -2; | ||
330 | } | ||
331 | |||
332 | return ivm_populate_env(buf, len); | ||
297 | } | 333 | } |
298 | 334 | ||
299 | int ivm_read_eeprom(void) | 335 | int ivm_read_eeprom(void) |
300 | { | 336 | { |
301 | uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN]; | 337 | uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN]; |
302 | int ret; | 338 | int ret; |