i.MX31: Add a debug menu to play around with DVFS/DPTC settings for fun, testing...
[kugel-rb.git] / firmware / target / arm / ata-pp5020.c
blob0eb64351f206e578fe2aa5b76f95e7423715bd0e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006 by Barry Wardell
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 /* ATA stuff was taken from the iPod code */
24 #include <stdbool.h>
25 #include "system.h"
26 #include "ata.h"
27 #include "ata-target.h"
29 void ata_reset()
34 void ata_enable(bool on)
36 /* TODO: Implement ata_enable() */
37 (void)on;
40 bool ata_is_coldstart()
42 return false;
43 /* TODO: Implement coldstart variable */
46 void ata_device_init()
48 #ifdef SAMSUNG_YH920
49 CPU_INT_DIS = (1<<IDE_IRQ);
50 #endif
51 #ifdef HAVE_ATA_DMA
52 IDE_DMA_CONTROL |= 2;
53 IDE_DMA_CONTROL &= ~1;
54 IDE0_CFG &= ~0x8010;
55 IDE0_CFG |= 0x20;
56 #else
58 /* From ipod-ide.c:ipod_ide_register() */
59 IDE0_CFG |= (1<<5);
60 #ifdef IPOD_NANO
61 IDE0_CFG |= (0x10000000); /* cpu > 65MHz */
62 #else
63 IDE0_CFG &=~(0x10000000); /* cpu < 65MHz */
64 #endif
65 #endif
67 IDE0_PRI_TIMING0 = 0x10;
68 IDE0_PRI_TIMING1 = 0x80002150;
71 /* These are PIO timings for 80 Mhz. At 24 Mhz,
72 the first value is 0 but the rest are the same.
73 They go in IDE0_PRI_TIMING0.
75 Rockbox used 0x10, and test_disk shows that leads to faster PIO.
76 If 0x10 is incorrect, these timings may be needed with some devices.
77 static const unsigned long pio80mhz[] = {
78 0xC293, 0x43A2, 0x11A1, 0x7232, 0x3131
79 };
82 #ifdef HAVE_ATA_DMA
83 /* Timings for multi-word and ultra DMA modes.
84 These go in IDE0_PRI_TIMING1
86 static const unsigned long tm_mwdma[] = {
87 0xF9F92, 0x56562, 0x45451
90 static const unsigned long tm_udma[] = {
91 0x800037C1, 0x80003491, 0x80003371,
92 #if ATA_MAX_UDMA > 2
93 0x80003271, 0x80003071
94 #endif
97 #if ATA_MAX_UDMA > 2
98 static bool dma_boosted = false;
99 static bool dma_needs_boost;
100 #endif
102 /* This function sets up registers for 80 Mhz.
103 Ultra DMA mode 2 works at 30 Mhz.
105 void ata_dma_set_mode(unsigned char mode) {
106 int modeidx;
108 (*(volatile unsigned long *)(0x600060C4)) = 0xC0000000; /* 80 Mhz */
109 #if !defined(IPOD_NANO)
110 IDE0_CFG &= ~0x10000000;
111 #endif
113 modeidx = mode & 7;
114 mode &= 0xF8;
115 if (mode == 0x40 && modeidx <= ATA_MAX_UDMA) {
116 IDE0_PRI_TIMING1 = tm_udma[modeidx];
117 #if ATA_MAX_UDMA > 2
118 if (modeidx > 2)
119 dma_needs_boost = true;
120 else
121 dma_needs_boost = false;
122 #endif
123 } else if (mode == 0x20 && modeidx <= ATA_MAX_MWDMA)
124 IDE0_PRI_TIMING1 = tm_mwdma[modeidx];
126 #if !defined(IPOD_NANO)
127 IDE0_CFG |= 0x20000000; /* >= 50 Mhz */
128 #endif
131 #define IDE_CFG_INTRQ 8
132 #define IDE_DMA_CONTROL_READ 8
134 /* This waits for an ATA interrupt using polling.
135 In ATA_CONTROL, CONTROL_nIEN must be cleared.
137 STATICIRAM ICODE_ATTR int ata_wait_intrq(void)
139 long timeout = current_tick + HZ*10;
143 if (IDE0_CFG & IDE_CFG_INTRQ)
144 return 1;
145 ata_keep_active();
146 yield();
147 } while (TIME_BEFORE(current_tick, timeout));
149 return 0; /* timeout */
152 /* This function checks if parameters are appropriate for DMA,
153 and if they are, it sets up for DMA.
155 If return value is false, caller may use PIO for this transfer.
157 If return value is true, caller must issue a DMA ATA command
158 and then call ata_dma_finish().
160 bool ata_dma_setup(void *addr, unsigned long bytes, bool write) {
161 /* Require cacheline alignment for reads to prevent interference. */
162 if (!write && ((unsigned long)addr & 15))
163 return false;
165 /* Writes only need to be word-aligned, but by default DMA
166 * is not used for writing as it appears to be slower.
168 #ifdef ATA_DMA_WRITES
169 if (write && ((unsigned long)addr & 3))
170 return false;
171 #else
172 if (write)
173 return false;
174 #endif
176 #if ATA_MAX_UDMA > 2
177 if (dma_needs_boost && !dma_boosted) {
178 cpu_boost(true);
179 dma_boosted = true;
181 #endif
183 if (write) {
184 /* If unflushed, old data may be written to disk */
185 cpucache_flush();
187 else {
188 /* Invalidate cache because new data may be present in RAM */
189 cpucache_invalidate();
192 /* Clear pending interrupts so ata_dma_finish() can wait for an
193 interrupt from this transfer
195 IDE0_CFG |= IDE_CFG_INTRQ;
197 IDE_DMA_CONTROL |= 2;
198 IDE_DMA_LENGTH = bytes - 4;
200 #if !defined(BOOTLOADER) || defined (HAVE_BOOTLOADER_USB_MODE)
201 if ((unsigned long)addr < DRAM_START)
202 /* Rockbox remaps DRAM to start at 0 */
203 IDE_DMA_ADDR = (unsigned long)addr + DRAM_START;
204 else
205 #endif
206 IDE_DMA_ADDR = (unsigned long)addr;
208 if (write)
209 IDE_DMA_CONTROL &= ~IDE_DMA_CONTROL_READ;
210 else
211 IDE_DMA_CONTROL |= IDE_DMA_CONTROL_READ;
213 IDE0_CFG |= 0x8000;
215 return true;
218 /* This function waits for a DMA transfer to end.
219 It must be called to finish what ata_dma_setup started.
221 Return value is true if DMA completed before the timeout, and false
222 if a timeout happened.
224 bool ata_dma_finish(void) {
225 bool res;
227 /* It may be okay to put this at the end of setup */
228 IDE_DMA_CONTROL |= 1;
230 /* Wait for end of transfer.
231 Reading standard ATA status while DMA is in progress causes
232 failures and hangs. Because of that, another wait is used.
234 res = ata_wait_intrq();
236 IDE0_CFG &= ~0x8000;
237 IDE_DMA_CONTROL &= ~0x80000001;
239 #if ATA_MAX_UDMA > 2
240 if (dma_boosted) {
241 cpu_boost(false);
242 dma_boosted = false;
244 #endif
246 return res;
249 #endif /* HAVE_ATA_DMA */