diff options
author | Linus Walleij <linus.walleij@linaro.org> | 2017-05-15 13:23:24 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2017-07-02 19:42:35 -0400 |
commit | 2eeb02b28579fc317504a691f3acb0b9bf94b42b (patch) | |
tree | 8525fc52b4e719504ae0070871adcc058492ce2b | |
parent | d1ef28900d6607ea7a25c39a3bd1ce152f6ab24a (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.c | 56 |
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 | ||
122 | static int faraday_res_to_memcfg(resource_size_t mem_base, | 127 | static 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); |