?? hal_x86.c
字號:
/************************************************************
* NXP ISP176x Hardware Abstraction Layer code file
*
* (c) 2006 NXP B.V., All rights reserved. <usb.linux@nxp.com>
*
* 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
*
* File Name: hal_x86.c
*
* Refering linux kernel version 2.6.9
*
* History:
*
* Date Author Comments
* ---------------------------------------------------------------------
* Nov 29 2005 Prabhakar Kalasani Initial Creation
*
**********************************************************************
*/
#ifdef LINUX_269
#include <linux/config.h>
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.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/pci.h>
#include <linux/poll.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <asm/dma.h>
/*--------------------------------------------------------------*
* linux system include files
*--------------------------------------------------------------*/
#include "hal_x86.h"
#include "../hal/hal_intf.h"
#include "../hal/isp1761.h"
/*--------------------------------------------------------------*
* Local variable Definitions
*--------------------------------------------------------------*/
struct isp1761_dev isp1761_loc_dev[ISP1761_LAST_DEV];
static struct isp1761_hal hal_data;
static __u32 pci_io_base = 0;
void *iobase = 0;
int iolength = 0;
static __u32 pci_mem_phy0 =0;
static __u32 pci_mem_len = 0xffff;
static int isp1761_pci_latency;
/*--------------------------------------------------------------*
* Local # Definitions
*--------------------------------------------------------------*/
#define PCI_ACCESS_RETRY_COUNT 20
#define PLX_INT_CSR_REG 0x68
#define PLX_LBRD0_REG 0x18
#define PLX_LBRD0_WAIT_STATE_MASK 0x000000C3
#define PLX_LBRD0_WAIT_STATES 0x00000003
#define isp1761_driver_name "1761-pci"
/*--------------------------------------------------------------*
* Local Function
*--------------------------------------------------------------*/
static void __devexit isp1761_pci_remove (struct pci_dev *dev);
static int __devinit isp1761_pci_probe (struct pci_dev *dev,
const struct pci_device_id *id);
static int isp1761_pci_suspend (struct pci_dev *dev, __u32 state);
static int isp1761_pci_resume (struct pci_dev *dev);
static irqreturn_t isp1761_pci_isr (int irq, void *dev_id, struct pt_regs *regs);
/*--------------------------------------------------------------*
* ISP 1761 interrupt locking functions
*--------------------------------------------------------------*/
int isp1761_hw_lock = 0;
int isp1761_hw_isr = 0;
void isp1761_disable_interrupt(void) {
struct isp1761_dev *dev;
u32 hw_mode_buff;
/* Process the Host Controller Driver */
dev = &isp1761_loc_dev[ISP1761_HC];
hw_mode_buff = isp1761_reg_read32(dev, HC_HW_MODE_REG, hw_mode_buff);
/* Disable ISP176x global interrupt */
hw_mode_buff &= ~(0x1);
isp1761_reg_write32(dev, HC_HW_MODE_REG, hw_mode_buff);
}
void isp1761_enable_interrupt(void) {
struct isp1761_dev *dev;
u32 hw_mode_buff;
/* Process the Host Controller Driver */
dev = &isp1761_loc_dev[ISP1761_HC];
hw_mode_buff = isp1761_reg_read32(dev, HC_HW_MODE_REG, hw_mode_buff);
/* Enable ISP176x global interrupt */
hw_mode_buff |= 0x1;
isp1761_reg_write32(dev, HC_HW_MODE_REG, hw_mode_buff);
}
/*--------------------------------------------------------------*
* ISP1761 Interrupt Service Routine
*--------------------------------------------------------------*/
/*Interrupt Service Routine for device controller*/
irqreturn_t isp1761_pci_dc_isr(int irq, void *data, struct pt_regs *r)
{
struct isp1761_dev *dev;
dev = &isp1761_loc_dev[ISP1761_DC];
hal_entry("%s: Entered\n",__FUNCTION__);
/*not ready yet*/
if(dev->active == 0)
{
printk("isp1761_pci_dc_isr: dev->active is NULL \n");
return IRQ_NONE;
}
/* Get the source of interrupts for Device Controller
* Device Controller interrupts are cleared by the driver
* during processing
*/
/*unblock the device interrupt*/
isp1761_reg_write32(dev, DEV_UNLOCK_REGISTER, 0xaa37);
dev->int_reg = isp1761_reg_read32(dev, DEV_INTERRUPT_REGISTER, dev->int_reg);
hal_int("isp1761_pci_dc_isr:INTERRUPT_REGISTER 0x%x\n",dev->int_reg);
/*clear the interrupt source*/
isp1761_reg_write32(dev, 0x218, dev->int_reg);
dev->int_reg &= 0x03fffdb9;
if(dev->int_reg)
dev->handler(dev, dev->isr_data,r);
hal_entry("%s: Exit\n",__FUNCTION__);
return IRQ_HANDLED;
}
/* Interrupt Service Routine of isp1761
* Reads the source of interrupt and calls the corresponding driver's ISR.
* Before calling the driver's ISR clears the source of interrupt.
* The drivers can get the source of interrupt from the dev->int_reg field
*/
irqreturn_t isp1761_pci_isr(int irq, void *__data, struct pt_regs *r)
{
__u32 irq_mask = 0;
struct isp1761_dev *dev;
hal_entry("%s: Entered\n",__FUNCTION__);
isp1761_disable_interrupt();
/* Process the Host Controller Driver */
dev = &isp1761_loc_dev[ISP1761_HC];
/* Get the source of interrupts for Host Controller*/
dev->int_reg = isp1761_reg_read32(dev, HC_INTERRUPT_REG,dev->int_reg);
isp1761_reg_write32(dev,HC_INTERRUPT_REG,dev->int_reg);
irq_mask = isp1761_reg_read32(dev, HC_INTENABLE_REG,irq_mask);
dev->int_reg &= irq_mask; /*shared irq ??*/
/*call the Host Isr if any valid(minus otg)interrupt is present*/
if(dev->int_reg & ~HC_OTG_INTERRUPT)
dev->handler(dev,dev->isr_data,r);
#ifdef OTG
#ifndef MSEC_INT_BASED
mdelay(1);
#endif
/*process otg interrupt if there is any*/
if(dev->int_reg & HC_OTG_INTERRUPT){
u32 otg_int;
#ifndef MSEC_INT_BASED
mdelay(1);
#endif
otg_int = (dev->int_reg & HC_OTG_INTERRUPT);
/* Process OTG controller Driver
* Since OTG is part of HC interrupt register,
* the interrupt source will be HC interrupt Register
* */
dev = &isp1761_loc_dev[ISP1761_OTG];
/* Read the source of OTG_INT and clear the
interrupt source */
dev->int_reg = otg_int;
dev->handler(dev, dev->isr_data,r);
}
#endif
dev->handler(dev, dev->isr_data,r);
isp1761_enable_interrupt();
hal_entry("%s: Exit\n",__FUNCTION__);
return IRQ_HANDLED;
} /* End of isp1362_pci_isr */
/*--------------------------------------------------------------*
* PCI Driver Interface Functions
*--------------------------------------------------------------*/
static const struct pci_device_id __devinitdata isp1761_pci_ids [] = {
{
/* handle PCI BRIDE manufactured by PLX */
class: ((PCI_CLASS_BRIDGE_OTHER << 8) | (0x06 << 16)),
class_mask: ~0,
/* no matter who makes it */
vendor: /*0x10B5,*/PCI_ANY_ID,
device: /*0x5406,*/PCI_ANY_ID,
subvendor: PCI_ANY_ID,
subdevice: PCI_ANY_ID,
},
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE (pci, isp1761_pci_ids);
/* Pci driver interface functions */
static struct pci_driver isp1761_pci_driver = {
name: "isp1761-hal",
id_table: &isp1761_pci_ids[0],
probe: isp1761_pci_probe,
remove: isp1761_pci_remove,
};
/*--------------------------------------------------------------*
* ISP1761 Read write routine
*--------------------------------------------------------------*/
/* Write a 32 bit Register of isp1761 */
void isp1761_reg_write32(struct isp1761_dev *dev,__u16 reg,__u32 data)
{
/* Write the 32bit to the register address given to us*/
writel(data,dev->baseaddress+reg);
}
/* Read a 32 bit Register of isp1761 */
__u32 isp1761_reg_read32(struct isp1761_dev *dev,__u16 reg,__u32 data)
{
data = readl(dev->baseaddress + reg);
return data;
}
/* Read a 16 bit Register of isp1761 */
__u16 isp1761_reg_read16(struct isp1761_dev *dev,__u16 reg,__u16 data)
{
data = readw(dev->baseaddress+reg);
return data;
}
/* Write a 16 bit Register of isp1761 */
void isp1761_reg_write16(struct isp1761_dev *dev,__u16 reg,__u16 data)
{
writew(data,dev->baseaddress+reg);
}
/*--------------------------------------------------------------*
*
* Module dtatils: isp1761_mem_read
*
* Memory read using PIO method.
*
* Input: struct isp1761_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
isp1761_mem_read(struct isp1761_dev *dev, __u32 start_add,
__u32 end_add, __u32 * buffer, __u32 length, __u16 dir)
{
u8 *temp_base_mem = 0;
u8 *one = (u8 *) buffer;
u16 *two = (u16 *) buffer;
int a = (int)length;
u32 w;
temp_base_mem= (dev->baseaddress + start_add);
/*initialize the Register 0x33C-used to manage Multiple threads */
writel(start_add,dev->baseaddress+0x33c);
if(buffer == NULL)
{
printk("@@@@ In isp1761_mem_read The buffer is pointing to null\n");
return 0;
}
last:
w = readl(temp_base_mem);
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;
temp_base_mem = temp_base_mem+4;
start_add +=4;
a -= 4;
if(a == 0)
break;
if(a < 4){
buffer += 1;
one = (u8 *)buffer;
two = (u16 *)buffer;
goto last;
}
buffer += 1;
w = readl(temp_base_mem);
}
return ((a < 0) || (a == 0))?0:(-1);
}
/*--------------------------------------------------------------*
*
* Module dtatils: isp1761_mem_write
*
* Memory write using PIO method.
*
* Input: struct isp1761_driver *drv --> Driver structure.
* __u32 start_add --> Starting address of memory
* __u32 end_add ---> End address
*
* __u32 * buffer --> Buffer pointer.
* __u32 length ---> Length
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -