Commit 57c8cb8f242988b8048a7058cd1edde025c6f232

Authored by John Crispin
Committed by Ralf Baechle
1 parent ddd4eeca96

MIPS: pci: convert lantiq driver to OF

Implement support for OF inside the lantiq PCI driver. The patch also splits
pcibios_plat_dev_init and pcibios_map_irq out into their own file to accomodate
coexistance with the upcoming pcie driver.

Signed-off-by: John Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/3806/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 4 changed files with 131 additions and 94 deletions Side-by-side Diff

arch/mips/lantiq/Kconfig
... ... @@ -18,7 +18,6 @@
18 18 select HW_HAS_PCI
19 19 endchoice
20 20  
21   -
22 21 choice
23 22 prompt "Devicetree"
24 23  
... ... @@ -26,6 +25,10 @@
26 25 bool "Easy50712"
27 26 depends on SOC_XWAY
28 27 endchoice
  28 +
  29 +config PCI_LANTIQ
  30 + bool "PCI Support"
  31 + depends on SOC_XWAY && PCI
29 32  
30 33 endif
arch/mips/pci/Makefile
... ... @@ -41,7 +41,8 @@
41 41 obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
42 42 obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
43 43 obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
44   -obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o
  44 +obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
  45 +obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
45 46 obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
46 47 obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
47 48 obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
arch/mips/pci/fixup-lantiq.c
  1 +/*
  2 + * This program is free software; you can redistribute it and/or modify it
  3 + * under the terms of the GNU General Public License version 2 as published
  4 + * by the Free Software Foundation.
  5 + *
  6 + * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
  7 + */
  8 +
  9 +#include <linux/of_irq.h>
  10 +#include <linux/of_pci.h>
  11 +
  12 +int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL;
  13 +int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL;
  14 +
  15 +int pcibios_plat_dev_init(struct pci_dev *dev)
  16 +{
  17 + if (ltq_pci_plat_arch_init)
  18 + return ltq_pci_plat_arch_init(dev);
  19 +
  20 + if (ltq_pci_plat_dev_init)
  21 + return ltq_pci_plat_dev_init(dev);
  22 +
  23 + return 0;
  24 +}
  25 +
  26 +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  27 +{
  28 + struct of_irq dev_irq;
  29 + int irq;
  30 +
  31 + if (of_irq_map_pci(dev, &dev_irq)) {
  32 + dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
  33 + slot, pin);
  34 + return 0;
  35 + }
  36 + irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
  37 + dev_irq.size);
  38 + dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
  39 + return irq;
  40 +}
arch/mips/pci/pci-lantiq.c
... ... @@ -13,8 +13,12 @@
13 13 #include <linux/delay.h>
14 14 #include <linux/mm.h>
15 15 #include <linux/vmalloc.h>
16   -#include <linux/export.h>
17   -#include <linux/platform_device.h>
  16 +#include <linux/module.h>
  17 +#include <linux/clk.h>
  18 +#include <linux/of_platform.h>
  19 +#include <linux/of_gpio.h>
  20 +#include <linux/of_irq.h>
  21 +#include <linux/of_pci.h>
