summaryrefslogtreecommitdiff
path: root/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c')
-rw-r--r--firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c b/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c
new file mode 100644
index 0000000000..f1577ee857
--- /dev/null
+++ b/firmware/target/arm/s5l8702/ipod6g/ata-ipod6g.c
@@ -0,0 +1,197 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: ata-meg-fx.c 27935 2010-08-28 23:12:11Z funman $
9 *
10 * Copyright (C) 2011 by Michael Sparmann
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#include "config.h"
22#include "cpu.h"
23#include "kernel.h"
24#include "thread.h"
25#include "system.h"
26#include "power.h"
27#include "panic.h"
28#include "pmu-target.h"
29#include "ata.h"
30#include "ata-target.h"
31#include "s5l8702.h"
32
33
34static struct wakeup ata_wakeup;
35
36#ifdef HAVE_ATA_DMA
37static uint32_t ata_dma_flags;
38#endif
39
40
41void ata_reset(void)
42{
43 ATA_SWRST = 1;
44 sleep(HZ / 100);
45 ATA_SWRST = 0;
46 sleep(HZ / 10);
47}
48
49void ata_enable(bool on)
50{
51 if (on)
52 {
53 PWRCON(0) &= ~(1 << 5);
54 ATA_CFG = 0x41;
55 sleep(HZ / 100);
56 ATA_CFG = 0x40;
57 sleep(HZ / 20);
58 ata_reset();
59 ATA_CCONTROL = 1;
60 sleep(HZ / 5);
61 ATA_PIO_TIME = 0x191f7;
62 *ATA_HCYL = 0;
63 while (!(ATA_PIO_READY & 2)) yield();
64 }
65 else
66 {
67 ATA_CCONTROL = 0;
68 while (!(ATA_CCONTROL & 2)) yield();
69 PWRCON(1) |= 1 << 5;
70 }
71}
72
73bool ata_is_coldstart(void)
74{
75 return false;
76}
77
78void ata_device_init(void)
79{
80 VIC0INTENABLE = 1 << IRQ_ATA;
81}
82
83uint16_t ata_read_cbr(uint32_t volatile* reg)
84{
85 while (!(ATA_PIO_READY & 2));
86 volatile uint32_t __attribute__((unused)) dummy = *reg;
87 while (!(ATA_PIO_READY & 1));
88 return ATA_PIO_RDATA;
89}
90
91void ata_write_cbr(uint32_t volatile* reg, uint16_t data)
92{
93 while (!(ATA_PIO_READY & 2));
94 *reg = data;
95}
96
97void ata_set_pio_timings(int mode)
98{
99 if (mode >= 4) ATA_PIO_TIME = 0x7083;
100 if (mode >= 3) ATA_PIO_TIME = 0x2072;
101 else ATA_PIO_TIME = 0x11f3;
102}
103
104#ifdef HAVE_ATA_DMA
105static void ata_set_mdma_timings(unsigned int mode)
106{
107 if (mode >= 2) ATA_MDMA_TIME = 0x5072;
108 if (mode >= 1) ATA_MDMA_TIME = 0x7083;
109 else ATA_MDMA_TIME = 0x1c175;
110}
111
112static void ata_set_udma_timings(unsigned int mode)
113{
114 if (mode >= 4) ATA_UDMA_TIME = 0x2010a52;
115 if (mode >= 3) ATA_UDMA_TIME = 0x2020a52;
116 if (mode >= 2) ATA_UDMA_TIME = 0x3030a52;
117 if (mode >= 1) ATA_UDMA_TIME = 0x3050a52;
118 else ATA_UDMA_TIME = 0x5071152;
119}
120
121void ata_dma_set_mode(unsigned char mode)
122{
123 unsigned int modeidx = mode & 0x07;
124 unsigned int dmamode = mode & 0xf8;
125
126 if (dmamode == 0x40 && modeidx <= ATA_MAX_UDMA)
127 {
128 /* Using Ultra DMA */
129 ata_set_udma_timings(dmamode);
130 ata_dma_flags = 0x60c;
131 }
132 else if (dmamode == 0x20 && modeidx <= ATA_MAX_MWDMA)
133 {
134 /* Using Multiword DMA */
135 ata_set_mdma_timings(dmamode);
136 ata_dma_flags = 0x408;
137 }
138 else
139 {
140 /* Don't understand this - force PIO. */
141 ata_dma_flags = 0;
142 }
143}
144
145bool ata_dma_setup(void *addr, unsigned long bytes, bool write)
146{
147 if ((((int)addr) & 0xf) || (((int)bytes) & 0xf) || !ata_dma_flags)
148 return false;
149
150 if (write) clean_dcache();
151 else invalidate_dcache();
152 ATA_CCOMMAND = 2;
153
154 if (write)
155 {
156 ATA_SBUF_START = addr;
157 ATA_SBUF_SIZE = bytes;
158 ATA_CFG |= 0x10;
159 }
160 else
161 {
162 ATA_TBUF_START = addr;
163 ATA_TBUF_SIZE = bytes;
164 ATA_CFG &= ~0x10;
165 }
166 ATA_XFR_NUM = bytes - 1;
167
168 return true;
169}
170
171bool ata_dma_finish(void)
172{
173 ATA_CFG |= ata_dma_flags;
174 ATA_CFG &= ~0x180;
175 wakeup_wait(&ata_wakeup, TIMEOUT_NOBLOCK);
176 ATA_IRQ = 0x1f;
177 ATA_IRQ_MASK = 1;
178 ATA_CCOMMAND = 1;
179 if (wakeup_wait(&ata_wakeup, HZ / 2) != OBJ_WAIT_SUCCEEDED)
180 {
181 ATA_CCOMMAND = 2;
182 ATA_CFG &= ~0x100c;
183 return false;
184 }
185 ATA_CCOMMAND = 2;
186 ATA_CFG &= ~0x100c;
187 return true;
188}
189#endif /* HAVE_ATA_DMA */
190
191void INT_ATA(void)
192{
193 uint32_t ata_irq = ATA_IRQ;
194 ATA_IRQ = ata_irq;
195 if (ata_irq & ATA_IRQ_MASK) wakeup_signal(&ata_wakeup);
196 ATA_IRQ_MASK = 0;
197}