📄 hal_pxa250.c
字号:
/************************************************************************ * Philips ISP1362 hardware access layer driver for * Intel PXA250 based Accelent IDP platform * * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved * * This source code and any compilation or derivative thereof is the * proprietary information of Koninklijke Philips Electronics N.V. * and is confidential in nature. * Under no circumstances is this software to be exposed to or placed * under an Open Source License of any type without the expressed * written permission of Koninklijke Philips Electronics N.V. * * File Name: hal_pxa250.c * * History: * * Version Date Author Comments * ------------------------------------------------- * 1.0 09/23/02 SYARRA Initial Creation * * Note: use tab space 4 ************************************************************************/#include <linux/config.h>#define MODULE#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> /* for in_interrupt() */#undef DEBUG#include <linux/usb.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/unaligned.h>#include <asm/dma.h>#include "hal_intf.h"/*--------------------------------------------------------------* * Local variable Definitions *--------------------------------------------------------------*/struct isp1362_dev isp1362_loc_dev[ISP1362_LAST_DEV];static struct isp1362_hal pxa250_hal_data;/*--------------------------------------------------------------* * Local # Definitions *--------------------------------------------------------------*/#define isp1362_driver_name "1362-hal"#define DRIVER_AUTHOR "Philips Semiconductors"#define DRIVER_DESC "ISP1362 bus driver"/*--------------------------------------------------------------* * Local Function Declerations *--------------------------------------------------------------*/static void isp1362_hal_remove (struct isp1362_hal *info);static int isp1362_hal_probe (struct isp1362_hal *info);#ifdef CONFIG_PMstatic int isp1362_hal_suspend (__u32 state);static int isp1362_hal_resume (void);#endif /* CONFIG_PM */static void isp1362_hal_isr (int irq, void *__data, struct pt_regs *r);/*--------------------------------------------------------------* * ISP1362 Interrupt Service Routine *--------------------------------------------------------------*//* Interrupt Service Routine of isp1362 * 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 */void isp1362_hal_isr(int irq, void *__data, struct pt_regs *r) { __u32 irq_mask; __u32 hc_int_reg; __u32 intrenable; __u8 repeat_flag = 0; struct isp1362_dev *dev; func_debug(("isp1362_hal_isr(irq = %d,__data=%p,r=%p)\n",irq,__data,r)) do{ repeat_flag = 0; /* Process the Host Controller Driver */ dev = &isp1362_loc_dev[ISP1362_HC]; /* Get the source of interrupts for Host Controller */ isp1362_reg_read16(dev, HC_MP_INT_REG,(dev->int_reg)); isp1362_reg_read16(dev, HC_MP_INT_EN_REG,irq_mask); isp1362_reg_read32(dev, HC_INT_STS_REG,(dev->alt_int_reg) ); isp1362_reg_read32(dev, HC_INT_EN_REG,intrenable ); /* Clear the source of interrupts for Host Controller */ isp1362_reg_write16(dev,(HC_MP_INT_REG|0x80), (dev->int_reg)); isp1362_reg_write32(dev,(HC_INT_STS_REG|0x80), (dev->alt_int_reg)); dev->int_reg &= irq_mask; hc_int_reg = dev->int_reg; dev->alt_int_reg &= intrenable; /* call the Host Isr if any valid interrupt is present */ if(dev->int_reg) { repeat_flag = 1; dev->handler(dev,dev->isr_data); } /* Process OTG controller Driver * Since OTG is part of HC interrupt register, the interrupt source * will be HC interrupt Register */ dev = &isp1362_loc_dev[ISP1362_OTG]; if(hc_int_reg & HC_OTG_INT) { /* Read the source of OTG_INT and clear the * interrupt source */ isp1362_reg_read16(dev, OTG_INT_REG,(dev->int_reg)); isp1362_reg_write16(dev, (OTG_INT_REG|0x80),OTG_INT_MASK); if(dev->int_reg) { dev->handler(dev, dev->isr_data); repeat_flag = 1; } } /* Process the Device Controller */ dev = &isp1362_loc_dev[ISP1362_DC]; /* Get the source of interrupts for Device Controller * Device Controller interrupts are cleared by the driver * during processing */ isp1362_reg_read32(dev, DC_INT_REG,(dev->int_reg)); isp1362_reg_read32(dev, DC_INT_EN_REG,irq_mask); dev->int_reg &= irq_mask; if(dev->int_reg) { dev->handler(dev, dev->isr_data); repeat_flag = 1; } /* If there is any interrupt generated at the time of clearing the interrupts (because it consumes time to clear the interrupt), we might miss some of them. (Accelent PXA250 board will detect interrupts on falling edge only. and hardware is configured for Level triggering. The problem with configuring hardware for Edge triggering is limited by ISP1362 Edge pulse of <200nsec and CPU needs at least 1usec pulse to detect it */ } while(repeat_flag); return;} /* End of isp1362_hal_isr *//* probe function of ISP1362 * This function is called when the module is loaded This function * initializes the information for the 3 Controllers with the assigned * resources and tests the register access to these controllers and do a * software reset and makes them ready for the drivers to play with them. */static int __devinitisp1362_hal_probe (struct isp1362_hal *info){ __u32 reg_data = 0; struct isp1362_dev *loc_dev; func_debug(("isp1362_hal_probe(info=%p)\n",info)) if ((info->int_ch1 == 0) || (info->int_ch2 ==0)) { detail_debug(("found ISP1362 device with no IRQ assigned. check BIOS settings!")) return -ENODEV; } /* Get the Host Controller IO and INT resources */ loc_dev = &(isp1362_loc_dev[ISP1362_HC]); loc_dev->irq = info->int_ch1; loc_dev->io_base = (unsigned long)info->io_base; loc_dev->io_data = loc_dev->io_base; loc_dev->io_cmd = loc_dev->io_base + sizeof(void*); loc_dev->io_len = 2*sizeof(void*); loc_dev->index = ISP1362_HC; detail_debug(("isp1362 HC IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq)) /* Get the Device Controller IO and INT resources * Device controller also uses the same INT channel for PCI * but the IO is different */ loc_dev = &(isp1362_loc_dev[ISP1362_DC]); loc_dev->irq = info->int_ch2; loc_dev->io_base = (unsigned long)info->io_base + 2*sizeof(void*); loc_dev->io_data = loc_dev->io_base; loc_dev->io_cmd = loc_dev->io_base + sizeof(void*); loc_dev->io_len = 2*sizeof(void*); loc_dev->index = ISP1362_DC; detail_debug(("isp1362 DC IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq)) /* Get the OTG Controller IO and INT resources * OTG controller resources are same as Host Controller resources */ loc_dev = &(isp1362_loc_dev[ISP1362_OTG]); loc_dev->irq = info->int_ch1; loc_dev->io_base = (unsigned long)info->io_base; loc_dev->io_data = loc_dev->io_base; loc_dev->io_cmd = loc_dev->io_base + sizeof(void*); loc_dev->io_len = 2*sizeof(void*); loc_dev->index = ISP1362_OTG; detail_debug(("isp1362 OTG IO Base= %x irq = %x\n", loc_dev->io_base,loc_dev->irq)) loc_dev = &(isp1362_loc_dev[ISP1362_HC]); /* Try to check whether we can access Scratch Register of * Host Controller or not. The initial PCI access is retried until * local init for the PCI bridge is completed */ isp1362_reg_write16(loc_dev, (HC_SCRATCH_REG|0x80), 0xFACE); isp1362_reg_read16(loc_dev, HC_SCRATCH_REG,reg_data); /* Host Controller presence is detected by writing to scratch register * and reading back and checking the contents are same or not */ if(reg_data != 0xFACE) { detail_debug(("%s unable to access HC Scratch Register",isp1362_driver_name)) return -ENODEV; } /* Reset the Host controller (reset requires some time ..... * is 100 msec ok?? */ loc_dev->active = 1; isp1362_reg_write16(loc_dev, (HC_SW_RESET_REG|0x80), 0x00F6); isp1362_mdelay(100); isp1362_reg_read16(loc_dev, HC_CHIP_ID_REG,(loc_dev->chip_id)); detail_debug(("%s: found HC Chip Id = %x\n",isp1362_driver_name, loc_dev->chip_id)) /* Update the local and store the PCI data */ info->io_usage = 0; info->irq_usage = 0; /* Now Process the Device Controller */ loc_dev = &(isp1362_loc_dev[ISP1362_DC]); reg_data = 0; isp1362_reg_write16(loc_dev, (DC_SCRATCH_REG&0xFE), 0xFACE); isp1362_reg_read16(loc_dev, DC_SCRATCH_REG,reg_data); if(reg_data != 0xFACE) { detail_debug(("%s unable to access DC Scratch Register",isp1362_driver_name)) return -ENODEV; } loc_dev->active = 1; isp1362_reg_read16(loc_dev, DC_CHIP_ID_REG,(loc_dev->chip_id)); detail_debug(("%s: found DC Chip Id = %x\n",isp1362_driver_name, loc_dev->chip_id)) /* Rest the DC. Assume 10 msec are fairly enough for DC to reset */ isp1362_command(DC_SW_RESET_REG,loc_dev); isp1362_mdelay(10); /* Now Process the OTG Controller * OTG resources are same as HC resource nothing to be done here */ loc_dev = &(isp1362_loc_dev[ISP1362_OTG]); loc_dev->active = 1; return 0;} /* End of isp1362_hal_probe *//* hal cleanup function of ISP1362 * This function is called when module is unloaded or a de-registration of * driver. * This functions checks the registerd drivers (HCD, DCD, OTG) and calls * the corresponding removal functions. Also initializes the local variables * to zero. */static void __devexitisp1362_hal_remove (struct isp1362_hal *info){ struct isp1362_dev *loc_dev; int index; func_debug(("isp1362_hal_remove(info=%p)\n",info)) /* For each controller check whether driver is registerd * or not. If registerd call the removal function if it is * present */ for(index=ISP1362_1ST_DEV;index<ISP1362_LAST_DEV;index++) { loc_dev = &isp1362_loc_dev[index]; if(loc_dev->driver) { loc_dev->driver->remove(loc_dev); loc_dev->driver = NULL; return; } } /* Clear the local variables */ pxa250_hal_data.io_usage = 0; pxa250_hal_data.irq_usage = 0; return;} /* End of isp1362_hal_remove */#ifdef CONFIG_PM/* PCI suspend function of ISP1362 * This function is called from PCI Driver. * This functions checks the registerd drivers (HCD, DCD, OTG) and calls * the corresponding suspend functions if present. */static int isp1362_hal_suspend (__u32 state) { struct isp1362_dev *loc_dev; int index; func_debug(("isp1362_hal_suspend(state = %x)\n",state)) loc_dev = isp1362_loc_dev; /* For each controller check whether driver is registerd * or not. If registerd call the suspend function if it is * present
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -