2006-08-12 08:01:54 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
2008-03-31 04:53:03 +00:00
|
|
|
* $Id$
|
2006-08-12 08:01:54 +00:00
|
|
|
*
|
2007-01-04 11:35:09 +00:00
|
|
|
* Copyright (C) 2006,2007 by Marcoen Hirschberg
|
2006-08-12 08:01:54 +00:00
|
|
|
*
|
|
|
|
* All files in this archive are subject to the GNU General Public License.
|
|
|
|
* See the file COPYING in the source tree root for full license agreement.
|
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "kernel.h"
|
2007-04-30 12:54:05 +00:00
|
|
|
#include "thread.h"
|
2006-08-12 08:01:54 +00:00
|
|
|
#include "system.h"
|
|
|
|
#include "power.h"
|
2007-01-04 11:35:09 +00:00
|
|
|
#include "panic.h"
|
2006-08-12 08:01:54 +00:00
|
|
|
#include "pcf50606.h"
|
2007-01-04 11:35:09 +00:00
|
|
|
#include "ata-target.h"
|
2007-01-07 06:38:57 +00:00
|
|
|
#include "backlight-target.h"
|
2006-08-12 08:01:54 +00:00
|
|
|
|
2007-04-11 05:30:15 +00:00
|
|
|
/* ARESET on C7C68300 and RESET on ATA interface (Active Low) */
|
|
|
|
#define ATA_RESET_ENABLE GPGDAT &= ~(1 << 10)
|
|
|
|
#define ATA_RESET_DISABLE GPGDAT |= (1 << 10)
|
|
|
|
|
|
|
|
/* ATA_EN on C7C68300 */
|
|
|
|
#define USB_ATA_ENABLE GPBDAT |= (1 << 5)
|
|
|
|
#define USB_ATA_DISABLE GPBDAT &= ~(1 << 5)
|
|
|
|
|
2006-08-12 08:01:54 +00:00
|
|
|
void ata_reset(void)
|
|
|
|
{
|
2007-04-11 05:30:15 +00:00
|
|
|
ATA_RESET_ENABLE;
|
2006-12-29 02:49:12 +00:00
|
|
|
sleep(1); /* > 25us */
|
2007-04-11 05:30:15 +00:00
|
|
|
ATA_RESET_DISABLE;
|
2006-12-29 02:49:12 +00:00
|
|
|
sleep(1); /* > 2ms */
|
2006-08-12 08:01:54 +00:00
|
|
|
}
|
|
|
|
|
2007-04-11 05:30:15 +00:00
|
|
|
/* This function is called before enabling the USB bus */
|
2006-08-12 08:01:54 +00:00
|
|
|
void ata_enable(bool on)
|
|
|
|
{
|
2007-05-07 19:34:34 +00:00
|
|
|
GPBCON=( GPBCON&~(1<<11) ) | (1<<10); /* Make the pin an output */
|
|
|
|
GPBUP|=1<<5; /* Disable pullup in SOC as we are now driving */
|
2006-12-29 02:49:12 +00:00
|
|
|
if(on)
|
2007-04-11 05:30:15 +00:00
|
|
|
USB_ATA_DISABLE;
|
2006-12-29 02:49:12 +00:00
|
|
|
else
|
2007-04-11 05:30:15 +00:00
|
|
|
USB_ATA_ENABLE;
|
2006-08-12 08:01:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool ata_is_coldstart(void)
|
|
|
|
{
|
2007-04-11 05:30:15 +00:00
|
|
|
/* Check the pin configuration - return true when pin is unconfigured */
|
|
|
|
return (GPGCON & 0x00300000) == 0;
|
2006-08-12 08:01:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ata_device_init(void)
|
|
|
|
{
|
2007-04-11 05:30:15 +00:00
|
|
|
GPGCON=( GPGCON&~(1<<21) ) | (1<<20); /* Make the pin an output */
|
|
|
|
GPGUP |= 1<<10; /* Disable pullup in SOC as we are now driving */
|
2007-05-07 19:34:34 +00:00
|
|
|
/* ATA reset */
|
|
|
|
ATA_RESET_DISABLE; /* Set the pin to disable an active low reset */
|
2006-08-12 08:01:54 +00:00
|
|
|
}
|
2007-01-04 11:35:09 +00:00
|
|
|
|
2007-01-13 02:24:15 +00:00
|
|
|
#if !defined(BOOTLOADER)
|
2007-01-04 11:35:09 +00:00
|
|
|
void copy_read_sectors(unsigned char* buf, int wordcount)
|
|
|
|
{
|
2007-01-08 08:53:36 +00:00
|
|
|
__buttonlight_trigger();
|
2007-01-13 02:24:15 +00:00
|
|
|
|
2007-01-06 01:26:36 +00:00
|
|
|
/* Unaligned transfer - slow copy */
|
|
|
|
if ( (unsigned long)buf & 1)
|
|
|
|
{ /* not 16-bit aligned, copy byte by byte */
|
|
|
|
unsigned short tmp = 0;
|
|
|
|
unsigned char* bufend = buf + wordcount*2;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tmp = ATA_DATA;
|
|
|
|
*buf++ = tmp & 0xff; /* I assume big endian */
|
|
|
|
*buf++ = tmp >> 8; /* and don't use the SWAB16 macro */
|
|
|
|
} while (buf < bufend); /* tail loop is faster */
|
|
|
|
return;
|
|
|
|
}
|
2007-01-04 11:35:09 +00:00
|
|
|
/* This should never happen, but worth watching for */
|
|
|
|
if(wordcount > (1 << 18))
|
|
|
|
panicf("atd-meg-fx.c: copy_read_sectors: too many sectors per read!");
|
2007-01-05 04:17:25 +00:00
|
|
|
|
|
|
|
//#define GIGABEAT_DEBUG_ATA
|
2007-01-04 11:35:09 +00:00
|
|
|
#ifdef GIGABEAT_DEBUG_ATA
|
2007-01-06 01:26:36 +00:00
|
|
|
static int line = 0;
|
|
|
|
static char str[256];
|
|
|
|
snprintf(str, sizeof(str), "ODD DMA to %08x, %d", buf, wordcount);
|
|
|
|
lcd_puts(10, line, str);
|
|
|
|
line = (line+1) % 32;
|
|
|
|
lcd_update();
|
2007-01-04 11:35:09 +00:00
|
|
|
#endif
|
|
|
|
/* Reset the channel */
|
|
|
|
DMASKTRIG0 |= 4;
|
|
|
|
/* Wait for DMA controller to be ready */
|
|
|
|
while(DMASKTRIG0 & 0x2)
|
|
|
|
;
|
|
|
|
while(DSTAT0 & (1 << 20))
|
|
|
|
;
|
|
|
|
/* Source is ATA_DATA, on AHB Bus, Fixed */
|
|
|
|
DISRC0 = (int) 0x18000000;
|
|
|
|
DISRCC0 = 0x1;
|
|
|
|
/* Dest mapped to physical address, on AHB bus, increment */
|
2007-01-13 02:24:15 +00:00
|
|
|
DIDST0 = (int) buf;
|
|
|
|
if(DIDST0 < 0x30000000)
|
|
|
|
DIDST0 += 0x30000000;
|
2007-01-04 11:35:09 +00:00
|
|
|
DIDSTC0 = 0;
|
|
|
|
|
2007-04-30 12:54:05 +00:00
|
|
|
/* DACK/DREQ Sync to AHB, Whole service, No reload, 16-bit transfers */
|
|
|
|
DCON0 = ((1 << 30) | (1<<27) | (1<<22) | (1<<20)) | wordcount;
|
2007-01-04 11:35:09 +00:00
|
|
|
|
|
|
|
/* Activate the channel */
|
|
|
|
DMASKTRIG0 = 0x2;
|
|
|
|
|
2007-01-06 01:26:36 +00:00
|
|
|
invalidate_dcache_range((void *)buf, wordcount*2);
|
2007-01-04 11:35:09 +00:00
|
|
|
|
|
|
|
/* Start DMA */
|
|
|
|
DMASKTRIG0 |= 0x1;
|
|
|
|
|
|
|
|
/* Wait for transfer to complete */
|
|
|
|
while((DSTAT0 & 0x000fffff))
|
2008-03-25 02:34:12 +00:00
|
|
|
yield();
|
2007-01-06 01:26:36 +00:00
|
|
|
/* Dump cache for the buffer */
|
2007-01-05 04:17:25 +00:00
|
|
|
}
|
2007-01-13 02:24:15 +00:00
|
|
|
#endif
|