blob: 96028f01bc90142e50ef3b8ce5d85e6775f1e619 [file] [log] [blame]
Linus Walleijd3c68e02017-03-12 23:24:03 +01001/*
2 * Support for Faraday Technology FTPC100 PCI Controller
3 *
4 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
5 *
6 * Based on the out-of-tree OpenWRT patch for Cortina Gemini:
7 * Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
8 * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
9 * Based on SL2312 PCI controller code
10 * Storlink (C) 2003
11 */
12
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/io.h>
16#include <linux/kernel.h>
17#include <linux/of_address.h>
18#include <linux/of_device.h>
19#include <linux/of_irq.h>
20#include <linux/of_pci.h>
21#include <linux/pci.h>
22#include <linux/platform_device.h>
23#include <linux/slab.h>
24#include <linux/irqdomain.h>
25#include <linux/irqchip/chained_irq.h>
26#include <linux/bitops.h>
27#include <linux/irq.h>
Linus Walleij2eeb02b2017-05-15 19:23:24 +020028#include <linux/clk.h>
Linus Walleijd3c68e02017-03-12 23:24:03 +010029
30/*
31 * Special configuration registers directly in the first few words
32 * in I/O space.
33 */
34#define PCI_IOSIZE 0x00
35#define PCI_PROT 0x04 /* AHB protection */
36#define PCI_CTRL 0x08 /* PCI control signal */
37#define PCI_SOFTRST 0x10 /* Soft reset counter and response error enable */
38#define PCI_CONFIG 0x28 /* PCI configuration command register */
39#define PCI_DATA 0x2C
40
Linus Walleij2eeb02b2017-05-15 19:23:24 +020041#define FARADAY_PCI_STATUS_CMD 0x04 /* Status and command */
Linus Walleijd3c68e02017-03-12 23:24:03 +010042#define FARADAY_PCI_PMC 0x40 /* Power management control */
43#define FARADAY_PCI_PMCSR 0x44 /* Power management status */
44#define FARADAY_PCI_CTRL1 0x48 /* Control register 1 */
45#define FARADAY_PCI_CTRL2 0x4C /* Control register 2 */
46#define FARADAY_PCI_MEM1_BASE_SIZE 0x50 /* Memory base and size #1 */
47#define FARADAY_PCI_MEM2_BASE_SIZE 0x54 /* Memory base and size #2 */
48#define FARADAY_PCI_MEM3_BASE_SIZE 0x58 /* Memory base and size #3 */
49
Linus Walleij2eeb02b2017-05-15 19:23:24 +020050#define PCI_STATUS_66MHZ_CAPABLE BIT(21)
51
Linus Walleijd3c68e02017-03-12 23:24:03 +010052/* Bits 31..28 gives INTD..INTA status */
53#define PCI_CTRL2_INTSTS_SHIFT 28
54#define PCI_CTRL2_INTMASK_CMDERR BIT(27)
55#define PCI_CTRL2_INTMASK_PARERR BIT(26)
56/* Bits 25..22 masks INTD..INTA */
57#define PCI_CTRL2_INTMASK_SHIFT 22
58#define PCI_CTRL2_INTMASK_MABRT_RX BIT(21)
59#define PCI_CTRL2_INTMASK_TABRT_RX BIT(20)
60#define PCI_CTRL2_INTMASK_TABRT_TX BIT(19)
61#define PCI_CTRL2_INTMASK_RETRY4 BIT(18)
62#define PCI_CTRL2_INTMASK_SERR_RX BIT(17)
63#define PCI_CTRL2_INTMASK_PERR_RX BIT(16)
64/* Bit 15 reserved */
65#define PCI_CTRL2_MSTPRI_REQ6 BIT(14)
66#define PCI_CTRL2_MSTPRI_REQ5 BIT(13)
67#define PCI_CTRL2_MSTPRI_REQ4 BIT(12)
68#define PCI_CTRL2_MSTPRI_REQ3 BIT(11)
69#define PCI_CTRL2_MSTPRI_REQ2 BIT(10)
70#define PCI_CTRL2_MSTPRI_REQ1 BIT(9)
71#define PCI_CTRL2_MSTPRI_REQ0 BIT(8)
72/* Bits 7..4 reserved */
73/* Bits 3..0 TRDYW */
74
75/*
76 * Memory configs:
77 * Bit 31..20 defines the PCI side memory base
78 * Bit 19..16 (4 bits) defines the size per below
79 */
80#define FARADAY_PCI_MEMBASE_MASK 0xfff00000
81#define FARADAY_PCI_MEMSIZE_1MB 0x0
82#define FARADAY_PCI_MEMSIZE_2MB 0x1
83#define FARADAY_PCI_MEMSIZE_4MB 0x2
84#define FARADAY_PCI_MEMSIZE_8MB 0x3
85#define FARADAY_PCI_MEMSIZE_16MB 0x4
86#define FARADAY_PCI_MEMSIZE_32MB 0x5
87#define FARADAY_PCI_MEMSIZE_64MB 0x6
88#define FARADAY_PCI_MEMSIZE_128MB 0x7
89#define FARADAY_PCI_MEMSIZE_256MB 0x8
90#define FARADAY_PCI_MEMSIZE_512MB 0x9
91#define FARADAY_PCI_MEMSIZE_1GB 0xa
92#define FARADAY_PCI_MEMSIZE_2GB 0xb
93#define FARADAY_PCI_MEMSIZE_SHIFT 16
94
95/*
96 * The DMA base is set to 0x0 for all memory segments, it reflects the
97 * fact that the memory of the host system starts at 0x0.
98 */
99#define FARADAY_PCI_DMA_MEM1_BASE 0x00000000
100#define FARADAY_PCI_DMA_MEM2_BASE 0x00000000
101#define FARADAY_PCI_DMA_MEM3_BASE 0x00000000
102
103/* Defines for PCI configuration command register */
104#define PCI_CONF_ENABLE BIT(31)
105#define PCI_CONF_WHERE(r) ((r) & 0xFC)
106#define PCI_CONF_BUS(b) (((b) & 0xFF) << 16)
107#define PCI_CONF_DEVICE(d) (((d) & 0x1F) << 11)
108#define PCI_CONF_FUNCTION(f) (((f) & 0x07) << 8)
109
110/**
111 * struct faraday_pci_variant - encodes IP block differences
112 * @cascaded_irq: this host has cascaded IRQs from an interrupt controller
113 * embedded in the host bridge.
114 */
115struct faraday_pci_variant {
116 bool cascaded_irq;
117};
118
119struct faraday_pci {
120 struct device *dev;
121 void __iomem *base;
122 struct irq_domain *irqdomain;
123 struct pci_bus *bus;
Linus Walleij2eeb02b2017-05-15 19:23:24 +0200124 struct clk *bus_clk;
Linus Walleijd3c68e02017-03-12 23:24:03 +0100125};
126
127static int faraday_res_to_memcfg(resource_size_t mem_base,
128 resource_size_t mem_size, u32 *val)
129{
130 u32 outval;
131
132 switch (mem_size) {
133 case SZ_1M:
134 outval = FARADAY_PCI_MEMSIZE_1MB;
135 break;
136 case SZ_2M:
137 outval = FARADAY_PCI_MEMSIZE_2MB;
138 break;
139 case SZ_4M:
140 outval = FARADAY_PCI_MEMSIZE_4MB;
141 break;
142 case SZ_8M:
143 outval = FARADAY_PCI_MEMSIZE_8MB;
144 break;
145 case SZ_16M:
146 outval = FARADAY_PCI_MEMSIZE_16MB;
147 break;
148 case SZ_32M:
149 outval = FARADAY_PCI_MEMSIZE_32MB;
150 break;
151 case SZ_64M:
152 outval = FARADAY_PCI_MEMSIZE_64MB;
153 break;
154 case SZ_128M:
155 outval = FARADAY_PCI_MEMSIZE_128MB;
156 break;
157 case SZ_256M:
158 outval = FARADAY_PCI_MEMSIZE_256MB;
159 break;
160 case SZ_512M:
161 outval = FARADAY_PCI_MEMSIZE_512MB;
162 break;
163 case SZ_1G:
164 outval = FARADAY_PCI_MEMSIZE_1GB;
165 break;
166 case SZ_2G:
167 outval = FARADAY_PCI_MEMSIZE_2GB;
168 break;
169 default:
170 return -EINVAL;
171 }
172 outval <<= FARADAY_PCI_MEMSIZE_SHIFT;
173
174 /* This is probably not good */
175 if (mem_base & ~(FARADAY_PCI_MEMBASE_MASK))
176 pr_warn("truncated PCI memory base\n");
177 /* Translate to bridge side address space */
178 outval |= (mem_base & FARADAY_PCI_MEMBASE_MASK);
179 pr_debug("Translated pci base @%pap, size %pap to config %08x\n",
180 &mem_base, &mem_size, outval);
181
182 *val = outval;
183 return 0;
184}
185
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500186static int faraday_raw_pci_read_config(struct faraday_pci *p, int bus_number,
187 unsigned int fn, int config, int size,
188 u32 *value)
Linus Walleijd3c68e02017-03-12 23:24:03 +0100189{
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500190 writel(PCI_CONF_BUS(bus_number) |
Linus Walleijd3c68e02017-03-12 23:24:03 +0100191 PCI_CONF_DEVICE(PCI_SLOT(fn)) |
192 PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
193 PCI_CONF_WHERE(config) |
194 PCI_CONF_ENABLE,
195 p->base + PCI_CONFIG);
196
197 *value = readl(p->base + PCI_DATA);
198
199 if (size == 1)
200 *value = (*value >> (8 * (config & 3))) & 0xFF;
201 else if (size == 2)
202 *value = (*value >> (8 * (config & 3))) & 0xFFFF;
203
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500204 return PCIBIOS_SUCCESSFUL;
205}
206
207static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
208 int config, int size, u32 *value)
209{
210 struct faraday_pci *p = bus->sysdata;
211
Linus Walleijd3c68e02017-03-12 23:24:03 +0100212 dev_dbg(&bus->dev,
213 "[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
214 PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
215
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500216 return faraday_raw_pci_read_config(p, bus->number, fn, config, size, value);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100217}
218
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500219static int faraday_raw_pci_write_config(struct faraday_pci *p, int bus_number,
220 unsigned int fn, int config, int size,
221 u32 value)
Linus Walleijd3c68e02017-03-12 23:24:03 +0100222{
Linus Walleijd3c68e02017-03-12 23:24:03 +0100223 int ret = PCIBIOS_SUCCESSFUL;
224
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500225 writel(PCI_CONF_BUS(bus_number) |
Linus Walleijd3c68e02017-03-12 23:24:03 +0100226 PCI_CONF_DEVICE(PCI_SLOT(fn)) |
227 PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
228 PCI_CONF_WHERE(config) |
229 PCI_CONF_ENABLE,
230 p->base + PCI_CONFIG);
231
232 switch (size) {
233 case 4:
234 writel(value, p->base + PCI_DATA);
235 break;
236 case 2:
237 writew(value, p->base + PCI_DATA + (config & 3));
238 break;
239 case 1:
240 writeb(value, p->base + PCI_DATA + (config & 3));
241 break;
242 default:
243 ret = PCIBIOS_BAD_REGISTER_NUMBER;
244 }
245
246 return ret;
247}
248
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500249static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
250 int config, int size, u32 value)
251{
252 struct faraday_pci *p = bus->sysdata;
253
254 dev_dbg(&bus->dev,
255 "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
256 PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
257
258 return faraday_raw_pci_write_config(p, bus->number, fn, config, size,
259 value);
260}
261
Linus Walleijd3c68e02017-03-12 23:24:03 +0100262static struct pci_ops faraday_pci_ops = {
263 .read = faraday_pci_read_config,
264 .write = faraday_pci_write_config,
265};
266
267static void faraday_pci_ack_irq(struct irq_data *d)
268{
269 struct faraday_pci *p = irq_data_get_irq_chip_data(d);
270 unsigned int reg;
271
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500272 faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100273 reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
274 reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTSTS_SHIFT);
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500275 faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100276}
277
278static void faraday_pci_mask_irq(struct irq_data *d)
279{
280 struct faraday_pci *p = irq_data_get_irq_chip_data(d);
281 unsigned int reg;
282
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500283 faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100284 reg &= ~((0xF << PCI_CTRL2_INTSTS_SHIFT)
285 | BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT));
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500286 faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100287}
288
289static void faraday_pci_unmask_irq(struct irq_data *d)
290{
291 struct faraday_pci *p = irq_data_get_irq_chip_data(d);
292 unsigned int reg;
293
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500294 faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100295 reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
296 reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT);
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500297 faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100298}
299
300static void faraday_pci_irq_handler(struct irq_desc *desc)
301{
302 struct faraday_pci *p = irq_desc_get_handler_data(desc);
303 struct irq_chip *irqchip = irq_desc_get_chip(desc);
304 unsigned int irq_stat, reg, i;
305
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500306 faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100307 irq_stat = reg >> PCI_CTRL2_INTSTS_SHIFT;
308
309 chained_irq_enter(irqchip, desc);
310
311 for (i = 0; i < 4; i++) {
312 if ((irq_stat & BIT(i)) == 0)
313 continue;
314 generic_handle_irq(irq_find_mapping(p->irqdomain, i));
315 }
316
317 chained_irq_exit(irqchip, desc);
318}
319
320static struct irq_chip faraday_pci_irq_chip = {
321 .name = "PCI",
322 .irq_ack = faraday_pci_ack_irq,
323 .irq_mask = faraday_pci_mask_irq,
324 .irq_unmask = faraday_pci_unmask_irq,
325};
326
327static int faraday_pci_irq_map(struct irq_domain *domain, unsigned int irq,
328 irq_hw_number_t hwirq)
329{
330 irq_set_chip_and_handler(irq, &faraday_pci_irq_chip, handle_level_irq);
331 irq_set_chip_data(irq, domain->host_data);
332
333 return 0;
334}
335
336static const struct irq_domain_ops faraday_pci_irqdomain_ops = {
337 .map = faraday_pci_irq_map,
338};
339
340static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
341{
342 struct device_node *intc = of_get_next_child(p->dev->of_node, NULL);
343 int irq;
344 int i;
345
346 if (!intc) {
347 dev_err(p->dev, "missing child interrupt-controller node\n");
348 return -EINVAL;
349 }
350
351 /* All PCI IRQs cascade off this one */
352 irq = of_irq_get(intc, 0);
Sergei Shtylyovb9f27af2017-07-16 00:43:10 +0300353 if (irq <= 0) {
Linus Walleijd3c68e02017-03-12 23:24:03 +0100354 dev_err(p->dev, "failed to get parent IRQ\n");
Sergei Shtylyovb9f27af2017-07-16 00:43:10 +0300355 return irq ?: -EINVAL;
Linus Walleijd3c68e02017-03-12 23:24:03 +0100356 }
357
Paul Burton341d3292017-08-15 16:26:36 -0500358 p->irqdomain = irq_domain_add_linear(intc, PCI_NUM_INTX,
Linus Walleijd3c68e02017-03-12 23:24:03 +0100359 &faraday_pci_irqdomain_ops, p);
360 if (!p->irqdomain) {
361 dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n");
362 return -EINVAL;
363 }
364
365 irq_set_chained_handler_and_data(irq, faraday_pci_irq_handler, p);
366
367 for (i = 0; i < 4; i++)
368 irq_create_mapping(p->irqdomain, i);
369
370 return 0;
371}
372
373static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
374 struct device_node *node)
375{
376 const int na = 3, ns = 2;
377 int rlen;
378
379 parser->node = node;
380 parser->pna = of_n_addr_cells(node);
381 parser->np = parser->pna + na + ns;
382
383 parser->range = of_get_property(node, "dma-ranges", &rlen);
384 if (!parser->range)
385 return -ENOENT;
386 parser->end = parser->range + rlen / sizeof(__be32);
387
388 return 0;
389}
390
391static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
392 struct device_node *np)
393{
394 struct of_pci_range range;
395 struct of_pci_range_parser parser;
396 struct device *dev = p->dev;
397 u32 confreg[3] = {
398 FARADAY_PCI_MEM1_BASE_SIZE,
399 FARADAY_PCI_MEM2_BASE_SIZE,
400 FARADAY_PCI_MEM3_BASE_SIZE,
401 };
402 int i = 0;
403 u32 val;
404
405 if (pci_dma_range_parser_init(&parser, np)) {
406 dev_err(dev, "missing dma-ranges property\n");
407 return -EINVAL;
408 }
409
410 /*
411 * Get the dma-ranges from the device tree
412 */
413 for_each_of_pci_range(&parser, &range) {
414 u64 end = range.pci_addr + range.size - 1;
415 int ret;
416
417 ret = faraday_res_to_memcfg(range.pci_addr, range.size, &val);
418 if (ret) {
419 dev_err(dev,
420 "DMA range %d: illegal MEM resource size\n", i);
421 return -EINVAL;
422 }
423
424 dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n",
425 i + 1, range.pci_addr, end, val);
426 if (i <= 2) {
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500427 faraday_raw_pci_write_config(p, 0, 0, confreg[i],
428 4, val);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100429 } else {
430 dev_err(dev, "ignore extraneous dma-range %d\n", i);
431 break;
432 }
433
434 i++;
435 }
436
437 return 0;
438}
439
440static int faraday_pci_probe(struct platform_device *pdev)
441{
442 struct device *dev = &pdev->dev;
443 const struct faraday_pci_variant *variant =
444 of_device_get_match_data(dev);
445 struct resource *regs;
446 resource_size_t io_base;
447 struct resource_entry *win;
448 struct faraday_pci *p;
449 struct resource *mem;
450 struct resource *io;
451 struct pci_host_bridge *host;
Linus Walleij2eeb02b2017-05-15 19:23:24 +0200452 struct clk *clk;
453 unsigned char max_bus_speed = PCI_SPEED_33MHz;
454 unsigned char cur_bus_speed = PCI_SPEED_33MHz;
Linus Walleijd3c68e02017-03-12 23:24:03 +0100455 int ret;
456 u32 val;
457 LIST_HEAD(res);
458
Lorenzo Pieralisi9aa17a72017-06-28 15:13:53 -0500459 host = devm_pci_alloc_host_bridge(dev, sizeof(*p));
Linus Walleijd3c68e02017-03-12 23:24:03 +0100460 if (!host)
461 return -ENOMEM;
462
463 host->dev.parent = dev;
464 host->ops = &faraday_pci_ops;
465 host->busnr = 0;
466 host->msi = NULL;
Lorenzo Pieralisif7c2e692017-06-28 15:14:08 -0500467 host->map_irq = of_irq_parse_and_map_pci;
468 host->swizzle_irq = pci_common_swizzle;
Linus Walleijd3c68e02017-03-12 23:24:03 +0100469 p = pci_host_bridge_priv(host);
470 host->sysdata = p;
471 p->dev = dev;
472
Linus Walleij2eeb02b2017-05-15 19:23:24 +0200473 /* 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
Linus Walleijd3c68e02017-03-12 23:24:03 +0100491 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
492 p->base = devm_ioremap_resource(dev, regs);
493 if (IS_ERR(p->base))
494 return PTR_ERR(p->base);
495
496 ret = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff,
497 &res, &io_base);
498 if (ret)
499 return ret;
500
501 ret = devm_request_pci_bus_resources(dev, &res);
502 if (ret)
503 return ret;
504
505 /* Get the I/O and memory ranges from DT */
506 resource_list_for_each_entry(win, &res) {
507 switch (resource_type(win->res)) {
508 case IORESOURCE_IO:
509 io = win->res;
510 io->name = "Gemini PCI I/O";
511 if (!faraday_res_to_memcfg(io->start - win->offset,
512 resource_size(io), &val)) {
513 /* setup I/O space size */
514 writel(val, p->base + PCI_IOSIZE);
515 } else {
516 dev_err(dev, "illegal IO mem size\n");
517 return -EINVAL;
518 }
519 ret = pci_remap_iospace(io, io_base);
520 if (ret) {
521 dev_warn(dev, "error %d: failed to map resource %pR\n",
522 ret, io);
523 continue;
524 }
525 break;
526 case IORESOURCE_MEM:
527 mem = win->res;
528 mem->name = "Gemini PCI MEM";
529 break;
530 case IORESOURCE_BUS:
531 break;
532 default:
533 break;
534 }
535 }
536
537 /* Setup hostbridge */
538 val = readl(p->base + PCI_CTRL);
539 val |= PCI_COMMAND_IO;
540 val |= PCI_COMMAND_MEMORY;
541 val |= PCI_COMMAND_MASTER;
542 writel(val, p->base + PCI_CTRL);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100543 /* Mask and clear all interrupts */
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500544 faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000);
Linus Walleijd3c68e02017-03-12 23:24:03 +0100545 if (variant->cascaded_irq) {
546 ret = faraday_pci_setup_cascaded_irq(p);
547 if (ret) {
548 dev_err(dev, "failed to setup cascaded IRQ\n");
549 return ret;
550 }
551 }
552
Linus Walleij2eeb02b2017-05-15 19:23:24 +0200553 /* 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
Linus Walleijd3c68e02017-03-12 23:24:03 +0100581 ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
582 if (ret)
583 return ret;
584
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500585 list_splice_init(&res, &host->windows);
Lorenzo Pieralisicea9bc02017-06-28 15:13:55 -0500586 ret = pci_scan_root_bus_bridge(host);
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500587 if (ret) {
Lorenzo Pieralisicea9bc02017-06-28 15:13:55 -0500588 dev_err(dev, "failed to scan host: %d\n", ret);
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500589 return ret;
590 }
591 p->bus = host->bus;
Linus Walleij2eeb02b2017-05-15 19:23:24 +0200592 p->bus->max_bus_speed = max_bus_speed;
593 p->bus->cur_bus_speed = cur_bus_speed;
Lorenzo Pieralisif1e8bd22017-06-28 15:13:51 -0500594
Linus Walleijd3c68e02017-03-12 23:24:03 +0100595 pci_bus_assign_resources(p->bus);
596 pci_bus_add_devices(p->bus);
597 pci_free_resource_list(&res);
598
599 return 0;
600}
601
602/*
603 * We encode bridge variants here, we have at least two so it doesn't
604 * hurt to have infrastructure to encompass future variants as well.
605 */
606const struct faraday_pci_variant faraday_regular = {
607 .cascaded_irq = true,
608};
609
610const struct faraday_pci_variant faraday_dual = {
611 .cascaded_irq = false,
612};
613
614static const struct of_device_id faraday_pci_of_match[] = {
615 {
616 .compatible = "faraday,ftpci100",
617 .data = &faraday_regular,
618 },
619 {
620 .compatible = "faraday,ftpci100-dual",
621 .data = &faraday_dual,
622 },
623 {},
624};
625
626static struct platform_driver faraday_pci_driver = {
627 .driver = {
628 .name = "ftpci100",
629 .of_match_table = of_match_ptr(faraday_pci_of_match),
Brian Norrisa5f40e82017-04-20 15:36:25 -0500630 .suppress_bind_attrs = true,
Linus Walleijd3c68e02017-03-12 23:24:03 +0100631 },
632 .probe = faraday_pci_probe,
633};
634builtin_platform_driver(faraday_pci_driver);