summaryrefslogtreecommitdiffstats
path: root/arch/arm/boards/zii-common/board.c
blob: 96f9243591f2fe6fbe3d572e1eda1e2e58d43710 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2019 Zodiac Inflight Innovation

#include <common.h>
#include <fs.h>
#include <globalvar.h>
#include <init.h>
#include <linux/nvmem-consumer.h>
#include <net.h>
#include <restart.h>

static int rdu_eth_register_ethaddr(struct device_node *np)
{
	u8 mac[ETH_ALEN];
	u8 *data;
	int i;

	data = nvmem_cell_get_and_read(np, "mac-address", ETH_ALEN);
	if (IS_ERR(data))
		return PTR_ERR(data);
	/*
	 * EEPROM stores MAC address in reverse (to what we expect it
	 * to be) byte order.
	 */
	for (i = 0; i < ETH_ALEN; i++)
		mac[i] = data[ETH_ALEN - i - 1];

	free(data);

	of_eth_register_ethaddr(np, mac);

	return 0;
}

static int rdu_ethernet_init(void)
{
	static const char * const aliases[] = { "ethernet0", "ethernet1" };
	struct device_node *np, *root;
	int i, ret;

	if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx6qp-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx8mq-ultra"))
		return 0;

	root = of_get_root_node();

	for (i = 0; i < ARRAY_SIZE(aliases); i++) {
		const char *alias = aliases[i];

		np = of_find_node_by_alias(root, alias);
		if (!np) {
			pr_warn("Failed to find %s\n", alias);
			continue;
		}

		ret = rdu_eth_register_ethaddr(np);
		if (ret) {
			pr_warn("Failed to register MAC for %s\n", alias);
			continue;
		}
	}

	return 0;
}
late_initcall(rdu_ethernet_init);

static int rdu_networkconfig(void)
{
	static char *rdu_netconfig;
	struct device *sp_dev;

	if (!of_machine_is_compatible("zii,imx8mq-ultra") &&
	    !of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx6qp-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx51-rdu1"))
		return 0;

	sp_dev = get_device_by_name("sp");
	if (!sp_dev) {
		pr_warn("no sp device found, network config not available!\n");
		return -ENODEV;
	}

	rdu_netconfig = basprintf("ip=%s:::%s::eth0:",
				  dev_get_param(sp_dev, "ipaddr"),
				  dev_get_param(sp_dev, "netmask"));

	globalvar_add_simple_string("linux.bootargs.rdu_network",
				    &rdu_netconfig);

	return 0;
}
late_initcall(rdu_networkconfig);

#ifdef CONFIG_PCI_IMX6

#define I210_CFGWORD_PCIID_157B		0x157b1a11
static int rdu_i210_invm(void)
{
	int fd;
	u32 val;

	if (!of_machine_is_compatible("zii,imx6q-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx6qp-zii-rdu2") &&
	    !of_machine_is_compatible("zii,imx8mq-ultra"))
		return 0;

	fd = open("/dev/e1000-invm0", O_RDWR);
	if (fd < 0) {
		pr_err("could not open e1000 iNVM device!\n");
		return fd;
	}

	pread(fd, &val, sizeof(val), 0);
	if (val == I210_CFGWORD_PCIID_157B) {
		pr_debug("i210 already programmed correctly\n");
		return 0;
	}

	val = I210_CFGWORD_PCIID_157B;
	pwrite(fd, &val, sizeof(val), 0);

	shutdown_barebox();
	restart_machine();

	return 0;
}
late_initcall(rdu_i210_invm);

#endif