11.16Smsaitoh/* $NetBSD: gcscide.c,v 1.16 2016/07/11 11:31:49 msaitoh Exp $ */ 21.1Sxtraeme 31.6Sxtraeme/*- 41.6Sxtraeme * Copyright (c) 2007 Juan Romero Pardines. 51.1Sxtraeme * All rights reserved. 61.1Sxtraeme * 71.1Sxtraeme * Redistribution and use in source and binary forms, with or without 81.1Sxtraeme * modification, are permitted provided that the following conditions 91.1Sxtraeme * are met: 101.1Sxtraeme * 1. Redistributions of source code must retain the above copyright 111.1Sxtraeme * notice, this list of conditions and the following disclaimer. 121.1Sxtraeme * 2. Redistributions in binary form must reproduce the above copyright 131.1Sxtraeme * notice, this list of conditions and the following disclaimer in the 141.1Sxtraeme * documentation and/or other materials provided with the distribution. 151.1Sxtraeme * 161.6Sxtraeme * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 171.6Sxtraeme * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 181.6Sxtraeme * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 191.6Sxtraeme * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 201.6Sxtraeme * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 211.6Sxtraeme * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 221.6Sxtraeme * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 231.6Sxtraeme * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 241.6Sxtraeme * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 251.6Sxtraeme * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 261.1Sxtraeme */ 271.1Sxtraeme 281.1Sxtraeme/* 291.3Sxtraeme * Driver for the IDE Controller of the National Semiconductor/AMD 301.3Sxtraeme * CS5535 Companion device. Available on systems with an AMD Geode GX2 311.3Sxtraeme * CPU, for example the decTOP. 321.1Sxtraeme * 331.1Sxtraeme * Datasheet at: 341.1Sxtraeme * 351.1Sxtraeme * http://www.amd.com/files/connectivitysolutions/geode/geode_gx/31506_cs5535_databook.pdf 361.1Sxtraeme */ 371.1Sxtraeme 381.1Sxtraeme#include <sys/cdefs.h> 391.16Smsaitoh__KERNEL_RCSID(0, "$NetBSD: gcscide.c,v 1.16 2016/07/11 11:31:49 msaitoh Exp $"); 401.1Sxtraeme 411.1Sxtraeme#include <sys/param.h> 421.1Sxtraeme#include <sys/systm.h> 431.1Sxtraeme 441.1Sxtraeme#include <dev/pci/pcivar.h> 451.1Sxtraeme#include <dev/pci/pcidevs.h> 461.1Sxtraeme#include <dev/pci/pciidereg.h> 471.1Sxtraeme#include <dev/pci/pciidevar.h> 481.1Sxtraeme 491.1Sxtraeme#include <machine/cpufunc.h> 501.1Sxtraeme 511.16Smsaitoh/* 521.5Sxtraeme * 6.4 - ATA-5 Controller Register Definitions. 531.5Sxtraeme */ 541.1Sxtraeme#define GCSCIDE_MSR_ATAC_BASE 0x51300000 551.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_CAP (GCSCIDE_MSR_ATAC_BASE + 0) 561.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_CONFIG (GCSCIDE_MSR_ATAC_BASE + 0x01) 571.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_SMI (GCSCIDE_MSR_ATAC_BASE + 0x02) 581.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_ERROR (GCSCIDE_MSR_ATAC_BASE + 0x03) 591.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_PM (GCSCIDE_MSR_ATAC_BASE + 0x04) 601.1Sxtraeme#define GCSCIDE_ATAC_GLD_MSR_DIAG (GCSCIDE_MSR_ATAC_BASE + 0x05) 611.1Sxtraeme#define GCSCIDE_ATAC_IO_BAR (GCSCIDE_MSR_ATAC_BASE + 0x08) 621.1Sxtraeme#define GCSCIDE_ATAC_RESET (GCSCIDE_MSR_ATAC_BASE + 0x10) 631.1Sxtraeme#define GCSCIDE_ATAC_CH0D0_PIO (GCSCIDE_MSR_ATAC_BASE + 0x20) 641.1Sxtraeme#define GCSCIDE_ATAC_CH0D0_DMA (GCSCIDE_MSR_ATAC_BASE + 0x21) 651.1Sxtraeme#define GCSCIDE_ATAC_CH0D1_PIO (GCSCIDE_MSR_ATAC_BASE + 0x22) 661.1Sxtraeme#define GCSCIDE_ATAC_CH0D1_DMA (GCSCIDE_MSR_ATAC_BASE + 0x23) 671.1Sxtraeme#define GCSCIDE_ATAC_PCI_ABRTERR (GCSCIDE_MSR_ATAC_BASE + 0x24) 681.1Sxtraeme#define GCSCIDE_ATAC_BM0_CMD_PRIM 0x00 691.1Sxtraeme#define GCSCIDE_ATAC_BM0_STS_PRIM 0x02 701.1Sxtraeme#define GCSCIDE_ATAC_BM0_PRD 0x04 711.5Sxtraeme/* 721.5Sxtraeme * ATAC_CH0D0_DMA registers: 731.5Sxtraeme * 741.5Sxtraeme * PIO Format (bit 31): Format 1 allows independent control of command 751.5Sxtraeme * and data per drive, while Format 0 selects the slowest speed 761.5Sxtraeme * of the two drives. 771.5Sxtraeme */ 781.5Sxtraeme#define GCSCIDE_ATAC_PIO_FORMAT (1 << 31) /* PIO Mode Format 1 */ 791.5Sxtraeme/* 801.5Sxtraeme * DMA_SEL (bit 20): sets Ultra DMA mode (if enabled) or Multi-word 811.5Sxtraeme * DMA mode (if disabled). 821.5Sxtraeme */ 831.5Sxtraeme#define GCSCIDE_ATAC_DMA_SEL (1 << 20) 841.1Sxtraeme 851.7Scubestatic int gcscide_match(device_t, cfdata_t, void *); 861.7Scubestatic void gcscide_attach(device_t, device_t, void *); 871.1Sxtraeme 881.16Smsaitohstatic void gcscide_chip_map(struct pciide_softc *, 891.16Smsaitoh const struct pci_attach_args *); 901.1Sxtraemestatic void gcscide_setup_channel(struct ata_channel *); 911.1Sxtraeme 921.5Sxtraeme/* PIO Format 1 settings */ 931.1Sxtraemestatic const uint32_t gcscide_pio_timings[] = { 941.1Sxtraeme 0xf7f4f7f4, /* PIO Mode 0 */ 951.1Sxtraeme 0x53f3f173, /* PIO Mode 1 */ 961.1Sxtraeme 0x13f18141, /* PIO Mode 2 */ 971.1Sxtraeme 0x51315131, /* PIO Mode 3 */ 981.1Sxtraeme 0x11311131 /* PIO Mode 4 */ 991.1Sxtraeme}; 1001.1Sxtraeme 1011.1Sxtraemestatic const uint32_t gcscide_mdma_timings[] = { 1021.1Sxtraeme 0x7f0ffff3, /* MDMA Mode 0 */ 1031.1Sxtraeme 0x7f035352, /* MDMA Mode 1 */ 1041.1Sxtraeme 0x7f024241 /* MDMA Mode 2 */ 1051.1Sxtraeme}; 1061.1Sxtraeme 1071.1Sxtraemestatic const uint32_t gcscide_udma_timings[] = { 1081.1Sxtraeme 0x7f7436a1, /* Ultra DMA Mode 0 */ 1091.1Sxtraeme 0x7f733481, /* Ultra DMA Mode 1 */ 1101.1Sxtraeme 0x7f723261, /* Ultra DMA Mode 2 */ 1111.1Sxtraeme 0x7f713161, /* Ultra DMA Mode 3 */ 1121.1Sxtraeme 0x7f703061 /* Ultra DMA Mode 4 */ 1131.1Sxtraeme}; 1141.1Sxtraeme 1151.7ScubeCFATTACH_DECL_NEW(gcscide, sizeof(struct pciide_softc), 1161.15Sjakllsch gcscide_match, gcscide_attach, pciide_detach, NULL); 1171.1Sxtraeme 1181.1Sxtraemestatic const struct pciide_product_desc pciide_gcscide_products[] = { 1191.1Sxtraeme { 1201.1Sxtraeme PCI_PRODUCT_NS_CS5535_IDE, 1211.1Sxtraeme 0, 1221.1Sxtraeme "National Semiconductor/AMD CS5535 IDE Controller", 1231.1Sxtraeme gcscide_chip_map 1241.1Sxtraeme }, 1251.1Sxtraeme { 0, 0, NULL, NULL } 1261.1Sxtraeme}; 1271.1Sxtraeme 1281.1Sxtraemestatic int 1291.7Scubegcscide_match(device_t parent, cfdata_t cfdata, void *aux) 1301.1Sxtraeme{ 1311.1Sxtraeme struct pci_attach_args *pa = (struct pci_attach_args *)aux; 1321.1Sxtraeme 1331.1Sxtraeme if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_NS && 1341.1Sxtraeme PCI_CLASS(pa->pa_class) == PCI_CLASS_MASS_STORAGE && 1351.1Sxtraeme PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_MASS_STORAGE_IDE && 1361.1Sxtraeme pciide_lookup_product(pa->pa_id, pciide_gcscide_products)) 1371.1Sxtraeme return 2; 1381.1Sxtraeme return 0; 1391.1Sxtraeme} 1401.1Sxtraeme 1411.1Sxtraemestatic void 1421.7Scubegcscide_attach(device_t parent, device_t self, void *aux) 1431.1Sxtraeme{ 1441.1Sxtraeme struct pci_attach_args *pa = aux; 1451.7Scube struct pciide_softc *sc = device_private(self); 1461.7Scube 1471.7Scube sc->sc_wdcdev.sc_atac.atac_dev = self; 1481.1Sxtraeme 1491.1Sxtraeme pciide_common_attach(sc, pa, 1501.1Sxtraeme pciide_lookup_product(pa->pa_id, pciide_gcscide_products)); 1511.1Sxtraeme} 1521.1Sxtraeme 1531.1Sxtraemestatic void 1541.9Sdyounggcscide_chip_map(struct pciide_softc *sc, const struct pci_attach_args *pa) 1551.1Sxtraeme{ 1561.1Sxtraeme pcireg_t interface; 1571.1Sxtraeme 1581.1Sxtraeme if (pciide_chipen(sc, pa) == 0) 1591.1Sxtraeme return; 1601.1Sxtraeme 1611.7Scube aprint_verbose_dev(sc->sc_wdcdev.sc_atac.atac_dev, 1621.7Scube "bus-master DMA support present"); 1631.1Sxtraeme pciide_mapreg_dma(sc, pa); 1641.1Sxtraeme aprint_verbose("\n"); 1651.1Sxtraeme 1661.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_cap = ATAC_CAP_DATA16 | ATAC_CAP_DATA32; 1671.1Sxtraeme if (sc->sc_dma_ok) { 1681.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_cap |= ATAC_CAP_DMA | ATAC_CAP_UDMA; 1691.1Sxtraeme sc->sc_wdcdev.irqack = pciide_irqack; 1701.1Sxtraeme } 1711.1Sxtraeme 1721.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_pio_cap = 4; 1731.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_dma_cap = 2; 1741.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_udma_cap = 4; 1751.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_set_modes = gcscide_setup_channel; 1761.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_channels = sc->wdc_chanarray; 1771.1Sxtraeme sc->sc_wdcdev.sc_atac.atac_nchannels = 1; 1781.1Sxtraeme 1791.1Sxtraeme interface = PCI_INTERFACE(pa->pa_class); 1801.1Sxtraeme 1811.1Sxtraeme wdc_allocate_regs(&sc->sc_wdcdev); 1821.1Sxtraeme 1831.1Sxtraeme if (pciide_chansetup(sc, 0, interface) == 0) 1841.1Sxtraeme return; 1851.1Sxtraeme 1861.1Sxtraeme pciide_mapchan(pa, &sc->pciide_channels[0], interface, 1871.8Sjakllsch pciide_pci_intr); 1881.1Sxtraeme} 1891.1Sxtraeme 1901.1Sxtraemestatic void 1911.1Sxtraemegcscide_setup_channel(struct ata_channel *chp) 1921.1Sxtraeme{ 1931.1Sxtraeme struct pciide_channel *cp = CHAN_TO_PCHAN(chp); 1941.1Sxtraeme struct ata_drive_datas *drvp; 1951.1Sxtraeme uint64_t reg = 0; 1961.1Sxtraeme int drive, s; 1971.1Sxtraeme 1981.1Sxtraeme pciide_channel_dma_setup(cp); 1991.1Sxtraeme 2001.1Sxtraeme for (drive = 0; drive < 2; drive++) { 2011.1Sxtraeme drvp = &chp->ch_drive[drive]; 2021.14Sbouyer if (drvp->drive_type == ATA_DRIVET_NONE) 2031.1Sxtraeme continue; 2041.5Sxtraeme 2051.5Sxtraeme reg = rdmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 2061.5Sxtraeme GCSCIDE_ATAC_CH0D0_DMA); 2071.1Sxtraeme 2081.14Sbouyer if (drvp->drive_flags & ATA_DRIVE_UDMA) { 2091.1Sxtraeme s = splbio(); 2101.14Sbouyer drvp->drive_flags &= ~ATA_DRIVE_DMA; 2111.1Sxtraeme splx(s); 2121.5Sxtraeme /* Enable the Ultra DMA mode bit */ 2131.5Sxtraeme reg |= GCSCIDE_ATAC_DMA_SEL; 2141.5Sxtraeme /* set the Ultra DMA mode */ 2151.1Sxtraeme reg |= gcscide_udma_timings[drvp->UDMA_mode]; 2161.1Sxtraeme 2171.1Sxtraeme wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 2181.1Sxtraeme GCSCIDE_ATAC_CH0D0_DMA, reg); 2191.1Sxtraeme 2201.14Sbouyer } else if (drvp->drive_flags & ATA_DRIVE_DMA) { 2211.5Sxtraeme /* Enable the Multi-word DMA bit */ 2221.5Sxtraeme reg &= ~GCSCIDE_ATAC_DMA_SEL; 2231.5Sxtraeme /* set the Multi-word DMA mode */ 2241.1Sxtraeme reg |= gcscide_mdma_timings[drvp->DMA_mode]; 2251.1Sxtraeme 2261.1Sxtraeme wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 2271.1Sxtraeme GCSCIDE_ATAC_CH0D0_DMA, reg); 2281.1Sxtraeme } 2291.5Sxtraeme 2301.5Sxtraeme /* Always use PIO Format 1. */ 2311.5Sxtraeme wrmsr(drive ? GCSCIDE_ATAC_CH0D1_DMA : 2321.5Sxtraeme GCSCIDE_ATAC_CH0D0_DMA, reg | GCSCIDE_ATAC_PIO_FORMAT); 2331.5Sxtraeme 2341.5Sxtraeme /* Set PIO mode */ 2351.4Sxtraeme wrmsr(drive ? GCSCIDE_ATAC_CH0D1_PIO : GCSCIDE_ATAC_CH0D0_PIO, 2361.1Sxtraeme gcscide_pio_timings[drvp->PIO_mode]); 2371.1Sxtraeme } 2381.1Sxtraeme} 239