]> git.sur5r.net Git - u-boot/blob - board/compulab/common/eeprom.c
Merge branch 'master' of git://git.denx.de/u-boot-atmel
[u-boot] / board / compulab / common / eeprom.c
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  *
7  * SPDX-License-Identifier:     GPL-2.0+
8  */
9
10 #include <common.h>
11 #include <i2c.h>
12
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
18 #ifndef CONFIG_SYS_I2C_EEPROM_BUS
19 #define CONFIG_SYS_I2C_EEPROM_BUS       0
20 #endif
21
22 #define EEPROM_LAYOUT_VER_OFFSET        44
23 #define BOARD_SERIAL_OFFSET             20
24 #define BOARD_SERIAL_OFFSET_LEGACY      8
25 #define BOARD_REV_OFFSET                0
26 #define BOARD_REV_OFFSET_LEGACY         6
27 #define BOARD_REV_SIZE                  2
28 #define MAC_ADDR_OFFSET                 4
29 #define MAC_ADDR_OFFSET_LEGACY          0
30
31 #define LAYOUT_INVALID  0
32 #define LAYOUT_LEGACY   0xff
33
34 static int cl_eeprom_bus;
35 static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */
36
37 static int cl_eeprom_read(uint offset, uchar *buf, int len)
38 {
39         int res;
40         unsigned int current_i2c_bus = i2c_get_bus_num();
41
42         res = i2c_set_bus_num(cl_eeprom_bus);
43         if (res < 0)
44                 return res;
45
46         res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset,
47                         CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len);
48
49         i2c_set_bus_num(current_i2c_bus);
50
51         return res;
52 }
53
54 static int cl_eeprom_setup(uint eeprom_bus)
55 {
56         int res;
57
58         /*
59          * We know the setup was already done when the layout is set to a valid
60          * value and we're using the same bus as before.
61          */
62         if (cl_eeprom_layout != LAYOUT_INVALID && eeprom_bus == cl_eeprom_bus)
63                 return 0;
64
65         cl_eeprom_bus = eeprom_bus;
66         res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET,
67                              (uchar *)&cl_eeprom_layout, 1);
68         if (res) {
69                 cl_eeprom_layout = LAYOUT_INVALID;
70                 return res;
71         }
72
73         if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20)
74                 cl_eeprom_layout = LAYOUT_LEGACY;
75
76         return 0;
77 }
78
79 void get_board_serial(struct tag_serialnr *serialnr)
80 {
81         u32 serial[2];
82         uint offset;
83
84         memset(serialnr, 0, sizeof(*serialnr));
85
86         if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
87                 return;
88
89         offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
90                 BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY;
91
92         if (cl_eeprom_read(offset, (uchar *)serial, 8))
93                 return;
94
95         if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) {
96                 serialnr->low = serial[0];
97                 serialnr->high = serial[1];
98         }
99 }
100
101 /*
102  * Routine: cl_eeprom_read_mac_addr
103  * Description: read mac address and store it in buf.
104  */
105 int cl_eeprom_read_mac_addr(uchar *buf, uint eeprom_bus)
106 {
107         uint offset;
108
109         if (cl_eeprom_setup(eeprom_bus))
110                 return 0;
111
112         offset = (cl_eeprom_layout != LAYOUT_LEGACY) ?
113                         MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY;
114
115         return cl_eeprom_read(offset, buf, 6);
116 }
117
118 static u32 board_rev;
119
120 /*
121  * Routine: cl_eeprom_get_board_rev
122  * Description: read system revision from eeprom
123  */
124 u32 cl_eeprom_get_board_rev(void)
125 {
126         char str[5]; /* Legacy representation can contain at most 4 digits */
127         uint offset = BOARD_REV_OFFSET_LEGACY;
128
129         if (board_rev)
130                 return board_rev;
131
132         if (cl_eeprom_setup(CONFIG_SYS_I2C_EEPROM_BUS))
133                 return 0;
134
135         if (cl_eeprom_layout != LAYOUT_LEGACY)
136                 offset = BOARD_REV_OFFSET;
137
138         if (cl_eeprom_read(offset, (uchar *)&board_rev, BOARD_REV_SIZE))
139                 return 0;
140
141         /*
142          * Convert legacy syntactic representation to semantic
143          * representation. i.e. for rev 1.00: 0x100 --> 0x64
144          */
145         if (cl_eeprom_layout == LAYOUT_LEGACY) {
146                 sprintf(str, "%x", board_rev);
147                 board_rev = simple_strtoul(str, NULL, 10);
148         }
149
150         return board_rev;
151 };