[U-Boot] [PATCH 1/2] cmd_ide: enhance new feature "CONFIG_IDE_AHB"

Although most IDE controller is designed to be connected to PCI bridge, there are still some IDE controller support AHB interface for SoC design.
The driver implementation of these IDE-AHB controllers differ from other IDE-PCI controller, some additional registers and commands access is required during CMD/DATA I/O. Hence a configuration "CONFIG_IDE_AHB" in cmd_ide.c is required to be defined to support these kinds of SoC controllers. Such as Faraday's FTIDE020 series and Global Unichip's UINF-0301.
Signed-off-by: Macpaul Lin macpaul@andestech.com --- README | 8 ++++++++ common/cmd_ide.c | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletions(-)
diff --git a/README b/README index 727bf8a..3de0605 100644 --- a/README +++ b/README @@ -2673,6 +2673,14 @@ Low Level (hardware related) configuration options: source code. It is used to make hardware dependant initializations.
+- CONFIG_IDE_AHB: + Most IDE controllers were designed to be connected with PCI + interface. Only few of them were designed for AHB interface. + When software is doing ATA command and data transfer to + IDE devices through IDE-AHB controller, some additional + registers accessing to these kind of IDE-AHB controller + is requierd. + - CONFIG_SYS_IMMR: Physical address of the Internal Memory. DO NOT CHANGE unless you know exactly what you're doing! (11-4) [MPC8xx/82xx systems only] diff --git a/common/cmd_ide.c b/common/cmd_ide.c index ea0f4a7..edb4fc0 100644 --- a/common/cmd_ide.c +++ b/common/cmd_ide.c @@ -518,8 +518,22 @@ __ide_outb(int dev, int port, unsigned char val) { debug ("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", dev, port, val, (ATA_CURR_BASE(dev)+CONFIG_SYS_ATA_PORT_ADDR(port))); + +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + extern void ide_write_register(int, unsigned int, unsigned char); + + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else outb(val, (ATA_CURR_BASE(dev)+CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif } + void ide_outb (int dev, int port, unsigned char val) __attribute__((weak, alias("__ide_outb")));
@@ -527,7 +541,15 @@ unsigned char inline __ide_inb(int dev, int port) { uchar val; + +#if defined(CONFIG_IDE_AHB) + extern unsigned char ide_read_register(int, unsigned int); + + val = ide_read_register(dev, port); +#else val = inb((ATA_CURR_BASE(dev)+CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + debug ("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", dev, port, (ATA_CURR_BASE(dev)+CONFIG_SYS_ATA_PORT_ADDR(port)), val); return val; @@ -696,6 +718,7 @@ void ide_init (void) ide_dev_desc[i].blksz=0; ide_dev_desc[i].lba=0; ide_dev_desc[i].block_read=ide_read; + ide_dev_desc[i].block_write = ide_write; if (!ide_bus_ok[IDE_BUS(i)]) continue; ide_led (led, 1); /* LED on */ @@ -902,7 +925,13 @@ output_data(int dev, ulong *sect_buf, int words) static void output_data(int dev, ulong *sect_buf, int words) { - outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words<<1); +#if defined(CONFIG_IDE_AHB) + extern void ide_write_data(int, ulong *, int); + + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words << 1); +#endif } #endif /* CONFIG_IDE_SWAP_IO */
@@ -960,7 +989,13 @@ input_data(int dev, ulong *sect_buf, int words) static void input_data(int dev, ulong *sect_buf, int words) { +#if defined(CONFIG_IDE_AHB) + extern void ide_read_data(int, ulong *, int); + + ide_read_data(dev, sect_buf, words); +#else insw(ATA_CURR_BASE(dev)+ATA_DATA_REG, sect_buf, words << 1); +#endif }
#endif /* CONFIG_IDE_SWAP_IO */

Faraday's ftide020_s is an IDE-AHB controller for SoC design. This patch ported the u-boot driver (PIO) of ftide020 ATA (IDE) driver from Linux kernel. IDE commands include read, info, and other functions has been implemented.
Because this IDE controller support AHB interface only which is differ from other most IDE controller supports PCI interface. Some registers access is required during CMD/DATA I/O. Hence a configuration "CONFIG_IDE_AHB" is required to be defined according to the feature in cmd_ide.c.
Signed-off-by: Macpaul Lin macpaul@andestech.com --- drivers/block/Makefile | 1 + drivers/block/ftide020.c | 380 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/block/ftide020.h | 265 ++++++++++++++++++++++++++++++++ 3 files changed, 646 insertions(+), 0 deletions(-) create mode 100644 drivers/block/ftide020.c create mode 100644 drivers/block/ftide020.h
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index e27175b..e3f46b8 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)libblock.o COBJS-$(CONFIG_SCSI_AHCI) += ahci.o COBJS-$(CONFIG_ATA_PIIX) += ata_piix.o COBJS-$(CONFIG_FSL_SATA) += fsl_sata.o +COBJS-$(CONFIG_IDE_FTIDE020) += ftide020.o COBJS-$(CONFIG_LIBATA) += libata.o COBJS-$(CONFIG_CMD_MG_DISK) += mg_disk.o COBJS-$(CONFIG_MVSATA_IDE) += mvsata_ide.o diff --git a/drivers/block/ftide020.c b/drivers/block/ftide020.c new file mode 100644 index 0000000..eef8c08 --- /dev/null +++ b/drivers/block/ftide020.c @@ -0,0 +1,380 @@ +/* + * [origin: Linux kernel drivers/ide/ftide020.c] + * Faraday FTIDE020 ATA Controller (AHB) + * + * (C) Copyright 2011 Andes Technology + * Greentime Hu greentime@andestech.com + * Macpaul Lin macpaul@andestech.com + * Kuo-Wei Chou kwchou@andestech.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + * + */ +/* ftide020.c - ide support functions for the FTIDE020_S controller */ + +#include <config.h> +#include <common.h> +#include <ata.h> +#include <ide.h> +#include <asm/io.h> +#include <api_public.h> + +#include "ftide020.h" + +#define FTIDE_IP_NAME "FTIDE020_S" +#define FTIDE_DRIVER_VERSION "1.0.1" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* DEBUG */ +#ifdef FTIDE_DEBUG + #define P_DEBUG(fmt, args...) printf(FTIDE_IP_NAME ":" fmt, ## args) +#else + #define P_DEBUG(a...) +#endif + +/* base address */ +#define FTIDE_BASE CONFIG_SYS_ATA_BASE_ADDR + +/* + * data address - The CMD and DATA use the same FIFO in FTIDE020_S + * FTIDE_DATA = CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_DATA_OFFSET + * = &ftide020->rw_fifo + */ +#define FTIDE_DATA (&ftide020->rw_fifo) + +/* command and data I/O macros */ +/* 0x0 - DATA FIFO */ +#define WRITE_DATA(x) outl((x), &ftide020->rw_fifo) /* 0x00 */ +#define READ_DATA() inl(&ftide020->rw_fifo) /* 0x00 */ +/* 0x04 - R: Status Reg, W: CMD_FIFO */ +#define WRITE_CMD(x) outl((x), &ftide020->cmd_fifo) /* 0x04 */ +#define READ_STATUS() inl(&ftide020->cmd_fifo) /* 0x04 */ + +#define mdelay(n) ({unsigned long msec = (n); while (msec--) udelay(1000); }) + +void ftide_set_device(int cx8, int dev) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + WRITE_CMD(SET_DEV_CMD | IDE_SET_CX8(cx8) | dev); +} + +unsigned char ide_read_register(int dev, unsigned int port) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + ftide_set_device(0, dev); + WRITE_CMD(READ_REG_CMD | IDE_REG_CS_READ(CONFIG_IDE_REG_CS) | + IDE_REG_DA_WRITE(port)); + + return READ_DATA() & 0xff; +} + +void ide_write_register(int dev, unsigned int port, unsigned char val) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + ftide_set_device(0, dev); + WRITE_CMD(WRITE_REG_CMD | IDE_REG_CS_WRITE(CONFIG_IDE_REG_CS) | + IDE_REG_DA_WRITE(port) | val); +} + +void ide_write_data(int dev, ulong *sect_buf, int words) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + ftide_set_device(0, dev); + WRITE_CMD(WRITE_DATA_CMD | ((words << 2) - 1)); + + /* block write */ + outsl(FTIDE_DATA, sect_buf, words); +} + +void ide_read_data(int dev, ulong *sect_buf, int words) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + ftide_set_device(0, dev); + WRITE_CMD(READ_DATA_CMD | ((words << 2) - 1)); + + /* block read */ + insl(FTIDE_DATA, sect_buf, words); +} + +void ftide_dfifo_ready(ulong *time) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + + while (!(READ_STATUS() & STATUS_RFE)) { + if (*time-- == 0) + break; + + udelay(100); + } +} + +extern ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS]; + +/* Reset_IDE_controller */ +static void reset_ide_controller(void) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + unsigned int val; + + val = inl(&ftide020->cr); + + val |= CONTROL_RST; + outl(val, &ftide020->cr); + + /* wait until reset OK, this is poor HW design */ + mdelay(50); + val &= ~(CONTROL_RST); + outl(val, &ftide020->cr); + + mdelay(50); + val |= CONTROL_SRST; + outl(val, &ftide020->cr); + + /* wait until reset OK, this is poor HW design */ + mdelay(50); + val &= ~(CONTROL_SRST); + outl(val, &ftide020->cr); + + /* IORDY enable for PIO, for 2 device */ + val |= (CONTROL_IRE0 | CONTROL_IRE1); + outl(val, &ftide020->cr); +} + +/* IDE clock frequence */ +uint ftide_clock_freq(void) +{ + /* + * todo: To aquire dynamic system frequency is dependend on the power + * management unit which the ftide020 is connected to. In current, + * there are only few PMU supports in u-boot. + * So this function is wait for future enhancement. + */ + return 100; +} + +/* Calculate Timing Registers */ +static unsigned int timing_cal(u16 t0, u16 t1, u16 t2, u16 t4) +{ + unsigned int val, ahb_ns = 8; + u8 TEOC, T1, T2, T4; + + T1 = (u8) (t1 / ahb_ns); + if ((T1 * ahb_ns) == t1) + T1--; + + T2 = (u8) (t2 / ahb_ns); + if ((T2 * ahb_ns) == t2) + T2--; + + T4 = (u8) (t4 / ahb_ns); + if ((T4 * ahb_ns) == t4) + T4--; + + TEOC = (u8) (t0 / ahb_ns); + if ((TEOC * ahb_ns) == t0) + TEOC--; + + TEOC = ((TEOC > (T1 + T2 + T4)) ? (TEOC - (T1 + T2 + T4)) : 0); + + /* + * Here the fields in data timing registers in PIO mode + * is accessed the same way as command timing registers. + */ + val = DT_REG_PIO_T1(T1) | + DT_REG_PIO_T2(T2) | + DT_REG_PIO_T4(T4) | + DT_REG_PIO_TEOC(TEOC); + + return val; +} + +/* Set Timing Register */ +static unsigned int set_mode_timing(u8 dev, u8 id, u8 mode) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + u16 t0, t1, t2, t4; + u8 tcyc, tcvs, tmli, tenv, tack, trp; + unsigned int val, sysclk = 8; + + if (id >= TATOL_TIMING) + return FALSE; + + sysclk = ftide_clock_freq(); + switch (id) { + case CMD_TIMING: + if (mode < REG_MODE) { + t0 = REG_ACCESS_TIMING[REG_T0][mode]; + t1 = REG_ACCESS_TIMING[REG_T1][mode]; + t2 = REG_ACCESS_TIMING[REG_T2][mode]; + t4 = REG_ACCESS_TIMING[REG_T4][mode]; + + val = timing_cal(t0, t1, t2, t4); + outl(val, (dev ? &ftide020->ctrd1 : &ftide020->ctrd0)); + return TRUE; + } else + return FALSE; + case PIO_TIMING: + if (mode < PIO_MODE) { + t0 = PIO_ACCESS_TIMING[PIO_T0][mode]; + t1 = PIO_ACCESS_TIMING[PIO_T1][mode]; + t2 = PIO_ACCESS_TIMING[PIO_T2][mode]; + t4 = PIO_ACCESS_TIMING[PIO_T4][mode]; + + val = timing_cal(t0, t1, t2, t4); + + outl(val, (dev ? &ftide020->dtrd1 : &ftide020->dtrd0)); + return TRUE; + } else + return FALSE; + case DMA_TIMING: + if (mode < UDMA_MODE) { + /* + * 0.999 is ceiling + * for tcyc, tcvs, tmli, tenv, trp, tack + */ + tcyc = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCYC][mode] * sysclk) + 9990) / 10000); + tcvs = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCVS][mode] * sysclk) + 9990) / 10000); + tmli = (u8) (((UDMA_ACCESS_TIMING[UDMA_TMLI][mode] * sysclk) + 9990) / 10000); + tenv = (u8) (((UDMA_ACCESS_TIMING[UDMA_TENV][mode] * sysclk) + 9990) / 10000); + trp = (u8) (((UDMA_ACCESS_TIMING[UDMA_TRP][mode] * sysclk) + 9990) / 10000); + tack = (u8) (((UDMA_ACCESS_TIMING[UDMA_TACK][mode] * sysclk) + 9990) / 10000); + + val = DT_REG_UDMA_TENV((tenv > 0) ? (tenv - 1) : 0) | + DT_REG_UDMA_TMLI((tmli > 0) ? (tmli - 1) : 0) | + DT_REG_UDMA_TCYC((tcyc > 0) ? (tcyc - 1) : 0) | + DT_REG_UDMA_TACK((tack > 0) ? (tack - 1) : 0) | + DT_REG_UDMA_TCVS((tcvs > 0) ? (tcvs - 1) : 0) | + DT_REG_UDMA_TRP((trp > 0) ? (trp - 1) : 0); + + outl(val, (dev ? &ftide020->dtrd1 : &ftide020->dtrd0)); + return TRUE; + } else + return FALSE; + default: + return FALSE; + } +} + +static void ftide_read_hwrev(void) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + unsigned int rev; + + rev = inl(&ftide020->revision); +} + +static int ftide_controller_probe(void) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + unsigned int bak; + + bak = inl(&ftide020->ctrd1); + + /* probing by using shorter setup time */ + outl(CONFIG_CTRD1_PROBE_T1, &ftide020->ctrd1); + if ((inl(&ftide020->ctrd1) & 0xff) != CONFIG_CTRD1_PROBE_T1) { + outl(bak, &ftide020->ctrd1); + return 0; + } + + /* probing by using longer setup time */ + outl(CONFIG_CTRD1_PROBE_T2, &ftide020->ctrd1); + if ((inl(&ftide020->ctrd1) & 0xff) != CONFIG_CTRD1_PROBE_T2) { + outl(bak, &ftide020->ctrd1); + return 0; + } + + outl(bak, &ftide020->ctrd1); + + return 1; +} + +/* ide_preinit() was migrated from linux driver ide_probe_for_ftide() */ +int ide_preinit(void) +{ + static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE; + int status; + unsigned int val; + int i; + + status = 1; + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; i++) + ide_bus_offset[i] = -ATA_STATUS; + + /* auto-detect IDE controller */ + if (ftide_controller_probe()) { + printf("Faraday %s driver version %s\n", FTIDE_IP_NAME, + FTIDE_DRIVER_VERSION); + } else { + printf("Faraday ATA controller not found.\n"); + return API_ENODEV; + } + + /* check HW IP revision */ + ftide_read_hwrev(); + + /* set FIFO threshold */ + outl(((WRITE_FIFO - RX_THRESH) << 16) | RX_THRESH, &ftide020->dmatirr); + + /* set Device_0 PIO_0 timing */ + set_mode_timing(0, CMD_TIMING, REG_MODE0); + set_mode_timing(0, PIO_TIMING, PIO_MODE0); + + /* set Device_1 PIO_0 timing */ + set_mode_timing(1, CMD_TIMING, REG_MODE0); + set_mode_timing(1, PIO_TIMING, PIO_MODE0); + + /* from E-bios */ + /* little endian */ + outl(0x0, &ftide020->cr); + mdelay(10); + + outl(0x0fff0fff, &ftide020->ahbtr); + mdelay(10); + + /* Enable controller Interrupt */ + val = inl(&ftide020->cr); + + /* Enable: IDE IRQ, IDE Terminate ERROR IRQ, AHB Timeout error IRQ */ + val |= (CONTROL_IIE | CONTROL_TERIE | CONTROL_AERIE); + outl(val, &ftide020->cr); + + status = 0; + + return status; +} + +void ide_set_reset(int flag) +{ + debug("ide_set_reset()\n"); + reset_ide_controller(); + return; +} diff --git a/drivers/block/ftide020.h b/drivers/block/ftide020.h new file mode 100644 index 0000000..f3eefec --- /dev/null +++ b/drivers/block/ftide020.h @@ -0,0 +1,265 @@ +/* + * Faraday FTIDE020_s ATA Controller (AHB) + * + * (C) Copyright 2011 Andes Technology + * Greentime Hu greentime@andestech.com + * Macpaul Lin macpaul@andestech.com + * Kuo-Wei Chou kwchou@andestech.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + * + */ + +#ifndef __FTIDE020_H +#define __FTIDE020_H + +/* ftide020.h - ide support functions for the FTIDE020_S controller */ + +/* ATA controller register offset */ +struct ftide020_s { + unsigned int rw_fifo; /* 0x00 - READ/WRITE FIFO */ + unsigned int cmd_fifo; /* 0x04 - R: Status Reg, W: CMD_FIFO */ + unsigned int cr; /* 0x08 - Control Reg */ + unsigned int dmatirr; /* 0x0c - DMA Threshold/Interrupt Reg */ + unsigned int ctrd0; /* 0x10 - Command Timing Reg Device 0 */ + unsigned int dtrd0; /* 0x14 - Data Timing Reg Device 0 */ + unsigned int ctrd1; /* 0x18 - Command Timing Reg Device 1 */ + unsigned int dtrd1; /* 0x1c - Data Timing Reg Device 1 */ + unsigned int ahbtr; /* 0x20 - AHB Timeout Reg */ + unsigned int RESVD0; /* 0x24 */ + unsigned int RESVD1; /* 0x28 */ + unsigned int RESVD2; /* 0x2c */ + unsigned int f_cfifo; /* 0x30 - Feature Info of CMD_FIFO */ + unsigned int f_wfifo; /* 0x34 - Feature Info of WRITE_FIFO */ + unsigned int f_rfifo; /* 0x3c - Feature Info of READ_FIFO */ + unsigned int revision; /* 0x38 - Revision No. of FTIDE020_S */ +}; + +/* reference parameters */ +#define CONFIG_IDE_REG_CS 0x2 /* ref: ATA spec chaper 10, table 42 */ +#define CONFIG_CTRD1_PROBE_T1 0x2 +#define CONFIG_CTRD1_PROBE_T2 0x5 + +/* status register - 0x04 */ +#define STATUS_CSEL (1 << 0) /* CSEL */ +#define STATUS_CS(x) (((x) >> 1) & 0x3) /* CS#[1:0] */ +#define STATUS_DMACK (1 << 3) /* DMACK# */ +#define STATUS_DMARQ (1 << 4) /* DMA req */ +#define STATUS_INTRQ (1 << 5) /* INT req */ +#define STATUS_DIOR (1 << 6) /* DIOR */ +#define STATUS_IORDY (1 << 7) /* I/O ready */ +#define STATUS_DIOW (1 << 8) /* DIOW# */ +#define STATUS_PDIAG (1 << 9) /* PDIAG */ +#define STATUS_DASP (1 << 10) /* DASP# */ +#define STATUS_DEV (1 << 11) /* selected device */ +#define STATUS_PIO (1 << 12) /* PIO in progress */ +#define STATUS_DMA (1 << 13) /* DMA in progress */ +#define STATUS_WFE (1 << 14) /* write fifo full */ +#define STATUS_RFE (1 << 15) /* read fifo empty */ +#define STATUS_COUNTER(x) (((x) >> 16) & 0x3fff) /* data tx counter */ +#define STATUS_ERR (1 << 30) /* trasfer terminated */ +#define STATUS_AER (1 << 31) /* AHB timeout indicate */ + +/* Control register - 0x08 */ +#define CONTROL_TYPE_PIO 0x0 +#define CONTROL_TYPE_UDMA 0x1 + +/* Device 0 */ +#define CONTROL_TYP0(x) (((x) & 0x7) << 0) +#define CONTROL_IRE0 (1 << 3) /* Device 0 - enable IORDY for PIO */ +#define CONTROL_RESVD_DW0 (1 << 4) /* Reserved - DW0 ? */ +#define CONTROL_E0 (1 << 5) /* Device 0 - E0: 1: Big Endian */ +#define CONTROL_RESVD_WP0 (1 << 6) /* Reserved - WP0 ? */ +#define CONTROL_RESVD_SE0 (1 << 7) /* Reserved - SE0 ? */ +#define CONTROL_RESVD_ECC0 (1 << 8) /* Reserved - ECC0 ? */ + +#define CONTROL_RAEIE (1 << 9) /* IRQ - read fifo almost full */ +#define CONTROL_RNEIE (1 << 10) /* IRQ - read fifo not empty */ +#define CONTROL_WAFIE (1 << 11) /* IRQ - write fifo almost empty*/ +#define CONTROL_WNFIE (1 << 12) /* IRQ - write fifo not full */ +#define CONTROL_RESVD_FIRQ (1 << 13) /* RESERVED - FIRQ ? */ +#define CONTROL_AERIE (1 << 14) /* IRQ - AHB timeout error */ +#define CONTROL_IIE (1 << 15) /* IDE IRQ enable */ + +/* Device 1 */ +#define CONTROL_TYP1(x) (((x) & 0x7) << 16) +#define CONTROL_IRE1 (1 << 19) /* Device 1 - enable IORDY for PIO */ +#define CONTROL_RESVD_DW1 (1 << 20) /* Reserved - DW1 ? */ +#define CONTROL_E1 (1 << 21) /* Device 1 - E1: 1: Big Endian */ +#define CONTROL_RESVD_WP1 (1 << 22) /* Reserved - WP1 ? */ +#define CONTROL_RESVD_SE1 (1 << 23) /* Reserved - SE1 ? */ +#define CONTROL_RESVD_ECC1 (1 << 24) /* Reserved - ECC1 ? */ + +#define CONTROL_DRE (1 << 25) /* DMA receive enable */ +#define CONTROL_DTE (1 << 26) /* DMA transmit enable */ +#define CONTRIL_RESVD (1 << 27) +#define CONTROL_TERIE (1 << 28) /* transfer terminate error IRQ */ +#define CONTROL_T (1 << 29) /* terminate current operation */ +#define CONTROL_SRST (1 << 30) /* IDE soft reset */ +#define CONTROL_RST (1 << 31) /* IDE hardware reset */ + +/* IRQ register - 0x0c */ +#define IRQ_RXTHRESH(x) (((x) & 0x3ff) << 0) /* Read FIFO threshold */ +#define IRQ_RFAEIRQ (1 << 10) /* Read FIFO almost full intr req */ +#define IRQ_RFNEIRQ (1 << 11) /* Read FIFO not empty intr req */ +#define IRQ_WFAFIRQ (1 << 12) /* Write FIFO almost empty intr req */ +#define IRQ_WFNFIRQ (1 << 13) /* Write FIFO not full intr req */ +#define IRQ_RESVD_FIRQ (1 << 14) /* Reserved - FIRQ ? */ +#define IRQ_IIRQ (1 << 15) /* IDE device interrupt request */ +#define IRQ_TXTHRESH(x) (((x) & 0x3ff) << 16) /* Write FIFO thershold */ +#define IRQ_TERMERR (1 << 28) /* Transfer termination indication */ +#define IRQ_AHBERR (1 << 29) /* AHB Timeout indication */ + +/* Command Timing Register 0-1: ctrd (0x10, 0x18) */ +#define CT_REG_T1(x) (((x) & 0xff) << 0) /* the setup time of addressed */ +#define CT_REG_T2(x) (((x) & 0xff) << 8) /* the pluse width of DIOR/DIOW */ +#define CT_REG_T4(x) (((x) & 0xff) << 16) /* data hold time */ +#define CT_REG_TEOC(x) (((x) & 0xff) << 24) /* the time to the end of a cycle */ + +/* Data Timing Register 0-1: dtrd (0x14, 0x1c) */ +#define DT_REG_PIO_T1(x) (((x) & 0xff) << 0) /* the setup time of addressed */ +#define DT_REG_PIO_T2(x) (((x) & 0xff) << 8) /* the pluse width of DIOR/DIOW */ +#define DT_REG_PIO_T4(x) (((x) & 0xff) << 16) /* data hold time */ +#define DT_REG_PIO_TEOC(x) (((x) & 0xff) << 24) /* the time to the end of a cycle */ + +#define DT_REG_UDMA_TENV(x) (((x) & 0xf) << 0) /* the envelope time */ +#define DT_REG_UDMA_TMLI(x) (((x) & 0xf) << 4) /* interlock time */ +#define DT_REG_UDMA_TCYC(x) (((x) & 0xff) << 8) /* cycle time - data time */ +#define DT_REG_UDMA_TACK(x) (((x) & 0xf) << 16) /* the setup and hold time of DMACK */ +#define DT_REG_UDMA_TCVS(x) (((x) & 0xf) << 20) /* the setup tim eof CRC */ +#define DT_REG_UDMA_TRP(x) (((x) & 0xff) << 24) /* the time to ready to pause */ + +/* ftide020_s command formats */ +/* read: IDE Register (CF1) */ +#define IDE_REG_OPCODE_READ (1 << 13) /* 0x2000 */ +#define IDE_REG_CS_READ(x) (((x) & 0x3) << 11) +#define IDE_REG_DA_READ(x) (((x) & 0x7) << 8) +#define IDE_REG_CMD_READ(x) 0x0 /* fixed value */ + +/* write: IDE Register (CF2) */ +#define IDE_REG_OPCODE_WRITE (0x5 << 13) /* 0xA000 */ +#define IDE_REG_CS_WRITE(x) (((x) & 0x3) << 11) +#define IDE_REG_DA_WRITE(x) (((x) & 0x7) << 8) +#define IDE_REG_CMD_WRITE(x) (((x) & 0xff) << 0)i /* Actual ATA command or data */ + +/* read/write data: PIO/UDMA (CF3) */ +#define IDE_DATA_WRITE (1 << 15) /* read: 0, write: 1 */ +#define IDE_DATA_OPCODE (0x2 << 13) /* device data access opcode */ +#define IDE_DATA_COUNTER(x) (((x) & 0x1fff) << 0) /* Number of transfers minus 1 */ + +/* set device: (CF4) */ +#define IDE_SET_OPCODE (0x2740 << 2) /* [15:2], 0x9d00 */ +/* CF3 counter value: 0: Tx in bytes, 1: in blocks (each block is 8 bytes) */ +#define IDE_SET_CX8(x) (((x) & 0x1) << 1) +#define IDE_SET_DEV(x) (((x) & 0x1) << 0) /* 0: Master, 1: Slave */ + +/* + * IDE command bit definition + * This section is designed for minor hardware revision compatibility. + */ +#define READ_REG_CMD IDE_REG_OPCODE_READ /* 0x2000 */ +#define WRITE_REG_CMD IDE_REG_OPCODE_WRITE /* 0xA000 */ +#define READ_DATA_CMD IDE_DATA_OPCODE /* 0x4000 */ +#define WRITE_DATA_CMD (IDE_DATA_OPCODE | IDE_DATA_WRITE) /* 0xC000 */ +#define SET_DEV_CMD IDE_SET_OPCODE /* 0x9D00 */ + +#define TATOL_TIMING 3 +#define CMD_TIMING 0 +#define PIO_TIMING 1 +#define DMA_TIMING 2 + +/* Timing Parameters */ +/* Register Access Timing Parameters */ +#define REG_PARAMETER 4 +#define REG_T0 0 +#define REG_T1 1 +#define REG_T2 2 +#define REG_T4 3 + +#define REG_MODE 5 +#define REG_MODE0 0 +#define REG_MODE1 1 +#define REG_MODE2 2 +#define REG_MODE3 3 +#define REG_MODE4 4 + +/* PIO Access Timing Parameters */ +#define PIO_PARAMETER 4 +#define PIO_T0 0 +#define PIO_T1 1 +#define PIO_T2 2 +#define PIO_T4 3 + +#define PIO_MODE 5 +#define PIO_MODE0 0 +#define PIO_MODE1 1 +#define PIO_MODE2 2 +#define PIO_MODE3 3 +#define PIO_MODE4 4 + +/* UDMA Access Timing Parameters */ +#define UDMA_PARAMETER 6 +#define UDMA_TCYC 0 +#define UDMA_TCVS 1 +#define UDMA_TMLI 2 +#define UDMA_TENV 3 +#define UDMA_TRP 4 +#define UDMA_TACK 5 + +#define UDMA_MODE 7 +#define UDMA_MODE0 0 +#define UDMA_MODE1 1 +#define UDMA_MODE2 2 +#define UDMA_MODE3 3 +#define UDMA_MODE4 4 +#define UDMA_MODE5 5 +#define UDMA_MODE6 6 + +/* + * RX_THRESH: + * hardware limitation: max = 8, should support 1,4,8,16,32,64,128,256 + */ +#define RX_THRESH 8 +#define WRITE_FIFO 32 /* Hardwired value */ + +/* Time Table */ +unsigned int REG_ACCESS_TIMING[REG_PARAMETER][REG_MODE] = { + {600, 383, 330, 180, 120}, + {70, 50, 30, 30, 25}, + {290, 290, 290, 80, 70}, + {30, 20, 15, 10, 10}, +}; + +unsigned int PIO_ACCESS_TIMING[PIO_PARAMETER][PIO_MODE] = { + {600, 383, 240, 180, 120}, + {70, 50, 30, 30, 25}, + {165, 125, 100, 80, 70}, + {30, 20, 15, 10, 10}, +}; + +unsigned int UDMA_ACCESS_TIMING[UDMA_PARAMETER][UDMA_MODE] = { + {1120, 730, 540, 390, 250, 168, 130}, /* 10X */ + {700, 480, 310, 200, 67, 100, 100}, /* 10X */ + {200, 200, 200, 200, 200, 200, 200}, /* 10X */ + {200, 200, 200, 200, 200, 200, 200}, /* 10X */ + {1600, 1250, 1000, 1000, 1000, 850, 850}, /* 10X */ + {200, 200, 200, 200, 200, 200, 200}, /* 10X */ +}; + +#endif /* __FTIDE020_H */

Dear Macpaul Lin,
In message 1295873267-32570-2-git-send-email-macpaul@andestech.com you wrote:
Faraday's ftide020_s is an IDE-AHB controller for SoC design. This patch ported the u-boot driver (PIO) of ftide020 ATA (IDE) driver from Linux kernel. IDE commands include read, info, and other functions has been implemented.
When copying code from Linux, you must give exact reference from which file and which exact version (commit ID) the code was taken rom; please see bullet # 4 at http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign
...
+extern ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS];
See before - please move to header file.
...
tcyc = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCYC][mode] * sysclk) + 9990) / 10000);
tcvs = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCVS][mode] * sysclk) + 9990) / 10000);
tmli = (u8) (((UDMA_ACCESS_TIMING[UDMA_TMLI][mode] * sysclk) + 9990) / 10000);
tenv = (u8) (((UDMA_ACCESS_TIMING[UDMA_TENV][mode] * sysclk) + 9990) / 10000);
trp = (u8) (((UDMA_ACCESS_TIMING[UDMA_TRP][mode] * sysclk) + 9990) / 10000);
tack = (u8) (((UDMA_ACCESS_TIMING[UDMA_TACK][mode] * sysclk) + 9990) / 10000);
Lines too long, please fix globally.
...
+/* set device: (CF4) */ +#define IDE_SET_OPCODE (0x2740 << 2) /* [15:2], 0x9d00 */
please, no space before tabs. Please fix globally.
Best regards,
Wolfgang Denk

