From c1780af9fcc6b7751b267e4e9577bbb2424a1169 Mon Sep 17 00:00:00 2001 From: Rafaël Carré Date: Mon, 6 Jul 2009 13:54:51 +0000 Subject: Samsa AMS: start of an USB driver (nothing working atm) Work based on AMD 5536 linux driver and AMD Geode CS5536 datasheet Rockbox still doesn't reboot on USB insert git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21689 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/as3525/usb-drv-as3525.c | 286 ++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 firmware/target/arm/as3525/usb-drv-as3525.c (limited to 'firmware/target/arm/as3525/usb-drv-as3525.c') diff --git a/firmware/target/arm/as3525/usb-drv-as3525.c b/firmware/target/arm/as3525/usb-drv-as3525.c new file mode 100644 index 0000000000..bac5f6776b --- /dev/null +++ b/firmware/target/arm/as3525/usb-drv-as3525.c @@ -0,0 +1,286 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright © 2009 Rafaël Carré + * + * 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 "usb.h" +#include "usb_drv.h" +#include "as3525.h" +#include "clock-target.h" +#include "ascodec.h" +#include "as3514.h" +#include + +/* 4 input endpoints */ +#define USB_IEP_CTRL(i) *((volatile unsigned long*) USB_BASE + 0x0000 + (i*0x20)) +#define USB_IEP_STS(i) *((volatile unsigned long*) USB_BASE + 0x0004 + (i*0x20)) +#define USB_IEP_TXFSIZE(i) *((volatile unsigned long*) USB_BASE + 0x0008 + (i*0x20)) +#define USB_IEP_MPS(i) *((volatile unsigned long*) USB_BASE + 0x000C + (i*0x20)) +#define USB_IEP_DESC_PTR(i) *((volatile unsigned long*) USB_BASE + 0x0014 + (i*0x20)) +#define USB_IEP_STS_MASK(i) *((volatile unsigned long*) USB_BASE + 0x0018 + (i*0x20)) + +/* 4 output endpoints */ +#define USB_OEP_CTRL(i) *((volatile unsigned long*) USB_BASE + 0x0200 + (i*0x20)) +#define USB_OEP_STS(i) *((volatile unsigned long*) USB_BASE + 0x0204 + (i*0x20)) +#define USB_OEP_RXFR(i) *((volatile unsigned long*) USB_BASE + 0x0208 + (i*0x20)) +#define USB_OEP_MPS(i) *((volatile unsigned long*) USB_BASE + 0x020C + (i*0x20)) +#define USB_OEP_SUP_PTR(i) *((volatile unsigned long*) USB_BASE + 0x0210 + (i*0x20)) +#define USB_OEP_DESC_PTR(i) *((volatile unsigned long*) USB_BASE + 0x0214 + (i*0x20)) +#define USB_OEP_STS_MASK(i) *((volatile unsigned long*) USB_BASE + 0x0218 + (i*0x20)) + +#define USB_DEV_CFG *((volatile unsigned long*) USB_BASE + 0x0400) +#define USB_DEV_CTRL *((volatile unsigned long*) USB_BASE + 0x0404) +#define USB_DEV_STS *((volatile unsigned long*) USB_BASE + 0x0408) +#define USB_DEV_INTR *((volatile unsigned long*) USB_BASE + 0x040C) +#define USB_DEV_INTR_MASK *((volatile unsigned long*) USB_BASE + 0x0410) +#define USB_DEV_EP_INTR *((volatile unsigned long*) USB_BASE + 0x0414) +#define USB_DEV_EP_INTR_MASK *((volatile unsigned long*) USB_BASE + 0x0418) + +#define USB_PHY_EP0_INFO *((volatile unsigned long*) USB_BASE + 0x0504) +#define USB_PHY_EP1_INFO *((volatile unsigned long*) USB_BASE + 0x0508) +#define USB_PHY_EP2_INFO *((volatile unsigned long*) USB_BASE + 0x050C) +#define USB_PHY_EP3_INFO *((volatile unsigned long*) USB_BASE + 0x0510) +#define USB_PHY_EP4_INFO *((volatile unsigned long*) USB_BASE + 0x0514) +#define USB_PHY_EP5_INFO *((volatile unsigned long*) USB_BASE + 0x0518) + +/* 4 channels */ +#define USB_HOST_CH_SPLT(i) *((volatile unsigned long*) USB_BASE + 0x1000 + (i*0x20)) +#define USB_HOST_CH_STS(i) *((volatile unsigned long*) USB_BASE + 0x1004 + (i*0x20)) +#define USB_HOST_CH_TXFSIZE(i) *((volatile unsigned long*) USB_BASE + 0x1008 + (i*0x20)) +#define USB_HOST_CH_REQ(i) *((volatile unsigned long*) USB_BASE + 0x100C + (i*0x20)) +#define USB_HOST_CH_PER_INFO(i) *((volatile unsigned long*) USB_BASE + 0x1010 + (i*0x20)) +#define USB_HOST_CH_DESC_PTR(i) *((volatile unsigned long*) USB_BASE + 0x1014 + (i*0x20)) +#define USB_HOST_CH_STS_MASK(i) *((volatile unsigned long*) USB_BASE + 0x1018 + (i*0x20)) + +#define USB_HOST_CFG *((volatile unsigned long*) USB_BASE + 0x1400) +#define USB_HOST_CTRL *((volatile unsigned long*) USB_BASE + 0x1404) +#define USB_HOST_INTR *((volatile unsigned long*) USB_BASE + 0x140C) +#define USB_HOST_INTR_MASK *((volatile unsigned long*) USB_BASE + 0x1410) +#define USB_HOST_CH_INTR *((volatile unsigned long*) USB_BASE + 0x1414) +#define USB_HOST_CH_INTR_MASK *((volatile unsigned long*) USB_BASE + 0x1418) +#define USB_HOST_FRAME_INT *((volatile unsigned long*) USB_BASE + 0x141C) +#define USB_HOST_FRAME_REM *((volatile unsigned long*) USB_BASE + 0x1420) +#define USB_HOST_FRAME_NUM *((volatile unsigned long*) USB_BASE + 0x1424) + +#define USB_HOST_PORT0_CTRL_STS *((volatile unsigned long*) USB_BASE + 0x1500) + +#define USB_OTG_CSR *((volatile unsigned long*) USB_BASE + 0x2000) +#define USB_I2C_CSR *((volatile unsigned long*) USB_BASE + 0x2004) +#define USB_GPIO_CSR *((volatile unsigned long*) USB_BASE + 0x2008) +#define USB_SNPSID_CSR *((volatile unsigned long*) USB_BASE + 0x200C) +#define USB_USERID_CSR *((volatile unsigned long*) USB_BASE + 0x2010) +#define USB_USER_CONF1 *((volatile unsigned long*) USB_BASE + 0x2014) +#define USB_USER_CONF2 *((volatile unsigned long*) USB_BASE + 0x2018) +#define USB_USER_CONF3 *((volatile unsigned long*) USB_BASE + 0x201C) +#define USB_USER_CONF4 *((volatile unsigned long*) USB_BASE + 0x2020) +#define USB_USER_CONF5 *((volatile unsigned long*) USB_BASE + 0x2024) + +struct usb_endpoint +{ + void *buf; + unsigned int len; + union + { + unsigned int sent; + unsigned int received; + }; + bool wait; + bool busy; +}; + +static struct usb_endpoint endpoints[USB_NUM_ENDPOINTS*2]; + +void usb_attach(void) +{ + usb_enable(true); +} + +void usb_drv_init(void) +{ + int i; + for(i = 0; i < USB_NUM_ENDPOINTS * 2; i++) + endpoints[i].busy = false; + + ascodec_write(AS3514_CVDD_DCDC3, ascodec_read(AS3514_CVDD_DCDC3) | 1<<2); + ascodec_write(AS3514_USB_UTIL, ascodec_read(AS3514_USB_UTIL) & ~(1<<4)); + + USB_GPIO_CSR |= 0x1C00000; //sleep(3) + sleep(1); + USB_GPIO_CSR |= 0x200000; //sleep(10) + sleep(1); + + /* PHY part */ + CGU_USB = 1<<5 /* enable */ + | (CLK_DIV(AS3525_PLLA_FREQ, 48000000) / 2) << 2 + | 1; /* source = PLLA */ + + /* AHB part */ + CGU_PERI |= CGU_USB_CLOCK_ENABLE; + + /* UVDD */ + ascodec_write(AS3514_USB_UTIL, ascodec_read(AS3514_USB_UTIL) | (1<<4)); + + sleep(10); + + USB_DEV_CFG |= (1<<31); /* soft reset */ + volatile int tmp = USB_DEV_CFG; + (void)tmp; + + USB_GPIO_CSR = 0x6180000; + + USB_DEV_CFG = (USB_DEV_CFG & ~3) | 1; /* full speed */ + + USB_DEV_CTRL |= 0x400; /* soft disconnect */ + + + USB_GPIO_CSR |= 0x1C00000; //sleep(3) + sleep(1); + USB_GPIO_CSR |= 0x200000; //sleep(10) + sleep(1); + + USB_DEV_CTRL |= 0x400; /* soft disconnect */ + + USB_GPIO_CSR &= ~0x1C00000; //sleep(3) + sleep(1); + USB_GPIO_CSR &= ~0x200000; //sleep(10) + sleep(1); + USB_DEV_CTRL &= ~0x400; /* soft disconnect */ + + GPIOA_DIR |= (1<<6); + GPIOA_PIN(6) = (1<<6); + +#if 0 /* linux */ + USB_DEV_CFG |= (1<<17) /* csr programming */ + | (1<<3) /* self powered */ + | (1<<2); /* remote wakeup */ + + USB_DEV_CFG &= ~3; /* high speed */ +#endif + + USB_IEP_CTRL(0) &= (3 << 4); /* control endpoint */ + USB_IEP_DESC_PTR(0) = 0; + + USB_OEP_CTRL(0) &= (3 << 4); /* control endpoint */ + USB_OEP_DESC_PTR(0) = 0; + + USB_DEV_INTR_MASK &= ~0xff; /* unmask all flags */ + + USB_DEV_EP_INTR_MASK &= ~((1<<0) | (1<<16)); /* ep 0 */ + + VIC_INT_ENABLE |= INTERRUPT_USB; + + USB_IEP_CTRL(0) |= (1<<7); /* set NAK */ + USB_OEP_CTRL(0) |= (1<<7); /* set NAK */ +} + +void usb_drv_exit(void) +{ + USB_DEV_CTRL |= (1<<10); /* soft disconnect */ + VIC_INT_EN_CLEAR = INTERRUPT_USB; + CGU_USB &= ~(1<<5); + CGU_PERI &= ~CGU_USB_CLOCK_ENABLE; + ascodec_write(AS3514_USB_UTIL, ascodec_read(AS3514_USB_UTIL) & ~(1<<4)); +} + +int usb_drv_port_speed(void) +{ + return (USB_DEV_CFG & 3) ? 0 : 1; +} + +int usb_drv_request_endpoint(int type, int dir) +{ + (void) type; + int i = dir == USB_DIR_IN ? 0 : 1; + + for(; i < USB_NUM_ENDPOINTS * 2; i += 2) + if(!endpoints[i].busy) + { + endpoints[i].busy = true; + i >>= 1; + USB_DEV_EP_INTR_MASK &= ~((1<= 2) + return -1; + + return -1; +} + +int usb_drv_send(int ep, void *ptr, int len) +{ + (void)ep;(void)ptr;(void)len; + if(ep >= 2) + return -1; + + return -1; +} + +int usb_drv_send_nonblocking(int ep, void *ptr, int len) +{ + /* TODO */ + return usb_drv_send(ep, ptr, len); +} + +/* interrupt service routine */ +void INT_USB(void) +{ +} + +/* (not essential? , not implemented in usb-tcc.c) */ +void usb_drv_set_test_mode(int mode) +{ + (void)mode; +} + +void usb_drv_set_address(int address) +{ + (void)address; +} + +void usb_drv_stall(int ep, bool stall, bool in) +{ + (void)ep;(void)stall;(void)in; +} + +bool usb_drv_stalled(int ep, bool in) +{ + (void)ep;(void)in; + return true; +} + -- cgit v1.2.3