From 977169ea7af37e8e4617a67a84874bb98d07b070 Mon Sep 17 00:00:00 2001 From: Jens Arnold Date: Fri, 16 Jun 2006 17:34:18 +0000 Subject: 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 --- apps/main.c | 7 ++ firmware/SOURCES | 4 + firmware/crt0.S | 13 +++- firmware/drivers/isp1362.c | 177 ++++++++++++++++++++++++++++++++++++++++++ firmware/export/config-h300.h | 3 + firmware/export/config.h | 4 +- firmware/export/isp1362.h | 134 ++++++++++++++++++++++++++++++++ firmware/system.c | 20 ++++- 8 files changed, 355 insertions(+), 7 deletions(-) create mode 100755 firmware/drivers/isp1362.c create mode 100755 firmware/export/isp1362.h diff --git a/apps/main.c b/apps/main.c index 7bfc438cfd..d6e3c342c9 100644 --- a/apps/main.c +++ b/apps/main.c @@ -88,6 +88,10 @@ #include "lcd-remote.h" #endif +#if CONFIG_USBOTG == USBOTG_ISP1362 +#include "isp1362.h" +#endif + /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */ const char appsversion[]=APPSVERSION; @@ -276,6 +280,9 @@ void init(void) adc_init(); usb_init(); +#if CONFIG_USBOTG == USBOTG_ISP1362 + isp1362_init(); +#endif backlight_init(); diff --git a/firmware/SOURCES b/firmware/SOURCES index 07f4ffd796..d6765ef627 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -203,6 +203,10 @@ sound.c common/sscanf.c usb_serial.c #endif +#if CONFIG_USBOTG == USBOTG_ISP1362 +drivers/isp1362.c +#endif + #ifndef SIMULATOR #ifdef IAUDIO_X5 diff --git a/firmware/crt0.S b/firmware/crt0.S index e8ccede187..7594416c06 100644 --- a/firmware/crt0.S +++ b/firmware/crt0.S @@ -531,7 +531,7 @@ irq_handler: /* Chip select 1 - LCD controller */ move.l #0xf0000000,%d0 /* CSAR1 - Base = 0xf0000000 */ move.l %d0,(0x08c,%a0) - moveq.l #0x1,%d0 /* CSMR1 - 64K */ + moveq.l #0x1,%d0 /* CSMR1 - 64K */ move.l %d0,(0x090,%a0) move.l #0x00000180,%d0 /* CSCR1 - no wait states, 16 bits, no bursts */ move.l %d0,(0x094,%a0) @@ -545,7 +545,16 @@ irq_handler: move.l %d0,(0x0a0,%a0) /* NOTE: I'm not sure about the wait states. We have to be careful with the access times, since IORDY isn't connected to the HDD. */ - + +#if CONFIG_USBOTG == USBOTG_ISP1362 + /* Chip select 3 - USBOTG controller */ + move.l #0xc0000000,%d0 /* CSAR3 - Base = 0xc0000000 */ + move.l %d0,(0x0a4,%a0) + moveq.l #0x1,%d0 /* CSMR3 - 64K */ + move.l %d0,(0x0a8,%a0) + move.l #0x00000180,%d0 /* CSCR3 - no wait states, 16 bits, no bursts */ + move.l %d0,(0x0ac,%a0) +#endif #ifdef BOOTLOADER /* The cookie is not reset. This must mean that the boot loader diff --git a/firmware/drivers/isp1362.c b/firmware/drivers/isp1362.c new file mode 100755 index 0000000000..473c9dc3db --- /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(); +} diff --git a/firmware/export/config-h300.h b/firmware/export/config-h300.h index 7ed54958ca..30cca21253 100644 --- a/firmware/export/config-h300.h +++ b/firmware/export/config-h300.h @@ -110,6 +110,9 @@ #define USB_IRIVERSTYLE +/* USB On-the-go */ +#define CONFIG_USBOTG USBOTG_ISP1362 + /* Define this if you have adjustable CPU frequency */ #define HAVE_ADJUSTABLE_CPU_FREQ diff --git a/firmware/export/config.h b/firmware/export/config.h index 910aeca4eb..a1327558ed 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -122,6 +122,7 @@ /* CONFIG_LED */ #define LED_REAL 1 /* SW controlled LED (Archos recorders, player, Gmini) */ #define LED_VIRTUAL 2 /* Virtual LED (icon) (Archos Ondio) */ +/* else HW controlled LED (iRiver H1x0) */ /* CONFIG_FLASH */ #define FLASH_IFP7XX 1 @@ -132,7 +133,8 @@ #define RTC_PCF50606 3 /* iriver H300 */ #define RTC_S3C2440 4 -/* else HW controlled LED (iRiver H1x0) */ +/* USB On-the-go */ +#define USBOTG_ISP1362 1362 /* now go and pick yours */ #if defined(ARCHOS_PLAYER) diff --git a/firmware/export/isp1362.h b/firmware/export/isp1362.h new file mode 100755 index 0000000000..cba693e4f0 --- /dev/null +++ b/firmware/export/isp1362.h @@ -0,0 +1,134 @@ +/*************************************************************************** + * __________ __ ___. + * 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. + * + ****************************************************************************/ + +unsigned isp1362_read_hc_reg16(unsigned reg); +unsigned isp1362_read_hc_reg32(unsigned reg); +void isp1362_write_hc_reg16(unsigned reg, unsigned data); +void isp1362_write_hc_reg32(unsigned reg, unsigned data); + +#define ISP1362_OTG_CONTROL 0x62 +#define ISP1362_OTG_STATUS 0x67 /* read only */ +#define ISP1362_OTG_INTERRUPT 0x68 +#define ISP1362_OTG_INT_ENABLE 0x69 +#define ISP1362_OTG_TIMER 0x6a +#define ISP1362_OTG_ALT_TIMER 0x6c + +#define ISP1362_HC_REVISION 0x00 /* read only */ +#define ISP1362_HC_CONTROL 0x01 +#define ISP1362_HC_COMMAND_STATUS 0x02 +#define ISP1362_HC_INT_STATUS 0x03 +#define ISP1362_HC_INT_ENABLE 0x04 +#define ISP1362_HC_INT_DISABLE 0x05 +#define ISP1362_HC_FM_INTERVAL 0x0d +#define ISP1362_HC_FM_REMAINING 0x0e +#define ISP1362_HC_FM_NUMBER 0x0f +#define ISP1362_HC_LS_THRESHOLD 0x11 +#define ISP1362_HC_RH_DESCRIPTOR_A 0x12 +#define ISP1362_HC_RH_DESCRIPTOR_B 0x13 +#define ISP1362_HC_RH_STATUS 0x14 +#define ISP1362_HC_RH_PORT_STATUS1 0x15 +#define ISP1362_HC_RH_PORT_STATUS2 0x16 +#define ISP1362_HC_HARDWARE_CONFIG 0x20 +#define ISP1362_HC_DMA_CONFIG 0x21 +#define ISP1362_HC_TRANSFER_COUNTER 0x22 +#define ISP1362_HC_UP_INTERRUPT 0x24 +#define ISP1362_HC_UP_INT_ENABLE 0x25 +#define ISP1362_HC_CHIP_ID 0x27 /* read only */ +#define ISP1362_HC_SCRATCH 0x28 +#define ISP1362_HC_SOFTWARE_RESET 0x29 /* write only */ +#define ISP1362_HC_BUFFER_STATUS 0x2c +#define ISP1362_HC_DIRECT_ADDR_LEN 0x32 +#define ISP1362_HC_DIRECT_ADDR_DATA 0x45 +#define ISP1362_HC_ISTL_BUF_SIZE 0x30 +#define ISP1362_HC_ISTL0_BUF_PORT 0x40 +#define ISP1362_HC_ISTL1_BUF_PORT 0x42 +#define ISP1362_HC_ISTL_TOGGLE_RATE 0x47 +#define ISP1362_HC_INTL_BUF_SIZE 0x33 +#define ISP1362_HC_INTL_BUF_PORT 0x43 +#define ISP1362_HC_INTL_BLK_SIZE 0x53 +#define ISP1362_HC_INTL_PRD_DONE_MAP 0x17 /* read only */ +#define ISP1362_HC_INTL_PTD_SKIP_MAP 0x18 +#define ISP1362_HC_INTL_LAST_PTD 0x19 +#define ISP1362_HC_INTL_CUR_ACT_PTD 0x1a /* read only */ +#define ISP1362_HC_ATL_BUF_SIZE 0x34 +#define ISP1362_HC_ATL_BUF_PORT 0x44 +#define ISP1362_HC_ATL_BLK_SIZE 0x54 +#define ISP1362_HC_ATL_PTD_DONE_MAP 0x1b /* read only */ +#define ISP1362_HC_ATL_PTD_SKIP_MAP 0x1c +#define ISP1362_HC_ATL_LAST_PTD 0x1d +#define ISP1362_HC_ATL_CUR_ACT_PTD 0x1e /* read only */ +#define ISP1362_HC_ATL_PTD_DONE_THR_CNT 0x51 +#define ISP1362_HC_ATL_PTD_DONE_THR_TMO 0x52 + +unsigned isp1362_read_dc_reg16(unsigned reg); +unsigned isp1362_read_dc_reg32(unsigned reg); +void isp1362_write_dc_reg16(unsigned reg, unsigned data); +void isp1362_write_dc_reg32(unsigned reg, unsigned data); + +#define ISP1362_DC_CTRL_OUT_CFG_W 0x20 +#define ISP1362_DC_CTRL_IN_CFG_W 0x21 +#define ISP1362_DC_ENDPOINT_CFG_BASE_W 0x22 +#define ISP1362_DC_CTRL_OUT_CFG_R 0x30 +#define ISP1362_DC_CTRL_IN_CFG_R 0x31 +#define ISP1362_DC_ENDPOINT_CFG_BASE_R 0x32 +#define ISP1362_DC_ADDRESS_W 0xb6 +#define ISP1362_DC_ADDRESS_R 0xb7 +#define ISP1362_DC_MODE_W 0xb8 +#define ISP1362_DC_MODE_R 0xb9 +#define ISP1362_DC_HARDWARE_CONFIG_W 0xba +#define ISP1362_DC_HARDWARE_CONFIG_R 0xbb +#define ISP1362_DC_INT_ENABLE_W 0xc2 +#define ISP1362_DC_INT_ENABLE_R 0xc3 +#define ISP1362_DC_DMA_CONFIG_W 0xf0 +#define ISP1362_DC_DMA_CONFIG_R 0xf1 +#define ISP1362_DC_DMA_COUNTER_W 0xf2 +#define ISP1362_DC_DMA_COUNTER_R 0xf3 +#define ISP1362_DC_RESET 0xf6 +#define ISP1362_DC_CTRL_IN_BUF_W 0x01 +#define ISP1362_DC_ENDPOINT_BUF_BASE_W 0x02 +#define ISP1362_DC_CTRL_OUT_BUF_R 0x10 +#define ISP1362_DC_ENDPOINT_BUF_BASE_R 0x12 +#define ISP1362_DC_CTRL_OUT_STALL 0x40 +#define ISP1362_DC_CTRL_IN_STALL 0x41 +#define ISP1362_DC_ENDPOINT_STALL_BASE 0x42 +#define ISP1362_DC_CTRL_OUT_STATUS_R 0x50 +#define ISP1362_DC_CTRL_IN_STATUS_R 0x51 +#define ISP1362_DC_ENDPOINT_STATUS_BASE_R 0x52 +#define ISP1362_DC_CTRL_IN_VALIDATE 0x61 +#define ISP1362_DC_ENDPOINT_VALIDATE_BASE 0x62 +#define ISP1362_DC_CTRL_OUT_CLEAR 0x70 +#define ISP1362_DC_ENDPOINT_CLEAR_BASE 0x72 +#define ISP1362_DC_CTRL_OUT_UNSTALL 0x80 +#define ISP1362_DC_CTRL_IN_UNSTALL 0x81 +#define ISP1362_DC_ENDPOINT_UNSTALL_BASE 0x82 +#define ISP1362_DC_CTRL_OUT_STAT_IMG_R 0xd0 +#define ISP1362_DC_CTRL_IN_STAT_IMG_R 0xd1 +#define ISP1362_DC_ENDPOINT_STAT_IMG_BASE_R 0xd2 +#define ISP1362_DC_SETUP_ACK 0xf4 +#define ISP1362_DC_CTRL_OUT_ERROR_R 0xa0 +#define ISP1362_DC_CTRL_IN_ERROR_R 0xa1 +#define ISP1362_DC_ENDPOINT_ERROR_BASE_R 0xa2 +#define ISP1362_DC_UNLOCK_DEVICE 0xb0 +#define ISP1362_DC_SCRATCH_W 0xb2 +#define ISP1362_DC_SCRATCH_R 0xb3 +#define ISP1362_DC_FRAME_NUMBER_R 0xb4 +#define ISP1362_DC_CHIP_ID_R 0xb5 +#define ISP1362_DC_INTERRUPT_R 0xc0 + +void isp1362_init(void); diff --git a/firmware/system.c b/firmware/system.c index 6e6408bf1b..af2b74a17a 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -616,13 +616,17 @@ void set_cpu_frequency(long frequency) PLLCR = 0x11c56005; CSCR0 = 0x00001180; /* Flash: 4 wait states */ CSCR1 = 0x00000980; /* LCD: 2 wait states */ +#if CONFIG_USBOTG == USBOTG_ISP1362 + CSCR3 = 0x00002180; /* USBOTG: 8 wait states */ +#endif while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. This may take up to 10ms! */ timers_adjust_prescale(CPUFREQ_MAX_MULT, true); DCR = (0x8200 | MAX_REFRESH_TIMER); /* Refresh timer */ cpu_frequency = CPUFREQ_MAX; - IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ - IDECONFIG2 = 0x40000 | (1 << 8); /* TA enable + CS2wait */ + IDECONFIG1 = 0x10100000 | (3 << 13) | (5 << 10); + /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */ + IDECONFIG2 = 0x40000 | (2 << 8); /* TA enable + CS2wait */ break; case CPUFREQ_NORMAL: @@ -634,12 +638,16 @@ void set_cpu_frequency(long frequency) PLLCR = 0x13c5e005; CSCR0 = 0x00000580; /* Flash: 1 wait state */ CSCR1 = 0x00000180; /* LCD: 0 wait states */ +#if CONFIG_USBOTG == USBOTG_ISP1362 + CSCR3 = 0x00000580; /* USBOTG: 1 wait state */ +#endif while(!(PLLCR & 0x80000000)) {}; /* Wait until the PLL has locked. This may take up to 10ms! */ timers_adjust_prescale(CPUFREQ_NORMAL_MULT, true); DCR = (0x8000 | NORMAL_REFRESH_TIMER); /* Refresh timer */ cpu_frequency = CPUFREQ_NORMAL; - IDECONFIG1 = 0x106000 | (5 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ + IDECONFIG1 = 0x10100000 | (3 << 13) | (5 << 10); + /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */ IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */ break; default: @@ -651,9 +659,13 @@ void set_cpu_frequency(long frequency) PLLCR = 0x10c00200; /* Power down PLL, but keep CLSEL and CRSEL */ CSCR0 = 0x00000180; /* Flash: 0 wait states */ CSCR1 = 0x00000180; /* LCD: 0 wait states */ +#if CONFIG_USBOTG == USBOTG_ISP1362 + CSCR3 = 0x00000180; /* USBOTG: 0 wait states */ +#endif DCR = (0x8000 | DEFAULT_REFRESH_TIMER); /* Refresh timer */ cpu_frequency = CPUFREQ_DEFAULT; - IDECONFIG1 = 0x106000 | (1 << 10); /* BUFEN2 enable + CS2Pre/CS2Post */ + IDECONFIG1 = 0x10100000 | (3 << 13) | (1 << 10); + /* SRE active on write (H300 USBOTG) | BUFEN2 enable | CS2Post | CS2Pre */ IDECONFIG2 = 0x40000 | (0 << 8); /* TA enable + CS2wait */ break; } -- cgit v1.2.3