* [RFC V2 PATCH 0/8] ARM: kirkwood: cleanup DT conversion
From: Jason Gunthorpe @ 2013-01-28 18:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130128104008.GA5170@localhost>
> > // MBUS Decoder window for NAND
> > nand at f4000000 {
> > #address-cells = <1>;
> > #size-cells = <1>;
> > compatible = "simple-bus", "marvell,orion-mbus";
> > mbus-target = 0xXXXXX;
> > ranges = <0 0xf4000000 0x10000>;
> >
> > nand at 0 {
> > cle = <0>;
> > ale = <1>;
> > bank-width = <1>;
> > chip-delay = <50>;
> > compatible = "marvell,orion-nand";
> > reg = <0x0 0x400>;
> > };
> > };
> >
>
> This is a nice idea.
>
> I have a few questions, though.
>
> 1. Are you sure we should use "ranges" property?
> In this case it's not an address translation but rather
> and address window configuration.
Yes, you'd use ranges with an identity transation. The purpose is so
that child OF blocks are all relative to the start of the decode
region. This way changing the address of the HW block behind the mbus
window is simply done by changing the ranges property.
Note the reg on the nand is starting at offset 0, so ranges will
translate that to 0xf4000000. Similar for the internal regs.
> I would think we could add a new "windows" property to reflect
> address window configuration.
My arrangement above would have each "marvell,orion-mbus" specify the
mbus-target, which I imagined to be all the HW specific bits (target,
attributes, etc). The addr-map driver would select a window for this
bus and then assign those bits to it.
> 2. Also, If we use "ranges" property. How would that work?
> By reading the property in the addr-map driver or
> by somehow improving on of_bus to include this new kind of busses?
The addr-map driver would have to read it, I believe the rules of how
busses work make this fairly simple:
1) very early on the addr-map driver would have to scan the OF tree,
find the address of the mbus mapping registers, and the internal
register map.
2) Verify the mbus window for the internal registers matches the DT
This is just a sanity check, if the correct value doesn't come back
then the DT doesnt match what the bootloader setup, and some
jtag accessible diagnostic can be printed...
3) Wipe all the mbus windows
4) Register a "marvell,orion-mbus" bus handler somehow
5) When OF processes the DT it would call the bus handler for each
"marvell,orion-mbus" which should parse the ranges, allocate
a free window, program that window then instantiate the child
devices.
Jason
^ permalink raw reply
* [PATCH 00/14] Rewrite Tegra PCIe driver
From: Bjorn Helgaas @ 2013-01-28 18:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1357764194-12677-1-git-send-email-thierry.reding@avionic-design.de>
On Wed, Jan 9, 2013 at 1:43 PM, Thierry Reding
<thierry.reding@avionic-design.de> wrote:
> This patch series contains an almost complete rewrite of the Tegra PCIe
> driver. The code is moved to the drivers/pci/host directory and turned
> into a proper platform driver, adding MSI and DT support while at it.
> Other PCI host controller drivers can be added to that directory in an
> attempt to make it easier to factor out common code.
>
> Patches 1 to 4 add generic OF helpers to parse a PCI node's ranges
> property as well as obtain the bus, device and function numbers from a
> node's reg property.
>
> Patch 5 provides an implementation of a cache for I/O mappings. This can
> be used in situations where a large physical memory region needs to be
> ioremap()'ed. On Tegra, the PCIe standard and extended configuration
> spaces can be accessed through a 256 MiB window. Mapping that in one
> chunk is wasteful and may not always work because the vmalloc area may
> not be large enough. The implementation in this patch uses an LRU based
> approach to map a limited amount of pages on an as-needed basis.
>
> Patches 6 and 7 prepare the ARM PCI code to enable PCI host controller
> drivers to load after the init stage, which can happen due to deferred
> probing, and to allow private data to be passed for each controller.
>
> Patches 8 and 9 move some of the Tegra specific code around to allow it
> to be used from outside the arch/arm/mach-tegra directory.
>
> Patch 10 moves the Tegra PCIe controller driver to the drivers/pci/host
> directory and turns it into a proper platform driver. It also adds MSI
> (based on patches by NVIDIA) and DT support.
>
> Patches 11 to 14 add device tree based probing for the TEC, Harmony and
> TrimSlice boards.
>
> Thierry
>
> Andrew Murray (1):
> of/pci: Provide support for parsing PCI DT ranges property
>
> Thierry Reding (13):
> of/pci: Add of_pci_get_devfn() function
> of/pci: Add of_pci_get_bus() function
> of/pci: Add of_pci_parse_bus_range() function
> lib: Add I/O map cache implementation
> ARM: pci: Keep pci_common_init() around after init
> ARM: pci: Allow passing per-controller private data
> ARM: tegra: Move tegra_pcie_xclk_clamp() to PMC
> ARM: tegra: Move pmc.h to include/mach
> PCI: tegra: Move PCIe driver to drivers/pci/host
> ARM: tegra: tamonten: Add PCIe support
> ARM: tegra: tec: Add PCIe support
> ARM: tegra: harmony: Initialize PCIe from DT
> ARM: tegra: trimslice: Initialize PCIe from DT
>
> .../bindings/pci/nvidia,tegra20-pcie.txt | 115 ++
> arch/arm/Kconfig | 2 +
> arch/arm/boot/dts/tegra20-harmony.dts | 20 +-
> arch/arm/boot/dts/tegra20-tamonten.dtsi | 2 +-
> arch/arm/boot/dts/tegra20-tec.dts | 198 +++
> arch/arm/boot/dts/tegra20-trimslice.dts | 12 +
> arch/arm/boot/dts/tegra20.dtsi | 45 +
> arch/arm/include/asm/mach/pci.h | 1 +
> arch/arm/kernel/bios32.c | 9 +-
> arch/arm/mach-tegra/Kconfig | 5 -
> arch/arm/mach-tegra/Makefile | 3 -
> arch/arm/mach-tegra/board-dt-tegra20.c | 24 -
> arch/arm/mach-tegra/board-harmony-pcie.c | 84 --
> arch/arm/mach-tegra/board.h | 4 +-
> arch/arm/mach-tegra/common.c | 2 +-
> arch/arm/mach-tegra/include/mach/pmc.h | 24 +
> arch/arm/mach-tegra/iomap.h | 3 -
> arch/arm/mach-tegra/pcie.c | 887 -------------
> arch/arm/mach-tegra/pmc.c | 16 +
> arch/arm/mach-tegra/pmc.h | 23 -
> drivers/of/address.c | 63 +
> drivers/of/of_pci.c | 78 +-
> drivers/pci/Kconfig | 2 +
> drivers/pci/Makefile | 3 +
> drivers/pci/host/Kconfig | 8 +
> drivers/pci/host/Makefile | 1 +
> drivers/pci/host/pci-tegra.c | 1322 ++++++++++++++++++++
> include/linux/io.h | 12 +
> include/linux/of_address.h | 9 +
> include/linux/of_pci.h | 3 +
> lib/ioremap.c | 266 ++++
> 31 files changed, 2203 insertions(+), 1043 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
> delete mode 100644 arch/arm/mach-tegra/board-harmony-pcie.c
> create mode 100644 arch/arm/mach-tegra/include/mach/pmc.h
> delete mode 100644 arch/arm/mach-tegra/pcie.c
> delete mode 100644 arch/arm/mach-tegra/pmc.h
> create mode 100644 drivers/pci/host/Kconfig
> create mode 100644 drivers/pci/host/Makefile
> create mode 100644 drivers/pci/host/pci-tegra.c
Hi Thierry,
Since the bulk of this series affects ARM, I'm assuming this will be
merged via the ARM tree or at least some non-PCI route. It looks like
[10/14] is the only one that touches drivers/pci, and since it's only
adding new stuff (the rewrite of the Tegra PCIe driver, if I
understand correctly), that's fine with me.
There have been enough comments that I assume you'll be posting an
updated series soon. I'll watch for it and review and ack the
drivers/pci parts. Let me know if you want me to do anything else.
Bjorn
^ permalink raw reply
* [PATCH] cpufreq: instantiate cpufreq-cpu0 as a platform_driver
From: Nishanth Menon @ 2013-01-28 18:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130128083159.GD31689@S2101-09.ap.freescale.net>
On 16:32-20130128, Shawn Guo wrote:
> On Sat, Jan 26, 2013 at 11:21:27PM +0100, Rafael J. Wysocki wrote:
> > On Saturday, January 26, 2013 09:55:50 PM Shawn Guo wrote:
> > > As multiplatform build is being adopted by more and more ARM platforms,
> > > initcall function should be used very carefully. For example, when
> > > GENERIC_CPUFREQ_CPU0 is built in the kernel, cpu0_cpufreq_driver_init()
> > > will be called on all the platforms to initialize cpufreq-cpu0 driver.
> > >
> > > To eliminate this undesired the effect, the patch changes cpufreq-cpu0
> > > driver to have it instantiated as a platform_driver. Then it will only
> > > run on platforms that create the platform_device "cpufreq-cpu0".
> > >
> > > Along with the change, it also changes cpu_dev to be &pdev->dev,
> > > so that managed functions can start working, and module build gets
> > > supported too.
> > >
> > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> > > ---
> > > Rafael,
> > >
> > > The patch depends patch "power: export opp cpufreq functions".
> > > https://patchwork.kernel.org/patch/1847261/
> >
> > That one should use EXPORT_SYMBOL_GPL() for exporting symbols, though.
> >
> When commit 80126ce (PM / OPP: Export symbols for module usage.)
> already exported a few symbols with EXPORT_SYMBOL()?
I have split this out as a separate OPP series with a variant of
https://patchwork.kernel.org/patch/1847261/ added at last.
Will post this out in a few mins.
--
Regards,
Nishanth Menon
^ permalink raw reply
* [PATCH v2 1/2] ARM: kirkwood: Ensure that kirkwood_ge0[01]_init() finds its clock
From: Jason Gunthorpe @ 2013-01-28 18:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <510506F9.3070500@gmail.com>
On Sun, Jan 27, 2013 at 11:52:41AM +0100, Sebastian Hesselbarth wrote:
> I agree that loosing the MAC address _is_ an issue but there must
> be another way to retain it during gated ge clocks than not gate the
> clocks at all.
>
> I can think of some ways to retain it but don't know what is the most
> common with linux:
> - make u-boot pass it through cmdline and let mv643xx get it from there
> - have kirkwood's common code grab it before clk gates kick in
The cannonical solution here is to have a DT attribute
'local-mac-address' that is filled in by the bootloader rather than
attempting to pass the mac address to the kernel through the ethernet
controller registers.
Until the bootloaders are fixed a reasonable hack is to have the
platform startup code look for an all-zeros local-mac-address in the
DT and if found then copy the MAC from the ethernet registers into the
DT. Then the ethernet driver can safely be a module since the MAC is
captured in the DT.
I've been using this patch here on top of the original Ian Molton
patch.
Jason: Can you include something like this as well?
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index 7048d7c..2b2cfcb 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2891,6 +2891,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
struct mv643xx_eth_private *mp;
struct net_device *dev;
struct resource *res;
+ const u8 *mac;
+ int len;
int err;
if (pdev->dev.of_node) {
@@ -2912,6 +2914,10 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
else
pd->phy_addr = MV643XX_ETH_PHY_ADDR_DEFAULT;
+ mac = of_get_property(pdev->dev.of_node, "local-mac-address", &len);
+ if (mac && len == 6)
+ memcpy(pd->mac_addr, mac, sizeof pd->mac_addr);
+
np = of_parse_phandle(pdev->dev.of_node, "mdio", 0);
if (np) {
pd->shared = of_find_device_by_node(np);
--
1.7.5.4
^ permalink raw reply related
* [RFC V2 PATCH 0/8] ARM: kirkwood: cleanup DT conversion
From: Thomas Petazzoni @ 2013-01-28 18:24 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130128180716.GA9436@obsidianresearch.com>
Dear Jason Gunthorpe,
On Mon, 28 Jan 2013 11:07:16 -0700, Jason Gunthorpe wrote:
> > 2. Also, If we use "ranges" property. How would that work?
> > By reading the property in the addr-map driver or
> > by somehow improving on of_bus to include this new kind of busses?
>
> The addr-map driver would have to read it, I believe the rules of how
> busses work make this fairly simple:
>
> 1) very early on the addr-map driver would have to scan the OF tree,
> find the address of the mbus mapping registers, and the internal
> register map.
> 2) Verify the mbus window for the internal registers matches the DT
> This is just a sanity check, if the correct value doesn't come back
> then the DT doesnt match what the bootloader setup, and some
> jtag accessible diagnostic can be printed...
> 3) Wipe all the mbus windows
> 4) Register a "marvell,orion-mbus" bus handler somehow
> 5) When OF processes the DT it would call the bus handler for each
> "marvell,orion-mbus" which should parse the ranges, allocate
> a free window, program that window then instantiate the child
> devices.
I am not totally convinced that we want to describe the address
decoding windows in the DT, because it is too static. For example, the
number, size and location of address decoding windows for PCIe
interfaces vary depending on the PCIe devices connected in those PCIe
interfaces. So we clearly do not want to have address decoding windows
fixed in stone in the Device Tree, in my opinion.
Instead, I think the "address decoding window driver" in the kernel
should provide an API for device drivers to request an address decoding
window at a given address, with a given size and target/attribute. This
is already what the PCIe code is doing (I'm going to submit v2 of the
PCIe code soon), and I think we should to the same for other devices as
well.
Best regards,
Thomas
--
Thomas Petazzoni, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: tegra: fix compile error when disable CPU_IDLE
From: Stephen Warren @ 2013-01-28 18:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359095912-32455-1-git-send-email-josephl@nvidia.com>
On 01/24/2013 11:38 PM, Joseph Lo wrote:
> The "sleep.S" file has many functions that be shared by different module
> currently. Not just for CPU idle driver. Make it build as default now.
I've applied this to Tegra's for-3.9/cleanup branch.
^ permalink raw reply
* [PATCH v2 1/2] ARM: kirkwood: Ensure that kirkwood_ge0[01]_init() finds its clock
From: Jason Gunthorpe @ 2013-01-28 18:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <51053F81.6020904@gmail.com>
On Sun, Jan 27, 2013 at 03:53:53PM +0100, Sebastian Hesselbarth wrote:
> I just want Simon to confirm that Kirkwood's gbe is really loosing the
> contents of its MAC address registers during gated clocks, which is from
> a HW point of view very unlikely.
FWIW, there are two block power management controls on the kirkwood
chips, one is documented to a clock gate, and one is documented to a
be a power down. I wouldn't expect the clock gate to have a problem
with the MAC address, but the powerdown I would expect to wipe it..
Other varients might have only the powerdown..
That said, I'm not sure what Linux uses on Kirkwood, it ideally should
be using both, I think.
Jason
^ permalink raw reply
* [RFC V2 PATCH 0/8] ARM: kirkwood: cleanup DT conversion
From: Ezequiel Garcia @ 2013-01-28 18:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130128192445.6984e7dd@skate>
Hi Thomas,
On Mon, Jan 28, 2013 at 3:24 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:
>
> Instead, I think the "address decoding window driver" in the kernel
> should provide an API for device drivers to request an address decoding
> window at a given address, with a given size and target/attribute. This
> is already what the PCIe code is doing (I'm going to submit v2 of the
> PCIe code soon), and I think we should to the same for other devices as
> well.
>
Note that in Jason's proposal, it's possible to instantiate a bus' child
device, configure its address window and then call the corresponding
driver using a regular of_node.
For instance,
// MBUS Decoder window for NAND
nand at f4000000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus", "marvell,orion-mbus";
mbus-target = <0x01 0x2f>;
ranges = <0 0xf4000000 0x10000>;
nand at 0 {
// ...
compatible = "marvell,orion-nand";
reg = <0x0 0x400>;
};
};
In this example, we can configure the window using both mbus-target and ranges
properties and then use the child node to instantiate an "orion-nand" device.
I understand your point regarding PCIe flexibility needs.
So I wonder, in your proposed scheme,
who should call this "address decoding window" driver
in order to still be able to instantiate child devices easily?
Thanks,
--
Ezequiel
^ permalink raw reply
* [RFC V2 PATCH 0/8] ARM: kirkwood: cleanup DT conversion
From: Jason Gunthorpe @ 2013-01-28 18:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130128192445.6984e7dd@skate>
On Mon, Jan 28, 2013 at 07:24:45PM +0100, Thomas Petazzoni wrote:
> > 1) very early on the addr-map driver would have to scan the OF tree,
> > find the address of the mbus mapping registers, and the internal
> > register map.
> > 2) Verify the mbus window for the internal registers matches the DT
> > This is just a sanity check, if the correct value doesn't come back
> > then the DT doesnt match what the bootloader setup, and some
> > jtag accessible diagnostic can be printed...
> > 3) Wipe all the mbus windows
> > 4) Register a "marvell,orion-mbus" bus handler somehow
> > 5) When OF processes the DT it would call the bus handler for each
> > "marvell,orion-mbus" which should parse the ranges, allocate
> > a free window, program that window then instantiate the child
> > devices.
[..]
> Instead, I think the "address decoding window driver" in the kernel
> should provide an API for device drivers to request an address decoding
> window at a given address, with a given size and target/attribute. This
> is already what the PCIe code is doing (I'm going to submit v2 of the
> PCIe code soon), and I think we should to the same for other devices as
> well.
Sure, but that isn't exclusive with setting up the bulk of the windows
through DT - the tegra PCI-E driver can use a request API for its
dynamic windows, while everyone else can be setup by having the DT bus
declarations automatically request the proper windows.
All this would do is replace the tables of window configurations in
the board files with a DT representation of the same table.
Jason
^ permalink raw reply
* [PATCH v2] PCIe support for the Armada 370 and Armada XP SoCs
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This series of patches introduces PCIe support for the Marvell Armada
370 and Armada XP. This "PATCH v2" follows the "RFC v1" that has been
sent on December, 7th. If possible, I'd like this patch series to be
considered 3.9 material, so reviews and comments are highly
appreciated in order to converge towards something that can be merged.
Since the previous version, the main changes are:
* We now use the standard PCI Device Tree bindings, both for
describing memory ranges, and interrupts.
* We now use an emulated PCI host bridge and emulated PCI-to-PCI
bridges to link together the PCIe interfaces of the SoC. This also
has the added benefit that the allocation of memory and I/O
addresses is now done by the PCI core, which avoids oversizing
address decoding windows and removes a specific PCI address
allocator that was present in the v1.
* The driver is now located in drivers/pci/host.
On the Armada XP evaluation board that has 6 usable PCIe slots, one
Intel e1000e PCIe card connected in slot 3 and one Marvell SATA PCIe
card connected in slot 4, the lspci -t output is:
-[0000:00]-+-00.0
+-01.0-[01]--
+-02.0-[02]--
+-03.0-[03]----00.0
+-04.0-[04]----00.0
+-05.0-[09]--
\-06.0-[0a]--
With lspci showing:
00:00.0 Host bridge: Marvell Technology Group Ltd. Device 102d
00:01.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
00:02.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
00:03.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
00:04.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
00:05.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
00:06.0 PCI bridge: Marvell Technology Group Ltd. Device 1092
03:00.0 Ethernet controller: Intel Corporation 82572EI Gigabit Ethernet Controller (Copper) (rev 06)
04:00.0 SCSI storage controller: Marvell Technology Group Ltd. 88SX7042 PCI-e 4-port SATA-II (rev 02)
Please see at the end of this e-mail the entire output of lspci -vvv.
A quick description of the patches:
* Patches 1 to 3 add PCI-related Device Tree parsing functions. Those
patches are common with the Nvidia Tegra PCIe patch set from
Thierry Redding. They are included in this series so that it can be
tested easily.
* Patch 4 extends the ARM PCI core to store a per-controller private
data pointer. This patch is common with the Nvidia Tegra PCIe patch
set from Thierry Redding. It is included in this series so that it
can be tested easily.
* Patch 5 extends the ARM PCI core with an additional hook that a PCI
controller driver can register and get called to realign PCI
ressource addresses. This is needed for the support of Marvell PCIe
interfaces because the address decoding windows for I/O ranges have
a granularity of 64 KB, while the PCI standard requires only a 4 KB
alignement. See the patch itself for details.
* Patch 6 fixes a problem in lib/devres.c that prevents certain
PCI-related functions from being visible on NO_IOPORT platforms. I
know this patch isn't acceptable by itself, but the discussion
about this has been so huge and went in so many directions that in
the end, I don't know what is the correct way of fixing this. If an
agreement is found on how to fix this properly, I'm willing to work
on it if needed.
* Patch 7 and 8 respectively add a minimal emulated PCI host bridge
and emulated PCI-to-PCI bridge. The former has originally been
written by Thierry Redding. Even though I made a few minor changes
to it, I kept Thierry's authorship on it (Thierry do not hesitate
to let me know if my changes are too substantial to keep your name
on this code). The latter was largely inspired by Thierry's code.
* Patch 9 creates the drivers/pci/host directory and makes the
related minimal changes to Kconfig/Makefile. This patch will
trivially conflict with the NVidia Tegra PCIe support posted by
Thierry Redding, which also creates the drivers/pci/host directory.
* Patch 10 fixes a mistake in the interrupt controller node of the
Armada 370/XP Device Tree, which was invisible until we started
using the of_irq_map_raw() function, needed in our PCIe support.
* Patch 11 and 12 fixes some issues in the Armada 370/XP clock gating
driver, related to PCIe interfaces.
* Patch 13 and 14 are cleanup/refactoring of the common plat-orion
address decoding code, in preparation for further changes related
to PCIe.
* Patch 15 introduces in the common plat-orion address decoding code
functions to allocate/free an address decoding window. Until now,
the address decoding windows were configured statically. With
Armada XP having up to 10 PCIe interfaces, we don't want to
allocate useless address decoding windows statically, so we move to
a more dynamic model in which address decoding windows are
configured only for the PCIe interfaces that are actually in use.
* Patch 16 improves the Armada 370/XP specific address decoding code
to provide functions that add and remove an address decoding window
for a given PCIe interface. It relies on the common functions added
in patch 15.
* Patch 17 makes the common plat-orion PCIe code available on
PLAT_ORION platforms such as ARCH_MVEBU.
* Patch 18 adds some variants of the PCI configuration space
read/write functions that were available in the plat-orion/pcie.c
code. Those variants are needed due to the usage of the emulated
host-bridge + emulated PCI-to-PCI bridge model.
* Patch 19 contains the Armada 370/XP PCIe driver itself, that
implements the necessary operations required by the ARM PCI core,
and configures the address decoding windows as needed. This driver
relies on a Device Tree description of the PCIe interfaces.
* Patch 20 marks the ARCH_MVEBU platform has having PCI available,
which allows the compilation of the PCIe support.
* Patches 21 and 22 add the SoC-level Device Tree informations
related to PCIe for Armada 370 and Armada XP.
* Patch 23, 24, 25 and 26 add the board-level Device Tree
informations related to PCIe for the Armada XP DB, Armada 370 DB,
PlatHome OpenBlocks AX3-4 and GlobalScale Mirabox boards.
* Patch 27 updates mvebu_defconfig with PCI and USB support.
This patch set applies on top of v3.8-rc5, and has been pushed
at:
git://github.com/MISL-EBU-System-SW/mainline-public.git marvell-pcie-v2
Thanks,
Thomas
---
Output of lspci -vvv:
# /usr/sbin/lspci -vvv
00:00.0 Host bridge: Marvell Technology Group Ltd. Device 102d
Control: I/O- Mem- BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Interrupt: pin ? routed to IRQ 0
Capabilities: [fc] <chain broken>
00:01.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: fff00000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
00:02.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=02, subordinate=02, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: fff00000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
00:03.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=03, subordinate=03, sec-latency=0
I/O behind bridge: c0000000-c0000fff
Memory behind bridge: c1000000-c10fffff
Prefetchable memory behind bridge: c1100000-c11fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
00:04.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=04, subordinate=04, sec-latency=0
I/O behind bridge: c0010000-c0010fff
Memory behind bridge: c1200000-c12fffff
Prefetchable memory behind bridge: c1300000-c13fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
00:05.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=09, subordinate=09, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: fff00000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
00:06.0 PCI bridge: Marvell Technology Group Ltd. Device 1092 (prog-if 00 [Normal decode])
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz+ UDF+ FastB2B+ ParErr+ DEVSEL=?? >TAbort+ <TAbort+ <MAbort+ >SERR+ <PERR+ INTx+
Latency: 0, Cache Line Size: 64 bytes
Bus: primary=00, secondary=0a, subordinate=0a, sec-latency=0
I/O behind bridge: 0000f000-00000fff
Memory behind bridge: fff00000-000fffff
Prefetchable memory behind bridge: fff00000-000fffff
Secondary status: 66MHz- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- <SERR- <PERR-
BridgeCtl: Parity+ SERR+ NoISA+ VGA+ MAbort+ >Reset+ FastB2B+
PriDiscTmr+ SecDiscTmr+ DiscTmrStat+ DiscTmrSERREn+
Capabilities: [fc] <chain broken>
03:00.0 Ethernet controller: Intel Corporation 82572EI Gigabit Ethernet Controller (Copper) (rev 06)
Subsystem: Intel Corporation PRO/1000 PT Server Adapter
Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 105
Region 0: Memory at c1000000 (32-bit, non-prefetchable) [size=128K]
Region 1: Memory at c1020000 (32-bit, non-prefetchable) [size=128K]
Region 2: I/O ports at c0000000 [disabled] [size=32]
[virtual] Expansion ROM@c1100000 [disabled] [size=128K]
Capabilities: [c8] Power Management version 2
Flags: PMEClk- DSI+ D1- D2- AuxCurrent=0mA PME(D0+,D1-,D2-,D3hot+,D3cold+)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=1 PME-
Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000000000000 Data: 0000
Capabilities: [e0] Express (v1) Endpoint, MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <512ns, L1 <64us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd+ ExtTag- PhantFunc- AuxPwr- NoSnoop+
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr+ TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x1, ASPM L0s, Latency L0 <4us, L1 <64us
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 64 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES- TLP- FCP+ CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
Capabilities: [140 v1] Device Serial Number 00-1b-21-ff-ff-c1-c4-fe
Kernel driver in use: e1000e
04:00.0 SCSI storage controller: Marvell Technology Group Ltd. 88SX7042 PCI-e 4-port SATA-II (rev 02)
Subsystem: Marvell Technology Group Ltd. Device 11ab
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
Latency: 0, Cache Line Size: 64 bytes
Interrupt: pin A routed to IRQ 106
Region 0: Memory at c1200000 (64-bit, non-prefetchable) [size=1M]
Region 2: I/O ports at c0010000 [size=256]
[virtual] Expansion ROM@c1300000 [disabled] [size=512K]
Capabilities: [40] Power Management version 2
Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
Address: 0000000012345678 Data: 0000
Capabilities: [60] Express (v1) Legacy Endpoint, MSI 00
DevCap: MaxPayload 256 bytes, PhantFunc 0, Latency L0s <256ns, L1 <1us
ExtTag- AttnBtn- AttnInd- PwrInd- RBE- FLReset-
DevCtl: Report errors: Correctable- Non-Fatal- Fatal- Unsupported-
RlxdOrd- ExtTag- PhantFunc- AuxPwr- NoSnoop-
MaxPayload 128 bytes, MaxReadReq 512 bytes
DevSta: CorrErr- UncorrErr- FatalErr- UnsuppReq- AuxPwr- TransPend-
LnkCap: Port #0, Speed 2.5GT/s, Width x4, ASPM L0s, Latency L0 <256ns, L1 unlimited
ClockPM- Surprise- LLActRep- BwNot-
LnkCtl: ASPM Disabled; RCB 128 bytes Disabled- Retrain- CommClk-
ExtSynch- ClockPM- AutWidDis- BWInt- AutBWInt-
LnkSta: Speed 2.5GT/s, Width x1, TrErr- Train- SlotClk+ DLActive- BWMgmt- ABWMgmt-
Capabilities: [100 v1] Advanced Error Reporting
UESta: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UEMsk: DLP- SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF- MalfTLP- ECRC- UnsupReq- ACSViol-
UESvrt: DLP+ SDES- TLP- FCP- CmpltTO- CmpltAbrt- UnxCmplt- RxOF+ MalfTLP+ ECRC- UnsupReq- ACSViol-
CESta: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
CEMsk: RxErr- BadTLP- BadDLLP- Rollover- Timeout- NonFatalErr-
AERCap: First Error Pointer: 00, GenCap- CGenEn- ChkCap- ChkEn-
Kernel driver in use: sata_mv
^ permalink raw reply
* [PATCH v2 01/27] of/pci: Provide support for parsing PCI DT ranges property
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
From: Andrew Murray <andrew.murray@arm.com>
DT bindings for PCI host bridges often use the ranges property to describe
memory and IO ranges - this binding tends to be the same across architectures
yet several parsing implementations exist, e.g. arch/mips/pci/pci.c,
arch/powerpc/kernel/pci-common.c, arch/sparc/kernel/pci.c and
arch/microblaze/pci/pci-common.c (clone of PPC). Some of these duplicate
functionality provided by drivers/of/address.c.
This patch provides a common iterator-based parser for the ranges property, it
is hoped this will reduce DT representation differences between architectures
and that architectures will migrate in part to this new parser.
It is also hoped (and the motativation for the patch) that this patch will
reduce duplication of code when writing host bridge drivers that are supported
by multiple architectures.
This patch provides struct resources from a device tree node, e.g.:
u32 *last = NULL;
struct resource res;
while ((last = of_pci_process_ranges(np, res, last))) {
//do something with res
}
Platforms with quirks can then do what they like with the resource or migrate
common quirk handling to the parser. In an ideal world drivers can just request
the obtained resources and pass them on (e.g. pci_add_resource_offset).
Signed-off-by: Andrew Murray <Andrew.Murray@arm.com>
Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/of/address.c | 63 ++++++++++++++++++++++++++++++++++++++++++++
include/linux/of_address.h | 9 +++++++
2 files changed, 72 insertions(+)
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 0125524..d659527 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -13,6 +13,7 @@
#define OF_CHECK_COUNTS(na, ns) (OF_CHECK_ADDR_COUNT(na) && (ns) > 0)
static struct of_bus *of_match_bus(struct device_node *np);
+static struct of_bus *of_find_bus(const char *name);
static int __of_address_to_resource(struct device_node *dev,
const __be32 *addrp, u64 size, unsigned int flags,
const char *name, struct resource *r);
@@ -227,6 +228,57 @@ int of_pci_address_to_resource(struct device_node *dev, int bar,
return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
}
EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
+
+const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res, const __be32 *from)
+{
+ const __be32 *start, *end;
+ int na, ns, np, pna;
+ int rlen;
+ struct of_bus *bus;
+
+ WARN_ON(!res);
+
+ bus = of_find_bus("pci");
+ bus->count_cells(node, &na, &ns);
+ if (!OF_CHECK_COUNTS(na, ns)) {
+ pr_err("Bad cell count for %s\n", node->full_name);
+ return NULL;
+ }
+
+ pna = of_n_addr_cells(node);
+ np = pna + na + ns;
+
+ start = of_get_property(node, "ranges", &rlen);
+ if (start == NULL)
+ return NULL;
+
+ end = start + rlen / sizeof(__be32);
+
+ if (!from)
+ from = start;
+
+ while (from + np <= end) {
+ u64 cpu_addr, size;
+
+ cpu_addr = of_translate_address(node, from + na);
+ size = of_read_number(from + na + pna, ns);
+ res->flags = bus->get_flags(from);
+ from += np;
+
+ if (cpu_addr == OF_BAD_ADDR || size == 0)
+ continue;
+
+ res->name = node->full_name;
+ res->start = cpu_addr;
+ res->end = res->start + size - 1;
+ res->parent = res->child = res->sibling = NULL;
+ return from;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(of_pci_process_ranges);
#endif /* CONFIG_PCI */
/*
@@ -337,6 +389,17 @@ static struct of_bus *of_match_bus(struct device_node *np)
return NULL;
}
+static struct of_bus *of_find_bus(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(of_busses); i++)
+ if (strcmp(name, of_busses[i].name) == 0)
+ return &of_busses[i];
+
+ return NULL;
+}
+
static int of_translate_one(struct device_node *parent, struct of_bus *bus,
struct of_bus *pbus, __be32 *addr,
int na, int ns, int pna, const char *rprop)
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 0506eb5..751e889 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -27,6 +27,8 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
#define pci_address_to_pio pci_address_to_pio
#endif
+const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res, const __be32 *from);
#else /* CONFIG_OF_ADDRESS */
#ifndef of_address_to_resource
static inline int of_address_to_resource(struct device_node *dev, int index,
@@ -53,6 +55,13 @@ static inline const __be32 *of_get_address(struct device_node *dev, int index,
{
return NULL;
}
+
+static inline const __be32 *of_pci_process_ranges(struct device_node *node,
+ struct resource *res,
+ const __be32 *from)
+{
+ return NULL;
+}
#endif /* CONFIG_OF_ADDRESS */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 02/27] of/pci: Add of_pci_get_devfn() function
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
From: Thierry Reding <thierry.reding@avionic-design.de>
This function can be used to parse the device and function number from a
standard 5-cell PCI resource. PCI_SLOT() and PCI_FUNC() can be used on
the returned value obtain the device and function numbers respectively.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/of/of_pci.c | 32 ++++++++++++++++++++++++++++----
include/linux/of_pci.h | 1 +
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 13e37e2..0dd52df 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -7,12 +7,13 @@
static inline int __of_pci_pci_compare(struct device_node *node,
unsigned int devfn)
{
- unsigned int size;
- const __be32 *reg = of_get_property(node, "reg", &size);
+ int err;
- if (!reg || size < 5 * sizeof(__be32))
+ err = of_pci_get_devfn(node);
+ if (err < 0)
return 0;
- return ((be32_to_cpup(®[0]) >> 8) & 0xff) == devfn;
+
+ return devfn == err;
}
struct device_node *of_pci_find_child_device(struct device_node *parent,
@@ -40,3 +41,26 @@ struct device_node *of_pci_find_child_device(struct device_node *parent,
return NULL;
}
EXPORT_SYMBOL_GPL(of_pci_find_child_device);
+
+/**
+ * of_pci_get_devfn() - Get device and function numbers for a device node
+ * @np: device node
+ *
+ * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
+ * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
+ * and function numbers respectively. On error a negative error code is
+ * returned.
+ */
+int of_pci_get_devfn(struct device_node *np)
+{
+ unsigned int size;
+ const __be32 *reg;
+
+ reg = of_get_property(np, "reg", &size);
+
+ if (!reg || size < 5 * sizeof(__be32))
+ return -EINVAL;
+
+ return (be32_to_cpup(reg) >> 8) & 0xff;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_devfn);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index bb115de..91ec484 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -10,5 +10,6 @@ int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
struct device_node;
struct device_node *of_pci_find_child_device(struct device_node *parent,
unsigned int devfn);
+int of_pci_get_devfn(struct device_node *np);
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 03/27] of/pci: Add of_pci_parse_bus_range() function
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
From: Thierry Reding <thierry.reding@avionic-design.de>
This function can be used to parse a bus-range property as specified by
device nodes representing PCI bridges.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/of/of_pci.c | 25 +++++++++++++++++++++++++
include/linux/of_pci.h | 1 +
2 files changed, 26 insertions(+)
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
index 0dd52df..3ea0e84 100644
--- a/drivers/of/of_pci.c
+++ b/drivers/of/of_pci.c
@@ -64,3 +64,28 @@ int of_pci_get_devfn(struct device_node *np)
return (be32_to_cpup(reg) >> 8) & 0xff;
}
EXPORT_SYMBOL_GPL(of_pci_get_devfn);
+
+/**
+ * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
+ * @node: device node
+ * @res: address to a struct resource to return the bus-range
+ *
+ * Returns 0 on success or a negative error-code on failure.
+ */
+int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
+{
+ const __be32 *values;
+ int len;
+
+ values = of_get_property(node, "bus-range", &len);
+ if (!values || len < sizeof(*values) * 2)
+ return -EINVAL;
+
+ res->name = node->name;
+ res->start = be32_to_cpup(values++);
+ res->end = be32_to_cpup(values);
+ res->flags = IORESOURCE_BUS;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
diff --git a/include/linux/of_pci.h b/include/linux/of_pci.h
index 91ec484..7a04826 100644
--- a/include/linux/of_pci.h
+++ b/include/linux/of_pci.h
@@ -11,5 +11,6 @@ struct device_node;
struct device_node *of_pci_find_child_device(struct device_node *parent,
unsigned int devfn);
int of_pci_get_devfn(struct device_node *np);
+int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
#endif
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 04/27] ARM: pci: Allow passing per-controller private data
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
From: Thierry Reding <thierry.reding@avionic-design.de>
In order to allow drivers to specify private data for each controller,
this commit adds a private_data field to the struct hw_pci. This field
is an array of nr_controllers pointers that will be used to initialize
the private_data field of the corresponding controller's pci_sys_data
structure.
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
---
arch/arm/include/asm/mach/pci.h | 1 +
arch/arm/kernel/bios32.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index db9fedb..5cf2e97 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -23,6 +23,7 @@ struct hw_pci {
#endif
struct pci_ops *ops;
int nr_controllers;
+ void **private_data;
int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
void (*preinit)(void);
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 379cf32..5401645 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -464,6 +464,9 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
sys->map_irq = hw->map_irq;
INIT_LIST_HEAD(&sys->resources);
+ if (hw->private_data)
+ sys->private_data = hw->private_data[nr];
+
ret = hw->setup(nr, sys);
if (ret > 0) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 05/27] arm: pci: add a align_resource hook
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
The PCI specifications says that an I/O region must be aligned on a 4
KB boundary, and a memory region aligned on a 1 MB boundary.
However, the Marvell PCIe interfaces rely on address decoding windows
(which allow to associate a range of physical addresses with a given
device). For PCIe memory windows, those windows are defined with a 1
MB granularity (which matches the PCI specs), but PCIe I/O windows can
only be defined with a 64 KB granularity, so they have to be 64 KB
aligned. We therefore need to tell the PCI core about this special
alignement requirement.
The PCI core already calls pcibios_align_resource() in the ARM PCI
core, specifically for such purposes. So this patch extends the ARM
PCI core so that it calls a ->align_resource() hook registered by the
PCI driver, exactly like the existing ->map_irq() and ->swizzle()
hooks.
A particular PCI driver can register a align_resource() hook, and do
its own specific alignement, depending on the specific constraints of
the underlying hardware.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Russell King <linux@arm.linux.org.uk>
---
arch/arm/include/asm/mach/pci.h | 11 +++++++++++
arch/arm/kernel/bios32.c | 6 ++++++
2 files changed, 17 insertions(+)
diff --git a/arch/arm/include/asm/mach/pci.h b/arch/arm/include/asm/mach/pci.h
index 5cf2e97..7d2c3c8 100644
--- a/arch/arm/include/asm/mach/pci.h
+++ b/arch/arm/include/asm/mach/pci.h
@@ -30,6 +30,11 @@ struct hw_pci {
void (*postinit)(void);
u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
int (*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+ resource_size_t (*align_resource)(struct pci_dev *dev,
+ const struct resource *res,
+ resource_size_t start,
+ resource_size_t size,
+ resource_size_t align);
};
/*
@@ -51,6 +56,12 @@ struct pci_sys_data {
u8 (*swizzle)(struct pci_dev *, u8 *);
/* IRQ mapping */
int (*map_irq)(const struct pci_dev *, u8, u8);
+ /* Resource alignement requirements */
+ resource_size_t (*align_resource)(struct pci_dev *dev,
+ const struct resource *res,
+ resource_size_t start,
+ resource_size_t size,
+ resource_size_t align);
void *private_data; /* platform controller private data */
};
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 5401645..be2e6c9 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -462,6 +462,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
sys->busnr = busnr;
sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq;
+ sys->align_resource = hw->align_resource;
INIT_LIST_HEAD(&sys->resources);
if (hw->private_data)
@@ -574,6 +575,8 @@ char * __init pcibios_setup(char *str)
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
+ struct pci_dev *dev = data;
+ struct pci_sys_data *sys = dev->sysdata;
resource_size_t start = res->start;
if (res->flags & IORESOURCE_IO && start & 0x300)
@@ -581,6 +584,9 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
start = (start + align - 1) & ~(align - 1);
+ if (sys->align_resource)
+ return sys->align_resource(dev, res, start, size, align);
+
return start;
}
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 06/27] lib: devres: don't enclose pcim_*() functions in CONFIG_HAS_IOPORT
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
The pcim_*() functions are used by the libata-sff subsystem, and this
subsystem is used for many SATA drivers on ARM platforms that do not
necessarily have I/O ports.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: linux-kernel at vger.kernel.org
---
lib/devres.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/devres.c b/lib/devres.c
index 80b9c76..5639c3e 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -195,6 +195,7 @@ void devm_ioport_unmap(struct device *dev, void __iomem *addr)
devm_ioport_map_match, (void *)addr));
}
EXPORT_SYMBOL(devm_ioport_unmap);
+#endif /* CONFIG_HAS_IOPORT */
#ifdef CONFIG_PCI
/*
@@ -400,4 +401,3 @@ void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
}
EXPORT_SYMBOL(pcim_iounmap_regions);
#endif /* CONFIG_PCI */
-#endif /* CONFIG_HAS_IOPORT */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 07/27] PCI: Add software-emulated host bridge
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
From: Thierry Reding <thierry.reding@avionic-design.de>
[Thomas Petazzoni:
- Simplify capabilities handling.
- Move to a separate file.
- Fix mask used when writing a 4 bytes value.]
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/pci/Kconfig | 3 +
drivers/pci/Makefile | 3 +
drivers/pci/sw-host-bridge.c | 144 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 23 +++++++
4 files changed, 173 insertions(+)
create mode 100644 drivers/pci/sw-host-bridge.c
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 6d51aa6..f7548e2 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -119,3 +119,6 @@ config PCI_IOAPIC
config PCI_LABEL
def_bool y if (DMI || ACPI)
select NLS
+
+config PCI_SW_HOST_BRIDGE
+ bool
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 0c3efcf..44ce914 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -15,6 +15,9 @@ obj-$(CONFIG_PCIEPORTBUS) += pcie/
obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
+# Emulated PCI elements
+obj-$(CONFIG_PCI_SW_HOST_BRIDGE) += sw-host-bridge.o
+
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
ifdef CONFIG_HOTPLUG_PCI
diff --git a/drivers/pci/sw-host-bridge.c b/drivers/pci/sw-host-bridge.c
new file mode 100644
index 0000000..b5a2aed
--- /dev/null
+++ b/drivers/pci/sw-host-bridge.c
@@ -0,0 +1,144 @@
+/*
+ * Implementation of a simple emulated PCI host bridge.
+ *
+ * Thierry Reding <thierry.reding@avionic-design.de>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+int pci_sw_host_bridge_init(struct pci_sw_host_bridge *bridge)
+{
+ unsigned int i;
+
+ if (!bridge)
+ return -EINVAL;
+
+ bridge->vendor = 0x0000;
+ bridge->device = 0x0000;
+
+ bridge->command = 0x0000;
+ bridge->status = PCI_STATUS_CAP_LIST;
+
+ bridge->class = PCI_CLASS_BRIDGE_HOST;
+ bridge->interface = 0x00;
+ bridge->revision = 0x00;
+
+ bridge->bist = 0x00;
+ bridge->header_type = PCI_HEADER_TYPE_NORMAL;
+ bridge->latency_timer = 0x00;
+ bridge->cache_line_size = 0x10;
+
+ for (i = 0; i < 6; i++)
+ bridge->bar[i] = 0x00000000;
+
+ bridge->subsystem_vendor = 0x0000;
+ bridge->subsystem_device = 0x0000;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_sw_host_bridge_init);
+
+int pci_sw_host_bridge_read(struct pci_sw_host_bridge *bridge,
+ unsigned int where, int size, u32 *value)
+{
+ switch (where & ~3) {
+ case PCI_VENDOR_ID:
+ *value = bridge->device << 16 | bridge->vendor;
+ break;
+
+ case PCI_COMMAND:
+ *value = bridge->status << 16 | bridge->command;
+ break;
+
+ case PCI_STATUS:
+ *value = 0;
+ break;
+
+ case PCI_CLASS_REVISION:
+ *value = bridge->class << 16 | bridge->interface << 8 |
+ bridge->revision;
+ break;
+
+ case PCI_CACHE_LINE_SIZE:
+ *value = bridge->bist << 24 | bridge->header_type << 16 |
+ bridge->latency_timer << 8 | bridge->cache_line_size;
+ break;
+
+ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
+ *value = bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4];
+ break;
+
+ case PCI_CARDBUS_CIS:
+ *value = 0;
+ break;
+
+ case PCI_SUBSYSTEM_VENDOR_ID:
+ *value = bridge->subsystem_device << 16 |
+ bridge->subsystem_vendor;
+ break;
+
+ case PCI_ROM_ADDRESS:
+ *value = 0;
+ break;
+
+ case PCI_INTERRUPT_LINE:
+ break;
+
+ default:
+ *value = 0xffffffff;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ if (size == 2)
+ *value = (*value >> (8 * (where & 3))) & 0xffff;
+ else if (size == 1)
+ *value = (*value >> (8 * (where & 3))) & 0xff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_sw_host_bridge_read);
+
+int pci_sw_host_bridge_write(struct pci_sw_host_bridge *bridge,
+ unsigned int where, int size, u32 value)
+{
+ u32 mask, reg;
+ int err;
+
+ if (size == 4)
+ mask = 0x0;
+ else if (size == 2)
+ mask = ~(0xffff << ((where & 3) * 8));
+ else if (size == 1)
+ mask = ~(0xff << ((where & 3) * 8));
+ else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ err = pci_sw_host_bridge_read(bridge, where & ~3, 4, ®);
+ if (err)
+ return err;
+
+ value = (reg & mask) | value << ((where & 3) * 8);
+
+ switch (where & ~3) {
+ case PCI_COMMAND:
+ bridge->command = value & 0xffff;
+ bridge->status = value >> 16;
+ break;
+
+ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
+ bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_sw_host_bridge_write);
+
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 15472d6..c93e258 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1841,4 +1841,27 @@ 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_sw_host_bridge {
+ u16 vendor;
+ u16 device;
+ u16 command;
+ u16 status;
+ u16 class;
+ u8 interface;
+ u8 revision;
+ u8 bist;
+ u8 header_type;
+ u8 latency_timer;
+ u8 cache_line_size;
+ u32 bar[6];
+ u16 subsystem_vendor;
+ u16 subsystem_device;
+};
+
+extern int pci_sw_host_bridge_init(struct pci_sw_host_bridge *bridge);
+extern int pci_sw_host_bridge_read(struct pci_sw_host_bridge *bridge,
+ unsigned int where, int size, u32 *value);
+extern int pci_sw_host_bridge_write(struct pci_sw_host_bridge *bridge,
+ unsigned int where, int size, u32 value);
+
#endif /* LINUX_PCI_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 08/27] pci: implement an emulated PCI-to-PCI bridge
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/pci/Kconfig | 3 +
drivers/pci/Makefile | 1 +
drivers/pci/sw-pci-pci-bridge.c | 185 +++++++++++++++++++++++++++++++++++++++
include/linux/pci.h | 43 +++++++++
4 files changed, 232 insertions(+)
create mode 100644 drivers/pci/sw-pci-pci-bridge.c
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index f7548e2..6ed3db1 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -122,3 +122,6 @@ config PCI_LABEL
config PCI_SW_HOST_BRIDGE
bool
+
+config PCI_SW_PCI_PCI_BRIDGE
+ bool
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 44ce914..5b48961 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
# Emulated PCI elements
obj-$(CONFIG_PCI_SW_HOST_BRIDGE) += sw-host-bridge.o
+obj-$(CONFIG_PCI_SW_PCI_PCI_BRIDGE) += sw-pci-pci-bridge.o
# Build the PCI Hotplug drivers if we were asked to
obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
diff --git a/drivers/pci/sw-pci-pci-bridge.c b/drivers/pci/sw-pci-pci-bridge.c
new file mode 100644
index 0000000..25679cc
--- /dev/null
+++ b/drivers/pci/sw-pci-pci-bridge.c
@@ -0,0 +1,185 @@
+/*
+ * Implementation of a simple emulated PCI-to-PCI bridge.
+ *
+ * Thierry Reding <thierry.reding@avionic-design.de>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+
+int pci_sw_pci_bridge_init(struct pci_sw_pci_bridge *bridge)
+{
+ if (!bridge)
+ return -EINVAL;
+
+ memset(bridge, 0, sizeof(struct pci_sw_pci_bridge));
+
+ bridge->status = PCI_STATUS_CAP_LIST;
+ bridge->class = PCI_CLASS_BRIDGE_PCI;
+ bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
+ bridge->cache_line_size = 0x10;
+
+ /* We support 32 bits I/O addressing */
+ bridge->iobase = PCI_IO_RANGE_TYPE_32;
+ bridge->iolimit = PCI_IO_RANGE_TYPE_32;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_sw_pci_bridge_init);
+
+int pci_sw_pci_bridge_read(struct pci_sw_pci_bridge *bridge,
+ unsigned int where, int size, u32 *value)
+{
+ switch (where & ~3) {
+ case PCI_VENDOR_ID:
+ *value = bridge->device << 16 | bridge->vendor;
+ break;
+
+ case PCI_COMMAND:
+ *value = bridge->status << 16 | bridge->command;
+ break;
+
+ case PCI_CLASS_REVISION:
+ *value = bridge->class << 16 | bridge->interface << 8 |
+ bridge->revision;
+ break;
+
+ case PCI_CACHE_LINE_SIZE:
+ *value = bridge->bist << 24 | bridge->header_type << 16 |
+ bridge->latency_timer << 8 | bridge->cache_line_size;
+ break;
+
+ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
+ *value = bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4];
+ break;
+
+ case PCI_PRIMARY_BUS:
+ *value = (bridge->secondary_latency_timer << 24 |
+ bridge->subordinate_bus << 16 |
+ bridge->secondary_bus << 8 |
+ bridge->primary_bus);
+ break;
+
+ case PCI_IO_BASE:
+ *value = (bridge->secondary_status << 16 |
+ bridge->iolimit << 8 |
+ bridge->iobase);
+ break;
+
+ case PCI_MEMORY_BASE:
+ *value = (bridge->memlimit << 16 | bridge->membase);
+ break;
+
+ case PCI_PREF_MEMORY_BASE:
+ *value = (bridge->prefmemlimit << 16 | bridge->prefmembase);
+ break;
+
+ case PCI_PREF_BASE_UPPER32:
+ *value = bridge->prefbaseupper;
+ break;
+
+ case PCI_PREF_LIMIT_UPPER32:
+ *value = bridge->preflimitupper;
+ break;
+
+ case PCI_IO_BASE_UPPER16:
+ *value = (bridge->iolimitupper << 16 | bridge->iobaseupper);
+ break;
+
+ case PCI_ROM_ADDRESS1:
+ *value = 0;
+ break;
+
+ default:
+ *value = 0xffffffff;
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ if (size == 2)
+ *value = (*value >> (8 * (where & 3))) & 0xffff;
+ else if (size == 1)
+ *value = (*value >> (8 * (where & 3))) & 0xff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_sw_pci_bridge_read);
+
+int pci_sw_pci_bridge_write(struct pci_sw_pci_bridge *bridge,
+ unsigned int where, int size, u32 value)
+{
+ u32 mask, reg;
+ int err;
+
+ if (size == 4)
+ mask = 0x0;
+ else if (size == 2)
+ mask = ~(0xffff << ((where & 3) * 8));
+ else if (size == 1)
+ mask = ~(0xff << ((where & 3) * 8));
+ else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ err = pci_sw_pci_bridge_read(bridge, where & ~3, 4, ®);
+ if (err)
+ return err;
+
+ value = (reg & mask) | value << ((where & 3) * 8);
+
+ switch (where & ~3) {
+ case PCI_COMMAND:
+ bridge->command = value & 0xffff;
+ bridge->status = value >> 16;
+ break;
+
+ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
+ bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
+ break;
+
+ case PCI_IO_BASE:
+ /*
+ * We also keep bit 1 set, it is a read-only bit that
+ * indicates we support 32 bits addressing for the
+ * I/O
+ */
+ bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;
+ bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32;
+ bridge->secondary_status = value >> 16;
+ break;
+
+ case PCI_MEMORY_BASE:
+ bridge->membase = value & 0xffff;
+ bridge->memlimit = value >> 16;
+ break;
+
+ case PCI_PREF_MEMORY_BASE:
+ bridge->prefmembase = value & 0xffff;
+ bridge->prefmemlimit = value >> 16;
+ break;
+
+ case PCI_PREF_BASE_UPPER32:
+ bridge->prefbaseupper = value;
+ break;
+
+ case PCI_PREF_LIMIT_UPPER32:
+ bridge->preflimitupper = value;
+ break;
+
+ case PCI_IO_BASE_UPPER16:
+ bridge->iobaseupper = value & 0xffff;
+ bridge->iolimitupper = value >> 16;
+ break;
+
+ default:
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+EXPORT_SYMBOL_GPL(pci_sw_pci_bridge_write);
diff --git a/include/linux/pci.h b/include/linux/pci.h
index c93e258..b83b4c8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1864,4 +1864,47 @@ extern int pci_sw_host_bridge_read(struct pci_sw_host_bridge *bridge,
extern int pci_sw_host_bridge_write(struct pci_sw_host_bridge *bridge,
unsigned int where, int size, u32 value);
+struct pci_sw_pci_bridge {
+ u16 vendor;
+ u16 device;
+ u16 command;
+ u16 status;
+ u16 class;
+ u8 interface;
+ u8 revision;
+ u8 bist;
+ u8 header_type;
+ u8 latency_timer;
+ u8 cache_line_size;
+ u32 bar[2];
+ u8 primary_bus;
+ u8 secondary_bus;
+ u8 subordinate_bus;
+ u8 secondary_latency_timer;
+ u8 iobase;
+ u8 iolimit;
+ u16 secondary_status;
+ u16 membase;
+ u16 memlimit;
+ u16 prefmembase;
+ u16 prefmemlimit;
+ u32 prefbaseupper;
+ u32 preflimitupper;
+ u16 iobaseupper;
+ u16 iolimitupper;
+ u8 cappointer;
+ u8 reserved1;
+ u16 reserved2;
+ u32 romaddr;
+ u8 intline;
+ u8 intpin;
+ u16 bridgectrl;
+};
+
+extern int pci_sw_pci_bridge_init(struct pci_sw_pci_bridge *bridge);
+extern int pci_sw_pci_bridge_read(struct pci_sw_pci_bridge *bridge,
+ unsigned int where, int size, u32 *value);
+extern int pci_sw_pci_bridge_write(struct pci_sw_pci_bridge *bridge,
+ unsigned int where, int size, u32 value);
+
#endif /* LINUX_PCI_H */
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 09/27] pci: infrastructure to add drivers in drivers/pci/host
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
As agreed by the community, PCI host drivers will now be stored in
drivers/pci/host. This commit adds this directory and the related
Kconfig/Makefile changes to allow new drivers to be added in this
directory.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/pci/Kconfig | 2 ++
drivers/pci/Makefile | 3 +++
drivers/pci/host/Kconfig | 4 ++++
3 files changed, 9 insertions(+)
create mode 100644 drivers/pci/host/Kconfig
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 6ed3db1..45392ab 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -125,3 +125,5 @@ config PCI_SW_HOST_BRIDGE
config PCI_SW_PCI_PCI_BRIDGE
bool
+
+source "drivers/pci/host/Kconfig"
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 5b48961..eae4db1 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -71,3 +71,6 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
obj-$(CONFIG_OF) += of.o
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
+
+# PCI host controller drivers
+obj-y += host/
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
new file mode 100644
index 0000000..cc3a1af
--- /dev/null
+++ b/drivers/pci/host/Kconfig
@@ -0,0 +1,4 @@
+menu "PCI host controller drivers"
+ depends on PCI
+
+endmenu
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 10/27] arm: mvebu: fix address-cells in mpic DT node
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
There is no need to have a #address-cells property in the MPIC Device
Tree node, and more than that, having it confuses the of_irq_map_raw()
logic, which will be used by the Marvell PCIe driver.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/boot/dts/armada-370-xp.dtsi | 1 -
1 file changed, 1 deletion(-)
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 4c0abe8..1dcdae9 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -31,7 +31,6 @@
mpic: interrupt-controller at d0020000 {
compatible = "marvell,mpic";
#interrupt-cells = <1>;
- #address-cells = <1>;
#size-cells = <1>;
interrupt-controller;
};
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 11/27] clk: mvebu: create parent-child relation for PCIe clocks on Armada 370
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
The Armada 370 has two gatable clocks for each PCIe interface, and we
want both of them to be enabled. We therefore make one of the two
clocks a child of the other, as we did for the sataX and sataXlnk
clocks on Armada XP.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Mike Turquette <mturquette@linaro.org>
---
drivers/clk/mvebu/clk-gating-ctrl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
index 8fa5408..fd52b5f 100644
--- a/drivers/clk/mvebu/clk-gating-ctrl.c
+++ b/drivers/clk/mvebu/clk-gating-ctrl.c
@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __initconst armada_370_gating_descr[] = {
{ "pex1_en", NULL, 2 },
{ "ge1", NULL, 3 },
{ "ge0", NULL, 4 },
- { "pex0", NULL, 5 },
- { "pex1", NULL, 9 },
+ { "pex0", "pex0_en", 5 },
+ { "pex1", "pex1_en", 9 },
{ "sata0", NULL, 15 },
{ "sdio", NULL, 17 },
{ "tdm", NULL, 25 },
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 12/27] clk: mvebu: add more PCIe clocks for Armada XP
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
The current revision of the datasheet only mentions the gatable clocks
for the PCIe 0.0, 0.1, 0.2 and 0.3 interfaces, and forgot to mention
the ones for the PCIe 1.0, 1.1, 1.2, 1.3, 2.0 and 3.0
interfaces. After confirmation with Marvell engineers, this patch adds
the missing gatable clocks for those PCIe interfaces.
It also changes the name of the previously existing PCIe gatable
clocks, in order to match the naming using the datasheets.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
drivers/clk/mvebu/clk-gating-ctrl.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/mvebu/clk-gating-ctrl.c b/drivers/clk/mvebu/clk-gating-ctrl.c
index fd52b5f..24137f8 100644
--- a/drivers/clk/mvebu/clk-gating-ctrl.c
+++ b/drivers/clk/mvebu/clk-gating-ctrl.c
@@ -137,10 +137,14 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
{ "ge2", NULL, 2 },
{ "ge1", NULL, 3 },
{ "ge0", NULL, 4 },
- { "pex0", NULL, 5 },
- { "pex1", NULL, 6 },
- { "pex2", NULL, 7 },
- { "pex3", NULL, 8 },
+ { "pex00", NULL, 5 },
+ { "pex01", NULL, 6 },
+ { "pex02", NULL, 7 },
+ { "pex03", NULL, 8 },
+ { "pex10", NULL, 9 },
+ { "pex11", NULL, 10 },
+ { "pex12", NULL, 11 },
+ { "pex13", NULL, 12 },
{ "bp", NULL, 13 },
{ "sata0lnk", NULL, 14 },
{ "sata0", "sata0lnk", 15 },
@@ -152,6 +156,8 @@ static const struct mvebu_soc_descr __initconst armada_xp_gating_descr[] = {
{ "xor0", NULL, 22 },
{ "crypto", NULL, 23 },
{ "tdm", NULL, 25 },
+ { "pex20", NULL, 26 },
+ { "pex30", NULL, 27 },
{ "xor1", NULL, 28 },
{ "sata1lnk", NULL, 29 },
{ "sata1", "sata1lnk", 30 },
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 13/27] arm: plat-orion: introduce WIN_CTRL_ENABLE in address mapping code
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
Instead of hardcoding "1" as being the bit value to enable an address
decoding window, introduce and use a WIN_CTRL_ENABLE definition.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/plat-orion/addr-map.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
index febe386..4dec3db 100644
--- a/arch/arm/plat-orion/addr-map.c
+++ b/arch/arm/plat-orion/addr-map.c
@@ -38,6 +38,7 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
* CPU Address Decode Windows registers
*/
#define WIN_CTRL_OFF 0x0000
+#define WIN_CTRL_ENABLE BIT(0)
#define WIN_BASE_OFF 0x0004
#define WIN_REMAP_LO_OFF 0x0008
#define WIN_REMAP_HI_OFF 0x000c
@@ -79,7 +80,8 @@ void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
}
base_high = base & 0xffff0000;
- ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1;
+ ctrl = ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) |
+ WIN_CTRL_ENABLE;
writel(base_high, addr + WIN_BASE_OFF);
writel(ctrl, addr + WIN_CTRL_OFF);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 14/27] arm: plat-orion: refactor the orion_disable_wins() function
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
In the address decoding code, the orion_disable_wins() function is
used at boot time to disable all address decoding windows, before
configuring only the ones that are needed. This allows to make sure
that no configuration is left from the bootloader.
As a preparation for the introduction of address decoding window
allocation/deallocation function, we refactor this function into an
orion_disable_cpu_win() which disables a single window.
The orion_config_wins() function is changed to call
orion_disable_cpu_win() in a loop, to preserve an identical behavior.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/plat-orion/addr-map.c | 35 +++++++++++++++++------------------
1 file changed, 17 insertions(+), 18 deletions(-)
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
index 4dec3db..dd98638 100644
--- a/arch/arm/plat-orion/addr-map.c
+++ b/arch/arm/plat-orion/addr-map.c
@@ -95,6 +95,19 @@ void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
}
}
+static void __init orion_disable_cpu_win(const struct orion_addr_map_cfg *cfg,
+ const int win)
+{
+ void __iomem *addr = cfg->win_cfg_base(cfg, win);
+
+ writel(0, addr + WIN_BASE_OFF);
+ writel(0, addr + WIN_CTRL_OFF);
+ if (cfg->cpu_win_can_remap(cfg, win)) {
+ writel(0, addr + WIN_REMAP_LO_OFF);
+ writel(0, addr + WIN_REMAP_HI_OFF);
+ }
+}
+
/*
* Configure a number of windows.
*/
@@ -108,36 +121,22 @@ static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg,
}
}
-static void __init orion_disable_wins(const struct orion_addr_map_cfg * cfg)
-{
- void __iomem *addr;
- int i;
-
- for (i = 0; i < cfg->num_wins; i++) {
- addr = cfg->win_cfg_base(cfg, i);
-
- writel(0, addr + WIN_BASE_OFF);
- writel(0, addr + WIN_CTRL_OFF);
- if (cfg->cpu_win_can_remap(cfg, i)) {
- writel(0, addr + WIN_REMAP_LO_OFF);
- writel(0, addr + WIN_REMAP_HI_OFF);
- }
- }
-}
-
/*
* Disable, clear and configure windows.
*/
void __init orion_config_wins(struct orion_addr_map_cfg * cfg,
const struct orion_addr_map_info *info)
{
+ int win;
+
if (!cfg->cpu_win_can_remap)
cfg->cpu_win_can_remap = orion_cpu_win_can_remap;
if (!cfg->win_cfg_base)
cfg->win_cfg_base = orion_win_cfg_base;
- orion_disable_wins(cfg);
+ for (win = 0; win < cfg->num_wins; win++)
+ orion_disable_cpu_win(cfg, win);
if (info)
orion_setup_cpu_wins(cfg, info);
--
1.7.9.5
^ permalink raw reply related
* [PATCH v2 15/27] arm: plat-orion: introduce orion_{alloc, free}_cpu_win() functions
From: Thomas Petazzoni @ 2013-01-28 18:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1359399397-29729-1-git-send-email-thomas.petazzoni@free-electrons.com>
In the address decoding code, we implement two new functions:
orion_alloc_cpu_win() and orion_free_cpu_win(). The first function
finds an unused address decoding window, and configures it according
to the given arguments (in terms of base address, size, target,
attributes). The second function frees an address decoding window,
given a physical base address.
Those two new functions will be used by the PCIe code, which needs to
dynamically register address decoding windows depending on the PCIe
devices that are detected.
The orion_free_cpu_win() function is only here to handle error cases
in the PCIe devices initialization, in the normal case, address
decoding windows are never freed.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
---
arch/arm/plat-orion/addr-map.c | 50 +++++++++++++++++++++++++++
arch/arm/plat-orion/include/plat/addr-map.h | 7 ++++
2 files changed, 57 insertions(+)
diff --git a/arch/arm/plat-orion/addr-map.c b/arch/arm/plat-orion/addr-map.c
index dd98638..8f4ef82 100644
--- a/arch/arm/plat-orion/addr-map.c
+++ b/arch/arm/plat-orion/addr-map.c
@@ -109,6 +109,56 @@ static void __init orion_disable_cpu_win(const struct orion_addr_map_cfg *cfg,
}
/*
+ * Find an unused address decoding window, and enable it according to
+ * the arguments passed (base, size, target, attributes, remap).
+ */
+int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg,
+ const u32 base, const u32 size,
+ const u8 target, const u8 attr, const int remap)
+{
+ int win;
+
+ for (win = 0; win < cfg->num_wins; win++) {
+ void __iomem *addr = cfg->win_cfg_base(cfg, win);
+ u32 ctrl = readl(addr + WIN_CTRL_OFF);
+ if (!(ctrl & WIN_CTRL_ENABLE))
+ break;
+ }
+
+ /* No more windows available */
+ if (win == cfg->num_wins)
+ return -ENOMEM;
+
+ orion_setup_cpu_win(cfg, win, base, size, target, attr, remap);
+ return 0;
+}
+
+/*
+ * Free an address decoding window, given its base address.
+ */
+int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg,
+ const u32 base)
+{
+ int win;
+
+ for (win = 0; win < cfg->num_wins; win++) {
+ void __iomem *addr = cfg->win_cfg_base(cfg, win);
+ u32 winbase = readl(addr + WIN_BASE_OFF);
+ u32 ctrl = readl(addr + WIN_CTRL_OFF);
+
+ if (!(ctrl & WIN_CTRL_ENABLE))
+ continue;
+
+ if (winbase == (base & 0xffff0000)) {
+ orion_disable_cpu_win(cfg, win);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+/*
* Configure a number of windows.
*/
static void __init orion_setup_cpu_wins(const struct orion_addr_map_cfg * cfg,
diff --git a/arch/arm/plat-orion/include/plat/addr-map.h b/arch/arm/plat-orion/include/plat/addr-map.h
index b76c065..f8bb539 100644
--- a/arch/arm/plat-orion/include/plat/addr-map.h
+++ b/arch/arm/plat-orion/include/plat/addr-map.h
@@ -49,6 +49,13 @@ void __init orion_setup_cpu_win(const struct orion_addr_map_cfg *cfg,
const u32 size, const u8 target,
const u8 attr, const int remap);
+int __init orion_alloc_cpu_win(const struct orion_addr_map_cfg *cfg,
+ const u32 base, const u32 size,
+ const u8 target, const u8 attr, const int remap);
+
+int __init orion_free_cpu_win(const struct orion_addr_map_cfg *cfg,
+ const u32 base);
+
void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
const void __iomem *ddr_window_cpu_base);
#endif
--
1.7.9.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox