aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-integrator/pci_v3.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2013-02-28 20:20:55 -0500
committerLinus Walleij <linus.walleij@linaro.org>2013-06-15 16:18:39 -0400
commitf55b2b56cd37fa8bcfcb75248c27094eaf09e04c (patch)
tree6a2c06ee9b692498e823d4b6d6e4716428c3bf61 /arch/arm/mach-integrator/pci_v3.c
parentae9daf2d00ee103b257a1f3b4ea9c575b708fe7a (diff)
ARM: integrator: basic PCIv3 device tree support
This registers the memory ranges for I/O, non-prefetched and prefetched memory and configuration space for the PCIv3 bridge and let us fetch these basic memory resources from the device tree in the device tree boot path. Remove the stepping stone platform device. This is an either/or approach - the platform data path is mutually exclusive to the plain platform data path and provided addresses from the device tree have to be correct. This adds the interrupt-map property to the PCIv3 DTS file and makes the bridge obtain mappings from the device tree. Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'arch/arm/mach-integrator/pci_v3.c')
-rw-r--r--arch/arm/mach-integrator/pci_v3.c177
1 files changed, 152 insertions, 25 deletions
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index a3cefdebd136..a0e069d37e14 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -28,6 +28,10 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/of.h>
32#include <linux/of_address.h>
33#include <linux/of_irq.h>
34#include <linux/of_pci.h>
31#include <video/vga.h> 35#include <video/vga.h>
32 36
33#include <mach/hardware.h> 37#include <mach/hardware.h>
@@ -279,7 +283,12 @@
279 * the mappings into PCI memory. 283 * the mappings into PCI memory.
280 */ 284 */
281 285
286/* Filled in by probe */
282static void __iomem *pci_v3_base; 287static void __iomem *pci_v3_base;
288static struct resource conf_mem; /* FIXME: remap this instead of static map */
289static struct resource io_mem;
290static struct resource non_mem;
291static struct resource pre_mem;
283 292
284// V3 access routines 293// V3 access routines
285#define v3_writeb(o,v) __raw_writeb(v, pci_v3_base + (unsigned int)(o)) 294#define v3_writeb(o,v) __raw_writeb(v, pci_v3_base + (unsigned int)(o))
@@ -423,13 +432,13 @@ static void __iomem *v3_open_config_window(struct pci_bus *bus,
423 * prefetchable), this frees up base1 for re-use by 432 * prefetchable), this frees up base1 for re-use by
424 * configuration memory 433 * configuration memory
425 */ 434 */
426 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | 435 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) |
427 V3_LB_BASE_ADR_SIZE_512MB | V3_LB_BASE_ENABLE); 436 V3_LB_BASE_ADR_SIZE_512MB | V3_LB_BASE_ENABLE);
428 437
429 /* 438 /*
430 * Set up base1/map1 to point into configuration space. 439 * Set up base1/map1 to point into configuration space.
431 */ 440 */
432 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_CONFIG_BASE) | 441 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(conf_mem.start) |
433 V3_LB_BASE_ADR_SIZE_16MB | V3_LB_BASE_ENABLE); 442 V3_LB_BASE_ADR_SIZE_16MB | V3_LB_BASE_ENABLE);
434 v3_writew(V3_LB_MAP1, mapaddress); 443 v3_writew(V3_LB_MAP1, mapaddress);
435 444
@@ -441,7 +450,7 @@ static void v3_close_config_window(void)
441 /* 450 /*
442 * Reassign base1 for use by prefetchable PCI memory 451 * Reassign base1 for use by prefetchable PCI memory
443 */ 452 */
444 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) | 453 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) |
445 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | 454 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH |
446 V3_LB_BASE_ENABLE); 455 V3_LB_BASE_ENABLE);
447 v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) | 456 v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) |
@@ -450,7 +459,7 @@ static void v3_close_config_window(void)
450 /* 459 /*
451 * And shrink base0 back to a 256M window (NOTE: MAP0 already correct) 460 * And shrink base0 back to a 256M window (NOTE: MAP0 already correct)
452 */ 461 */
453 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | 462 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) |
454 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); 463 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
455} 464}
456 465
@@ -522,20 +531,6 @@ static struct pci_ops pci_v3_ops = {
522 .write = v3_write_config, 531 .write = v3_write_config,
523}; 532};
524 533
525static struct resource non_mem = {
526 .name = "PCI non-prefetchable",
527 .start = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START,
528 .end = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START + PCI_BUS_NONMEM_SIZE - 1,
529 .flags = IORESOURCE_MEM,
530};
531
532static struct resource pre_mem = {
533 .name = "PCI prefetchable",
534 .start = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START,
535 .end = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START + PCI_BUS_PREMEM_SIZE - 1,
536 .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
537};
538
539static int __init pci_v3_setup_resources(struct pci_sys_data *sys) 534static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
540{ 535{
541 if (request_resource(&iomem_resource, &non_mem)) { 536 if (request_resource(&iomem_resource, &non_mem)) {
@@ -659,7 +654,7 @@ static int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
659 return -EINVAL; 654 return -EINVAL;
660 655
661 if (nr == 0) { 656 if (nr == 0) {
662 sys->mem_offset = PHYS_PCI_MEM_BASE; 657 sys->mem_offset = non_mem.start;
663 ret = pci_v3_setup_resources(sys); 658 ret = pci_v3_setup_resources(sys);
664 } 659 }
665 660
@@ -697,7 +692,7 @@ static void __init pci_v3_preinit(void)
697 * Setup window 0 - PCI non-prefetchable memory 692 * Setup window 0 - PCI non-prefetchable memory
698 * Local: 0x40000000 Bus: 0x00000000 Size: 256MB 693 * Local: 0x40000000 Bus: 0x00000000 Size: 256MB
699 */ 694 */
700 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE) | 695 v3_writel(V3_LB_BASE0, v3_addr_to_lb_base(non_mem.start) |
701 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE); 696 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_ENABLE);
702 v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(PCI_BUS_NONMEM_START) | 697 v3_writew(V3_LB_MAP0, v3_addr_to_lb_map(PCI_BUS_NONMEM_START) |
703 V3_LB_MAP_TYPE_MEM); 698 V3_LB_MAP_TYPE_MEM);
@@ -706,7 +701,7 @@ static void __init pci_v3_preinit(void)
706 * Setup window 1 - PCI prefetchable memory 701 * Setup window 1 - PCI prefetchable memory
707 * Local: 0x50000000 Bus: 0x10000000 Size: 256MB 702 * Local: 0x50000000 Bus: 0x10000000 Size: 256MB
708 */ 703 */
709 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(PHYS_PCI_MEM_BASE + SZ_256M) | 704 v3_writel(V3_LB_BASE1, v3_addr_to_lb_base(pre_mem.start) |
710 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH | 705 V3_LB_BASE_ADR_SIZE_256MB | V3_LB_BASE_PREFETCH |
711 V3_LB_BASE_ENABLE); 706 V3_LB_BASE_ENABLE);
712 v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) | 707 v3_writew(V3_LB_MAP1, v3_addr_to_lb_map(PCI_BUS_PREMEM_START) |
@@ -715,7 +710,7 @@ static void __init pci_v3_preinit(void)
715 /* 710 /*
716 * Setup window 2 - PCI IO 711 * Setup window 2 - PCI IO
717 */ 712 */
718 v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(PHYS_PCI_IO_BASE) | 713 v3_writel(V3_LB_BASE2, v3_addr_to_lb_base2(io_mem.start) |
719 V3_LB_BASE_ENABLE); 714 V3_LB_BASE_ENABLE);
720 v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0)); 715 v3_writew(V3_LB_MAP2, v3_addr_to_lb_map2(0));
721 716
@@ -772,7 +767,7 @@ static void __init pci_v3_postinit(void)
772 "interrupt: %d\n", ret); 767 "interrupt: %d\n", ret);
773#endif 768#endif
774 769
775 register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0); 770 register_isa_ports(non_mem.start, io_mem.start, 0);
776} 771}
777 772
778/* 773/*
@@ -837,7 +832,6 @@ static int __init pci_v3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
837 832
838static struct hw_pci pci_v3 __initdata = { 833static struct hw_pci pci_v3 __initdata = {
839 .swizzle = pci_v3_swizzle, 834 .swizzle = pci_v3_swizzle,
840 .map_irq = pci_v3_map_irq,
841 .setup = pci_v3_setup, 835 .setup = pci_v3_setup,
842 .nr_controllers = 1, 836 .nr_controllers = 1,
843 .ops = &pci_v3_ops, 837 .ops = &pci_v3_ops,
@@ -845,8 +839,107 @@ static struct hw_pci pci_v3 __initdata = {
845 .postinit = pci_v3_postinit, 839 .postinit = pci_v3_postinit,
846}; 840};
847 841
842#ifdef CONFIG_OF
843
844static int __init pci_v3_map_irq_dt(const struct pci_dev *dev, u8 slot, u8 pin)
845{
846 struct of_irq oirq;
847 int ret;
848
849 ret = of_irq_map_pci(dev, &oirq);
850 if (ret) {
851 dev_err(&dev->dev, "of_irq_map_pci() %d\n", ret);
852 /* Proper return code 0 == NO_IRQ */
853 return 0;
854 }
855
856 return irq_create_of_mapping(oirq.controller, oirq.specifier,
857 oirq.size);
858}
859
860static int __init pci_v3_dtprobe(struct platform_device *pdev,
861 struct device_node *np)
862{
863 struct of_pci_range_parser parser;
864 struct of_pci_range range;
865 struct resource *res;
866 int irq, ret;
867
868 if (of_pci_range_parser_init(&parser, np))
869 return -EINVAL;
870
871 /* Get base for bridge registers */
872 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
873 if (!res) {
874 dev_err(&pdev->dev, "unable to obtain PCIv3 base\n");
875 return -ENODEV;
876 }
877 pci_v3_base = devm_ioremap(&pdev->dev, res->start,
878 resource_size(res));
879 if (!pci_v3_base) {
880 dev_err(&pdev->dev, "unable to remap PCIv3 base\n");
881 return -ENODEV;
882 }
883
884 /* Get and request error IRQ resource */
885 irq = platform_get_irq(pdev, 0);
886 if (irq <= 0) {
887 dev_err(&pdev->dev, "unable to obtain PCIv3 error IRQ\n");
888 return -ENODEV;
889 }
890 ret = devm_request_irq(&pdev->dev, irq, v3_irq, 0,
891 "PCIv3 error", NULL);
892 if (ret < 0) {
893 dev_err(&pdev->dev, "unable to request PCIv3 error IRQ %d (%d)\n", irq, ret);
894 return ret;
895 }
896
897 for_each_of_pci_range(&parser, &range) {
898 if (!range.flags) {
899 of_pci_range_to_resource(&range, np, &conf_mem);
900 conf_mem.name = "PCIv3 config";
901 }
902 if (range.flags & IORESOURCE_IO) {
903 of_pci_range_to_resource(&range, np, &io_mem);
904 io_mem.name = "PCIv3 I/O";
905 }
906 if ((range.flags & IORESOURCE_MEM) &&
907 !(range.flags & IORESOURCE_PREFETCH)) {
908 of_pci_range_to_resource(&range, np, &non_mem);
909 non_mem.name = "PCIv3 non-prefetched mem";
910 }
911 if ((range.flags & IORESOURCE_MEM) &&
912 (range.flags & IORESOURCE_PREFETCH)) {
913 of_pci_range_to_resource(&range, np, &pre_mem);
914 pre_mem.name = "PCIv3 prefetched mem";
915 }
916 }
917
918 if (!conf_mem.start || !io_mem.start ||
919 !non_mem.start || !pre_mem.start) {
920 dev_err(&pdev->dev, "missing ranges in device node\n");
921 return -EINVAL;
922 }
923
924 pci_v3.map_irq = pci_v3_map_irq_dt;
925 pci_common_init_dev(&pdev->dev, &pci_v3);
926
927 return 0;
928}
929
930#else
931
932static inline int pci_v3_dtprobe(struct platform_device *pdev,
933 struct device_node *np)
934{
935 return -EINVAL;
936}
937
938#endif
939
848static int __init pci_v3_probe(struct platform_device *pdev) 940static int __init pci_v3_probe(struct platform_device *pdev)
849{ 941{
942 struct device_node *np = pdev->dev.of_node;
850 int ret; 943 int ret;
851 944
852 /* Remap the Integrator system controller */ 945 /* Remap the Integrator system controller */
@@ -856,6 +949,10 @@ static int __init pci_v3_probe(struct platform_device *pdev)
856 return -ENODEV; 949 return -ENODEV;
857 } 950 }
858 951
952 /* Device tree probe path */
953 if (np)
954 return pci_v3_dtprobe(pdev, np);
955
859 pci_v3_base = devm_ioremap(&pdev->dev, PHYS_PCI_V3_BASE, SZ_64K); 956 pci_v3_base = devm_ioremap(&pdev->dev, PHYS_PCI_V3_BASE, SZ_64K);
860 if (!pci_v3_base) { 957 if (!pci_v3_base) {
861 dev_err(&pdev->dev, "unable to remap PCIv3 base\n"); 958 dev_err(&pdev->dev, "unable to remap PCIv3 base\n");
@@ -869,14 +966,44 @@ static int __init pci_v3_probe(struct platform_device *pdev)
869 return -ENODEV; 966 return -ENODEV;
870 } 967 }
871 968
872 pci_common_init(&pci_v3); 969 conf_mem.name = "PCIv3 config";
970 conf_mem.start = PHYS_PCI_CONFIG_BASE;
971 conf_mem.end = PHYS_PCI_CONFIG_BASE + SZ_16M - 1;
972 conf_mem.flags = IORESOURCE_MEM;
973
974 io_mem.name = "PCIv3 I/O";
975 io_mem.start = PHYS_PCI_IO_BASE;
976 io_mem.end = PHYS_PCI_IO_BASE + SZ_16M - 1;
977 io_mem.flags = IORESOURCE_MEM;
978
979 non_mem.name = "PCIv3 non-prefetched mem";
980 non_mem.start = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START;
981 non_mem.end = PHYS_PCI_MEM_BASE + PCI_BUS_NONMEM_START +
982 PCI_BUS_NONMEM_SIZE - 1;
983 non_mem.flags = IORESOURCE_MEM;
984
985 pre_mem.name = "PCIv3 prefetched mem";
986 pre_mem.start = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START;
987 pre_mem.end = PHYS_PCI_MEM_BASE + PCI_BUS_PREMEM_START +
988 PCI_BUS_PREMEM_SIZE - 1;
989 pre_mem.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
990
991 pci_v3.map_irq = pci_v3_map_irq;
992
993 pci_common_init_dev(&pdev->dev, &pci_v3);
873 994
874 return 0; 995 return 0;
875} 996}
876 997
998static const struct of_device_id pci_ids[] = {
999 { .compatible = "v3,v360epc-pci", },
1000 {},
1001};
1002
877static struct platform_driver pci_v3_driver = { 1003static struct platform_driver pci_v3_driver = {
878 .driver = { 1004 .driver = {
879 .name = "pci-v3", 1005 .name = "pci-v3",
1006 .of_match_table = pci_ids,
880 }, 1007 },
881}; 1008};
882 1009