예제 #1
0
int cpci_led_off(struct slot* slot)
{
    int hs_cap;
    u16 hs_csr;

    hs_cap = pci_bus_find_capability(slot->bus,
                     slot->devfn,
                     PCI_CAP_ID_CHSWP);
    if (!hs_cap)
        return -ENODEV;
    if (pci_bus_read_config_word(slot->bus,
                     slot->devfn,
                     hs_cap + 2,
                     &hs_csr))
        return -ENODEV;
    if (hs_csr & HS_CSR_LOO) {
        hs_csr &= ~HS_CSR_LOO;
        if (pci_bus_write_config_word(slot->bus,
                          slot->devfn,
                          hs_cap + 2,
                          hs_csr)) {
            err("Could not clear LOO for slot %s",
                slot->hotplug_slot->name);
            return -ENODEV;
        }
    }
    return 0;
}
예제 #2
0
int cpci_set_attention_status(struct slot* slot, int status)
{
    int hs_cap;
    u16 hs_csr;

    hs_cap = pci_bus_find_capability(slot->bus,
                     slot->devfn,
                     PCI_CAP_ID_CHSWP);
    if (!hs_cap)
        return 0;
    if (pci_bus_read_config_word(slot->bus,
                     slot->devfn,
                     hs_cap + 2,
                     &hs_csr))
        return 0;
    if (status)
        hs_csr |= HS_CSR_LOO;
    else
        hs_csr &= ~HS_CSR_LOO;
    if (pci_bus_write_config_word(slot->bus,
                      slot->devfn,
                      hs_cap + 2,
                      hs_csr))
        return 0;
    return 1;
}
예제 #3
0
int cpci_clear_ext(struct slot* slot)
{
    int hs_cap;
    u16 hs_csr;

    hs_cap = pci_bus_find_capability(slot->bus,
                     slot->devfn,
                     PCI_CAP_ID_CHSWP);
    if (!hs_cap)
        return -ENODEV;
    if (pci_bus_read_config_word(slot->bus,
                     slot->devfn,
                     hs_cap + 2,
                     &hs_csr))
        return -ENODEV;
    if (hs_csr & HS_CSR_EXT) {
        /* Clear EXT (by setting it) */
        if (pci_bus_write_config_word(slot->bus,
                          slot->devfn,
                          hs_cap + 2,
                          hs_csr))
            return -ENODEV;
    }
    return 0;
}
예제 #4
0
int cpci_check_and_clear_ins(struct slot* slot)
{
    int hs_cap;
    u16 hs_csr;
    int ins = 0;

    hs_cap = pci_bus_find_capability(slot->bus,
                     slot->devfn,
                     PCI_CAP_ID_CHSWP);
    if (!hs_cap)
        return 0;
    if (pci_bus_read_config_word(slot->bus,
                     slot->devfn,
                     hs_cap + 2,
                     &hs_csr))
        return 0;
    if (hs_csr & HS_CSR_INS) {
        /* Clear INS (by setting it) */
        if (pci_bus_write_config_word(slot->bus,
                          slot->devfn,
                          hs_cap + 2,
                          hs_csr))
            ins = 0;
        else
            ins = 1;
    }
    return ins;
}
예제 #5
0
파일: pcie-iproc.c 프로젝트: DenisLug/mptcp
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
{
	u8 hdr_type;
	u32 link_ctrl;
	u16 pos, link_status;
	int link_is_active = 0;

	/* make sure we are not in EP mode */
	pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type);
	if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) {
		dev_err(pcie->dev, "in EP mode, hdr=%#02x\n", hdr_type);
		return -EFAULT;
	}

	/* force class to PCI_CLASS_BRIDGE_PCI (0x0604) */
	pci_bus_write_config_word(bus, 0, PCI_CLASS_DEVICE,
				  PCI_CLASS_BRIDGE_PCI);

	/* check link status to see if link is active */
	pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
	pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status);
	if (link_status & PCI_EXP_LNKSTA_NLW)
		link_is_active = 1;

	if (!link_is_active) {
		/* try GEN 1 link speed */
#define PCI_LINK_STATUS_CTRL_2_OFFSET 0x0dc
#define PCI_TARGET_LINK_SPEED_MASK    0xf
#define PCI_TARGET_LINK_SPEED_GEN2    0x2
#define PCI_TARGET_LINK_SPEED_GEN1    0x1
		pci_bus_read_config_dword(bus, 0,
					  PCI_LINK_STATUS_CTRL_2_OFFSET,
					  &link_ctrl);
		if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) ==
		    PCI_TARGET_LINK_SPEED_GEN2) {
			link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK;
			link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1;
			pci_bus_write_config_dword(bus, 0,
					   PCI_LINK_STATUS_CTRL_2_OFFSET,
					   link_ctrl);
			msleep(100);

			pos = pci_bus_find_capability(bus, 0, PCI_CAP_ID_EXP);
			pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA,
						 &link_status);
			if (link_status & PCI_EXP_LNKSTA_NLW)
				link_is_active = 1;
		}
	}

	dev_info(pcie->dev, "link: %s\n", link_is_active ? "UP" : "DOWN");

	return link_is_active ? 0 : -ENODEV;
}
예제 #6
0
int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
{
	if (pci_dev_is_disconnected(dev))
		return PCIBIOS_DEVICE_NOT_FOUND;
	return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
}
예제 #7
0
파일: pcie.c 프로젝트: 01org/prd
static void __init cns3xxx_pcie_hw_init(struct cns3xxx_pcie *cnspci)
{
	int port = cnspci->port;
	struct pci_sys_data sd = {
		.private_data = cnspci,
	};
	struct pci_bus bus = {
		.number = 0,
		.ops = &cns3xxx_pcie_ops,
		.sysdata = &sd,
	};
	u16 mem_base  = cnspci->res_mem.start >> 16;
	u16 mem_limit = cnspci->res_mem.end   >> 16;
	u16 io_base   = cnspci->res_io.start  >> 16;
	u16 io_limit  = cnspci->res_io.end    >> 16;
	u32 devfn = 0;
	u8 tmp8;
	u16 pos;
	u16 dc;

	pci_bus_write_config_byte(&bus, devfn, PCI_PRIMARY_BUS, 0);
	pci_bus_write_config_byte(&bus, devfn, PCI_SECONDARY_BUS, 1);
	pci_bus_write_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, 1);

	pci_bus_read_config_byte(&bus, devfn, PCI_PRIMARY_BUS, &tmp8);
	pci_bus_read_config_byte(&bus, devfn, PCI_SECONDARY_BUS, &tmp8);
	pci_bus_read_config_byte(&bus, devfn, PCI_SUBORDINATE_BUS, &tmp8);

	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_BASE, mem_base);
	pci_bus_write_config_word(&bus, devfn, PCI_MEMORY_LIMIT, mem_limit);
	pci_bus_write_config_word(&bus, devfn, PCI_IO_BASE_UPPER16, io_base);
	pci_bus_write_config_word(&bus, devfn, PCI_IO_LIMIT_UPPER16, io_limit);

	if (!cnspci->linked)
		return;

	/* Set Device Max_Read_Request_Size to 128 byte */
	bus.number = 1; /* directly connected PCIe device */
	devfn = PCI_DEVFN(0, 0);
	pos = pci_bus_find_capability(&bus, devfn, PCI_CAP_ID_EXP);
	pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
	if (dc & PCI_EXP_DEVCTL_READRQ) {
		dc &= ~PCI_EXP_DEVCTL_READRQ;
		pci_bus_write_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, dc);
		pci_bus_read_config_word(&bus, devfn, pos + PCI_EXP_DEVCTL, &dc);
		if (dc & PCI_EXP_DEVCTL_READRQ)
			pr_warn("PCIe: Unable to set device Max_Read_Request_Size\n");
		else
			pr_info("PCIe: Max_Read_Request_Size set to 128 bytes\n");
	}
	/* Disable PCIe0 Interrupt Mask INTA to INTD */
	__raw_writel(~0x3FFF, MISC_PCIE_INT_MASK(port));
}

