summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/ata-imx31.c33
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/power-imx31.c17
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/system-imx31.c2
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c10
4 files changed, 50 insertions, 12 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
index 9c3c72e2c5..885e7e7521 100644
--- a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c
@@ -26,6 +26,7 @@
#include "ata.h"
#include "ata-target.h"
#include "clkctl-imx31.h"
+#
static const struct ata_pio_timings
{
@@ -81,10 +82,15 @@ static const struct ata_pio_timings
static int pio_mode = 0; /* Setup mode 0 by default */
+static void ata_wait_for_idle(void)
+{
+ while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
+}
+
/* Setup the timing for PIO mode */
void ata_set_pio_timings(int mode)
{
- while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
+ ata_wait_for_idle();
const struct ata_pio_timings * const timings = &pio_timings[mode];
/* T = period in nanoseconds */
@@ -107,20 +113,34 @@ void ata_set_pio_timings(int mode)
void ata_reset(void)
{
/* Be sure we're not busy */
- while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
+ ata_wait_for_idle();
ATA_INTF_CONTROL &= ~ATA_ATA_RST;
sleep(1);
ATA_INTF_CONTROL |= ATA_ATA_RST;
sleep(1);
- while (!(ATA_INTERRUPT_PENDING & ATA_CONTROLLER_IDLE));
+ ata_wait_for_idle();
}
-/* This function is called before enabling the USB bus */
void ata_enable(bool on)
{
- (void)on;
+ /* Unconditionally clock module before writing regs */
+ imx31_clkctl_module_clock_gating(CG_ATA, CGM_ON_ALL);
+
+ if (on)
+ {
+ ATA_INTF_CONTROL |= ATA_ATA_RST;
+ }
+ else
+ {
+ ata_wait_for_idle();
+
+ ATA_INTF_CONTROL &= ~ATA_ATA_RST;
+
+ /* Disable off - unclock ATA module */
+ imx31_clkctl_module_clock_gating(CG_ATA, CGM_OFF);
+ }
}
bool ata_is_coldstart(void)
@@ -130,7 +150,8 @@ bool ata_is_coldstart(void)
void ata_device_init(void)
{
- ATA_INTF_CONTROL |= ATA_ATA_RST; /* Make sure we're not in reset mode */
+ /* Make sure we're not in reset mode */
+ ata_enable(true);
/* mode may be switched later once identify info is ready in which
* case the main driver calls back */
diff --git a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
index e51318d16f..3e845d7d93 100644
--- a/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/power-imx31.c
@@ -19,6 +19,7 @@
#include "config.h"
#include "system.h"
#include "power.h"
+#include "ata.h"
#include "backlight.h"
#include "backlight-target.h"
#include "avic-imx31.h"
@@ -50,7 +51,21 @@ bool charging_state(void) {
void ide_power_enable(bool on)
{
- (void)on;
+ if (!on)
+ {
+ /* Bus must be isolated before power off */
+ imx31_regmod32(&GPIO2_DR, (1 << 16), (1 << 16));
+ }
+
+ /* HD power switch */
+ imx31_regmod32(&GPIO3_DR, on ? (1 << 5) : 0, (1 << 5));
+
+ if (on)
+ {
+ /* Bus switch may be turned on after powerup */
+ sleep(HZ/10);
+ imx31_regmod32(&GPIO2_DR, 0, (1 << 16));
+ }
}
bool ide_powered(void)
diff --git a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
index ca82a18fbd..412bbcc4b0 100644
--- a/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/system-imx31.c
@@ -27,7 +27,7 @@ void system_init(void)
gpio_init();
}
-void imx31_regmod32(volatile uint32_t *reg_p, uint32_t mask, uint32_t value)
+void imx31_regmod32(volatile uint32_t *reg_p, uint32_t value, uint32_t mask)
{
value &= mask;
mask = ~mask;
diff --git a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c
index c8a04ce20e..a88571ee14 100644
--- a/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/wmcodec-imx31.c
@@ -39,10 +39,12 @@ static struct i2c_node wm8978_i2c_node =
void audiohw_init(void)
{
/* USB PLL = 338.688MHz, /30 = 11.2896MHz = 256Fs */
- imx31_regmod32(&CLKCTL_PDR1, PDR1_SSI1_PODF | PDR1_SSI2_PODF,
- PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1));
- imx31_regmod32(&CLKCTL_PDR1, PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF,
- PDR1_SSI1_PRE_PODFw(4-1) | PDR1_SSI2_PRE_PODFw(1-1));
+ imx31_regmod32(&CLKCTL_PDR1,
+ PDR1_SSI1_PODFw(64-1) | PDR1_SSI2_PODFw(5-1),
+ PDR1_SSI1_PODF | PDR1_SSI2_PODF);
+ imx31_regmod32(&CLKCTL_PDR1,
+ PDR1_SSI1_PRE_PODFw(4-1) | PDR1_SSI2_PRE_PODFw(1-1),
+ PDR1_SSI1_PRE_PODF | PDR1_SSI2_PRE_PODF);
i2c_enable_node(&wm8978_i2c_node, true);
audiohw_preinit();