/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: ata-e200.c 13557 2007-06-05 07:03:30Z jethead71 $ * * Copyright (C) 2006 Daniel Ankers * * 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 "ata.h" #include "hotswap-target.h" #include "ata-target.h" #include "ata_idle_notify.h" #include "system.h" #include #include "thread.h" #include "disk.h" #include "pp5024.h" #include "panic.h" #define BLOCK_SIZE (512) #define SECTOR_SIZE (512) #define BLOCKS_PER_BANK 0x7a7800 #define STATUS_REG (*(volatile unsigned int *)(0x70008204)) #define REG_1 (*(volatile unsigned int *)(0x70008208)) #define UNKNOWN (*(volatile unsigned int *)(0x70008210)) #define BLOCK_SIZE_REG (*(volatile unsigned int *)(0x7000821c)) #define BLOCK_COUNT_REG (*(volatile unsigned int *)(0x70008220)) #define REG_5 (*(volatile unsigned int *)(0x70008224)) #define CMD_REG0 (*(volatile unsigned int *)(0x70008228)) #define CMD_REG1 (*(volatile unsigned int *)(0x7000822c)) #define CMD_REG2 (*(volatile unsigned int *)(0x70008230)) #define RESPONSE_REG (*(volatile unsigned int *)(0x70008234)) #define SD_STATE_REG (*(volatile unsigned int *)(0x70008238)) #define REG_11 (*(volatile unsigned int *)(0x70008240)) #define REG_12 (*(volatile unsigned int *)(0x70008244)) #define DATA_REG (*(volatile unsigned int *)(0x70008280)) #define DATA_DONE (1 << 12) #define CMD_DONE (1 << 13) #define ERROR_BITS (0x3f) #define READY_FOR_DATA (1 << 8) #define FIFO_FULL (1 << 7) #define FIFO_EMPTY (1 << 6) /* SD States */ #define IDLE 0 #define READY 1 #define IDENT 2 #define STBY 3 #define TRAN 4 #define DATA 5 #define RCV 6 #define PRG 7 #define DIS 8 #define FIFO_SIZE 16 /* FIFO is 16 words deep */ /* SD Commands */ #define GO_IDLE_STATE 0 #define ALL_SEND_CID 2 #define SEND_RELATIVE_ADDR 3 #define SET_DSR 4 #define SWITCH_FUNC 6 #define SELECT_CARD 7 #define DESELECT_CARD 7 #define SEND_CSD 9 #define SEND_CID 10 #define STOP_TRANSMISSION 12 #define SEND_STATUS 13 #define GO_INACTIVE_STATE 15 #define SET_BLOCKLEN 16 #define READ_SINGLE_BLOCK 17 #define READ_MULTIPLE_BLOCK 18 #define SEND_NUM_WR_BLOCKS 22 #define WRITE_BLOCK 24 #define WRITE_MULTIPLE_BLOCK 25 #define ERASE_WR_BLK_START 32 #define ERASE_WR_BLK_END 33 #define ERASE 38 #define EC_POWER_UP 1 /* error code */ #define EC_READ_TIMEOUT 2 /* error code */ #define EC_WRITE_TIMEOUT 3 /* error code */ #define EC_TRAN_SEL_BANK 4 /* error code */ #define EC_TRAN_READ_ENTRY 5 /* error code */ #define EC_TRAN_READ_EXIT 6 /* error code */ #define EC_TRAN_WRITE_ENTRY 7 /* error code */ #define EC_TRAN_WRITE_EXIT 8 /* error code */ #define DO_PANIC 32 /* marker */ #define NO_PANIC 0 /* marker */ #define EC_COMMAND 10 /* error code */ #define EC_FIFO_SEL_BANK_EMPTY 11 /* error code */ #define EC_FIFO_SEL_BANK_DONE 12 /* error code */ #define EC_FIFO_ENA_BANK_EMPTY 13 /* error code */ #define EC_FIFO_READ_FULL 14 /* error code */ #define EC_FIFO_WR_EMPTY 15 /* error code */ #define EC_FIFO_WR_DONE 16 /* error code */ /* Application Specific commands */ #define SET_BUS_WIDTH 6 #define SD_APP_OP_COND 41 long last_disk_activity = -1; static bool sd_thread_initialized = false; static tSDCardInfo card_info[2]; static tSDCardInfo *currcard; /* current active card */ static struct mutex sd_mtx; static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x800)/sizeof(long)]; static const char sd_thread_name[] = "sd"; static struct event_queue sd_queue; static int sd_countdown; /* for sd switch debouncing */ static bool sd_monitor_enabled = true; static int last_sd_status = 0; static enum {SD_UNKNOWN, SD_UNTOUCHED, SD_TOUCHED} sd_status = SD_UNKNOWN; static void sd_tick(void); /* Private Functions */ static unsigned int check_time[10]; static inline void sd_check_timeout(unsigned int timeout, int id) { if(USEC_TIMER > check_time[id] + timeout) panicf("Error SDCard: %d", id); } static inline bool sd_poll_status(unsigned int trigger, unsigned int timeout, int id) { unsigned int t = USEC_TIMER; while ((STATUS_REG & trigger) == 0) { if(USEC_TIMER > t + timeout) { if(id & DO_PANIC) panicf("Error SDCard: %d", id & 31); return false; } } return true; } bool sd_command(unsigned int cmd, unsigned long arg1, unsigned int *response, unsigned int type) { int i, words; /* Number of 16 bit words to read from RESPONSE_REG */ unsigned int data[9]; do { CMD_REG0 = cmd; CMD_REG1 = (unsigned int)((arg1 & 0xffff0000) >> 16); CMD_REG2 = (unsigned int)((arg1 & 0xffff)); UNKNOWN = type; sd_poll_status(CMD_DONE, 100000, EC_COMMAND | DO_PANIC); } while (STATUS_REG & ERROR_BITS); if(cmd == GO_IDLE_STATE) return true; /* no response here */ words = (type == 2) ? 9 : 3; for (i = 0; i < words; i++) /* RESPONSE_REG is read MSB first */ { data[i] = RESPONSE_REG; /* Read most significant 16-bit word */ } if(type == 2) { /* Response type 2 has the following structure: Start bit Transmission bit Reserved (6 bits) CSD/CID register (127 bits) Stop bit */ response[3] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); response[2] = (data[2]<<24) + (data[3]<<8) + ((data[4]&0xff00)>>8); response[1] = (data[4]<<24) + (data[5]<<8) + ((data[6]&0xff00)>>8); response[0] = (data[6]<<24) + (data[7]<<8) + ((data[8]&0xff00)>>8); } else { /* Response types 1,3 have the following structure: Start bit Transmission bit Command index (6 bits) Card data (32 bits) CRC7 (7 bits) Stop bit */ response[0] = (data[0]<<24) + (data[1]<<8) + ((data[2]&0xff00)>>8); } return true; } void sd_wait_for_state(unsigned int state, unsigned int id) { unsigned int response = 0; check_time[id] = USEC_TIMER; while(((response >> 9) & 0xf) != state) { <<<<<<< .mine sd_command(SEND_STATUS, currcard->rca, &response, 1); sd_check_timeout(0x80000, id); ======= sd_send_command(SEND_STATUS, (card->rca) << 16, 1); priority_yield(); sd_read_response(&response, 1); /* TODO: Add a timeout and error handling */ >>>>>>> .r13569 } SD_STATE_REG = state; } static inline void copy_read_sectors(unsigned char* buf) { if ( (int)buf & 1) { /* not 16-bit aligned, copy byte by byte */ unsigned int tmp = 0; unsigned char* bufend = buf + FIFO_SIZE*2; do { tmp = DATA_REG; *buf++ = tmp & 0xff; *buf++ = tmp >> 8; } while (buf < bufend); /* tail loop is faster */ } else { /* 16-bit aligned, can do faster copy */ unsigned short* wbuf = (unsigned short*)buf; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; *wbuf++ = DATA_REG; } } static inline void copy_write_sectors(const unsigned char* buf) { unsigned short tmp = 0; const unsigned char* bufend = buf + FIFO_SIZE*2; do { tmp = (unsigned short) *buf++; tmp |= (unsigned short) *buf++ << 8; DATA_REG = tmp; } while (buf < bufend); /* tail loop is faster */ } void sd_select_bank(unsigned char bank) { unsigned int response; unsigned char card_data[512]; unsigned char* write_buf; int i; if (currcard->current_bank != bank) { memset(card_data, 0, 512); sd_wait_for_state(TRAN, EC_TRAN_SEL_BANK); BLOCK_SIZE_REG = 512; BLOCK_COUNT_REG = 1; sd_command(35, 0, &response, 0x1c0d); /* CMD35 is vendor specific */ SD_STATE_REG = PRG; card_data[0] = bank; /* Write the card data */ write_buf = card_data; for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) { /* Wait for the FIFO to empty */ sd_poll_status(FIFO_EMPTY, 10000, EC_FIFO_SEL_BANK_EMPTY | DO_PANIC); copy_write_sectors(write_buf); /* Copy one chunk of 16 words */ write_buf += FIFO_SIZE*2; /* Advance one chunk of 16 words */ } sd_poll_status(DATA_DONE, 10000, EC_FIFO_SEL_BANK_DONE | DO_PANIC); currcard->current_bank = bank; } } void sd_init_device(int card_no) { /* SD Protocol registers */ unsigned int i, dummy; unsigned int c_size = 0; unsigned long c_mult = 0; unsigned char carddata[512]; unsigned char *dataptr; currcard = &card_info[card_no]; /* Initialise card data as blank */ memset(currcard, 0, sizeof(*currcard)); /* Enable and initialise controller */ GPIOG_ENABLE |= (0x3 << 5); GPIOG_OUTPUT_EN |= (0x3 << 5); GPIOG_OUTPUT_VAL |= (0x3 << 5); outl(inl(0x70000088) & ~(0x4), 0x70000088); outl(inl(0x7000008c) & ~(0x4), 0x7000008c); outl(inl(0x70000080) | 0x4, 0x70000080); outl(inl(0x70000084) | 0x4, 0x70000084); REG_1 = 6; outl(0x1010, 0x70000034); GPIOA_ENABLE |= (1 << 7); GPIOA_OUTPUT_EN &= ~(1 << 7); if(card_no == 0) { GPIOA_ENABLE &= ~0x7a; GPIOA_OUTPUT_EN &= ~0x7a; GPIOD_ENABLE |= 0x1f; GPIOD_OUTPUT_EN |= 0x1f; outl((inl(0x70000014) & ~(0x3ffff)) | 0x255aa, 0x70000014); } else { outl(inl(0x70000080) & ~0x4, 0x70000080); GPIOD_ENABLE &= ~0x1f; GPIOD_OUTPUT_EN &= ~0x1f; GPIOA_ENABLE |= 0x7a; GPIOA_OUTPUT_EN |= 0x7a; outl(inl(0x70000014) & ~(0x3ffff), 0x70000014); } DEV_EN |= DEV_ATA; /* Enable controller */ DEV_RS |= DEV_ATA; /* Reset controller */ DEV_RS &=~DEV_ATA; /* Clear Reset */ /* Init NAND */ REG_11 |= (1 << 15); REG_12 |= (1 << 15); REG_12 &= ~(3 << 12); REG_12 |= (1 << 13); REG_11 &= ~(3 << 12); REG_11 |= (1 << 13); SD_STATE_REG = TRAN; REG_5 = 0xf; sd_command(GO_IDLE_STATE, 0, &dummy, 256); check_time[EC_POWER_UP] = USEC_TIMER; while ((currcard->ocr & (1 << 31)) == 0) /* until card is powered up */ { sd_command(55, currcard->rca, &dummy, 1); sd_command(SD_APP_OP_COND, 0x100000, &currcard->ocr, 3); sd_check_timeout(5000000, EC_POWER_UP); } sd_command(ALL_SEND_CID, 0, currcard->cid, 2); sd_command(SEND_RELATIVE_ADDR, 0, &currcard->rca, 1); sd_command(SEND_CSD, currcard->rca, currcard->csd, 2); /* These calculations come from the Sandisk SD card product manual */ c_size = ((currcard->csd[2] & 0x3ff) << 2) + (currcard->csd[1] >> 30) + 1; c_mult = 4 << ((currcard->csd[1] >> 15) & 7); currcard->max_read_bl_len = 1 << ((currcard->csd[2] >> 16) & 15); currcard->block_size = BLOCK_SIZE; /* Always use 512 byte blocks */ currcard->numblocks = c_size * c_mult * (currcard->max_read_bl_len / 512); currcard->capacity = currcard->numblocks * currcard->block_size; REG_1 = 0; sd_command(SELECT_CARD, currcard->rca , &dummy, 129); sd_command(55, currcard->rca , &dummy, 1); sd_command(SET_BUS_WIDTH, currcard->rca | 2 , &dummy, 1); /* 4 bit */ sd_command(SET_BLOCKLEN, currcard->block_size, &dummy, 1); BLOCK_SIZE_REG = currcard->block_size; /* If this card is > 4Gb, then we need to enable bank switching */ if(currcard->numblocks >= BLOCKS_PER_BANK) { SD_STATE_REG = TRAN; BLOCK_COUNT_REG = 1; sd_command(SWITCH_FUNC, 0x80ffffef, &dummy, 0x1c05); /* Read 512 bytes from the card. The first 512 bits contain the status information TODO: Do something useful with this! */ dataptr = carddata; for (i = 0; i < BLOCK_SIZE / 2; i += FIFO_SIZE) { /* Wait for the FIFO to be full */ sd_poll_status(FIFO_FULL, 100000, EC_FIFO_ENA_BANK_EMPTY | DO_PANIC); copy_read_sectors(dataptr); /* Copy one chunk of 16 words */ dataptr += (FIFO_SIZE*2); /* Advance one chunk of 16 words */ } } <<<<<<< .mine currcard->initialized = true; ======= spinlock_init(&sd_mtx); >>>>>>> .r13569 } /* API Functions */ void ata_led(bool onoff) { (void)onoff; } int ata_read_sectors(IF_MV2(int drive,) unsigned long start, int incount, void* inbuf) { int ret = 0; void *buf, *buf_end; unsigned int dummy; /* TODO: Add DMA support. */ spinlock_lock(&sd_mtx); ata_enable(true); ata_led(true); if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */ { ret = -9; goto error; } if((card_info+drive != currcard) || !card_info[drive].initialized) sd_init_device(drive); last_disk_activity = current_tick; if(start >= BLOCKS_PER_BANK) { sd_select_bank(1); start -= BLOCKS_PER_BANK; } else sd_select_bank(0); ret = 0; sd_wait_for_state(TRAN, EC_TRAN_READ_ENTRY); BLOCK_COUNT_REG = incount; sd_command(READ_MULTIPLE_BLOCK, start * BLOCK_SIZE, &dummy, 0x1c25); /* TODO: Don't assume BLOCK_SIZE == SECTOR_SIZE */ buf_end = inbuf + incount * currcard->block_size; for (buf = inbuf; buf < buf_end; buf += FIFO_SIZE*2) { /* Wait for the FIFO to be full */ sd_poll_status(FIFO_FULL, 0x80000, EC_FIFO_READ_FULL | DO_PANIC); copy_read_sectors(buf); /* Copy one chunk of 16 words */ /* TODO: Switch bank if necessary */ } last_disk_activity = current_tick; // udelay(75); sd_command(STOP_TRANSMISSION, 0, &dummy, 1); sd_wait_for_state(TRAN, EC_TRAN_READ_EXIT); error: ata_led(false); ata_enable(false); spinlock_unlock(&sd_mtx); return ret; } int ata_write_sectors(IF_MV2(int drive,) unsigned long start, int count, const void* outbuf) { /* Write support is not finished yet */ /* TODO: The standard suggests using ACMD23 prior to writing multiple blocks to improve performance */ unsigned int response; void const* buf, *buf_end; int ret = 0; spinlock_lock(&sd_mtx); ata_enable(true); ata_led(true); if(drive && (GPIOA_INPUT_VAL & 0x80)) /* no external sd-card inserted */ { ret = -9; goto error; } if((card_info+drive != currcard) || !card_info[drive].initialized) sd_init_device(drive); if(start >= BLOCKS_PER_BANK) { sd_select_bank(1); start -= BLOCKS_PER_BANK; } else sd_select_bank(0); check_time[EC_WRITE_TIMEOUT] = USEC_TIMER; sd_wait_for_state(TRAN, EC_TRAN_WRITE_ENTRY); BLOCK_COUNT_REG = count; sd_command(WRITE_MULTIPLE_BLOCK, start * SECTOR_SIZE, &response, 0x1c2d); buf_end = outbuf + count * currcard->block_size; for (buf = outbuf; buf < buf_end; buf += 2 * FIFO_SIZE) { if(buf >= buf_end - 2 * FIFO_SIZE) { /* Set SD_STATE_REG to PRG for the last buffer fill */ SD_STATE_REG = PRG; } udelay(2); /* needed here (loop is too fast :-) */ /* Wait for the FIFO to empty */ sd_poll_status(FIFO_EMPTY, 0x80000, EC_FIFO_WR_EMPTY | DO_PANIC); copy_write_sectors(buf); /* Copy one chunk of 16 words */ /* TODO: Switch bank if necessary */ } last_disk_activity = current_tick; sd_poll_status(DATA_DONE, 0x80000, EC_FIFO_WR_DONE | DO_PANIC); sd_check_timeout(0x80000, EC_WRITE_TIMEOUT); sd_command(STOP_TRANSMISSION, 0, &response, 1); sd_wait_for_state(TRAN, EC_TRAN_WRITE_EXIT); error: ata_led(false); ata_enable(false); spinlock_unlock(&sd_mtx); return ret; } static void sd_thread(void) { struct event ev; bool idle_notified = false; while (1) { queue_wait_w_tmo(&sd_queue, &ev, HZ); switch ( ev.id ) { case SYS_CARD_INSERTED: disk_mount(1); /* mount SD-CARD */ queue_broadcast(SYS_FS_CHANGED, 0); break; case SYS_CARD_EXTRACTED: disk_unmount(1); /* release "by force" */ queue_broadcast(SYS_FS_CHANGED, 0); break; default: if (TIME_BEFORE(current_tick, last_disk_activity+(3*HZ))) { idle_notified = false; } else { if (!idle_notified) { call_ata_idle_notifys(false); idle_notified = true; } } break; } } } void ata_spindown(int seconds) { (void)seconds; } bool ata_disk_is_active(void) { return 0; } void ata_sleep(void) { } void ata_spin(void) { } /* Hardware reset protocol as specified in chapter 9.1, ATA spec draft v5 */ int ata_hard_reset(void) { return 0; } int ata_soft_reset(void) { return 0; } void ata_enable(bool on) { if(on) { DEV_EN |= DEV_ATA; /* Enable controller */ } else { DEV_EN &= ~DEV_ATA; /* Disable controller */ } } int ata_init(void) { mutex_init(&sd_mtx); sd_init_device(0); if ( !sd_thread_initialized ) { queue_init(&sd_queue, true); create_thread(sd_thread, sd_stack, sizeof(sd_stack), sd_thread_name IF_PRIO(, PRIORITY_SYSTEM) IF_COP(, CPU, false)); tick_add_task(sd_tick); sd_thread_initialized = true; } return 0; } /* move the sd-card info to mmc struct */ tCardInfo *card_get_info_target(int card_no) { int i, temp; static tCardInfo card; static const char mantissa[] = { /* *10 */ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 }; static const int exponent[] = { /* use varies */ 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000 }; card.initialized = card_info[card_no].initialized; card.ocr = card_info[card_no].ocr; for(i=0; i<4; i++) card.csd[i] = card_info[card_no].csd[3-i]; for(i=0; i<4; i++) card.cid[i] = card_info[card_no].cid[3-i]; card.numblocks = card_info[card_no].numblocks; card.blocksize = card_info[card_no].block_size; card.size = card_info[card_no].capacity < 0xffffffff ? card_info[card_no].capacity : 0xffffffff; card.block_exp = card_info[card_no].block_exp; temp = card_extract_bits(card.csd, 29, 3); card.speed = mantissa[card_extract_bits(card.csd, 25, 4)] * exponent[temp > 2 ? 7 : temp + 4]; card.nsac = 100 * card_extract_bits(card.csd, 16, 8); temp = card_extract_bits(card.csd, 13, 3); card.tsac = mantissa[card_extract_bits(card.csd, 9, 4)] * exponent[temp] / 10; card.cid[0] = htobe32(card.cid[0]); /* ascii chars here */ card.cid[1] = htobe32(card.cid[1]); /* ascii chars here */ temp = *((char*)card.cid+13); /* adjust year<=>month, 1997 <=> 2000 */ *((char*)card.cid+13) = (unsigned char)((temp >> 4) | (temp << 4)) + 3; return &card; } bool card_touched_target(void) { if (sd_status == SD_UNKNOWN) /* try to detect */ { if(~GPIOA_INPUT_VAL & 0x80) { mutex_lock(&sd_mtx); sd_init_device(1); sd_status = SD_TOUCHED; mutex_unlock(&sd_mtx); } } return sd_status == SD_TOUCHED; } bool card_detect_target(void) { return GPIOA_INPUT_VAL & 0x80 ? false : true; } void card_enable_monitoring_target(bool on) { sd_monitor_enabled = on; } static void sd_tick(void) { int current_status; if (sd_monitor_enabled) { /* 0x80:inserted, 0x00:not inserted */ current_status = ~GPIOA_INPUT_VAL & 0x80; /* Only report when the status has changed */ if (current_status != last_sd_status) { last_sd_status = current_status; sd_countdown = 30; } else { /* Count down until it gets negative */ if (sd_countdown >= 0) sd_countdown--; if (sd_countdown == 0) { if (current_status) { queue_broadcast(SYS_CARD_INSERTED, 0); } else { queue_broadcast(SYS_CARD_EXTRACTED, 0); sd_status = SD_UNKNOWN; card_info[1].initialized = false; } } } } }