Commit 4edbdf9a authored by Jeff Garzik's avatar Jeff Garzik

[libata] Add paranoia checks/settings suggested by Promise

parent d7d46878
...@@ -51,6 +51,7 @@ enum { ...@@ -51,6 +51,7 @@ enum {
PDC_CTLSTAT = 0x60, /* IDE control and status register */ PDC_CTLSTAT = 0x60, /* IDE control and status register */
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */ PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
PDC_SLEW_CTL = 0x470, /* slew rate control reg */ PDC_SLEW_CTL = 0x470, /* slew rate control reg */
PDC_HDMA_CTLSTAT = 0x12C, /* Host DMA control / status */
PDC_20621_SEQCTL = 0x400, PDC_20621_SEQCTL = 0x400,
PDC_20621_SEQMASK = 0x480, PDC_20621_SEQMASK = 0x480,
PDC_20621_PAGE_SIZE = (32 * 1024), PDC_20621_PAGE_SIZE = (32 * 1024),
...@@ -67,7 +68,8 @@ enum { ...@@ -67,7 +68,8 @@ enum {
PDC_DIMM_ATA_PKT = (128 * 2), PDC_DIMM_ATA_PKT = (128 * 2),
PDC_DIMM_APKT_PRD = (128 * 3), PDC_DIMM_APKT_PRD = (128 * 3),
PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128, PDC_DIMM_HEADER_SZ = PDC_DIMM_APKT_PRD + 128,
PDC_PAGE_DATA = 0x40 + PDC_PAGE_WINDOW = 0x40,
PDC_PAGE_DATA = PDC_PAGE_WINDOW +
(PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE), (PDC_20621_DIMM_DATA / PDC_20621_PAGE_SIZE),
PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE, PDC_PAGE_SET = PDC_DIMM_DATA_STEP / PDC_20621_PAGE_SIZE,
...@@ -78,6 +80,7 @@ enum { ...@@ -78,6 +80,7 @@ enum {
board_20621 = 2, /* FastTrak S150 SX4 */ board_20621 = 2, /* FastTrak S150 SX4 */
PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */ PDC_FLAG_20621 = (1 << 30), /* we have a 20621 */
PDC_HDMA_RESET = (1 << 11), /* HDMA reset */
}; };
...@@ -559,7 +562,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf, ...@@ -559,7 +562,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
tmp = PDC_PKT_READ; tmp = PDC_PKT_READ;
else else
tmp = 0; tmp = 0;
tmp |= ((portno + 1 + 4) << 16); tmp |= ((portno + 1 + 4) << 16); /* seq. id */
tmp |= (0xff << 24); /* delay seq. id */
buf32[dw + 0] = cpu_to_le32(tmp); buf32[dw + 0] = cpu_to_le32(tmp);
buf32[dw + 1] = cpu_to_le32(host_sg); buf32[dw + 1] = cpu_to_le32(host_sg);
buf32[dw + 2] = cpu_to_le32(dimm_sg); buf32[dw + 2] = cpu_to_le32(dimm_sg);
...@@ -643,21 +647,42 @@ static void pdc20621_push_hdma(struct ata_queued_cmd *qc) ...@@ -643,21 +647,42 @@ static void pdc20621_push_hdma(struct ata_queued_cmd *qc)
/* hard-code chip #0 */ /* hard-code chip #0 */
mmio += PDC_CHIP0_OFS; mmio += PDC_CHIP0_OFS;
tmp = port_no + 1 + 4; tmp = readl(mmio + PDC_HDMA_CTLSTAT) & 0xffffff00;
tmp |= port_no + 1 + 4; /* seq. ID */
if (!rw) if (!rw)
tmp |= (1 << 6); tmp |= (1 << 6); /* hdma data direction */
writel(tmp, mmio + 0x12C); writel(tmp, mmio + PDC_HDMA_CTLSTAT); /* note: stops DMA, if active */
readl(mmio + 0x12C); /* flush */ readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
writel(host_sg, mmio + 0x108); writel(host_sg, mmio + 0x108);
writel(dimm_sg, mmio + 0x10C); writel(dimm_sg, mmio + 0x10C);
writel(0, mmio + 0x128); writel(0, mmio + 0x128);
tmp |= (1 << 7); tmp |= (1 << 7);
writel(tmp, mmio + 0x12C); writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + 0x12C); /* flush */ readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
} }
#endif #endif
#ifdef ATA_VERBOSE_DEBUG
static void pdc20621_dump_hdma(struct ata_queued_cmd *qc)
{
struct ata_port *ap = qc->ap;
unsigned int port_no = ap->port_no;
void *dimm_mmio = ap->host_set->private_data;
dimm_mmio += (port_no * PDC_DIMM_WINDOW_STEP);
dimm_mmio += PDC_DIMM_HOST_PKT;
printk(KERN_ERR "HDMA[0] == 0x%08X\n", readl(dimm_mmio));
printk(KERN_ERR "HDMA[1] == 0x%08X\n", readl(dimm_mmio + 4));
printk(KERN_ERR "HDMA[2] == 0x%08X\n", readl(dimm_mmio + 8));
printk(KERN_ERR "HDMA[3] == 0x%08X\n", readl(dimm_mmio + 12));
}
#else
static inline void pdc20621_dump_hdma(struct ata_queued_cmd *qc) { }
#endif /* ATA_VERBOSE_DEBUG */
static void pdc20621_dma_start(struct ata_queued_cmd *qc) static void pdc20621_dma_start(struct ata_queued_cmd *qc)
{ {
struct ata_port *ap = qc->ap; struct ata_port *ap = qc->ap;
...@@ -686,6 +711,7 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc) ...@@ -686,6 +711,7 @@ static void pdc20621_dma_start(struct ata_queued_cmd *qc)
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
if (doing_hdma) { if (doing_hdma) {
pdc20621_dump_hdma(qc);
#ifdef DIRECT_HDMA #ifdef DIRECT_HDMA
pdc20621_push_hdma(qc); pdc20621_push_hdma(qc);
#else #else
...@@ -724,7 +750,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -724,7 +750,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
/* step two - DMA from DIMM to host */ /* step two - DMA from DIMM to host */
if (doing_hdma) { if (doing_hdma) {
VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: read hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + 0x12c)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
} }
...@@ -732,9 +758,10 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -732,9 +758,10 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
else { else {
u8 seq = (u8) (port_no + 1 + 4); u8 seq = (u8) (port_no + 1 + 4);
VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: read ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + 0x12c)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* submit hdma pkt */ /* submit hdma pkt */
pdc20621_dump_hdma(qc);
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
#ifdef DIRECT_HDMA #ifdef DIRECT_HDMA
pdc20621_push_hdma(qc); pdc20621_push_hdma(qc);
...@@ -751,7 +778,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -751,7 +778,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
if (doing_hdma) { if (doing_hdma) {
u8 seq = (u8) (port_no + 1); u8 seq = (u8) (port_no + 1);
VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: write hdma, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + 0x12c)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
/* submit ata pkt */ /* submit ata pkt */
writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4)); writel(0x00000001, mmio + PDC_20621_SEQCTL + (seq * 4));
...@@ -762,7 +789,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap, ...@@ -762,7 +789,7 @@ static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
/* step two - execute ATA command */ /* step two - execute ATA command */
else { else {
VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id, VPRINTK("ata%u: write ata, 0x%x 0x%x\n", ap->id,
readl(mmio + 0x104), readl(mmio + 0x12c)); readl(mmio + 0x104), readl(mmio + PDC_HDMA_CTLSTAT));
pdc_dma_complete(ap, qc); pdc_dma_complete(ap, qc);
} }
handled = 1; handled = 1;
...@@ -1053,13 +1080,27 @@ static void pdc_20621_init(struct ata_probe_ent *pe) ...@@ -1053,13 +1080,27 @@ static void pdc_20621_init(struct ata_probe_ent *pe)
mmio += PDC_CHIP0_OFS; mmio += PDC_CHIP0_OFS;
/*
* Select page 0x40 for our 32k DIMM window
*/
tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000; tmp = readl(mmio + PDC_20621_DIMM_WINDOW) & 0xffff0000;
tmp |= 0x40; /* page 40h; arbitrarily selected */ tmp |= PDC_PAGE_WINDOW; /* page 40h; arbitrarily selected */
writel(tmp, mmio + PDC_20621_DIMM_WINDOW); writel(tmp, mmio + PDC_20621_DIMM_WINDOW);
writel( (1 << 11), mmio + 0x12C); /*
* Reset Host DMA
*/
tmp = readl(mmio + PDC_HDMA_CTLSTAT);
tmp |= PDC_HDMA_RESET;
writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
udelay(10); udelay(10);
writel(0, mmio + 0x12C);
tmp = readl(mmio + PDC_HDMA_CTLSTAT);
tmp &= ~PDC_HDMA_RESET;
writel(tmp, mmio + PDC_HDMA_CTLSTAT);
readl(mmio + PDC_HDMA_CTLSTAT); /* flush */
} }
static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe) static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
......
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