2 * Copyright 2001 MontaVista Software Inc.
3 * Completed implementation.
4 * Author: MontaVista Software, Inc. <source@mvista.com>
5 * Hai-Pao Fan <hpfan@mvista.com>
7 * Module name: stb03xxx.c
12 #include <linux/types.h>
13 #include <linux/hdreg.h>
14 #include <linux/delay.h>
15 #include <linux/ide.h>
18 #include <asm/scatterlist.h>
19 #include <asm/ppc405_dma.h>
21 #include "ide_modes.h"
23 #define REDWOOD_IDE_CMD 0xf2100000
24 #define REDWOOD_IDE_CTRL 0xf4100000
25 #define IDE_CMD_OFF 0x00100000
26 #define IDE_CTL_OFF 0x00100000
28 #define IDE_INTRQ 25 /* interrupt level(int0) */
30 #define REDWOOD_DMA_ADDR 0xfce00000
33 /* use DMA channel 2 for IDE DMA operations */
35 #define IDE_DMA_INT 6 /* IDE dma channel 2 interrupt */
38 #define IDE_DMACR_CE 0x80000000 /* 00 channel enable */
39 #define IDE_DMACR_CIE 0x40000000 /* 01 channel interrupt enable */
40 #define IDE_DMACR_TD 0x20000000 /* 02 transfer direction */
41 /* 0 = write 1 = read */
42 #define IDE_DMACR_PL 0x10000000 /* 03 peripheral location */
43 #define IDE_DMACR_PW 0x0C000000 /* 04-05 peripheral width */
44 #define IDE_DMACR_DAI 0x02000000 /* 06 destination address increment */
45 #define IDE_DMACR_SAI 0x01000000 /* 07 source address increment */
46 #define IDE_DMACR_CP 0x00800000 /* 08 high order channel priority bit*/
47 #define IDE_DMACR_TM 0x00600000 /* 09-10 transfer mode */
48 #define IDE_DMACR_PSC 0x00180000 /* 11-12 peripheral setup cycles */
49 #define IDE_DMACR_PWC 0x0007E000 /* 13-18 peripheral wait cycles */
50 #define IDE_DMACR_PHC 0x00001C00 /* 19-21 peripheral hold cycles */
51 #define IDE_DMACR_ETD 0x00000200 /* 22 EOT/TC */
52 #define IDE_DMACR_TCE 0x00000100 /* 23 TC Enable */
53 #define IDE_DMACR_CH 0x00000080 /* 24 chaining enable */
54 #define IDE_DMACR_ECE 0x00000020 /* 26 EOT chain mode enable */
55 #define IDE_DMACR_TCD 0x00000010 /* 27 TC chain mode enable */
56 #define IDE_DMACR_DEC 0x00000004 /* 29 destination address decrement */
57 #define IDE_DMACR_CP1 0x00000001 /* 31 low order channel priority bit */
59 #define IDE_DMASR_TC 0x20000000
60 #define IDE_DMASR_EOT 0x02000000
61 #define IDE_DMASR_ERR 0x00200000
62 #define IDE_DMASR_CB 0x00000100
63 #define IDE_DMASR_CT 0x00000020
65 unsigned long dmacr_def = 0x0000AB02; /* pwc=101 phc=10, res:30=1 */
66 extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
69 #define WMODE 0 /* default to DMA line mode */
71 static volatile unsigned long dmastat;
73 /* Function Prototypes */
74 static void redwood_ide_tune_drive(ide_drive_t *, byte);
75 static byte redwood_ide_dma_2_pio(byte);
76 static int redwood_ide_tune_chipset(ide_drive_t *, byte);
77 static int redwood_ide_dmaproc(ide_dma_action_t, ide_drive_t *);
80 static void redwood_ide_tune_drive(ide_drive_t *drive, byte pio)
82 pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
85 static byte redwood_ide_dma_2_pio(byte xfer_rate)
114 static int redwood_ide_tune_chipset (ide_drive_t *drive, byte speed)
118 redwood_ide_tune_drive(drive, redwood_ide_dma_2_pio(speed));
120 if (!drive->init_speed)
121 drive->init_speed = speed;
122 err = ide_config_drive_speed(drive, speed);
123 drive->current_speed = speed;
127 static int redwood_config_drive_for_dma(ide_drive_t *drive)
129 struct hd_driveid *id = drive->id;
131 int func = ide_dma_off;
134 * Enable DMA on any drive that has multiword DMA
136 if (id->field_valid & 2) {
137 if (id->dma_mword & 0x0004) {
138 speed = XFER_MW_DMA_2;
140 } else if (id->dma_mword & 0x0002) {
141 speed = XFER_MW_DMA_1;
143 } else if (id->dma_mword & 1) {
144 speed = XFER_MW_DMA_0;
146 } else if (id->dma_1word & 0x0004) {
147 speed = XFER_SW_DMA_2;
151 ide_get_best_pio_mode(drive, 255, 5, NULL);
155 redwood_ide_tune_drive(drive, redwood_ide_dma_2_pio(speed));
156 return redwood_ide_dmaproc(func, drive);
159 ide_startstop_t redwood_ide_intr (ide_drive_t *drive)
164 ide_hwgroup_t *hwgroup = HWGROUP(drive);
165 struct request *rq = hwgroup->rq;
166 unsigned long block,b1,b2,b3,b4;
168 nsect = rq->current_nr_sectors;
170 dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
173 rq->buffer += nsect<<9;
175 i = (rq->nr_sectors -= nsect);
176 ide_end_request(1, HWGROUP(drive));
178 b1 = IN_BYTE(IDE_SECTOR_REG);
179 b2 = IN_BYTE(IDE_LCYL_REG);
180 b3 = IN_BYTE(IDE_HCYL_REG);
181 b4 = IN_BYTE(IDE_SELECT_REG);
182 block = ((b4 & 0x0f) << 24) + (b3 << 16) + (b2 << 8) + (b1);
184 if (drive->select.b.lba) {
185 OUT_BYTE(block,IDE_SECTOR_REG);
186 OUT_BYTE(block>>=8,IDE_LCYL_REG);
187 OUT_BYTE(block>>=8,IDE_HCYL_REG);
188 OUT_BYTE(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
190 unsigned int sect,head,cyl,track;
191 track = block / drive->sect;
192 sect = block % drive->sect + 1;
193 OUT_BYTE(sect,IDE_SECTOR_REG);
194 head = track % drive->head;
195 cyl = track / drive->head;
196 OUT_BYTE(cyl,IDE_LCYL_REG);
197 OUT_BYTE(cyl>>8,IDE_HCYL_REG);
198 OUT_BYTE(head|drive->select.all,IDE_SELECT_REG);
202 dma_stat = HWIF(drive)->dmaproc(ide_dma_read, drive);
204 dma_stat = HWIF(drive)->dmaproc(ide_dma_write, drive);
210 void redwood_ide_dma_intr (int irq, void *dev_id, struct pt_regs *regs)
212 dmastat = mfdcr(DCRN_DMASR);
215 IDE_DMASR_TC | IDE_DMASR_EOT | IDE_DMASR_ERR | IDE_DMASR_CT);
218 mtdcr(DCRN_UIC_SR(UIC0), (0x80000000 >> IDE_DMA_INT));
221 static int redwood_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
223 ide_hwif_t *hwif = HWIF(drive);
225 struct request *rq=HWGROUP(drive)->rq;
227 unsigned long length;
231 case ide_dma_off_quietly:
240 mtdcr(DCRN_DMACR2,0);
241 mtdcr(DCRN_DMASR, IDE_DMASR_TC | IDE_DMASR_EOT | IDE_DMASR_ERR
244 /* level-sensitive (UICTR bit = 0) and positive-active (UICPR bit = 1) */
245 mtdcr(DCRN_UIC_PR(UIC0), (mfdcr(DCRN_UIC_PR(UIC0)) | UIC_D2));
248 if ( ide_request_irq(IDE_DMA_INT, &redwood_ide_dma_intr, SA_INTERRUPT,
249 hwif->name, hwif->hwgroup) ) {
250 printk("ide_redwood: ide_request_irq failed int=%d\n",
252 restore_flags(flags);
255 restore_flags(flags);
257 drive->using_dma = (func == ide_dma_on);
259 mtdcr(DCRN_DCRXBCR, 0);
260 mtdcr(DCRN_CICCR, mfdcr(DCRN_CICCR) | 0x00000400);
262 /* Configure CIC reg for line mode dma */
263 mtdcr(DCRN_CICCR, mfdcr(DCRN_CICCR) & ~0x00000400);
268 return redwood_config_drive_for_dma(drive);
272 if (drive->media != ide_disk)
275 if (mfdcr(DCRN_DMACR2) & IDE_DMACR_CE) /* DMA is busy? */
278 mtdcr(DCRN_DMASR, IDE_DMASR_TC | IDE_DMASR_EOT | IDE_DMASR_ERR
282 dma_cache_inv((unsigned long) rq->buffer,
283 rq->current_nr_sectors * 512);
285 mtdcr(DCRN_DMASA2,0);
287 mtdcr(DCRN_DMASA2,0xfce00000);
289 mtdcr(DCRN_DMADA2, virt_to_bus(rq->buffer));
291 dma_cache_wback_inv((unsigned long) rq->buffer,
292 rq->current_nr_sectors * 512);
293 mtdcr(DCRN_DMASA2, virt_to_bus(rq->buffer));
295 mtdcr(DCRN_DMADA2,0);
297 mtdcr(DCRN_DMADA2,0xfce00000);
302 length = rq->current_nr_sectors * 512/2;
304 length = rq->current_nr_sectors * 512/16;
306 OUT_BYTE(rq->current_nr_sectors,IDE_NSECTOR_REG);
307 mtdcr(DCRN_DMACT2, length);
309 /* CE=0 disable DMA */
310 /* Set up the Line Buffer Control Register
311 * 11d1xxxx0.. - 11=Mode 2 (120 ns cycle), d=1/0(read/write)
312 * 1=active, 0=1X clock mode.
317 mtdcr(DCRN_DMACR2, 0x66000000 | dmacr_def);
319 mtdcr(DCRN_DCRXBCR,0xD0000000);
320 mtdcr(DCRN_DMACR2, 0x6E600000 | dmacr_def);
324 mtdcr(DCRN_DMACR2, 0x46000000 | dmacr_def);
326 mtdcr(DCRN_DCRXBCR, 0xF0000000);
327 mtdcr(DCRN_DMACR2, 0x4D600000 | dmacr_def);
331 set_dma_mode(hwif->hw.dma, reading
332 ? DMA_MODE_READ : DMA_MODE_WRITE);
333 drive->waiting_for_dma = 1;
334 ide_set_handler(drive, &redwood_ide_intr, WAIT_CMD, NULL);
335 OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
339 mtdcr(DCRN_DMACR2,mfdcr(DCRN_DMACR2) | 0x80000000);
341 /* wait for dma to complete (channel 2 terminal count) */
342 for (i=0; i < 5000000; i++) {
343 if (dmastat & DMA_CS2)
350 drive->waiting_for_dma = 0;
353 mtdcr(DCRN_DMACR2, mfdcr(DCRN_DMACR2) & ~0x80000000);
354 mtdcr(DCRN_DCRXBCR,0);
357 case ide_dma_test_irq:
358 return 1; /* returns 1 if dma irq issued, 0 otherwise */
360 case ide_dma_bad_drive:
361 case ide_dma_good_drive:
362 case ide_dma_verbose:
363 case ide_dma_timeout:
365 case ide_dma_lostirq:
366 printk("ide_dmaproc: chipset supported %s func only: %d\n",
367 ide_dmafunc_verbose(func), func);
370 printk("ide_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
373 //return ide_dmaproc(func, drive);
378 int nonpci_ide_default_irq(ide_ioreg_t base)
385 nonpci_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
387 unsigned long reg = data_port;
388 unsigned long ioaddr;
389 unsigned long xilinx;
392 if (!request_region(REDWOOD_IDE_CMD, 0x10, "IDE"))
395 if (!request_region(REDWOOD_IDE_CTRL, 2, "IDE")) {
396 release_region(REDWOOD_IDE_CMD, 0x10);
400 mtdcr(DCRN_DCRXICR, 0x40000000); /* set dcrx internal arbiter */
402 /* reconstruct phys addrs from EBIU config regs for CS2# */
403 reg = ((mfdcr(DCRN_BRCR2) & 0xff000000) >> 4) | 0xf0000000;
404 xilinx = reg | 0x00040000;
405 reg = reg | IDE_CMD_OFF;
407 ioaddr = (unsigned long)ioremap(reg, 0x10);
408 xilinx = (unsigned long)ioremap(xilinx, 0x10);
412 for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
413 hw->io_ports[i] = ioaddr;
416 hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ioremap(REDWOOD_IDE_CTRL,2);
418 /* add RE & OEN to value set by boot rom */
419 mtdcr(DCRN_BRCR3, 0x407cfffe);
421 /* init CIC control reg to enable IDE interface PIO mode */
422 mtdcr(DCRN_CICCR, (mfdcr(DCRN_CICCR) & 0xffff7bff) | 0x0003);
426 writew( i & ~0x8001, xilinx);
427 writew( 0, xilinx+7*2);
428 udelay(10*1000); /* 10 ms */
431 /* init xilinx control registers - enable ide mux, clear reset bit */
432 writew( i | 0x8001, xilinx);
433 writew( 0, xilinx+7*2);
435 /* wait until drive is not busy (it may be spinning up) */
436 for (i=0; i < 10; i++) {
438 stat = inb_p(hw->io_ports[7]);
439 /* wait for !busy & ready */
440 if ((stat & 0x80) == 0)
443 udelay(1000*1000); /* 1 second */
446 /* use DMA channel 2 for IDE DMA operations */
449 mtdcr(DCRN_DMACR2, 0x4d600000 | dmacr_def);
450 mtdcr(DCRN_DMASR, 0xffffffff); /* clear status register */
452 /* init CIC select2 reg to connect external DMA port 3 to internal
455 mtdcr(DCRN_DMAS2, (mfdcr(DCRN_DMAS2) & 0xfffffff0) | 0x00000002);
459 ide_hwifs[index].tuneproc = &redwood_ide_tune_drive;
460 ide_hwifs[index].drives[0].autotune = 1;
461 ide_hwifs[index].autodma = 1;
462 ide_hwifs[index].dmaproc = &redwood_ide_dmaproc;
463 ide_hwifs[index].speedproc = &redwood_ide_tune_chipset;
464 ide_hwifs[index].noprobe = 0;
466 memcpy(ide_hwifs[index].io_ports, hw->io_ports, sizeof(hw->io_ports));
467 ide_hwifs[index].irq = IDE_INTRQ;