| /* |
| * (C) Copyright 2000-2006 |
| * ARC International |
| * |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of |
| * the License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| * MA 02111-1307 USA |
| * |
| * AA4 IDE intitialization code cribed from arc_cobalt |
| * |
| */ |
| |
| |
| #include <common.h> |
| |
| #ifdef CONFIG_CMD_IDE |
| |
| static unsigned p_base_addr = (CONFIG_SYS_ATA_BASE_ADDR - 0x9000); |
| /* ------------------------------------------------------------------------- */ |
| |
| #define IDE_ID (* (volatile unsigned long *) (p_base_addr + 0x00009000)) |
| #define IDE_PIO (* (volatile unsigned long *) (p_base_addr + 0x00009004)) |
| #define IDE_STAT (* (volatile unsigned long *) (p_base_addr + 0x00009008)) |
| #define IDE_PIO_ACC (* (volatile unsigned long *) (p_base_addr + 0x000090A0)) |
| #define IDE_ERROR_REG (* (volatile unsigned long *) (p_base_addr + 0x000090A4)) |
| #define IDE_SEC_CNT (* (volatile unsigned long *) (p_base_addr + 0x000090A8)) |
| #define IDE_LBA_LOW (* (volatile unsigned long *) (p_base_addr + 0x000090AC)) |
| #define IDE_LBA_MID (* (volatile unsigned long *) (p_base_addr + 0x000090B0)) |
| #define IDE_LBA_HIGH (* (volatile unsigned long *) (p_base_addr + 0x000090B4)) |
| #define IDE_DEVICE_REG (* (volatile unsigned long *) (p_base_addr + 0x000090B8)) |
| #define IDE_CMD_REG (* (volatile unsigned long *) (p_base_addr + 0x000090BC)) |
| #define IDE_DEV_HEAD_CNTRL (* (volatile unsigned long *) (p_base_addr + 0x000090D8)) |
| #define IDE_ERROR_REG (* (volatile unsigned long *) (p_base_addr + 0x000090A4)) |
| #define IDE_ALT_STAT (* (volatile unsigned long *) (p_base_addr + 0x000090D8)) |
| |
| void WaitForReady(void) |
| { |
| // Bit 6 of the status register is the ready bit. |
| // Command register when read acts as the status register |
| unsigned long rdy; |
| do |
| { |
| rdy = IDE_CMD_REG; |
| } |
| while(!((rdy >> 6) & 0x01)); |
| } |
| |
| void WaitForBusyClear(void) |
| { |
| int i=0; |
| // Bit 6 of the status register is the ready bit. |
| // Command register when read acts as the status register |
| unsigned long busy; |
| do |
| { |
| busy = IDE_CMD_REG; |
| if (i++ > 1000000) |
| { |
| printf("timeout in WaitForBusyClear, IDE_CMD_REG=%x\n", IDE_CMD_REG); |
| break; |
| } |
| } |
| while((busy >> 7) & 0x01); |
| } |
| |
| |
| void Delay_ms(int x) |
| { |
| udelay (1000 * x); |
| } |
| |
| #define PCMCIA_SHT(t) ((t & 0xff)<<16) /* Strobe Hold Time */ |
| #define PCMCIA_SST(t) ((t & 0xff)<<8) /* Strobe Setup Time */ |
| #define PCMCIA_SL(t) (t & 0xff) /* Strobe Length */ |
| |
| static unsigned cy(unsigned x) |
| { |
| return (x * (CONFIG_SYS_HZ/1000000))/1000; |
| } |
| |
| int ide_preinit(void) |
| { |
| unsigned pio_setup, pio_length, pio_hold, pio_total, timings; |
| |
| printf("Resetting IDE device...\n"); |
| |
| /* setup PIO mode 0 */ |
| pio_setup=cy(70); |
| pio_length=cy(165); |
| pio_hold=cy(30); |
| pio_total=cy(600); |
| |
| # define UNDER (pio_setup + pio_length + pio_hold < pio_total) |
| while (UNDER) |
| { |
| pio_length++; |
| if (UNDER) pio_setup++; |
| if (UNDER) pio_length++; |
| } |
| |
| timings = PCMCIA_SHT(pio_hold) |
| | PCMCIA_SST(pio_setup) |
| | PCMCIA_SL (pio_length) |
| ; |
| printf("pio mode 0 timings (%u, %u %u) = %x\n", pio_setup, pio_length, pio_hold, timings); |
| |
| |
| |
| // Set up the PIO Timing register |
| IDE_PIO = timings; |
| |
| // Issue the hardware reset and wait for some cycle for the |
| // reset to complete. |
| // Bit 2 in the control register is the reset bit |
| // Writing 0 to it will reset it |
| IDE_STAT = 0x00; |
| |
| // wait for the reset to complete |
| Delay_ms (5); |
| |
| // Clear the IDE bus reset-line |
| IDE_STAT = 0x04; |
| |
| // Wait for Busy bit to clear |
| WaitForBusyClear(); |
| |
| |
| // Now set the software reset bit in the IDE |
| IDE_DEV_HEAD_CNTRL = 0x04; |
| |
| // Wait for 5 ms |
| Delay_ms (5); |
| |
| // Clear the S/W reset |
| IDE_DEV_HEAD_CNTRL = 0x00; |
| |
| // Wait for Busy bit to clear |
| WaitForBusyClear(); |
| |
| // Chack if the device is ready |
| WaitForReady(); |
| |
| // Set the head number as 0 and the device to be master |
| // bits 3..0 of this register hold the head number (0..15) for a |
| // transfer. The bit 4 is to be written 0 for access to the IDE |
| // master device, 1 for access to the IDE slave device. The bits |
| // 7..5 are fixed at 101B in the traditional interface. |
| IDE_DEVICE_REG = 0x00; |
| |
| WaitForReady(); |
| |
| // Wait for Busy bit to clear |
| WaitForBusyClear(); |
| |
| printf("IDE device reset OK.\n"); |
| return 0; |
| } |
| |
| #endif |