1*6e54367aSthorpej /* $NetBSD: smsh_fdt.c,v 1.4 2021/01/27 03:10:19 thorpej Exp $ */
25e4a0549Sjmcneill
35e4a0549Sjmcneill /*-
45e4a0549Sjmcneill * Copyright (c) 2017 Jared McNeill <jmcneill@invisible.ca>
55e4a0549Sjmcneill * All rights reserved.
65e4a0549Sjmcneill *
75e4a0549Sjmcneill * Redistribution and use in source and binary forms, with or without
85e4a0549Sjmcneill * modification, are permitted provided that the following conditions
95e4a0549Sjmcneill * are met:
105e4a0549Sjmcneill * 1. Redistributions of source code must retain the above copyright
115e4a0549Sjmcneill * notice, this list of conditions and the following disclaimer.
125e4a0549Sjmcneill * 2. Redistributions in binary form must reproduce the above copyright
135e4a0549Sjmcneill * notice, this list of conditions and the following disclaimer in the
145e4a0549Sjmcneill * documentation and/or other materials provided with the distribution.
155e4a0549Sjmcneill *
165e4a0549Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
175e4a0549Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
185e4a0549Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
195e4a0549Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
205e4a0549Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
215e4a0549Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
225e4a0549Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
235e4a0549Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
245e4a0549Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
255e4a0549Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265e4a0549Sjmcneill * SUCH DAMAGE.
275e4a0549Sjmcneill */
285e4a0549Sjmcneill
295e4a0549Sjmcneill #include <sys/cdefs.h>
30*6e54367aSthorpej __KERNEL_RCSID(0, "$NetBSD: smsh_fdt.c,v 1.4 2021/01/27 03:10:19 thorpej Exp $");
315e4a0549Sjmcneill
325e4a0549Sjmcneill #include <sys/param.h>
335e4a0549Sjmcneill #include <sys/bus.h>
345e4a0549Sjmcneill #include <sys/device.h>
355e4a0549Sjmcneill #include <sys/systm.h>
365e4a0549Sjmcneill #include <sys/kernel.h>
375e4a0549Sjmcneill
385e4a0549Sjmcneill #include <dev/fdt/fdtvar.h>
395e4a0549Sjmcneill
405e4a0549Sjmcneill #include <net/if.h>
415e4a0549Sjmcneill #include <net/if_ether.h>
425e4a0549Sjmcneill #include <net/if_media.h>
435e4a0549Sjmcneill
445e4a0549Sjmcneill #include <dev/mii/miivar.h>
455e4a0549Sjmcneill
465e4a0549Sjmcneill #include <dev/ic/lan9118var.h>
475e4a0549Sjmcneill #include <dev/ic/lan9118reg.h>
485e4a0549Sjmcneill
495e4a0549Sjmcneill static int smsh_fdt_match(device_t, cfdata_t, void *);
505e4a0549Sjmcneill static void smsh_fdt_attach(device_t, device_t, void *);
515e4a0549Sjmcneill
52*6e54367aSthorpej static const struct device_compatible_entry compat_data[] = {
53*6e54367aSthorpej { .compat = "smsc,lan9118" },
54*6e54367aSthorpej { .compat = "smsc,lan9115" },
55*6e54367aSthorpej DEVICE_COMPAT_EOL
56b2da2235Sjmcneill };
575e4a0549Sjmcneill
585e4a0549Sjmcneill CFATTACH_DECL_NEW(smsh_fdt, sizeof(struct lan9118_softc),
595e4a0549Sjmcneill smsh_fdt_match, smsh_fdt_attach, NULL, NULL);
605e4a0549Sjmcneill
615e4a0549Sjmcneill static int
smsh_fdt_match(device_t parent,cfdata_t cf,void * aux)625e4a0549Sjmcneill smsh_fdt_match(device_t parent, cfdata_t cf, void *aux)
635e4a0549Sjmcneill {
645e4a0549Sjmcneill struct fdt_attach_args * const faa = aux;
655e4a0549Sjmcneill
66*6e54367aSthorpej return of_compatible_match(faa->faa_phandle, compat_data);
675e4a0549Sjmcneill }
685e4a0549Sjmcneill
695e4a0549Sjmcneill static void
smsh_fdt_attach(device_t parent,device_t self,void * aux)705e4a0549Sjmcneill smsh_fdt_attach(device_t parent, device_t self, void *aux)
715e4a0549Sjmcneill {
725e4a0549Sjmcneill struct lan9118_softc * const sc = device_private(self);
735e4a0549Sjmcneill struct fdt_attach_args * const faa = aux;
745e4a0549Sjmcneill const int phandle = faa->faa_phandle;
75b2da2235Sjmcneill const char *enaddr;
76b2da2235Sjmcneill char intrstr[128];
775e4a0549Sjmcneill bus_addr_t addr;
785e4a0549Sjmcneill bus_size_t size;
79b2da2235Sjmcneill int len;
805e4a0549Sjmcneill void *ih;
815e4a0549Sjmcneill
825e4a0549Sjmcneill if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0) {
835e4a0549Sjmcneill aprint_error(": missing 'reg' property\n");
845e4a0549Sjmcneill return;
855e4a0549Sjmcneill }
865e4a0549Sjmcneill
875e4a0549Sjmcneill if (!fdtbus_intr_str(phandle, 0, intrstr, sizeof(intrstr))) {
885e4a0549Sjmcneill aprint_error_dev(self, "failed to decode interrupt\n");
895e4a0549Sjmcneill return;
905e4a0549Sjmcneill }
915e4a0549Sjmcneill
925e4a0549Sjmcneill sc->sc_dev = self;
935e4a0549Sjmcneill sc->sc_iot = faa->faa_bst;
945e4a0549Sjmcneill if (bus_space_map(faa->faa_bst, addr, size, 0, &sc->sc_ioh)) {
955e4a0549Sjmcneill aprint_error(": couldn't map device\n");
965e4a0549Sjmcneill return;
975e4a0549Sjmcneill }
985e4a0549Sjmcneill
995e4a0549Sjmcneill if (of_hasprop(phandle, "smsc,irq-active-high"))
1005e4a0549Sjmcneill sc->sc_flags |= LAN9118_FLAGS_IRQ_ACTHI;
1015e4a0549Sjmcneill if (of_hasprop(phandle, "smsc,irq-push-pull"))
1025e4a0549Sjmcneill sc->sc_flags |= LAN9118_FLAGS_IRQ_PP;
1035e4a0549Sjmcneill
104b2da2235Sjmcneill enaddr = fdtbus_get_prop(phandle, "local-mac-address", &len);
105b2da2235Sjmcneill if (enaddr == NULL || len != ETHER_ADDR_LEN)
106b2da2235Sjmcneill enaddr = fdtbus_get_prop(phandle, "mac-address", &len);
107b2da2235Sjmcneill if (enaddr != NULL && len == ETHER_ADDR_LEN) {
108b2da2235Sjmcneill memcpy(sc->sc_enaddr, enaddr, ETHER_ADDR_LEN);
109b2da2235Sjmcneill sc->sc_flags |= LAN9118_FLAGS_NO_EEPROM;
110b2da2235Sjmcneill }
111b2da2235Sjmcneill
1125e4a0549Sjmcneill if (lan9118_attach(sc) != 0)
1135e4a0549Sjmcneill goto unmap;
1145e4a0549Sjmcneill
11564e248edSryo ih = fdtbus_intr_establish_xname(phandle, 0, IPL_NET, 0, lan9118_intr, sc,
11664e248edSryo device_xname(self));
1175e4a0549Sjmcneill if (ih == NULL) {
1185e4a0549Sjmcneill aprint_error_dev(self, "couldn't install interrupt handler\n");
1195e4a0549Sjmcneill goto unmap;
1205e4a0549Sjmcneill }
1215e4a0549Sjmcneill aprint_normal_dev(self, "interrupting on %s\n", intrstr);
1225e4a0549Sjmcneill
1235e4a0549Sjmcneill return;
1245e4a0549Sjmcneill
1255e4a0549Sjmcneill unmap:
1265e4a0549Sjmcneill bus_space_unmap(sc->sc_iot, sc->sc_ioh, size);
1275e4a0549Sjmcneill }
128