ARM: use BX when branch to an address in register
[kugel-rb.git] / firmware / target / arm / s3c2440 / gigabeat-fx / ata-meg-fx.c
blob4b1e1d9ccc54dd23923b86c17932550745846cfa
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2006,2007 by Marcoen Hirschberg
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 ****************************************************************************/
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 "pcf50606.h"
29 #include "ata.h"
30 #include "ata-target.h"
31 #include "backlight-target.h"
33 /* ARESET on C7C68300 and RESET on ATA interface (Active Low) */
34 #define ATA_RESET_ENABLE GPGDAT &= ~(1 << 10)
35 #define ATA_RESET_DISABLE GPGDAT |= (1 << 10)
37 /* ATA_EN on C7C68300 */
38 #define USB_ATA_ENABLE GPBDAT |= (1 << 5)
39 #define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
41 void ata_reset(void)
43 ATA_RESET_ENABLE;
44 sleep(1); /* > 25us */
45 ATA_RESET_DISABLE;
46 sleep(1); /* > 2ms */
49 /* This function is called before enabling the USB bus */
50 void ata_enable(bool on)
52 GPBCON=( GPBCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
53 GPBUP|=1<<5; /* Disable pullup in SOC as we are now driving */
54 if(on)
55 USB_ATA_DISABLE;
56 else
57 USB_ATA_ENABLE;
60 bool ata_is_coldstart(void)
62 /* Check the pin configuration - return true when pin is unconfigured */
63 return (GPGCON & 0x00300000) == 0;
66 void ata_device_init(void)
68 GPGCON=( GPGCON&~(1<<21) ) | (1<<20); /* Make the pin an output */
69 GPGUP |= 1<<10; /* Disable pullup in SOC as we are now driving */
70 /* ATA reset */
71 ATA_RESET_DISABLE; /* Set the pin to disable an active low reset */
74 #if !defined(BOOTLOADER)
75 void copy_read_sectors(unsigned char* buf, int wordcount)
77 __buttonlight_trigger();
79 /* Unaligned transfer - slow copy */
80 if ( (unsigned long)buf & 1)
81 { /* not 16-bit aligned, copy byte by byte */
82 unsigned short tmp = 0;
83 unsigned char* bufend = buf + wordcount*2;
86 tmp = ATA_DATA;
87 *buf++ = tmp & 0xff; /* I assume big endian */
88 *buf++ = tmp >> 8; /* and don't use the SWAB16 macro */
89 } while (buf < bufend); /* tail loop is faster */
90 return;
92 /* This should never happen, but worth watching for */
93 if(wordcount > (1 << 18))
94 panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!");
96 //#define GIGABEAT_DEBUG_ATA
97 #ifdef GIGABEAT_DEBUG_ATA
98 static int line = 0;
99 static char str[256];
100 snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
101 lcd_puts(10, line, str);
102 line = (line+1) % 32;
103 lcd_update();
104 #endif
105 /* Reset the channel */
106 DMASKTRIG0 |= 4;
107 /* Wait for DMA controller to be ready */
108 while(DMASKTRIG0 & 0x2)
110 while(DSTAT0 & (1 << 20))
112 /* Source is ATA_DATA, on AHB Bus, Fixed */
113 DISRC0 = (int) 0x18000000;
114 DISRCC0 = 0x1;
115 /* Dest mapped to physical address, on AHB bus, increment */
116 DIDST0 = (int) buf;
117 if(DIDST0 < 0x30000000)
118 DIDST0 += 0x30000000;
119 DIDSTC0 = 0;
121 /* DACK/DREQ Sync to AHB, Whole service, No reload, 16-bit transfers */
122 DCON0 = ((1 << 30) | (1<<27) | (1<<22) | (1<<20)) | wordcount;
124 /* Activate the channel */
125 DMASKTRIG0 = 0x2;
127 invalidate_dcache_range((void *)buf, wordcount*2);
129 /* Start DMA */
130 DMASKTRIG0 |= 0x1;
132 /* Wait for transfer to complete */
133 while((DSTAT0 & 0x000fffff))
134 yield();
135 /* Dump cache for the buffer */
137 #endif