diff options
Diffstat (limited to 'firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c')
-rw-r--r-- | firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c new file mode 100644 index 0000000000..bc2b53d776 --- /dev/null +++ b/firmware/target/arm/s3c2440/gigabeat-fx/ata-meg-fx.c | |||
@@ -0,0 +1,143 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id $ | ||
9 | * | ||
10 | * Copyright (C) 2006,2007 by Marcoen Hirschberg | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "config.h" | ||
20 | #include "cpu.h" | ||
21 | #include <stdbool.h> | ||
22 | #include "kernel.h" | ||
23 | #include "system.h" | ||
24 | #include "power.h" | ||
25 | #include "panic.h" | ||
26 | #include "pcf50606.h" | ||
27 | #include "ata-target.h" | ||
28 | #include "mmu-meg-fx.h" | ||
29 | #include "backlight-target.h" | ||
30 | |||
31 | /* ARESET on C7C68300 and RESET on ATA interface (Active Low) */ | ||
32 | #define ATA_RESET_ENABLE GPGDAT &= ~(1 << 10) | ||
33 | #define ATA_RESET_DISABLE GPGDAT |= (1 << 10) | ||
34 | |||
35 | /* ATA_EN on C7C68300 */ | ||
36 | #define USB_ATA_ENABLE GPBDAT |= (1 << 5) | ||
37 | #define USB_ATA_DISABLE GPBDAT &= ~(1 << 5) | ||
38 | |||
39 | void ata_reset(void) | ||
40 | { | ||
41 | ATA_RESET_ENABLE; | ||
42 | sleep(1); /* > 25us */ | ||
43 | ATA_RESET_DISABLE; | ||
44 | sleep(1); /* > 2ms */ | ||
45 | } | ||
46 | |||
47 | /* This function is called before enabling the USB bus */ | ||
48 | void ata_enable(bool on) | ||
49 | { | ||
50 | if(on) | ||
51 | USB_ATA_DISABLE; | ||
52 | else | ||
53 | USB_ATA_ENABLE; | ||
54 | |||
55 | GPBCON=( GPGCON&~(1<<11) ) | (1<<10); /* Make the pin an output */ | ||
56 | // GPBUP|=1<<5; /* Disable pullup in SOC as we are now driving */ | ||
57 | } | ||
58 | |||
59 | bool ata_is_coldstart(void) | ||
60 | { | ||
61 | /* Check the pin configuration - return true when pin is unconfigured */ | ||
62 | return (GPGCON & 0x00300000) == 0; | ||
63 | } | ||
64 | |||
65 | void ata_device_init(void) | ||
66 | { | ||
67 | /* ATA reset */ | ||
68 | ATA_RESET_DISABLE; /* Set the pin to disable an active low reset */ | ||
69 | GPGCON=( GPGCON&~(1<<21) ) | (1<<20); /* Make the pin an output */ | ||
70 | GPGUP |= 1<<10; /* Disable pullup in SOC as we are now driving */ | ||
71 | } | ||
72 | |||
73 | #if !defined(BOOTLOADER) | ||
74 | void copy_read_sectors(unsigned char* buf, int wordcount) | ||
75 | { | ||
76 | __buttonlight_trigger(); | ||
77 | |||
78 | /* Unaligned transfer - slow copy */ | ||
79 | if ( (unsigned long)buf & 1) | ||
80 | { /* not 16-bit aligned, copy byte by byte */ | ||
81 | unsigned short tmp = 0; | ||
82 | unsigned char* bufend = buf + wordcount*2; | ||
83 | do | ||
84 | { | ||
85 | tmp = ATA_DATA; | ||
86 | *buf++ = tmp & 0xff; /* I assume big endian */ | ||
87 | *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */ | ||
88 | } while (buf < bufend); /* tail loop is faster */ | ||
89 | return; | ||
90 | } | ||
91 | /* This should never happen, but worth watching for */ | ||
92 | if(wordcount > (1 << 18)) | ||
93 | panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!"); | ||
94 | |||
95 | //#define GIGABEAT_DEBUG_ATA | ||
96 | #ifdef GIGABEAT_DEBUG_ATA | ||
97 | static int line = 0; | ||
98 | static char str[256]; | ||
99 | snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount); | ||
100 | lcd_puts(10, line, str); | ||
101 | line = (line+1) % 32; | ||
102 | lcd_update(); | ||
103 | #endif | ||
104 | /* Reset the channel */ | ||
105 | DMASKTRIG0 |= 4; | ||
106 | /* Wait for DMA controller to be ready */ | ||
107 | while(DMASKTRIG0 & 0x2) | ||
108 | ; | ||
109 | while(DSTAT0 & (1 << 20)) | ||
110 | ; | ||
111 | /* Source is ATA_DATA, on AHB Bus, Fixed */ | ||
112 | DISRC0 = (int) 0x18000000; | ||
113 | DISRCC0 = 0x1; | ||
114 | /* Dest mapped to physical address, on AHB bus, increment */ | ||
115 | DIDST0 = (int) buf; | ||
116 | if(DIDST0 < 0x30000000) | ||
117 | DIDST0 += 0x30000000; | ||
118 | DIDSTC0 = 0; | ||
119 | |||
120 | /* DACK/DREQ Sync to AHB, Int on Transfer complete, Whole service, No reload, 16-bit transfers */ | ||
121 | DCON0 = ((1 << 30) | (1<< 29) | (1<<27) | (1<<22) | (1<<20)) | wordcount; | ||
122 | |||
123 | /* Activate the channel */ | ||
124 | DMASKTRIG0 = 0x2; | ||
125 | |||
126 | invalidate_dcache_range((void *)buf, wordcount*2); | ||
127 | |||
128 | INTMSK &= ~(1<<17); /* unmask the interrupt */ | ||
129 | SRCPND = (1<<17); /* clear any pending interrupts */ | ||
130 | /* Start DMA */ | ||
131 | DMASKTRIG0 |= 0x1; | ||
132 | |||
133 | /* Wait for transfer to complete */ | ||
134 | while((DSTAT0 & 0x000fffff)) | ||
135 | yield(); | ||
136 | /* Dump cache for the buffer */ | ||
137 | } | ||
138 | #endif | ||
139 | void dma0(void) | ||
140 | { | ||
141 | } | ||
142 | |||
143 | |||