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

Commit 2eeb02b2 authored by Linus Walleij's avatar Linus Walleij Committed by Bjorn Helgaas
Browse files

PCI: faraday: Add clock handling



Add some optional clock handling to the Faraday FTPCI100.  We just get and
prepare+enable the clocks right now, if they exist.  We can add more
elaborate clock handling later.

Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
[bhelgaas: folded in "Make clocks compulsory" fix from
http://lkml.kernel.org/r/20170621085730.28804-1-linus.walleij@linaro.org
Also folded in the clock max/cur speed fixes from
http://lkml.kernel.org/r/20170621162651.25315-1-linus.walleij@linaro.org

]
Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
parent d1ef2890
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/irqchip/chained_irq.h>
#include <linux/bitops.h>
#include <linux/irq.h>
#include <linux/clk.h>

/*
 * Special configuration registers directly in the first few words
@@ -37,6 +38,7 @@
#define PCI_CONFIG	0x28 /* PCI configuration command register */
#define PCI_DATA	0x2C

#define FARADAY_PCI_STATUS_CMD		0x04 /* Status and command */
#define FARADAY_PCI_PMC			0x40 /* Power management control */
#define FARADAY_PCI_PMCSR		0x44 /* Power management status */
#define FARADAY_PCI_CTRL1		0x48 /* Control register 1 */
@@ -45,6 +47,8 @@
#define FARADAY_PCI_MEM2_BASE_SIZE	0x54 /* Memory base and size #2 */
#define FARADAY_PCI_MEM3_BASE_SIZE	0x58 /* Memory base and size #3 */

#define PCI_STATUS_66MHZ_CAPABLE	BIT(21)

/* Bits 31..28 gives INTD..INTA status */
#define PCI_CTRL2_INTSTS_SHIFT		28
#define PCI_CTRL2_INTMASK_CMDERR	BIT(27)
@@ -117,6 +121,7 @@ struct faraday_pci {
	void __iomem *base;
	struct irq_domain *irqdomain;
	struct pci_bus *bus;
	struct clk *bus_clk;
};

static int faraday_res_to_memcfg(resource_size_t mem_base,
@@ -444,6 +449,9 @@ static int faraday_pci_probe(struct platform_device *pdev)
	struct resource *mem;
	struct resource *io;
	struct pci_host_bridge *host;
	struct clk *clk;
	unsigned char max_bus_speed = PCI_SPEED_33MHz;
	unsigned char cur_bus_speed = PCI_SPEED_33MHz;
	int ret;
	u32 val;
	LIST_HEAD(res);
@@ -462,6 +470,24 @@ static int faraday_pci_probe(struct platform_device *pdev)
	host->sysdata = p;
	p->dev = dev;

	/* Retrieve and enable optional clocks */
	clk = devm_clk_get(dev, "PCLK");
	if (IS_ERR(clk))
		return PTR_ERR(clk);
	ret = clk_prepare_enable(clk);
	if (ret) {
		dev_err(dev, "could not prepare PCLK\n");
		return ret;
	}
	p->bus_clk = devm_clk_get(dev, "PCICLK");
	if (IS_ERR(p->bus_clk))
		return PTR_ERR(clk);
	ret = clk_prepare_enable(p->bus_clk);
	if (ret) {
		dev_err(dev, "could not prepare PCICLK\n");
		return ret;
	}

	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	p->base = devm_ioremap_resource(dev, regs);
	if (IS_ERR(p->base))
@@ -524,6 +550,34 @@ static int faraday_pci_probe(struct platform_device *pdev)
		}
	}

	/* Check bus clock if we can gear up to 66 MHz */
	if (!IS_ERR(p->bus_clk)) {
		unsigned long rate;
		u32 val;

		faraday_raw_pci_read_config(p, 0, 0,
					    FARADAY_PCI_STATUS_CMD, 4, &val);
		rate = clk_get_rate(p->bus_clk);

		if ((rate == 33000000) && (val & PCI_STATUS_66MHZ_CAPABLE)) {
			dev_info(dev, "33MHz bus is 66MHz capable\n");
			max_bus_speed = PCI_SPEED_66MHz;
			ret = clk_set_rate(p->bus_clk, 66000000);
			if (ret)
				dev_err(dev, "failed to set bus clock\n");
		} else {
			dev_info(dev, "33MHz only bus\n");
			max_bus_speed = PCI_SPEED_33MHz;
		}

		/* Bumping the clock may fail so read back the rate */
		rate = clk_get_rate(p->bus_clk);
		if (rate == 33000000)
			cur_bus_speed = PCI_SPEED_33MHz;
		if (rate == 66000000)
			cur_bus_speed = PCI_SPEED_66MHz;
	}

	ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
	if (ret)
		return ret;
@@ -535,6 +589,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
		return ret;
	}
	p->bus = host->bus;
	p->bus->max_bus_speed = max_bus_speed;
	p->bus->cur_bus_speed = cur_bus_speed;

	pci_bus_assign_resources(p->bus);
	pci_bus_add_devices(p->bus);