1 /* $NetBSD: autoconf.c,v 1.33 2026/02/18 13:35:40 thorpej 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.33 2026/02/18 13:35:40 thorpej 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 #include <dev/i2c/i2c_calls.h> 55 #include <dev/i2c/i2c_enum.h> 56 57 static struct btinfo_rootdevice *bi_rdev; 58 static struct btinfo_bootpath *bi_path; 59 static struct btinfo_net *bi_net; 60 static struct btinfo_prodfamily *bi_pfam; 61 static struct btinfo_model *bi_model; 62 63 static const struct i2c_deventry dlink_i2cdevs[] = { 64 { .name = "strtc", 65 .compat = "st,m41t80", 66 .addr = 0x68 }, 67 68 I2C_DEVENTRY_EOL 69 }; 70 71 static const struct i2c_deventry iomega_i2cdevs[] = { 72 { .name = "dsrtc", 73 .compat = "dallas,ds1307", 74 .addr = 0x68 }, 75 76 I2C_DEVENTRY_EOL 77 }; 78 79 static const struct i2c_deventry kurobox_i2cdevs[] = { 80 { .name = "rs5c372rtc", 81 .compat = "ricoh,rs5c372a", 82 .addr = 0x32 }, 83 84 I2C_DEVENTRY_EOL 85 }; 86 87 static const struct i2c_deventry nhnas_i2cdevs[] = { 88 { .name = "pcf8563rtc", 89 .compat = "nxp,pcf8563", 90 .addr = 0x51 }, 91 92 I2C_DEVENTRY_EOL 93 }; 94 95 static const struct i2c_deventry qnap_i2cdevs[] = { 96 { .name = "s390rtc", 97 .compat = "sii,s35390a", 98 .addr = 0x30 }, 99 100 I2C_DEVENTRY_EOL 101 }; 102 103 static const struct i2c_deventry synology_i2cdevs[] = { 104 { .name = "rs5c372rtc", 105 .compat = "ricoh,rs5c372a", 106 .addr = 0x32 }, 107 108 { .name = "lmtemp", 109 .compat = "national,lm75", 110 .addr = 0x48, 111 .value = BI_MODEL_THERMAL }, 112 113 I2C_DEVENTRY_EOL 114 }; 115 116 static const struct device_compatible_entry sandpoint_i2c_devices[] = { 117 { .compat = "dlink", 118 .data = dlink_i2cdevs }, 119 120 { .compat = "iomega", 121 .data = iomega_i2cdevs }, 122 123 { .compat = "kurobox", 124 .data = kurobox_i2cdevs }, 125 { .compat = "kurot4", 126 .data = kurobox_i2cdevs }, 127 128 { .compat = "nhnas", 129 .data = nhnas_i2cdevs }, 130 131 { .compat = "qnap", 132 .data = qnap_i2cdevs }, 133 134 { .compat = "synology", 135 .data = synology_i2cdevs }, 136 137 DEVICE_COMPAT_EOL 138 }; 139 140 static bool 141 sandpoint_i2cdev_callback(device_t dev, devhandle_t call_handle, 142 const struct i2c_deventry *entry, devhandle_t *child_devhandlep) 143 { 144 return (entry->value == 0 || 145 (entry->value & bi_model->flags) != 0); 146 } 147 148 static int 149 sandpoint_i2c_enumerate_devices(device_t dev, devhandle_t call_handle, void *v) 150 { 151 struct i2c_enumerate_devices_args *args = v; 152 153 /* Pointer to the table has been stashed in the devhandle. */ 154 const struct i2c_deventry *table = call_handle.const_pointer; 155 156 return i2c_enumerate_deventries(dev, call_handle, args, 157 table, sandpoint_i2cdev_callback); 158 } 159 160 static device_call_t 161 sandpoint_i2c_lookup_device_call(devhandle_t handle, const char *name, 162 devhandle_t *call_handlep) 163 { 164 if (strcmp(name, I2C_ENUMERATE_DEVICES_STR) == 0) { 165 return sandpoint_i2c_enumerate_devices; 166 } 167 168 /* Defer everything else to the "super". */ 169 return NULL; 170 } 171 172 static const struct devhandle_impl sandpoint_i2c_devhandle_impl = { 173 .type = DEVHANDLE_TYPE_PRIVATE, 174 .lookup_device_call = sandpoint_i2c_lookup_device_call, 175 }; 176 177 /* 178 * Determine i/o configuration for a machine. 179 */ 180 void 181 cpu_configure(void) 182 { 183 184 bi_rdev = lookup_bootinfo(BTINFO_ROOTDEVICE); 185 bi_path = lookup_bootinfo(BTINFO_BOOTPATH); 186 bi_net = lookup_bootinfo(BTINFO_NET); 187 bi_pfam = lookup_bootinfo(BTINFO_PRODFAMILY); 188 bi_model = lookup_bootinfo(BTINFO_MODEL); 189 190 if (config_rootfound("mainbus", NULL) == NULL) 191 panic("configure: mainbus not configured"); 192 193 genppc_cpu_configure(); 194 } 195 196 void 197 cpu_rootconf(void) 198 { 199 200 if (bi_path != NULL) 201 booted_kernel = bi_path->bootpath; 202 203 aprint_normal("boot device: %s\n", 204 booted_device ? device_xname(booted_device) : "<unknown>"); 205 rootconf(); 206 } 207 208 void 209 device_register(device_t dev, void *aux) 210 { 211 struct pci_attach_args *pa; 212 static device_t boot_parent = NULL, net_parent = NULL; 213 static pcitag_t boot_tag, net_tag; 214 pcitag_t tag; 215 216 if (device_is_a(dev, "skc")) { 217 pa = aux; 218 if (bi_rdev != NULL && bi_rdev->cookie == pa->pa_tag) { 219 boot_parent = dev; 220 boot_tag = pa->pa_tag; 221 } 222 if (bi_net != NULL && bi_net->cookie == pa->pa_tag) { 223 net_parent = dev; 224 net_tag = pa->pa_tag; 225 } 226 } 227 else if (device_class(dev) == DV_IFNET) { 228 if (device_is_a(device_parent(dev), "pci")) { 229 pa = aux; 230 tag = pa->pa_tag; 231 } else if (device_parent(dev) == boot_parent) 232 tag = boot_tag; 233 else if (device_parent(dev) == net_parent) 234 tag = net_tag; 235 else 236 tag = 0; 237 238 if (bi_rdev != NULL && device_is_a(dev, bi_rdev->devname) 239 && bi_rdev->cookie == tag) 240 booted_device = dev; 241 242 if (bi_net != NULL && device_is_a(dev, bi_net->devname) 243 && bi_net->cookie == tag) { 244 if (! device_setprop_data(dev, "mac-address", 245 bi_net->mac_address, 246 ETHER_ADDR_LEN)) { 247 printf("WARNING: unable to set mac-addr " 248 "property for %s\n", device_xname(dev)); 249 } 250 bi_net = NULL; /* do it just once */ 251 } 252 } 253 else if (bi_rdev != NULL && device_class(dev) == DV_DISK 254 && device_is_a(dev, bi_rdev->devname) 255 && device_unit(dev) == (bi_rdev->cookie >> 8)) { 256 booted_device = dev; 257 booted_partition = bi_rdev->cookie & 0xff; 258 } 259 else if (device_is_a(dev, "ociic") && bi_pfam != NULL) { 260 const struct device_compatible_entry *dce = 261 device_compatible_lookup_strlist(bi_pfam->name, 262 strlen(bi_pfam->name) + 1, sandpoint_i2c_devices); 263 if (dce != NULL) { 264 devhandle_t new_devhandle = { 265 .impl = &sandpoint_i2c_devhandle_impl, 266 .const_pointer = dce->data, 267 }; 268 device_set_handle(dev, new_devhandle); 269 } 270 } 271 } 272