summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 16:39:11 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2013-06-18 16:41:13 +0200
commit0b6198f8a859700e3816254222e31466014ea553 (patch)
tree5b7cd61707943f0b4146881cfacf37451b65c8c3
parentbbb789120ce4c2eb470233920e602e5f79c62430 (diff)
downloadrockbox-0b6198f8a859700e3816254222e31466014ea553.tar.gz
rockbox-0b6198f8a859700e3816254222e31466014ea553.zip
imx233: add basic ATA driver
The current driver only works in PIO mode. Change-Id: I1cf2eaedcce0172a254c3bab0e1257886226d3a0
-rw-r--r--firmware/SOURCES3
-rw-r--r--firmware/target/arm/imx233/ata-imx233.c232
-rw-r--r--firmware/target/arm/imx233/ata-target.h78
3 files changed, 313 insertions, 0 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 83389482f3..40e0f36773 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -521,6 +521,9 @@ target/arm/imx233/kernel-imx233.c
521# if (CONFIG_STORAGE & (STORAGE_SD | STORAGE_MMC)) 521# if (CONFIG_STORAGE & (STORAGE_SD | STORAGE_MMC))
522target/arm/imx233/sdmmc-imx233.c 522target/arm/imx233/sdmmc-imx233.c
523# endif 523# endif
524# if (CONFIG_STORAGE & (STORAGE_ATA))
525target/arm/imx233/ata-imx233.c
526# endif
524target/arm/imx233/partitions-imx233.c 527target/arm/imx233/partitions-imx233.c
525target/arm/imx233/ssp-imx233.c 528target/arm/imx233/ssp-imx233.c
526target/arm/imx233/dma-imx233.c 529target/arm/imx233/dma-imx233.c
diff --git a/firmware/target/arm/imx233/ata-imx233.c b/firmware/target/arm/imx233/ata-imx233.c
new file mode 100644
index 0000000000..da546ab2a1
--- /dev/null
+++ b/firmware/target/arm/imx233/ata-imx233.c
@@ -0,0 +1,232 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef ATA_IMX233_H
22#define ATA_IMX233_H
23
24#include "config.h"
25#include "system.h"
26#include "pinctrl-imx233.h"
27#include "clkctrl-imx233.h"
28#include "ata-target.h"
29#include "ata-defines.h"
30
31#include "regs/regs-gpmi.h"
32
33struct pio_timing_t
34{
35 /** all values are in ns */
36 int addr_setup; /* "Address valid to DIOR-/DIOW-setup" */
37 int data_hold; /* "DIOR-/DIOW-recovery time" */
38 int data_setup; /* "DIOR-/DIOW-" */
39};
40
41static struct pio_timing_t pio_timing[] =
42{
43 /* FIXME: OF uses 290, 290, 290, 80, 70 for data_setup */
44 {70, 100, 165},
45 {50, 100, 125},
46 {30, 100, 100},
47 {30, 70, 80},
48 {25, 25, 70},
49};
50
51static void imx233_ata_wait_ready(void)
52{
53 while(BF_RD(GPMI_CTRL0, RUN))
54 yield();
55}
56
57static uint16_t imx233_ata_read_reg(unsigned reg)
58{
59 /* wait ready */
60 imx233_ata_wait_ready();
61
62 /* setup command */
63 HW_GPMI_CTRL0 = BF_OR6(GPMI_CTRL0, RUN(1),
64 COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ),
65 WORD_LENGTH(BV_GPMI_CTRL0_WORD_LENGTH__16_BIT),
66 CS(IMX233_ATA_REG_CS(reg)), ADDRESS(IMX233_ATA_REG_ADDR(reg)),
67 XFER_COUNT(1));
68
69 /* wait for completion */
70 while(BF_RD(GPMI_STAT, FIFO_EMPTY));
71
72 /* get data */
73 return HW_GPMI_DATA & 0xffff;
74}
75
76static void imx233_ata_write_reg(unsigned reg, uint16_t data)
77{
78 /* wait ready */
79 imx233_ata_wait_ready();
80
81 /* setup command */
82 HW_GPMI_CTRL0 = BF_OR6(GPMI_CTRL0, RUN(1),
83 COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE),
84 WORD_LENGTH(BV_GPMI_CTRL0_WORD_LENGTH__16_BIT),
85 CS(IMX233_ATA_REG_CS(reg)), ADDRESS(IMX233_ATA_REG_ADDR(reg)),
86 XFER_COUNT(1));
87
88 /* send data */
89 HW_GPMI_DATA = data;
90}
91
92uint8_t imx233_ata_inb(unsigned reg)
93{
94 return imx233_ata_read_reg(reg) & 0xff;
95}
96
97uint16_t imx233_ata_inw(unsigned reg)
98{
99 return imx233_ata_read_reg(reg);
100}
101
102void imx233_ata_outb(unsigned reg, uint8_t v)
103{
104 imx233_ata_write_reg(reg, v);
105}
106
107void imx233_ata_outw(unsigned reg, uint16_t v)
108{
109 imx233_ata_write_reg(reg, v);
110}
111
112void ata_set_pio_timings(int mode)
113{
114 /* load timing */
115 struct pio_timing_t t = pio_timing[mode > 3 ? 3 : mode];
116 /* adjust to the clock */
117 unsigned clock_freq = 80 * 1000;
118#define adjust_to_clock(val) \
119 val = (val * clock_freq) / 1000 / 1000
120
121 adjust_to_clock(t.addr_setup);
122 adjust_to_clock(t.data_hold);
123 adjust_to_clock(t.data_setup);
124 /* write */
125 imx233_ata_wait_ready();
126 HW_GPMI_TIMING0 = BF_OR3(GPMI_TIMING0, ADDRESS_SETUP(t.addr_setup),
127 DATA_HOLD(t.data_hold), DATA_SETUP(t.data_setup));
128}
129
130void ata_reset(void)
131{
132 /* reset device */
133 BF_WR_V(GPMI_CTRL1, DEV_RESET, ENABLED);
134 sleep(HZ / 10);
135 BF_WR_V(GPMI_CTRL1, DEV_RESET, DISABLED);
136}
137
138void ata_enable(bool on)
139{
140}
141
142bool ata_is_coldstart(void)
143{
144 return false;
145}
146
147#ifdef HAVE_ATA_DMA
148void ata_dma_set_mode(unsigned char mode);
149bool ata_dma_setup(void *addr, unsigned long bytes, bool write);
150bool ata_dma_finish(void);
151#endif
152
153static int ata_wait_status(unsigned status, unsigned mask, int timeout)
154{
155 long end_tick = current_tick + timeout;
156
157 while(TIME_BEFORE(current_tick, end_tick))
158 {
159 if((ATA_IN8(ATA_STATUS) & mask) == status)
160 return 1;
161 sleep(0);
162 }
163
164 return 0;
165}
166
167int ata_wait_for_bsy(void)
168{
169 /* BSY = 0 */
170 return ata_wait_status(0, STATUS_BSY, HZ);
171}
172
173int ata_wait_for_rdy(void)
174{
175 /* RDY = 1 && BSY = 0 */
176 return ata_wait_status(STATUS_RDY, STATUS_RDY | STATUS_BSY, HZ);
177}
178
179void ata_device_init(void)
180{
181 /* reset block */
182 imx233_reset_block(&HW_GPMI_CTRL0);
183 /* setup pins */
184 imx233_pinctrl_setup_vpin(VPIN_GPMI_D0, "ata d0", PINCTRL_DRIVE_4mA, false);
185 imx233_pinctrl_setup_vpin(VPIN_GPMI_D1, "ata d1", PINCTRL_DRIVE_4mA, false);
186 imx233_pinctrl_setup_vpin(VPIN_GPMI_D2, "ata d2", PINCTRL_DRIVE_4mA, false);
187 imx233_pinctrl_setup_vpin(VPIN_GPMI_D3, "ata d3", PINCTRL_DRIVE_4mA, false);
188 imx233_pinctrl_setup_vpin(VPIN_GPMI_D4, "ata d4", PINCTRL_DRIVE_4mA, false);
189 imx233_pinctrl_setup_vpin(VPIN_GPMI_D5, "ata d5", PINCTRL_DRIVE_4mA, false);
190 imx233_pinctrl_setup_vpin(VPIN_GPMI_D6, "ata d6", PINCTRL_DRIVE_4mA, false);
191 imx233_pinctrl_setup_vpin(VPIN_GPMI_D7, "ata d7", PINCTRL_DRIVE_4mA, false);
192 imx233_pinctrl_setup_vpin(VPIN_GPMI_D8, "ata d8", PINCTRL_DRIVE_4mA, false);
193 imx233_pinctrl_setup_vpin(VPIN_GPMI_D9, "ata d9", PINCTRL_DRIVE_4mA, false);
194 imx233_pinctrl_setup_vpin(VPIN_GPMI_D10, "ata d10", PINCTRL_DRIVE_4mA, false);
195 imx233_pinctrl_setup_vpin(VPIN_GPMI_D11, "ata d11", PINCTRL_DRIVE_4mA, false);
196 imx233_pinctrl_setup_vpin(VPIN_GPMI_D12, "ata d12", PINCTRL_DRIVE_4mA, false);
197 imx233_pinctrl_setup_vpin(VPIN_GPMI_D13, "ata d13", PINCTRL_DRIVE_4mA, false);
198 imx233_pinctrl_setup_vpin(VPIN_GPMI_D14, "ata d14", PINCTRL_DRIVE_4mA, false);
199 imx233_pinctrl_setup_vpin(VPIN_GPMI_D15, "ata d15", PINCTRL_DRIVE_4mA, false);
200 imx233_pinctrl_setup_vpin(VPIN_GPMI_D15, "ata d15", PINCTRL_DRIVE_4mA, false);
201 imx233_pinctrl_setup_vpin(VPIN_GPMI_CE0n, "ata cs0", PINCTRL_DRIVE_4mA, false);
202 imx233_pinctrl_setup_vpin(VPIN_GPMI_CE1n, "ata cs1", PINCTRL_DRIVE_4mA, false);
203 imx233_pinctrl_setup_vpin(VPIN_GPMI_A0, "ata a0", PINCTRL_DRIVE_4mA, false);
204 imx233_pinctrl_setup_vpin(VPIN_GPMI_A1, "ata a1", PINCTRL_DRIVE_4mA, false);
205 imx233_pinctrl_setup_vpin(VPIN_GPMI_A2, "ata a2", PINCTRL_DRIVE_4mA, false);
206 imx233_pinctrl_setup_vpin(VPIN_GPMI_IRQ, "ata irq", PINCTRL_DRIVE_4mA, false);
207 imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY, "ata rdy", PINCTRL_DRIVE_4mA, false);
208#ifdef HAVE_ATA_DMA
209 imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY2, "ata dmack", PINCTRL_DRIVE_4mA, false);
210 imx233_pinctrl_setup_vpin(VPIN_GPMI_RDY3, "ata dmarq", PINCTRL_DRIVE_4mA, false);
211#endif
212 imx233_pinctrl_setup_vpin(VPIN_GPMI_RDn, "ata rd", PINCTRL_DRIVE_4mA, false);
213 imx233_pinctrl_setup_vpin(VPIN_GPMI_WRn, "ata wr", PINCTRL_DRIVE_4mA, false);
214 /* setup ata mode */
215 BF_WR_V(GPMI_CTRL1, GPMI_MODE, ATA);
216 /* reset device */
217 ata_reset();
218 ata_enable(true);
219
220 /* setup mode 0 for all until identification */
221 ata_set_pio_timings(0);
222
223#ifdef HAVE_ATA_DMA
224 ata_set_mdma_timings(0);
225 ata_set_udma_timings(0);
226#endif
227}
228
229#endif /* ATA_IMX233_H */
230
231
232
diff --git a/firmware/target/arm/imx233/ata-target.h b/firmware/target/arm/imx233/ata-target.h
new file mode 100644
index 0000000000..a95ea03247
--- /dev/null
+++ b/firmware/target/arm/imx233/ata-target.h
@@ -0,0 +1,78 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2013 Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef ATA_TARGET_H
22#define ATA_TARGET_H
23
24#include "config.h"
25
26#ifdef BOOTLOADER
27#define ATA_DRIVER_CLOSE
28#endif
29
30#ifdef HAVE_ATA_DMA
31/* FIXME does this chips does MWDMA ? */
32#define ATA_MAX_MWDMA 2
33#define ATA_MAX_UDMA 4
34#endif
35
36uint8_t imx233_ata_inb(unsigned reg);
37uint16_t imx233_ata_inw(unsigned reg);
38void imx233_ata_outb(unsigned reg, uint8_t v);
39void imx233_ata_outw(unsigned reg, uint16_t v);
40
41#define IMX233_ATA_REG(cs,addr) ((cs) << 3 | (addr))
42#define IMX233_ATA_REG_CS(reg) ((reg) >> 3)
43#define IMX233_ATA_REG_ADDR(reg) ((reg) & 0x7)
44/* use register address (see ATA spec) */
45#define ATA_DATA IMX233_ATA_REG(0, 0)
46#define ATA_ERROR IMX233_ATA_REG(0, 1)
47#define ATA_NSECTOR IMX233_ATA_REG(0, 2)
48#define ATA_SECTOR IMX233_ATA_REG(0, 3)
49#define ATA_LCYL IMX233_ATA_REG(0, 4)
50#define ATA_HCYL IMX233_ATA_REG(0, 5)
51#define ATA_SELECT IMX233_ATA_REG(0, 6)
52#define ATA_COMMAND IMX233_ATA_REG(0, 7)
53#define ATA_CONTROL IMX233_ATA_REG(1, 6)
54
55/* keep consistent with definition of IMX233_ATA_REG */
56#define ATA_OUT8(reg, data) imx233_ata_outb(reg, data)
57#define ATA_OUT16(reg, data) imx233_ata_outw(reg, data)
58#define ATA_IN8(reg) imx233_ata_inb(reg)
59#define ATA_IN16(reg) imx233_ata_inw(reg)
60
61#define ATA_SET_PIO_TIMING
62
63#define ATA_TARGET_POLLING
64
65void ata_set_pio_timings(int mode);
66void ata_reset(void);
67void ata_enable(bool on);
68bool ata_is_coldstart(void);
69#ifdef HAVE_ATA_DMA
70void ata_dma_set_mode(unsigned char mode);
71bool ata_dma_setup(void *addr, unsigned long bytes, bool write);
72bool ata_dma_finish(void);
73#endif
74int ata_wait_for_bsy(void);
75int ata_wait_for_rdy(void);
76void ata_device_init(void);
77
78#endif /* ATA_TARGET_H */