Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2c4e82e authored by Kevin Hilman's avatar Kevin Hilman
Browse files

Merge tag 'drivers-3.13-2' of git://git.infradead.org/linux-mvebu into next/drivers

From Jason Cooper:
mvebu driver changes for v3.13 (round 2)

 - mvebu
    - pcie
       - dynamic link up detection
       - add IO wrappers
       - declare some local functions static

* tag 'drivers-3.13-2' of git://git.infradead.org/linux-mvebu

:
  PCI: mvebu: make local functions static
  PCI: mvebu: add I/O access wrappers
  PCI: mvebu: Dynamically detect if the PEX link is up to enable hot plug

Signed-off-by: default avatarKevin Hilman <khilman@linaro.org>
parents e85923ac f5072dfb
Loading
Loading
Loading
Loading
+69 −59
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ struct mvebu_pcie_port {
	char *name;
	void __iomem *base;
	spinlock_t conf_lock;
	int haslink;
	u32 port;
	u32 lane;
	int devfn;
@@ -141,29 +140,39 @@ struct mvebu_pcie_port {
	size_t iowin_size;
};

static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg)
{
	writel(val, port->base + reg);
}

static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg)
{
	return readl(port->base + reg);
}

static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
{
	return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
	return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
}

static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
{
	u32 stat;

	stat = readl(port->base + PCIE_STAT_OFF);
	stat = mvebu_readl(port, PCIE_STAT_OFF);
	stat &= ~PCIE_STAT_BUS;
	stat |= nr << 8;
	writel(stat, port->base + PCIE_STAT_OFF);
	mvebu_writel(port, stat, PCIE_STAT_OFF);
}

static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
{
	u32 stat;

	stat = readl(port->base + PCIE_STAT_OFF);
	stat = mvebu_readl(port, PCIE_STAT_OFF);
	stat &= ~PCIE_STAT_DEV;
	stat |= nr << 16;
	writel(stat, port->base + PCIE_STAT_OFF);
	mvebu_writel(port, stat, PCIE_STAT_OFF);
}

/*
@@ -181,33 +190,34 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)

	/* First, disable and clear BARs and windows. */
	for (i = 1; i < 3; i++) {
		writel(0, port->base + PCIE_BAR_CTRL_OFF(i));
		writel(0, port->base + PCIE_BAR_LO_OFF(i));
		writel(0, port->base + PCIE_BAR_HI_OFF(i));
		mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i));
		mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i));
		mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i));
	}

	for (i = 0; i < 5; i++) {
		writel(0, port->base + PCIE_WIN04_CTRL_OFF(i));
		writel(0, port->base + PCIE_WIN04_BASE_OFF(i));
		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
		mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i));
		mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i));
		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
	}

	writel(0, port->base + PCIE_WIN5_CTRL_OFF);
	writel(0, port->base + PCIE_WIN5_BASE_OFF);
	writel(0, port->base + PCIE_WIN5_REMAP_OFF);
	mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF);
	mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF);
	mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF);

	/* Setup windows for DDR banks.  Count total DDR size on the fly. */
	size = 0;
	for (i = 0; i < dram->num_cs; i++) {
		const struct mbus_dram_window *cs = dram->cs + i;

		writel(cs->base & 0xffff0000,
		       port->base + PCIE_WIN04_BASE_OFF(i));
		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
		writel(((cs->size - 1) & 0xffff0000) |
		mvebu_writel(port, cs->base & 0xffff0000,
			     PCIE_WIN04_BASE_OFF(i));
		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));
		mvebu_writel(port,
			     ((cs->size - 1) & 0xffff0000) |
			     (cs->mbus_attr << 8) |
			     (dram->mbus_dram_target_id << 4) | 1,
		       port->base + PCIE_WIN04_CTRL_OFF(i));
			     PCIE_WIN04_CTRL_OFF(i));

		size += cs->size;
	}
@@ -217,41 +227,40 @@ static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
		size = 1 << fls(size);

	/* Setup BAR[1] to all DRAM banks. */
	writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1));
	writel(0, port->base + PCIE_BAR_HI_OFF(1));
	writel(((size - 1) & 0xffff0000) | 1,
	       port->base + PCIE_BAR_CTRL_OFF(1));
	mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1));
	mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1));
	mvebu_writel(port, ((size - 1) & 0xffff0000) | 1,
		     PCIE_BAR_CTRL_OFF(1));
}

