aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2017-05-15 13:23:24 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-07-02 19:42:35 -0400
commit2eeb02b28579fc317504a691f3acb0b9bf94b42b (patch)
tree8525fc52b4e719504ae0070871adcc058492ce2b
parentd1ef28900d6607ea7a25c39a3bd1ce152f6ab24a (diff)
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: Linus 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: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--drivers/pci/host/pci-ftpci100.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/pci/host/pci-ftpci100.c b/drivers/pci/host/pci-ftpci100.c
index e938eebcb180..5162dffc102b 100644
--- a/drivers/pci/host/pci-ftpci100.c
+++ b/drivers/pci/host/pci-ftpci100.c
@@ -25,6 +25,7 @@
25#include <linux/irqchip/chained_irq.h> 25#include <linux/irqchip/chained_irq.h>
26#include <linux/bitops.h> 26#include <linux/bitops.h>
27#include <linux/irq.h> 27#include <linux/irq.h>
28#include <linux/clk.h>
28 29
29/* 30/*
30 * Special configuration registers directly in the first few words 31 * Special configuration registers directly in the first few words
@@ -37,6 +38,7 @@
37#define PCI_CONFIG 0x28 /* PCI configuration command register */ 38#define PCI_CONFIG 0x28 /* PCI configuration command register */
38#define PCI_DATA 0x2C 39#define PCI_DATA 0x2C
39 40
41#define FARADAY_PCI_STATUS_CMD 0x04 /* Status and command */
40#define FARADAY_PCI_PMC 0x40 /* Power management control */ 42#define FARADAY_PCI_PMC 0x40 /* Power management control */
41#define FARADAY_PCI_PMCSR 0x44 /* Power management status */ 43#define FARADAY_PCI_PMCSR 0x44 /* Power management status */
42#define FARADAY_PCI_CTRL1 0x48 /* Control register 1 */ 44#define FARADAY_PCI_CTRL1 0x48 /* Control register 1 */
@@ -45,6 +47,8 @@
45#define FARADAY_PCI_MEM2_BASE_SIZE 0x54 /* Memory base and size #2 */ 47#define FARADAY_PCI_MEM2_BASE_SIZE 0x54 /* Memory base and size #2 */
46#define FARADAY_PCI_MEM3_BASE_SIZE 0x58 /* Memory base and size #3 */ 48#define FARADAY_PCI_MEM3_BASE_SIZE 0x58 /* Memory base and size #3 */
47 49
50#define PCI_STATUS_66MHZ_CAPABLE BIT(21)
51
48/* Bits 31..28 gives INTD..INTA status */ 52/* Bits 31..28 gives INTD..INTA status */
49#define PCI_CTRL2_INTSTS_SHIFT 28 53#define PCI_CTRL2_INTSTS_SHIFT 28
50#define PCI_CTRL2_INTMASK_CMDERR BIT(27) 54#define PCI_CTRL2_INTMASK_CMDERR BIT(27)
@@ -117,6 +121,7 @@ struct faraday_pci {
117 void __iomem *base; 121 void __iomem *base;
118 struct irq_domain *irqdomain; 122 struct irq_domain *irqdomain;
119 struct pci_bus *bus; 123 struct pci_bus *bus;
124 struct clk *bus_clk;
120}; 125};
121 126
122static int faraday_res_to_memcfg(resource_size_t mem_base, 127static int faraday_res_to_memcfg(resource_size_t mem_base,
@@ -444,6 +449,9 @@ static int faraday_pci_probe(struct platform_device *pdev)
444 struct resource *mem; 449 struct resource *mem;
445 struct resource *io; 450 struct resource *io;
446 struct pci_host_bridge *host; 451 struct pci_host_bridge *host;
452 struct clk *clk;
453 unsigned char max_bus_speed = PCI_SPEED_33MHz;
454 unsigned char cur_bus_speed = PCI_SPEED_33MHz;
447 int ret; 455 int ret;
448 u32 val; 456 u32 val;
449 LIST_HEAD(res); 457 LIST_HEAD(res);
@@ -462,6 +470,24 @@ static int faraday_pci_probe(struct platform_device *pdev)
462 host->sysdata = p; 470 host->sysdata = p;
463 p->dev = dev; 471 p->dev = dev;
464 472
473 /* Retrieve and enable optional clocks */
474 clk = devm_clk_get(dev, "PCLK");
475 if (IS_ERR(clk))
476 return PTR_ERR(clk);
477 ret = clk_prepare_enable(clk);
478 if (ret) {
479 dev_err(dev, "could not prepare PCLK\n");
480 return ret;
481 }
482 p->bus_clk = devm_clk_get(dev, "PCICLK");
483 if (IS_ERR(p->bus_clk))
484 return PTR_ERR(clk);
485 ret = clk_prepare_enable(p->bus_clk);
486 if (ret) {
487 dev_err(dev, "could not prepare PCICLK\n");
488 return ret;
489 }
490
465 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 491 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
466 p->base = devm_ioremap_resource(dev, regs); 492 p->base = devm_ioremap_resource(dev, regs);
467 if (IS_ERR(p->base)) 493 if (IS_ERR(p->base))
@@ -524,6 +550,34 @@ static int faraday_pci_probe(struct platform_device *pdev)
524 } 550 }
525 } 551 }
526 552
553 /* Check bus clock if we can gear up to 66 MHz */
554 if (!IS_ERR(p->bus_clk)) {
555 unsigned long rate;
556 u32 val;
557
558 faraday_raw_pci_read_config(p, 0, 0,
559 FARADAY_PCI_STATUS_CMD, 4, &val);
560 rate = clk_get_rate(p->bus_clk);
561
562 if ((rate == 33000000) && (val & PCI_STATUS_66MHZ_CAPABLE)) {
563 dev_info(dev, "33MHz bus is 66MHz capable\n");
564 max_bus_speed = PCI_SPEED_66MHz;
565 ret = clk_set_rate(p->bus_clk, 66000000);
566 if (ret)
567 dev_err(dev, "failed to set bus clock\n");
568 } else {
569 dev_info(dev, "33MHz only bus\n");
570 max_bus_speed = PCI_SPEED_33MHz;
571 }
572
573 /* Bumping the clock may fail so read back the rate */
574 rate = clk_get_rate(p->bus_clk);
575 if (rate == 33000000)
576 cur_bus_speed = PCI_SPEED_33MHz;
577 if (rate == 66000000)
578 cur_bus_speed = PCI_SPEED_66MHz;
579 }
580
527 ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node); 581 ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
528 if (ret) 582 if (ret)
529 return ret; 583 return ret;
@@ -535,6 +589,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
535 return ret; 589 return ret;
536 } 590 }
537 p->bus = host->bus; 591 p->bus = host->bus;
592 p->bus->max_bus_speed = max_bus_speed;
593 p->bus->cur_bus_speed = cur_bus_speed;
538 594
539 pci_bus_assign_resources(p->bus); 595 pci_bus_assign_resources(p->bus);
540 pci_bus_add_devices(p->bus); 596 pci_bus_add_devices(p->bus);