|
@@ -988,6 +988,64 @@ static void sil24_host_stop(struct ata_host_set *host_set)
|
|
|
kfree(hpriv);
|
|
|
}
|
|
|
|
|
|
+static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
|
|
|
+ unsigned long host_flags,
|
|
|
+ void __iomem *host_base,
|
|
|
+ void __iomem *port_base)
|
|
|
+{
|
|
|
+ u32 tmp;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ /* GPIO off */
|
|
|
+ writel(0, host_base + HOST_FLASH_CMD);
|
|
|
+
|
|
|
+ /* clear global reset & mask interrupts during initialization */
|
|
|
+ writel(0, host_base + HOST_CTRL);
|
|
|
+
|
|
|
+ /* init ports */
|
|
|
+ for (i = 0; i < n_ports; i++) {
|
|
|
+ void __iomem *port = port_base + i * PORT_REGS_SIZE;
|
|
|
+
|
|
|
+ /* Initial PHY setting */
|
|
|
+ writel(0x20c, port + PORT_PHY_CFG);
|
|
|
+
|
|
|
+ /* Clear port RST */
|
|
|
+ tmp = readl(port + PORT_CTRL_STAT);
|
|
|
+ if (tmp & PORT_CS_PORT_RST) {
|
|
|
+ writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
|
|
|
+ tmp = ata_wait_register(port + PORT_CTRL_STAT,
|
|
|
+ PORT_CS_PORT_RST,
|
|
|
+ PORT_CS_PORT_RST, 10, 100);
|
|
|
+ if (tmp & PORT_CS_PORT_RST)
|
|
|
+ dev_printk(KERN_ERR, &pdev->dev,
|
|
|
+ "failed to clear port RST\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Configure IRQ WoC */
|
|
|
+ if (host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
|
|
|
+ writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
|
|
|
+ else
|
|
|
+ writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
|
|
|
+
|
|
|
+ /* Zero error counters. */
|
|
|
+ writel(0x8000, port + PORT_DECODE_ERR_THRESH);
|
|
|
+ writel(0x8000, port + PORT_CRC_ERR_THRESH);
|
|
|
+ writel(0x8000, port + PORT_HSHK_ERR_THRESH);
|
|
|
+ writel(0x0000, port + PORT_DECODE_ERR_CNT);
|
|
|
+ writel(0x0000, port + PORT_CRC_ERR_CNT);
|
|
|
+ writel(0x0000, port + PORT_HSHK_ERR_CNT);
|
|
|
+
|
|
|
+ /* Always use 64bit activation */
|
|
|
+ writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
|
|
|
+
|
|
|
+ /* Clear port multiplier enable and resume bits */
|
|
|
+ writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Turn on interrupts */
|
|
|
+ writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
|
|
|
+}
|
|
|
+
|
|
|
static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
{
|
|
|
static int printed_version = 0;
|
|
@@ -1076,9 +1134,6 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* GPIO off */
|
|
|
- writel(0, host_base + HOST_FLASH_CMD);
|
|
|
-
|
|
|
/* Apply workaround for completion IRQ loss on PCI-X errata */
|
|
|
if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
|
|
|
tmp = readl(host_base + HOST_CTRL);
|
|
@@ -1090,56 +1145,18 @@ static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|
|
probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
|
|
|
}
|
|
|
|
|
|
- /* clear global reset & mask interrupts during initialization */
|
|
|
- writel(0, host_base + HOST_CTRL);
|
|
|
-
|
|
|
for (i = 0; i < probe_ent->n_ports; i++) {
|
|
|
- void __iomem *port = port_base + i * PORT_REGS_SIZE;
|
|
|
- unsigned long portu = (unsigned long)port;
|
|
|
+ unsigned long portu =
|
|
|
+ (unsigned long)port_base + i * PORT_REGS_SIZE;
|
|
|
|
|
|
probe_ent->port[i].cmd_addr = portu;
|
|
|
probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
|
|
|
|
|
|
ata_std_ports(&probe_ent->port[i]);
|
|
|
-
|
|
|
- /* Initial PHY setting */
|
|
|
- writel(0x20c, port + PORT_PHY_CFG);
|
|
|
-
|
|
|
- /* Clear port RST */
|
|
|
- tmp = readl(port + PORT_CTRL_STAT);
|
|
|
- if (tmp & PORT_CS_PORT_RST) {
|
|
|
- writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
|
|
|
- tmp = ata_wait_register(port + PORT_CTRL_STAT,
|
|
|
- PORT_CS_PORT_RST,
|
|
|
- PORT_CS_PORT_RST, 10, 100);
|
|
|
- if (tmp & PORT_CS_PORT_RST)
|
|
|
- dev_printk(KERN_ERR, &pdev->dev,
|
|
|
- "failed to clear port RST\n");
|
|
|
- }
|
|
|
-
|
|
|
- /* Configure IRQ WoC */
|
|
|
- if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
|
|
|
- writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
|
|
|
- else
|
|
|
- writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
|
|
|
-
|
|
|
- /* Zero error counters. */
|
|
|
- writel(0x8000, port + PORT_DECODE_ERR_THRESH);
|
|
|
- writel(0x8000, port + PORT_CRC_ERR_THRESH);
|
|
|
- writel(0x8000, port + PORT_HSHK_ERR_THRESH);
|
|
|
- writel(0x0000, port + PORT_DECODE_ERR_CNT);
|
|
|
- writel(0x0000, port + PORT_CRC_ERR_CNT);
|
|
|
- writel(0x0000, port + PORT_HSHK_ERR_CNT);
|
|
|
-
|
|
|
- /* Always use 64bit activation */
|
|
|
- writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
|
|
|
-
|
|
|
- /* Clear port multiplier enable and resume bits */
|
|
|
- writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
|
|
|
}
|
|
|
|
|
|
- /* Turn on interrupts */
|
|
|
- writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
|
|
|
+ sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
|
|
|
+ host_base, port_base);
|
|
|
|
|
|
pci_set_master(pdev);
|
|
|
|