summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/ata-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-imx31.c179
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
29static 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 */
82static 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
29void ata_reset(void) 103void ata_reset(void)
30{ 104{
@@ -47,92 +121,35 @@ bool ata_is_coldstart(void)
47 return true; 121 return true;
48} 122}
49 123
50unsigned 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
94unsigned 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
111void ata_device_init(void) 124void 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 134void ata_identify_ready(void)
132#if !defined(BOOTLOADER)
133void 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