/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2006 Jens Arnold * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * 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(); }