xref: /netbsd-src/sys/arch/macppc/dev/uni-n.c (revision 416b0beb004b040ca9dd337a6750d9a8b57e1f5c)
1*416b0bebSmacallan /*	$NetBSD: uni-n.c,v 1.13 2022/12/28 07:18:29 macallan Exp $	*/
298735d6cSmacallan 
398735d6cSmacallan /*-
498735d6cSmacallan  * Copyright (C) 2005 Michael Lorenz.
598735d6cSmacallan  *
698735d6cSmacallan  * Redistribution and use in source and binary forms, with or without
798735d6cSmacallan  * modification, are permitted provided that the following conditions
898735d6cSmacallan  * are met:
998735d6cSmacallan  * 1. Redistributions of source code must retain the above copyright
1098735d6cSmacallan  *    notice, this list of conditions and the following disclaimer.
1198735d6cSmacallan  * 2. Redistributions in binary form must reproduce the above copyright
1298735d6cSmacallan  *    notice, this list of conditions and the following disclaimer in the
1398735d6cSmacallan  *    documentation and/or other materials provided with the distribution.
1498735d6cSmacallan  * 3. The name of the author may not be used to endorse or promote products
1598735d6cSmacallan  *    derived from this software without specific prior written permission.
1698735d6cSmacallan  *
1798735d6cSmacallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1898735d6cSmacallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1998735d6cSmacallan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2098735d6cSmacallan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2198735d6cSmacallan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2298735d6cSmacallan  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2398735d6cSmacallan  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2498735d6cSmacallan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2598735d6cSmacallan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2698735d6cSmacallan  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2798735d6cSmacallan  */
2898735d6cSmacallan 
2998735d6cSmacallan /*
3098735d6cSmacallan  * a driver to match the uni_n node in OF's device tree and attach its children
3198735d6cSmacallan  */
3298735d6cSmacallan 
3398735d6cSmacallan #include <sys/cdefs.h>
34*416b0bebSmacallan __KERNEL_RCSID(0, "$NetBSD: uni-n.c,v 1.13 2022/12/28 07:18:29 macallan Exp $");
3598735d6cSmacallan 
3698735d6cSmacallan #include <sys/param.h>
3798735d6cSmacallan #include <sys/systm.h>
3898735d6cSmacallan #include <sys/kernel.h>
3998735d6cSmacallan #include <sys/device.h>
4098735d6cSmacallan 
4198735d6cSmacallan #include <dev/ofw/openfirm.h>
42dd732ee7Smacallan #include <dev/ofw/ofw_pci.h>
4398735d6cSmacallan 
4498735d6cSmacallan #include <machine/autoconf.h>
4598735d6cSmacallan 
46653b75ceSmacallan #include "fcu.h"
47653b75ceSmacallan 
4805b09539Smatt static void uni_n_attach(device_t, device_t, void *);
4905b09539Smatt static int uni_n_match(device_t, cfdata_t, void *);
5098735d6cSmacallan static int uni_n_print(void *, const char *);
5198735d6cSmacallan 
5298735d6cSmacallan struct uni_n_softc {
53319ca643Smacallan 	device_t sc_dev;
54dd732ee7Smacallan 	struct powerpc_bus_space sc_memt;
5598735d6cSmacallan 	int sc_node;
5698735d6cSmacallan };
5798735d6cSmacallan 
58319ca643Smacallan CFATTACH_DECL_NEW(uni_n, sizeof(struct uni_n_softc),
5998735d6cSmacallan     uni_n_match, uni_n_attach, NULL, NULL);
6098735d6cSmacallan 
61653b75ceSmacallan #if NFCU > 0
62653b75ceSmacallan /* storage for CPUID SEEPROM contents found on some G5 */
63653b75ceSmacallan static uint8_t eeprom[2][160];
64653b75ceSmacallan #endif
65653b75ceSmacallan 
66*416b0bebSmacallan static const char *skiplist[] = {
67*416b0bebSmacallan 	"openpic",
68*416b0bebSmacallan 	"chrp,open-pic",
69*416b0bebSmacallan 	"open-pic",
70*416b0bebSmacallan 	"mpic",
71*416b0bebSmacallan 	"dart",
72*416b0bebSmacallan 	"u3-dart",
73*416b0bebSmacallan 	"u4-dart",
74*416b0bebSmacallan 	NULL
75*416b0bebSmacallan };
76*416b0bebSmacallan 
7798735d6cSmacallan int
uni_n_match(device_t parent,cfdata_t cf,void * aux)7805b09539Smatt uni_n_match(device_t parent, cfdata_t cf, void *aux)
7998735d6cSmacallan {
8098735d6cSmacallan 	struct confargs *ca = aux;
8198735d6cSmacallan 	char compat[32];
82dd732ee7Smacallan 	if ((strcmp(ca->ca_name, "uni-n") != 0) &&
83cf0535baSmacallan 	    (strcmp(ca->ca_name, "u4") != 0) &&
84cf0535baSmacallan 	    (strcmp(ca->ca_name, "u3") != 0))
8598735d6cSmacallan 		return 0;
8698735d6cSmacallan 
8798735d6cSmacallan 	memset(compat, 0, sizeof(compat));
88dd732ee7Smacallan #if 0
8998735d6cSmacallan 	OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
9098735d6cSmacallan 	if (strcmp(compat, "uni-north") != 0)
9198735d6cSmacallan 		return 0;
92dd732ee7Smacallan #endif
9398735d6cSmacallan 	return 1;
9498735d6cSmacallan }
9598735d6cSmacallan 
9698735d6cSmacallan /*
9798735d6cSmacallan  * Attach all the sub-devices we can find
9898735d6cSmacallan  */
9998735d6cSmacallan void
uni_n_attach(device_t parent,device_t self,void * aux)10005b09539Smatt uni_n_attach(device_t parent, device_t self, void *aux)
10198735d6cSmacallan {
10205b09539Smatt 	struct uni_n_softc *sc = device_private(self);
10398735d6cSmacallan 	struct confargs *our_ca = aux;
10498735d6cSmacallan 	struct confargs ca;
10598735d6cSmacallan 	int node, child, namelen;
106653b75ceSmacallan #if NFCU > 0
107653b75ceSmacallan 	int cpuid;
108653b75ceSmacallan #endif
10998735d6cSmacallan 	u_int reg[20];
11098735d6cSmacallan 	int intr[6];
11198735d6cSmacallan 	char name[32];
11298735d6cSmacallan 
113319ca643Smacallan 	sc->sc_dev = self;
114dd732ee7Smacallan 	node = our_ca->ca_node;
11598735d6cSmacallan 	sc->sc_node = node;
116653b75ceSmacallan 	printf(" address 0x%08x\n",
117653b75ceSmacallan 	    our_ca->ca_reg[our_ca->ca_nreg > 8 ? 1 : 0]);
118653b75ceSmacallan 
119653b75ceSmacallan #if NFCU > 0
120653b75ceSmacallan 	/*
121653b75ceSmacallan 	 * zero out eeprom blocks, then see if we have valid data
122*416b0bebSmacallan 	 * doing this here because the EEPROMs are dangling from our i2c bus
123653b75ceSmacallan 	 * but we can get all the data just from looking at the properties
124653b75ceSmacallan 	 */
125653b75ceSmacallan 	memset(eeprom, 0, sizeof(eeprom));
126653b75ceSmacallan 	cpuid = OF_finddevice("/u3/i2c/cpuid@a0");
127653b75ceSmacallan 	OF_getprop(cpuid, "cpuid", eeprom[0], sizeof(eeprom[0]));
128653b75ceSmacallan 	if (eeprom[0][1] != 0)
129653b75ceSmacallan 		aprint_normal_dev(self, "found EEPROM data for CPU 0\n");
130*416b0bebSmacallan 
131653b75ceSmacallan 	cpuid = OF_finddevice("/u3/i2c/cpuid@a2");
132653b75ceSmacallan 	OF_getprop(cpuid, "cpuid", eeprom[1], sizeof(eeprom[1]));
133653b75ceSmacallan 	if (eeprom[1][1] != 0)
134653b75ceSmacallan 		aprint_normal_dev(self, "found EEPROM data for CPU 1\n");
135653b75ceSmacallan #endif
13698735d6cSmacallan 
137dd732ee7Smacallan 	memset(&sc->sc_memt, 0, sizeof(struct powerpc_bus_space));
138dd732ee7Smacallan 	sc->sc_memt.pbs_flags = _BUS_SPACE_LITTLE_ENDIAN|_BUS_SPACE_MEM_TYPE;
139dd732ee7Smacallan 	if (ofwoea_map_space(RANGE_TYPE_MACIO, RANGE_MEM, node, &sc->sc_memt,
140dd732ee7Smacallan 	    "uni-n mem-space") != 0) {
141dd732ee7Smacallan 		panic("Can't init uni-n mem tag");
142dd732ee7Smacallan 	}
143dd732ee7Smacallan 
1443944ff70Sthorpej 	devhandle_t selfh = device_handle(self);
14598735d6cSmacallan 	for (child = OF_child(node); child; child = OF_peer(child)) {
146*416b0bebSmacallan 		if (of_compatible(child, skiplist)) continue;
14798735d6cSmacallan 		namelen = OF_getprop(child, "name", name, sizeof(name));
14898735d6cSmacallan 		if (namelen < 0)
14998735d6cSmacallan 			continue;
15098735d6cSmacallan 		if (namelen >= sizeof(name))
15198735d6cSmacallan 			continue;
15298735d6cSmacallan 
15398735d6cSmacallan 		name[namelen] = 0;
15498735d6cSmacallan 		ca.ca_name = name;
15598735d6cSmacallan 		ca.ca_node = child;
156dd732ee7Smacallan 		ca.ca_tag = &sc->sc_memt;
15798735d6cSmacallan 		ca.ca_nreg  = OF_getprop(child, "reg", reg, sizeof(reg));
15898735d6cSmacallan 		ca.ca_nintr = OF_getprop(child, "AAPL,interrupts", intr,
15998735d6cSmacallan 				sizeof(intr));
16098735d6cSmacallan 		if (ca.ca_nintr == -1)
16198735d6cSmacallan 			ca.ca_nintr = OF_getprop(child, "interrupts", intr,
16298735d6cSmacallan 					sizeof(intr));
16398735d6cSmacallan 
16498735d6cSmacallan 		ca.ca_reg = reg;
16598735d6cSmacallan 		ca.ca_intr = intr;
1662685996bSthorpej 		config_found(self, &ca, uni_n_print,
1673944ff70Sthorpej 		    CFARGS(.devhandle = devhandle_from_of(selfh, child)));
16898735d6cSmacallan 	}
16998735d6cSmacallan }
17098735d6cSmacallan 
17198735d6cSmacallan int
uni_n_print(void * aux,const char * uni_n)172454af1c0Sdsl uni_n_print(void *aux, const char *uni_n)
17398735d6cSmacallan {
17498735d6cSmacallan 	struct confargs *ca = aux;
17598735d6cSmacallan 	if (uni_n)
17698735d6cSmacallan 		aprint_normal("%s at %s", ca->ca_name, uni_n);
17798735d6cSmacallan 
17898735d6cSmacallan 	if (ca->ca_nreg > 0)
17998735d6cSmacallan 		aprint_normal(" address 0x%x", ca->ca_reg[0]);
18098735d6cSmacallan 
18198735d6cSmacallan 	return UNCONF;
18298735d6cSmacallan }
183653b75ceSmacallan 
184653b75ceSmacallan #if NFCU > 0
185653b75ceSmacallan int
get_cpuid(int cpu,uint8_t * buf)186653b75ceSmacallan get_cpuid(int cpu, uint8_t *buf)
187653b75ceSmacallan {
188653b75ceSmacallan 	if ((cpu < 0) || (cpu > 1)) return -1;
189653b75ceSmacallan 	if (eeprom[cpu][1] == 0) return 0;
190653b75ceSmacallan 	memcpy(buf, eeprom[cpu], sizeof(eeprom[cpu]));
191653b75ceSmacallan 	return sizeof(eeprom[cpu]);
192653b75ceSmacallan }
193653b75ceSmacallan #endif
194