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