linux/drivers/ata/sata_sis.c
<<
>>
Prefs
   1/*
   2 *  sata_sis.c - Silicon Integrated Systems SATA
   3 *
   4 *  Maintained by:  Uwe Koziolek
   5 *                  Please ALWAYS copy linux-ide@vger.kernel.org
   6 *                  on emails.
   7 *
   8 *  Copyright 2004 Uwe Koziolek
   9 *
  10 *
  11 *  This program is free software; you can redistribute it and/or modify
  12 *  it under the terms of the GNU General Public License as published by
  13 *  the Free Software Foundation; either version 2, or (at your option)
  14 *  any later version.
  15 *
  16 *  This program is distributed in the hope that it will be useful,
  17 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 *  GNU General Public License for more details.
  20 *
  21 *  You should have received a copy of the GNU General Public License
  22 *  along with this program; see the file COPYING.  If not, write to
  23 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24 *
  25 *
  26 *  libata documentation is available via 'make {ps|pdf}docs',
  27 *  as Documentation/DocBook/libata.*
  28 *
  29 *  Hardware documentation available under NDA.
  30 *
  31 */
  32
  33#include <linux/kernel.h>
  34#include <linux/module.h>
  35#include <linux/pci.h>
  36#include <linux/init.h>
  37#include <linux/blkdev.h>
  38#include <linux/delay.h>
  39#include <linux/interrupt.h>
  40#include <linux/device.h>
  41#include <scsi/scsi_host.h>
  42#include <linux/libata.h>
  43#include "sis.h"
  44
  45#define DRV_NAME        "sata_sis"
  46#define DRV_VERSION     "1.0"
  47
  48enum {
  49        sis_180                 = 0,
  50        SIS_SCR_PCI_BAR         = 5,
  51
  52        /* PCI configuration registers */
  53        SIS_GENCTL              = 0x54, /* IDE General Control register */
  54        SIS_SCR_BASE            = 0xc0, /* sata0 phy SCR registers */
  55        SIS180_SATA1_OFS        = 0x10, /* offset from sata0->sata1 phy regs */
  56        SIS182_SATA1_OFS        = 0x20, /* offset from sata0->sata1 phy regs */
  57        SIS_PMR                 = 0x90, /* port mapping register */
  58        SIS_PMR_COMBINED        = 0x30,
  59
  60        /* random bits */
  61        SIS_FLAG_CFGSCR         = (1 << 30), /* host flag: SCRs via PCI cfg */
  62
  63        GENCTL_IOMAPPED_SCR     = (1 << 26), /* if set, SCRs are in IO space */
  64};
  65
  66static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
  67static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
  68static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
  69
  70static const struct pci_device_id sis_pci_tbl[] = {
  71        { PCI_VDEVICE(SI, 0x0180), sis_180 },   /* SiS 964/180 */
  72        { PCI_VDEVICE(SI, 0x0181), sis_180 },   /* SiS 964/180 */
  73        { PCI_VDEVICE(SI, 0x0182), sis_180 },   /* SiS 965/965L */
  74        { PCI_VDEVICE(SI, 0x0183), sis_180 },   /* SiS 965/965L */
  75        { PCI_VDEVICE(SI, 0x1182), sis_180 },   /* SiS 966/680 */
  76        { PCI_VDEVICE(SI, 0x1183), sis_180 },   /* SiS 966/966L/968/680 */
  77
  78        { }     /* terminate list */
  79};
  80
  81static struct pci_driver sis_pci_driver = {
  82        .name                   = DRV_NAME,
  83        .id_table               = sis_pci_tbl,
  84        .probe                  = sis_init_one,
  85        .remove                 = ata_pci_remove_one,
  86};
  87
  88static struct scsi_host_template sis_sht = {
  89        ATA_BMDMA_SHT(DRV_NAME),
  90};
  91
  92static struct ata_port_operations sis_ops = {
  93        .inherits               = &ata_bmdma_port_ops,
  94        .scr_read               = sis_scr_read,
  95        .scr_write              = sis_scr_write,
  96};
  97
  98static const struct ata_port_info sis_port_info = {
  99        .flags          = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
 100        .pio_mask       = ATA_PIO4,
 101        .mwdma_mask     = ATA_MWDMA2,
 102        .udma_mask      = ATA_UDMA6,
 103        .port_ops       = &sis_ops,
 104};
 105
 106MODULE_AUTHOR("Uwe Koziolek");
 107MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
 108MODULE_LICENSE("GPL");
 109MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 110MODULE_VERSION(DRV_VERSION);
 111
 112static unsigned int get_scr_cfg_addr(struct ata_link *link, unsigned int sc_reg)
 113{
 114        struct ata_port *ap = link->ap;
 115        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 116        unsigned int addr = SIS_SCR_BASE + (4 * sc_reg);
 117        u8 pmr;
 118
 119        if (ap->port_no)  {
 120                switch (pdev->device) {
 121                case 0x0180:
 122                case 0x0181:
 123                        pci_read_config_byte(pdev, SIS_PMR, &pmr);
 124                        if ((pmr & SIS_PMR_COMBINED) == 0)
 125                                addr += SIS180_SATA1_OFS;
 126                        break;
 127
 128                case 0x0182:
 129                case 0x0183:
 130                case 0x1182:
 131                        addr += SIS182_SATA1_OFS;
 132                        break;
 133                }
 134        }
 135        if (link->pmp)
 136                addr += 0x10;
 137
 138        return addr;
 139}
 140
 141static u32 sis_scr_cfg_read(struct ata_link *link,
 142                            unsigned int sc_reg, u32 *val)
 143{
 144        struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
 145        unsigned int cfg_addr = get_scr_cfg_addr(link, sc_reg);
 146
 147        if (sc_reg == SCR_ERROR) /* doesn't exist in PCI cfg space */
 148                return -EINVAL;
 149
 150        pci_read_config_dword(pdev, cfg_addr, val);
 151        return 0;
 152}
 153
 154static int sis_scr_cfg_write(struct ata_link *link,
 155                             unsigned int sc_reg, u32 val)
 156{
 157        struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
 158        unsigned int cfg_addr = get_scr_cfg_addr(link, sc_reg);
 159
 160        pci_write_config_dword(pdev, cfg_addr, val);
 161        return 0;
 162}
 163
 164static int sis_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
 165{
 166        struct ata_port *ap = link->ap;
 167        void __iomem *base = ap->ioaddr.scr_addr + link->pmp * 0x10;
 168
 169        if (sc_reg > SCR_CONTROL)
 170                return -EINVAL;
 171
 172        if (ap->flags & SIS_FLAG_CFGSCR)
 173                return sis_scr_cfg_read(link, sc_reg, val);
 174
 175        *val = ioread32(base + sc_reg * 4);
 176        return 0;
 177}
 178
 179static int sis_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
 180{
 181        struct ata_port *ap = link->ap;
 182        void __iomem *base = ap->ioaddr.scr_addr + link->pmp * 0x10;
 183
 184        if (sc_reg > SCR_CONTROL)
 185                return -EINVAL;
 186
 187        if (ap->flags & SIS_FLAG_CFGSCR)
 188                return sis_scr_cfg_write(link, sc_reg, val);
 189
 190        iowrite32(val, base + (sc_reg * 4));
 191        return 0;
 192}
 193
 194static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 195{
 196        static int printed_version;
 197        struct ata_port_info pi = sis_port_info;
 198        const struct ata_port_info *ppi[] = { &pi, &pi };
 199        struct ata_host *host;
 200        u32 genctl, val;
 201        u8 pmr;
 202        u8 port2_start = 0x20;
 203        int i, rc;
 204
 205        if (!printed_version++)
 206                dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n");
 207
 208        rc = pcim_enable_device(pdev);
 209        if (rc)
 210                return rc;
 211
 212        /* check and see if the SCRs are in IO space or PCI cfg space */
 213        pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
 214        if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
 215                pi.flags |= SIS_FLAG_CFGSCR;
 216
 217        /* if hardware thinks SCRs are in IO space, but there are
 218         * no IO resources assigned, change to PCI cfg space.
 219         */
 220        if ((!(pi.flags & SIS_FLAG_CFGSCR)) &&
 221            ((pci_resource_start(pdev, SIS_SCR_PCI_BAR) == 0) ||
 222             (pci_resource_len(pdev, SIS_SCR_PCI_BAR) < 128))) {
 223                genctl &= ~GENCTL_IOMAPPED_SCR;
 224                pci_write_config_dword(pdev, SIS_GENCTL, genctl);
 225                pi.flags |= SIS_FLAG_CFGSCR;
 226        }
 227
 228        pci_read_config_byte(pdev, SIS_PMR, &pmr);
 229        switch (ent->device) {
 230        case 0x0180:
 231        case 0x0181:
 232
 233                /* The PATA-handling is provided by pata_sis */
 234                switch (pmr & 0x30) {
 235                case 0x10:
 236                        ppi[1] = &sis_info133_for_sata;
 237                        break;
 238
 239                case 0x30:
 240                        ppi[0] = &sis_info133_for_sata;
 241                        break;
 242                }
 243                if ((pmr & SIS_PMR_COMBINED) == 0) {
 244                        dev_printk(KERN_INFO, &pdev->dev,
 245                                   "Detected SiS 180/181/964 chipset in SATA mode\n");
 246                        port2_start = 64;
 247                } else {
 248                        dev_printk(KERN_INFO, &pdev->dev,
 249                                   "Detected SiS 180/181 chipset in combined mode\n");
 250                        port2_start = 0;
 251                        pi.flags |= ATA_FLAG_SLAVE_POSS;
 252                }
 253                break;
 254
 255        case 0x0182:
 256        case 0x0183:
 257                pci_read_config_dword(pdev, 0x6C, &val);
 258                if (val & (1L << 31)) {
 259                        dev_printk(KERN_INFO, &pdev->dev,
 260                                   "Detected SiS 182/965 chipset\n");
 261                        pi.flags |= ATA_FLAG_SLAVE_POSS;
 262                } else {
 263                        dev_printk(KERN_INFO, &pdev->dev,
 264                                   "Detected SiS 182/965L chipset\n");
 265                }
 266                break;
 267
 268        case 0x1182:
 269                dev_printk(KERN_INFO, &pdev->dev,
 270                           "Detected SiS 1182/966/680 SATA controller\n");
 271                pi.flags |= ATA_FLAG_SLAVE_POSS;
 272                break;
 273
 274        case 0x1183:
 275                dev_printk(KERN_INFO, &pdev->dev,
 276                           "Detected SiS 1183/966/966L/968/680 controller in PATA mode\n");
 277                ppi[0] = &sis_info133_for_sata;
 278                ppi[1] = &sis_info133_for_sata;
 279                break;
 280        }
 281
 282        rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
 283        if (rc)
 284                return rc;
 285
 286        for (i = 0; i < 2; i++) {
 287                struct ata_port *ap = host->ports[i];
 288
 289                if (ap->flags & ATA_FLAG_SATA &&
 290                    ap->flags & ATA_FLAG_SLAVE_POSS) {
 291                        rc = ata_slave_link_init(ap);
 292                        if (rc)
 293                                return rc;
 294                }
 295        }
 296
 297        if (!(pi.flags & SIS_FLAG_CFGSCR)) {
 298                void __iomem *mmio;
 299
 300                rc = pcim_iomap_regions(pdev, 1 << SIS_SCR_PCI_BAR, DRV_NAME);
 301                if (rc)
 302                        return rc;
 303                mmio = host->iomap[SIS_SCR_PCI_BAR];
 304
 305                host->ports[0]->ioaddr.scr_addr = mmio;
 306                host->ports[1]->ioaddr.scr_addr = mmio + port2_start;
 307        }
 308
 309        pci_set_master(pdev);
 310        pci_intx(pdev, 1);
 311        return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
 312                                 IRQF_SHARED, &sis_sht);
 313}
 314
 315static int __init sis_init(void)
 316{
 317        return pci_register_driver(&sis_pci_driver);
 318}
 319
 320static void __exit sis_exit(void)
 321{
 322        pci_unregister_driver(&sis_pci_driver);
 323}
 324
 325module_init(sis_init);
 326module_exit(sis_exit);
 327