aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2012-05-11 12:47:30 -0400
committerRalf Baechle <ralf@linux-mips.org>2012-05-21 09:31:52 -0400
commit57c8cb8f242988b8048a7058cd1edde025c6f232 (patch)
tree980f3ad2b686d8959312d9a5858b879aa58bcd49
parentddd4eeca961cc6b1d57e0ca2f264403d690b6882 (diff)
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>
-rw-r--r--arch/mips/lantiq/Kconfig5
-rw-r--r--arch/mips/pci/Makefile3
-rw-r--r--arch/mips/pci/fixup-lantiq.c40
-rw-r--r--arch/mips/pci/pci-lantiq.c177
4 files changed, 131 insertions, 94 deletions
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 9485fe54752b..7389098fd983 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -18,7 +18,6 @@ config SOC_XWAY
18 select HW_HAS_PCI 18 select HW_HAS_PCI
19endchoice 19endchoice
20 20
21
22choice 21choice
23 prompt "Devicetree" 22 prompt "Devicetree"
24 23
@@ -27,4 +26,8 @@ config DT_EASY50712
27 depends on SOC_XWAY 26 depends on SOC_XWAY
28endchoice 27endchoice
29 28
29config PCI_LANTIQ
30 bool "PCI Support"
31 depends on SOC_XWAY && PCI
32
30endif 33endif
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index c3ac4b086eb2..499a019c2c5f 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -41,7 +41,8 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
41obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o 41obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
42obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o 42obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
43obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o 43obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
44obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o 44obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
45obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
45obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o 46obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
46obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o 47obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
47obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o 48obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
new file mode 100644
index 000000000000..6c829df28dc7
--- /dev/null
+++ b/arch/mips/pci/fixup-lantiq.c
@@ -0,0 +1,40 @@
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
12int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL;
13int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL;
14
15int 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
26int __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}
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
index 4d8c49beeda4..ea453532a33c 100644
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -13,8 +13,12 @@
13#include <linux/delay.h> 13#include <linux/delay.h>
14#include <linux/mm.h> 14#include <linux/mm.h>
15#include <linux/vmalloc.h> 15#include <linux/vmalloc.h>
16#include <linux/export.h> 16#include <linux/module.h>
17#include <linux/platform_device.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#include <asm/pci.h> 23#include <asm/pci.h>
20#include <asm/gpio.h> 24#include <asm/gpio.h>
@@ -22,17 +26,9 @@
22 26
23#include <lantiq_soc.h> 27#include <lantiq_soc.h>
24#include <lantiq_irq.h> 28#include <lantiq_irq.h>
25#include <lantiq_platform.h>
26 29
27#include "pci-lantiq.h" 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#define PCI_CR_FCI_ADDR_MAP0 0x00C0 32#define PCI_CR_FCI_ADDR_MAP0 0x00C0
37#define PCI_CR_FCI_ADDR_MAP1 0x00C4 33#define PCI_CR_FCI_ADDR_MAP1 0x00C4
38#define PCI_CR_FCI_ADDR_MAP2 0x00C8 34#define PCI_CR_FCI_ADDR_MAP2 0x00C8
@@ -71,50 +67,24 @@
71__iomem void *ltq_pci_mapped_cfg; 67__iomem void *ltq_pci_mapped_cfg;
72static __iomem void *ltq_pci_membase; 68static __iomem void *ltq_pci_membase;
73 69
74int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL; 70static int reset_gpio;
75 71static struct clk *clk_pci, *clk_external;
76/* Since the PCI REQ pins can be reused for other functionality, make it 72static struct resource pci_io_resource;
77 possible to exclude those from interpretation by the PCI controller */ 73static struct resource pci_mem_resource;
78static int ltq_pci_req_mask = 0xf; 74static struct pci_ops pci_ops = {
79
80static int *ltq_pci_irq_map;
81
82struct pci_ops ltq_pci_ops = {
83 .read = ltq_pci_read_config_dword, 75 .read = ltq_pci_read_config_dword,
84 .write = ltq_pci_write_config_dword 76 .write = ltq_pci_write_config_dword
85}; 77};
86 78
87static struct resource pci_io_resource = { 79static struct pci_controller pci_controller = {
88 .name = "pci io space", 80 .pci_ops = &pci_ops,
89 .start = LTQ_PCI_IO_BASE,
90 .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
91 .flags = IORESOURCE_IO
92};
93
94static 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
101static struct pci_controller ltq_pci_controller = {
102 .pci_ops = &ltq_pci_ops,
103 .mem_resource = &pci_mem_resource, 81 .mem_resource = &pci_mem_resource,
104 .mem_offset = 0x00000000UL, 82 .mem_offset = 0x00000000UL,
105 .io_resource = &pci_io_resource, 83 .io_resource = &pci_io_resource,
106 .io_offset = 0x00000000UL, 84 .io_offset = 0x00000000UL,
107}; 85};
108 86
109int pcibios_plat_dev_init(struct pci_dev *dev) 87static inline u32 ltq_calc_bar11mask(void)
110{
111 if (ltqpci_plat_dev_init)
112 return ltqpci_plat_dev_init(dev);
113
114 return 0;
115}
116
117static u32 ltq_calc_bar11mask(void)
118{ 88{
119 u32 mem, bar11mask; 89 u32 mem, bar11mask;
120 90
@@ -125,32 +95,42 @@ static u32 ltq_calc_bar11mask(void)
125 return bar11mask; 95 return bar11mask;
126} 96}
127 97
128static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) 98static 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 u32 temp_buffer; 102 u32 temp_buffer;
131 103
132 /* set clock to 33Mhz */ 104 /* get our clocks */
133 if (ltq_is_ar9()) { 105 clk_pci = clk_get(&pdev->dev, NULL);
134 ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR); 106 if (IS_ERR(clk_pci)) {
135 ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR); 107 dev_err(&pdev->dev, "failed to get pci clock\n");
136 } else { 108 return PTR_ERR(clk_pci);
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);
139 } 109 }
140 110
141 /* external or internal clock ? */ 111 clk_external = clk_get(&pdev->dev, "external");
142 if (conf->clock) { 112 if (IS_ERR(clk_external)) {
143 ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16), 113 clk_put(clk_pci);
144 LTQ_CGU_IFCCR); 114 dev_err(&pdev->dev, "failed to get external pci clock\n");
145 ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR); 115 return PTR_ERR(clk_external);
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);
150 } 116 }
151 117
152 /* setup pci clock and gpis used by pci */ 118 /* read the bus speed that we want */
153 gpio_request(21, "pci-reset"); 119 bus_clk = of_get_property(node, "lantiq,bus-clock", NULL);
120 if (bus_clk)
121 clk_set_rate(clk_pci, *bus_clk);
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");
154 134
155 /* enable auto-switching between PCI and EBU */ 135 /* enable auto-switching between PCI and EBU */
156 ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); 136 ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
@@ -163,7 +143,12 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
163 143
164 /* enable external 2 PCI masters */ 144 /* enable external 2 PCI masters */
165 temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB); 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 /* enable internal arbiter */ 152 /* enable internal arbiter */
168 temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); 153 temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
169 /* enable internal PCI master reqest */ 154 /* enable internal PCI master reqest */
@@ -207,47 +192,55 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
207 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN); 192 ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
208 193
209 /* toggle reset pin */ 194 /* toggle reset pin */
210 __gpio_set_value(21, 0); 195 if (reset_gpio > 0) {
211 wmb(); 196 __gpio_set_value(reset_gpio, 0);
212 mdelay(1); 197 wmb();
213 __gpio_set_value(21, 1); 198 mdelay(1);
214 return 0; 199 __gpio_set_value(reset_gpio, 1);
215} 200 }
216
217int __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; 201 return 0;
225} 202}
226 203
227static int __devinit ltq_pci_probe(struct platform_device *pdev) 204static int __devinit ltq_pci_probe(struct platform_device *pdev)
228{ 205{
229 struct ltq_pci_data *ltq_pci_data = 206 struct resource *res_cfg, *res_bridge;
230 (struct ltq_pci_data *) pdev->dev.platform_data;
231 207
232 pci_clear_flags(PCI_PROBE_ONLY); 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 return 0; 229 return 0;
243} 230}
244 231
245static struct platform_driver 232static const struct of_device_id ltq_pci_match[] = {
246ltq_pci_driver = { 233 { .compatible = "lantiq,pci-xway" },
234 {},
235};
236MODULE_DEVICE_TABLE(of, ltq_pci_match);
237
238static struct platform_driver ltq_pci_driver = {
247 .probe = ltq_pci_probe, 239 .probe = ltq_pci_probe,
248 .driver = { 240 .driver = {
249 .name = "ltq_pci", 241 .name = "pci-xway",
250 .owner = THIS_MODULE, 242 .owner = THIS_MODULE,
243 .of_match_table = ltq_pci_match,
251 }, 244 },
252}; 245};
253 246
@@ -255,7 +248,7 @@ int __init pcibios_init(void)
255{ 248{
256 int ret = platform_driver_register(&ltq_pci_driver); 249 int ret = platform_driver_register(&ltq_pci_driver);
257 if (ret) 250 if (ret)
258 printk(KERN_INFO "ltq_pci: Error registering platfom driver!"); 251 pr_info("pci-xway: Error registering platform driver!");
259 return ret; 252 return ret;
260} 253}
261 254