* [PATCH v7 0/4] Support for Generic PCI Host Controller
@ 2014-05-23 16:51 ` Will Deacon
0 siblings, 0 replies; 18+ messages in thread
From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw)
To: linux-arm-kernel
Cc: arnd, linux-pci, bhelgaas, jgunthorpe, sthokal, Will Deacon
Hi all,
This is version 7 of the generic PCI host controller series that has
previously been posted here:
v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/229679.html
v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/232213.html
v3: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/233491.html
v4: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/235468.html
v5: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/237540.html
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/252915.html
v6: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/253993.html
Changes since v6 include:
- Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled
SoCs
- Included patch from Srikanth for generic Configuration Space access to
be factored out and used by other drivers
- Fixed minor issue in I/O port allocation (I had a >= instead of a >)
All comments welcome,
Will
Srikanth Thokala (1):
PCI: Generic Configuration Access Mechanism support
Will Deacon (3):
ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM
PCI: ARM: add support for generic PCI host controller
MAINTAINERS: add entry for generic PCI host controller driver
.../devicetree/bindings/pci/host-generic-pci.txt | 100 ++++++
MAINTAINERS | 8 +
arch/arm/Kconfig | 1 +
arch/arm/mach-bcm/Kconfig | 1 -
arch/arm/mach-cns3xxx/Kconfig | 1 -
arch/arm/mach-imx/Kconfig | 1 -
arch/arm/mach-mvebu/Kconfig | 1 -
arch/arm/mach-shmobile/Kconfig | 1 -
arch/arm/mach-tegra/Kconfig | 1 -
drivers/pci/Makefile | 2 +-
drivers/pci/host/Kconfig | 7 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pci-host-generic.c | 388 +++++++++++++++++++++
drivers/pci/pci-cfg.c | 162 +++++++++
include/linux/pci.h | 34 ++
15 files changed, 702 insertions(+), 7 deletions(-)
create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt
create mode 100644 drivers/pci/host/pci-host-generic.c
create mode 100644 drivers/pci/pci-cfg.c
--
1.9.2
^ permalink raw reply [flat|nested] 18+ messages in thread* [PATCH v7 0/4] Support for Generic PCI Host Controller @ 2014-05-23 16:51 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Hi all, This is version 7 of the generic PCI host controller series that has previously been posted here: v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/229679.html v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/232213.html v3: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/233491.html v4: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/235468.html v5: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-March/237540.html http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/252915.html v6: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-May/253993.html Changes since v6 include: - Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled SoCs - Included patch from Srikanth for generic Configuration Space access to be factored out and used by other drivers - Fixed minor issue in I/O port allocation (I had a >= instead of a >) All comments welcome, Will Srikanth Thokala (1): PCI: Generic Configuration Access Mechanism support Will Deacon (3): ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM PCI: ARM: add support for generic PCI host controller MAINTAINERS: add entry for generic PCI host controller driver .../devicetree/bindings/pci/host-generic-pci.txt | 100 ++++++ MAINTAINERS | 8 + arch/arm/Kconfig | 1 + arch/arm/mach-bcm/Kconfig | 1 - arch/arm/mach-cns3xxx/Kconfig | 1 - arch/arm/mach-imx/Kconfig | 1 - arch/arm/mach-mvebu/Kconfig | 1 - arch/arm/mach-shmobile/Kconfig | 1 - arch/arm/mach-tegra/Kconfig | 1 - drivers/pci/Makefile | 2 +- drivers/pci/host/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-host-generic.c | 388 +++++++++++++++++++++ drivers/pci/pci-cfg.c | 162 +++++++++ include/linux/pci.h | 34 ++ 15 files changed, 702 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt create mode 100644 drivers/pci/host/pci-host-generic.c create mode 100644 drivers/pci/pci-cfg.c -- 1.9.2 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 1/4] ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 16:51 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Cc: arnd, linux-pci, bhelgaas, jgunthorpe, sthokal, Will Deacon When targetting ARCH_MULTIPLATFORM, we may include support for SoCs with PCI-capable devices (e.g. mach-virt with virtio-pci). This patch allows PCI support to be selected for these SoCs by selecting CONFIG_MIGHT_HAVE_PCI when CONFIG_ARCH_MULTIPLATFORM=y and removes the individual selections from multi-platform enabled SoCs. Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Will Deacon <will.deacon@arm.com> --- arch/arm/Kconfig | 1 + arch/arm/mach-bcm/Kconfig | 1 - arch/arm/mach-cns3xxx/Kconfig | 1 - arch/arm/mach-imx/Kconfig | 1 - arch/arm/mach-mvebu/Kconfig | 1 - arch/arm/mach-shmobile/Kconfig | 1 - arch/arm/mach-tegra/Kconfig | 1 - 7 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c5414223e..860bea828ac4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -314,6 +314,7 @@ config ARCH_MULTIPLATFORM select CLKSRC_OF select COMMON_CLK select GENERIC_CLOCKEVENTS + select MIGHT_HAVE_PCI select MULTI_IRQ_HANDLER select SPARSE_IRQ select USE_OF diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 49c914cd9c7a..764c129b5eee 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -55,7 +55,6 @@ config ARCH_BCM_5301X select GENERIC_CLOCKEVENTS select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - select MIGHT_HAVE_PCI help Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index dce8decd5d46..66838f42037f 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -1,7 +1,6 @@ config ARCH_CNS3XXX bool "Cavium Networks CNS3XXX family" if ARCH_MULTI_V6 select ARM_GIC - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI help Support for Cavium Networks CNS3XXX platform. diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5740296dc429..50bb546b893a 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -796,7 +796,6 @@ config SOC_IMX6Q select ARM_ERRATA_764369 if SMP select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI select PINCTRL_IMX6Q select SOC_IMX6 diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3f73eecbcfb0..120301ebd324 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -9,7 +9,6 @@ config ARCH_MVEBU select MVEBU_MBUS select ZONE_DMA if ARM_LPAE select ARCH_REQUIRE_GPIOLIB - select MIGHT_HAVE_PCI select PCI_QUIRKS if PCI select OF_ADDRESS_PCI diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 0f92ba8e7884..905003898913 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -8,7 +8,6 @@ config ARCH_SHMOBILE_MULTI select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select ARM_GIC - select MIGHT_HAVE_PCI select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select NO_IOPORT_MAP select PINCTRL diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 55b305d51669..e16999e5b735 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -7,7 +7,6 @@ config ARCH_TEGRA select CLKSRC_MMIO select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PINCTRL select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 1/4] ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM @ 2014-05-23 16:51 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel When targetting ARCH_MULTIPLATFORM, we may include support for SoCs with PCI-capable devices (e.g. mach-virt with virtio-pci). This patch allows PCI support to be selected for these SoCs by selecting CONFIG_MIGHT_HAVE_PCI when CONFIG_ARCH_MULTIPLATFORM=y and removes the individual selections from multi-platform enabled SoCs. Acked-by: Rob Herring <robh@kernel.org> Signed-off-by: Will Deacon <will.deacon@arm.com> --- arch/arm/Kconfig | 1 + arch/arm/mach-bcm/Kconfig | 1 - arch/arm/mach-cns3xxx/Kconfig | 1 - arch/arm/mach-imx/Kconfig | 1 - arch/arm/mach-mvebu/Kconfig | 1 - arch/arm/mach-shmobile/Kconfig | 1 - arch/arm/mach-tegra/Kconfig | 1 - 7 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index db3c5414223e..860bea828ac4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -314,6 +314,7 @@ config ARCH_MULTIPLATFORM select CLKSRC_OF select COMMON_CLK select GENERIC_CLOCKEVENTS + select MIGHT_HAVE_PCI select MULTI_IRQ_HANDLER select SPARSE_IRQ select USE_OF diff --git a/arch/arm/mach-bcm/Kconfig b/arch/arm/mach-bcm/Kconfig index 49c914cd9c7a..764c129b5eee 100644 --- a/arch/arm/mach-bcm/Kconfig +++ b/arch/arm/mach-bcm/Kconfig @@ -55,7 +55,6 @@ config ARCH_BCM_5301X select GENERIC_CLOCKEVENTS select ARM_GLOBAL_TIMER select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - select MIGHT_HAVE_PCI help Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig index dce8decd5d46..66838f42037f 100644 --- a/arch/arm/mach-cns3xxx/Kconfig +++ b/arch/arm/mach-cns3xxx/Kconfig @@ -1,7 +1,6 @@ config ARCH_CNS3XXX bool "Cavium Networks CNS3XXX family" if ARCH_MULTI_V6 select ARM_GIC - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI help Support for Cavium Networks CNS3XXX platform. diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 5740296dc429..50bb546b893a 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -796,7 +796,6 @@ config SOC_IMX6Q select ARM_ERRATA_764369 if SMP select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PCI_DOMAINS if PCI select PINCTRL_IMX6Q select SOC_IMX6 diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 3f73eecbcfb0..120301ebd324 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -9,7 +9,6 @@ config ARCH_MVEBU select MVEBU_MBUS select ZONE_DMA if ARM_LPAE select ARCH_REQUIRE_GPIOLIB - select MIGHT_HAVE_PCI select PCI_QUIRKS if PCI select OF_ADDRESS_PCI diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 0f92ba8e7884..905003898913 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig @@ -8,7 +8,6 @@ config ARCH_SHMOBILE_MULTI select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select ARM_GIC - select MIGHT_HAVE_PCI select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE select NO_IOPORT_MAP select PINCTRL diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 55b305d51669..e16999e5b735 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -7,7 +7,6 @@ config ARCH_TEGRA select CLKSRC_MMIO select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP - select MIGHT_HAVE_PCI select PINCTRL select ARCH_HAS_RESET_CONTROLLER select RESET_CONTROLLER -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 2/4] PCI: ARM: add support for generic PCI host controller 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 16:51 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Cc: arnd, linux-pci, bhelgaas, jgunthorpe, sthokal, Will Deacon This patch adds support for a generic PCI host controller, such as a firmware-initialised device with static windows or an emulation by something such as kvmtool. The controller itself has no configuration registers and has its address spaces described entirely by the device-tree (using the bindings from ePAPR). Both CAM and ECAM are supported for Config Space accesses. Corresponding documentation is added for the DT binding. Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> --- .../devicetree/bindings/pci/host-generic-pci.txt | 100 ++++++ drivers/pci/host/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-host-generic.c | 388 +++++++++++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt create mode 100644 drivers/pci/host/pci-host-generic.c diff --git a/Documentation/devicetree/bindings/pci/host-generic-pci.txt b/Documentation/devicetree/bindings/pci/host-generic-pci.txt new file mode 100644 index 000000000000..f0b0436807b4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/host-generic-pci.txt @@ -0,0 +1,100 @@ +* Generic PCI host controller + +Firmware-initialised PCI host controllers and PCI emulations, such as the +virtio-pci implementations found in kvmtool and other para-virtualised +systems, do not require driver support for complexities such as regulator +and clock management. In fact, the controller may not even require the +configuration of a control interface by the operating system, instead +presenting a set of fixed windows describing a subset of IO, Memory and +Configuration Spaces. + +Such a controller can be described purely in terms of the standardized device +tree bindings communicated in pci.txt: + + +Properties of the host controller node: + +- compatible : Must be "pci-host-cam-generic" or "pci-host-ecam-generic" + depending on the layout of configuration space (CAM vs + ECAM respectively). + +- device_type : Must be "pci". + +- ranges : As described in IEEE Std 1275-1994, but must provide + at least a definition of non-prefetchable memory. One + or both of prefetchable Memory and IO Space may also + be provided. + +- bus-range : Optional property (also described in IEEE Std 1275-1994) + to indicate the range of bus numbers for this controller. + If absent, defaults to <0 255> (i.e. all buses). + +- #address-cells : Must be 3. + +- #size-cells : Must be 2. + +- reg : The Configuration Space base address and size, as accessed + from the parent bus. + + +Properties of the /chosen node: + +- linux,pci-probe-only + : Optional property which takes a single-cell argument. + If '0', then Linux will assign devices in its usual manner, + otherwise it will not try to assign devices and instead use + them as they are configured already. + +Configuration Space is assumed to be memory-mapped (as opposed to being +accessed via an ioport) and laid out with a direct correspondence to the +geography of a PCI bus address by concatenating the various components to +form an offset. + +For CAM, this 24-bit offset is: + + cfg_offset(bus, device, function, register) = + bus << 16 | device << 11 | function << 8 | register + +Whilst ECAM extends this by 4 bits to accomodate 4k of function space: + + cfg_offset(bus, device, function, register) = + bus << 20 | device << 15 | function << 12 | register + +Interrupt mapping is exactly as described in `Open Firmware Recommended +Practice: Interrupt Mapping' and requires the following properties: + +- #interrupt-cells : Must be 1 + +- interrupt-map : <see aforementioned specification> + +- interrupt-map-mask : <see aforementioned specification> + + +Example: + +pci { + compatible = "pci-host-cam-generic" + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0x1>; + + // CPU_PHYSICAL(2) SIZE(2) + reg = <0x0 0x40000000 0x0 0x1000000>; + + // BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2) + ranges = <0x01000000 0x0 0x01000000 0x0 0x01000000 0x0 0x00010000>, + <0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0x3f000000>; + + + #interrupt-cells = <0x1>; + + // PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(3) + interrupt-map = < 0x0 0x0 0x0 0x1 &gic 0x0 0x4 0x1 + 0x800 0x0 0x0 0x1 &gic 0x0 0x5 0x1 + 0x1000 0x0 0x0 0x1 &gic 0x0 0x6 0x1 + 0x1800 0x0 0x0 0x1 &gic 0x0 0x7 0x1>; + + // PCI_DEVICE(3) INT#(1) + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; +} diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index a6f67ec8882f..32d446effbb3 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2 There are 3 internal PCI controllers available with a single built-in EHCI/OHCI host controller present on each one. +config PCI_HOST_GENERIC + bool "Generic PCI host controller" + depends on ARM && OF + help + Say Y here if you want to support a simple generic PCI host + controller, such as the one emulated by kvmtool. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 13fb3333aa05..bd1bf1ab4ac8 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o +obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c new file mode 100644 index 000000000000..44fe6aa6a43f --- /dev/null +++ b/drivers/pci/host/pci-host-generic.c @@ -0,0 +1,388 @@ +/* + * Simple, generic PCI host controller driver targetting firmware-initialised + * systems and virtual machines (e.g. the PCI emulation provided by kvmtool). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2014 ARM Limited + * + * Author: Will Deacon <will.deacon@arm.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/platform_device.h> + +struct gen_pci_cfg_bus_ops { + u32 bus_shift; + void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); +}; + +struct gen_pci_cfg_windows { + struct resource res; + struct resource bus_range; + void __iomem **win; + + const struct gen_pci_cfg_bus_ops *ops; +}; + +struct gen_pci { + struct pci_host_bridge host; + struct gen_pci_cfg_windows cfg; + struct list_head resources; +}; + +static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + resource_size_t idx = bus->number - pci->cfg.bus_range.start; + + return pci->cfg.win[idx] + ((devfn << 8) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = { + .bus_shift = 16, + .map_bus = gen_pci_map_cfg_bus_cam, +}; + +static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + resource_size_t idx = bus->number - pci->cfg.bus_range.start; + + return pci->cfg.win[idx] + ((devfn << 12) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = { + .bus_shift = 20, + .map_bus = gen_pci_map_cfg_bus_ecam, +}; + +static int gen_pci_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + + addr = pci->cfg.ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + *val = readb(addr); + break; + case 2: + *val = readw(addr); + break; + default: + *val = readl(addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +static int gen_pci_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + + addr = pci->cfg.ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + writeb(val, addr); + break; + case 2: + writew(val, addr); + break; + default: + writel(val, addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops gen_pci_ops = { + .read = gen_pci_config_read, + .write = gen_pci_config_write, +}; + +static const struct of_device_id gen_pci_of_match[] = { + { .compatible = "pci-host-cam-generic", + .data = &gen_pci_cfg_cam_bus_ops }, + + { .compatible = "pci-host-ecam-generic", + .data = &gen_pci_cfg_ecam_bus_ops }, + + { }, +}; +MODULE_DEVICE_TABLE(of, gen_pci_of_match); + +static int gen_pci_calc_io_offset(struct device *dev, + struct of_pci_range *range, + struct resource *res, + resource_size_t *offset) +{ + static atomic_t wins = ATOMIC_INIT(0); + int err, idx, max_win; + unsigned int window; + + if (!PAGE_ALIGNED(range->cpu_addr)) + return -EINVAL; + + max_win = (IO_SPACE_LIMIT + 1) / SZ_64K; + idx = atomic_inc_return(&wins); + if (idx > max_win) + return -ENOSPC; + + window = (idx - 1) * SZ_64K; + err = pci_ioremap_io(window, range->cpu_addr); + if (err) + return err; + + of_pci_range_to_resource(range, dev->of_node, res); + res->start = window; + res->end = res->start + range->size - 1; + *offset = window - range->pci_addr; + return 0; +} + +static int gen_pci_calc_mem_offset(struct device *dev, + struct of_pci_range *range, + struct resource *res, + resource_size_t *offset) +{ + of_pci_range_to_resource(range, dev->of_node, res); + *offset = range->cpu_addr - range->pci_addr; + return 0; +} + +static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) +{ + struct pci_host_bridge_window *win; + + list_for_each_entry(win, &pci->resources, list) + release_resource(win->res); + + pci_free_resource_list(&pci->resources); +} + +static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) +{ + struct of_pci_range range; + struct of_pci_range_parser parser; + int err, res_valid = 0; + struct device *dev = pci->host.dev.parent; + struct device_node *np = dev->of_node; + + if (of_pci_range_parser_init(&parser, np)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + struct resource *parent, *res; + resource_size_t offset; + u32 restype = range.flags & IORESOURCE_TYPE_BITS; + + res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); + if (!res) { + err = -ENOMEM; + goto out_release_res; + } + + switch (restype) { + case IORESOURCE_IO: + parent = &ioport_resource; + err = gen_pci_calc_io_offset(dev, &range, res, &offset); + break; + case IORESOURCE_MEM: + parent = &iomem_resource; + err = gen_pci_calc_mem_offset(dev, &range, res, &offset); + res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); + break; + default: + err = -EINVAL; + continue; + } + + if (err) { + dev_warn(dev, + "error %d: failed to add resource [type 0x%x, %lld bytes]\n", + err, restype, range.size); + continue; + } + + err = request_resource(parent, res); + if (err) + goto out_release_res; + + pci_add_resource_offset(&pci->resources, res, offset); + } + + if (!res_valid) { + dev_err(dev, "non-prefetchable memory resource required\n"); + err = -EINVAL; + goto out_release_res; + } + + return 0; + +out_release_res: + gen_pci_release_of_pci_ranges(pci); + return err; +} + +static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) +{ + int err; + u8 bus_max; + resource_size_t busn; + struct resource *bus_range; + struct device *dev = pci->host.dev.parent; + struct device_node *np = dev->of_node; + + if (of_pci_parse_bus_range(np, &pci->cfg.bus_range)) + pci->cfg.bus_range = (struct resource) { + .name = np->name, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_BUS, + }; + + err = of_address_to_resource(np, 0, &pci->cfg.res); + if (err) { + dev_err(dev, "missing \"reg\" property\n"); + return err; + } + + pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), + sizeof(*pci->cfg.win), GFP_KERNEL); + if (!pci->cfg.win) + return -ENOMEM; + + /* Limit the bus-range to fit within reg */ + bus_max = pci->cfg.bus_range.start + + (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; + pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, + bus_max); + + /* Map our Configuration Space windows */ + if (!devm_request_mem_region(dev, pci->cfg.res.start, + resource_size(&pci->cfg.res), + "Configuration Space")) + return -ENOMEM; + + bus_range = &pci->cfg.bus_range; + for (busn = bus_range->start; busn <= bus_range->end; ++busn) { + u32 idx = busn - bus_range->start; + u32 sz = 1 << pci->cfg.ops->bus_shift; + + pci->cfg.win[idx] = devm_ioremap(dev, + pci->cfg.res.start + busn * sz, + sz); + if (!pci->cfg.win[idx]) + return -ENOMEM; + } + + /* Register bus resource */ + pci_add_resource(&pci->resources, bus_range); + return 0; +} + +static int gen_pci_setup(int nr, struct pci_sys_data *sys) +{ + struct gen_pci *pci = sys->private_data; + list_splice_init(&pci->resources, &sys->resources); + return 1; +} + +static int gen_pci_probe(struct platform_device *pdev) +{ + int err; + const char *type; + const struct of_device_id *of_id; + const int *prop; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + struct hw_pci hw = { + .nr_controllers = 1, + .private_data = (void **)&pci, + .setup = gen_pci_setup, + .map_irq = of_irq_parse_and_map_pci, + .ops = &gen_pci_ops, + }; + + if (!pci) + return -ENOMEM; + + type = of_get_property(np, "device_type", NULL); + if (!type || strcmp(type, "pci")) { + dev_err(dev, "invalid \"device_type\" %s\n", type); + return -EINVAL; + } + + prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); + if (prop) { + if (*prop) + pci_add_flags(PCI_PROBE_ONLY); + else + pci_clear_flags(PCI_PROBE_ONLY); + } + + of_id = of_match_node(gen_pci_of_match, np); + pci->cfg.ops = of_id->data; + pci->host.dev.parent = dev; + INIT_LIST_HEAD(&pci->host.windows); + INIT_LIST_HEAD(&pci->resources); + + /* Parse our PCI ranges and request their resources */ + err = gen_pci_parse_request_of_pci_ranges(pci); + if (err) + return err; + + /* Parse and map our Configuration Space windows */ + err = gen_pci_parse_map_cfg_windows(pci); + if (err) { + gen_pci_release_of_pci_ranges(pci); + return err; + } + + pci_common_init_dev(dev, &hw); + return 0; +} + +static struct platform_driver gen_pci_driver = { + .driver = { + .name = "pci-host-generic", + .owner = THIS_MODULE, + .of_match_table = gen_pci_of_match, + }, + .probe = gen_pci_probe, +}; +module_platform_driver(gen_pci_driver); + +MODULE_DESCRIPTION("Generic PCI host driver"); +MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); +MODULE_LICENSE("GPLv2"); -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 2/4] PCI: ARM: add support for generic PCI host controller @ 2014-05-23 16:51 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel This patch adds support for a generic PCI host controller, such as a firmware-initialised device with static windows or an emulation by something such as kvmtool. The controller itself has no configuration registers and has its address spaces described entirely by the device-tree (using the bindings from ePAPR). Both CAM and ECAM are supported for Config Space accesses. Corresponding documentation is added for the DT binding. Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> --- .../devicetree/bindings/pci/host-generic-pci.txt | 100 ++++++ drivers/pci/host/Kconfig | 7 + drivers/pci/host/Makefile | 1 + drivers/pci/host/pci-host-generic.c | 388 +++++++++++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt create mode 100644 drivers/pci/host/pci-host-generic.c diff --git a/Documentation/devicetree/bindings/pci/host-generic-pci.txt b/Documentation/devicetree/bindings/pci/host-generic-pci.txt new file mode 100644 index 000000000000..f0b0436807b4 --- /dev/null +++ b/Documentation/devicetree/bindings/pci/host-generic-pci.txt @@ -0,0 +1,100 @@ +* Generic PCI host controller + +Firmware-initialised PCI host controllers and PCI emulations, such as the +virtio-pci implementations found in kvmtool and other para-virtualised +systems, do not require driver support for complexities such as regulator +and clock management. In fact, the controller may not even require the +configuration of a control interface by the operating system, instead +presenting a set of fixed windows describing a subset of IO, Memory and +Configuration Spaces. + +Such a controller can be described purely in terms of the standardized device +tree bindings communicated in pci.txt: + + +Properties of the host controller node: + +- compatible : Must be "pci-host-cam-generic" or "pci-host-ecam-generic" + depending on the layout of configuration space (CAM vs + ECAM respectively). + +- device_type : Must be "pci". + +- ranges : As described in IEEE Std 1275-1994, but must provide + at least a definition of non-prefetchable memory. One + or both of prefetchable Memory and IO Space may also + be provided. + +- bus-range : Optional property (also described in IEEE Std 1275-1994) + to indicate the range of bus numbers for this controller. + If absent, defaults to <0 255> (i.e. all buses). + +- #address-cells : Must be 3. + +- #size-cells : Must be 2. + +- reg : The Configuration Space base address and size, as accessed + from the parent bus. + + +Properties of the /chosen node: + +- linux,pci-probe-only + : Optional property which takes a single-cell argument. + If '0', then Linux will assign devices in its usual manner, + otherwise it will not try to assign devices and instead use + them as they are configured already. + +Configuration Space is assumed to be memory-mapped (as opposed to being +accessed via an ioport) and laid out with a direct correspondence to the +geography of a PCI bus address by concatenating the various components to +form an offset. + +For CAM, this 24-bit offset is: + + cfg_offset(bus, device, function, register) = + bus << 16 | device << 11 | function << 8 | register + +Whilst ECAM extends this by 4 bits to accomodate 4k of function space: + + cfg_offset(bus, device, function, register) = + bus << 20 | device << 15 | function << 12 | register + +Interrupt mapping is exactly as described in `Open Firmware Recommended +Practice: Interrupt Mapping' and requires the following properties: + +- #interrupt-cells : Must be 1 + +- interrupt-map : <see aforementioned specification> + +- interrupt-map-mask : <see aforementioned specification> + + +Example: + +pci { + compatible = "pci-host-cam-generic" + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + bus-range = <0x0 0x1>; + + // CPU_PHYSICAL(2) SIZE(2) + reg = <0x0 0x40000000 0x0 0x1000000>; + + // BUS_ADDRESS(3) CPU_PHYSICAL(2) SIZE(2) + ranges = <0x01000000 0x0 0x01000000 0x0 0x01000000 0x0 0x00010000>, + <0x02000000 0x0 0x41000000 0x0 0x41000000 0x0 0x3f000000>; + + + #interrupt-cells = <0x1>; + + // PCI_DEVICE(3) INT#(1) CONTROLLER(PHANDLE) CONTROLLER_DATA(3) + interrupt-map = < 0x0 0x0 0x0 0x1 &gic 0x0 0x4 0x1 + 0x800 0x0 0x0 0x1 &gic 0x0 0x5 0x1 + 0x1000 0x0 0x0 0x1 &gic 0x0 0x6 0x1 + 0x1800 0x0 0x0 0x1 &gic 0x0 0x7 0x1>; + + // PCI_DEVICE(3) INT#(1) + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; +} diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index a6f67ec8882f..32d446effbb3 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -33,4 +33,11 @@ config PCI_RCAR_GEN2 There are 3 internal PCI controllers available with a single built-in EHCI/OHCI host controller present on each one. +config PCI_HOST_GENERIC + bool "Generic PCI host controller" + depends on ARM && OF + help + Say Y here if you want to support a simple generic PCI host + controller, such as the one emulated by kvmtool. + endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index 13fb3333aa05..bd1bf1ab4ac8 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o +obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c new file mode 100644 index 000000000000..44fe6aa6a43f --- /dev/null +++ b/drivers/pci/host/pci-host-generic.c @@ -0,0 +1,388 @@ +/* + * Simple, generic PCI host controller driver targetting firmware-initialised + * systems and virtual machines (e.g. the PCI emulation provided by kvmtool). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2014 ARM Limited + * + * Author: Will Deacon <will.deacon@arm.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/platform_device.h> + +struct gen_pci_cfg_bus_ops { + u32 bus_shift; + void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); +}; + +struct gen_pci_cfg_windows { + struct resource res; + struct resource bus_range; + void __iomem **win; + + const struct gen_pci_cfg_bus_ops *ops; +}; + +struct gen_pci { + struct pci_host_bridge host; + struct gen_pci_cfg_windows cfg; + struct list_head resources; +}; + +static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + resource_size_t idx = bus->number - pci->cfg.bus_range.start; + + return pci->cfg.win[idx] + ((devfn << 8) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = { + .bus_shift = 16, + .map_bus = gen_pci_map_cfg_bus_cam, +}; + +static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + resource_size_t idx = bus->number - pci->cfg.bus_range.start; + + return pci->cfg.win[idx] + ((devfn << 12) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = { + .bus_shift = 20, + .map_bus = gen_pci_map_cfg_bus_ecam, +}; + +static int gen_pci_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + + addr = pci->cfg.ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + *val = readb(addr); + break; + case 2: + *val = readw(addr); + break; + default: + *val = readl(addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +static int gen_pci_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct gen_pci *pci = sys->private_data; + + addr = pci->cfg.ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + writeb(val, addr); + break; + case 2: + writew(val, addr); + break; + default: + writel(val, addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops gen_pci_ops = { + .read = gen_pci_config_read, + .write = gen_pci_config_write, +}; + +static const struct of_device_id gen_pci_of_match[] = { + { .compatible = "pci-host-cam-generic", + .data = &gen_pci_cfg_cam_bus_ops }, + + { .compatible = "pci-host-ecam-generic", + .data = &gen_pci_cfg_ecam_bus_ops }, + + { }, +}; +MODULE_DEVICE_TABLE(of, gen_pci_of_match); + +static int gen_pci_calc_io_offset(struct device *dev, + struct of_pci_range *range, + struct resource *res, + resource_size_t *offset) +{ + static atomic_t wins = ATOMIC_INIT(0); + int err, idx, max_win; + unsigned int window; + + if (!PAGE_ALIGNED(range->cpu_addr)) + return -EINVAL; + + max_win = (IO_SPACE_LIMIT + 1) / SZ_64K; + idx = atomic_inc_return(&wins); + if (idx > max_win) + return -ENOSPC; + + window = (idx - 1) * SZ_64K; + err = pci_ioremap_io(window, range->cpu_addr); + if (err) + return err; + + of_pci_range_to_resource(range, dev->of_node, res); + res->start = window; + res->end = res->start + range->size - 1; + *offset = window - range->pci_addr; + return 0; +} + +static int gen_pci_calc_mem_offset(struct device *dev, + struct of_pci_range *range, + struct resource *res, + resource_size_t *offset) +{ + of_pci_range_to_resource(range, dev->of_node, res); + *offset = range->cpu_addr - range->pci_addr; + return 0; +} + +static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) +{ + struct pci_host_bridge_window *win; + + list_for_each_entry(win, &pci->resources, list) + release_resource(win->res); + + pci_free_resource_list(&pci->resources); +} + +static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) +{ + struct of_pci_range range; + struct of_pci_range_parser parser; + int err, res_valid = 0; + struct device *dev = pci->host.dev.parent; + struct device_node *np = dev->of_node; + + if (of_pci_range_parser_init(&parser, np)) { + dev_err(dev, "missing \"ranges\" property\n"); + return -EINVAL; + } + + for_each_of_pci_range(&parser, &range) { + struct resource *parent, *res; + resource_size_t offset; + u32 restype = range.flags & IORESOURCE_TYPE_BITS; + + res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); + if (!res) { + err = -ENOMEM; + goto out_release_res; + } + + switch (restype) { + case IORESOURCE_IO: + parent = &ioport_resource; + err = gen_pci_calc_io_offset(dev, &range, res, &offset); + break; + case IORESOURCE_MEM: + parent = &iomem_resource; + err = gen_pci_calc_mem_offset(dev, &range, res, &offset); + res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); + break; + default: + err = -EINVAL; + continue; + } + + if (err) { + dev_warn(dev, + "error %d: failed to add resource [type 0x%x, %lld bytes]\n", + err, restype, range.size); + continue; + } + + err = request_resource(parent, res); + if (err) + goto out_release_res; + + pci_add_resource_offset(&pci->resources, res, offset); + } + + if (!res_valid) { + dev_err(dev, "non-prefetchable memory resource required\n"); + err = -EINVAL; + goto out_release_res; + } + + return 0; + +out_release_res: + gen_pci_release_of_pci_ranges(pci); + return err; +} + +static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) +{ + int err; + u8 bus_max; + resource_size_t busn; + struct resource *bus_range; + struct device *dev = pci->host.dev.parent; + struct device_node *np = dev->of_node; + + if (of_pci_parse_bus_range(np, &pci->cfg.bus_range)) + pci->cfg.bus_range = (struct resource) { + .name = np->name, + .start = 0, + .end = 0xff, + .flags = IORESOURCE_BUS, + }; + + err = of_address_to_resource(np, 0, &pci->cfg.res); + if (err) { + dev_err(dev, "missing \"reg\" property\n"); + return err; + } + + pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), + sizeof(*pci->cfg.win), GFP_KERNEL); + if (!pci->cfg.win) + return -ENOMEM; + + /* Limit the bus-range to fit within reg */ + bus_max = pci->cfg.bus_range.start + + (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; + pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, + bus_max); + + /* Map our Configuration Space windows */ + if (!devm_request_mem_region(dev, pci->cfg.res.start, + resource_size(&pci->cfg.res), + "Configuration Space")) + return -ENOMEM; + + bus_range = &pci->cfg.bus_range; + for (busn = bus_range->start; busn <= bus_range->end; ++busn) { + u32 idx = busn - bus_range->start; + u32 sz = 1 << pci->cfg.ops->bus_shift; + + pci->cfg.win[idx] = devm_ioremap(dev, + pci->cfg.res.start + busn * sz, + sz); + if (!pci->cfg.win[idx]) + return -ENOMEM; + } + + /* Register bus resource */ + pci_add_resource(&pci->resources, bus_range); + return 0; +} + +static int gen_pci_setup(int nr, struct pci_sys_data *sys) +{ + struct gen_pci *pci = sys->private_data; + list_splice_init(&pci->resources, &sys->resources); + return 1; +} + +static int gen_pci_probe(struct platform_device *pdev) +{ + int err; + const char *type; + const struct of_device_id *of_id; + const int *prop; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + struct hw_pci hw = { + .nr_controllers = 1, + .private_data = (void **)&pci, + .setup = gen_pci_setup, + .map_irq = of_irq_parse_and_map_pci, + .ops = &gen_pci_ops, + }; + + if (!pci) + return -ENOMEM; + + type = of_get_property(np, "device_type", NULL); + if (!type || strcmp(type, "pci")) { + dev_err(dev, "invalid \"device_type\" %s\n", type); + return -EINVAL; + } + + prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); + if (prop) { + if (*prop) + pci_add_flags(PCI_PROBE_ONLY); + else + pci_clear_flags(PCI_PROBE_ONLY); + } + + of_id = of_match_node(gen_pci_of_match, np); + pci->cfg.ops = of_id->data; + pci->host.dev.parent = dev; + INIT_LIST_HEAD(&pci->host.windows); + INIT_LIST_HEAD(&pci->resources); + + /* Parse our PCI ranges and request their resources */ + err = gen_pci_parse_request_of_pci_ranges(pci); + if (err) + return err; + + /* Parse and map our Configuration Space windows */ + err = gen_pci_parse_map_cfg_windows(pci); + if (err) { + gen_pci_release_of_pci_ranges(pci); + return err; + } + + pci_common_init_dev(dev, &hw); + return 0; +} + +static struct platform_driver gen_pci_driver = { + .driver = { + .name = "pci-host-generic", + .owner = THIS_MODULE, + .of_match_table = gen_pci_of_match, + }, + .probe = gen_pci_probe, +}; +module_platform_driver(gen_pci_driver); + +MODULE_DESCRIPTION("Generic PCI host driver"); +MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); +MODULE_LICENSE("GPLv2"); -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 3/4] MAINTAINERS: add entry for generic PCI host controller driver 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 16:51 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Cc: arnd, linux-pci, bhelgaas, jgunthorpe, sthokal, Will Deacon Add myself as the maintainer for the generic PCI host controller driver. Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Will Deacon <will.deacon@arm.com> --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51ebb779c5f3..fc1d6ff43067 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6751,6 +6751,14 @@ L: linux-pci@vger.kernel.org S: Maintained F: drivers/pci/host/*designware* +PCI DRIVER FOR GENERIC OF HOSTS +M: Will Deacon <will.deacon@arm.com> +L: linux-pci@vger.kernel.org +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/pci/host-generic-pci.txt +F: drivers/pci/host/pci-host-generic.c + PCMCIA SUBSYSTEM P: Linux PCMCIA Team L: linux-pcmcia@lists.infradead.org -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 3/4] MAINTAINERS: add entry for generic PCI host controller driver @ 2014-05-23 16:51 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Add myself as the maintainer for the generic PCI host controller driver. Cc: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Will Deacon <will.deacon@arm.com> --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 51ebb779c5f3..fc1d6ff43067 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6751,6 +6751,14 @@ L: linux-pci at vger.kernel.org S: Maintained F: drivers/pci/host/*designware* +PCI DRIVER FOR GENERIC OF HOSTS +M: Will Deacon <will.deacon@arm.com> +L: linux-pci at vger.kernel.org +L: linux-arm-kernel at lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/pci/host-generic-pci.txt +F: drivers/pci/host/pci-host-generic.c + PCMCIA SUBSYSTEM P: Linux PCMCIA Team L: linux-pcmcia at lists.infradead.org -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 16:51 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel Cc: arnd, linux-pci, bhelgaas, jgunthorpe, sthokal, Will Deacon From: Srikanth Thokala <sthokal@xilinx.com> This patch adds support for a generic CAM and ECAM configuration space accesses. Signed-off-by: Srikanth Thokala <sthokal@xilinx.com> Signed-off-by: Will Deacon <will.deacon@arm.com> --- drivers/pci/Makefile | 2 +- drivers/pci/pci-cfg.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 34 +++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 drivers/pci/pci-cfg.c diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index e04fe2d9df3b..37cfc3356e84 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ - irq.o vpd.o setup-bus.o vc.o + irq.o vpd.o setup-bus.o vc.o pci-cfg.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSFS) += slot.o diff --git a/drivers/pci/pci-cfg.c b/drivers/pci/pci-cfg.c new file mode 100644 index 000000000000..2b15fe4c3c20 --- /dev/null +++ b/drivers/pci/pci-cfg.c @@ -0,0 +1,162 @@ +/* + * PCI generic configuration access mechanism + * + * Copyright (C) 2014 ARM Limited + * Copyright (c) 2014 Xilinx, Inc. + * + * Author: Will Deacon <will.deacon@arm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/of_pci.h> + +/* CAM definitions */ +#define PCI_CFG_CAM_BUS_NUM 16 +#define PCI_CFG_CAM_DEV_NUM 8 + +/* ECAM definitions */ +#define PCI_CFG_ECAM_BUS_NUM 20 +#define PCI_CFG_ECAM_DEV_NUM 12 + +/* Invalid device/function value */ +#define PCI_CFG_INVALID_DEVFN 0xFFFFFFFF + +/** + * pci_cfg_map_bus_cam - Get the CAM based configuration space address + * @bus: PCI Bus pointer + * @devfn: Device/Function + * @where: Offset from base + * + * Return: Configuration Space address + */ +static void __iomem *pci_cfg_map_bus_cam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + resource_size_t idx = bus->number - cfg->bus_range.start; + + return cfg->win[idx] + ((devfn << PCI_CFG_CAM_DEV_NUM) | where); +} + +/** + * pci_cfg_map_bus_ecam - Get the ECAM based configuration space address + * @bus: PCI bus pointer + * @devfn: Device/Function + * @where: Offset from base + * + * Return: Configuration space address + */ +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + resource_size_t idx = bus->number - cfg->bus_range.start; + + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); +} + +/** + * pci_cfg_read - Read configuration space + * @bus: PCI bus pointer + * @devfn: Device/function + * @where: Offset from base + * @size: Byte/word/dword + * @val: Value to be read + * + * Return: PCIBIOS_SUCCESSFUL on success + * PCIBIOS_DEVICE_NOT_FOUND on failure + */ +static int pci_cfg_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, unsigned int *val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + + if (cfg->ops->is_valid_cfg_access) { + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) { + *val = PCI_CFG_INVALID_DEVFN; + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + addr = cfg->ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + *val = readb(addr); + break; + case 2: + *val = readw(addr); + break; + default: + *val = readl(addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +/** + * pci_cfg_write - Write configuration space + * @bus: PCI bus pointer + * @devfn: Device/function + * @where: Offset from base + * @size: Byte/word/dword + * @val: Value to write + * + * Return: PCIBIOS_SUCCESSFUL on success + * PCIBIOS_DEVICE_NOT_FOUND on failure + */ +static int pci_cfg_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, unsigned int val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + + if (cfg->ops->is_valid_cfg_access) + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = cfg->ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + writeb(val, addr); + break; + case 2: + writew(val, addr); + break; + default: + writel(val, addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +/* Generic PCI CAM/ECAM Configuration Bus Operations */ + +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = { + .bus_shift = PCI_CFG_CAM_BUS_NUM, + .map_bus = pci_cfg_map_bus_cam, +}; +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops); + +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = { + .bus_shift = PCI_CFG_ECAM_BUS_NUM, + .map_bus = pci_cfg_map_bus_ecam, +}; +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops); + +struct pci_ops pci_cfg_ops = { + .read = pci_cfg_read, + .write = pci_cfg_write, +}; +EXPORT_SYMBOL_GPL(pci_cfg_ops); diff --git a/include/linux/pci.h b/include/linux/pci.h index aab57b4abe7f..6ebe21ebec1a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1806,4 +1806,38 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev) */ struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev); +/** + * struct pci_cfg_bus_ops - PCI bus configuration operations + * @bus_shift: Bus number + * @map_bus: Function pointer to get the configuration space address + * @is_valid_cfg_access: Function pointer to check for a valid device/function + */ +struct pci_cfg_bus_ops { + u32 bus_shift; + void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); + /* + * This function pointer is to check if we are addressing a valid + * device's function under a particular bus. + */ + int (*is_valid_cfg_access)(struct pci_bus *, unsigned int); +}; + +/** + * struct pci_cfg_windows - PCI bus configuration memory windows + * @res: Configuration space resource + * @bus_range: Bus range + * @win: Configuration space memory windows + * @ops: PCI bus configuration operations + */ +struct pci_cfg_windows { + struct resource res; + struct resource bus_range; + void __iomem **win; + struct pci_cfg_bus_ops *ops; +}; + +extern struct pci_ops pci_cfg_ops; +extern struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops; +extern struct pci_cfg_bus_ops pci_cfg_cam_bus_ops; + #endif /* LINUX_PCI_H */ -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support @ 2014-05-23 16:51 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-23 16:51 UTC (permalink / raw) To: linux-arm-kernel From: Srikanth Thokala <sthokal@xilinx.com> This patch adds support for a generic CAM and ECAM configuration space accesses. Signed-off-by: Srikanth Thokala <sthokal@xilinx.com> Signed-off-by: Will Deacon <will.deacon@arm.com> --- drivers/pci/Makefile | 2 +- drivers/pci/pci-cfg.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/pci.h | 34 +++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 drivers/pci/pci-cfg.c diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index e04fe2d9df3b..37cfc3356e84 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ - irq.o vpd.o setup-bus.o vc.o + irq.o vpd.o setup-bus.o vc.o pci-cfg.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_SYSFS) += slot.o diff --git a/drivers/pci/pci-cfg.c b/drivers/pci/pci-cfg.c new file mode 100644 index 000000000000..2b15fe4c3c20 --- /dev/null +++ b/drivers/pci/pci-cfg.c @@ -0,0 +1,162 @@ +/* + * PCI generic configuration access mechanism + * + * Copyright (C) 2014 ARM Limited + * Copyright (c) 2014 Xilinx, Inc. + * + * Author: Will Deacon <will.deacon@arm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/of_pci.h> + +/* CAM definitions */ +#define PCI_CFG_CAM_BUS_NUM 16 +#define PCI_CFG_CAM_DEV_NUM 8 + +/* ECAM definitions */ +#define PCI_CFG_ECAM_BUS_NUM 20 +#define PCI_CFG_ECAM_DEV_NUM 12 + +/* Invalid device/function value */ +#define PCI_CFG_INVALID_DEVFN 0xFFFFFFFF + +/** + * pci_cfg_map_bus_cam - Get the CAM based configuration space address + * @bus: PCI Bus pointer + * @devfn: Device/Function + * @where: Offset from base + * + * Return: Configuration Space address + */ +static void __iomem *pci_cfg_map_bus_cam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + resource_size_t idx = bus->number - cfg->bus_range.start; + + return cfg->win[idx] + ((devfn << PCI_CFG_CAM_DEV_NUM) | where); +} + +/** + * pci_cfg_map_bus_ecam - Get the ECAM based configuration space address + * @bus: PCI bus pointer + * @devfn: Device/Function + * @where: Offset from base + * + * Return: Configuration space address + */ +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, + unsigned int devfn, + int where) +{ + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + resource_size_t idx = bus->number - cfg->bus_range.start; + + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); +} + +/** + * pci_cfg_read - Read configuration space + * @bus: PCI bus pointer + * @devfn: Device/function + * @where: Offset from base + * @size: Byte/word/dword + * @val: Value to be read + * + * Return: PCIBIOS_SUCCESSFUL on success + * PCIBIOS_DEVICE_NOT_FOUND on failure + */ +static int pci_cfg_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, unsigned int *val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + + if (cfg->ops->is_valid_cfg_access) { + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) { + *val = PCI_CFG_INVALID_DEVFN; + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + addr = cfg->ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + *val = readb(addr); + break; + case 2: + *val = readw(addr); + break; + default: + *val = readl(addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +/** + * pci_cfg_write - Write configuration space + * @bus: PCI bus pointer + * @devfn: Device/function + * @where: Offset from base + * @size: Byte/word/dword + * @val: Value to write + * + * Return: PCIBIOS_SUCCESSFUL on success + * PCIBIOS_DEVICE_NOT_FOUND on failure + */ +static int pci_cfg_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, unsigned int val) +{ + void __iomem *addr; + struct pci_sys_data *sys = bus->sysdata; + struct pci_cfg_windows *cfg = sys->private_data; + + if (cfg->ops->is_valid_cfg_access) + if (!cfg->ops->is_valid_cfg_access(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = cfg->ops->map_bus(bus, devfn, where); + + switch (size) { + case 1: + writeb(val, addr); + break; + case 2: + writew(val, addr); + break; + default: + writel(val, addr); + } + + return PCIBIOS_SUCCESSFUL; +} + +/* Generic PCI CAM/ECAM Configuration Bus Operations */ + +struct pci_cfg_bus_ops pci_cfg_cam_bus_ops = { + .bus_shift = PCI_CFG_CAM_BUS_NUM, + .map_bus = pci_cfg_map_bus_cam, +}; +EXPORT_SYMBOL_GPL(pci_cfg_cam_bus_ops); + +struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops = { + .bus_shift = PCI_CFG_ECAM_BUS_NUM, + .map_bus = pci_cfg_map_bus_ecam, +}; +EXPORT_SYMBOL_GPL(pci_cfg_ecam_bus_ops); + +struct pci_ops pci_cfg_ops = { + .read = pci_cfg_read, + .write = pci_cfg_write, +}; +EXPORT_SYMBOL_GPL(pci_cfg_ops); diff --git a/include/linux/pci.h b/include/linux/pci.h index aab57b4abe7f..6ebe21ebec1a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1806,4 +1806,38 @@ static inline struct eeh_dev *pci_dev_to_eeh_dev(struct pci_dev *pdev) */ struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev); +/** + * struct pci_cfg_bus_ops - PCI bus configuration operations + * @bus_shift: Bus number + * @map_bus: Function pointer to get the configuration space address + * @is_valid_cfg_access: Function pointer to check for a valid device/function + */ +struct pci_cfg_bus_ops { + u32 bus_shift; + void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); + /* + * This function pointer is to check if we are addressing a valid + * device's function under a particular bus. + */ + int (*is_valid_cfg_access)(struct pci_bus *, unsigned int); +}; + +/** + * struct pci_cfg_windows - PCI bus configuration memory windows + * @res: Configuration space resource + * @bus_range: Bus range + * @win: Configuration space memory windows + * @ops: PCI bus configuration operations + */ +struct pci_cfg_windows { + struct resource res; + struct resource bus_range; + void __iomem **win; + struct pci_cfg_bus_ops *ops; +}; + +extern struct pci_ops pci_cfg_ops; +extern struct pci_cfg_bus_ops pci_cfg_ecam_bus_ops; +extern struct pci_cfg_bus_ops pci_cfg_cam_bus_ops; + #endif /* LINUX_PCI_H */ -- 1.9.2 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 19:22 ` Arnd Bergmann -1 siblings, 0 replies; 18+ messages in thread From: Arnd Bergmann @ 2014-05-23 19:22 UTC (permalink / raw) To: Will Deacon; +Cc: linux-arm-kernel, linux-pci, bhelgaas, jgunthorpe, sthokal On Friday 23 May 2014, Will Deacon wrote: > +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, > + unsigned int devfn, > + int where) > +{ > + struct pci_sys_data *sys = bus->sysdata; > + struct pci_cfg_windows *cfg = sys->private_data; > + resource_size_t idx = bus->number - cfg->bus_range.start; > + > + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); > +} I just noticed that this function makes the code rather non-generic, because struct pci_sys_data is the ARM specific structure that doesn't exist elsewhere, and sys->private_data wouldn't typically point to struct pci_cfg_windows on anything other than your generic PCI host. I'd say let's drop this for now. I know it was my idea to do it like this, but it seems it's more complex than I had hoped to get this right, and I'd really prefer to merge the other three patches for 3.16 if possible. We can factor it out later if we get more users. Arnd ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support @ 2014-05-23 19:22 ` Arnd Bergmann 0 siblings, 0 replies; 18+ messages in thread From: Arnd Bergmann @ 2014-05-23 19:22 UTC (permalink / raw) To: linux-arm-kernel On Friday 23 May 2014, Will Deacon wrote: > +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, > + unsigned int devfn, > + int where) > +{ > + struct pci_sys_data *sys = bus->sysdata; > + struct pci_cfg_windows *cfg = sys->private_data; > + resource_size_t idx = bus->number - cfg->bus_range.start; > + > + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); > +} I just noticed that this function makes the code rather non-generic, because struct pci_sys_data is the ARM specific structure that doesn't exist elsewhere, and sys->private_data wouldn't typically point to struct pci_cfg_windows on anything other than your generic PCI host. I'd say let's drop this for now. I know it was my idea to do it like this, but it seems it's more complex than I had hoped to get this right, and I'd really prefer to merge the other three patches for 3.16 if possible. We can factor it out later if we get more users. Arnd ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support 2014-05-23 19:22 ` Arnd Bergmann @ 2014-05-25 10:48 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-25 10:48 UTC (permalink / raw) To: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, bhelgaas@google.com, jgunthorpe@obsidianresearch.com, sthokal@xilinx.com On Fri, May 23, 2014 at 08:22:18PM +0100, Arnd Bergmann wrote: > On Friday 23 May 2014, Will Deacon wrote: > > +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, > > + unsigned int devfn, > > + int where) > > +{ > > + struct pci_sys_data *sys = bus->sysdata; > > + struct pci_cfg_windows *cfg = sys->private_data; > > + resource_size_t idx = bus->number - cfg->bus_range.start; > > + > > + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); > > +} > > I just noticed that this function makes the code rather non-generic, because > struct pci_sys_data is the ARM specific structure that doesn't exist elsewhere, > and sys->private_data wouldn't typically point to struct pci_cfg_windows on > anything other than your generic PCI host. Indeed. That's what I was refering to initially when I suggested some potential alignment on the private_data across host controller drivers trying to use this. > I'd say let's drop this for now. I know it was my idea to do it like this, > but it seems it's more complex than I had hoped to get this right, and > I'd really prefer to merge the other three patches for 3.16 if possible. > We can factor it out later if we get more users. Sure, I think we all had good intentions. I'll send a pull for the first three patches -- should it go via arm-soc or Bjorn's PCI tree? Cheers, Will ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support @ 2014-05-25 10:48 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-25 10:48 UTC (permalink / raw) To: linux-arm-kernel On Fri, May 23, 2014 at 08:22:18PM +0100, Arnd Bergmann wrote: > On Friday 23 May 2014, Will Deacon wrote: > > +static void __iomem *pci_cfg_map_bus_ecam(struct pci_bus *bus, > > + unsigned int devfn, > > + int where) > > +{ > > + struct pci_sys_data *sys = bus->sysdata; > > + struct pci_cfg_windows *cfg = sys->private_data; > > + resource_size_t idx = bus->number - cfg->bus_range.start; > > + > > + return cfg->win[idx] + ((devfn << PCI_CFG_ECAM_DEV_NUM) | where); > > +} > > I just noticed that this function makes the code rather non-generic, because > struct pci_sys_data is the ARM specific structure that doesn't exist elsewhere, > and sys->private_data wouldn't typically point to struct pci_cfg_windows on > anything other than your generic PCI host. Indeed. That's what I was refering to initially when I suggested some potential alignment on the private_data across host controller drivers trying to use this. > I'd say let's drop this for now. I know it was my idea to do it like this, > but it seems it's more complex than I had hoped to get this right, and > I'd really prefer to merge the other three patches for 3.16 if possible. > We can factor it out later if we get more users. Sure, I think we all had good intentions. I'll send a pull for the first three patches -- should it go via arm-soc or Bjorn's PCI tree? Cheers, Will ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/4] Support for Generic PCI Host Controller 2014-05-23 16:51 ` Will Deacon @ 2014-05-23 19:19 ` Arnd Bergmann -1 siblings, 0 replies; 18+ messages in thread From: Arnd Bergmann @ 2014-05-23 19:19 UTC (permalink / raw) To: Will Deacon; +Cc: linux-arm-kernel, linux-pci, bhelgaas, jgunthorpe, sthokal On Friday 23 May 2014, Will Deacon wrote: > - Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled > SoCs > > - Included patch from Srikanth for generic Configuration Space access to > be factored out and used by other drivers > > - Fixed minor issue in I/O port allocation (I had a >= instead of a >) > It seems strange that you include the patch from Srikanth but then use a separate copy of the same code in patch 2. Is that intentional? Arnd ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 0/4] Support for Generic PCI Host Controller @ 2014-05-23 19:19 ` Arnd Bergmann 0 siblings, 0 replies; 18+ messages in thread From: Arnd Bergmann @ 2014-05-23 19:19 UTC (permalink / raw) To: linux-arm-kernel On Friday 23 May 2014, Will Deacon wrote: > - Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled > SoCs > > - Included patch from Srikanth for generic Configuration Space access to > be factored out and used by other drivers > > - Fixed minor issue in I/O port allocation (I had a >= instead of a >) > It seems strange that you include the patch from Srikanth but then use a separate copy of the same code in patch 2. Is that intentional? Arnd ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH v7 0/4] Support for Generic PCI Host Controller 2014-05-23 19:19 ` Arnd Bergmann @ 2014-05-25 10:43 ` Will Deacon -1 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-25 10:43 UTC (permalink / raw) To: Arnd Bergmann Cc: linux-arm-kernel@lists.infradead.org, linux-pci@vger.kernel.org, bhelgaas@google.com, jgunthorpe@obsidianresearch.com, sthokal@xilinx.com Hi Arnd, On Fri, May 23, 2014 at 08:19:23PM +0100, Arnd Bergmann wrote: > On Friday 23 May 2014, Will Deacon wrote: > > - Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled > > SoCs > > > > - Included patch from Srikanth for generic Configuration Space access to > > be factored out and used by other drivers > > > > - Fixed minor issue in I/O port allocation (I had a >= instead of a >) > > > > It seems strange that you include the patch from Srikanth but then use > a separate copy of the same code in patch 2. Is that intentional? That was a combination of me not being sure about the status of Srikanth's patch (the review didn't seem to conclude) but also then forgetting to move over to using it. However, judging by your most recent comments, I'm glad I didn't spend any time on it! Will ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH v7 0/4] Support for Generic PCI Host Controller @ 2014-05-25 10:43 ` Will Deacon 0 siblings, 0 replies; 18+ messages in thread From: Will Deacon @ 2014-05-25 10:43 UTC (permalink / raw) To: linux-arm-kernel Hi Arnd, On Fri, May 23, 2014 at 08:19:23PM +0100, Arnd Bergmann wrote: > On Friday 23 May 2014, Will Deacon wrote: > > - Removed redundant MIGHT_HAVE_PCI selections from multiplatform-enabled > > SoCs > > > > - Included patch from Srikanth for generic Configuration Space access to > > be factored out and used by other drivers > > > > - Fixed minor issue in I/O port allocation (I had a >= instead of a >) > > > > It seems strange that you include the patch from Srikanth but then use > a separate copy of the same code in patch 2. Is that intentional? That was a combination of me not being sure about the status of Srikanth's patch (the review didn't seem to conclude) but also then forgetting to move over to using it. However, judging by your most recent comments, I'm glad I didn't spend any time on it! Will ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2014-05-25 10:48 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2014-05-23 16:51 [PATCH v7 0/4] Support for Generic PCI Host Controller Will Deacon 2014-05-23 16:51 ` Will Deacon 2014-05-23 16:51 ` [PATCH v7 1/4] ARM: kconfig: allow PCI support to be selected with ARCH_MULTIPLATFORM Will Deacon 2014-05-23 16:51 ` Will Deacon 2014-05-23 16:51 ` [PATCH v7 2/4] PCI: ARM: add support for generic PCI host controller Will Deacon 2014-05-23 16:51 ` Will Deacon 2014-05-23 16:51 ` [PATCH v7 3/4] MAINTAINERS: add entry for generic PCI host controller driver Will Deacon 2014-05-23 16:51 ` Will Deacon 2014-05-23 16:51 ` [PATCH v7 4/4] PCI: Generic Configuration Access Mechanism support Will Deacon 2014-05-23 16:51 ` Will Deacon 2014-05-23 19:22 ` Arnd Bergmann 2014-05-23 19:22 ` Arnd Bergmann 2014-05-25 10:48 ` Will Deacon 2014-05-25 10:48 ` Will Deacon 2014-05-23 19:19 ` [PATCH v7 0/4] Support for Generic PCI Host Controller Arnd Bergmann 2014-05-23 19:19 ` Arnd Bergmann 2014-05-25 10:43 ` Will Deacon 2014-05-25 10:43 ` Will Deacon
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.