diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-05-05 10:53:06 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-05-05 10:53:06 +0000 |
commit | be0c7d0ff306a9e95aaa89ec4943b3739d4b0434 (patch) | |
tree | 899e944950961862112dda4b073a6274207fbe6f /firmware/target | |
parent | 367aec35d714e4b3f87184ea718538c1b5800462 (diff) | |
download | rockbox-be0c7d0ff306a9e95aaa89ec4943b3739d4b0434.tar.gz rockbox-be0c7d0ff306a9e95aaa89ec4943b3739d4b0434.zip |
Gigabeat S: Use the fastest PIO mode the installed drive allows instead of always PIO0. Centralize clock information in clkctl-imx31.c.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@17371 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/imx31/debug-imx31.c | 35 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/ata-imx31.c | 179 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/ata-target.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c | 40 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h | 23 |
5 files changed, 169 insertions, 111 deletions
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c index 9fe2eae584..614a703836 100644 --- a/firmware/target/arm/imx31/debug-imx31.c +++ b/firmware/target/arm/imx31/debug-imx31.c | |||
@@ -26,32 +26,7 @@ | |||
26 | #include "debug-target.h" | 26 | #include "debug-target.h" |
27 | #include "mc13783.h" | 27 | #include "mc13783.h" |
28 | #include "adc.h" | 28 | #include "adc.h" |
29 | 29 | #include "clkctl-imx31.h" | |
30 | #define CONFIG_CLK32_FREQ 32768 | ||
31 | #define CONFIG_HCLK_FREQ 27000000 | ||
32 | |||
33 | /* Return PLL frequency in HZ */ | ||
34 | static unsigned int decode_pll(unsigned int reg, | ||
35 | unsigned int infreq) | ||
36 | { | ||
37 | uint64_t mfi = (reg >> 10) & 0xf; | ||
38 | uint64_t mfn = reg & 0x3ff; | ||
39 | uint64_t mfd = ((reg >> 16) & 0x3ff) + 1; | ||
40 | uint64_t pd = ((reg >> 26) & 0xf) + 1; | ||
41 | |||
42 | mfi = mfi <= 5 ? 5 : mfi; | ||
43 | |||
44 | return 2*infreq*(mfi * mfd + mfn) / (mfd * pd); | ||
45 | } | ||
46 | |||
47 | /* Get the PLL reference clock frequency */ | ||
48 | static unsigned int get_pll_ref_clk_freq(void) | ||
49 | { | ||
50 | if ((CLKCTL_CCMR & (3 << 1)) == (1 << 1)) | ||
51 | return CONFIG_CLK32_FREQ * 1024; | ||
52 | else | ||
53 | return CONFIG_HCLK_FREQ; | ||
54 | } | ||
55 | 30 | ||
56 | bool __dbg_hw_info(void) | 31 | bool __dbg_hw_info(void) |
57 | { | 32 | { |
@@ -74,11 +49,11 @@ bool __dbg_hw_info(void) | |||
74 | spctl = CLKCTL_SPCTL; | 49 | spctl = CLKCTL_SPCTL; |
75 | upctl = CLKCTL_UPCTL; | 50 | upctl = CLKCTL_UPCTL; |
76 | 51 | ||
77 | pllref = get_pll_ref_clk_freq(); | 52 | pllref = imx31_clkctl_get_pll_ref_clk(); |
78 | 53 | ||
79 | mcu_pllfreq = decode_pll(mpctl, pllref); | 54 | mcu_pllfreq = imx31_clkctl_get_pll(PLL_MCU); |
80 | ser_pllfreq = decode_pll(spctl, pllref); | 55 | ser_pllfreq = imx31_clkctl_get_pll(PLL_SERIAL); |
81 | usb_pllfreq = decode_pll(upctl, pllref); | 56 | usb_pllfreq = imx31_clkctl_get_pll(PLL_USB); |
82 | 57 | ||
83 | snprintf(buf, sizeof (buf), "pll_ref_clk: %u", pllref); | 58 | snprintf(buf, sizeof (buf), "pll_ref_clk: %u", pllref); |
84 | lcd_puts(0, line++, buf); line++; | 59 | lcd_puts(0, line++, buf); line++; |
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 | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h index a1720644fe..7b61039c7e 100644 --- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/ata-target.h | |||
@@ -68,4 +68,7 @@ void ata_reset(void); | |||
68 | void ata_device_init(void); | 68 | void ata_device_init(void); |
69 | bool ata_is_coldstart(void); | 69 | bool ata_is_coldstart(void); |
70 | 70 | ||
71 | #define ATA_NOTIFY_IDENTIFY_READY | ||
72 | void ata_identify_ready(void); | ||
73 | |||
71 | #endif | 74 | #endif |
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c index a01fab07d0..2dc6e817de 100644 --- a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c | |||
@@ -43,3 +43,43 @@ void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg, | |||
43 | 43 | ||
44 | restore_interrupt(oldlevel); | 44 | restore_interrupt(oldlevel); |
45 | } | 45 | } |
46 | |||
47 | /* Get the PLL reference clock frequency in HZ */ | ||
48 | unsigned int imx31_clkctl_get_pll_ref_clk(void) | ||
49 | { | ||
50 | if ((CLKCTL_CCMR & (3 << 1)) == (1 << 1)) | ||
51 | return CONFIG_CLK32_FREQ * 1024; | ||
52 | else | ||
53 | return CONFIG_HCLK_FREQ; | ||
54 | } | ||
55 | |||
56 | /* Return PLL frequency in HZ */ | ||
57 | unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll) | ||
58 | { | ||
59 | uint32_t infreq = imx31_clkctl_get_pll_ref_clk(); | ||
60 | uint32_t reg = (&CLKCTL_MPCTL)[pll]; | ||
61 | uint32_t mfn = reg & 0x3ff; | ||
62 | uint32_t pd = ((reg >> 26) & 0xf) + 1; | ||
63 | uint64_t mfd = ((reg >> 16) & 0x3ff) + 1; | ||
64 | uint32_t mfi = (reg >> 10) & 0xf; | ||
65 | |||
66 | mfi = mfi <= 5 ? 5 : mfi; | ||
67 | |||
68 | return 2*infreq*(mfi * mfd + mfn) / (mfd * pd); | ||
69 | } | ||
70 | |||
71 | unsigned int imx31_clkctl_get_ipg_clk(void) | ||
72 | { | ||
73 | unsigned int pll = imx31_clkctl_get_pll((CLKCTL_PMCR0 & 0xC0000000) == 0 ? | ||
74 | PLL_SERIAL : PLL_MCU); | ||
75 | uint32_t reg = CLKCTL_PDR0; | ||
76 | unsigned int max_pdf = ((reg >> 3) & 0x7) + 1; | ||
77 | unsigned int ipg_pdf = ((reg >> 6) & 0x3) + 1; | ||
78 | |||
79 | return pll / (max_pdf * ipg_pdf); | ||
80 | } | ||
81 | |||
82 | unsigned int imx31_clkctl_get_ata_clk(void) | ||
83 | { | ||
84 | return imx31_clkctl_get_ipg_clk(); | ||
85 | } | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h index da15ef2706..37d01efde8 100644 --- a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h +++ b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h | |||
@@ -83,4 +83,27 @@ enum IMX31_CG_MODES | |||
83 | void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg, | 83 | void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg, |
84 | enum IMX31_CG_MODES mode); | 84 | enum IMX31_CG_MODES mode); |
85 | 85 | ||
86 | enum IMX31_PLLS | ||
87 | { | ||
88 | PLL_MCU = 0, | ||
89 | PLL_USB, | ||
90 | PLL_SERIAL, | ||
91 | NUM_PLLS, | ||
92 | }; | ||
93 | |||
94 | #define CONFIG_CLK32_FREQ 32768 | ||
95 | #define CONFIG_HCLK_FREQ 27000000 | ||
96 | |||
97 | /* Get the PLL reference clock frequency in HZ */ | ||
98 | unsigned int imx31_clkctl_get_pll_ref_clk(void); | ||
99 | |||
100 | /* Return PLL frequency in HZ */ | ||
101 | unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll); | ||
102 | |||
103 | /* Return ipg_clk in HZ */ | ||
104 | unsigned int imx31_clkctl_get_ipg_clk(void); | ||
105 | |||
106 | /* Return the ATA frequency in HZ */ | ||
107 | unsigned int imx31_clkctl_get_ata_clk(void); | ||
108 | |||
86 | #endif /* _CLKCTL_IMX31_H_ */ | 109 | #endif /* _CLKCTL_IMX31_H_ */ |