xref: /netbsd-src/sys/arch/sandpoint/sandpoint/autoconf.c (revision 27e451df132470df1910b6cf8004bc6d7cf8441c)
1 /*	$NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $	*/
2 
3 /*-
4  * Copyright (c) 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * William Jolitz.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)autoconf.c	7.1 (Berkeley) 5/9/91
35  */
36 
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.29 2020/07/09 05:12:09 nisimura Exp $");
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/conf.h>
43 #include <sys/device.h>
44 
45 #include <dev/cons.h>
46 #include <dev/pci/pcivar.h>
47 
48 #include <net/if.h>
49 #include <net/if_ether.h>
50 
51 #include <machine/bootinfo.h>
52 #include <machine/pio.h>
53 
54 static struct btinfo_rootdevice *bi_rdev;
55 static struct btinfo_bootpath *bi_path;
56 static struct btinfo_net *bi_net;
57 static struct btinfo_prodfamily *bi_pfam;
58 static struct btinfo_model *bi_model;
59 
60 struct i2c_dev {
61 	const char	*name;
62 	unsigned	addr;
63 	/* only attach when one of these bits in the model flags is set */
64 	uint32_t	model_mask;
65 };
66 
67 #define MAXI2CDEVS	4
68 struct model_i2c {
69 	const char	*family;
70 	struct i2c_dev	i2c_devs[MAXI2CDEVS];
71 };
72 
73 static struct model_i2c model_i2c_list[] = {
74 	{ "dlink",	{	{ "strtc",	0x68, 0 } } },
75 	{ "iomega",	{	{ "dsrtc",	0x68, 0 } } },
76 	{ "kurobox",	{	{ "rs5c372rtc", 0x32, 0 } } },
77 	{ "kurot4",	{	{ "rs5c372rtc", 0x32, 0 } } },
78 	{ "nhnas",	{	{ "pcf8563rtc", 0x51, 0 } } },
79 	{ "qnap",	{	{ "s390rtc",    0x30, 0 } } },
80 	{ "synology",	{	{ "rs5c372rtc", 0x32, 0 },
81 				{ "lmtemp",	0x48, BI_MODEL_THERMAL } } },
82 };
83 
84 static void add_i2c_child_devices(device_t, const char *);
85 
86 /*
87  * Determine i/o configuration for a machine.
88  */
89 void
cpu_configure(void)90 cpu_configure(void)
91 {
92 
93 	bi_rdev = lookup_bootinfo(BTINFO_ROOTDEVICE);
94 	bi_path = lookup_bootinfo(BTINFO_BOOTPATH);
95 	bi_net = lookup_bootinfo(BTINFO_NET);
96 	bi_pfam = lookup_bootinfo(BTINFO_PRODFAMILY);
97 	bi_model = lookup_bootinfo(BTINFO_MODEL);
98 
99 	if (config_rootfound("mainbus", NULL) == NULL)
100 		panic("configure: mainbus not configured");
101 
102 	genppc_cpu_configure();
103 }
104 
105 void
cpu_rootconf(void)106 cpu_rootconf(void)
107 {
108 
109 	if (bi_path != NULL)
110 		booted_kernel = bi_path->bootpath;
111 
112 	aprint_normal("boot device: %s\n",
113 	    booted_device ? device_xname(booted_device) : "<unknown>");
114 	rootconf();
115 }
116 
117 void
device_register(device_t dev,void * aux)118 device_register(device_t dev, void *aux)
119 {
120 	struct pci_attach_args *pa;
121 	static device_t boot_parent = NULL, net_parent = NULL;
122 	static pcitag_t boot_tag, net_tag;
123 	pcitag_t tag;
124 
125 	if (device_is_a(dev, "skc")) {
126 		pa = aux;
127 		if (bi_rdev != NULL && bi_rdev->cookie == pa->pa_tag) {
128 			boot_parent = dev;
129 			boot_tag = pa->pa_tag;
130 		}
131 		if (bi_net != NULL && bi_net->cookie == pa->pa_tag) {
132 			net_parent = dev;
133 			net_tag = pa->pa_tag;
134 		}
135 	}
136 	else if (device_class(dev) == DV_IFNET) {
137 		if (device_is_a(device_parent(dev), "pci")) {
138 			pa = aux;
139 			tag = pa->pa_tag;
140 		} else if (device_parent(dev) == boot_parent)
141 			tag = boot_tag;
142 		else if (device_parent(dev) == net_parent)
143 			tag = net_tag;
144 		else
145 			tag = 0;
146 
147 		if (bi_rdev != NULL && device_is_a(dev, bi_rdev->devname)
148 		    && bi_rdev->cookie == tag)
149 			booted_device = dev;
150 
151 		if (bi_net != NULL && device_is_a(dev, bi_net->devname)
152 		    && bi_net->cookie == tag) {
153 			prop_data_t pd;
154 
155 			pd = prop_data_create_nocopy(bi_net->mac_address,
156 			    ETHER_ADDR_LEN);
157 			KASSERT(pd != NULL);
158 			if (prop_dictionary_set(device_properties(dev),
159 			    "mac-address", pd) == false)
160 				printf("WARNING: unable to set mac-addr "
161 				    "property for %s\n", device_xname(dev));
162 			prop_object_release(pd);
163 			bi_net = NULL;	/* do it just once */
164 		}
165 	}
166 	else if (bi_rdev != NULL && device_class(dev) == DV_DISK
167 	    && device_is_a(dev, bi_rdev->devname)
168 	    && device_unit(dev) == (bi_rdev->cookie >> 8)) {
169 		booted_device = dev;
170 		booted_partition = bi_rdev->cookie & 0xff;
171 	}
172 	else if (device_is_a(dev, "ociic") && bi_pfam != NULL) {
173 		add_i2c_child_devices(dev, bi_pfam->name);
174 	}
175 }
176 
177 static void
add_i2c_child_devices(device_t self,const char * family)178 add_i2c_child_devices(device_t self, const char *family)
179 {
180 	struct i2c_dev *model_i2c_devs;
181 	prop_dictionary_t pd;
182 	prop_array_t pa;
183 	int i;
184 
185 	for (i = 0;
186 	    i < (int)(sizeof(model_i2c_list) / sizeof(model_i2c_list[0]));
187 	    i++) {
188 		if (strcmp(family, model_i2c_list[i].family) == 0) {
189 			model_i2c_devs = model_i2c_list[i].i2c_devs;
190 			goto found;
191 		}
192 	}
193 	return;
194 
195  found:
196 	/* make an i2c-child-devices property list with for direct config. */
197 	pa = prop_array_create();
198 
199 	for (i = 0; i < MAXI2CDEVS && model_i2c_devs[i].name != NULL; i++) {
200 		if (model_i2c_devs[i].model_mask != 0 &&
201 		    !(bi_model->flags & model_i2c_devs[i].model_mask))
202 			continue;
203 		pd = prop_dictionary_create();
204 		prop_dictionary_set_string_nocopy(pd, "name",
205 		    model_i2c_devs[i].name);
206 		prop_dictionary_set_uint32(pd, "addr",
207 		    model_i2c_devs[i].addr);
208 		prop_array_add(pa, pd);
209 		prop_object_release(pd);
210 	}
211 
212 	prop_dictionary_set(device_properties(self), "i2c-child-devices", pa);
213 	prop_object_release(pa);
214 }
215