summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-06-16 17:34:18 +0000
committerJens Arnold <amiconn@rockbox.org>2006-06-16 17:34:18 +0000
commit977169ea7af37e8e4617a67a84874bb98d07b070 (patch)
tree2d6f28e11682b2788dde041fa03cd198ab44fcde /firmware/drivers
parentcd69996450ab847fe3014c3a3c701173e36997fe (diff)
downloadrockbox-977169ea7af37e8e4617a67a84874bb98d07b070.zip
rockbox-977169ea7af37e8e4617a67a84874bb98d07b070.tar.gz
rockbox-977169ea7af37e8e4617a67a84874bb98d07b070.tar.bz2
rockbox-977169ea7af37e8e4617a67a84874bb98d07b070.tar.xz
H300: Rudimentary driver for the ISP1362 USB on-the-go controller. For now it just sends the chip to sleep, solving the poor battery runtime issue.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10128 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rwxr-xr-xfirmware/drivers/isp1362.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/firmware/drivers/isp1362.c b/firmware/drivers/isp1362.c
new file mode 100755
index 0000000..473c9dc
--- /dev/null
+++ b/firmware/drivers/isp1362.c
@@ -0,0 +1,177 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Jens Arnold
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "system.h"
+#include "kernel.h"
+#include "isp1362.h"
+
+#define HC_DATA (*((volatile unsigned short*)0xc0000000))
+#define HC_CMD (*((volatile unsigned short*)0xc0000002))
+#define DC_DATA (*((volatile unsigned short*)0xc0000004))
+#define DC_CMD (*((volatile unsigned short*)0xc0000006))
+
+/* host controller access */
+
+unsigned isp1362_read_hc_reg16(unsigned reg)
+{
+ HC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+
+ return HC_DATA;
+}
+
+unsigned isp1362_read_hc_reg32(unsigned reg)
+{
+ unsigned data;
+
+ HC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+
+ data = HC_DATA;
+ data |= HC_DATA << 16;
+ return data;
+}
+
+void isp1362_write_hc_reg16(unsigned reg, unsigned data)
+{
+ HC_CMD = reg | 0x80;
+
+ asm ("nop\n nop\n nop\n");
+
+ HC_DATA = data;
+}
+
+void isp1362_write_hc_reg32(unsigned reg, unsigned data)
+{
+ HC_CMD = reg | 0x80;
+
+ asm ("nop\n nop\n nop\n");
+
+ HC_DATA = data;
+ HC_DATA = data >> 16;
+}
+
+/* device controller access */
+
+unsigned isp1362_read_dc_reg16(unsigned reg)
+{
+ DC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+
+ return DC_DATA;
+}
+
+unsigned isp1362_read_dc_reg32(unsigned reg)
+{
+ unsigned data;
+
+ DC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+ asm ("nop\n nop\n nop\n nop\n");
+
+ data = DC_DATA;
+ data |= DC_DATA << 16;
+ return data;
+}
+
+void isp1362_write_dc_reg16(unsigned reg, unsigned data)
+{
+ DC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n");
+
+ DC_DATA = data;
+}
+
+void isp1362_write_dc_reg32(unsigned reg, unsigned data)
+{
+ DC_CMD = reg;
+
+ asm ("nop\n nop\n nop\n");
+
+ DC_DATA = data;
+ DC_DATA = data >> 16;
+}
+
+static void isp1362_suspend(void)
+{
+ unsigned data;
+
+ data = isp1362_read_hc_reg16(ISP1362_OTG_CONTROL);
+ data &= ~0x0001; /* DRV_VBUS = 0 */
+ isp1362_write_hc_reg16(ISP1362_OTG_CONTROL, data);
+
+ /* prepare the DC */
+ data = isp1362_read_dc_reg16(ISP1362_DC_HARDWARE_CONFIG_R);
+ data &= ~0x1008; /* CLKRUN = WKUPCS = 0. Wakeup is still possible via /D_WAKEUP */
+ isp1362_write_dc_reg16(ISP1362_DC_HARDWARE_CONFIG_W, data);
+
+ /* send the DC to sleep */
+ data = isp1362_read_dc_reg16(ISP1362_DC_MODE_R);
+ data |= 0x20; /* GOSUSP = 1 */
+ isp1362_write_dc_reg16(ISP1362_DC_MODE_W, data);
+ data &= ~0x20; /* GOSUSP = 0 */
+ isp1362_write_dc_reg16(ISP1362_DC_MODE_W, data);
+
+ /* prepare the HC */
+ data = isp1362_read_hc_reg16(ISP1362_HC_HARDWARE_CONFIG);
+ data &= ~0x0800; /* SuspendClkNotStop = 0 */
+ data |= 0x4001; /* GlobalPowerDown = InterruptPinEnable = 1 */
+ isp1362_write_hc_reg16(ISP1362_HC_HARDWARE_CONFIG, data);
+
+ /* TODO: OTG wake-up cfg */
+ /* TODO: Interrupt setup */
+
+ /* set the HC to operational */
+ isp1362_write_hc_reg32(ISP1362_HC_CONTROL, 0x0680);
+ /* RWE = RWC = 1, HCFS = 0b10 (USBOperational) */
+ /* ..then send it to sleep */
+ isp1362_write_hc_reg32(ISP1362_HC_CONTROL, 0x06c0);
+ /* RWE = RWC = 1, HCFS = 0b11 (USBSuspend) */
+}
+
+/* init */
+
+void isp1362_init(void)
+{
+ and_l(~0x00200080, &GPIO1_OUT); /* disable 5V USB host power and ??? */
+ or_l( 0x00200080, &GPIO1_ENABLE);
+ or_l( 0x00200080, &GPIO1_FUNCTION);
+
+ or_l( 0x20600000, &GPIO_OUT); /* ID = D_SUSPEND = /OTGMODE = 1 */
+ and_l(~0x04000000, &GPIO_OUT); /* ?R26? = 0 */
+ or_l( 0x24600000, &GPIO_ENABLE); /* ID, ?R26?, D_SUSPEND, /OTGMODE outputs */
+ and_l(~0x000000a8, &GPIO_ENABLE); /* /INT2, /INT1, /RESET inputs */
+ or_l( 0x246000a8, &GPIO_FUNCTION); /* GPIO for these pins */
+
+ sleep(HZ/5);
+
+ isp1362_suspend();
+}