📄 ops-pmcmsp.c
字号:
* * FUNCTION: msp_pcibios_config_access * _________________________________________________________________________ * * DESCRIPTION: Performs a PCI configuration access (rd or wr), then * checks that the access succeeded by querying MSP7120's * PCI status bits. * * INPUTS: * access_type - kind of PCI configuration cycle to perform * (read or write). Legal values are * PCI_ACCESS_WRITE and PCI_ACCESS_READ. * * bus - pointer to the bus number of the device to * be targetted for the configuration cycle. * The only element of the pci_bus structure * used is bus->number. This argument determines * if the configuration access will be Type 0 or * Type 1. Since MSP7120 assumes itself to be the * PCI Host, any non-zero bus->number generates * a Type 1 access. * * devfn - this is an 8-bit field. The lower three bits * specify the function number of the device to * be targetted for the configuration cycle, with * all three-bit combinations being legal. The * upper five bits specify the device number, * with legal values being 10 to 31. * * where - address within the Configuration Header * space to access. * * data - for write accesses, contains the data to * write. * * OUTPUTS: * data - for read accesses, contains the value read. * * RETURNS: PCIBIOS_SUCCESSFUL - success * -1 - access failure * ****************************************************************************/int msp_pcibios_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, unsigned char where, u32 *data){ struct msp_pci_regs *preg = (void *)PCI_BASE_REG; unsigned char bus_num = bus->number; unsigned char dev_fn = (unsigned char)devfn; unsigned long flags; unsigned long intr; unsigned long value; static char pciirqflag;#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) unsigned int vpe_status;#endif#if defined(CONFIG_PROC_FS) && defined(PCI_COUNTERS) if (proc_init == 0) { pci_proc_init(); proc_init = ~0; }#endif /* CONFIG_PROC_FS && PCI_COUNTERS */ /* * Just the first time this function invokes, allocate * an interrupt line for PCI host status interrupts. The * allocation assigns an interrupt handler to the interrupt. */ if (pciirqflag == 0) { request_irq(MSP_INT_PCI,/* Hardcoded internal MSP7120 wiring */ bpci_interrupt, IRQF_SHARED | IRQF_DISABLED, "PMC MSP PCI Host", preg); pciirqflag = ~0; }#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) local_irq_save(flags); vpe_status = dvpe();#else spin_lock_irqsave(&bpci_lock, flags);#endif /* * Clear PCI cause register bits. * * In Polo, the PCI Host had a dedicated DMA called the * Block Copy (not to be confused with the general purpose Block * Copy Engine block). There appear to have been special interrupts * for this Block Copy, called Block Copy 0 Fault (BC0F) and * Block Copy 1 Fault (BC1F). MSP4200 and MSP7120 don't have this * dedicated Block Copy block, so these two interrupts are now * marked reserved. In case the Block Copy is resurrected in a * future design, maintain the code that treats these two interrupts * specially. * * Write to clear all interrupts in the PCI status register, aside * from BC0F and BC1F. */ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F); /* Setup address that is to appear on PCI bus */ preg->config_addr = BPCI_CFGADDR_ENABLE | (bus_num << BPCI_CFGADDR_BUSNUM_SHF) | (dev_fn << BPCI_CFGADDR_FUNCTNUM_SHF) | (where & 0xFC); /* IF access is a PCI configuration write */ if (access_type == PCI_ACCESS_WRITE) { value = cpu_to_le32(*data); *PCI_CONFIG_SPACE_REG = value; } else { /* ELSE access is a PCI configuration read */ value = le32_to_cpu(*PCI_CONFIG_SPACE_REG); *data = value; } /* * Check if the PCI configuration cycle (rd or wr) succeeded, by * checking the status bits for errors like master or target abort. */ intr = preg->if_status; /* Clear config access */ preg->config_addr = 0; /* IF error occurred */ if (intr & ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F)) { /* Clear status bits */ preg->if_status = ~(BPCI_IFSTATUS_BC0F | BPCI_IFSTATUS_BC1F);#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) evpe(vpe_status); local_irq_restore(flags);#else spin_unlock_irqrestore(&bpci_lock, flags);#endif return -1; }#if defined(CONFIG_PMC_MSP7120_GW) || defined(CONFIG_PMC_MSP7120_EVAL) evpe(vpe_status); local_irq_restore(flags);#else spin_unlock_irqrestore(&bpci_lock, flags);#endif return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_read_config_byte * _________________________________________________________________________ * * DESCRIPTION: Read a byte from PCI configuration address spac * Since the hardware can't address 8 bit chunks * directly, read a 32-bit chunk, then mask off extraneous * bits. * * INPUTS bus - structure containing attributes for the PCI bus * that the read is destined for. * devfn - device/function combination that the read is * destined for. * where - register within the Configuration Header space * to access. * * OUTPUTS val - read data * * RETURNS: PCIBIOS_SUCCESSFUL - success * -1 - read access failure * ****************************************************************************/static intmsp_pcibios_read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u32 *val){ u32 data = 0; /* * If the config access did not complete normally (e.g., underwent * master abort) do the PCI compliant thing, which is to supply an * all ones value. */ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) { *val = 0xFFFFFFFF; return -1; } *val = (data >> ((where & 3) << 3)) & 0x0ff; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_read_config_word * _________________________________________________________________________ * * DESCRIPTION: Read a word (16 bits) from PCI configuration address space. * Since the hardware can't address 16 bit chunks * directly, read a 32-bit chunk, then mask off extraneous * bits. * * INPUTS bus - structure containing attributes for the PCI bus * that the read is destined for. * devfn - device/function combination that the read is * destined for. * where - register within the Configuration Header space * to access. * * OUTPUTS val - read data * * RETURNS: PCIBIOS_SUCCESSFUL - success * PCIBIOS_BAD_REGISTER_NUMBER - bad register address * -1 - read access failure * ****************************************************************************/static intmsp_pcibios_read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u32 *val){ u32 data = 0; /* if (where & 1) */ /* Commented out non-compliant code. * Should allow word access to configuration * registers, with only exception being when * the word access would wrap around into * the next dword. */ if ((where & 3) == 3) { *val = 0xFFFFFFFF; return PCIBIOS_BAD_REGISTER_NUMBER; } /* * If the config access did not complete normally (e.g., underwent * master abort) do the PCI compliant thing, which is to supply an * all ones value. */ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) { *val = 0xFFFFFFFF; return -1; } *val = (data >> ((where & 3) << 3)) & 0x0ffff; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_read_config_dword * _________________________________________________________________________ * * DESCRIPTION: Read a double word (32 bits) from PCI configuration * address space. * * INPUTS bus - structure containing attributes for the PCI bus * that the read is destined for. * devfn - device/function combination that the read is * destined for. * where - register within the Configuration Header space * to access. * * OUTPUTS val - read data * * RETURNS: PCIBIOS_SUCCESSFUL - success * PCIBIOS_BAD_REGISTER_NUMBER - bad register address * -1 - read access failure * ****************************************************************************/static intmsp_pcibios_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 *val){ u32 data = 0; /* Address must be dword aligned. */ if (where & 3) { *val = 0xFFFFFFFF; return PCIBIOS_BAD_REGISTER_NUMBER; } /* * If the config access did not complete normally (e.g., underwent * master abort) do the PCI compliant thing, which is to supply an * all ones value. */ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) { *val = 0xFFFFFFFF; return -1; } *val = data; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_write_config_byte * _________________________________________________________________________ * * DESCRIPTION: Write a byte to PCI configuration address space. * Since the hardware can't address 8 bit chunks * directly, a read-modify-write is performed. * * INPUTS bus - structure containing attributes for the PCI bus * that the write is destined for. * devfn - device/function combination that the write is * destined for. * where - register within the Configuration Header space * to access. * val - value to write * * OUTPUTS none *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -