diff options
-rw-r--r-- | arch/arm/cpu/armv7/omap4/sys_info.c | 41 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-omap4/cpu.h | 12 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-omap4/sys_proto.h | 1 | ||||
-rw-r--r-- | board/ti/panda/panda.c | 18 |
4 files changed, 72 insertions, 0 deletions
diff --git a/arch/arm/cpu/armv7/omap4/sys_info.c b/arch/arm/cpu/armv7/omap4/sys_info.c index b9e57659f..7800d180a 100644 --- a/arch/arm/cpu/armv7/omap4/sys_info.c +++ b/arch/arm/cpu/armv7/omap4/sys_info.c @@ -23,6 +23,7 @@ */ #include <common.h> +#include <asm/io.h> #include <asm/arch/sys_proto.h> /* @@ -51,3 +52,43 @@ int print_cpuinfo(void) return 0; } + +/* + * this uses the unique per-cpu info from the cpu fuses set at factory to + * generate a 6-byte MAC address. Two bits in the generated code are used + * to elaborate the generated address into four, so it can be used on multiple + * network interfaces. + */ + +void omap4_die_id_to_ethernet_mac(u8 *mac, int subtype) +{ + struct ctrl_id *id_base = (struct ctrl_id *)(CTRL_BASE + 0x200); + u32 idcode; + u32 id[4]; + + idcode = readl(&id_base->idcode); + id[0] = readl(&id_base->die_id_0); + id[1] = readl(&id_base->die_id_1); + id[2] = readl(&id_base->die_id_2); + id[3] = readl(&id_base->die_id_3); + + mac[0] = id[2]; + mac[1] = id[2] >> 8; + mac[2] = id[1]; + mac[3] = id[1] >> 8; + mac[4] = id[1] >> 16; + mac[5] = id[1] >> 24; + /* XOR other chip-specific data with ID */ + idcode ^= id[3]; + + mac[0] ^= idcode; + mac[1] ^= idcode >> 8; + mac[2] ^= idcode >> 16; + mac[3] ^= idcode >> 24; + + /* allow four MACs from this same basic data */ + mac[1] = (mac[1] & ~0xc0) | ((subtype & 3) << 6); + + /* mark it as not multicast and outside official 80211 MAC namespace */ + mac[0] = (mac[0] & ~1) | 2; +} diff --git a/arch/arm/include/asm/arch-omap4/cpu.h b/arch/arm/include/asm/arch-omap4/cpu.h index 08b9c9935..f80701c76 100644 --- a/arch/arm/include/asm/arch-omap4/cpu.h +++ b/arch/arm/include/asm/arch-omap4/cpu.h @@ -94,6 +94,18 @@ struct gptimer { u32 tcicr; /* 0x40 rw */ u32 tcar2; /* 0x44 r */ }; + +struct ctrl_id { + u32 die_id_0; /* 0x00 */ + u32 idcode; /* 0x04 */ + u32 die_id_1; /* 0x08 */ + u32 die_id_2; /* 0x0c */ + u32 die_id_3; /* 0x10 */ + u32 prod_id_0; /* 0x14 */ + u32 prod_id_1; /* 0x18 */ +}; + + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL_STRICT_NAMES */ diff --git a/arch/arm/include/asm/arch-omap4/sys_proto.h b/arch/arm/include/asm/arch-omap4/sys_proto.h index a81f8e5c2..9a4a8eb0c 100644 --- a/arch/arm/include/asm/arch-omap4/sys_proto.h +++ b/arch/arm/include/asm/arch-omap4/sys_proto.h @@ -53,6 +53,7 @@ u32 omap4_ddr_clk(void); void cancel_out(u32 *num, u32 *den, u32 den_limit); void sdram_init(void); u32 omap4_sdram_size(void); +void omap4_die_id_to_ethernet_mac(u8 *, int); static inline u32 running_from_sdram(void) { diff --git a/board/ti/panda/panda.c b/board/ti/panda/panda.c index e60a2e267..5fe01b176 100644 --- a/board/ti/panda/panda.c +++ b/board/ti/panda/panda.c @@ -48,8 +48,26 @@ int board_init(void) return 0; } +/* + * Panda has a usb nic with no ethernet rom so generate a macaddr + * from the SOC die-id and set the usbethaddr env var to that + * value. + */ int board_eth_init(bd_t *bis) { + u8 macaddr[6]; + char usbethaddr[20]; + + /* + * NB: The 1 here has been found to generate an address + * consistent with the kernel. + */ + omap4_die_id_to_ethernet_mac(macaddr, 1); + sprintf (usbethaddr, "%02X:%02X:%02X:%02X:%02X:%02X", + macaddr[0], macaddr[1], + macaddr[2], macaddr[3], + macaddr[4], macaddr[5]) ; + setenv ("usbethaddr", usbethaddr); return 0; } |