static int cns3xxx_pcie_abort_handler(unsigned long addr, unsigned int fsr,
				      struct pt_regs *regs)
{
	if (fsr & (1 << 10))
		regs->ARM_pc += 4;
	return 0;
}

void __init cns3xxx_pcie_init_late(void)
{
	int i;
	void *private_data;
	struct hw_pci hw_pci = {
	       .nr_controllers = 1,
	       .ops = &cns3xxx_pcie_ops,
	       .setup = cns3xxx_pci_setup,
	       .map_irq = cns3xxx_pcie_map_irq,
	       .private_data = &private_data,
	};

	pcibios_min_io = 0;
	pcibios_min_mem = 0;

	hook_fault_code(16 + 6, cns3xxx_pcie_abort_handler, SIGBUS, 0,
			"imprecise external abort");

	for (i = 0; i < ARRAY_SIZE(cns3xxx_pcie); i++) {
		cns3xxx_pwr_clk_en(0x1 << PM_CLK_GATE_REG_OFFSET_PCIE(i));
		cns3xxx_pwr_soft_rst(0x1 << PM_SOFT_RST_REG_OFFST_PCIE(i));
		cns3xxx_pcie_check_link(&cns3xxx_pcie[i]);
		cns3xxx_pcie_hw_init(&cns3xxx_pcie[i]);
		private_data = &cns3xxx_pcie[i];
		pci_common_init(&hw_pci);
	}

	pci_assign_unassigned_resources();
}