1/*	$NetBSD: autoconf.c,v 1.10 2022/02/12 03:24:34 riastradh Exp $	*/
2
3/*
4 * Copyright 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Simon Burge for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed for the NetBSD Project by
20 *      Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 *    or promote products derived from this software without specific prior
23 *    written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <sys/cdefs.h>
39__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.10 2022/02/12 03:24:34 riastradh Exp $");
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/buf.h>
44#include <sys/conf.h>
45#include <sys/device.h>
46
47#include <net/if_ether.h>
48
49#include <mips/cpu.h>
50#include <mips/locore.h>
51
52#include <evbmips/cavium/octeon_uboot.h>
53
54static void	findroot(void);
55
56void
57cpu_configure(void)
58{
59
60	intr_init();
61
62	/* Kick off autoconfiguration. */
63	(void)splhigh();
64	if (config_rootfound("mainbus", NULL) == NULL)
65		panic("no mainbus found");
66
67	/* XXX need this? */
68	(void)spl0();
69	KDASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE);
70}
71
72void
73cpu_rootconf(void)
74{
75
76#ifndef MEMORY_DISK_IS_ROOT
77	findroot();
78#endif
79
80	printf("boot device: %s\n",
81		booted_device ? device_xname(booted_device) : "<unknown>");
82
83	rootconf();
84}
85
86extern int	netboot;
87
88static void
89findroot(void)
90{
91	device_t dv;
92	deviter_t di;
93
94	if (booted_device)
95		return;
96
97	if (rootspec && *rootspec) {
98		/* if we get passed root=octethN, convert to cnmacN */
99		if (strncmp(rootspec, "octeth", 6) == 0) {
100			/* allow for up to 100 interfaces */
101			static char buf[sizeof("cnmacXX")];
102			const char *cp = &rootspec[strlen("octeth")];
103
104			KASSERT(strlen(cp) < sizeof("XX"));
105			snprintf(buf, sizeof(buf), "cnmac%s", cp);
106			rootspec = buf;
107		}
108
109		/* XXX hard coded "cnmac" for network boot */
110		if (strncmp(rootspec, "cnmac", 5) == 0) {
111			rootfstype = "nfs";
112			netboot = 1;
113			return;
114		}
115
116		/*
117		 * XXX
118		 * Assume that if the root spec is not a cnmac, it'll
119		 * be a sd. handled below.  Should be fixed to handle
120		 * multiple sd devices.
121		 */
122	}
123
124	if (netboot == 0) {
125		/* if no root device specified, default to a "sd" device */
126		for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
127		     dv = deviter_next(&di)) {
128			if (device_class(dv) == DV_DISK &&
129			    device_is_a(dv, "sd"))
130				    booted_device = dv;
131		}
132		deviter_release(&di);
133	}
134
135	/*
136	 * XXX Match up MBR boot specification with BSD disklabel for root?
137	 */
138	booted_partition = 0;
139
140	return;
141}
142
143static void
144prop_set_cnmac(device_t dev)
145{
146	prop_dictionary_t dict = device_properties(dev);
147	prop_data_t pd;
148	prop_number_t pn;
149	uint8_t enaddr[ETHER_ADDR_LEN];
150	uint32_t mac_lo;
151	int unit = device_unit(dev);
152
153	/* ethernet mac address */
154	memcpy(enaddr, octeon_btinfo.obt_mac_addr_base,
155	    sizeof(enaddr));
156	mac_lo = enaddr[3] << 16;
157	mac_lo += enaddr[4] << 8;
158	mac_lo += enaddr[5];
159	KASSERT(unit < octeon_btinfo.obt_mac_addr_count);
160	mac_lo += unit;
161	enaddr[3] = (mac_lo >> 16) & 0xff;
162	enaddr[4] = (mac_lo >> 8) & 0xff;
163	enaddr[5] = mac_lo & 0xff;
164	pd = prop_data_create_copy(enaddr, ETHER_ADDR_LEN);
165	KASSERT(pd != NULL);
166	prop_dictionary_set_and_rel(dict, "mac-address", pd);
167
168	/* ethernet phy address */
169	switch (octeon_btinfo.obt_board_type) {
170	case BOARD_TYPE_UBIQUITI_E100:
171	case BOARD_TYPE_UBIQUITI_E120:
172		pn = prop_number_create_signed(7 - unit);
173		break;
174	case BOARD_TYPE_UBIQUITI_E300:
175		pn = prop_number_create_signed(4 + device_unit(dev));
176		break;
177	default:
178		pn = prop_number_create_signed(-1);
179		break;
180	}
181	KASSERT(pn != NULL);
182	prop_dictionary_set_and_rel(dict, "phy-addr", pn);
183}
184
185static void
186prop_set_octeon_gmx(device_t dev)
187{
188	prop_dictionary_t dict = device_properties(dev);
189	prop_number_t tx, rx;
190
191	/* ethernet rgmii phy dependent timing parameters. */
192	tx = rx = NULL;
193	switch (octeon_btinfo.obt_board_type) {
194	case BOARD_TYPE_UBIQUITI_E100:
195	case BOARD_TYPE_UBIQUITI_E120:
196		tx = prop_number_create_signed(16);
197		rx = prop_number_create_signed(0);
198		break;
199	}
200	if (tx)
201		prop_dictionary_set_and_rel(dict, "rgmii-tx", tx);
202	if (rx)
203		prop_dictionary_set_and_rel(dict, "rgmii-rx", rx);
204}
205
206void
207device_register(device_t dev, void *aux)
208{
209
210	if ((booted_device == NULL) && (netboot == 1))
211		if (device_class(dev) == DV_IFNET)
212			booted_device = dev;
213
214	if (device_is_a(dev, "cnmac")) {
215		prop_set_cnmac(dev);
216	} else if (device_is_a(dev, "octgmx")) {
217		prop_set_octeon_gmx(dev);
218	}
219}
220