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.zip
rockbox-be0c7d0ff306a9e95aaa89ec4943b3739d4b0434.tar.gz
rockbox-be0c7d0ff306a9e95aaa89ec4943b3739d4b0434.tar.bz2
rockbox-be0c7d0ff306a9e95aaa89ec4943b3739d4b0434.tar.xz
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 25eac26..e949f38 100644
--- a/firmware/drivers/ata.c
+++ b/firmware/drivers/ata.c
@@ -1089,6 +1089,10 @@ static int identify(void)
identify_info[i] = ATA_DATA;
#endif
}
+
+#ifdef ATA_NOTIFY_IDENTIFY_READY
+ ata_identify_ready();
+#endif
return 0;
}
diff --git a/firmware/target/arm/imx31/debug-imx31.c b/firmware/target/arm/imx31/debug-imx31.c
index 9fe2eae..614a703 100644
--- a/firmware/target/arm/imx31/debug-imx31.c
+++ b/firmware/target/arm/imx31/debug-imx31.c
@@ -26,32 +26,7 @@
#include "debug-target.h"
#include "mc13783.h"
#include "adc.h"
-
-#define CONFIG_CLK32_FREQ 32768
-#define CONFIG_HCLK_FREQ 27000000
-
-/* Return PLL frequency in HZ */
-static unsigned int decode_pll(unsigned int reg,
- unsigned int infreq)
-{
- uint64_t mfi = (reg >> 10) & 0xf;
- uint64_t mfn = reg & 0x3ff;
- uint64_t mfd = ((reg >> 16) & 0x3ff) + 1;
- uint64_t pd = ((reg >> 26) & 0xf) + 1;
-
- mfi = mfi <= 5 ? 5 : mfi;
-
- return 2*infreq*(mfi * mfd + mfn) / (mfd * pd);
-}
-
-/* Get the PLL reference clock frequency */
-static unsigned int get_pll_ref_clk_freq(void)
-{
- if ((CLKCTL_CCMR & (3 << 1)) == (1 << 1))
- return CONFIG_CLK32_FREQ * 1024;
- else
- return CONFIG_HCLK_FREQ;
-}
+#include "clkctl-imx31.h"
bool __dbg_hw_info(void)
{
@@ -74,11 +49,11 @@ bool __dbg_hw_info(void)
spctl = CLKCTL_SPCTL;
upctl = CLKCTL_UPCTL;
- pllref = get_pll_ref_clk_freq();
+ pllref = imx31_clkctl_get_pll_ref_clk();
- mcu_pllfreq = decode_pll(mpctl, pllref);
- ser_pllfreq = decode_pll(spctl, pllref);
- usb_pllfreq = decode_pll(upctl, pllref);
+ mcu_pllfreq = imx31_clkctl_get_pll(PLL_MCU);
+ ser_pllfreq = imx31_clkctl_get_pll(PLL_SERIAL);
+ usb_pllfreq = imx31_clkctl_get_pll(PLL_USB);
snprintf(buf, sizeof (buf), "pll_ref_clk: %u", pllref);
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 2272b2c..2c362ed 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 @@
#include "system.h"
#include "power.h"
#include "panic.h"
-#include "pcf50606.h"
-#include "ata-target.h"
+#include "ata.h"
+#include "clkctl-imx31.h"
+
+static const struct ata_pio_timings
+{
+ uint16_t time_2w; /* t2 during write */
+ uint16_t time_2r; /* t2 during read */
+ uint8_t time_1; /* t1 */
+ uint8_t time_pio_rdx; /* trd */
+ uint8_t time_4; /* t4 */
+ uint8_t time_9; /* t9 */
+} pio_timings[5] =
+{
+ [0] = /* PIO mode 0 */
+ {
+ .time_1 = 70,
+ .time_2w = 290,
+ .time_2r = 290,
+ .time_4 = 30,
+ .time_9 = 20
+ },
+ [1] = /* PIO mode 1 */
+ {
+ .time_1 = 50,
+ .time_2w = 290,
+ .time_2r = 290,
+ .time_4 = 20,
+ .time_9 = 15
+ },
+ [2] = /* PIO mode 2 */
+ {
+ .time_1 = 30,
+ .time_2w = 290,
+ .time_2r = 290,
+ .time_4 = 15,
+ .time_9 = 10
+ },
+ [3] = /* PIO mode 3 */
+ {
+ .time_1 = 30,
+ .time_2w = 80,
+ .time_2r = 80,
+ .time_4 = 10,
+ .time_9 = 10
+ },
+ [4] = /* PIO mode 4 */
+ {
+ .time_1 = 25,
+ .time_2w = 70,
+ .time_2r = 70,
+ .time_4 = 10,
+ .time_9 = 10
+ },
+};
+
+/* Setup the timing for PIO mode */
+static void ata_set_pio_mode(int mode)
+{
+ const struct ata_pio_timings * const timings = &pio_timings[mode];
+
+ /* T = period in nanoseconds */
+ int T = 1000 * 1000 * 1000 / imx31_clkctl_get_ata_clk();
+
+ while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
+
+ ATA_TIME_OFF = 3;
+ ATA_TIME_ON = 3;
+
+ ATA_TIME_1 = (timings->time_1 + T) / T;
+ ATA_TIME_2W = (timings->time_2w + T) / T;
+ ATA_TIME_2R = (timings->time_2r + T) / T;
+ ATA_TIME_AX = (35 + T) / T; /* tA */
+ ATA_TIME_PIO_RDX = 1;
+ ATA_TIME_4 = (timings->time_4 + T) / T;
+ ATA_TIME_9 = (timings->time_9 + T) / T;
+}
void ata_reset(void)
{
@@ -47,92 +121,35 @@ bool ata_is_coldstart(void)
return true;
}
-unsigned long get_pll(bool serial) {
- unsigned long mfi, mfn, mfd, pdf, ref_clk;
- unsigned long reg = 0, ccmr;
- unsigned long long temp;
- unsigned int prcs;
-
- ccmr = CLKCTL_CCMR;
- prcs = (ccmr & 0x6) >> 1;
- if(prcs == 0x1) {
- ref_clk = 32768 * 1024;
- } else {
- ref_clk = 27000000;
- }
-
- if(serial) {
- reg = CLKCTL_SPCTL;
- } else {
- if((ccmr & 0x8) == 0)
- return ref_clk;
- if((ccmr & 0x80) != 0)
- return ref_clk;
- reg = CLKCTL_MPCTL;
- }
- pdf = (reg & (0x7 << 26)) >> 26;
- mfd = (reg & (0x3FF << 16)) >> 16;
- mfi = (reg & (0xF << 10)) >> 10;
- mfi = (mfi <= 5) ? 5 : mfi;
- mfn = (reg & 0x3FF);
-
- if(mfn < 0x200) {
- temp = (unsigned long long)2 *ref_clk * mfn;
- temp /= (mfd + 1);
- temp = (unsigned long long)2 *ref_clk * mfi + temp;
- temp /= (pdf + 1);
- } else {
- temp = (unsigned long long)2 *ref_clk * (0x400 - mfn);
- temp /= (mfd + 1);
- temp = (unsigned long long)2 *ref_clk * mfi - temp;
- temp /= (pdf + 1);
-
- }
- return (unsigned long)temp;
-}
-
-unsigned long get_ata_clock(void) {
- unsigned long pll, ret_val, hclk, max_pdf, ipg_pdf, mcu_pdf;
-
- max_pdf = (CLKCTL_PDR0 & (0x7 << 3)) >> 3;
- ipg_pdf = (CLKCTL_PDR0 & (0x3 << 6)) >> 6;
- mcu_pdf = (CLKCTL_PDR0 & 0x7);
- if((CLKCTL_PMCR0 & 0xC0000000 ) == 0) {
- pll = get_pll(true);
- } else {
- pll = get_pll(false);
- }
- hclk = pll/(max_pdf + 1);
- ret_val = hclk / (ipg_pdf + 1);
-
- return ret_val;
-}
-
void ata_device_init(void)
{
ATA_INTF_CONTROL |= ATA_ATA_RST; /* Make sure we're not in reset mode */
while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
- /* Setup the timing for PIO mode */
- int T = 1000 * 1000 * 1000 / get_ata_clock();
- ATA_TIME_OFF = 3;
- ATA_TIME_ON = 3;
-
- ATA_TIME_1 = (T + 70)/T;
- ATA_TIME_2W = (T + 290)/T;
- ATA_TIME_2R = (T + 290)/T;
- ATA_TIME_AX = (T + 50)/T;
- ATA_TIME_PIO_RDX = 1;
- ATA_TIME_4 = (T + 30)/T;
- ATA_TIME_9 = (T + 20)/T;
+ /* Setup mode 0 by default */
+ ata_set_pio_mode(0);
}
-#if 0
-#if !defined(BOOTLOADER)
-void copy_write_sectors(const unsigned char* buf, int wordcount)
+void ata_identify_ready(void)
{
- (void)buf; (void)wordcount;
+ const unsigned short* identify_info = ata_get_identify();
+ int mode = 0;
+
+ if (identify_info[53] & (1 << 1))
+ {
+ /* Set up advanced timings */
+ if (identify_info[64] & (1 << 1))
+ mode = 4; /* Mode 0, 1, 2, 3, 4 */
+ else if (identify_info[64] & (1 << 0))
+ mode = 3; /* Mode 0, 1, 2, 3 */
+ else
+ mode = 2; /* Mode 0, 1, 2 */
+ }
+
+ /* If mode changed, actually set the timings */
+ if (mode != 0)
+ {
+ ata_set_pio_mode(mode);
+ }
}
-#endif
-#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h
index a172064..7b61039 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);
void ata_device_init(void);
bool ata_is_coldstart(void);
+#define ATA_NOTIFY_IDENTIFY_READY
+void ata_identify_ready(void);
+
#endif
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.c
index a01fab0..2dc6e81 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,
restore_interrupt(oldlevel);
}
+
+/* Get the PLL reference clock frequency in HZ */
+unsigned int imx31_clkctl_get_pll_ref_clk(void)
+{
+ if ((CLKCTL_CCMR & (3 << 1)) == (1 << 1))
+ return CONFIG_CLK32_FREQ * 1024;
+ else
+ return CONFIG_HCLK_FREQ;
+}
+
+/* Return PLL frequency in HZ */
+unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll)
+{
+ uint32_t infreq = imx31_clkctl_get_pll_ref_clk();
+ uint32_t reg = (&CLKCTL_MPCTL)[pll];
+ uint32_t mfn = reg & 0x3ff;
+ uint32_t pd = ((reg >> 26) & 0xf) + 1;
+ uint64_t mfd = ((reg >> 16) & 0x3ff) + 1;
+ uint32_t mfi = (reg >> 10) & 0xf;
+
+ mfi = mfi <= 5 ? 5 : mfi;
+
+ return 2*infreq*(mfi * mfd + mfn) / (mfd * pd);
+}
+
+unsigned int imx31_clkctl_get_ipg_clk(void)
+{
+ unsigned int pll = imx31_clkctl_get_pll((CLKCTL_PMCR0 & 0xC0000000) == 0 ?
+ PLL_SERIAL : PLL_MCU);
+ uint32_t reg = CLKCTL_PDR0;
+ unsigned int max_pdf = ((reg >> 3) & 0x7) + 1;
+ unsigned int ipg_pdf = ((reg >> 6) & 0x3) + 1;
+
+ return pll / (max_pdf * ipg_pdf);
+}
+
+unsigned int imx31_clkctl_get_ata_clk(void)
+{
+ return imx31_clkctl_get_ipg_clk();
+}
diff --git a/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h b/firmware/target/arm/imx31/gigabeat-s/clkctl-imx31.h
index da15ef2..37d01ef 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
void imx31_clkctl_module_clock_gating(enum IMX31_CG_LIST cg,
enum IMX31_CG_MODES mode);
+enum IMX31_PLLS
+{
+ PLL_MCU = 0,
+ PLL_USB,
+ PLL_SERIAL,
+ NUM_PLLS,
+};
+
+#define CONFIG_CLK32_FREQ 32768
+#define CONFIG_HCLK_FREQ 27000000
+
+/* Get the PLL reference clock frequency in HZ */
+unsigned int imx31_clkctl_get_pll_ref_clk(void);
+
+/* Return PLL frequency in HZ */
+unsigned int imx31_clkctl_get_pll(enum IMX31_PLLS pll);
+
+/* Return ipg_clk in HZ */
+unsigned int imx31_clkctl_get_ipg_clk(void);
+
+/* Return the ATA frequency in HZ */
+unsigned int imx31_clkctl_get_ata_clk(void);
+
#endif /* _CLKCTL_IMX31_H_ */