1689be5f8SIgor Grinberg /* 2689be5f8SIgor Grinberg * (C) Copyright 2011 CompuLab, Ltd. <www.compulab.co.il> 3689be5f8SIgor Grinberg * 4689be5f8SIgor Grinberg * Authors: Nikita Kiryanov <nikita@compulab.co.il> 5689be5f8SIgor Grinberg * Igor Grinberg <grinberg@compulab.co.il> 6689be5f8SIgor Grinberg * 7689be5f8SIgor Grinberg * SPDX-License-Identifier: GPL-2.0+ 8689be5f8SIgor Grinberg */ 9689be5f8SIgor Grinberg 10689be5f8SIgor Grinberg #include <common.h> 11689be5f8SIgor Grinberg #include <i2c.h> 12689be5f8SIgor Grinberg 13*d3f041c0SIgor Grinberg #ifndef CONFIG_SYS_I2C_EEPROM_ADDR 14*d3f041c0SIgor Grinberg # define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 15*d3f041c0SIgor Grinberg # define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 16*d3f041c0SIgor Grinberg #endif 17*d3f041c0SIgor Grinberg 18689be5f8SIgor Grinberg #define EEPROM_LAYOUT_VER_OFFSET 44 19689be5f8SIgor Grinberg #define BOARD_SERIAL_OFFSET 20 20689be5f8SIgor Grinberg #define BOARD_SERIAL_OFFSET_LEGACY 8 21689be5f8SIgor Grinberg #define BOARD_REV_OFFSET 0 22689be5f8SIgor Grinberg #define BOARD_REV_OFFSET_LEGACY 6 23689be5f8SIgor Grinberg #define BOARD_REV_SIZE 2 24689be5f8SIgor Grinberg #define MAC_ADDR_OFFSET 4 25689be5f8SIgor Grinberg #define MAC_ADDR_OFFSET_LEGACY 0 26689be5f8SIgor Grinberg 27689be5f8SIgor Grinberg #define LAYOUT_INVALID 0 28689be5f8SIgor Grinberg #define LAYOUT_LEGACY 0xff 29689be5f8SIgor Grinberg 30689be5f8SIgor Grinberg static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */ 31689be5f8SIgor Grinberg 32689be5f8SIgor Grinberg static int cl_eeprom_read(uint offset, uchar *buf, int len) 33689be5f8SIgor Grinberg { 34689be5f8SIgor Grinberg return i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset, 35689be5f8SIgor Grinberg CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len); 36689be5f8SIgor Grinberg } 37689be5f8SIgor Grinberg 38689be5f8SIgor Grinberg static int cl_eeprom_setup_layout(void) 39689be5f8SIgor Grinberg { 40689be5f8SIgor Grinberg int res; 41689be5f8SIgor Grinberg 42689be5f8SIgor Grinberg if (cl_eeprom_layout != LAYOUT_INVALID) 43689be5f8SIgor Grinberg return 0; 44689be5f8SIgor Grinberg 45689be5f8SIgor Grinberg res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET, 46689be5f8SIgor Grinberg (uchar *)&cl_eeprom_layout, 1); 47689be5f8SIgor Grinberg if (res) { 48689be5f8SIgor Grinberg cl_eeprom_layout = LAYOUT_INVALID; 49689be5f8SIgor Grinberg return res; 50689be5f8SIgor Grinberg } 51689be5f8SIgor Grinberg 52689be5f8SIgor Grinberg if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20) 53689be5f8SIgor Grinberg cl_eeprom_layout = LAYOUT_LEGACY; 54689be5f8SIgor Grinberg 55689be5f8SIgor Grinberg return 0; 56689be5f8SIgor Grinberg } 57689be5f8SIgor Grinberg 58689be5f8SIgor Grinberg void get_board_serial(struct tag_serialnr *serialnr) 59689be5f8SIgor Grinberg { 60689be5f8SIgor Grinberg u32 serial[2]; 61689be5f8SIgor Grinberg uint offset; 62689be5f8SIgor Grinberg 63689be5f8SIgor Grinberg memset(serialnr, 0, sizeof(*serialnr)); 64689be5f8SIgor Grinberg 65689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 66689be5f8SIgor Grinberg return; 67689be5f8SIgor Grinberg 68689be5f8SIgor Grinberg offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? 69689be5f8SIgor Grinberg BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY; 70689be5f8SIgor Grinberg 71689be5f8SIgor Grinberg if (cl_eeprom_read(offset, (uchar *)serial, 8)) 72689be5f8SIgor Grinberg return; 73689be5f8SIgor Grinberg 74689be5f8SIgor Grinberg if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) { 75689be5f8SIgor Grinberg serialnr->low = serial[0]; 76689be5f8SIgor Grinberg serialnr->high = serial[1]; 77689be5f8SIgor Grinberg } 78689be5f8SIgor Grinberg } 79689be5f8SIgor Grinberg 80689be5f8SIgor Grinberg /* 81689be5f8SIgor Grinberg * Routine: cl_eeprom_read_mac_addr 82689be5f8SIgor Grinberg * Description: read mac address and store it in buf. 83689be5f8SIgor Grinberg */ 84689be5f8SIgor Grinberg int cl_eeprom_read_mac_addr(uchar *buf) 85689be5f8SIgor Grinberg { 86689be5f8SIgor Grinberg uint offset; 87689be5f8SIgor Grinberg 88689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 89689be5f8SIgor Grinberg return 0; 90689be5f8SIgor Grinberg 91689be5f8SIgor Grinberg offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? 92689be5f8SIgor Grinberg MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY; 93689be5f8SIgor Grinberg 94689be5f8SIgor Grinberg return cl_eeprom_read(offset, buf, 6); 95689be5f8SIgor Grinberg } 96689be5f8SIgor Grinberg 97689be5f8SIgor Grinberg /* 98689be5f8SIgor Grinberg * Routine: cl_eeprom_get_board_rev 99689be5f8SIgor Grinberg * Description: read system revision from eeprom 100689be5f8SIgor Grinberg */ 101689be5f8SIgor Grinberg u32 cl_eeprom_get_board_rev(void) 102689be5f8SIgor Grinberg { 103689be5f8SIgor Grinberg u32 rev = 0; 104689be5f8SIgor Grinberg char str[5]; /* Legacy representation can contain at most 4 digits */ 105689be5f8SIgor Grinberg uint offset = BOARD_REV_OFFSET_LEGACY; 106689be5f8SIgor Grinberg 107689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 108689be5f8SIgor Grinberg return 0; 109689be5f8SIgor Grinberg 110689be5f8SIgor Grinberg if (cl_eeprom_layout != LAYOUT_LEGACY) 111689be5f8SIgor Grinberg offset = BOARD_REV_OFFSET; 112689be5f8SIgor Grinberg 113689be5f8SIgor Grinberg if (cl_eeprom_read(offset, (uchar *)&rev, BOARD_REV_SIZE)) 114689be5f8SIgor Grinberg return 0; 115689be5f8SIgor Grinberg 116689be5f8SIgor Grinberg /* 117689be5f8SIgor Grinberg * Convert legacy syntactic representation to semantic 118689be5f8SIgor Grinberg * representation. i.e. for rev 1.00: 0x100 --> 0x64 119689be5f8SIgor Grinberg */ 120689be5f8SIgor Grinberg if (cl_eeprom_layout == LAYOUT_LEGACY) { 121689be5f8SIgor Grinberg sprintf(str, "%x", rev); 122689be5f8SIgor Grinberg rev = simple_strtoul(str, NULL, 10); 123689be5f8SIgor Grinberg } 124689be5f8SIgor Grinberg 125689be5f8SIgor Grinberg return rev; 126689be5f8SIgor Grinberg }; 127