summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-05-05 10:53:06 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-05-05 10:53:06 +0000
commitbe0c7d0ff306a9e95aaa89ec4943b3739d4b0434 (patch)
tree899e944950961862112dda4b073a6274207fbe6f
parent367aec35d714e4b3f87184ea718538c1b5800462 (diff)
downloadrockbox-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
-rw-r--r--firmware/drivers/ata.c4
-rw-r--r--firmware/target/arm/imx31/debug-imx31.c35
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-imx31.c179
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-target.h3
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c40
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h23
6 files changed, 173 insertions, 111 deletions
diff --git a/firmware/drivers/ata.c b/firmware/drivers/ata.c
index 25eac26e99..e949f38a9d 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -1089,6 +1089,10 @@ static int identify(void)
1089 identify_info[i] = ATA_DATA; 1089 identify_info[i] = ATA_DATA;
1090#endif 1090#endif
1091 } 1091 }
1092
1093#ifdef ATA_NOTIFY_IDENTIFY_READY
1094 ata_identify_ready();
1095#endif
1092 1096
1093 return 0; 1097 return 0;
1094} 1098}
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 */
34static 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 */
48static 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
56bool __dbg_hw_info(void) 31bool __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
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
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);
68void ata_device_init(void); 68void ata_device_init(void);
69bool ata_is_coldstart(void); 69bool ata_is_coldstart(void);
70 70
71#define ATA_NOTIFY_IDENTIFY_READY
72void 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 */
48unsigned 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 */
57unsigned 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
71unsigned 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
82unsigned 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
83void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg, 83void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg,
84 enum IMX31_CG_MODES mode); 84 enum IMX31_CG_MODES mode);
85 85
86enum 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 */
98unsigned int imx31_clkctl_get_pll_ref_clk(void);
99
100/* Return PLL frequency in HZ */
101unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll);
102
103/* Return ipg_clk in HZ */
104unsigned int imx31_clkctl_get_ipg_clk(void);
105
106/* Return the ATA frequency in HZ */
107unsigned int imx31_clkctl_get_ata_clk(void);
108
86#endif /* _CLKCTL_IMX31_H_ */ 109#endif /* _CLKCTL_IMX31_H_ */