Commit 931506d3 authored by Anantha Subramanyam's avatar Anantha Subramanyam Committed by Jeff Garzik

sata_svw: Add support for HT1100 SATA controller

This patch adds support (including ATAPI DMA) for HT1100 (aka BCM11000) SATA controller.
Signed-off-by: default avatarAnantha Subramanyam <ananth@broadcom.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 7704a8b6
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/device.h> #include <linux/device.h>
#include <scsi/scsi_host.h> #include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi.h>
#include <linux/libata.h> #include <linux/libata.h>
#ifdef CONFIG_PPC_OF #ifdef CONFIG_PPC_OF
...@@ -59,6 +61,7 @@ enum { ...@@ -59,6 +61,7 @@ enum {
/* ap->flags bits */ /* ap->flags bits */
K2_FLAG_SATA_8_PORTS = (1 << 24), K2_FLAG_SATA_8_PORTS = (1 << 24),
K2_FLAG_NO_ATAPI_DMA = (1 << 25), K2_FLAG_NO_ATAPI_DMA = (1 << 25),
K2_FLAG_BAR_POS_3 = (1 << 26),
/* Taskfile registers offsets */ /* Taskfile registers offsets */
K2_SATA_TF_CMD_OFFSET = 0x00, K2_SATA_TF_CMD_OFFSET = 0x00,
...@@ -88,8 +91,10 @@ enum { ...@@ -88,8 +91,10 @@ enum {
/* Port stride */ /* Port stride */
K2_SATA_PORT_OFFSET = 0x100, K2_SATA_PORT_OFFSET = 0x100,
board_svw4 = 0, chip_svw4 = 0,
board_svw8 = 1, chip_svw8 = 1,
chip_svw42 = 2, /* bar 3 */
chip_svw43 = 3, /* bar 5 */
}; };
static u8 k2_stat_check_status(struct ata_port *ap); static u8 k2_stat_check_status(struct ata_port *ap);
...@@ -97,10 +102,25 @@ static u8 k2_stat_check_status(struct ata_port *ap); ...@@ -97,10 +102,25 @@ static u8 k2_stat_check_status(struct ata_port *ap);
static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc) static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc)
{ {
u8 cmnd = qc->scsicmd->cmnd[0];
if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA) if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA)
return -1; /* ATAPI DMA not supported */ return -1; /* ATAPI DMA not supported */
else {
switch (cmnd) {
case READ_10:
case READ_12:
case READ_16:
case WRITE_10:
case WRITE_12:
case WRITE_16:
return 0;
default:
return -1;
}
return 0; }
} }
static int k2_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val) static int k2_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val)
...@@ -354,7 +374,7 @@ static const struct ata_port_operations k2_sata_ops = { ...@@ -354,7 +374,7 @@ static const struct ata_port_operations k2_sata_ops = {
}; };
static const struct ata_port_info k2_port_info[] = { static const struct ata_port_info k2_port_info[] = {
/* board_svw4 */ /* chip_svw4 */
{ {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
...@@ -363,7 +383,7 @@ static const struct ata_port_info k2_port_info[] = { ...@@ -363,7 +383,7 @@ static const struct ata_port_info k2_port_info[] = {
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops, .port_ops = &k2_sata_ops,
}, },
/* board_svw8 */ /* chip_svw8 */
{ {
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
...@@ -373,6 +393,24 @@ static const struct ata_port_info k2_port_info[] = { ...@@ -373,6 +393,24 @@ static const struct ata_port_info k2_port_info[] = {
.udma_mask = ATA_UDMA6, .udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops, .port_ops = &k2_sata_ops,
}, },
/* chip_svw42 */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
/* chip_svw43 */
{
.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
ATA_FLAG_MMIO,
.pio_mask = 0x1f,
.mwdma_mask = 0x07,
.udma_mask = ATA_UDMA6,
.port_ops = &k2_sata_ops,
},
}; };
static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base) static void k2_sata_setup_port(struct ata_ioports *port, void __iomem *base)
...@@ -402,7 +440,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ...@@ -402,7 +440,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
{ &k2_port_info[ent->driver_data], NULL }; { &k2_port_info[ent->driver_data], NULL };
struct ata_host *host; struct ata_host *host;
void __iomem *mmio_base; void __iomem *mmio_base;
int n_ports, i, rc; int n_ports, i, rc, bar_pos;
if (!printed_version++) if (!printed_version++)
dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n"); dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
...@@ -416,6 +454,9 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ...@@ -416,6 +454,9 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
if (!host) if (!host)
return -ENOMEM; return -ENOMEM;
bar_pos = 5;
if (ppi[0]->flags & K2_FLAG_BAR_POS_3)
bar_pos = 3;
/* /*
* If this driver happens to only be useful on Apple's K2, then * If this driver happens to only be useful on Apple's K2, then
* we should check that here as it has a normal Serverworks ID * we should check that here as it has a normal Serverworks ID
...@@ -428,17 +469,23 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ...@@ -428,17 +469,23 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
* Check if we have resources mapped at all (second function may * Check if we have resources mapped at all (second function may
* have been disabled by firmware) * have been disabled by firmware)
*/ */
if (pci_resource_len(pdev, 5) == 0) if (pci_resource_len(pdev, bar_pos) == 0) {
/* In IDE mode we need to pin the device to ensure that
pcim_release does not clear the busmaster bit in config
space, clearing causes busmaster DMA to fail on
ports 3 & 4 */
pcim_pin_device(pdev);
return -ENODEV; return -ENODEV;
}
/* Request and iomap PCI regions */ /* Request and iomap PCI regions */
rc = pcim_iomap_regions(pdev, 1 << 5, DRV_NAME); rc = pcim_iomap_regions(pdev, 1 << bar_pos, DRV_NAME);
if (rc == -EBUSY) if (rc == -EBUSY)
pcim_pin_device(pdev); pcim_pin_device(pdev);
if (rc) if (rc)
return rc; return rc;
host->iomap = pcim_iomap_table(pdev); host->iomap = pcim_iomap_table(pdev);
mmio_base = host->iomap[5]; mmio_base = host->iomap[bar_pos];
/* different controllers have different number of ports - currently 4 or 8 */ /* different controllers have different number of ports - currently 4 or 8 */
/* All ports are on the same function. Multi-function device is no /* All ports are on the same function. Multi-function device is no
...@@ -483,11 +530,13 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en ...@@ -483,11 +530,13 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en
* controller * controller
* */ * */
static const struct pci_device_id k2_sata_pci_tbl[] = { static const struct pci_device_id k2_sata_pci_tbl[] = {
{ PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 }, { PCI_VDEVICE(SERVERWORKS, 0x0240), chip_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 }, { PCI_VDEVICE(SERVERWORKS, 0x0241), chip_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 }, { PCI_VDEVICE(SERVERWORKS, 0x0242), chip_svw8 },
{ PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 }, { PCI_VDEVICE(SERVERWORKS, 0x024a), chip_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 }, { PCI_VDEVICE(SERVERWORKS, 0x024b), chip_svw4 },
{ PCI_VDEVICE(SERVERWORKS, 0x0410), chip_svw42 },
{ PCI_VDEVICE(SERVERWORKS, 0x0411), chip_svw43 },
{ } { }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment