mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
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))
|
# if (CONFIG_STORAGE & (STORAGE_SD | STORAGE_MMC))
|
||||||
target/arm/imx233/sdmmc-imx233.c
|
target/arm/imx233/sdmmc-imx233.c
|
||||||
# endif
|
# endif
|
||||||
|
# if (CONFIG_STORAGE & (STORAGE_ATA))
|
||||||
|
target/arm/imx233/ata-imx233.c
|
||||||
|
# endif
|
||||||
target/arm/imx233/partitions-imx233.c
|
target/arm/imx233/partitions-imx233.c
|
||||||
target/arm/imx233/ssp-imx233.c
|
target/arm/imx233/ssp-imx233.c
|
||||||
target/arm/imx233/dma-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…
Add table
Add a link
Reference in a new issue