imx233: add basic ATA driver
The current driver only works in PIO mode. Change-Id: I1cf2eaedcce0172a254c3bab0e1257886226d3a0
This commit is contained in:
parent
bbb789120c
commit
0b6198f8a8
3 changed files with 313 additions and 0 deletions
|
@ -521,6 +521,9 @@ target/arm/imx233/kernel-imx233.c
|
|||
# if (CONFIG_STORAGE & (STORAGE_SD | STORAGE_MMC))
|
||||
target/arm/imx233/sdmmc-imx233.c
|
||||
# endif
|
||||
# if (CONFIG_STORAGE & (STORAGE_ATA))
|
||||
target/arm/imx233/ata-imx233.c
|
||||
# endif
|
||||
target/arm/imx233/partitions-imx233.c
|
||||
target/arm/imx233/ssp-imx233.c
|
||||
target/arm/imx233/dma-imx233.c
|
||||
|
|
232
firmware/target/arm/imx233/ata-imx233.c
Normal file
232
firmware/target/arm/imx233/ata-imx233.c
Normal file
|
@ -0,0 +1,232 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2013 Amaury Pouly
|
||||
*
|
||||
* 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef ATA_IMX233_H
|
||||
#define ATA_IMX233_H
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "pinctrl-imx233.h"
|
||||
#include "clkctrl-imx233.h"
|
||||
#include "ata-target.h"
|
||||
#include "ata-defines.h"
|
||||
|
||||
#include "regs/regs-gpmi.h"
|
||||
|
||||
struct pio_timing_t
|
||||
{
|
||||
/** all values are in ns */
|
||||
int addr_setup; /* "Address valid to DIOR-/DIOW-setup" */
|
||||
int data_hold; /* "DIOR-/DIOW-recovery time" */
|
||||
int data_setup; /* "DIOR-/DIOW-" */
|
||||
};
|
||||
|
||||
static struct pio_timing_t pio_timing[] =
|
||||
{
|
||||
/* FIXME: OF uses 290, 290, 290, 80, 70 for data_setup */
|
||||
{70, 100, 165},
|
||||
{50, 100, 125},
|
||||
{30, 100, 100},
|
||||
{30, 70, 80},
|
||||
{25, 25, 70},
|
||||
};
|
||||
|
||||
static void imx233_ata_wait_ready(void)
|
||||
{
|
||||
while(BF_RD(GPMI_CTRL0, RUN))
|
||||
yield();
|
||||
}
|
||||
|
||||
static uint16_t imx233_ata_read_reg(unsigned reg)
|
||||
{
|
||||
/* wait ready */
|
||||
imx233_ata_wait_ready();
|
||||
|
||||
/* setup command */
|
||||
HW_GPMI_CTRL0 = BF_OR6(GPMI_CTRL0, RUN(1),
|
||||
COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ),
|
||||
WORD_LENGTH(BV_GPMI_CTRL0_WORD_LENGTH__16_BIT),
|
||||
CS(IMX233_ATA_REG_CS(reg)), ADDRESS(IMX233_ATA_REG_ADDR(reg)),
|
||||
XFER_COUNT(1));
|
||||
|
||||
/* wait for completion */
|
||||
while(BF_RD(GPMI_STAT, FIFO_EMPTY));
|
||||
|
||||
/* get data */
|
||||
return HW_GPMI_DATA & 0xffff;
|
||||
}
|
||||
|
||||
static void imx233_ata_write_reg(unsigned reg, uint16_t data)
|
||||
{
|
||||
/* wait ready */
|
||||
imx233_ata_wait_ready();
|
||||
|
||||
/* setup command */
|
||||
HW_GPMI_CTRL0 = BF_OR6(GPMI_CTRL0, RUN(1),
|
||||
COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE),
|
||||
WORD_LENGTH(BV_GPMI_CTRL0_WORD_LENGTH__16_BIT),
|
||||
CS(IMX233_ATA_REG_CS(reg)), ADDRESS(IMX233_ATA_REG_ADDR(reg)),
|
||||
XFER_COUNT(1));
|
||||
|
||||
/* send data */
|
||||
HW_GPMI_DATA = data;
|
||||
}
|
||||
|
||||
uint8_t imx233_ata_inb(unsigned reg)
|
||||
{
|
||||
return imx233_ata_read_reg(reg) & 0xff;
|
||||
}
|
||||
|
||||
uint16_t imx233_ata_inw(unsigned reg)
|
||||
{
|
||||
return imx233_ata_read_reg(reg);
|
||||
}
|
||||
|
||||
void imx233_ata_outb(unsigned reg, uint8_t v)
|
||||
{
|
||||
imx233_ata_write_reg(reg, v);
|
||||
}
|
||||
|
||||
void imx233_ata_outw(unsigned reg, uint16_t v)
|
||||
{
|
||||
imx233_ata_write_reg(reg, v);
|
||||
}
|
||||
|
||||
void ata_set_pio_timings(int mode)
|
||||
{
|
||||
/* load timing */
|
||||
struct pio_timing_t t = pio_timing[mode > 3 ? 3 : mode];
|
||||
/* adjust to the clock */
|
||||
unsigned clock_freq = 80 * 1000;
|
||||
#define adjust_to_clock(val) \
|
||||
val = (val * clock_freq) / 1000 / 1000
|
||||
|
||||
adjust_to_clock(t.addr_setup);
|
||||
adjust_to_clock(t.data_hold);
|
||||
adjust_to_clock(t.data_setup);
|
||||
/* write */
|
||||
imx233_ata_wait_ready();
|
||||
HW_GPMI_TIMING0 = BF_OR3(GPMI_TIMING0, ADDRESS_SETUP(t.addr_setup),
|
||||
DATA_HOLD(t.data_hold), DATA_SETUP(t.data_setup));
|
||||
}
|
||||
|
||||
void ata_reset(void)
|
||||
{
|
||||
/* reset device */
|
||||
BF_WR_V(GPMI_CTRL1, DEV_RESET, ENABLED);
|
||||
sleep(HZ / 10);
|
||||
BF_WR_V(GPMI_CTRL1, DEV_RESET, DISABLED);
|
||||
}
|
||||
|
||||
void ata_enable(bool on)
|
||||
{
|
||||
}
|
||||
|
||||
bool ata_is_coldstart(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ATA_DMA
|
||||
void ata_dma_set_mode(unsigned char mode);
|
||||
bool ata_dma_setup(void *addr, unsigned long bytes, bool write);
|
||||
bool ata_dma_finish(void);
|
||||
#endif
|
||||
|
||||
static int ata_wait_status(unsigned status, unsigned mask, int timeout)
|
||||
{
|
||||
long end_tick = current_tick + timeout;
|
||||
|
||||
while(TIME_BEFORE(current_tick, end_tick))
|
||||
{
|
||||
if((ATA_IN8(ATA_STATUS) & mask) == status)
|
||||
return 1;
|
||||
sleep(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ata_wait_for_bsy(void)
|
||||
{
|
||||
/* BSY = 0 */
|
||||
return ata_wait_status(0, STATUS_BSY, HZ);
|
||||
}
|
||||
|
||||
int ata_wait_for_rdy(void)
|
||||
{
|
||||
/* RDY = 1 && BSY = 0 */
|
||||
return ata_wait_status(STATUS_RDY, STATUS_RDY | STATUS_BSY, HZ);
|
||||
}
|
||||
|
||||
void ata_device_init(void)
|
||||
{
|
||||
/* reset block */
|
||||
imx233_reset_block(&HW_GPMI_CTRL0);
|
||||
/* setup pins */
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D0, "ata d0", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D1, "ata d1", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D2, "ata d2", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D3, "ata d3", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D4, "ata d4", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D5, "ata d5", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D6, "ata d6", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D7, "ata d7", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D8, "ata d8", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D9, "ata d9", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D10, "ata d10", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D11, "ata d11", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D12, "ata d12", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D13, "ata d13", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D14, "ata d14", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D15, "ata d15", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_D15, "ata d15", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_CE0n, "ata cs0", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_CE1n, "ata cs1", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_A0, "ata a0", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_A1, "ata a1", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_A2, "ata a2", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_IRQ, "ata irq", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY, "ata rdy", PINCTRL_DRIVE_4mA, false);
|
||||
#ifdef HAVE_ATA_DMA
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY2, "ata dmack", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY3, "ata dmarq", PINCTRL_DRIVE_4mA, false);
|
||||
#endif
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_RDn, "ata rd", PINCTRL_DRIVE_4mA, false);
|
||||
imx233_pinctrl_setup_vpin(VPIN_GPMI_WRn, "ata wr", PINCTRL_DRIVE_4mA, false);
|
||||
/* setup ata mode */
|
||||
BF_WR_V(GPMI_CTRL1, GPMI_MODE, ATA);
|
||||
/* reset device */
|
||||
ata_reset();
|
||||
ata_enable(true);
|
||||
|
||||
/* setup mode 0 for all until identification */
|
||||
ata_set_pio_timings(0);
|
||||
|
||||
#ifdef HAVE_ATA_DMA
|
||||
ata_set_mdma_timings(0);
|
||||
ata_set_udma_timings(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ATA_IMX233_H */
|
||||
|
||||
|
||||
|
78
firmware/target/arm/imx233/ata-target.h
Normal file
78
firmware/target/arm/imx233/ata-target.h
Normal file
|
@ -0,0 +1,78 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2013 Amaury Pouly
|
||||
*
|
||||
* 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
#ifndef ATA_TARGET_H
|
||||
#define ATA_TARGET_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef BOOTLOADER
|
||||
#define ATA_DRIVER_CLOSE
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ATA_DMA
|
||||
/* FIXME does this chips does MWDMA ? */
|
||||
#define ATA_MAX_MWDMA 2
|
||||
#define ATA_MAX_UDMA 4
|
||||
#endif
|
||||
|
||||
uint8_t imx233_ata_inb(unsigned reg);
|
||||
uint16_t imx233_ata_inw(unsigned reg);
|
||||
void imx233_ata_outb(unsigned reg, uint8_t v);
|
||||
void imx233_ata_outw(unsigned reg, uint16_t v);
|
||||
|
||||
#define IMX233_ATA_REG(cs,addr) ((cs) << 3 | (addr))
|
||||
#define IMX233_ATA_REG_CS(reg) ((reg) >> 3)
|
||||
#define IMX233_ATA_REG_ADDR(reg) ((reg) & 0x7)
|
||||
/* use register address (see ATA spec) */
|
||||
#define ATA_DATA IMX233_ATA_REG(0, 0)
|
||||
#define ATA_ERROR IMX233_ATA_REG(0, 1)
|
||||
#define ATA_NSECTOR IMX233_ATA_REG(0, 2)
|
||||
#define ATA_SECTOR IMX233_ATA_REG(0, 3)
|
||||
#define ATA_LCYL IMX233_ATA_REG(0, 4)
|
||||
#define ATA_HCYL IMX233_ATA_REG(0, 5)
|
||||
#define ATA_SELECT IMX233_ATA_REG(0, 6)
|
||||
#define ATA_COMMAND IMX233_ATA_REG(0, 7)
|
||||
#define ATA_CONTROL IMX233_ATA_REG(1, 6)
|
||||
|
||||
/* keep consistent with definition of IMX233_ATA_REG */
|
||||
#define ATA_OUT8(reg, data) imx233_ata_outb(reg, data)
|
||||
#define ATA_OUT16(reg, data) imx233_ata_outw(reg, data)
|
||||
#define ATA_IN8(reg) imx233_ata_inb(reg)
|
||||
#define ATA_IN16(reg) imx233_ata_inw(reg)
|
||||
|
||||
#define ATA_SET_PIO_TIMING
|
||||
|
||||
#define ATA_TARGET_POLLING
|
||||
|
||||
void ata_set_pio_timings(int mode);
|
||||
void ata_reset(void);
|
||||
void ata_enable(bool on);
|
||||
bool ata_is_coldstart(void);
|
||||
#ifdef HAVE_ATA_DMA
|
||||
void ata_dma_set_mode(unsigned char mode);
|
||||
bool ata_dma_setup(void *addr, unsigned long bytes, bool write);
|
||||
bool ata_dma_finish(void);
|
||||
#endif
|
||||
int ata_wait_for_bsy(void);
|
||||
int ata_wait_for_rdy(void);
|
||||
void ata_device_init(void);
|
||||
|
||||
#endif /* ATA_TARGET_H */
|
Loading…
Reference in a new issue