eac1ca22bd
NOTE: this commit does not introduce any change, ideally even the binary should be almost the same. I checked the disassembly by hand and there are only a few differences here and there, mostly the compiler decides to compile very close expressions slightly differently. I tried to run the new code on several targets to make sure and saw no difference. The major syntax changes of the new headers are as follows: - BF_{WR,SET,CLR} are now superpowerful and allows to set several fileds at once: BF_WR(reg, field1(value1), field2(value2), ...) - BF_CS (use like BF_WR) does a write to reg_CLR and then reg_SET instead of RMW - there is no more need for macros like BF_{WR_,SET,CLR}_V, since one can simply BF_WR with field_V(name) - the old BF_SETV macro has no trivial equivalent and is replaced with its its equivalent for BF_WR(reg_SET, ...) I also rename the register headers: "regs/regs-x.h" -> "regs/x.h" to avoid the redundant "regs". Final note: the registers were generated using the following command: ./headergen_v2 -g imx -o ../../firmware/target/arm/imx233/regs/ desc/regs-stmp3{600,700,780}.xml Change-Id: I7485e8b4315a0929a8edb63e7fa1edcaa54b1edc
226 lines
6.9 KiB
C
226 lines
6.9 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* 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/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 */
|
|
BF_WR_ALL(GPMI_CTRL0, RUN(1), COMMAND_MODE_V(READ), WORD_LENGTH_V(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 */
|
|
BF_WR_ALL(GPMI_CTRL0, RUN(1), COMMAND_MODE_V(WRITE), WORD_LENGTH_V(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();
|
|
BF_WR_ALL(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(GPMI_CTRL1, DEV_RESET_V(ENABLED));
|
|
sleep(HZ / 10);
|
|
BF_WR(GPMI_CTRL1, DEV_RESET_V(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(GPMI_CTRL1, GPMI_MODE_V(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 */
|
|
|
|
|
|
|