1 /* $NetBSD: gcscide.c,v 1.16 2016/07/11 11:31:49 msaitoh Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 Juan Romero Pardines. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * Driver for the IDE Controller of the National Semiconductor/AMD 30 * CS5535 Companion device. Available on systems with an AMD Geode GX2 31 * CPU, for example the decTOP. 32 * 33 * Datasheet at: 34 * 35 * http://www.amd.com/files/connectivitysolutions/geode/geode_gx/31506_cs5535_databook.pdf 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: gcscide.c,v 1.16 2016/07/11 11:31:49 msaitoh Exp $"); 40 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 44 #include <dev/pci/pcivar.h> 45 #include <dev/pci/pcidevs.h> 46 #include <dev/pci/pciidereg.h> 47 #include <dev/pci/pciidevar.h> 48 49 #include <machine/cpufunc.h> 50 51 /* 52 * 6.4 - ATA-5 Controller Register Definitions. 53 */ 54 #define GCSCIDE_MSR_ATAC_BASE 0x51300000 55 #define GCSCIDE_ATAC_GLD_MSR_CAP (GCSCIDE_MSR_ATAC_BASE + 0) 56 #define GCSCIDE_ATAC_GLD_MSR_CONFIG (GCSCIDE_MSR_ATAC_BASE + 0x01) 57 #define GCSCIDE_ATAC_GLD_MSR_SMI (GCSCIDE_MSR_ATAC_BASE + 0x02) 58 #define GCSCIDE_ATAC_GLD_MSR_ERROR (GCSCIDE_MSR_ATAC_BASE + 0x03) 59 #define GCSCIDE_ATAC_GLD_MSR_PM (GCSCIDE_MSR_ATAC_BASE + 0x04) 60 #define GCSCIDE_ATAC_GLD_MSR_DIAG (GCSCIDE_MSR_ATAC_BASE + 0x05) 61 #define GCSCIDE_ATAC_IO_BAR (GCSCIDE_MSR_ATAC_BASE + 0x08) 62 #define GCSCIDE_ATAC_RESET (GCSCIDE_MSR_ATAC_BASE + 0x10) 63 #define GCSCIDE_ATAC_CH0D0_PIO (GCSCIDE_MSR_ATAC_BASE + 0x20) 64 #define GCSCIDE_ATAC_CH0D0_DMA (GCSCIDE_MSR_ATAC_BASE + 0x21) 65 #define GCSCIDE_ATAC_CH0D1_PIO (GCSCIDE_MSR_ATAC_BASE + 0x22) 66 #define GCSCIDE_ATAC_CH0D1_DMA (GCSCIDE_MSR_ATAC_BASE + 0x23) 67 #define GCSCIDE_ATAC_PCI_ABRTERR (GCSCIDE_MSR_ATAC_BASE + 0x24) 68 #define GCSCIDE_ATAC_BM0_CMD_PRIM 0x00 69 #define GCSCIDE_ATAC_BM0_STS_PRIM 0x02 70 #define GCSCIDE_ATAC_BM0_PRD 0x04 71 /* 72 * ATAC_CH0D0_DMA registers: 73 * 74 * PIO Format (bit 31): Format 1 allows independent control of command 75 * and data per drive, while Format 0 selects the slowest speed 76 * of the two drives. 77 */ 78 #define GCSCIDE_ATAC_PIO_FORMAT (1 << 31) /* PIO Mode Format 1 */ 79 /* 80 * DMA_SEL (bit 20): sets Ultra DMA mode (if enabled) or Multi-word 81 * DMA mode (if disabled). 82 */ 83 #define GCSCIDE_ATAC_DMA_SEL (1 << 20) 84 85 static int gcscide_match(device_t, cfdata_t, void *); 86 static void gcscide_attach(device_t, device_t, void *); 87 88 static void gcscide_chip_map(struct pciide_softc *, 89 const struct pci_attach_args *); 90 static void gcscide_setup_channel(struct ata_channel *); 91 92 /* PIO Format 1 settings */ 93 static const uint32_t gcscide_pio_timings[] = { 94 0xf7f4f7f4, /* PIO Mode 0 */ 95 0x53f3f173, /* PIO Mode 1 */ 96 0x13f18141, /* PIO Mode 2 */ 97 0x51315131, /* PIO Mode 3 */ 98 0x11311131 /* PIO Mode 4 */ 99 }; 100 101 static const uint32_t gcscide_mdma_timings[] = { 102 0x7f0ffff3, /* MDMA Mode 0 */ 103 0x7f035352, /* MDMA Mode 1 */ 104 0x7f024241 /* MDMA Mode 2 */ 105 }; 106 107 static const uint32_t gcscide_udma_timings[] = { 108 0x7f7436a1, /* Ultra DMA Mode 0 */ 109 0x7f733481, /* Ultra DMA Mode 1 */ 110 0x7f723261, /* Ultra DMA Mode 2 */ 111 0x7f713161, /* Ultra DMA Mode 3 */ 112 0x7f703061 /* Ultra DMA Mode 4 */ 113 }; 114 115 CFATTACH_DECL_NEW(gcscide, sizeof(struct pciide_softc), 116 gcscide_match, gcscide_attach, pciide_detach, NULL); 117 118 static const struct pciide_product_desc pciide_gcscide_products[] = { 119 { 120 PCI_PRODUCT_NS_CS5535_IDE, 121 0, 122 "National Semiconductor/AMD CS5535 IDE Controller", 123 gcscide_chip_map 124 }, 125 { 0, 0, NULL, NULL } 126 }; 127 128 static int 129 gcscide_match(device_t parent, cfdata_t cfdata, void *aux) 130 { 131 struct pci_attach_args *pa = (struct pci_attach_args *)aux; 132 133 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS && 134 PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE && 135 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE && 136 pciide_lookup_product(pa->pa_id, pciide_gcscide_products)) 137 return 2; 138 return 0; 139 } 140 141 static void 142 gcscide_attach(device_t parent, device_t self, void *aux) 143 { 144 struct pci_attach_args *pa = aux; 145 struct pciide_softc *sc = device_private(self); 146 147 sc->sc_wdcdev.sc_atac.atac_dev = self; 148 149 pciide_common_attach(sc, pa, 150 pciide_lookup_product(pa->pa_id, pciide_gcscide_products)); 151 } 152 153 static void 154 gcscide_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 155 { 156 pcireg_t interface; 157 158 if (pciide_chipen(sc, pa) == 0) 159 return; 160 161 aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 162 "bus-master DMA support present"); 163 pciide_mapreg_dma(sc, pa); 164 aprint_verbose("\n"); 165 166 sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 167 if (sc->sc_dma_ok) { 168 sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 169 sc->sc_wdcdev.irqack = pciide_irqack; 170 } 171 172 sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 173 sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 174 sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; 175 sc->sc_wdcdev.sc_atac.atac_set_modes = gcscide_setup_channel; 176 sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 177 sc->sc_wdcdev.sc_atac.atac_nchannels = 1; 178 179 interface = PCI_INTERFACE(pa->pa_class); 180 181 wdc_allocate_regs(&sc->sc_wdcdev); 182 183 if (pciide_chansetup(sc, 0, interface) == 0) 184 return; 185 186 pciide_mapchan(pa, &sc->pciide_channels[0], interface, 187 pciide_pci_intr); 188 } 189 190 static void 191 gcscide_setup_channel(struct ata_channel *chp) 192 { 193 struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 194 struct ata_drive_datas *drvp; 195 uint64_t reg = 0; 196 int drive, s; 197 198 pciide_channel_dma_setup(cp); 199 200 for (drive = 0; drive < 2; drive++) { 201 drvp = &chp->ch_drive[drive]; 202 if (drvp->drive_type == ATA_DRIVET_NONE) 203 continue; 204 205 reg = rdmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 206 GCSCIDE_ATAC_CH0D0_DMA); 207 208 if (drvp->drive_flags & ATA_DRIVE_UDMA) { 209 s = splbio(); 210 drvp->drive_flags &= ~ATA_DRIVE_DMA; 211 splx(s); 212 /* Enable the Ultra DMA mode bit */ 213 reg |= GCSCIDE_ATAC_DMA_SEL; 214 /* set the Ultra DMA mode */ 215 reg |= gcscide_udma_timings[drvp->UDMA_mode]; 216 217 wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 218 GCSCIDE_ATAC_CH0D0_DMA, reg); 219 220 } else if (drvp->drive_flags & ATA_DRIVE_DMA) { 221 /* Enable the Multi-word DMA bit */ 222 reg &= ~GCSCIDE_ATAC_DMA_SEL; 223 /* set the Multi-word DMA mode */ 224 reg |= gcscide_mdma_timings[drvp->DMA_mode]; 225 226 wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 227 GCSCIDE_ATAC_CH0D0_DMA, reg); 228 } 229 230 /* Always use PIO Format 1. */ 231 wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 232 GCSCIDE_ATAC_CH0D0_DMA, reg | GCSCIDE_ATAC_PIO_FORMAT); 233 234 /* Set PIO mode */ 235 wrmsr(drive ? GCSCIDE_ATAC_CH0D1_PIO : GCSCIDE_ATAC_CH0D0_PIO, 236 gcscide_pio_timings[drvp->PIO_mode]); 237 } 238 } 239