^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * leon_pci.c: LEON Host PCI support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Code is partially derived from pcic.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/leon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/leon_pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* The LEON architecture does not rely on a BIOS or bootloader to setup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * PCI for us. The Linux generic routines are used to setup resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * reset values of configuration-space register settings are preserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * PCI Memory and Prefetchable Memory is direct-mapped. However I/O Space is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * accessed through a Window which is translated to low 64KB in PCI space, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * first 4KB is not used so 60KB is available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) LIST_HEAD(resources);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct pci_bus *root_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct pci_host_bridge *bridge;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) bridge = pci_alloc_host_bridge(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (!bridge)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) pci_add_resource_offset(&resources, &info->io_space,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) info->io_space.start - 0x1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) pci_add_resource(&resources, &info->mem_space);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) info->busn.flags = IORESOURCE_BUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) pci_add_resource(&resources, &info->busn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) list_splice_init(&resources, &bridge->windows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) bridge->dev.parent = &ofdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) bridge->sysdata = info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) bridge->busnr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) bridge->ops = info->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) bridge->swizzle_irq = pci_common_swizzle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) bridge->map_irq = info->map_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) ret = pci_scan_root_bus_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) pci_free_host_bridge(bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) root_bus = bridge->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Assign devices with resources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) pci_assign_unassigned_resources();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) pci_bus_add_devices(root_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int pcibios_enable_device(struct pci_dev *dev, int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) u16 cmd, oldcmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) pci_read_config_word(dev, PCI_COMMAND, &cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) oldcmd = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (i = 0; i < PCI_NUM_RESOURCES; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) struct resource *res = &dev->resource[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /* Only set up the requested stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if (!(mask & (1<<i)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (res->flags & IORESOURCE_IO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) cmd |= PCI_COMMAND_IO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (res->flags & IORESOURCE_MEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) cmd |= PCI_COMMAND_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if (cmd != oldcmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) pci_info(dev, "enabling device (%04x -> %04x)\n", oldcmd, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) pci_write_config_word(dev, PCI_COMMAND, cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }