📄 ops-pmcmsp.c
字号:
* RETURNS: PCIBIOS_SUCCESSFUL - success * -1 - write access failure * ****************************************************************************/static intmsp_pcibios_write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val){ u32 data = 0; /* read config space */ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) return -1; /* modify the byte within the dword */ data = (data & ~(0xff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); /* write back the full dword */ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) return -1; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_write_config_word * _________________________________________________________________________ * * DESCRIPTION: Write a word (16-bits) to PCI configuration address space. * Since the hardware can't address 16 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 * * RETURNS: PCIBIOS_SUCCESSFUL - success * PCIBIOS_BAD_REGISTER_NUMBER - bad register address * -1 - write access failure * ****************************************************************************/static intmsp_pcibios_write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val){ u32 data = 0; /* Fixed non-compliance: if (where & 1) */ if ((where & 3) == 3) return PCIBIOS_BAD_REGISTER_NUMBER; /* read config space */ if (msp_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) return -1; /* modify the word within the dword */ data = (data & ~(0xffff << ((where & 3) << 3))) | (val << ((where & 3) << 3)); /* write back the full dword */ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) return -1; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_write_config_dword * _________________________________________________________________________ * * DESCRIPTION: Write a double word (32-bits) to PCI configuration address * space. * * 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 * * RETURNS: PCIBIOS_SUCCESSFUL - success * PCIBIOS_BAD_REGISTER_NUMBER - bad register address * -1 - write access failure * ****************************************************************************/static intmsp_pcibios_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val){ /* check that address is dword aligned */ if (where & 3) return PCIBIOS_BAD_REGISTER_NUMBER; /* perform write */ if (msp_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) return -1; return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_read_config * _________________________________________________________________________ * * DESCRIPTION: Interface the PCI configuration read request with * the appropriate function, based on how many bytes * the read request is. * * 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. * size - in units of bytes, should be 1, 2, or 4. * * OUTPUTS val - value read, with any extraneous bytes masked * to zero. * * RETURNS: PCIBIOS_SUCCESSFUL - success * -1 - failure * ****************************************************************************/intmsp_pcibios_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val){ if (size == 1) { if (msp_pcibios_read_config_byte(bus, devfn, where, val)) { return -1; } } else if (size == 2) { if (msp_pcibios_read_config_word(bus, devfn, where, val)) { return -1; } } else if (size == 4) { if (msp_pcibios_read_config_dword(bus, devfn, where, val)) { return -1; } } else { *val = 0xFFFFFFFF; return -1; } return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * FUNCTION: msp_pcibios_write_config * _________________________________________________________________________ * * DESCRIPTION: Interface the PCI configuration write request with * the appropriate function, based on how many bytes * the read request is. * * 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. * size - in units of bytes, should be 1, 2, or 4. * val - value to write * * OUTPUTS: none * * RETURNS: PCIBIOS_SUCCESSFUL - success * -1 - failure * ****************************************************************************/intmsp_pcibios_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val){ if (size == 1) { if (msp_pcibios_write_config_byte(bus, devfn, where, (u8)(0xFF & val))) { return -1; } } else if (size == 2) { if (msp_pcibios_write_config_word(bus, devfn, where, (u16)(0xFFFF & val))) { return -1; } } else if (size == 4) { if (msp_pcibios_write_config_dword(bus, devfn, where, val)) { return -1; } } else { return -1; } return PCIBIOS_SUCCESSFUL;}/***************************************************************************** * * STRUCTURE: msp_pci_ops * _________________________________________________________________________ * * DESCRIPTION: structure to abstract the hardware specific PCI * configuration accesses. * * ELEMENTS: * read - function for Linux to generate PCI Configuration reads. * write - function for Linux to generate PCI Configuration writes. * ****************************************************************************/struct pci_ops msp_pci_ops = { .read = msp_pcibios_read_config, .write = msp_pcibios_write_config};/***************************************************************************** * * STRUCTURE: msp_pci_controller * _________________________________________________________________________ * * Describes the attributes of the MSP7120 PCI Host Controller * * ELEMENTS: * pci_ops - abstracts the hardware specific PCI configuration * accesses. * * mem_resource - address range pciauto() uses to assign to PCI device * memory BARs. * * mem_offset - offset between how MSP7120 outbound PCI memory * transaction addresses appear on the PCI bus and how Linux * wants to configure memory BARs of the PCI devices. * MSP7120 does nothing funky, so just set to zero. * * io_resource - address range pciauto() uses to assign to PCI device * I/O BARs. * * io_offset - offset between how MSP7120 outbound PCI I/O * transaction addresses appear on the PCI bus and how * Linux defaults to configure I/O BARs of the PCI devices. * MSP7120 maps outbound I/O accesses into the bottom * bottom 4K of PCI address space (and ignores OATRAN). * Since the Linux default is to configure I/O BARs to the * bottom 4K, no special offset is needed. Just set to zero. * ****************************************************************************/static struct pci_controller msp_pci_controller = { .pci_ops = &msp_pci_ops, .mem_resource = &pci_mem_resource, .mem_offset = 0, .io_resource = &pci_io_resource, .io_offset = 0};/***************************************************************************** * * FUNCTION: msp_pci_init * _________________________________________________________________________ * * DESCRIPTION: Initialize the PCI Host Controller and register it with * Linux so Linux can seize control of the PCI bus. * ****************************************************************************/void __init msp_pci_init(void){ struct msp_pci_regs *preg = (void *)PCI_BASE_REG; u32 id; /* Extract Device ID */ id = read_reg32(PCI_JTAG_DEVID_REG, 0xFFFF) >> 12; /* Check if JTAG ID identifies MSP7120 */ if (!MSP_HAS_PCI(id)) { printk(KERN_WARNING "PCI: No PCI; id reads as %x\n", id); goto no_pci; } /* * Enable flushing of the PCI-SDRAM queue upon a read * of the SDRAM's Memory Configuration Register. */ *(unsigned long *)QFLUSH_REG_1 = 3; /* Configure PCI Host Controller. */ preg->if_status = ~0; /* Clear cause register bits */ preg->config_addr = 0; /* Clear config access */ preg->oatran = MSP_PCI_OATRAN; /* PCI outbound addr translation */ preg->if_mask = 0xF8BF87C0; /* Enable all PCI status interrupts */ /* configure so inb(), outb(), and family are functional */ set_io_port_base(MSP_PCI_IOSPACE_BASE); /* Tell Linux the details of the MSP7120 PCI Host Controller */ register_pci_controller(&msp_pci_controller); return;no_pci: /* Disable PCI channel */ printk(KERN_WARNING "PCI: no host PCI bus detected\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -