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 13d3f041c0SIgor Grinberg #ifndef CONFIG_SYS_I2C_EEPROM_ADDR 14d3f041c0SIgor Grinberg # define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 15d3f041c0SIgor Grinberg # define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 1 16d3f041c0SIgor Grinberg #endif 17d3f041c0SIgor Grinberg 18*7d2f669bSNikita Kiryanov #ifndef CONFIG_SYS_I2C_EEPROM_BUS 19*7d2f669bSNikita Kiryanov #define CONFIG_SYS_I2C_EEPROM_BUS 0 20*7d2f669bSNikita Kiryanov #endif 21*7d2f669bSNikita Kiryanov 22689be5f8SIgor Grinberg #define EEPROM_LAYOUT_VER_OFFSET 44 23689be5f8SIgor Grinberg #define BOARD_SERIAL_OFFSET 20 24689be5f8SIgor Grinberg #define BOARD_SERIAL_OFFSET_LEGACY 8 25689be5f8SIgor Grinberg #define BOARD_REV_OFFSET 0 26689be5f8SIgor Grinberg #define BOARD_REV_OFFSET_LEGACY 6 27689be5f8SIgor Grinberg #define BOARD_REV_SIZE 2 28689be5f8SIgor Grinberg #define MAC_ADDR_OFFSET 4 29689be5f8SIgor Grinberg #define MAC_ADDR_OFFSET_LEGACY 0 30689be5f8SIgor Grinberg 31689be5f8SIgor Grinberg #define LAYOUT_INVALID 0 32689be5f8SIgor Grinberg #define LAYOUT_LEGACY 0xff 33689be5f8SIgor Grinberg 34689be5f8SIgor Grinberg static int cl_eeprom_layout; /* Implicitly LAYOUT_INVALID */ 35689be5f8SIgor Grinberg 36689be5f8SIgor Grinberg static int cl_eeprom_read(uint offset, uchar *buf, int len) 37689be5f8SIgor Grinberg { 3852658fdaSNikita Kiryanov int res; 3952658fdaSNikita Kiryanov unsigned int current_i2c_bus = i2c_get_bus_num(); 4052658fdaSNikita Kiryanov 4152658fdaSNikita Kiryanov res = i2c_set_bus_num(CONFIG_SYS_I2C_EEPROM_BUS); 4252658fdaSNikita Kiryanov if (res < 0) 4352658fdaSNikita Kiryanov return res; 4452658fdaSNikita Kiryanov 4552658fdaSNikita Kiryanov res = i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, offset, 46689be5f8SIgor Grinberg CONFIG_SYS_I2C_EEPROM_ADDR_LEN, buf, len); 4752658fdaSNikita Kiryanov 4852658fdaSNikita Kiryanov i2c_set_bus_num(current_i2c_bus); 4952658fdaSNikita Kiryanov 5052658fdaSNikita Kiryanov return res; 51689be5f8SIgor Grinberg } 52689be5f8SIgor Grinberg 53689be5f8SIgor Grinberg static int cl_eeprom_setup_layout(void) 54689be5f8SIgor Grinberg { 55689be5f8SIgor Grinberg int res; 56689be5f8SIgor Grinberg 57689be5f8SIgor Grinberg if (cl_eeprom_layout != LAYOUT_INVALID) 58689be5f8SIgor Grinberg return 0; 59689be5f8SIgor Grinberg 60689be5f8SIgor Grinberg res = cl_eeprom_read(EEPROM_LAYOUT_VER_OFFSET, 61689be5f8SIgor Grinberg (uchar *)&cl_eeprom_layout, 1); 62689be5f8SIgor Grinberg if (res) { 63689be5f8SIgor Grinberg cl_eeprom_layout = LAYOUT_INVALID; 64689be5f8SIgor Grinberg return res; 65689be5f8SIgor Grinberg } 66689be5f8SIgor Grinberg 67689be5f8SIgor Grinberg if (cl_eeprom_layout == 0 || cl_eeprom_layout >= 0x20) 68689be5f8SIgor Grinberg cl_eeprom_layout = LAYOUT_LEGACY; 69689be5f8SIgor Grinberg 70689be5f8SIgor Grinberg return 0; 71689be5f8SIgor Grinberg } 72689be5f8SIgor Grinberg 73689be5f8SIgor Grinberg void get_board_serial(struct tag_serialnr *serialnr) 74689be5f8SIgor Grinberg { 75689be5f8SIgor Grinberg u32 serial[2]; 76689be5f8SIgor Grinberg uint offset; 77689be5f8SIgor Grinberg 78689be5f8SIgor Grinberg memset(serialnr, 0, sizeof(*serialnr)); 79689be5f8SIgor Grinberg 80689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 81689be5f8SIgor Grinberg return; 82689be5f8SIgor Grinberg 83689be5f8SIgor Grinberg offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? 84689be5f8SIgor Grinberg BOARD_SERIAL_OFFSET : BOARD_SERIAL_OFFSET_LEGACY; 85689be5f8SIgor Grinberg 86689be5f8SIgor Grinberg if (cl_eeprom_read(offset, (uchar *)serial, 8)) 87689be5f8SIgor Grinberg return; 88689be5f8SIgor Grinberg 89689be5f8SIgor Grinberg if (serial[0] != 0xffffffff && serial[1] != 0xffffffff) { 90689be5f8SIgor Grinberg serialnr->low = serial[0]; 91689be5f8SIgor Grinberg serialnr->high = serial[1]; 92689be5f8SIgor Grinberg } 93689be5f8SIgor Grinberg } 94689be5f8SIgor Grinberg 95689be5f8SIgor Grinberg /* 96689be5f8SIgor Grinberg * Routine: cl_eeprom_read_mac_addr 97689be5f8SIgor Grinberg * Description: read mac address and store it in buf. 98689be5f8SIgor Grinberg */ 99689be5f8SIgor Grinberg int cl_eeprom_read_mac_addr(uchar *buf) 100689be5f8SIgor Grinberg { 101689be5f8SIgor Grinberg uint offset; 102689be5f8SIgor Grinberg 103689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 104689be5f8SIgor Grinberg return 0; 105689be5f8SIgor Grinberg 106689be5f8SIgor Grinberg offset = (cl_eeprom_layout != LAYOUT_LEGACY) ? 107689be5f8SIgor Grinberg MAC_ADDR_OFFSET : MAC_ADDR_OFFSET_LEGACY; 108689be5f8SIgor Grinberg 109689be5f8SIgor Grinberg return cl_eeprom_read(offset, buf, 6); 110689be5f8SIgor Grinberg } 111689be5f8SIgor Grinberg 112689be5f8SIgor Grinberg /* 113689be5f8SIgor Grinberg * Routine: cl_eeprom_get_board_rev 114689be5f8SIgor Grinberg * Description: read system revision from eeprom 115689be5f8SIgor Grinberg */ 116689be5f8SIgor Grinberg u32 cl_eeprom_get_board_rev(void) 117689be5f8SIgor Grinberg { 118689be5f8SIgor Grinberg u32 rev = 0; 119689be5f8SIgor Grinberg char str[5]; /* Legacy representation can contain at most 4 digits */ 120689be5f8SIgor Grinberg uint offset = BOARD_REV_OFFSET_LEGACY; 121689be5f8SIgor Grinberg 122689be5f8SIgor Grinberg if (cl_eeprom_setup_layout()) 123689be5f8SIgor Grinberg return 0; 124689be5f8SIgor Grinberg 125689be5f8SIgor Grinberg if (cl_eeprom_layout != LAYOUT_LEGACY) 126689be5f8SIgor Grinberg offset = BOARD_REV_OFFSET; 127689be5f8SIgor Grinberg 128689be5f8SIgor Grinberg if (cl_eeprom_read(offset, (uchar *)&rev, BOARD_REV_SIZE)) 129689be5f8SIgor Grinberg return 0; 130689be5f8SIgor Grinberg 131689be5f8SIgor Grinberg /* 132689be5f8SIgor Grinberg * Convert legacy syntactic representation to semantic 133689be5f8SIgor Grinberg * representation. i.e. for rev 1.00: 0x100 --> 0x64 134689be5f8SIgor Grinberg */ 135689be5f8SIgor Grinberg if (cl_eeprom_layout == LAYOUT_LEGACY) { 136689be5f8SIgor Grinberg sprintf(str, "%x", rev); 137689be5f8SIgor Grinberg rev = simple_strtoul(str, NULL, 10); 138689be5f8SIgor Grinberg } 139689be5f8SIgor Grinberg 140689be5f8SIgor Grinberg return rev; 141689be5f8SIgor Grinberg }; 142