Dear Macpaul Lin,
In message 1295873267-32570-1-git-send-email-macpaul@andestech.com you wrote:
Although most IDE controller is designed to be connected to PCI bridge, there are still some IDE controller support AHB interface for SoC design.
The driver implementation of these IDE-AHB controllers differ from other IDE-PCI controller, some additional registers and commands access is required during CMD/DATA I/O. Hence a configuration "CONFIG_IDE_AHB" in cmd_ide.c is required to be defined to support these kinds of SoC controllers. Such as Faraday's FTIDE020 series and Global Unichip's UINF-0301.
...
extern void ide_write_register(int, unsigned int, unsigned char);
...
- extern unsigned char ide_read_register(int, unsigned int);
Etc. Please move all such prototype decarations to an appropriate header file and get rid of these "extern"s here.
Thanks.
Best regards,
Wolfgang Denk

Hi Wolfgang,
2011/4/12 Wolfgang Denk wd@denx.de
Dear Macpaul Lin, ...
- extern void ide_write_register(int, unsigned int, unsigned char);
...
- extern unsigned char ide_read_register(int, unsigned int);
Etc. Please move all such prototype decarations to an appropriate header file and get rid of these "extern"s here.
Thanks.
Best regards,
Wolfgang Denk
The patch v2 of this patch set has been send on 2011-04-12 as follows
cmd_ide: enhance new feature "CONFIG_IDE_AHB" http://patchwork.ozlabs.org/patch/90723/
ftide020: add faraday ide ahb controller http://patchwork.ozlabs.org/patch/90724/
Please help on checking if these 2 patch is adaptable.
Sorry for that at the time when I send patch v2, I have no idea about how to send patch with correct "In-reply-to" header.
Thanks.
-- Best regards, Macpaul Lin
participants (3)
-
Macpaul Lin
-
Macpaul Lin
-
Wolfgang Denk