📄 pcidrv.c
字号:
*vtpiocr = 0xA01F ;
/* wait for 33 VTP clock cycles */
udelay (10000);
*dftEnb = 1 ;
*vtpiocr = 0xA000 | (*vtpr | 0x3FF) ;
/* Wait for few more clock cycles */
udelay (10000);
*vtpiocr &= 0xFFFFDFFF ;
*dftEnb = 0 ;
}
/* ============================================================================
* @func HAL_readDMA
*
* @desc DMAs contents from DSP memory to GPP Memory. Here read means DSP
* write.
*
* @modif None.
* ============================================================================
*/
Void
HAL_readDMA (Uint32 srcAddr,
Uint32 dstAddr,
Uint32 size)
{
volatile DM64LCPCI_edmaRegs * edmaRegs = (DM64LCPCI_edmaRegs *) ((Uint32) regVirt + (DM64LCPCI_EDMAREG_BASE - 0x01C00000)) ;
volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
Uint32 i = 0 ;
Uint32 pageBase ;
Uint32 numUSec ;
Uint32 tmp ;
if (size <= DM64LCPCI_PCIADLEN) {
pageBase = dstAddr & DM64LCPCI_PCIADWRBITMASK ;
pciRegs->PCIADDSUB [0] = pageBase ;
printk ("<1>Page Base : %x %x\n", (int)pageBase, (int)dstAddr) ;
}
else {
for (tmp = size, i = 0 ; tmp > 0 ; tmp -= DM64LCPCI_PCIADLEN, i++) {
pageBase = (dstAddr + (DM64LCPCI_PCIADLEN * i))
& DM64LCPCI_PCIADWRBITMASK ;
pciRegs->PCIADDSUB [i] = pageBase ;
}
}
do {
/* Set the interrupt enable for 1st Channel. */
edmaRegs->IESR |= 0x1 ;
/* Clear any pending interrupt. */
edmaRegs->ICR |= 0x1 ;
/* Populate the Param entry. */
edmaRegs->PARAMENTRY [0].OPTION = 0x00100004 ;
edmaRegs->PARAMENTRY [0].SRC = srcAddr ;
/* Calculate the DSP PCI address for the PC address */
tmp = 0x30000000 + (dstAddr & ~DM64LCPCI_PCIADWRBITMASK) ;
edmaRegs->PARAMENTRY [0].DST = tmp ;
/* Calculate the A & B count */
if (size > 0x7000) {
tmp = size / 0x7000 ;
size -= (tmp * 0x7000) ;
tmp <<= 16 ;
tmp |= 0x7000 ;
}
else {
tmp = 0x10000 | size ;
size = 0 ;
}
edmaRegs->PARAMENTRY [0].A_B_CNT = tmp ;
edmaRegs->PARAMENTRY [0].LINK_BCNTRLD = 0xFFFF ;
edmaRegs->PARAMENTRY [0].SRC_DST_CIDX = 0 ;
/* C Count is set to 1 since mostly size will not be more than 1GB */
edmaRegs->PARAMENTRY [0].CCNT = 0x1 ;
/* no offset difference required */
edmaRegs->PARAMENTRY [0].SRC_DST_BIDX = 0x70007000 ;
/* Set the interrupt enable for 1st Channel. */
edmaRegs->EESR |= 0x1 ;
/* Clear any pending interrupt. */
edmaRegs->ESR |= 0x1 ;
/* wait for current DMA to finish. */
numUSec = size / 132 ;
do {
udelay (numUSec) ;
/* now check in steps of 10 usec. */
numUSec = 10 ;
} while ((edmaRegs->IPR & 0x1) == 0) ;
} while (size != 0) ;
/* Clear any pending interrupt. */
edmaRegs->ICR |= 0x1 ;
}
/* ============================================================================
* @func HAL_writeDMA
*
* @desc DMAs contents from GPP memory to DSP Memory. Here write means DSP
* read.
*
* @modif None.
* ============================================================================
*/
Void
HAL_writeDMA (Uint32 srcAddr,
Uint32 dstAddr,
Uint32 size)
{
volatile DM64LCPCI_edmaRegs * edmaRegs = (DM64LCPCI_edmaRegs *) ((Uint32) regVirt + (DM64LCPCI_EDMAREG_BASE - 0x01C00000)) ;
volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)) ;
Uint32 i = 0 ;
Uint32 pageBase ;
Uint32 numUSec ;
Uint32 tmp ;
if (size <= DM64LCPCI_PCIADLEN) {
pageBase = srcAddr & DM64LCPCI_PCIADWRBITMASK ;
pciRegs->PCIADDSUB [0] = pageBase ;
printk ("<1>Page Base : %x %x\n", (int)pageBase, (int)srcAddr) ;
}
else {
for (tmp = size, i = 0 ; tmp > 0 ; tmp -= DM64LCPCI_PCIADLEN, i++) {
pageBase = (srcAddr + (DM64LCPCI_PCIADLEN * i))
& DM64LCPCI_PCIADWRBITMASK ;
pciRegs->PCIADDSUB [i] = pageBase ;
}
}
do {
/* Set the interrupt enable for 1st Channel. */
edmaRegs->IESR |= 0x1 ;
/* Clear any pending interrupt. */
edmaRegs->ICR |= 0x1 ;
/* Populate the Param entry. */
edmaRegs->PARAMENTRY [0].OPTION = 0x00100004 ;
/* Calculate the DSP PCI address for the PC address */
tmp = 0x30000000 + (srcAddr & ~DM64LCPCI_PCIADWRBITMASK) ;
edmaRegs->PARAMENTRY [0].SRC = tmp ;
edmaRegs->PARAMENTRY [0].DST = dstAddr ;
/* Calculate the A & B count */
if (size > 0x7000) {
tmp = size / 0x7000 ;
size -= (tmp * 0x7000) ;
tmp <<= 16 ;
tmp |= 0x7000 ;
}
else {
tmp = 0x10000 | size ;
size = 0 ;
}
edmaRegs->PARAMENTRY [0].A_B_CNT = tmp ;
edmaRegs->PARAMENTRY [0].LINK_BCNTRLD = 0xFFFF ;
edmaRegs->PARAMENTRY [0].SRC_DST_CIDX = 0 ;
/* no offset difference required */
edmaRegs->PARAMENTRY [0].SRC_DST_BIDX = 0x70007000 ;
/* C Count is set to 1 since mostly size will not be more than 1GB */
edmaRegs->PARAMENTRY [0].CCNT = 0x1 ;
/* Set the interrupt enable for 1st Channel. */
edmaRegs->EESR |= 0x1 ;
/* Clear any pending interrupt. */
edmaRegs->ESR |= 0x1 ;
/* wait for current DMA to finish. */
numUSec = size / 132 ;
do {
udelay (numUSec) ;
/* now check in steps of 10 usec. */
numUSec = 10 ;
} while ((edmaRegs->IPR & 0x1) == 0) ;
} while (size != 0) ;
/* Clear any pending interrupt. */
edmaRegs->ICR |= 0x1 ;
}
#define DM64LCPCI_LRESET_MASK 0x00000100
#define GEM_MDCTL (0x01C41a00 + (4 * 39))
#define ADDR32(x) *((Uint32 *) ((Uint32)memVirt + x))
#define DM64LCPCI_DSPBOOTADDR 0x01C4000C
#define OP1 0x02084068 /* MVKH.S1 0x10800000,A4 */
#define OP2 0x0090B362 /* BNOP.S2X A4,5 */
Uint32 dummy ;
int init_module(void)
{
Uint8 * writeData ;
Uint8 * readData ;
Uint32 i ;
writeData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;
readData = (Uint8 *) kmalloc (0x8000, GFP_DMA) ;
printk("PCIDRV - Find PCI Devices\n");
PCI_FindPciDevices () ;
mdelay(1000);
printk("PCIDRV - Reading Bar\n");
PCI_readBAR () ;
mdelay(1000);
printk("PCIDRV - Enable Device\n");
pci_enable_device (GEM) ;
mdelay(1000);
printk("PCIDRV - Set DRV Data\n");
pci_set_drvdata (GEM, memVirt) ;
mdelay(1000);
printk("PCIDRV - Set Master\n");
PCI_setMaster () ;
#if 0
/* Enable the DDR2 PSC Module */
HAL_changeState (13, 0x3) ;
/* Programme the PLL1 (DDR2) to run at higher frequency. */
HAL_cfgPLL1 (23, 11, 1) ;
/* Programme the DDR PHY register corresponding to PLL1 frequency. */
HAL_cfgDDR2 (162) ;
/* Reset the DDR2 PSC Module */
HAL_changeState (13, 0x1) ;
/* Enable the DDR2 PSC Module */
HAL_changeState (13, 0x3) ;
#endif
PCI_dma () ;
for (i = 0 ; i < 0x8000 ; i++) {
writeData [i] = 0x42 ;
}
printk("Code ends here\n");
#if 0
if (writeData && readData) {
HAL_writeDMA ((Uint32) virt_to_bus (writeData), 0x80100000, 0x8000) ;
HAL_readDMA (0x80100000, (Uint32) virt_to_bus (readData), 0x8000) ;
if (readData [0] == writeData [0]) {
printk ("API DMA passed\n") ;
}
else {
printk ("API DMA failed %x\n", readData [0]) ;
}
}
#endif
mdelay(1000);
printk("PCIDRV: Registering interrupt\n");
HAL_PciDisableDspInterrupt () ;
printk("Interrupt number is : %d\n", GEM->irq);
request_irq (GEM->irq, ISR_handler5, SA_SHIRQ, "PCIDRV", &dummy) ;
HAL_PciEnableDspInterrupt () ;
mdelay(1000);
printk("PCIDRV: Interrupts registered\n");
if (regVirt) {
/* put GEM in reset */
*((Uint32 *) ((Uint32) regVirt + (GEM_MDCTL - 0x01C00000))) &= ~DM64LCPCI_LRESET_MASK ;
/* Set the DSP boot address. */
*((Uint32 *) ((Uint32) regVirt + (DM64LCPCI_DSPBOOTADDR - 0x01C00000))) = 0x10800000 ;
}
mdelay(1000);
printk("PCIDRV: GEM is reset and Boot address is set\n");
if (memVirt) {
/* Write the self loop code at 0x10800000 */
ADDR32 (0x0) = OP1 ;
ADDR32 (0x4) = OP2 ;
ADDR32 (0x8) = 0x0 ;
ADDR32 (0xC) = 0x0 ;
ADDR32 (0x10) = 0x0 ;
ADDR32 (0x14) = 0x0 ;
ADDR32 (0x18) = 0x0 ;
ADDR32 (0x1C) = 0x0 ;
}
mdelay(1000);
printk("PCIDRV: Opcode written\n");
if (regVirt) {
/* release the GEM from reset */
*((Uint32 *) ((Uint32) regVirt + (GEM_MDCTL - 0x01C00000))) |= DM64LCPCI_LRESET_MASK ;
}
mdelay(1000);
printk("PCIDRV: Release GEM reset\n");
kfree(readData);
kfree(writeData);
return 0 ;
}
void cleanup_module(void)
{
HAL_PciDisableDspInterrupt () ;
iounmap(memVirt) ;
if (pci_resource_flags (GEM, 0) & IORESOURCE_MEM) {
/* Map the memory region. */
release_mem_region (memBase,
memLen);
}
else {
/* Map the memory region. */
release_region (memBase,
memLen);
}
/* ---------------------------------------------------------------------
* Unmap baseRegs region & release the reg region.
* ---------------------------------------------------------------------
*/
iounmap(ddrRegVirt) ;
if (pci_resource_flags (GEM, 1) & IORESOURCE_MEM) {
/* Map the memory region. */
release_mem_region (ddrRegBase,
ddrRegLen);
}
else {
/* Map the memory region. */
release_region (ddrRegBase,
ddrRegLen);
}
/* ---------------------------------------------------------------------
* Unmap baseRegs region & release the reg region.
* ---------------------------------------------------------------------
*/
iounmap(regVirt) ;
if (pci_resource_flags (GEM, 2) & IORESOURCE_MEM) {
/* Map the memory region. */
release_mem_region (regBase,
regLen);
}
else {
/* Map the memory region. */
release_region (regBase,
regLen);
}
free_irq (GEM->irq, &dummy) ;
/* Free the allocated memory for read-write */
kfree((void*)rData);
kfree((void*)wData);
}
//gcc -I/usr/src/linux-2.4/include/ -DMODULE -D__KERNEL__ -c gem.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -