1 /* $OpenBSD: moxtet.c,v 1.2 2021/10/24 17:52:26 mpi Exp $ */ 2 /* 3 * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/systm.h> 20 #include <sys/kernel.h> 21 #include <sys/device.h> 22 #include <sys/malloc.h> 23 24 #include <dev/spi/spivar.h> 25 26 #include <dev/ofw/openfirm.h> 27 #include <dev/ofw/ofw_gpio.h> 28 #include <dev/ofw/ofw_pinctrl.h> 29 30 #define MOX_NMODULE 10 31 32 #define MOX_CPU_EMMC 0x00 33 #define MOX_CPU_SD 0x10 34 35 #define MOX_MODULE_SFP 0x01 36 #define MOX_MODULE_PCI 0x02 37 #define MOX_MODULE_TOPAZ 0x03 38 #define MOX_MODULE_PERIDOT 0x04 39 #define MOX_MODULE_USB3 0x05 40 #define MOX_MODULE_PASSPCI 0x06 41 42 struct moxtet_softc { 43 struct device sc_dev; 44 int sc_node; 45 46 spi_tag_t sc_spi_tag; 47 struct spi_config sc_spi_conf; 48 49 int sc_nmodule; 50 }; 51 52 int moxtet_match(struct device *, void *, void *); 53 void moxtet_attach(struct device *, struct device *, void *); 54 int moxtet_detach(struct device *, int); 55 56 int moxtet_read(struct moxtet_softc *, char *, size_t); 57 int moxtet_write(struct moxtet_softc *, char *, size_t); 58 59 const struct cfattach moxtet_ca = { 60 sizeof(struct moxtet_softc), moxtet_match, moxtet_attach, moxtet_detach 61 }; 62 63 struct cfdriver moxtet_cd = { 64 NULL, "moxtet", DV_DULL 65 }; 66 67 int 68 moxtet_match(struct device *parent, void *match, void *aux) 69 { 70 struct spi_attach_args *sa = aux; 71 72 if (strcmp(sa->sa_name, "cznic,moxtet") == 0) 73 return 1; 74 75 return 0; 76 } 77 78 void 79 moxtet_attach(struct device *parent, struct device *self, void *aux) 80 { 81 struct moxtet_softc *sc = (struct moxtet_softc *)self; 82 struct spi_attach_args *sa = aux; 83 uint8_t buf[MOX_NMODULE]; 84 int i; 85 86 sc->sc_spi_tag = sa->sa_tag; 87 sc->sc_node = *(int *)sa->sa_cookie; 88 89 pinctrl_byname(sc->sc_node, "default"); 90 91 sc->sc_spi_conf.sc_bpw = 8; 92 sc->sc_spi_conf.sc_freq = OF_getpropint(sc->sc_node, 93 "spi-max-frequency", 0); 94 sc->sc_spi_conf.sc_cs = OF_getpropint(sc->sc_node, "reg", 0); 95 if (OF_getproplen(sc->sc_node, "spi-cpol") == 0) 96 sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPOL; 97 if (OF_getproplen(sc->sc_node, "spi-cpha") == 0) 98 sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CPHA; 99 if (OF_getproplen(sc->sc_node, "spi-cs-high") == 0) 100 sc->sc_spi_conf.sc_flags |= SPI_CONFIG_CS_HIGH; 101 102 if (moxtet_read(sc, buf, sizeof(buf))) { 103 printf(": can't read moxtet\n"); 104 return; 105 } 106 107 if (buf[0] == MOX_CPU_EMMC) 108 printf(": eMMC"); 109 else if (buf[0] == MOX_CPU_SD) 110 printf(": SD"); 111 else { 112 printf(": unknown\n"); 113 return; 114 } 115 116 for (i = 1; i < MOX_NMODULE; i++) { 117 if (buf[i] == 0xff) 118 break; 119 sc->sc_nmodule++; 120 switch (buf[i] & 0xf) { 121 case MOX_MODULE_SFP: 122 printf(", SFP"); 123 break; 124 case MOX_MODULE_PCI: 125 printf(", mPCIe"); 126 break; 127 case MOX_MODULE_TOPAZ: 128 printf(", 4x GbE"); 129 break; 130 case MOX_MODULE_PERIDOT: 131 printf(", 8x GbE"); 132 break; 133 case MOX_MODULE_USB3: 134 printf(", 4x USB 3.0"); 135 break; 136 case MOX_MODULE_PASSPCI: 137 printf(", mPCIe (passthrough)"); 138 break; 139 default: 140 printf(", unknown (0x%02x)", buf[i] & 0xf); 141 break; 142 } 143 } 144 145 printf("\n"); 146 } 147 148 int 149 moxtet_detach(struct device *self, int flags) 150 { 151 return 0; 152 } 153 154 int 155 moxtet_read(struct moxtet_softc *sc, char *buf, size_t len) 156 { 157 int error; 158 159 spi_acquire_bus(sc->sc_spi_tag, 0); 160 spi_config(sc->sc_spi_tag, &sc->sc_spi_conf); 161 error = spi_read(sc->sc_spi_tag, buf, len); 162 spi_release_bus(sc->sc_spi_tag, 0); 163 return error; 164 } 165 166 int 167 moxtet_write(struct moxtet_softc *sc, char *buf, size_t len) 168 { 169 int error; 170 171 spi_acquire_bus(sc->sc_spi_tag, 0); 172 spi_config(sc->sc_spi_tag, &sc->sc_spi_conf); 173 error = spi_write(sc->sc_spi_tag, buf, len); 174 spi_release_bus(sc->sc_spi_tag, 0); 175 return error; 176 } 177