]>
Commit | Line | Data |
---|---|---|
82309250 NK |
1 | /* |
2 | * (C) Copyright 2011 CompuLab, Ltd. <www.compulab.co.il> | |
3 | * | |
4 | * Authors: Nikita Kiryanov <nikita@compulab.co.il> | |
5 | * Igor Grinberg <grinberg@compulab.co.il> | |
6 | * | |
1a459660 | 7 | * SPDX-License-Identifier: GPL-2.0+ |
82309250 NK |
8 | */ |
9 | ||
10 | #include <common.h> | |
11 | #include <i2c.h> | |
12 | ||
d3f041c0 IG |
13 | #ifndef CONFIG_SYS_I2C_EEPROM_ADDR |
14 | # define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 | |
15 | # define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 | |
16 | #endif | |
17 | ||
7d2f669b NK |
18 | #ifndef CONFIG_SYS_I2C_EEPROM_BUS |
19 | #define CONFIG_SYS_I2C_EEPROM_BUS 0 | |
20 | #endif | |
21 | ||
82309250 NK |
22 | #define EEPROM_LAYOUT_VER_OFFSET 44 |
23 | #define BOARD_SERIAL_OFFSET 20 | |
24 | #define BOARD_SERIAL_OFFSET_LEGACY 8 | |
7d3c97d7 NK |
25 | #define BOARD_REV_OFFSET 0 |
26 | #define BOARD_REV_OFFSET_LEGACY 6 | |
6f3b300c | 27 | #define BOARD_REV_SIZE 2 |
e4e2bf5e NK |
28 | #define MAC_ADDR_OFFSET 4 |
29 | #define MAC_ADDR_OFFSET_LEGACY 0 | |
82309250 NK |
30 | |
31 | #define LAYOUT_INVALID 0 | |
32 | #define LAYOUT_LEGACY 0xff | |
33 | ||
689be5f8 | 34 | static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */ |
82309250 | 35 | |
689be5f8 | 36 | static int cl_eeprom_read(uint offset, uchar *buf, int len) |
82309250 | 37 | { |
52658fda NK |
38 | int res; |
39 | unsigned int current_i2c_bus = i2c_get_bus_num(); | |
40 | ||
41 | res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); | |
42 | if (res < 0) | |
43 | return res; | |
44 | ||
45 | res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset, | |
82309250 | 46 | CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len); |
52658fda NK |
47 | |
48 | i2c_set_bus_num(current_i2c_bus); | |
49 | ||
50 | return res; | |
82309250 NK |
51 | } |
52 | ||
689be5f8 | 53 | static int cl_eeprom_setup_layout(void) |
82309250 NK |
54 | { |
55 | int res; | |
56 | ||
689be5f8 | 57 | if (cl_eeprom_layout != LAYOUT_INVALID) |
82309250 NK |
58 | return 0; |
59 | ||
689be5f8 IG |
60 | res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET, |
61 | (uchar *)&cl_eeprom_layout, 1); | |
82309250 | 62 | if (res) { |
689be5f8 | 63 | cl_eeprom_layout = LAYOUT_INVALID; |
82309250 NK |
64 | return res; |
65 | } | |
66 | ||
689be5f8 IG |
67 | if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20) |
68 | cl_eeprom_layout = LAYOUT_LEGACY; | |
82309250 NK |
69 | |
70 | return 0; | |
71 | } | |
72 | ||
73 | void get_board_serial(struct tag_serialnr *serialnr) | |
74 | { | |
75 | u32 serial[2]; | |
76 | uint offset; | |
77 | ||
78 | memset(serialnr, 0, sizeof(*serialnr)); | |
689be5f8 IG |
79 | |
80 | if (cl_eeprom_setup_layout()) | |
82309250 NK |
81 | return; |
82 | ||
689be5f8 IG |
83 | offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? |
84 | BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY; | |
85 | ||
86 | if (cl_eeprom_read(offset, (uchar *)serial, 8)) | |
82309250 NK |
87 | return; |
88 | ||
89 | if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) { | |
90 | serialnr->low = serial[0]; | |
91 | serialnr->high = serial[1]; | |
92 | } | |
93 | } | |
7d3c97d7 | 94 | |
e4e2bf5e | 95 | /* |
689be5f8 | 96 | * Routine: cl_eeprom_read_mac_addr |
e4e2bf5e NK |
97 | * Description: read mac address and store it in buf. |
98 | */ | |
689be5f8 | 99 | int cl_eeprom_read_mac_addr(uchar *buf) |
e4e2bf5e NK |
100 | { |
101 | uint offset; | |
102 | ||
689be5f8 | 103 | if (cl_eeprom_setup_layout()) |
e4e2bf5e NK |
104 | return 0; |
105 | ||
689be5f8 | 106 | offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? |
e4e2bf5e | 107 | MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY; |
689be5f8 IG |
108 | |
109 | return cl_eeprom_read(offset, buf, 6); | |
e4e2bf5e NK |
110 | } |
111 | ||
a937fd16 IG |
112 | static u32 board_rev; |
113 | ||
7d3c97d7 | 114 | /* |
689be5f8 | 115 | * Routine: cl_eeprom_get_board_rev |
8c318eb3 | 116 | * Description: read system revision from eeprom |
7d3c97d7 | 117 | */ |
689be5f8 | 118 | u32 cl_eeprom_get_board_rev(void) |
7d3c97d7 | 119 | { |
2ef6302f | 120 | char str[5]; /* Legacy representation can contain at most 4 digits */ |
7d3c97d7 | 121 | uint offset = BOARD_REV_OFFSET_LEGACY; |
7d3c97d7 | 122 | |
a937fd16 IG |
123 | if (board_rev) |
124 | return board_rev; | |
125 | ||
689be5f8 | 126 | if (cl_eeprom_setup_layout()) |
7d3c97d7 NK |
127 | return 0; |
128 | ||
689be5f8 | 129 | if (cl_eeprom_layout != LAYOUT_LEGACY) |
7d3c97d7 | 130 | offset = BOARD_REV_OFFSET; |
7d3c97d7 | 131 | |
a937fd16 | 132 | if (cl_eeprom_read(offset, (uchar *)&board_rev, BOARD_REV_SIZE)) |
7d3c97d7 NK |
133 | return 0; |
134 | ||
2ef6302f NK |
135 | /* |
136 | * Convert legacy syntactic representation to semantic | |
137 | * representation. i.e. for rev 1.00: 0x100 --> 0x64 | |
138 | */ | |
689be5f8 | 139 | if (cl_eeprom_layout == LAYOUT_LEGACY) { |
a937fd16 IG |
140 | sprintf(str, "%x", board_rev); |
141 | board_rev = simple_strtoul(str, NULL, 10); | |
2ef6302f NK |
142 | } |
143 | ||
a937fd16 | 144 | return board_rev; |
7d3c97d7 | 145 | }; |