1 /* $OpenBSD: sdhc_pci.c,v 1.21 2019/11/20 16:34:58 patrick 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 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 u_int32_t caps = 0; 114 115 sc->sc_pc = pa->pa_pc; 116 sc->sc_tag = pa->pa_tag; 117 sc->sc_id = pa->pa_id; 118 119 /* Some TI controllers needs special treatment. */ 120 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI && 121 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD && 122 pa->pa_function == 4) 123 sdhc_takecontroller(pa); 124 125 /* ENE controllers break if set to 0V bus power. */ 126 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENE && 127 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD) 128 sc->sc.sc_flags |= SDHC_F_NOPWR0; 129 130 /* Some Intel controllers break if set to 0V bus power. */ 131 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL && 132 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_100SERIES_LP_EMMC || 133 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_APOLLOLAKE_EMMC || 134 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GLK_EMMC)) 135 sc->sc.sc_flags |= SDHC_F_NOPWR0; 136 137 /* Some RICOH controllers need to be bumped into the right mode. */ 138 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH && 139 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U822 || 140 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823)) 141 sdhc_ricohfix(sc); 142 143 if (pci_intr_map(pa, &ih)) { 144 printf(": can't map interrupt\n"); 145 return; 146 } 147 148 intrstr = pci_intr_string(pa->pa_pc, ih); 149 sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC, 150 sdhc_intr, sc, sc->sc.sc_dev.dv_xname); 151 if (sc->sc_ih == NULL) { 152 printf(": can't establish interrupt\n"); 153 return; 154 } 155 printf(": %s\n", intrstr); 156 157 /* Enable use of DMA if supported by the interface. */ 158 usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA; 159 sc->sc.sc_dmat = pa->pa_dmat; 160 161 /* 162 * Map and attach all hosts supported by the host controller. 163 */ 164 slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag, 165 SDHC_PCI_CONF_SLOT_INFO); 166 nslots = SDHC_PCI_NUM_SLOTS(slotinfo); 167 168 /* Allocate an array big enough to hold all the possible hosts */ 169 sc->sc.sc_host = mallocarray(nslots, sizeof(struct sdhc_host *), 170 M_DEVBUF, M_WAITOK); 171 172 for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) * 4; 173 reg < SDHC_PCI_BAR_END && nslots > 0; 174 reg += 4, nslots--) { 175 if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, reg, &type)) 176 break; 177 178 if (type == PCI_MAPREG_TYPE_IO || pci_mapreg_map(pa, reg, 179 type, 0, &iot, &ioh, NULL, &size, 0)) { 180 printf("%s at 0x%x: can't map registers\n", 181 sc->sc.sc_dev.dv_xname, reg); 182 break; 183 } 184 185 if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, caps) != 0) 186 printf("%s at 0x%x: can't initialize host\n", 187 sc->sc.sc_dev.dv_xname, reg); 188 189 if (type & PCI_MAPREG_MEM_TYPE_64BIT) 190 reg += 4; 191 } 192 } 193 194 int 195 sdhc_pci_activate(struct device *self, int act) 196 { 197 struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self; 198 int rv; 199 200 switch (act) { 201 case DVACT_SUSPEND: 202 rv = sdhc_activate(self, act); 203 break; 204 case DVACT_RESUME: 205 /* Some RICOH controllers need to be bumped into the right mode. */ 206 if (PCI_VENDOR(sc->sc_id) == PCI_VENDOR_RICOH && 207 (PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_RICOH_R5U822 || 208 PCI_PRODUCT(sc->sc_id) == PCI_PRODUCT_RICOH_R5U823)) 209 sdhc_ricohfix(sc); 210 rv = sdhc_activate(self, act); 211 break; 212 default: 213 rv = sdhc_activate(self, act); 214 break; 215 } 216 return (rv); 217 } 218 219 void 220 sdhc_takecontroller(struct pci_attach_args *pa) 221 { 222 pcitag_t tag; 223 pcireg_t id, reg; 224 225 /* Look at func 3 for the flash device */ 226 tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 3); 227 id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG); 228 if (PCI_PRODUCT(id) != PCI_PRODUCT_TI_PCI7XX1_FLASH) 229 return; 230 231 /* 232 * Disable MMC/SD on the flash media controller so the 233 * SD host takes over. 234 */ 235 reg = pci_conf_read(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL); 236 reg |= MMC_SD_DIS; 237 pci_conf_write(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL, reg); 238 } 239 240 void 241 sdhc_ricohfix(struct sdhc_pci_softc *sc) 242 { 243 /* Enable SD2.0 mode. */ 244 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0xfc); 245 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20); 246 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_MODE_KEY, 0x00); 247 248 /* 249 * Some SD/MMC cards don't work with the default base 250 * clock frequency of 200MHz. Lower it to 50Hz. 251 */ 252 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 0x01); 253 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ, 50); 254 sdhc_pci_conf_write(sc->sc_pc, sc->sc_tag, SDHC_PCI_BASE_FREQ_KEY, 0x00); 255 } 256 257 void 258 sdhc_pci_conf_write(pci_chipset_tag_t pc, pcitag_t tag, int reg, uint8_t val) 259 { 260 pcireg_t tmp; 261 262 tmp = pci_conf_read(pc, tag, reg & ~0x3); 263 tmp &= ~(0xff << ((reg & 0x3) * 8)); 264 tmp |= (val << ((reg & 0x3) * 8)); 265 pci_conf_write(pc, tag, reg & ~0x3, tmp); 266 } 267