rockbox/firmware/target/arm/usb-fw-pp502x.c
2011-12-15 00:14:36 +00:00

309 lines
8.6 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Linus Nielsen Feltzing
*
* iPod driver based on code from the ipodlinux project - http://ipodlinux.org
* Adapted for Rockbox in January 2006
* Original file: podzilla/usb.c
* Copyright (C) 2005 Adam Johnston
*
* 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 "config.h"
#include "system.h"
#include "usb-target.h"
#include "usb.h"
#include "button.h"
#include "ata.h"
#include "string.h"
#include "usb_core.h"
#include "usb_drv.h"
#if defined(IPOD_4G) || defined(IPOD_COLOR) \
|| defined(IPOD_MINI) || defined(IPOD_MINI2G)
/* GPIO D bit 3 is usb detect */
#define USB_GPIO GPIOD
#define USB_GPIO_MASK 0x08
#define USB_GPIO_VAL 0x08
#elif defined(IPOD_NANO) || defined(IPOD_VIDEO)
/* GPIO L bit 4 is usb detect */
#define USB_GPIO GPIOL
#define USB_GPIO_MASK 0x10
#define USB_GPIO_VAL 0x10
#elif defined(SANSA_C200)
/* GPIO H bit 1 is usb/charger detect */
#define USB_GPIO GPIOH
#define USB_GPIO_MASK 0x02
#define USB_GPIO_VAL 0x02
#elif defined(SANSA_E200)
/* GPIO B bit 4 is usb/charger detect */
#define USB_GPIO GPIOB
#define USB_GPIO_MASK 0x10
#define USB_GPIO_VAL 0x10
#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB) || defined(MROBE_100)
/* GPIO L bit 2 is usb detect */
#define USB_GPIO GPIOL
#define USB_GPIO_MASK 0x04
#define USB_GPIO_VAL 0x04
#elif defined(PHILIPS_SA9200)
/* GPIO B bit 6 (high) is usb bus power detect */
#define USB_GPIO GPIOB
#define USB_GPIO_MASK 0x40
#define USB_GPIO_VAL 0x40
#elif defined(PHILIPS_HDD1630) || defined(PHILIPS_HDD6330)
/* GPIO E bit 2 is usb detect */
#define USB_GPIO GPIOE
#define USB_GPIO_MASK 0x04
#define USB_GPIO_VAL 0x04
#elif defined(SAMSUNG_YH820) || defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
/* GPIO D bit 4 is usb detect */
#define USB_GPIO GPIOD
#define USB_GPIO_MASK 0x10
#define USB_GPIO_VAL 0x10
#elif defined(TATUNG_TPJ1022)
/* GPIO ? bit ? is usb detect (dummy value)*/
#define USB_GPIO GPIOD
#define USB_GPIO_MASK 0x10
#define USB_GPIO_VAL 0x10
#elif defined(PBELL_VIBE500)
/* GPIO L bit 3 is usb detect */
#define USB_GPIO GPIOL
#define USB_GPIO_MASK 0x04
#define USB_GPIO_VAL 0x04
#else
#error No USB GPIO config specified
#endif
#define USB_GPIO_ENABLE GPIO_ENABLE(USB_GPIO)
#define USB_GPIO_OUTPUT_EN GPIO_OUTPUT_EN(USB_GPIO)
#define USB_GPIO_INPUT_VAL GPIO_INPUT_VAL(USB_GPIO)
#define USB_GPIO_INT_EN GPIO_INT_EN(USB_GPIO)
#define USB_GPIO_INT_LEV GPIO_INT_LEV(USB_GPIO)
#define USB_GPIO_INT_CLR GPIO_INT_CLR(USB_GPIO)
#define USB_GPIO_HI_INT_MASK GPIO_HI_INT_MASK(USB_GPIO)
static void usb_reset_controller(void)
{
/* enable usb module */
outl(inl(0x7000002C) | 0x3000000, 0x7000002C);
DEV_EN |= DEV_USB0;
DEV_EN |= DEV_USB1;
/* reset both USBs */
DEV_RS |= DEV_USB0;
DEV_RS &=~DEV_USB0;
DEV_RS |= DEV_USB1;
DEV_RS &=~DEV_USB1;
DEV_INIT2 |= INIT_USB;
while ((inl(0x70000028) & 0x80) == 0);
outl(inl(0x70000028) | 0x2, 0x70000028);
udelay(100000);
XMB_RAM_CFG |= 0x47A;
/* disable USB-devices until USB is detected via GPIO */
#ifndef BOOTLOADER
/* Disabling USB0 in the bootloader makes the OF not load,
Also something here breaks usb pin detect in bootloader.
leave it all enabled untill rockbox main loads */
DEV_EN &= ~DEV_USB0;
DEV_EN &= ~DEV_USB1;
DEV_INIT2 &= ~INIT_USB;
#endif
}
/* Enable raw status pin read only - not interrupt */
void usb_pin_init(void)
{
GPIO_CLEAR_BITWISE(USB_GPIO_OUTPUT_EN, USB_GPIO_MASK);
GPIO_SET_BITWISE(USB_GPIO_ENABLE, USB_GPIO_MASK);
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_OUTPUT_EN, 0x02);
GPIO_SET_BITWISE(GPIOC_ENABLE, 0x02);
#endif
}
void usb_init_device(void)
{
usb_reset_controller();
/* Do one-time inits (no dependency on controller) */
usb_drv_startup();
usb_pin_init();
/* These set INT_LEV to the inserted level so it will fire if already
* inserted at the time they are enabled. */
#ifdef USB_STATUS_BY_EVENT
GPIO_CLEAR_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, USB_GPIO_VAL, USB_GPIO_MASK);
USB_GPIO_INT_CLR = USB_GPIO_MASK;
GPIO_SET_BITWISE(USB_GPIO_INT_EN, USB_GPIO_MASK);
CPU_HI_INT_EN = USB_GPIO_HI_INT_MASK;
#ifdef USB_FIREWIRE_HANDLING
/* GPIO C bit 1 is firewire detect */
GPIO_CLEAR_BITWISE(GPIOC_INT_EN, 0x02);
GPIO_WRITE_BITWISE(GPIOC_INT_LEV, 0x00, 0x02);
GPIOC_INT_CLR = 0x02;
GPIO_SET_BITWISE(GPIOC_INT_EN, 0x02);
CPU_HI_INT_EN = GPIO0_MASK;
#endif
CPU_INT_EN = HI_MASK;
#endif /* USB_STATUS_BY_EVENT */
}
void usb_enable(bool on)
{
if (on) {
/* if USB is detected, re-enable the USB-devices, otherwise make sure it's disabled */
DEV_EN |= DEV_USB0;
DEV_EN |= DEV_USB1;
DEV_INIT2 |= INIT_USB;
usb_core_init();
}
else {
usb_core_exit();
/* Disable USB devices */
usb_reset_controller();
}
}
void usb_attach(void)
{
usb_drv_attach();
}
bool usb_plugged(void)
{
return (USB_GPIO_INPUT_VAL & USB_GPIO_MASK) == USB_GPIO_VAL;
}
#ifdef USB_STATUS_BY_EVENT
/* Cannot always tell power pin from USB pin */
static int usb_status = USB_EXTRACTED;
static int usb_timeout_event(struct timeout *tmo)
{
usb_status_event(tmo->data == USB_GPIO_VAL ? USB_INSERTED : USB_EXTRACTED);
return 0;
}
void usb_insert_int(void)
{
static struct timeout usb_oneshot;
unsigned long val = USB_GPIO_INPUT_VAL & USB_GPIO_MASK;
usb_status = (val == USB_GPIO_VAL) ? USB_INSERTED : USB_EXTRACTED;
GPIO_WRITE_BITWISE(USB_GPIO_INT_LEV, val ^ USB_GPIO_MASK, USB_GPIO_MASK);
USB_GPIO_INT_CLR = USB_GPIO_MASK;
timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val);
}
/* USB_DETECT_BY_CORE: Called when device descriptor is requested */
void usb_drv_usb_detect_event(void)
{
/* Filter for invalid bus reset when unplugging by checking the pin state. */
if(usb_plugged()) {
usb_status_event(USB_HOSTED);
}
}
#endif /* USB_STATUS_BY_EVENT */
#ifdef HAVE_BOOTLOADER_USB_MODE
/* Replacement function that returns all unused memory after the bootloader
* because the storage driver uses the audio buffer */
extern unsigned char freebuffer[];
extern unsigned char freebufferend[];
unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
{
if (buffer_size)
*buffer_size = freebufferend - freebuffer + 1;
return freebuffer;
(void)talk_buf;
}
#endif /* HAVE_BOOTLOADER_USB_MODE */
void usb_drv_int_enable(bool enable)
{
/* enable/disable USB IRQ in CPU */
if(enable) {
CPU_INT_EN = USB_MASK;
}
else {
CPU_INT_DIS = USB_MASK;
}
}
/* detect host or charger (INSERTED or EXTRACTED) */
int usb_detect(void)
{
#ifdef USB_STATUS_BY_EVENT
return usb_status;
#else
return usb_plugged() ? USB_INSERTED : USB_EXTRACTED;
#endif
}
#ifdef USB_FIREWIRE_HANDLING
#ifdef USB_STATUS_BY_EVENT
static bool firewire_status = false;
#endif
bool firewire_detect(void)
{
#ifdef USB_STATUS_BY_EVENT
return firewire_status;
#else
/* GPIO C bit 1 is firewire detect */
/* no charger detection needed for firewire */
return (GPIOC_INPUT_VAL & 0x02) == 0x00;
#endif
}
#ifdef USB_STATUS_BY_EVENT
static int firewire_timeout_event(struct timeout *tmo)
{
if (tmo->data == 0x00)
usb_firewire_connect_event();
return 0;
}
void firewire_insert_int(void)
{
static struct timeout firewire_oneshot;
unsigned long val = GPIOC_INPUT_VAL & 0x02;
firewire_status = val == 0x00;
GPIO_WRITE_BITWISE(GPIOC_INT_LEV, val ^ 0x02, 0x02);
GPIOC_INT_CLR = 0x02;
timeout_register(&firewire_oneshot, firewire_timeout_event, HZ/5, val);
}
#endif /* USB_STATUS_BY_EVENT */
#endif /* USB_FIREWIRE_HANDLING */