18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Miscellaneous SoC-specific hooks. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2011 Texas Instruments Incorporated 68c2ecf20Sopenharmony_ci * Author: Mark Salter <msalter@redhat.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/ctype.h> 108c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 118c2ecf20Sopenharmony_ci#include <asm/setup.h> 128c2ecf20Sopenharmony_ci#include <asm/soc.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistruct soc_ops soc_ops; 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ciint soc_get_exception(void) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci if (!soc_ops.get_exception) 198c2ecf20Sopenharmony_ci return -1; 208c2ecf20Sopenharmony_ci return soc_ops.get_exception(); 218c2ecf20Sopenharmony_ci} 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_civoid soc_assert_event(unsigned int evt) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci if (soc_ops.assert_event) 268c2ecf20Sopenharmony_ci soc_ops.assert_event(evt); 278c2ecf20Sopenharmony_ci} 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic u8 cmdline_mac[6]; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int __init get_mac_addr_from_cmdline(char *str) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci int count, i, val; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci for (count = 0; count < 6 && *str; count++, str += 3) { 368c2ecf20Sopenharmony_ci if (!isxdigit(str[0]) || !isxdigit(str[1])) 378c2ecf20Sopenharmony_ci return 0; 388c2ecf20Sopenharmony_ci if (str[2] != ((count < 5) ? ':' : '\0')) 398c2ecf20Sopenharmony_ci return 0; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci for (i = 0, val = 0; i < 2; i++) { 428c2ecf20Sopenharmony_ci val = val << 4; 438c2ecf20Sopenharmony_ci val |= isdigit(str[i]) ? 448c2ecf20Sopenharmony_ci str[i] - '0' : toupper(str[i]) - 'A' + 10; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci cmdline_mac[count] = val; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci return 1; 498c2ecf20Sopenharmony_ci} 508c2ecf20Sopenharmony_ci__setup("emac_addr=", get_mac_addr_from_cmdline); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * Setup the MAC address for SoC ethernet devices. 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * Before calling this function, the ethernet driver will have 568c2ecf20Sopenharmony_ci * initialized the addr with local-mac-address from the device 578c2ecf20Sopenharmony_ci * tree (if found). Allow command line to override, but not 588c2ecf20Sopenharmony_ci * the fused address. 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_ciint soc_mac_addr(unsigned int index, u8 *addr) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci int i, have_dt_mac = 0, have_cmdline_mac = 0, have_fuse_mac = 0; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci for (i = 0; i < 6; i++) { 658c2ecf20Sopenharmony_ci if (cmdline_mac[i]) 668c2ecf20Sopenharmony_ci have_cmdline_mac = 1; 678c2ecf20Sopenharmony_ci if (c6x_fuse_mac[i]) 688c2ecf20Sopenharmony_ci have_fuse_mac = 1; 698c2ecf20Sopenharmony_ci if (addr[i]) 708c2ecf20Sopenharmony_ci have_dt_mac = 1; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* cmdline overrides all */ 748c2ecf20Sopenharmony_ci if (have_cmdline_mac) 758c2ecf20Sopenharmony_ci memcpy(addr, cmdline_mac, 6); 768c2ecf20Sopenharmony_ci else if (!have_dt_mac) { 778c2ecf20Sopenharmony_ci if (have_fuse_mac) 788c2ecf20Sopenharmony_ci memcpy(addr, c6x_fuse_mac, 6); 798c2ecf20Sopenharmony_ci else 808c2ecf20Sopenharmony_ci eth_random_addr(addr); 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* adjust for specific EMAC device */ 848c2ecf20Sopenharmony_ci addr[5] += index * c6x_num_cores; 858c2ecf20Sopenharmony_ci return 1; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(soc_mac_addr); 88