/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*
* SL811HS USB HCD for Linux Version 0.1 (10/28/2001)
*
* requires (includes) hc_simple.[hc] simple generic HCD frontend
*
* COPYRIGHT(C) 2001 by CYPRESS SEMICONDUCTOR INC.
*
*-------------------------------------------------------------------------*
* 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 program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*-------------------------------------------------------------------------*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <asm/io.h>
#include <asm/arch/irq.h>
#include <linux/usb.h>
#undef HC_URB_TIMEOUT
#undef HC_SWITCH_INT
#undef HC_ENABLE_ISOC
#define SL811_DEBUG_ERR
//#ifdef SL811_DEBUG_ERR
//#define DBGERR(fmt, args...) printk(fmt,## args)
//#else
#define DBGERR(fmt, args...)
//#endif
//#ifdef SL811_DEBUG
//#define DBG(fmt, args...) printk(fmt,## args)
//#else
#define DBG(fmt, args...)
//#endif
//#ifdef SL811_DEBUG_FUNC
//#define DBGFUNC(fmt, args...) printk(fmt,## args)
//#else
#define DBGFUNC(fmt, args...)
//#endif
//#ifdef SL811_DEBUG_DATA
//#define DBGDATAR(fmt, args...) printk(fmt,## args)
//#define DBGDATAW(fmt, args...) printk(fmt,## args)
//#else
#define DBGDATAR(fmt, args...)
#define DBGDATAW(fmt, args...)
//#endif
//#ifdef SL811_DEBUG_VERBOSE
//#define DBGVERBOSE(fmt, args...) printk(fmt,## args)
//#else
#define DBGVERBOSE(fmt, args...)
//#endif
#define TRUE 1
#define FALSE 0
#define HC_SWITCH_INT
#include "hc_sl811.h"
#include "hc_simple.h"
static int urb_debug = 0;
#include "hc_simple.c"
#include "hc_sl811_rh.c"
#define MX1_PORTD_VA_BASE 0xf021c300
#define _reg_PORTD_DDIR (*((volatile U32 *)(MX1_PORTD_VA_BASE)))
#define _reg_PORTD_GIUS (*((volatile U32 *)(MX1_PORTD_VA_BASE + 0x20)))
#define _reg_PORTD_ICR1 (*((volatile U32 *)(MX1_PORTD_VA_BASE + 0x28)))
#define _reg_PORTD_IMR (*((volatile U32 *)(MX1_PORTD_VA_BASE + 0x30)))
#define _reg_PORTD_ISR (*((volatile U32 *)(MX1_PORTD_VA_BASE + 0x34)))
#define _reg_PORTD_PUEN (*((volatile U32 *)(MX1_PORTD_VA_BASE + 0x40)))
#define _reg_INTENNUM (*((volatile U32 *)(0xf0223008)))
#define _reg_INTENABLEH (*((volatile U32 *)(0xf0223010)))
#define U32 unsigned long
/* The base_addr, data_reg_addr, and irq number are board specific.
* The current values are design to run on the Accelent SA1110 IDP
* NOTE: values need to modify for different development boards
*/
static int base_addr = 0xf4000000;
static int data_reg_addr = 0xf4000001;
static int irq = 62;
/* forware declaration */
int SL11StartXaction(hci_t *hci, __u8 addr, __u8 epaddr, int pid, int len,
int toggle, int slow, int urb_state);
static int sofWaitCnt =0;
MODULE_PARM(urb_debug,"i");
MODULE_PARM_DESC(urb_debug,"debug urb messages, default is 0 (no)");
MODULE_PARM(base_addr,"i");
MODULE_PARM_DESC(base_addr,"sl811 base address 0xd3800000");
MODULE_PARM(data_reg_addr,"i");
MODULE_PARM_DESC(data_reg_addr,"sl811 data register address 0xd3810000");
MODULE_PARM(irq,"i");
MODULE_PARM_DESC(irq,"IRQ 34 (default)");
static int hc_reset (hci_t * hci);
/*******************************************************************/
void set_interrupt(void)
{
_reg_PORTD_GIUS |= 0x00000040; // select GPIO - 6th pin
_reg_PORTD_DDIR &= 0xFFFFFFbF; // config as input
_reg_PORTD_IMR |= 0x00000040; // enable interrupt
_reg_PORTD_ICR1 &= 0xFFFFeFFF; // config as positive edge trigger
_reg_PORTD_ICR1 |= 0x2000;
_reg_PORTD_PUEN |= 0xFFFFFFBF; // pull up enable interrupt
_reg_INTENNUM=62;
_reg_INTENABLEH |=1<<30;
}
void Clear_interrupt(void)
{
_reg_PORTD_ISR = 0x00000040;
}
/***************************************************************************
* Function Name : SL811Read
*
* Read a byte of data from the SL811H/SL11H
*
* Input: hci = data structure for the host controller
* offset = address of SL811/SL11H register or memory
*
* Return: data
**************************************************************************/
char SL811Read(hci_t *hci, char offset)
{
char data;
// writeb(offset, base_addr);
//wmb();
// data = readb (data_reg_addr);
//rmb();
*((volatile unsigned char *)0xf4000000)=offset;
wmb();
data= *((volatile unsigned char *)0xf4000001);
rmb();
return (data);
}
/***************************************************************************
* Function Name : SL811Write
*
* Write a byte of data to the SL811H/SL11H
*
* Input: hci = data structure for the host controller
* offset = address of SL811/SL11H register or memory
* data = the data going to write to SL811H
*
* Return: none
**************************************************************************/
void SL811Write(hci_t *hci, char offset, char data)
{
// writeb(offset, base_addr);
// writeb(data, data_reg_addr);
// wmb();
*((volatile unsigned char *)0xf4000000)=offset;
*((volatile unsigned char *)0xf4000001)=data;
wmb();
}
/***************************************************************************
* Function Name : SL811BufRead
*
* Read consecutive bytes of data from the SL811H/SL11H buffer
*
* Input: hci = data structure for the host controller
* offset = SL811/SL11H register offset
* buf = the buffer where the data will store
* size = number of bytes to read
*
* Return: none
**************************************************************************/
void SL811BufRead(hci_t *hci, short offset, char *buf, short size)
{
hcipriv_t *hp = &hci->hp;
if( size <= 0)
return;
// writeb((char) offset, hp->hcport);
*((volatile unsigned char *)0xf4000000)=(char)offset;
wmb();
DBGDATAR ("SL811BufRead: offset = 0x%x, data = ", offset);
while (size--)
{
// *buf++ = (char)readb(hp->hcport2);
*buf++=*((volatile unsigned char *)0xf4000001);
DBGDATAR ("0x%x ", *(buf-1));
rmb();
}
DBGDATAR ("\n");
}
/***************************************************************************
* Function Name : SL811BufWrite
*
* Write consecutive bytes of data to the SL811H/SL11H buffer
*
* Input: hci = data structure for the host controller
* offset = SL811/SL11H register offset
* buf = the data buffer
* size = number of bytes to write
*
* Return: none
**************************************************************************/
void SL811BufWrite(hci_t *hci, short offset, char *buf, short size)
{
hcipriv_t *hp = &hci->hp;
if(size<=0)
return;
// writeb((char) offset, hp->hcport);
*((volatile unsigned char*)0xf4000000)=(char)offset;
wmb();
DBGDATAW ("SL811BufWrite: offset = 0x%x, data = ", offset);
while (size--)
{
DBGDATAW ("0x%x ", *buf);
// writeb(*buf, hp->hcport2);
*((volatile unsigned char *)0xf4000001)=*buf;
wmb();
buf++;
}
DBGDATAW ("\n");
}
/***********************************