static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
{
	u16 cmd;
	u32 mask;
	u32 cmd, mask;

	/* Point PCIe unit MBUS decode windows to DRAM space. */
	mvebu_pcie_setup_wins(port);

	/* Master + slave enable. */
	cmd = readw(port->base + PCIE_CMD_OFF);
	cmd = mvebu_readl(port, PCIE_CMD_OFF);
	cmd |= PCI_COMMAND_IO;
	cmd |= PCI_COMMAND_MEMORY;
	cmd |= PCI_COMMAND_MASTER;
	writew(cmd, port->base + PCIE_CMD_OFF);
	mvebu_writel(port, cmd, PCIE_CMD_OFF);

	/* Enable interrupt lines A-D. */
	mask = readl(port->base + PCIE_MASK_OFF);
	mask = mvebu_readl(port, PCIE_MASK_OFF);
	mask |= PCIE_MASK_ENABLE_INTS;
	writel(mask, port->base + PCIE_MASK_OFF);
	mvebu_writel(port, mask, PCIE_MASK_OFF);
}

static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
				 struct pci_bus *bus,
				 u32 devfn, int where, int size, u32 *val)
{
	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
	       port->base + PCIE_CONF_ADDR_OFF);
	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
		     PCIE_CONF_ADDR_OFF);

	*val = readl(port->base + PCIE_CONF_DATA_OFF);
	*val = mvebu_readl(port, PCIE_CONF_DATA_OFF);

	if (size == 1)
		*val = (*val >> (8 * (where & 3))) & 0xff;
@@ -265,21 +274,24 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
				 struct pci_bus *bus,
				 u32 devfn, int where, int size, u32 val)
{
	int ret = PCIBIOS_SUCCESSFUL;
	u32 _val, shift = 8 * (where & 3);

	writel(PCIE_CONF_ADDR(bus->number, devfn, where),
	       port->base + PCIE_CONF_ADDR_OFF);
	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
		     PCIE_CONF_ADDR_OFF);
	_val = mvebu_readl(port, PCIE_CONF_DATA_OFF);

	if (size == 4)
		writel(val, port->base + PCIE_CONF_DATA_OFF);
		_val = val;
	else if (size == 2)
		writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
	else if (size == 1)
		writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
	else
		ret = PCIBIOS_BAD_REGISTER_NUMBER;
		return PCIBIOS_BAD_REGISTER_NUMBER;

	return ret;
	mvebu_writel(port, _val, PCIE_CONF_DATA_OFF);

	return PCIBIOS_SUCCESSFUL;
}

static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
@@ -560,7 +572,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
	if (bus->number == 0)
		return mvebu_sw_pci_bridge_write(port, where, size, val);

	if (!port->haslink)
	if (!mvebu_pcie_link_up(port))
		return PCIBIOS_DEVICE_NOT_FOUND;

	/*
@@ -602,7 +614,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
	if (bus->number == 0)
		return mvebu_sw_pci_bridge_read(port, where, size, val);

	if (!port->haslink) {
	if (!mvebu_pcie_link_up(port)) {
		*val = 0xffffffff;
		return PCIBIOS_DEVICE_NOT_FOUND;
	}
@@ -681,13 +693,13 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
	return bus;
}

void mvebu_pcie_add_bus(struct pci_bus *bus)
static void mvebu_pcie_add_bus(struct pci_bus *bus)
{
	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
	bus->msi = pcie->msi;
}

resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
						const struct resource *res,
						resource_size_t start,
						resource_size_t size,
@@ -950,14 +962,12 @@ static int mvebu_pcie_probe(struct platform_device *pdev)

		mvebu_pcie_set_local_dev_nr(port, 1);

		if (mvebu_pcie_link_up(port)) {
			port->haslink = 1;
			dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
				 port->port, port->lane);
		} else {
			port->haslink = 0;
			dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
		port->clk = of_clk_get_by_name(child, NULL);
		if (IS_ERR(port->clk)) {
			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
			       port->port, port->lane);
			iounmap(port->base);
			continue;
		}

		port->dn = child;