18 22  
19 23 #include <asm/pci.h>
20 24 #include <asm/gpio.h>
21 25  
... ... @@ -22,17 +26,9 @@
22 26  
23 27 #include <lantiq_soc.h>
24 28 #include <lantiq_irq.h>
25   -#include <lantiq_platform.h>
26 29  
27 30 #include "pci-lantiq.h"
28 31  
29   -#define LTQ_PCI_CFG_BASE 0x17000000
30   -#define LTQ_PCI_CFG_SIZE 0x00008000
31   -#define LTQ_PCI_MEM_BASE 0x18000000
32   -#define LTQ_PCI_MEM_SIZE 0x02000000
33   -#define LTQ_PCI_IO_BASE 0x1AE00000
34   -#define LTQ_PCI_IO_SIZE 0x00200000
35   -
36 32 #define PCI_CR_FCI_ADDR_MAP0 0x00C0
37 33 #define PCI_CR_FCI_ADDR_MAP1 0x00C4
38 34 #define PCI_CR_FCI_ADDR_MAP2 0x00C8
39 35  
40 36  
41 37  
... ... @@ -71,51 +67,25 @@
71 67 __iomem void *ltq_pci_mapped_cfg;
72 68 static __iomem void *ltq_pci_membase;
73 69  
74   -int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
75   -
76   -/* Since the PCI REQ pins can be reused for other functionality, make it
77   - possible to exclude those from interpretation by the PCI controller */
78   -static int ltq_pci_req_mask = 0xf;
79   -
80   -static int *ltq_pci_irq_map;
81   -
82   -struct pci_ops ltq_pci_ops = {
  70 +static int reset_gpio;
  71 +static struct clk *clk_pci, *clk_external;
  72 +static struct resource pci_io_resource;
  73 +static struct resource pci_mem_resource;
  74 +static struct pci_ops pci_ops = {
83 75 .read = ltq_pci_read_config_dword,
84 76 .write = ltq_pci_write_config_dword
85 77 };
86 78  
87   -static struct resource pci_io_resource = {
88   - .name = "pci io space",
89   - .start = LTQ_PCI_IO_BASE,
90   - .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
91   - .flags = IORESOURCE_IO
92   -};
93   -
94   -static struct resource pci_mem_resource = {
95   - .name = "pci memory space",
96   - .start = LTQ_PCI_MEM_BASE,
97   - .end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
98   - .flags = IORESOURCE_MEM
99   -};
100   -
101   -static struct pci_controller ltq_pci_controller = {
102   - .pci_ops = &ltq_pci_ops,
  79 +static struct pci_controller pci_controller = {
  80 + .pci_ops = &pci_ops,
103 81 .mem_resource = &pci_mem_resource,
104 82 .mem_offset = 0x00000000UL,
105 83 .io_resource = &pci_io_resource,
106 84 .io_offset = 0x00000000UL,
107 85 };
108 86  
109   -int pcibios_plat_dev_init(struct pci_dev *dev)
  87 +static inline u32 ltq_calc_bar11mask(void)
110 88 {
111   - if (ltqpci_plat_dev_init)
112   - return ltqpci_plat_dev_init(dev);
113   -
114   - return 0;
115   -}
116   -
117   -static u32 ltq_calc_bar11mask(void)
118   -{
119 89 u32 mem, bar11mask;
120 90  
121 91 /* BAR11MASK value depends on available memory on system. */
122 92  
123 93  
124 94  
125 95  
126 96  
... ... @@ -125,33 +95,43 @@
125 95 return bar11mask;
126 96 }
127 97  
128   -static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
  98 +static int __devinit ltq_pci_startup(struct platform_device *pdev)
129 99 {
  100 + struct device_node *node = pdev->dev.of_node;
  101 + const __be32 *req_mask, *bus_clk;
130 102 u32 temp_buffer;
131 103  
132   - /* set clock to 33Mhz */
133   - if (ltq_is_ar9()) {
134   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR);
135   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR);
136   - } else {
137   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
138   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
  104 + /* get our clocks */
  105 + clk_pci = clk_get(&pdev->dev, NULL);
  106 + if (IS_ERR(clk_pci)) {
  107 + dev_err(&pdev->dev, "failed to get pci clock\n");
  108 + return PTR_ERR(clk_pci);
139 109 }
140 110  
141   - /* external or internal clock ? */
142   - if (conf->clock) {
143   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
144   - LTQ_CGU_IFCCR);
145   - ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
146   - } else {
147   - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
148   - LTQ_CGU_IFCCR);
149   - ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
  111 + clk_external = clk_get(&pdev->dev, "external");
  112 + if (IS_ERR(clk_external)) {
  113 + clk_put(clk_pci);
  114 + dev_err(&pdev->dev, "failed to get external pci clock\n");
  115 + return PTR_ERR(clk_external);
150 116 }
151 117  
152   - /* setup pci clock and gpis used by pci */
153   - gpio_request(21, "pci-reset");
  118 + /* read the bus speed that we want */
  119 + bus_clk = of_get_property(node, "lantiq,bus-clock", NULL);
  120 + if (bus_clk)
  121 + clk_set_rate(clk_pci, *bus_clk);
154 122  
  123 + /* and enable the clocks */
  124 + clk_enable(clk_pci);
  125 + if (of_find_property(node, "lantiq,external-clock", NULL))
  126 + clk_enable(clk_external);
  127 + else
  128 + clk_disable(clk_external);
  129 +
  130 + /* setup reset gpio used by pci */
  131 + reset_gpio = of_get_named_gpio(node, "gpio-reset", 0);
  132 + if (reset_gpio > 0)
  133 + devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset");
  134 +
155 135 /* enable auto-switching between PCI and EBU */
156 136 ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
157 137  
... ... @@ -163,7 +143,12 @@
163 143  
164 144 /* enable external 2 PCI masters */
165 145 temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
166   - temp_buffer &= (~(ltq_pci_req_mask << 16));
  146 + /* setup the request mask */
  147 + req_mask = of_get_property(node, "req-mask", NULL);
  148 + if (req_mask)
  149 + temp_buffer &= ~((*req_mask & 0xf) << 16);
  150 + else
  151 + temp_buffer &= ~0xf0000;
167 152 /* enable internal arbiter */
168 153 temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
169 154 /* enable internal PCI master reqest */
170 155  
171 156  
172 157  
173 158  
174 159  
175 160  
176 161  
... ... @@ -207,47 +192,55 @@
207 192 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
208 193  
209 194 /* toggle reset pin */
210   - __gpio_set_value(21, 0);
211   - wmb();
212   - mdelay(1);
213   - __gpio_set_value(21, 1);
  195 + if (reset_gpio > 0) {
  196 + __gpio_set_value(reset_gpio, 0);
  197 + wmb();
  198 + mdelay(1);
  199 + __gpio_set_value(reset_gpio, 1);
  200 + }
214 201 return 0;
215 202 }
216 203  
217   -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
218   -{
219   - if (ltq_pci_irq_map[slot])
220   - return ltq_pci_irq_map[slot];
221   - printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
222   - slot);
223   -
224   - return 0;
225   -}
226   -
227 204 static int __devinit ltq_pci_probe(struct platform_device *pdev)
228 205 {
229   - struct ltq_pci_data *ltq_pci_data =
230   - (struct ltq_pci_data *) pdev->dev.platform_data;
  206 + struct resource *res_cfg, *res_bridge;
231 207  
232 208 pci_clear_flags(PCI_PROBE_ONLY);
233   - ltq_pci_irq_map = ltq_pci_data->irq;
234   - ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
235   - ltq_pci_mapped_cfg =
236   - ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
237   - ltq_pci_controller.io_map_base =
238   - (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
239   - ltq_pci_startup(ltq_pci_data);
240   - register_pci_controller(&ltq_pci_controller);
241 209  
  210 + res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  211 + res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  212 + if (!res_cfg || !res_bridge) {
  213 + dev_err(&pdev->dev, "missing memory reources\n");
  214 + return -EINVAL;
  215 + }
  216 +
  217 + ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge);
  218 + ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg);
  219 +
  220 + if (!ltq_pci_membase || !ltq_pci_mapped_cfg) {
  221 + dev_err(&pdev->dev, "failed to remap resources\n");
  222 + return -ENOMEM;
  223 + }
  224 +
  225 + ltq_pci_startup(pdev);
  226 +
  227 + pci_load_of_ranges(&pci_controller, pdev->dev.of_node);
  228 + register_pci_controller(&pci_controller);
242 229 return 0;
243 230 }
244 231  
245   -static struct platform_driver
246   -ltq_pci_driver = {
  232 +static const struct of_device_id ltq_pci_match[] = {
  233 + { .compatible = "lantiq,pci-xway" },
  234 + {},
  235 +};
  236 +MODULE_DEVICE_TABLE(of, ltq_pci_match);
  237 +
  238 +static struct platform_driver ltq_pci_driver = {
247 239 .probe = ltq_pci_probe,
248 240 .driver = {
249   - .name = "ltq_pci",
  241 + .name = "pci-xway",
250 242 .owner = THIS_MODULE,
  243 + .of_match_table = ltq_pci_match,
251 244 },
252 245 };
253 246  
... ... @@ -255,7 +248,7 @@
255 248 {
256 249 int ret = platform_driver_register(&ltq_pci_driver);
257 250 if (ret)
258   - printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
  251 + pr_info("pci-xway: Error registering platform driver!");
259 252 return ret;
260 253 }
261 254