M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
#
# Makefile for the pehci driver (if driver is inside kernel tree).
#
obj-$(CONFIG_USB_PEHCI_HCD) += hal/ host/
@@ -0,0 +1,6 @@
#
# Makefile for the pehci driver (if driver is inside kernel tree).
#
obj-$(CONFIG_USB_PEHCI_HCD) += hal_msm.o
@@ -0,0 +1,313 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : hal
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a hardware abstraction layer header file.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#ifndef HAL_INTF_H
#define HAL_INTF_H
/* Specify package here instead of including package.h */
/* #include "package.h" */
#define HCD_PACKAGE
#define NON_PCI
//#define PXA300
//#define MSEC_INT_BASED
#ifdef MSEC_INT_BASED
#define THREAD_BASED
#endif
#ifndef DATABUS_WIDTH_16
#define DATABUS_WIDTH_16
#endif
#ifdef DATABUS_WIDTH_16
/*DMA SUPPORT */
/* #define ENABLE_PLX_DMA */
//#undef ENABLE_PLX_DMA//PXA300
#endif
//#define EDGE_INTERRUPT
//#define POL_HIGH_INTERRUPT
#define DMA_BUF_SIZE (4096 * 2)
#define ISP1763_CHIPID 0x176320
/* Values for id_flags filed of isp1763_driver_t */
#define ISP1763_HC 0 /* Host Controller Driver */
#define ISP1763_DC 1 /* Device Controller Driver */
#define ISP1763_OTG 2 /* Otg Controller Driver */
#define ISP1763_LAST_DEV (ISP1763_OTG + 1)
#define ISP1763_1ST_DEV (ISP1763_HC)
#ifdef PXA300
#define HC_SPARAMS_REG (0x04<<1) /* Structural Parameters Register */
#define HC_CPARAMS_REG (0x08<<1) /* Capability Parameters Register */
#define HC_USBCMD_REG (0x8C<<1) /* USB Command Register */
#define HC_USBSTS_REG (0x90<<1) /* USB Status Register */
#define HC_INTERRUPT_REG_EHCI (0x94<<1) /* INterrupt Enable Register */
#define HC_FRINDEX_REG (0x98<<1) /* Frame Index Register */
#define HC_CONFIGFLAG_REG (0x9C<<1) /* Conigured Flag Register */
#define HC_PORTSC1_REG (0xA0<<1) /* Port Status Control for Port1 */
/*ISO Transfer Registers */
#define HC_ISO_PTD_DONEMAP_REG (0xA4<<1) /* ISO PTD Done Map Register */
#define HC_ISO_PTD_SKIPMAP_REG (0xA6<<1) /* ISO PTD Skip Map Register */
#define HC_ISO_PTD_LASTPTD_REG (0xA8<<1) /* ISO PTD Last PTD Register */
/*INT Transfer Registers */
#define HC_INT_PTD_DONEMAP_REG (0xAA<<1) /* INT PTD Done Map Register */
#define HC_INT_PTD_SKIPMAP_REG (0xAC<<1) /* INT PTD Skip Map Register */
#define HC_INT_PTD_LASTPTD_REG (0xAE<<1) /* INT PTD Last PTD Register */
/*ATL Transfer Registers */
#define HC_ATL_PTD_DONEMAP_REG (0xB0<<1) /* ATL PTD Last PTD Register */
#define HC_ATL_PTD_SKIPMAP_REG (0xB2<<1) /* ATL PTD Last PTD Register */
#define HC_ATL_PTD_LASTPTD_REG (0xB4<<1) /* ATL PTD Last PTD Register */
/*General Purpose Registers */
#define HC_HW_MODE_REG (0x0C<<1) /* H/W Mode Register */
#define HC_CHIP_ID_REG (0x70<<1) /* Chip ID Register */
#define HC_SCRATCH_REG (0x78<<1) /* Scratch Register */
#define HC_RESET_REG (0xB8<<1) /* HC Reset Register */
#define HC_HWMODECTRL_REG (0xB6<<1)
#define HC_UNLOCK_DEVICE (0x7C<<1)
/* Interrupt Registers */
#define HC_INTERRUPT_REG (0xD4<<1) /* Interrupt Register */
#define HC_INTENABLE_REG (0xD6<<1) /* Interrupt enable Register */
#define HC_ISO_IRQ_MASK_OR_REG (0xD8<<1) /* ISO Mask OR Register */
#define HC_INT_IRQ_MASK_OR_REG (0xDA<<1) /* INT Mask OR Register */
#define HC_ATL_IRQ_MASK_OR_REG (0xDC<<1) /* ATL Mask OR Register */
#define HC_ISO_IRQ_MASK_AND_REG (0xDE<<1) /* ISO Mask AND Register */
#define HC_INT_IRQ_MASK_AND_REG (0xE0<<1) /* INT Mask AND Register */
#define HC_ATL_IRQ_MASK_AND_REG (0xE2<<1) /* ATL Mask AND Register */
/*power control reg */
#define HC_POWER_DOWN_CONTROL_REG (0xD0<<1)
/*RAM Registers */
#define HC_DMACONFIG_REG (0xBC<<1) /* DMA Config Register */
#define HC_MEM_READ_REG (0xC4<<1) /* Memory Register */
#define HC_DATA_REG (0xC6<<1) /* Data Register */
#define OTG_CTRL_SET_REG (0xE4<<1)
#define OTG_CTRL_CLEAR_REG (0xE6<<1)
#define OTG_SOURCE_REG (0xE8<<1)
#define OTG_INTR_EN_F_SET_REG (0xF0<<1)
#define OTG_INTR_EN_R_SET_REG (0xF4<<1) /* OTG Interrupt Enable Rise register */
#else
#define HC_SPARAMS_REG 0x04 /* Structural Parameters Register */
#define HC_CPARAMS_REG 0x08 /* Capability Parameters Register */
#define HC_USBCMD_REG 0x8C /* USB Command Register */
#define HC_USBSTS_REG 0x90 /* USB Status Register */
#define HC_INTERRUPT_REG_EHCI 0x94 /* INterrupt Enable Register */
#define HC_FRINDEX_REG 0x98 /* Frame Index Register */
#define HC_CONFIGFLAG_REG 0x9C /* Conigured Flag Register */
#define HC_PORTSC1_REG 0xA0 /* Port Status Control for Port1 */
/*ISO Transfer Registers */
#define HC_ISO_PTD_DONEMAP_REG 0xA4 /* ISO PTD Done Map Register */
#define HC_ISO_PTD_SKIPMAP_REG 0xA6 /* ISO PTD Skip Map Register */
#define HC_ISO_PTD_LASTPTD_REG 0xA8 /* ISO PTD Last PTD Register */
/*INT Transfer Registers */
#define HC_INT_PTD_DONEMAP_REG 0xAA /* INT PTD Done Map Register */
#define HC_INT_PTD_SKIPMAP_REG 0xAC /* INT PTD Skip Map Register */
#define HC_INT_PTD_LASTPTD_REG 0xAE /* INT PTD Last PTD Register */
/*ATL Transfer Registers */
#define HC_ATL_PTD_DONEMAP_REG 0xB0 /* ATL PTD Last PTD Register */
#define HC_ATL_PTD_SKIPMAP_REG 0xB2 /* ATL PTD Last PTD Register */
#define HC_ATL_PTD_LASTPTD_REG 0xB4 /* ATL PTD Last PTD Register */
/*General Purpose Registers */
#define HC_HW_MODE_REG 0x0C //0xB6 /* H/W Mode Register */
#define HC_CHIP_ID_REG 0x70 /* Chip ID Register */
#define HC_SCRATCH_REG 0x78 /* Scratch Register */
#define HC_RESET_REG 0xB8 /* HC Reset Register */
#define HC_HWMODECTRL_REG 0xB6 //0x0C /* H/W Mode control Register */
#define HC_UNLOCK_DEVICE 0x7C
/* Interrupt Registers */
#define HC_INTERRUPT_REG 0xD4 /* Interrupt Register */
#define HC_INTENABLE_REG 0xD6 /* Interrupt enable Register */
#define HC_ISO_IRQ_MASK_OR_REG 0xD8 /* ISO Mask OR Register */
#define HC_INT_IRQ_MASK_OR_REG 0xDA /* INT Mask OR Register */
#define HC_ATL_IRQ_MASK_OR_REG 0xDC /* ATL Mask OR Register */
#define HC_ISO_IRQ_MASK_AND_REG 0xDE /* ISO Mask AND Register */
#define HC_INT_IRQ_MASK_AND_REG 0xE0 /* INT Mask AND Register */
#define HC_ATL_IRQ_MASK_AND_REG 0xE2 /* ATL Mask AND Register */
/*power control reg */
#define HC_POWER_DOWN_CONTROL_REG 0xD0
/*RAM Registers */
#define HC_DMACONFIG_REG 0xBC /* DMA Config Register */
#define HC_MEM_READ_REG 0xC4 /* Memory Register */
#define HC_DATA_REG 0xC6 /* Data Register */
#define OTG_CTRL_SET_REG 0xE4
#define OTG_CTRL_CLEAR_REG 0xE6
#define OTG_SOURCE_REG 0xE8
#define OTG_INTR_EN_F_SET_REG 0xF0 /* OTG Interrupt Enable Fall register */
#define OTG_INTR_EN_R_SET_REG 0xF4 /* OTG Interrupt Enable Rise register */
#endif
#define OTG_CTRL_DPPULLUP 0x0001
#define OTG_CTRL_DPPULLDOWN 0x0002
#define OTG_CTRL_DMPULLDOWN 0x0004
#define OTG_CTRL_VBUS_DRV 0x0010
#define OTG_CTRL_VBUS_DISCHRG 0x0020
#define OTG_CTRL_VBUS_CHRG 0x0040
#define OTG_CTRL_SW_SEL_HC_DC 0x0080
#define OTG_CTRL_BDIS_ACON_EN 0x0100
#define OTG_CTRL_OTG_SE0_EN 0x0200
#define OTG_CTRL_OTG_DISABLE 0x0400
#define OTG_CTRL_VBUS_DRV_PORT2 0x1000
#define OTG_CTRL_SW_SEL_HC_2 0x8000
/*interrupt count and buffer status register*/
#ifdef PXA300
#define HC_BUFFER_STATUS_REG (0xBA<<1)
#define HC_INT_THRESHOLD_REG (0xC8<<1)
#else
#define HC_BUFFER_STATUS_REG 0xBA
#define HC_INT_THRESHOLD_REG 0xC8
#endif
#define HC_OTG_INTERRUPT 0x400
#ifdef PXA300
#define DC_CHIPID (0x70<<1)
#else
#define DC_CHIPID 0x70
#endif
#ifdef PXA300
#define FPGA_CONFIG_REG (0x100<<1)
#else
#define FPGA_CONFIG_REG 0x100
#endif
#define HC_HW_MODE_GOBAL_INTR_ENABLE 0x01
#define HC_HW_MODE_INTR_EDGE 0x02
#define HC_HW_MODE_INTR_POLARITY_HIGH 0x04
#define HC_HW_MODE_LOCK 0x08
#define HC_HW_MODE_DATABUSWIDTH_8 0x10
#define HC_HW_MODE_DREQ_POL_HIGH 0x20
#define HC_HW_MODE_DACK_POL_HIGH 0x40
#define HC_HW_MODE_COMN_INT 0x80
struct isp1763_driver;
typedef struct _isp1763_id {
u16 idVendor;
u16 idProduct;
u32 driver_info;
} isp1763_id;
typedef struct isp1763_dev {
/*added for pci device */
#ifdef NON_PCI
struct platform_device *dev;
#else /*PCI*/
struct pci_dev *pcidev;
#endif
struct isp1763_driver *driver; /* which driver has allocated this device */
void *driver_data; /* data private to the host controller driver */
void *otg_driver_data; /*data private for otg controler */
unsigned char index; /* local controller (HC/DC/OTG) */
unsigned int irq; /*Interrupt Channel allocated for this device */
void (*handler) (struct isp1763_dev * dev, void *isr_data); /* Interrupt Serrvice Routine */
void *isr_data; /* isr data of the driver */
unsigned long int_reg; /* Interrupt register */
unsigned long alt_int_reg; /* Interrupt register 2 */
unsigned long start;
unsigned long length;
struct resource *mem_res;
unsigned long io_base; /* Start Io address space for this device */
unsigned long io_len; /* IO address space length for this device */
unsigned long chip_id; /* Chip Id */
char name[80]; /* device name */
int active; /* device status */
/* DMA resources should come here */
unsigned long dma;
u8 *baseaddress; /*base address for i/o ops */
u8 *dmabase;
isp1763_id *id;
} isp1763_dev_t;
typedef struct isp1763_driver {
char *name;
unsigned long index; /* HC or DC or OTG */
isp1763_id *id; /*device ids */
int (*probe) (struct isp1763_dev * dev, isp1763_id * id); /* New device inserted */
void (*remove) (struct isp1763_dev * dev); /* Device removed (NULL if not a hot-plug capable driver) */
void (*suspend) (struct isp1763_dev * dev); /* Device suspended */
void (*resume) (struct isp1763_dev * dev); /* Device woken up */
void (*remotewakeup) (struct isp1763_dev *dev); /* Remote Wakeup */
void (*powerup) (struct isp1763_dev *dev); /* Device poweup mode */
void (*powerdown) (struct isp1763_dev *dev); /* Device power down mode */
} isp_1763_driver_t;
struct usb_device *phci_register_otg_device(struct isp1763_dev *dev);
/*otg exported function from host*/
int phci_suspend_otg_port(struct isp1763_dev *dev, u32 command);
int phci_enumerate_otg_port(struct isp1763_dev *dev, u32 command);
extern int isp1763_register_driver(struct isp1763_driver *drv);
extern void isp1763_unregister_driver(struct isp1763_driver *drv);
extern int isp1763_request_irq(void (*handler)(struct isp1763_dev * dev, void *isr_data),
struct isp1763_dev *dev, void *isr_data);
extern void isp1763_free_irq(struct isp1763_dev *dev, void *isr_data);
extern u32 isp1763_reg_read32(isp1763_dev_t * dev, u16 reg, u32 data);
extern u16 isp1763_reg_read16(isp1763_dev_t * dev, u16 reg, u16 data);
extern u8 isp1763_reg_read8(struct isp1763_dev *dev, u16 reg, u8 data);
extern void isp1763_reg_write32(isp1763_dev_t * dev, u16 reg, u32 data);
extern void isp1763_reg_write16(isp1763_dev_t * dev, u16 reg, u16 data);
extern void isp1763_reg_write8(struct isp1763_dev *dev, u16 reg, u8 data);
extern int isp1763_mem_read(isp1763_dev_t * dev, u32 start_add,
u32 end_add, u32 * buffer, u32 length, u16 dir);
extern int isp1763_mem_write(isp1763_dev_t * dev, u32 start_add,
u32 end_add, u32 * buffer, u32 length, u16 dir);
#endif /* __HAL_INTF_H__ */
+748
View File
@@ -0,0 +1,748 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux HCD Controller driver : hal
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is the main hardware abstraction layer file. Hardware initialization, interupt
* processing and read/write routines are handled here.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/usb.h>
#include <linux/gpio.h>
#include <mach/board.h>
#include <linux/poll.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
/*--------------------------------------------------------------*
* linux system include files
*--------------------------------------------------------------*/
#include "hal_msm.h"
#include "../hal/hal_intf.h"
#include "../hal/isp1763.h"
/*--------------------------------------------------------------*
* Local variable Definitions
*--------------------------------------------------------------*/
struct isp1763_dev isp1763_loc_dev[ISP1763_LAST_DEV];
/*--------------------------------------------------------------*
* Local # Definitions
*--------------------------------------------------------------*/
#define PCI_ACCESS_RETRY_COUNT 20
#define ISP1763_DRIVER_NAME "isp1763_usb"
/*--------------------------------------------------------------*
* Local Function
*--------------------------------------------------------------*/
static int __devexit isp1763_remove(struct platform_device *pdev);
static int __devinit isp1763_probe(struct platform_device *pdev);
/*--------------------------------------------------------------*
* Platform Driver Interface Functions
*--------------------------------------------------------------*/
static struct platform_driver isp1763_usb_driver = {
.remove = __exit_p(isp1763_remove),
.driver = {
.name = ISP1763_DRIVER_NAME,
.owner = THIS_MODULE,
},
};
/*--------------------------------------------------------------*
* ISP1763 Read write routine
*--------------------------------------------------------------*/
/*
* EBI2 on 8660 ignores the first bit and shifts the address by
* one bit to the right.
* Hence, shift left all the register addresses before accessing
* them over EBI2.
* This logic applies only for the register read/writes, for
* read/write from ISP memory this conversion is not needed
* as the ISP obtains the memory address from 'memory' register
*/
/* Write a 32 bit Register of isp1763 */
void
isp1763_reg_write32(struct isp1763_dev *dev, u16 reg, u32 data)
{
/* Write the 32bit to the register address given to us */
reg <<= 1;
#ifdef DATABUS_WIDTH_16
writew((u16) data, dev->baseaddress + ((reg)));
writew((u16) (data >> 16), dev->baseaddress + (((reg + 4))));
#else
writeb((u8) data, dev->baseaddress + (reg));
writeb((u8) (data >> 8), dev->baseaddress + ((reg + 1)));
writeb((u8) (data >> 16), dev->baseaddress + ((reg + 2)));
writeb((u8) (data >> 24), dev->baseaddress + ((reg + 3)));
#endif
}
EXPORT_SYMBOL(isp1763_reg_write32);
/* Read a 32 bit Register of isp1763 */
u32
isp1763_reg_read32(struct isp1763_dev *dev, u16 reg, u32 data)
{
#ifdef DATABUS_WIDTH_16
u16 wvalue1, wvalue2;
#else
u8 bval1, bval2, bval3, bval4;
#endif
data = 0;
reg <<= 1;
#ifdef DATABUS_WIDTH_16
wvalue1 = readw(dev->baseaddress + ((reg)));
wvalue2 = readw(dev->baseaddress + (((reg + 4))));
data |= wvalue2;
data <<= 16;
data |= wvalue1;
#else
bval1 = readb(dev->baseaddress + (reg));
bval2 = readb(dev->baseaddress + (reg + 1));
bval3 = readb(dev->baseaddress + (reg + 2));
bval4 = readb(dev->baseaddress + (reg + 3));
data = 0;
data |= bval4;
data <<= 8;
data |= bval3;
data <<= 8;
data |= bval2;
data <<= 8;
data |= bval1;
#endif
return data;
}
EXPORT_SYMBOL(isp1763_reg_read32);
/* Read a 16 bit Register of isp1763 */
u16
isp1763_reg_read16(struct isp1763_dev * dev, u16 reg, u16 data)
{
reg <<= 1;
#ifdef DATABUS_WIDTH_16
data = readw(dev->baseaddress + ((reg)));
#else
u8 bval1, bval2;
bval1 = readb(dev->baseaddress + (reg));
if (reg == HC_DATA_REG){
bval2 = readb(dev->baseaddress + (reg));
} else {
bval2 = readb(dev->baseaddress + ((reg + 1)));
}
data = 0;
data |= bval2;
data <<= 8;
data |= bval1;
#endif
return data;
}
EXPORT_SYMBOL(isp1763_reg_read16);
/* Write a 16 bit Register of isp1763 */
void
isp1763_reg_write16(struct isp1763_dev *dev, u16 reg, u16 data)
{
reg <<= 1;
#ifdef DATABUS_WIDTH_16
writew(data, dev->baseaddress + ((reg)));
#else
writeb((u8) data, dev->baseaddress + (reg));
if (reg == HC_DATA_REG){
writeb((u8) (data >> 8), dev->baseaddress + (reg));
}else{
writeb((u8) (data >> 8), dev->baseaddress + ((reg + 1)));
}
#endif
}
EXPORT_SYMBOL(isp1763_reg_write16);
/* Read a 8 bit Register of isp1763 */
u8
isp1763_reg_read8(struct isp1763_dev *dev, u16 reg, u8 data)
{
reg <<= 1;
data = readb((dev->baseaddress + (reg)));
return data;
}
EXPORT_SYMBOL(isp1763_reg_read8);
/* Write a 8 bit Register of isp1763 */
void
isp1763_reg_write8(struct isp1763_dev *dev, u16 reg, u8 data)
{
reg <<= 1;
writeb(data, (dev->baseaddress + (reg)));
}
EXPORT_SYMBOL(isp1763_reg_write8);
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_mem_read
*
* Memory read using PIO method.
*
* Input: struct isp1763_driver *drv --> Driver structure.
* u32 start_add --> Starting address of memory
* u32 end_add ---> End address
*
* u32 * buffer --> Buffer pointer.
* u32 length ---> Length
* u16 dir ---> Direction ( Inc or Dec)
*
* Output int Length ----> Number of bytes read
*
* Called by: system function
*
*
*--------------------------------------------------------------*/
/* Memory read function PIO */
int
isp1763_mem_read(struct isp1763_dev *dev, u32 start_add,
u32 end_add, u32 * buffer, u32 length, u16 dir)
{
u8 *one = (u8 *) buffer;
u16 *two = (u16 *) buffer;
u32 a = (u32) length;
u32 w;
u32 w2;
if (buffer == 0) {
printk("Buffer address zero\n");
return 0;
}
isp1763_reg_write16(dev, HC_MEM_READ_REG, start_add);
/* This delay requirement comes from the ISP1763A programming guide */
ndelay(100);
last:
w = isp1763_reg_read16(dev, HC_DATA_REG, w);
w2 = isp1763_reg_read16(dev, HC_DATA_REG, w);
w2 <<= 16;
w = w | w2;
if (a == 1) {
*one = (u8) w;
return 0;
}
if (a == 2) {
*two = (u16) w;
return 0;
}
if (a == 3) {
*two = (u16) w;
two += 1;
w >>= 16;
*two = (u8) (w);
return 0;
}
while (a > 0) {
*buffer = w;
a -= 4;
if (a <= 0) {
break;
}
if (a < 4) {
buffer += 1;
one = (u8 *) buffer;
two = (u16 *) buffer;
goto last;
}
buffer += 1;
w = isp1763_reg_read16(dev, HC_DATA_REG, w);
w2 = isp1763_reg_read16(dev, HC_DATA_REG, w);
w2 <<= 16;
w = w | w2;
}
return ((a < 0) || (a == 0)) ? 0 : (-1);
}
EXPORT_SYMBOL(isp1763_mem_read);
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_mem_write
*
* Memory write using PIO method.
*
* Input: struct isp1763_driver *drv --> Driver structure.
* u32 start_add --> Starting address of memory
* u32 end_add ---> End address
*
* u32 * buffer --> Buffer pointer.
* u32 length ---> Length
* u16 dir ---> Direction ( Inc or Dec)
*
* Output int Length ----> Number of bytes read
*
* Called by: system function
*
*
*--------------------------------------------------------------*/
/* Memory read function IO */
int
isp1763_mem_write(struct isp1763_dev *dev,
u32 start_add, u32 end_add, u32 * buffer, u32 length, u16 dir)
{
int a = length;
u8 one = (u8) (*buffer);
u16 two = (u16) (*buffer);
isp1763_reg_write16(dev, HC_MEM_READ_REG, start_add);
/* This delay requirement comes from the ISP1763A programming guide */
ndelay(100);
if (a == 1) {
isp1763_reg_write16(dev, HC_DATA_REG, one);
return 0;
}
if (a == 2) {
isp1763_reg_write16(dev, HC_DATA_REG, two);
return 0;
}
while (a > 0) {
isp1763_reg_write16(dev, HC_DATA_REG, (u16) (*buffer));
if (a >= 3)
isp1763_reg_write16(dev, HC_DATA_REG,
(u16) ((*buffer) >> 16));
start_add += 4;
a -= 4;
if (a <= 0)
break;
buffer += 1;
}
return ((a < 0) || (a == 0)) ? 0 : (-1);
}
EXPORT_SYMBOL(isp1763_mem_write);
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_register_driver
*
* This function is used by top driver (OTG, HCD, DCD) to register
* their communication functions (probe, remove, suspend, resume) using
* the drv data structure.
* This function will call the probe function of the driver if the ISP1763
* corresponding to the driver is enabled
*
* Input: struct isp1763_driver *drv --> Driver structure.
* Output result
* 0= complete
* 1= error.
*
* Called by: system function module_init
*
*
*--------------------------------------------------------------*/
int
isp1763_register_driver(struct isp1763_driver *drv)
{
struct isp1763_dev *dev;
int result = -EINVAL;
hal_entry("%s: Entered\n", __FUNCTION__);
info("isp1763_register_driver(drv=%p)\n", drv);
if (!drv) {
return -EINVAL;
}
dev = &isp1763_loc_dev[drv->index];
if (!dev->baseaddress)
return -EINVAL;
dev->active = 1; /* set the driver as active*/
if (drv->probe) {
result = drv->probe(dev, drv->id);
} else {
printk("%s no probe function for indes %d \n", __FUNCTION__,
(int)drv->index);
}
if (result >= 0) {
pr_debug(KERN_INFO __FILE__ ": Registered Driver %s\n",
drv->name);
dev->driver = drv;
}
hal_entry("%s: Exit\n", __FUNCTION__);
return result;
} /* End of isp1763_register_driver */
EXPORT_SYMBOL(isp1763_register_driver);
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_unregister_driver
*
* This function is used by top driver (OTG, HCD, DCD) to de-register
* their communication functions (probe, remove, suspend, resume) using
* the drv data structure.
* This function will check whether the driver is registered or not and
* call the remove function of the driver if registered
*
* Input: struct isp1763_driver *drv --> Driver structure.
* Output result
* 0= complete
* 1= error.
*
* Called by: system function module_init
*
*
*--------------------------------------------------------------*/
void
isp1763_unregister_driver(struct isp1763_driver *drv)
{
struct isp1763_dev *dev;
hal_entry("%s: Entered\n", __FUNCTION__);
info("isp1763_unregister_driver(drv=%p)\n", drv);
dev = &isp1763_loc_dev[drv->index];
if (dev->driver == drv) {
/* driver registered is same as the requestig driver */
drv->remove(dev);
dev->driver = NULL;
info(": De-registered Driver %s\n", drv->name);
return;
}
hal_entry("%s: Exit\n", __FUNCTION__);
} /* End of isp1763_unregister_driver */
EXPORT_SYMBOL(isp1763_unregister_driver);
/*--------------------------------------------------------------*
* ISP1763 Platform driver interface routine.
*--------------------------------------------------------------*/
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_module_init
*
* This is the module initialization function. It registers to
* driver for a isp1763 platform device. And also resets the
* internal data structures.
*
* Input: void
* Output result
* 0= complete
* 1= error.
*
* Called by: system function module_init
*
*
*
-------------------------------------------------------------------*/
static int __init
isp1763_module_init(void)
{
int result = 0;
hal_entry("%s: Entered\n", __FUNCTION__);
pr_debug(KERN_NOTICE "+isp1763_module_init\n");
memset(isp1763_loc_dev, 0, sizeof(isp1763_loc_dev));
result = platform_driver_probe(&isp1763_usb_driver, isp1763_probe);
pr_debug(KERN_NOTICE "-isp1763_module_init\n");
hal_entry("%s: Exit\n", __FUNCTION__);
return result;
}
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_module_cleanup
*
* This is the module cleanup function. It de-registers the
* Platform driver and resets the internal data structures.
*
* Input: void
* Output void
*
* Called by: system function module_cleanup
*
*
*
--------------------------------------------------------------*/
static void __exit
isp1763_module_cleanup(void)
{
pr_debug("Hal Module Cleanup\n");
platform_driver_unregister(&isp1763_usb_driver);
memset(isp1763_loc_dev, 0, sizeof(isp1763_loc_dev));
}
void dummy_mem_read(struct isp1763_dev *dev)
{
u32 w = 0;
isp1763_reg_write16(dev, HC_MEM_READ_REG, 0x0400);
w = isp1763_reg_read16(dev, HC_DATA_REG, w);
pr_debug("dummy_read DONE: %x\n", w);
msleep(10);
}
/*--------------------------------------------------------------*
*
* Module dtatils: isp1763_probe
*
* probe function of ISP1763
* This function is called from module_init if the corresponding platform
* device is present. This function initializes the information
* for the Host Controller with the assigned resources and tests the register
* access to the controller and do a software reset and makes it ready
* for the driver to play with. It also calls setup_gpio passed from pdata
* to setup GPIOs (e.g. used for IRQ and RST lines).
*
* Input:
* struct platform_device *dev ----> Platform Device structure
* Output void
*
* Called by: system function module_cleanup
*
*
*
--------------------------------------------------------------**/
static int __devinit
isp1763_probe(struct platform_device *pdev)
{
u32 reg_data = 0;
struct isp1763_dev *loc_dev;
int status = 1;
u32 hwmodectrl = 0;
u16 us_reset_hc = 0;
u32 chipid = 0;
struct isp1763_platform_data *pdata = pdev->dev.platform_data;
hal_entry("%s: Entered\n", __FUNCTION__);
hal_init(("isp1763_probe(dev=%p)\n", dev));
loc_dev = &(isp1763_loc_dev[ISP1763_HC]);
loc_dev->dev = pdev;
/* Get the Host Controller IO and INT resources */
loc_dev->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!loc_dev->mem_res) {
pr_err("%s: failed to get platform resource mem\n", __func__);
return -ENODEV;
}
loc_dev->baseaddress = ioremap_nocache(loc_dev->mem_res->start,
resource_size(loc_dev->mem_res));
if (!loc_dev->baseaddress) {
pr_err("%s: ioremap failed\n", __func__);
status = -ENOMEM;
goto put_mem_res;
}
pr_info("%s: ioremap done at: %x\n", __func__,
(int)loc_dev->baseaddress);
loc_dev->irq = platform_get_irq(pdev, 0);
if (!loc_dev->irq) {
pr_err("%s: platform_get_irq failed\n", __func__);
status = -ENODEV;
goto free_regs;
}
loc_dev->index = ISP1763_HC; /*zero */
loc_dev->length = resource_size(loc_dev->mem_res);
hal_init(("isp1763 HC MEM Base= %p irq = %d\n",
loc_dev->baseaddress, loc_dev->irq));
/* Setup GPIOs and isssue RESET_N to Controller */
if (pdata->setup_gpio)
if (pdata->setup_gpio(1))
pr_err("%s: Failed to setup GPIOs for isp1763\n",
__func__);
if (pdata->reset_gpio) {
gpio_set_value(pdata->reset_gpio, 0);
msleep(10);
gpio_set_value(pdata->reset_gpio, 1);
} else {
pr_err("%s: Failed to issue RESET_N to isp1763\n", __func__);
}
dummy_mem_read(loc_dev);
chipid = isp1763_reg_read32(loc_dev, DC_CHIPID, chipid);
pr_info("START: chip id:%x\n", chipid);
/*reset the host controller */
pr_debug("RESETTING\n");
us_reset_hc |= 0x1;
isp1763_reg_write16(loc_dev, 0xB8, us_reset_hc);
msleep(20);
us_reset_hc = 0;
us_reset_hc |= 0x2;
isp1763_reg_write16(loc_dev, 0xB8, us_reset_hc);
chipid = isp1763_reg_read32(loc_dev, DC_CHIPID, chipid);
pr_info("after HC reset, chipid:%x\n", chipid);
msleep(20);
hwmodectrl = isp1763_reg_read16(loc_dev, HC_HWMODECTRL_REG, hwmodectrl);
pr_debug("Mode Ctrl Value b4 setting buswidth: %x\n", hwmodectrl);
#ifdef DATABUS_WIDTH_16
hwmodectrl &= 0xFFEF; /*enable the 16 bit bus */
#else
pr_debug("Setting 8-BIT mode\n");
hwmodectrl |= 0x0010; /*enable the 8 bit bus */
#endif
isp1763_reg_write16(loc_dev, HC_HWMODECTRL_REG, hwmodectrl);
pr_debug("writing 0x%x to hw mode reg\n", hwmodectrl);
hwmodectrl = isp1763_reg_read16(loc_dev, HC_HWMODECTRL_REG, hwmodectrl);
msleep(100);
pr_debug("Mode Ctrl Value after setting buswidth: %x\n", hwmodectrl);
chipid = isp1763_reg_read32(loc_dev, DC_CHIPID, chipid);
pr_debug("after setting HW MODE to 8bit, chipid:%x\n", chipid);
hal_init(("isp1763 DC MEM Base= %lx irq = %d\n",
loc_dev->io_base, loc_dev->irq));
reg_data = isp1763_reg_read16(loc_dev, HC_SCRATCH_REG, reg_data);
pr_debug("Scratch register is 0x%x\n", reg_data);
reg_data = 0xABCD;
isp1763_reg_write16(loc_dev, HC_SCRATCH_REG, reg_data);
reg_data = isp1763_reg_read16(loc_dev, HC_SCRATCH_REG, reg_data);
pr_debug("After write, Scratch register is 0x%x\n", reg_data);
if (reg_data != 0xABCD) {
pr_err("%s: Scratch register write mismatch!!\n", __func__);
status = -ENODEV;
goto free_gpios;
}
memcpy(loc_dev->name, ISP1763_DRIVER_NAME, sizeof(ISP1763_DRIVER_NAME));
loc_dev->name[sizeof(ISP1763_DRIVER_NAME)] = 0;
pr_debug(KERN_NOTICE "-isp1763_pci_probe\n");
hal_entry("%s: Exit\n", __FUNCTION__);
return 0;
free_gpios:
if (pdata->setup_gpio)
pdata->setup_gpio(0);
free_regs:
iounmap(loc_dev->baseaddress);
put_mem_res:
loc_dev->baseaddress = NULL;
hal_entry("%s: Exit\n", __FUNCTION__);
return status;
} /* End of isp1763_probe */
/*--------------------------------------------------------------*
*
* Module details: isp1763_remove
*
* cleanup function of ISP1763
* This functions de-initializes the local variables, frees GPIOs
* and releases memory resource.
*
* Input:
* struct platform_device *dev ----> Platform Device structure
*
* Output void
*
* Called by: system function module_cleanup
*
*
*
--------------------------------------------------------------*/
static int __devexit
isp1763_remove(struct platform_device *pdev)
{
struct isp1763_dev *loc_dev;
struct isp1763_platform_data *pdata = pdev->dev.platform_data;
hal_init(("isp1763_pci_remove(dev=%p)\n", dev));
loc_dev = &isp1763_loc_dev[ISP1763_HC];
iounmap(loc_dev->baseaddress);
loc_dev->baseaddress = NULL;
if (pdata->setup_gpio)
return pdata->setup_gpio(0);
return 0;
} /* End of isp1763_remove */
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
module_init(isp1763_module_init);
module_exit(isp1763_module_cleanup);
@@ -0,0 +1,85 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : hal
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a hardware abstraction layer header file.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#ifndef HAL_X86_H
#define HAL_X86_H
#define DRIVER_AUTHOR "ST-ERICSSON "
#define DRIVER_DESC "ISP1763 bus driver"
/* Driver tuning, per ST-ERICSSON requirements: */
#define MEM_TO_CHECK 4096 /*bytes, must be multiple of 2 */
/* BIT defines */
#define BIT0 (1 << 0)
#define BIT1 (1 << 1)
#define BIT2 (1 << 2)
#define BIT3 (1 << 3)
#define BIT4 (1 << 4)
#define BIT5 (1 << 5)
#define BIT6 (1 << 6)
#define BIT7 (1 << 7)
#define BIT8 (1 << 8)
#define BIT9 (1 << 9)
#define BIT10 (1 << 10)
#define BIT11 (1 << 11)
#define BIT12 (1 << 12)
#define BIT13 (1 << 13)
#define BIT14 (1 << 14)
#define BIT15 (1 << 15)
#define BIT16 (1 << 16)
#define BIT17 (1 << 17)
#define BIT18 (1 << 18)
#define BIT19 (1 << 19)
#define BIT20 (1 << 20)
#define BIT21 (1 << 21)
#define BIT22 (1 << 22)
#define BIT23 (1 << 23)
#define BIT24 (1 << 24)
#define BIT25 (1 << 26)
#define BIT27 (1 << 27)
#define BIT28 (1 << 28)
#define BIT29 (1 << 29)
#define BIT30 (1 << 30)
#define BIT31 (1 << 31)
/* Definitions Related to Chip Address and CPU Physical Address
* cpu_phy_add: CPU Physical Address , it uses 32 bit data per address
* chip_add : Chip Address, it uses double word(64) bit data per address
*/
#define chip_add(cpu_phy_add) (((cpu_phy_add) - 0x400) / 8)
#define cpu_phy_add(chip_add) ((8 * (chip_add)) + 0x400)
/* for getting end add, and start add, provided we have one address with us */
/* IMPORTANT length hex(base16) and dec(base10) works fine*/
#define end_add(start_add, length) (start_add + (length - 4))
#define start_add(end_add, length) (end_add - (length - 4))
/* Device Registers*/
#define DEV_UNLOCK_REGISTER 0x7C
#define DEV_INTERRUPT_REGISTER 0x18
#define INT_ENABLE_REGISTER 0x14
#endif /*_HAL_X86_H_ */
+227
View File
@@ -0,0 +1,227 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : hal
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a hardware abstraction layer header file.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#ifndef ISP1763_H
#define ISP1763_H
/* For debugging option: ------------------- */
#define PTD_DUMP_SCHEDULE
#undef PTD_DUMP_SCHEDULE
#define PTD_DUMP_COMPLETE
#undef PTD_DUMP_COMPLETE
/* ------------------------------------*/
#define CONFIG_ISO_SUPPORT
#ifdef CONFIG_ISO_SUPPORT
#define ISO_DBG_ENTRY 1
#define ISO_DBG_EXIT 1
#define ISO_DBG_ADDR 1
#define ISO_DBG_DATA 1
#define ISO_DBG_ERR 1
#define ISO_DBG_INFO 1
#if 0 /* Set to 1 to enable isochronous debugging */
#define iso_dbg(category, format, arg...) \
do \
{ \
if(category) \
{ \
printk(format, ## arg); \
} \
} while(0)
#else
#define iso_dbg(category, format, arg...) while(0)
#endif
#endif /* CONFIG_ISO_SUPPORT */
/*Debug For Entry/Exit of the functions */
//#define HCD_DEBUG_LEVEL1
#ifdef HCD_DEBUG_LEVEL1
#define pehci_entry(format, args... ) printk(format, ##args)
#else
#define pehci_entry(format, args...) do { } while(0)
#endif
/*Debug for Port Info and Errors */
//#define HCD_DEBUG_LEVEL2
#ifdef HCD_DEBUG_LEVEL2
#define pehci_print(format, args... ) printk(format, ##args)
#else
#define pehci_print(format, args...) do { } while(0)
#endif
/*Debug For the Port changes and Enumeration */
//#define HCD_DEBUG_LEVEL3
#ifdef HCD_DEBUG_LEVEL3
#define pehci_info(format,arg...) printk(format, ##arg)
#else
#define pehci_info(format,arg...) do {} while (0)
#endif
/*Debug For Transfer flow */
// #define HCD_DEBUG_LEVEL4
#ifdef HCD_DEBUG_LEVEL4
#define pehci_check(format,args...) printk(format, ##args)
#else
#define pehci_check(format,args...)
#endif
/*******************END HOST CONTROLLER**********************************/
/*******************START DEVICE CONTROLLER******************************/
/* For MTP support */
#undef MTP_ENABLE /* Enable to add MTP support; But requires MTP class driver to be present to work */
/*For CHAPTER8 TEST */
#undef CHAPTER8_TEST /* Enable to Pass Chapter 8 Test */
/* Debug Entery/Exit of Function as well as some other Info */
//#define DEV_DEBUG_LEVEL2
#ifdef DEV_DEBUG_LEVEL2
#define dev_print(format,arg...) printk(format, ##arg)
#else
#define dev_print(format,arg...) do {} while (0)
#endif
/*Debug for Interrupt , Registers , device Enable/Disable and some other info */
//#define DEV_DEBUG_LEVEL3
#undef dev_info
#ifdef DEV_DEBUG_LEVEL3
#define dev_info(format,arg...) printk(format, ##arg)
#else
#define dev_info(format,arg...) do {} while (0)
#endif
/*Debug for Tranffer flow , Enumeration and Packet info */
//#define DEV_DEBUG_LEVEL4
#ifdef DEV_DEBUG_LEVEL4
#define dev_check(format,args...) printk(format, ##args)
#else
#define dev_check(format,args...) do{}while(0)
#endif
/*******************END DEVICE CONTROLLER********************************/
/*******************START MSCD*******************************************/
/*Debug Entery/Exit of Function as well as some other Information*/
//#define MSCD_DEBUG_LEVEL2
#ifdef MSCD_DEBUG_LEVEL2
#define mscd_print(format,arg...) printk(format, ##arg)
#else
#define mscd_print(format,arg...) do {} while (0)
#endif
/*Debug for Info */
//#define MSCD_DEBUG_LEVEL3
#ifdef MSCD_DEBUG_LEVEL3
#define mscd_info(format,arg...) printk(format, ##arg)
#else
#define mscd_info(format,arg...) do {} while (0)
#endif
/*******************END MSCD*********************************************/
/*******************START OTG CONTROLLER*********************************/
/*#define OTG */ /*undef for Device only and Host only */
#define ALL_FSM_FLAGS
/*Debug for Entry/Exit and Info */
/* #define OTG_DEBUG_LEVEL1 */
#ifdef OTG_DEBUG_LEVEL1
#define otg_entry(format, args... ) printk(format, ##args)
#else
#define otg_entry(format, args...) do { } while(0)
#endif
/*Debug for State Machine Flow */
/* #define OTG_DEBUG_LEVEL2 */
#ifdef OTG_DEBUG_LEVEL2
#define otg_print(format,arg...) printk(format, ##arg)
#else
#define otg_print(format,arg...) do {} while (0)
#endif
/*Debug for Info */
/* #define OTG_DEBUG_LEVEL3 */
#ifdef OTG_DEBUG_LEVEL3
#define otg_info(format,arg...) printk(format, ##arg)
#else
#define otg_info(format,arg...) do {} while (0)
#endif
/* #define OTG_DEBUG_LEVEL4 */
#ifdef OTG_DEBUG_LEVEL4
#define otg_printB(format,arg...) printk(format, ##arg)
#else
#define otg_printB(format,arg...) do {} while (0)
#endif
/*******************END OTG CONTROLLER***********************************/
/*******************START FOR HAL ***************************************/
#define info pr_debug
#define warn pr_warn
/*Debug For Entry and Exit of the functions */
#undef HAL_DEBUG_LEVEL1
#ifdef HAL_DEBUG_LEVEL1
#define hal_entry(format, args... ) printk(format, ##args)
#else
#define hal_entry(format, args...) do { } while(0)
#endif
/*Debug For Interrupt information */
#undef HAL_DEBUG_LEVEL2
#ifdef HAL_DEBUG_LEVEL2
#define hal_int(format, args... ) printk(format, ##args)
#else
#define hal_int(format, args...) do { } while(0)
#endif
/*Debug For HAL Initialisation and Mem Initialisation */
#undef HAL_DEBUG_LEVEL3
#ifdef HAL_DEBUG_LEVEL3
#define hal_init(format, args... ) printk(format, ##args)
#else
#define hal_init(format, args...) do { } while(0)
#endif
/*******************END FOR HAL*******************************************/
/*******************START FOR ALL CONTROLLERS*****************************/
/*#define CONFIG_USB_OTG */ /*undef for Device only and Host only */
/*#define ISP1763_DEVICE */
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
/*******************END FOR ALL CONTROLLERS*******************************/
#endif
@@ -0,0 +1,6 @@
#
# Makefile for the pehci driver (if driver is inside kernel tree).
#
obj-$(CONFIG_USB_PEHCI_HCD) += pehci.o
File diff suppressed because it is too large Load Diff
+355
View File
@@ -0,0 +1,355 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : host
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a host controller driver file. Memory initialization, allocation, and
* deallocation are handled here.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#ifdef CONFIG_ISO_SUPPORT
/*memory utilization fuctions*/
void
phci_hcd_mem_init(void)
{
int i = 0;
u32 start_addr = 0x1000;
struct isp1763_mem_addr *memaddr;
for (i = 0; i < BLK_TOTAL; i++) {
memaddr = &memalloc[i];
memset(memaddr, 0, sizeof *memaddr);
}
/*initialize block of 128bytes */
for (i = 0; i < BLK_128_; i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_128;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_128;
}
/*initialize block of 256bytes */
for (i = BLK_128_; i < BLK_256_; i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_256;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_256;
}
/*initialize block of 1024bytes */
for (i = BLK_128_ + BLK_256_; i < (BLK_128_ + BLK_256_ + BLK_1024_);
i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_1024;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_1024;
}
/*initialize block of 2kbytes */
for (i = (BLK_128_ + BLK_256_ + BLK_1024_);
i < (BLK_128_ + BLK_256_ + BLK_1024_ + BLK_2048_); i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_2048;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_2048;
}
/* initialize block of 4kbytes */
for (i = (BLK_128_ + BLK_256_ + BLK_1024_ + BLK_2048_);
i < (BLK_128_ + BLK_256_ + BLK_1024_ + BLK_2048_ + BLK_4096_);
i++){
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_4096;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_4096;
}
/* initialize block of 8kbytes */
for (i = (BLK_128_ + BLK_256_ + BLK_1024_ + BLK_2048_); i <
(BLK_128_ + BLK_256_ + BLK_1024_ + BLK_2048_ + BLK_4096_ +
BLK_8196_); i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_8192;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_8192;
}
}
/*free memory*/
static void
phci_hcd_mem_free(struct isp1763_mem_addr *memptr)
{
/*block number to be freed */
int block = memptr->blk_num;
if (block < BLK_TOTAL){
if ((memptr->blk_size) && (memalloc[block].used != 0)) {
memalloc[block].used = 0;
memptr->used = 0;
}
}
}
/*allocate memory*/
static void
phci_hcd_mem_alloc(u32 size, struct isp1763_mem_addr *memptr, u32 flag)
{
u32 blk_size = size;
u16 i;
u32 nextblk1 = 0, nextblk4 = 0;
u32 start = 0, end = 0;
struct isp1763_mem_addr *memaddr = 0;
memset(memptr, 0, sizeof *memptr);
pehci_print("phci_hcd_mem_alloc(size = %d)\n", size);
if (blk_size == 0) {
memptr->phy_addr = 0;
memptr->virt_addr = 0;
memptr->blk_size = 0;
memptr->num_alloc = 0;
memptr->blk_num = 0;
return;
}
for (i = 0; i < BLK_TOTAL; i++) {
memaddr = &memalloc[i];
if (!memaddr->used && size <= memaddr->blk_size) {
memaddr->used = 1;
memptr->used = 1;
memptr->blk_num = i;
memptr->blk_size = memaddr->blk_size;
memptr->phy_addr = memaddr->phy_addr;
memptr->virt_addr = memptr->phy_addr;
return;
}
}
return;
/*end of the 1k blocks */
nextblk1 = BLK_256_ + BLK_1024_;
/*end of the 4k blocks */
nextblk4 = nextblk1 + BLK_4096_;
if (blk_size <= BLK_SIZE_128) {
blk_size = BLK_SIZE_128;
start = 0;
end = BLK_256_;
}
if (blk_size <= BLK_SIZE_256) {
blk_size = BLK_SIZE_256;
start = 0;
end = BLK_256_;
} else if (blk_size <= BLK_SIZE_1024) {
blk_size = BLK_SIZE_1024;
start = BLK_256_;
end = start + BLK_1024_;
} else if (blk_size > BLK_SIZE_1024) {
blk_size = BLK_SIZE_4096;
start = BLK_256_ + BLK_1024_;
end = start + BLK_4096_;
}
for (i = start; i < end; i++) {
memaddr = &memalloc[i];
if (!memaddr->used) {
memaddr->used = 1;
memptr->blk_num = i;
memptr->used = 1;
memptr->blk_size = blk_size;
memptr->phy_addr = memaddr->phy_addr;
memptr->virt_addr = memptr->phy_addr;
return;
}
}
/*look for in the next block if memory is free */
/*start from the first place of the next block */
start = end;
/*for 1k and 256 size request only 4k can be returned */
end = nextblk4;
for (i = start; i < end; i++) {
memaddr = &memalloc[i];
if (!memaddr->used) {
memaddr->used = 1;
memptr->used = 1;
memptr->blk_num = i;
memptr->blk_size = blk_size;
memptr->phy_addr = memaddr->phy_addr;
memptr->virt_addr = memptr->phy_addr;
return;
}
}
}
#else
void
phci_hcd_mem_init(void)
{
int i = 0;
u32 start_addr = 0x1000;
struct isp1763_mem_addr *memaddr;
for (i = 0; i < BLK_TOTAL; i++) {
memaddr = &memalloc[i];
memset(memaddr, 0, sizeof *memaddr);
}
/*initialize block of 256bytes */
for (i = 0; i < BLK_256_; i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_256;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_256;
}
/*initialize block of 1024bytes */
for (i = BLK_256_; i < (BLK_256_ + BLK_1024_); i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_1024;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_1024;
}
/*initialize block of 4kbytes */
for (i = (BLK_256_ + BLK_1024_); i < (BLK_256_ + BLK_1024_ + BLK_4096_);
i++) {
memaddr = &memalloc[i];
memaddr->blk_num = i;
memaddr->used = 0;
memaddr->blk_size = BLK_SIZE_4096;
memaddr->phy_addr = start_addr;
start_addr += BLK_SIZE_4096;
}
}
/*free memory*/
static void
phci_hcd_mem_free(struct isp1763_mem_addr *memptr)
{
/*block number to be freed */
int block = memptr->blk_num;
if (block < BLK_TOTAL)
if ((memptr->blk_size) && (memalloc[block].used != 0)) {
memalloc[block].used = 0;
memptr->used = 0;
}
}
/*allocate memory*/
static void
phci_hcd_mem_alloc(u32 size, struct isp1763_mem_addr *memptr, u32 flag)
{
u32 blk_size = size;
u16 i;
u32 nextblk1 = 0, nextblk4 = 0;
u32 start = 0, end = 0;
struct isp1763_mem_addr *memaddr = 0;
memset(memptr, 0, sizeof *memptr);
pehci_print("phci_hcd_mem_alloc(size = %d)\n", size);
if (blk_size == 0) {
memptr->phy_addr = 0;
memptr->virt_addr = 0;
memptr->blk_size = 0;
memptr->num_alloc = 0;
memptr->blk_num = 0;
return;
}
/*end of the 1k blocks */
nextblk1 = BLK_256_ + BLK_1024_;
/*end of the 4k blocks */
nextblk4 = nextblk1 + BLK_4096_;
if (blk_size <= BLK_SIZE_256) {
blk_size = BLK_SIZE_256;
start = 0;
end = BLK_256_;
} else if (blk_size <= BLK_SIZE_1024) {
blk_size = BLK_SIZE_1024;
start = BLK_256_;
end = start + BLK_1024_;
} else if (blk_size > BLK_SIZE_1024) {
blk_size = BLK_SIZE_4096;
start = BLK_256_ + BLK_1024_;
end = start + BLK_4096_;
}
for (i = start; i < end; i++) {
memaddr = &memalloc[i];
if (!memaddr->used) {
memaddr->used = 1;
memptr->blk_num = i;
memptr->used = 1;
memptr->blk_size = blk_size;
memptr->phy_addr = memaddr->phy_addr;
memptr->virt_addr = memptr->phy_addr;
return;
}
}
/*look for in the next block if memory is free */
/*start from the first place of the next block */
start = end;
/*for 1k and 256 size request only 4k can be returned */
end = nextblk4;
for (i = start; i < end; i++) {
memaddr = &memalloc[i];
if (!memaddr->used) {
memaddr->used = 1;
memptr->used = 1;
memptr->blk_num = i;
memptr->blk_size = blk_size;
memptr->phy_addr = memaddr->phy_addr;
memptr->virt_addr = memptr->phy_addr;
return;
}
}
}
#endif
+189
View File
@@ -0,0 +1,189 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : host
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* This is a host controller driver file. OTG related events are handled here.
*
* Author : wired support <wired.support@stericsson.com>
*
*/
/*hub device which connected with root port*/
struct usb_device *hubdev = 0;
/* hub interrupt urb*/
struct urb *huburb;
/*return otghub from here*/
struct usb_device *
phci_register_otg_device(struct isp1763_dev *dev)
{
printk("OTG dev %x %d\n",(u32) hubdev, hubdev->devnum);
if (hubdev && hubdev->devnum >= 0x2) {
return hubdev;
}
return NULL;
}
EXPORT_SYMBOL(phci_register_otg_device);
/*suspend the otg port(0)
* needed when port is switching
* from host to device
* */
int
phci_suspend_otg_port(struct isp1763_dev *dev, u32 command)
{
int status = 0;
hubdev->otgstate = USB_OTG_SUSPEND;
if (huburb->status == -EINPROGRESS) {
huburb->status = 0;
}
huburb->status = 0;
huburb->complete(huburb);
return status;
}
EXPORT_SYMBOL(phci_suspend_otg_port);
/*set the flag to enumerate the device*/
int
phci_enumerate_otg_port(struct isp1763_dev *dev, u32 command)
{
/*set the flag to enumerate */
/*connect change interrupt will happen from
* phci_intl_worker only
* */
hubdev->otgstate = USB_OTG_ENUMERATE;
if (huburb->status == -EINPROGRESS) {
huburb->status = 0;
}
/*complete the urb */
huburb->complete(huburb);
/*reset the otghub urb status */
huburb->status = -EINPROGRESS;
return 0;
}
EXPORT_SYMBOL(phci_enumerate_otg_port);
/*host controller resume sequence at otg port*/
int
phci_resume_otg_port(struct isp1763_dev *dev, u32 command)
{
printk("Resume is called\n");
hubdev->otgstate = USB_OTG_RESUME;
if (huburb->status == -EINPROGRESS) {
huburb->status = 0;
}
/*complete the urb */
huburb->complete(huburb);
/*reset the otghub urb status */
huburb->status = -EINPROGRESS;
return 0;
}
EXPORT_SYMBOL(phci_resume_otg_port);
/*host controller remote wakeup sequence at otg port*/
int
phci_remotewakeup(struct isp1763_dev *dev)
{
printk("phci_remotewakeup_otg_port is called\n");
hubdev->otgstate = USB_OTG_REMOTEWAKEUP;
if(huburb->status == -EINPROGRESS)
huburb->status = 0;
/*complete the urb*/
#if ((defined LINUX_269) || defined (LINUX_2611))
huburb->complete(huburb,NULL);
#else
huburb->complete(huburb);
#endif
/*reset the otghub urb status*/
huburb->status = -EINPROGRESS;
return 0;
}
EXPORT_SYMBOL(phci_remotewakeup);
/*host controller wakeup sequence at otg port*/
int
phci_resume_wakeup(struct isp1763_dev *dev)
{
printk("phci_wakeup_otg_port is called\n");
#if 0
hubdev->otgstate = USB_OTG_WAKEUP_ALL;
if(huburb->status == -EINPROGRESS)
#endif
huburb->status = 0;
/*complete the urb*/
#if ((defined LINUX_269) || defined (LINUX_2611))
huburb->complete(huburb,NULL);
#else
huburb->complete(huburb);
#endif
/*reset the otghub urb status*/
huburb->status = -EINPROGRESS;
return 0;
}
EXPORT_SYMBOL(phci_resume_wakeup);
struct isp1763_driver *host_driver;
struct isp1763_driver *device_driver;
void
pehci_delrhtimer(struct isp1763_dev *dev)
{
struct usb_hcd *usb_hcd =
container_of(huburb->dev->parent->bus, struct usb_hcd, self);
del_timer_sync(&usb_hcd->rh_timer);
del_timer(&usb_hcd->rh_timer);
}
EXPORT_SYMBOL(pehci_delrhtimer);
int
pehci_Deinitialize(struct isp1763_dev *dev)
{
dev -= 2;
if (dev->index == 0) {
if (dev->driver) {
if (dev->driver->powerdown) {
dev->driver->powerdown(dev);
}
}
}
return 0;
}
EXPORT_SYMBOL(pehci_Deinitialize);
int
pehci_Reinitialize(struct isp1763_dev *dev)
{
dev -= 2;
if (dev->index == 0) {
if(dev->driver->powerup){
dev->driver->powerup(dev);
}
}
return 0;
}
EXPORT_SYMBOL(pehci_Reinitialize);
File diff suppressed because it is too large Load Diff
+752
View File
@@ -0,0 +1,752 @@
/*
* Copyright (C) ST-Ericsson AP Pte Ltd 2010
*
* ISP1763 Linux OTG Controller driver : host
*
* 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; version
* 2 of the License.
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Refer to file ~/drivers/usb/host/ehci-dbg.h for copyright owners (kernel version 2.6.9)
* Code is modified for ST-Ericsson product
*
* Author : wired support <wired.support@stericsson.com>
*
*/
#ifndef __PEHCI_H__
#define __PEHCI_H__
#define DRIVER_AUTHOR "ST-ERICSSON "
#define DRIVER_DESC "ISP1763 'Enhanced' Host Controller (EHCI) Driver"
/* bus related stuff */
#define __ACTIVE 0x01
#define __SLEEPY 0x02
#define __SUSPEND 0x04
#define __TRANSIENT 0x80
#define USB_STATE_HALT 0
#define USB_STATE_RUNNING (__ACTIVE)
#define USB_STATE_READY (__ACTIVE|__SLEEPY)
#define USB_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE)
#define USB_STATE_RESUMING (__SUSPEND|__TRANSIENT)
#define USB_STATE_SUSPENDED (__SUSPEND)
/* System flags */
#define HCD_MEMORY 0x0001
#define HCD_USB2 0x0020
#define HCD_USB11 0x0010
#define HCD_IS_RUNNING(state) ((state) & __ACTIVE)
#define HCD_IS_SUSPENDED(state) ((state) & __SUSPEND)
/*---------------------------------------------------
* Host controller related
-----------------------------------------------------*/
/* IRQ line for the ISP1763 */
#define HCD_IRQ IRQ_GPIO(25)
#define CMD_RESET (1<<1) /* reset HC not bus */
#define CMD_RUN (1<<0) /* start/stop HC */
#define STS_PCD (1<<2) /* port change detect */
/* NOTE: urb->transfer_flags expected to not use this bit !!! */
#define EHCI_STATE_UNLINK 0x8000 /* urb being unlinked */
/* Bits definations for qha*/
/* Bits PID*/
#define SETUP_PID (2)
#define OUT_PID (0)
#define IN_PID (1)
/* Bits MULTI*/
#define MULTI(x) ((x)<< 29)
#define XFER_PER_UFRAME(x) (((x) >> 29) & 0x3)
/*Active, EP type and speed bits */
#define QHA_VALID (1<<0)
#define QHA_ACTIVE (1<<31)
/*1763 error bit maps*/
#define HC_MSOF_INT (1<< 0)
#define HC_MSEC_INT (1 << 1)
#define HC_EOT_INT (1 << 3)
#define HC_OPR_REG_INT (1<<4)
#define HC_CLK_RDY_INT (1<<6)
#define HC_INTL_INT (1 << 7)
#define HC_ATL_INT (1 << 8)
#define HC_ISO_INT (1 << 9)
#define HC_OTG_INT (1 << 10)
/*PTD error codes*/
#define PTD_STATUS_HALTED (1 << 30)
#define PTD_XACT_ERROR (1 << 28)
#define PTD_BABBLE (1 << 29)
#define PTD_ERROR (PTD_STATUS_HALTED | PTD_XACT_ERROR | PTD_BABBLE)
/*ep types*/
#define EPTYPE_BULK (2 << 12)
#define EPTYPE_CONTROL (0 << 12)
#define EPTYPE_INT (3 << 12)
#define EPTYPE_ISO (1 << 12)
#define PHCI_QHA_LENGTH 32
#define usb_inc_dev_use usb_get_dev
#define usb_dec_dev_use usb_put_dev
#define usb_free_dev usb_put_dev
/*1763 host controller periodic size*/
#define PTD_PERIODIC_SIZE 16
#define MAX_PERIODIC_SIZE 16
#define PTD_FRAME_MASK 0x1f
/*periodic list*/
struct _periodic_list {
int framenumber;
struct list_head sitd_itd_head;
char high_speed; /*1 - HS ; 0 - FS*/
u16 ptdlocation;
};
typedef struct _periodic_list periodic_list;
/*iso ptd*/
struct _isp1763_isoptd {
u32 td_info1;
u32 td_info2;
u32 td_info3;
u32 td_info4;
u32 td_info5;
u32 td_info6;
u32 td_info7;
u32 td_info8;
} __attribute__ ((aligned(32)));
typedef struct _isp1763_isoptd isp1763_isoptd;
struct _isp1763_qhint {
u32 td_info1;
u32 td_info2;
u32 td_info3;
u32 td_info4;
u32 td_info5;
#define INT_UNDERRUN (1 << 2)
#define INT_BABBLE (1 << 1)
#define INT_EXACT (1 << 0)
u32 td_info6;
u32 td_info7;
u32 td_info8;
} __attribute__ ((aligned(32)));
typedef struct _isp1763_qhint isp1763_qhint;
struct _isp1763_qha {
u32 td_info1; /* First 32 bit */
u32 td_info2; /* Second 32 bit */
u32 td_info3; /* third 32 bit */
u32 td_info4; /* fourth 32 bit */
u32 reserved[4];
};
typedef struct _isp1763_qha isp1763_qha, *pisp1763_qha;
/*this does not cover all interrupts in 1763 chip*/
typedef struct _ehci_regs {
/*standard ehci registers */
u32 command;
u32 usbinterrupt;
u32 usbstatus;
u32 hcsparams;
u32 frameindex;
/*isp1763 interrupt specific registers */
u16 hwmodecontrol;
u16 interrupt;
u16 interruptenable;
u32 interruptthreshold;
u16 iso_irq_mask_or;
u16 int_irq_mask_or;
u16 atl_irq_mask_or;
u16 iso_irq_mask_and;
u16 int_irq_mask_and;
u16 atl_irq_mask_and;
u16 buffer_status;
/*isp1763 initialization registers */
u32 reset;
u32 configflag;
u32 ports[4];
u32 pwrdwn_ctrl;
/*isp1763 transfer specific registers */
u16 isotddonemap;
u16 inttddonemap;
u16 atltddonemap;
u16 isotdskipmap;
u16 inttdskipmap;
u16 atltdskipmap;
u16 isotdlastmap;
u16 inttdlastmap;
u16 atltdlastmap;
u16 scratch;
} ehci_regs, *pehci_regs;
/*memory management structures*/
#define MEM_KV
#ifdef MEM_KV
typedef struct isp1763_mem_addr {
u32 phy_addr; /* Physical address of the memory */
u32 virt_addr; /* after ioremap() function call */
u8 num_alloc; /* In case n*smaller size is allocated then for clearing purpose */
u32 blk_size; /*block size */
u8 blk_num; /* number of the block */
u8 used; /*used/free */
} isp1763_mem_addr_t;
#else
typedef struct isp1763_mem_addr {
void *phy_addr; /* Physical address of the memory */
void *virt_addr; /* after ioremap() function call */
u8 usage;
u32 blk_size; /*block size */
} isp1763_mem_addr_t;
#endif
/* type tag from {qh,itd,sitd,fstn}->hw_next */
#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1))
/* values for that type tag */
#define Q_TYPE_ITD __constant_cpu_to_le32 (0 << 1)
#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1)
#define Q_TYPE_SITD __constant_cpu_to_le32 (2 << 1)
#define Q_TYPE_FSTN __constant_cpu_to_le32 (3 << 1)
/*next queuehead in execution*/
#define QH_NEXT(dma) cpu_to_le32((u32)dma)
struct ehci_qh {
/* first part defined by EHCI spec */
u32 hw_next; /* see EHCI 3.6.1 */
u32 hw_info1; /* see EHCI 3.6.2 */
u32 hw_info2; /* see EHCI 3.6.2 */
u32 hw_current; /* qtd list - see EHCI 3.6.4 */
/* qtd overlay (hardware parts of a struct ehci_qtd) */
u32 hw_qtd_next;
u32 hw_alt_next;
u32 hw_token;
u32 hw_buf[5];
u32 hw_buf_hi[5];
/* the rest is HCD-private */
dma_addr_t qh_dma; /* address of qh */
struct list_head qtd_list; /* sw qtd list */
struct ehci_qtd *dummy;
struct ehci_qh *reclaim; /* next to reclaim */
atomic_t refcount;
wait_queue_head_t waitforcomplete;
unsigned stamp;
u8 qh_state;
/* periodic schedule info */
u8 usecs; /* intr bandwidth */
u8 gap_uf; /* uframes split/csplit gap */
u8 c_usecs; /* ... split completion bw */
unsigned short period; /* polling interval */
unsigned short start; /* where polling starts */
u8 datatoggle; /*data toggle */
/*handling the ping stuffs */
u8 ping; /*ping bit */
/*qtd <-> ptd management */
u32 qtd_ptd_index; /* Td-PTD map index for this ptd */
u32 type; /* endpoint type */
/*iso stuffs */
struct usb_host_endpoint *ep;
int next_uframe; /*next uframe for this endpoint */
struct list_head itd_list; /*list of tds to this endpoint */
isp1763_mem_addr_t memory_addr;
struct _periodic_list periodic_list;
/*scheduling requirements for this endpoint */
u32 ssplit;
u32 csplit;
u8 totalptds; // total number of PTDs needed for current URB
u8 actualptds; // scheduled PTDs until now for current URB
};
/* urb private part for the driver. */
typedef struct {
struct ehci_qh *qh;
u16 length; /* number of tds associated with this request */
u16 td_cnt; /* number of tds already serviced */
int state; /* State machine state when URB is deleted */
int timeout; /* timeout for bulk transfers */
wait_queue_head_t wait; /* wait State machine state when URB is deleted */
/*FIX solve the full speed dying */
struct timer_list urb_timer;
struct list_head qtd_list;
struct ehci_qtd *qtd[0]; /* list pointer to all corresponding TDs associated with this request */
} urb_priv_t;
/*
* EHCI Specification 0.95 Section 3.6
* QH: describes control/bulk/interrupt endpoints
* See Fig 3-7 "Queue Head Structure Layout".
*
* These appear in both the async and (for interrupt) periodic schedules.
*/
/*Defination required for the ehci Queuehead */
#define QH_HEAD 0x00008000
#define QH_STATE_LINKED 1 /* HC sees this */
#define QH_STATE_UNLINK 2 /* HC may still see this */
#define QH_STATE_IDLE 3 /* HC doesn't see this */
#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */
#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */
#define QH_STATE_TAKE_NEXT 8 /*take the new transfer from */
#define NO_FRAME ((unsigned short)~0) /* pick new start */
#define EHCI_ITD_TRANLENGTH 0x0fff0000 /*transaction length */
#define EHCI_ITD_PG 0x00007000 /*page select */
#define EHCI_ITD_TRANOFFSET 0x00000fff /*transaction offset */
#define EHCI_ITD_BUFFPTR 0xfffff000 /*buffer pointer */
struct ehci_sitd {
/* first part defined by EHCI spec */
u32 hw_next; /* see EHCI 3.3.1 */
u32 hw_transaction[8]; /* see EHCI 3.3.2 */
#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */
#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */
#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */
#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff)
#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */
u32 hw_bufp[7]; /* see EHCI 3.3.3 */
u32 hw_bufp_hi[7]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t sitd_dma; /* for this itd */
struct urb *urb;
struct list_head sitd_list; /* list of urb frames' itds */
dma_addr_t buf_dma; /* frame's buffer address */
/* for now, only one hw_transaction per itd */
u32 transaction;
u16 index; /* in urb->iso_frame_desc */
u16 uframe; /* in periodic schedule */
u16 usecs;
/*memory address */
struct isp1763_mem_addr mem_addr;
int length;
u32 framenumber;
u32 ptdframe;
int sitd_index;
/*scheduling fields */
u32 ssplit;
u32 csplit;
u32 start_frame;
};
struct ehci_itd {
/* first part defined by EHCI spec */
u32 hw_next; /* see EHCI 3.3.1 */
u32 hw_transaction[8]; /* see EHCI 3.3.2 */
#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */
#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */
#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */
#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */
#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x7fff)
#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */
u32 hw_bufp[7]; /* see EHCI 3.3.3 */
u32 hw_bufp_hi[7]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t itd_dma; /* for this itd */
struct urb *urb;
struct list_head itd_list; /* list of urb frames' itds */
dma_addr_t buf_dma; /* frame's buffer address */
u8 num_of_pkts; /*number of packets for this ITD */
/* for now, only one hw_transaction per itd */
u32 transaction;
u16 index; /* in urb->iso_frame_desc */
u16 uframe; /* in periodic schedule */
u16 usecs;
/*memory address */
struct isp1763_mem_addr mem_addr;
int length;
u32 multi;
u32 framenumber;
u32 ptdframe;
int itd_index;
/*scheduling fields */
u32 ssplit;
u32 csplit;
};
/*
* EHCI Specification 0.95 Section 3.5
* QTD: describe data transfer components (buffer, direction, ...)
* See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram".
*
* These are associated only with "QH" (Queue Head) structures,
* used with control, bulk, and interrupt transfers.
*/
struct ehci_qtd {
/* first part defined by EHCI spec */
u32 hw_next; /* see EHCI 3.5.1 */
u32 hw_alt_next; /* see EHCI 3.5.2 */
u32 hw_token; /* see EHCI 3.5.3 */
u32 hw_buf[5]; /* see EHCI 3.5.4 */
u32 hw_buf_hi[5]; /* Appendix B */
/* the rest is HCD-private */
dma_addr_t qtd_dma; /* qtd address */
struct list_head qtd_list; /* sw qtd list */
struct urb *urb; /* qtd's urb */
size_t length; /* length of buffer */
u32 state; /*state of the qtd */
#define QTD_STATE_NEW 0x100
#define QTD_STATE_DONE 0x200
#define QTD_STATE_SCHEDULED 0x400
#define QTD_STATE_LAST 0x800
struct isp1763_mem_addr mem_addr;
};
#define QTD_TOGGLE (1 << 31) /* data toggle */
#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff)
#define QTD_IOC (1 << 15) /* interrupt on complete */
#define QTD_CERR(tok) (((tok)>>10) & 0x3)
#define QTD_PID(tok) (((tok)>>8) & 0x3)
#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */
#define QTD_STS_HALT (1 << 6) /* halted on error */
#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */
#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */
#define QTD_STS_XACT (1 << 3) /* device gave illegal response */
#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */
#define QTD_STS_STS (1 << 1) /* split transaction state */
#define QTD_STS_PING (1 << 0) /* issue PING? */
/* for periodic/async schedules and qtd lists, mark end of list */
#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */
#define QTD_NEXT(dma) cpu_to_le32((u32)dma)
struct _phci_driver;
struct _isp1763_hcd;
#define EHCI_MAX_ROOT_PORTS 1
#include <linux/usb/hcd.h>
#define USBNET
#ifdef USBNET
struct isp1763_async_cleanup_urb {
struct list_head urb_list;
struct urb *urb;
};
#endif
/*host controller*/
typedef struct _phci_hcd {
struct usb_hcd usb_hcd;
spinlock_t lock;
/* async schedule support */
struct ehci_qh *async;
struct ehci_qh *reclaim;
/* periodic schedule support */
unsigned periodic_size;
int next_uframe; /* scan periodic, start here */
int periodic_sched; /* periodic activity count */
int periodic_more_urb;
struct usb_device *otgdev; /*otg deice, with address 2 */
struct timer_list rh_timer; /* drives root hub */
struct list_head dev_list; /* devices on this bus */
struct list_head urb_list; /*iso testing */
/*msec break in interrupts */
atomic_t nuofsofs;
atomic_t missedsofs;
struct isp1763_dev *dev;
/*hw info */
u8 *iobase;
u32 iolength;
u8 *plxiobase;
u32 plxiolength;
int irq; /* irq allocated */
int state; /*state of the host controller */
unsigned long reset_done[EHCI_MAX_ROOT_PORTS];
ehci_regs regs;
struct _isp1763_qha qha;
struct _isp1763_qhint qhint;
struct _isp1763_isoptd isotd;
struct tasklet_struct tasklet;
/*this timer is going to run every 20 msec */
struct timer_list watchdog;
void (*worker_function) (struct _phci_hcd * hcd);
struct _periodic_list periodic_list[PTD_PERIODIC_SIZE];
#ifdef USBNET
struct isp1763_async_cleanup_urb cleanup_urb;
#endif
} phci_hcd, *pphci_hcd;
/*usb_device->hcpriv, points to this structure*/
typedef struct hcd_dev {
struct list_head dev_list;
struct list_head urb_list;
} hcd_dev;
#define usb_hcd_to_pehci_hcd(hcd) container_of(hcd, struct _phci_hcd, usb_hcd)
/*td allocation*/
#ifdef CONFIG_PHCI_MEM_SLAB
#define qha_alloc(t,c) kmem_cache_alloc(c,ALLOC_FLAGS)
#define qha_free(c,x) kmem_cache_free(c,x)
static kmem_cache_t *qha_cache, *qh_cache, *qtd_cache;
static int
phci_hcd_mem_init(void)
{
/* qha TDs accessed by controllers and host */
qha_cache = kmem_cache_create("phci_ptd", sizeof(isp1763_qha), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!qha_cache) {
printk("no TD cache?");
return -ENOMEM;
}
/* qh TDs accessed by controllers and host */
qh_cache = kmem_cache_create("phci_ptd", sizeof(isp1763_qha), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!qh_cache) {
printk("no TD cache?");
return -ENOMEM;
}
/* qtd accessed by controllers and host */
qtd_cache = kmem_cache_create("phci_ptd", sizeof(isp1763_qha), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (!qtd_cache) {
printk("no TD cache?");
return -ENOMEM;
}
return 0;
}
static void
phci_mem_cleanup(void)
{
if (qha_cache && kmem_cache_destroy(qha_cache))
err("td_cache remained");
qha_cache = 0;
}
#else
#define qha_alloc(t,c) kmalloc(t,ALLOC_FLAGS)
#define qha_free(c,x) kfree(x)
#define qha_cache 0
#ifdef CONFIG_ISO_SUPPORT
/*memory constants*/
#define BLK_128_ 2
#define BLK_256_ 3
#define BLK_1024_ 1
#define BLK_2048_ 3
#define BLK_4096_ 3 //1
#define BLK_8196_ 0 //1
#define BLK_TOTAL (BLK_128_+BLK_256_ + BLK_1024_ +BLK_2048_+ BLK_4096_+BLK_8196_)
#define BLK_SIZE_128 128
#define BLK_SIZE_256 256
#define BLK_SIZE_1024 1024
#define BLK_SIZE_2048 2048
#define BLK_SIZE_4096 4096
#define BLK_SIZE_8192 8192
#define COMMON_MEMORY 1
#else
#define BLK_256_ 8
#define BLK_1024_ 6
#define BLK_4096_ 3
#define BLK_TOTAL (BLK_256_ + BLK_1024_ + BLK_4096_)
#define BLK_SIZE_256 256
#define BLK_SIZE_1024 1024
#define BLK_SIZE_4096 4096
#endif
static void phci_hcd_mem_init(void);
static inline void
phci_mem_cleanup(void)
{
return;
}
#endif
#define PORT_WKOC_E (1<<22) /* wake on overcurrent (enable) */
#define PORT_WKDISC_E (1<<21) /* wake on disconnect (enable) */
#define PORT_WKCONN_E (1<<20) /* wake on connect (enable) */
/* 19:16 for port testing */
/* 15:14 for using port indicator leds (if HCS_INDICATOR allows) */
#define PORT_OWNER (1<<13) /* true: companion hc owns this port */
#define PORT_POWER (1<<12) /* true: has power (see PPC) */
#define PORT_USB11(x) (((x)&(3<<10))==(1<<10)) /* USB 1.1 device */
/* 11:10 for detecting lowspeed devices (reset vs release ownership) */
/* 9 reserved */
#define PORT_RESET (1<<8) /* reset port */
#define PORT_SUSPEND (1<<7) /* suspend port */
#define PORT_RESUME (1<<6) /* resume it */
#define PORT_OCC (1<<5) /* over current change */
#define PORT_OC (1<<4) /* over current active */
#define PORT_PEC (1<<3) /* port enable change */
#define PORT_PE (1<<2) /* port enable */
#define PORT_CSC (1<<1) /* connect status change */
#define PORT_CONNECT (1<<0) /* device connected */
#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
/*Legends,
* ATL control, bulk transfer
* INTL interrupt transfer
* ISTL iso transfer
* */
/*buffer(transfer) bitmaps*/
#define ATL_BUFFER 0x1
#define INT_BUFFER 0x2
#define ISO_BUFFER 0x4
#define BUFFER_MAP 0x7
/* buffer type for ST-ERICSSON HC */
#define TD_PTD_BUFF_TYPE_ATL 0 /* ATL buffer */
#define TD_PTD_BUFF_TYPE_INTL 1 /* INTL buffer */
#define TD_PTD_BUFF_TYPE_ISTL 2 /* ISO buffer */
#define TD_PTD_TOTAL_BUFF_TYPES (TD_PTD_BUFF_TYPE_ISTL +1)
/*maximum number of tds per transfer type*/
#define TD_PTD_MAX_BUFF_TDS 16
/*invalid td index in the headers*/
#define TD_PTD_INV_PTD_INDEX 0xFFFF
/*Host controller buffer defination*/
#define INVALID_FRAME_NUMBER 0xFFFFFFFF
/*per td transfer size*/
#define HC_ATL_PL_SIZE 4096
#define HC_ISTL_PL_SIZE 1024
#define HC_INTL_PL_SIZE 1024
/*TD_PTD_MAP states*/
#define TD_PTD_NEW 0x0000
#define TD_PTD_ACTIVE 0x0001
#define TD_PTD_IDLE 0x0002
#define TD_PTD_REMOVE 0x0004
#define TD_PTD_RELOAD 0x0008
#define TD_PTD_IN_SCHEDULE 0x0010
#define TD_PTD_DONE 0x0020
#define PTD_RETRY(x) (((x) >> 23) & 0x3)
#define PTD_PID(x) (((x) >> 10) & (0x3))
#define PTD_NEXTTOGGLE(x) (((x) >> 25) & (0x1))
#define PTD_XFERRED_LENGTH(x) ((x) & 0x7fff)
#define PTD_XFERRED_NONHSLENGTH(x) ((x) & 0x7ff)
#define PTD_PING_STATE(x) (((x) >> 26) & (0x1))
/* urb state*/
#define DELETE_URB 0x0008
#define NO_TRANSFER_ACTIVE 0xFFFF
#define NO_TRANSFER_DONE 0x0000
#define MAX_PTD_BUFFER_SIZE 4096 /*max ptd size */
/*information of the td in headers of host memory*/
typedef struct td_ptd_map {
u32 state; /* ACTIVE, NEW, TO_BE_REMOVED */
u8 datatoggle; /*to preserve the data toggle for ATL/ISTL transfers */
u32 ptd_bitmap; /* Bitmap of this ptd in HC headers */
u32 ptd_header_addr; /* headers address of this td */
u32 ptd_data_addr; /*data address of this td to write in and read from */
/*this is address is actual RAM address not the CPU address
* RAM address = (CPU ADDRESS-0x400) >> 3
* */
u32 ptd_ram_data_addr;
u8 lasttd; /*last td , complete the transfer */
struct ehci_qh *qh; /* endpoint */
struct ehci_qtd *qtd; /* qtds for this endpoint */
struct ehci_itd *itd; /*itd pointer */
struct ehci_sitd *sitd; /*itd pointer */
/*iso specific only */
u32 grouptdmap; /*if td need to complete with error, then process all the tds
in the groupmap */
} td_ptd_map_t;
/*buffer(ATL/ISTL/INTL) managemnet*/
typedef struct td_ptd_map_buff {
u8 buffer_type; /* Buffer type: BUFF_TYPE_ATL/INTL/ISTL0/ISTL1 */
u8 active_ptds; /* number of active td's in the buffer */
u8 total_ptds; /* Total number of td's present in the buffer (active + tobe removed + skip) */
u8 max_ptds; /* Maximum number of ptd's(32) this buffer can withstand */
u16 active_ptd_bitmap; /* Active PTD's bitmap */
u16 pending_ptd_bitmap; /* skip PTD's bitmap */
td_ptd_map_t map_list[TD_PTD_MAX_BUFF_TDS]; /* td_ptd_map list */
} td_ptd_map_buff_t;
#define USB_HCD_MAJOR 0
#define USB_HCD_MODULE_NAME "isp1763hcd"
/* static char devpath[] = "/dev/isp1763hcd"; */
#define HCD_IOC_MAGIC 'h'
#define HCD_IOC_POWERDOWN _IO(HCD_IOC_MAGIC, 1)
#define HCD_IOC_POWERUP _IO(HCD_IOC_MAGIC, 2)
#define HCD_IOC_TESTSE0_NACK _IO(HCD_IOC_MAGIC, 3)
#define HCD_IOC_TEST_J _IO(HCD_IOC_MAGIC,4)
#define HCD_IOC_TEST_K _IO(HCD_IOC_MAGIC,5)
#define HCD_IOC_TEST_TESTPACKET _IO(HCD_IOC_MAGIC,6)
#define HCD_IOC_TEST_FORCE_ENABLE _IO(HCD_IOC_MAGIC,7)
#define HCD_IOC_TEST_SUSPEND_RESUME _IO(HCD_IOC_MAGIC,8)
#define HCD_IOC_TEST_SINGLE_STEP_GET_DEV_DESC _IO(HCD_IOC_MAGIC,9)
#define HCD_IOC_TEST_SINGLE_STEP_SET_FEATURE _IO(HCD_IOC_MAGIC,10)
#define HCD_IOC_TEST_STOP _IO(HCD_IOC_MAGIC,11)
#define HCD_IOC_SUSPEND_BUS _IO(HCD_IOC_MAGIC,12)
#define HCD_IOC_RESUME_BUS _IO(HCD_IOC_MAGIC,13)
#define HCD_IOC_REMOTEWAKEUP_BUS _IO(HCD_IOC_MAGIC,14)
#define HOST_COMPILANCE_TEST_ENABLE 1
#define HOST_COMP_TEST_SE0_NAK 1
#define HOST_COMP_TEST_J 2
#define HOST_COMP_TEST_K 3
#define HOST_COMP_TEST_PACKET 4
#define HOST_COMP_TEST_FORCE_ENABLE 5
#define HOST_COMP_HS_HOST_PORT_SUSPEND_RESUME 6
#define HOST_COMP_SINGLE_STEP_GET_DEV_DESC 7
#define HOST_COMP_SINGLE_STEP_SET_FEATURE 8
#endif
File diff suppressed because it is too large Load Diff