1 /* $OpenBSD: sdhc_pci.c,v 1.26 2024/03/29 02:36:49 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/device.h> 21 #include <sys/systm.h> 22 #include <sys/malloc.h> 23 24 #include <dev/pci/pcivar.h> 25 #include <dev/pci/pcidevs.h> 26 #include <dev/sdmmc/sdhcreg.h> 27 #include <dev/sdmmc/sdhcvar.h> 28 #include <dev/sdmmc/sdmmcvar.h> 29 30 /* 31 * 8-bit PCI configuration register that tells us how many slots there 32 * are and which BAR entry corresponds to the first slot. 33 */ 34 #define SDHC_PCI_CONF_SLOT_INFO 0x40 35 #define SDHC_PCI_NUM_SLOTS(info) ((((info) >> 4) & 0x7) + 1) 36 #define SDHC_PCI_FIRST_BAR(info) ((info) & 0x7) 37 38 /* TI specific register */ 39 #define SDHC_PCI_GENERAL_CTL 0x4c 40 #define MMC_SD_DIS 0x02 41 42 /* RICOH specific registers */ 43 #define SDHC_PCI_MODE_KEY 0xf9 44 #define SDHC_PCI_MODE 0x150 45 #define SDHC_PCI_MODE_SD20 0x10 46 #define SDHC_PCI_BASE_FREQ_KEY 0xfc 47 #define SDHC_PCI_BASE_FREQ 0xe1 48 49 struct sdhc_pci_softc { 50 struct sdhc_softc sc; 51 pci_chipset_tag_t sc_pc; 52 pcitag_t sc_tag; 53 pcireg_t sc_id; 54 void *sc_ih; 55 }; 56 57 int sdhc_pci_match(struct device *, void *, void *); 58 void sdhc_pci_attach(struct device *, struct device *, void *); 59 int sdhc_pci_activate(struct device *, int); 60 61 void sdhc_pci_conf_write(pci_chipset_tag_t, pcitag_t, int, uint8_t); 62 void sdhc_takecontroller(struct pci_attach_args *); 63 void sdhc_ricohfix(struct sdhc_pci_softc *); 64 65 const struct cfattach sdhc_pci_ca = { 66 sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach, 67 NULL, sdhc_pci_activate 68 }; 69 70 int 71 sdhc_pci_match(struct device *parent, void *match, void *aux) 72 { 73 struct pci_attach_args *pa = aux; 74 75 /* 76 * The Realtek RTS5209 is supported by rtsx(4). Usually the device 77 * class for these is UNDEFINED but there are RTS5209 devices which 78 * are advertising an SYSTEM/SDHC device class in addition to a 79 * separate device advertising the UNDEFINED class. Such devices are 80 * not compatible with sdhc(4), so ignore them. 81 */ 82 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_REALTEK && 83 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_REALTEK_RTS5209) 84 return 0; 85 86 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SYSTEM && 87 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC) 88 return 1; 89 90 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH && 91 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U822 || 92 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)) 93 return 1; 94 95 return 0; 96 } 97 98 void 99 sdhc_pci_attach(struct device *parent, struct device *self, void *aux) 100 { 101 struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self; 102 struct pci_attach_args *pa = aux; 103 pci_intr_handle_t ih; 104 char const *intrstr; 105 int slotinfo; 106 int nslots; 107 int usedma; 108 int reg; 109 pcireg_t type; 110 bus_space_tag_t iot; 111 bus_space_handle_t ioh; 112 bus_size_t size; 113 114 sc->sc_pc = pa->pa_pc; 115 sc->sc_tag = pa->pa_tag; 116 sc->sc_id = pa->pa_id; 117 118 /* Some TI controllers needs special treatment. */ 119 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI && 120 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD && 121 pa->pa_function == 4) 122 sdhc_takecontroller(pa); 123 124 /* ENE controllers break if set to 0V bus power. */ 125 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENE && 126 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD) 127 sc->sc.sc_flags |= SDHC_F_NOPWR0; 128 129 /* Some Intel controllers break if set to 0V bus power. */ 130 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 131 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_100SERIES_LP_EMMC || 132 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_APOLLOLAKE_EMMC || 133 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GLK_EMMC || 134 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_JSL_EMMC || 135 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_EHL_EMMC || 136 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_ADL_N_EMMC)) 137 sc->sc.sc_flags |= SDHC_F_NOPWR0; 138 139 /* Some RICOH controllers need to be bumped into the right mode. */ 140 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH && 141 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U822 || 142 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)) 143 sdhc_ricohfix(sc); 144 145 if (pci_intr_map(pa, &ih)) { 146 printf(": can't map interrupt\n"); 147 return; 148 } 149 150 intrstr = pci_intr_string(pa->pa_pc, ih); 151 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC, 152 sdhc_intr, sc, sc->sc.sc_dev.dv_xname); 153 if (sc->sc_ih == NULL) { 154 printf(": can't establish interrupt\n"); 155 return; 156 } 157 printf(": %s\n", intrstr); 158 159 /* Enable use of DMA if supported by the interface. */ 160 usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA; 161 sc->sc.sc_dmat = pa->pa_dmat; 162 163 /* 164 * Map and attach all hosts supported by the host controller. 165 */ 166 slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag, 167 SDHC_PCI_CONF_SLOT_INFO); 168 nslots = SDHC_PCI_NUM_SLOTS(slotinfo); 169 170 /* Allocate an array big enough to hold all the possible hosts */ 171 sc->sc.sc_host = mallocarray(nslots, sizeof(struct sdhc_host *), 172 M_DEVBUF, M_WAITOK); 173 174 for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) * 4; 175 reg < SDHC_PCI_BAR_END && nslots > 0; 176 reg += 4, nslots--) { 177 if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, reg, &type)) 178 break; 179 180 if (type == PCI_MAPREG_TYPE_IO || pci_mapreg_map(pa, reg, 181 type, 0, &iot, &ioh, NULL, &size, 0)) { 182 printf("%s at 0x%x: can't map registers\n", 183 sc->sc.sc_dev.dv_xname, reg); 184 break; 185 } 186 187 if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, 0, 0) != 0) 188 printf("%s at 0x%x: can't initialize host\n", 189 sc->sc.sc_dev.dv_xname, reg); 190 191 if (type & PCI_MAPREG_MEM_TYPE_64BIT) 192 reg += 4; 193 } 194 } 195 196 int 197 sdhc_pci_activate(struct device *self, int act) 198 { 199 struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self; 200 int rv; 201 202 switch (act) { 203 case DVACT_SUSPEND: 204 rv = sdhc_activate(self, act); 205 break; 206 case DVACT_RESUME: 207 /* Some RICOH controllers need to be bumped into the right mode. */ 208 if (PCI_VENDOR(sc->sc_id) == PCI_VENDOR_RICOH && 209 (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_RICOH_R5U822 || 210 PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_RICOH_R5U823)) 211 sdhc_ricohfix(sc); 212 rv = sdhc_activate(self, act); 213 break; 214 default: 215 rv = sdhc_activate(self, act); 216 break; 217 } 218 return (rv); 219 } 220 221 void 222 sdhc_takecontroller(struct pci_attach_args *pa) 223 { 224 pcitag_t tag; 225 pcireg_t id, reg; 226 227 /* Look at func 3 for the flash device */ 228 tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 3); 229 id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG); 230 if (PCI_PRODUCT(id) != PCI_PRODUCT_TI_PCI7XX1_FLASH) 231 return; 232 233 /* 234 * Disable MMC/SD on the flash media controller so the 235 * SD host takes over. 236 */ 237 reg = pci_conf_read(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL); 238 reg |= MMC_SD_DIS; 239 pci_conf_write(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL, reg); 240 } 241 242 void 243 sdhc_ricohfix(struct sdhc_pci_softc *sc) 244 { 245 /* Enable SD2.0 mode. */ 246 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0xfc); 247 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20); 248 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0x00); 249 250 /* 251 * Some SD/MMC cards don't work with the default base 252 * clock frequency of 200MHz. Lower it to 50Hz. 253 */ 254 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 0x01); 255 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ, 50); 256 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 0x00); 257 } 258 259 void 260 sdhc_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val) 261 { 262 pcireg_t tmp; 263 264 tmp = pci_conf_read(pc, tag, reg & ~0x3); 265 tmp &= ~(0xff << ((reg & 0x3) * 8)); 266 tmp |= (val << ((reg & 0x3) * 8)); 267 pci_conf_write(pc, tag, reg & ~0x3, tmp); 268 } 269