diff options
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/ata-imx31.c')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/ata-imx31.c | 179 |
1 files changed, 98 insertions, 81 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c index 2272b2c929..2c362edbb7 100644 --- a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c | |||
@@ -23,8 +23,82 @@ | |||
23 | #include "system.h" | 23 | #include "system.h" |
24 | #include "power.h" | 24 | #include "power.h" |
25 | #include "panic.h" | 25 | #include "panic.h" |
26 | #include "pcf50606.h" | 26 | #include "ata.h" |
27 | #include "ata-target.h" | 27 | #include "clkctl-imx31.h" |
28 | |||
29 | static const struct ata_pio_timings | ||
30 | { | ||
31 | uint16_t time_2w; /* t2 during write */ | ||
32 | uint16_t time_2r; /* t2 during read */ | ||
33 | uint8_t time_1; /* t1 */ | ||
34 | uint8_t time_pio_rdx; /* trd */ | ||
35 | uint8_t time_4; /* t4 */ | ||
36 | uint8_t time_9; /* t9 */ | ||
37 | } pio_timings[5] = | ||
38 | { | ||
39 | [0] = /* PIO mode 0 */ | ||
40 | { | ||
41 | .time_1 = 70, | ||
42 | .time_2w = 290, | ||
43 | .time_2r = 290, | ||
44 | .time_4 = 30, | ||
45 | .time_9 = 20 | ||
46 | }, | ||
47 | [1] = /* PIO mode 1 */ | ||
48 | { | ||
49 | .time_1 = 50, | ||
50 | .time_2w = 290, | ||
51 | .time_2r = 290, | ||
52 | .time_4 = 20, | ||
53 | .time_9 = 15 | ||
54 | }, | ||
55 | [2] = /* PIO mode 2 */ | ||
56 | { | ||
57 | .time_1 = 30, | ||
58 | .time_2w = 290, | ||
59 | .time_2r = 290, | ||
60 | .time_4 = 15, | ||
61 | .time_9 = 10 | ||
62 | }, | ||
63 | [3] = /* PIO mode 3 */ | ||
64 | { | ||
65 | .time_1 = 30, | ||
66 | .time_2w = 80, | ||
67 | .time_2r = 80, | ||
68 | .time_4 = 10, | ||
69 | .time_9 = 10 | ||
70 | }, | ||
71 | [4] = /* PIO mode 4 */ | ||
72 | { | ||
73 | .time_1 = 25, | ||
74 | .time_2w = 70, | ||
75 | .time_2r = 70, | ||
76 | .time_4 = 10, | ||
77 | .time_9 = 10 | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | /* Setup the timing for PIO mode */ | ||
82 | static void ata_set_pio_mode(int mode) | ||
83 | { | ||
84 | const struct ata_pio_timings * const timings = &pio_timings[mode]; | ||
85 | |||
86 | /* T = period in nanoseconds */ | ||
87 | int T = 1000 * 1000 * 1000 / imx31_clkctl_get_ata_clk(); | ||
88 | |||
89 | while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE)); | ||
90 | |||
91 | ATA_TIME_OFF = 3; | ||
92 | ATA_TIME_ON = 3; | ||
93 | |||
94 | ATA_TIME_1 = (timings->time_1 + T) / T; | ||
95 | ATA_TIME_2W = (timings->time_2w + T) / T; | ||
96 | ATA_TIME_2R = (timings->time_2r + T) / T; | ||
97 | ATA_TIME_AX = (35 + T) / T; /* tA */ | ||
98 | ATA_TIME_PIO_RDX = 1; | ||
99 | ATA_TIME_4 = (timings->time_4 + T) / T; | ||
100 | ATA_TIME_9 = (timings->time_9 + T) / T; | ||
101 | } | ||
28 | 102 | ||
29 | void ata_reset(void) | 103 | void ata_reset(void) |
30 | { | 104 | { |
@@ -47,92 +121,35 @@ bool ata_is_coldstart(void) | |||
47 | return true; | 121 | return true; |
48 | } | 122 | } |
49 | 123 | ||
50 | unsigned long get_pll(bool serial) { | ||
51 | unsigned long mfi, mfn, mfd, pdf, ref_clk; | ||
52 | unsigned long reg = 0, ccmr; | ||
53 | unsigned long long temp; | ||
54 | unsigned int prcs; | ||
55 | |||
56 | ccmr = CLKCTL_CCMR; | ||
57 | prcs = (ccmr & 0x6) >> 1; | ||
58 | if(prcs == 0x1) { | ||
59 | ref_clk = 32768 * 1024; | ||
60 | } else { | ||
61 | ref_clk = 27000000; | ||
62 | } | ||
63 | |||
64 | if(serial) { | ||
65 | reg = CLKCTL_SPCTL; | ||
66 | } else { | ||
67 | if((ccmr & 0x8) == 0) | ||
68 | return ref_clk; | ||
69 | if((ccmr & 0x80) != 0) | ||
70 | return ref_clk; | ||
71 | reg = CLKCTL_MPCTL; | ||
72 | } | ||
73 | pdf = (reg & (0x7 << 26)) >> 26; | ||
74 | mfd = (reg & (0x3FF << 16)) >> 16; | ||
75 | mfi = (reg & (0xF << 10)) >> 10; | ||
76 | mfi = (mfi <= 5) ? 5 : mfi; | ||
77 | mfn = (reg & 0x3FF); | ||
78 | |||
79 | if(mfn < 0x200) { | ||
80 | temp = (unsigned long long)2 *ref_clk * mfn; | ||
81 | temp /= (mfd + 1); | ||
82 | temp = (unsigned long long)2 *ref_clk * mfi + temp; | ||
83 | temp /= (pdf + 1); | ||
84 | } else { | ||
85 | temp = (unsigned long long)2 *ref_clk * (0x400 - mfn); | ||
86 | temp /= (mfd + 1); | ||
87 | temp = (unsigned long long)2 *ref_clk * mfi - temp; | ||
88 | temp /= (pdf + 1); | ||
89 | |||
90 | } | ||
91 | return (unsigned long)temp; | ||
92 | } | ||
93 | |||
94 | unsigned long get_ata_clock(void) { | ||
95 | unsigned long pll, ret_val, hclk, max_pdf, ipg_pdf, mcu_pdf; | ||
96 | |||
97 | max_pdf = (CLKCTL_PDR0 & (0x7 << 3)) >> 3; | ||
98 | ipg_pdf = (CLKCTL_PDR0 & (0x3 << 6)) >> 6; | ||
99 | mcu_pdf = (CLKCTL_PDR0 & 0x7); | ||
100 | if((CLKCTL_PMCR0 & 0xC0000000 ) == 0) { | ||
101 | pll = get_pll(true); | ||
102 | } else { | ||
103 | pll = get_pll(false); | ||
104 | } | ||
105 | hclk = pll/(max_pdf + 1); | ||
106 | ret_val = hclk / (ipg_pdf + 1); | ||
107 | |||
108 | return ret_val; | ||
109 | } | ||
110 | |||
111 | void ata_device_init(void) | 124 | void ata_device_init(void) |
112 | { | 125 | { |
113 | ATA_INTF_CONTROL |= ATA_ATA_RST; /* Make sure we're not in reset mode */ | 126 | ATA_INTF_CONTROL |= ATA_ATA_RST; /* Make sure we're not in reset mode */ |
114 | 127 | ||
115 | while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE)); | 128 | while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE)); |
116 | 129 | ||
117 | /* Setup the timing for PIO mode */ | 130 | /* Setup mode 0 by default */ |
118 | int T = 1000 * 1000 * 1000 / get_ata_clock(); | 131 | ata_set_pio_mode(0); |
119 | ATA_TIME_OFF = 3; | ||
120 | ATA_TIME_ON = 3; | ||
121 | |||
122 | ATA_TIME_1 = (T + 70)/T; | ||
123 | ATA_TIME_2W = (T + 290)/T; | ||
124 | ATA_TIME_2R = (T + 290)/T; | ||
125 | ATA_TIME_AX = (T + 50)/T; | ||
126 | ATA_TIME_PIO_RDX = 1; | ||
127 | ATA_TIME_4 = (T + 30)/T; | ||
128 | ATA_TIME_9 = (T + 20)/T; | ||
129 | } | 132 | } |
130 | 133 | ||
131 | #if 0 | 134 | void ata_identify_ready(void) |
132 | #if !defined(BOOTLOADER) | ||
133 | void copy_write_sectors(const unsigned char* buf, int wordcount) | ||
134 | { | 135 | { |
135 | (void)buf; (void)wordcount; | 136 | const unsigned short* identify_info = ata_get_identify(); |
137 | int mode = 0; | ||
138 | |||
139 | if (identify_info[53] & (1 << 1)) | ||
140 | { | ||
141 | /* Set up advanced timings */ | ||
142 | if (identify_info[64] & (1 << 1)) | ||
143 | mode = 4; /* Mode 0, 1, 2, 3, 4 */ | ||
144 | else if (identify_info[64] & (1 << 0)) | ||
145 | mode = 3; /* Mode 0, 1, 2, 3 */ | ||
146 | else | ||
147 | mode = 2; /* Mode 0, 1, 2 */ | ||
148 | } | ||
149 | |||
150 | /* If mode changed, actually set the timings */ | ||
151 | if (mode != 0) | ||
152 | { | ||
153 | ata_set_pio_mode(mode); | ||
154 | } | ||
136 | } | 155 | } |
137 | #endif | ||
138 | #endif | ||