Commit 57c8cb8f242988b8048a7058cd1edde025c6f232
Committed by
Ralf Baechle
1 parent
ddd4eeca96
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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 = <q_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(<q_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(<q_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 |