===================================================================
@@ -32,6 +32,8 @@
#define ATA_SECTOR_WORDS (ATA_SECT_SIZE/2)
#define mdelay(n) udelay((n)*1000)
+#define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v))
+
extern block_dev_desc_t sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE];
static struct pci_device_id supported[] = {
@@ -135,15 +137,20 @@
struct sil_sata *sata = (struct sil_sata *)sata_dev_desc[dev].priv;
void __iomem *port = sata->port;
struct sil_prb *prb;
+ int i;
+ u32 *src, *dst;
prb = port + PORT_LRAM + tag * PORT_LRAM_SLOT_SZ;
- memcpy(fis, &prb->fis, sizeof(struct sata_fis_h2d));
+ src = (u32 *)&prb->fis;
+ dst = (u32 *)fis;
+ for (i = 0; i < sizeof(struct sata_fis_h2d); i += 4)
+ *dst++ = readl(src++);
}
static int sil_exec_cmd(int dev, struct sil_cmd_block *pcmd, int tag)
{
struct sil_sata *sata = (struct sil_sata *)sata_dev_desc[dev].priv;
void __iomem *port = sata->port;
- u64 paddr = (ulong)pcmd;
+ u64 paddr = virt_to_bus(sata_info.devno, pcmd);
u32 irq_mask, irq_stat;
int rc;
@@ -225,7 +232,7 @@
pcmd->prb.fis.fis_type = SATA_FIS_TYPE_REGISTER_H2D;
pcmd->prb.fis.pm_port_c = (1 << 7);
pcmd->prb.fis.command = ATA_CMD_ID_ATA;
- pcmd->sge.addr = cpu_to_le64((ulong)id);
+ pcmd->sge.addr = cpu_to_le64(virt_to_bus(sata_info.devno, id));
pcmd->sge.cnt = cpu_to_le32(sizeof(id[0]) * ATA_ID_WORDS);
pcmd->sge.flags = cpu_to_le32(SGE_TRM);
@@ -247,11 +254,12 @@
struct sil_sata *sata = (struct sil_sata *)sata_dev_desc[dev].priv;
struct sata_fis_d2h fis;
void __iomem *port = sata->port;
+ u32 irq_stat;
int ret;
/* put the port into known state */
if (sil_init_port(port)) {
- printf("SRST: port not ready\n");
+ printf("SRST: port %d not ready\n", dev);
return 1;
}
@@ -300,7 +308,7 @@
pcmd->prb.fis.lba_low = block & 0xff;
pcmd->prb.fis.sector_count = (u8)blkcnt & 0xff;
- pcmd->sge.addr = cpu_to_le64((u32)buffer);
+ pcmd->sge.addr = cpu_to_le64(virt_to_bus(sata_info.devno, buffer));
pcmd->sge.cnt = cpu_to_le32(blkcnt * ATA_SECT_SIZE);
pcmd->sge.flags = cpu_to_le32(SGE_TRM);
@@ -346,7 +354,7 @@
pcmd->prb.fis.sector_count_exp = (blkcnt >> 8) & 0xff;
pcmd->prb.fis.sector_count = blkcnt & 0xff;
- pcmd->sge.addr = cpu_to_le64((u32)buffer);
+ pcmd->sge.addr = cpu_to_le64(virt_to_bus(sata_info.devno, buffer));
pcmd->sge.cnt = cpu_to_le32(blkcnt * ATA_SECT_SIZE);
pcmd->sge.flags = cpu_to_le32(SGE_TRM);
@@ -529,6 +537,7 @@
if (devno == -1)
return 1;
+ sata_info.devno = devno;
pci_read_config_word(devno, PCI_DEVICE_ID, &word);
/* get the port number */
@@ -559,14 +568,14 @@
if (!(word & PCI_COMMAND_MEMORY) ||
(!(word & PCI_COMMAND_MASTER))) {
printf("Error: Can not enable MEM access or Bus Mastering.\n");
- debug("PCI command: %s\n", word);
+ debug("PCI command: 0x%08x\n", word);
return 1;
}
/* GPIO off */
- writel(0, sata_info.iobase[0] + HOST_FLASH_CMD);
+ writel(0, (void *)(sata_info.iobase[0] + HOST_FLASH_CMD));
/* clear global reset & mask interrupts during initialization */
- writel(0, sata_info.iobase[0] + HOST_CTRL);
+ writel(0, (void *)(sata_info.iobase[0] + HOST_CTRL));
return 0;
}
@@ -583,6 +592,7 @@
void __iomem *port;
u16 *id;
u32 tmp;
+ int cnt;
if (dev >= sata_info.maxport) {
printf("SATA#%d is not present\n", dev);
@@ -593,8 +603,6 @@
port = (void *)sata_info.iobase[1] +
PORT_REGS_SIZE * (dev - sata_info.portbase);
- sil_init_port(port);
-
/* Initial PHY setting */
writel(0x20c, port + PORT_PHY_CFG);
@@ -603,20 +611,35 @@
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, 1000);
+ PORT_CS_PORT_RST, PORT_CS_PORT_RST, 100);
if (tmp & PORT_CS_PORT_RST)
printf("Err: Failed to clear port RST\n");
}
-
- /* configure port */
+
sil_config_port(port);
- tmp = readl(port + PORT_SSTATUS);
+ /* Check if device is present */
+
+ for (cnt = 0; cnt < 100; cnt++) {
+ tmp = readl(port + PORT_SSTATUS);
+ if ((tmp & 0xF) == 0x3)
+ break;
+ mdelay(1);
+ }
+
if ((tmp & 0xf) != 0x3) {
printf(" (No RDY)\n");
return 1;
}
+ /* Wait for port ready */
+ tmp = ata_wait_register(port + PORT_CTRL_STAT,
+ PORT_CS_RDY, PORT_CS_RDY, 100);
+ if ((tmp & PORT_CS_RDY) != PORT_CS_RDY) {
+ printf("%d port not ready.\n", dev);
+ return 1;
+ }
+
sata = (struct sil_sata *)malloc(sizeof(struct sil_sata));
if (!sata) {
printf("%d no memory.\n", dev);
@@ -624,10 +647,23 @@
}
memset((void *)sata, 0, sizeof(struct sil_sata));
+ /* configure port */
+ sil_config_port(port);
+
+ /* Reset port */
+ writel(PORT_CS_DEV_RST, port + PORT_CTRL_STAT);
+ readl(port + PORT_CTRL_STAT); /* sync */
+ tmp = ata_wait_register(port + PORT_CTRL_STAT, PORT_CS_DEV_RST,
+ PORT_CS_DEV_RST, 100);
+ if (tmp & PORT_CS_DEV_RST) {
+ printf("%d port reset failed.\n", dev);
+ return 1;
+ }
+
/* turn on port interrupt */
- tmp = readl(sata_info.iobase[0] + HOST_CTRL);
+ tmp = readl((void *)(sata_info.iobase[0] + HOST_CTRL));
tmp |= (1 << (dev - sata_info.portbase));
- writel(tmp, sata_info.iobase[0] + HOST_CTRL);
+ writel(tmp, (void *)(sata_info.iobase[0] + HOST_CTRL));
/* Save the private struct to block device struct */
sata_dev_desc[dev].priv = (void *)sata;
@@ -652,7 +688,8 @@
sata_dev_desc[dev].lba48 = 1;
sata->lba48 = 1;
debug("Device support LBA48\n");
- }
+ } else
+ debug("Device supports LBA28");
#endif
/* Serial number */