diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-18 16:39:11 +0200 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-06-18 16:41:13 +0200 |
commit | 0b6198f8a859700e3816254222e31466014ea553 (patch) | |
tree | 5b7cd61707943f0b4146881cfacf37451b65c8c3 | |
parent | bbb789120ce4c2eb470233920e602e5f79c62430 (diff) | |
download | rockbox-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/SOURCES | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/ata-imx233.c | 232 | ||||
-rw-r--r-- | firmware/target/arm/imx233/ata-target.h | 78 |
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)) |
522 | target/arm/imx233/sdmmc-imx233.c | 522 | target/arm/imx233/sdmmc-imx233.c |
523 | # endif | 523 | # endif |
524 | # if (CONFIG_STORAGE & (STORAGE_ATA)) | ||
525 | target/arm/imx233/ata-imx233.c | ||
526 | # endif | ||
524 | target/arm/imx233/partitions-imx233.c | 527 | target/arm/imx233/partitions-imx233.c |
525 | target/arm/imx233/ssp-imx233.c | 528 | target/arm/imx233/ssp-imx233.c |
526 | target/arm/imx233/dma-imx233.c | 529 | target/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 | |||
33 | struct 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 | |||
41 | static 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 | |||
51 | static void imx233_ata_wait_ready(void) | ||
52 | { | ||
53 | while(BF_RD(GPMI_CTRL0, RUN)) | ||
54 | yield(); | ||
55 | } | ||
56 | |||
57 | static 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 | |||
76 | static 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 | |||
92 | uint8_t imx233_ata_inb(unsigned reg) | ||
93 | { | ||
94 | return imx233_ata_read_reg(reg) & 0xff; | ||
95 | } | ||
96 | |||
97 | uint16_t imx233_ata_inw(unsigned reg) | ||
98 | { | ||
99 | return imx233_ata_read_reg(reg); | ||
100 | } | ||
101 | |||
102 | void imx233_ata_outb(unsigned reg, uint8_t v) | ||
103 | { | ||
104 | imx233_ata_write_reg(reg, v); | ||
105 | } | ||
106 | |||
107 | void imx233_ata_outw(unsigned reg, uint16_t v) | ||
108 | { | ||
109 | imx233_ata_write_reg(reg, v); | ||
110 | } | ||
111 | |||
112 | void 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 | |||
130 | void 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 | |||
138 | void ata_enable(bool on) | ||
139 | { | ||
140 | } | ||
141 | |||
142 | bool ata_is_coldstart(void) | ||
143 | { | ||
144 | return false; | ||
145 | } | ||
146 | |||
147 | #ifdef HAVE_ATA_DMA | ||
148 | void ata_dma_set_mode(unsigned char mode); | ||
149 | bool ata_dma_setup(void *addr, unsigned long bytes, bool write); | ||
150 | bool ata_dma_finish(void); | ||
151 | #endif | ||
152 | |||
153 | static 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 | |||
167 | int ata_wait_for_bsy(void) | ||
168 | { | ||
169 | /* BSY = 0 */ | ||
170 | return ata_wait_status(0, STATUS_BSY, HZ); | ||
171 | } | ||
172 | |||
173 | int 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 | |||
179 | void 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 | |||
36 | uint8_t imx233_ata_inb(unsigned reg); | ||
37 | uint16_t imx233_ata_inw(unsigned reg); | ||
38 | void imx233_ata_outb(unsigned reg, uint8_t v); | ||
39 | void 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 | |||
65 | void ata_set_pio_timings(int mode); | ||
66 | void ata_reset(void); | ||
67 | void ata_enable(bool on); | ||
68 | bool ata_is_coldstart(void); | ||
69 | #ifdef HAVE_ATA_DMA | ||
70 | void ata_dma_set_mode(unsigned char mode); | ||
71 | bool ata_dma_setup(void *addr, unsigned long bytes, bool write); | ||
72 | bool ata_dma_finish(void); | ||
73 | #endif | ||
74 | int ata_wait_for_bsy(void); | ||
75 | int ata_wait_for_rdy(void); | ||
76 | void ata_device_init(void); | ||
77 | |||
78 | #endif /* ATA_TARGET_H */ | ||