* [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource
2015-07-01 9:43 [PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
@ 2015-07-01 9:43 ` Zhou Wang
2015-07-02 17:50 ` Liviu Dudau
2015-07-01 9:43 ` [PATCH v3 2/5] PCI: designware: Add ARM64 support Zhou Wang
` (3 subsequent siblings)
4 siblings, 1 reply; 22+ messages in thread
From: Zhou Wang @ 2015-07-01 9:43 UTC (permalink / raw)
To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni, James Morse, Liviu Dudau
Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
zhangjukuo, qiuzhenfa, liguozhu, Zhou Wang
This patch had added by Arnd Bergmann during last reviewing of v1 patchset[1].
PCI core codes call pcibios_align_resource(). In ARM specific one, it will
dereference pci_sys_data and call sys->align_resource. If we try to unify ARM
and ARM64 PCIe API in pcie-designware. it will bring kernel crash when run into
this dereferencing.
However, in ARM there is only pci-mvebu which implements align_resource. So
add align_resource call back in pci_host_bridge structure and override
pcibios_align_resource with it.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
[1] http://www.spinics.net/lists/linux-pci/msg41671.html
---
arch/arm/kernel/bios32.c | 6 ------
drivers/pci/host/pci-mvebu.c | 47 ++++++++++++++++++++++++++++----------------
drivers/pci/setup-res.c | 27 ++++++++++++++++++++-----
include/linux/pci.h | 3 +++
4 files changed, 55 insertions(+), 28 deletions(-)
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index fcbbbb1..b01189f 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
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)
@@ -588,8 +587,6 @@ 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)
@@ -597,9 +594,6 @@ 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;
}
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 1ab8635..155d05f 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -22,6 +22,8 @@
#include <linux/of_pci.h>
#include <linux/of_platform.h>
+#include "../pci.h" /* HACK to see pci_find_host_bridge */
+
/*
* PCIe unit register offsets.
*/
@@ -751,27 +753,20 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
return 1;
}
-static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+static resource_size_t mvebu_pcie_align_resource(void *data,
+ const struct resource *res,
+ resource_size_t size,
+ resource_size_t align)
{
- struct mvebu_pcie *pcie = sys_to_pcie(sys);
- struct pci_bus *bus;
+ struct pci_dev *dev = data;
- bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
- &mvebu_pcie_ops, sys, &sys->resources);
- if (!bus)
- return NULL;
+ resource_size_t start = res->start;
- pci_scan_child_bus(bus);
+ if (res->flags & IORESOURCE_IO && start & 0x300)
+ start = (start + 0x3ff) & ~0x3ff;
- return bus;
-}
+ start = (start + align - 1) & ~(align - 1);
-static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
- const struct resource *res,
- resource_size_t start,
- resource_size_t size,
- resource_size_t align)
-{
if (dev->bus->number != 0)
return start;
@@ -796,6 +791,25 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
return start;
}
+static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ struct mvebu_pcie *pcie = sys_to_pcie(sys);
+ struct pci_host_bridge *phb;
+ struct pci_bus *bus;
+
+ bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
+ &mvebu_pcie_ops, sys, &sys->resources);
+ if (!bus)
+ return NULL;
+
+ phb = pci_find_host_bridge(bus);
+ phb->align_resource = mvebu_pcie_align_resource;
+
+ pci_scan_child_bus(bus);
+
+ return bus;
+}
+
static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
{
struct hw_pci hw;
@@ -812,7 +826,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
hw.scan = mvebu_pcie_scan_bus;
hw.map_irq = of_irq_parse_and_map_pci;
hw.ops = &mvebu_pcie_ops;
- hw.align_resource = mvebu_pcie_align_resource;
pci_common_init(&hw);
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 232f925..73abca7 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -200,7 +200,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
}
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
- int resno, resource_size_t size, resource_size_t align)
+ int resno, resource_size_t size, resource_size_t align,
+ resource_size_t (*alignf)(void *,
+ const struct resource *,
+ resource_size_t,
+ resource_size_t))
{
struct resource *res = dev->resource + resno;
resource_size_t min;
@@ -217,7 +221,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
*/
ret = pci_bus_alloc_resource(bus, res, size, align, min,
IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
- pcibios_align_resource, dev);
+ alignf, dev);
if (ret == 0)
return 0;
@@ -229,7 +233,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
(IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
ret = pci_bus_alloc_resource(bus, res, size, align, min,
IORESOURCE_PREFETCH,
- pcibios_align_resource, dev);
+ alignf, dev);
if (ret == 0)
return 0;
}
@@ -242,7 +246,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
*/
if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
- pcibios_align_resource, dev);
+ alignf, dev);
return ret;
}
@@ -251,10 +255,23 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
resource_size_t size, resource_size_t min_align)
{
struct pci_bus *bus;
+ struct pci_host_bridge *phb;
+ resource_size_t (*alignf)(void *,
+ const struct resource *,
+ resource_size_t,
+ resource_size_t);
int ret;
bus = dev->bus;
- while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
+ phb = pci_find_host_bridge(bus);
+
+ if (phb->align_resource)
+ alignf = phb->align_resource;
+ else
+ alignf = pcibios_align_resource;
+
+ while ((ret = __pci_assign_resource(bus, dev, resno, size,
+ min_align, alignf))) {
if (!bus->parent || !bus->self->transparent)
break;
bus = bus->parent;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 353db8d..39e48fc 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -404,6 +404,9 @@ struct pci_host_bridge {
struct device dev;
struct pci_bus *bus; /* root bus */
struct list_head windows; /* resource_entry */
+ resource_size_t (*align_resource)(void *data,
+ const struct resource *res,
+ resource_size_t size, resource_size_t align);
void (*release_fn)(struct pci_host_bridge *);
void *release_data;
unsigned int ignore_reset_delay:1; /* for entire hierarchy */
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource
2015-07-01 9:43 ` [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
@ 2015-07-02 17:50 ` Liviu Dudau
2015-07-07 5:44 ` Zhou Wang
0 siblings, 1 reply; 22+ messages in thread
From: Liviu Dudau @ 2015-07-02 17:50 UTC (permalink / raw)
To: Zhou Wang
Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni@huawei.com, James Morse,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, yuanzhichang@hisilicon.com,
zhudacai@hisilicon.com, zhangjukuo@huawei.com,
qiuzhenfa@hisilicon.com, liguozhu@hisilicon.com
On Wed, Jul 01, 2015 at 10:43:33AM +0100, Zhou Wang wrote:
> This patch had added by Arnd Bergmann during last reviewing of v1 patchset[1].
>
> PCI core codes call pcibios_align_resource(). In ARM specific one, it will
> dereference pci_sys_data and call sys->align_resource. If we try to unify ARM
> and ARM64 PCIe API in pcie-designware. it will bring kernel crash when run into
> this dereferencing.
>
> However, in ARM there is only pci-mvebu which implements align_resource. So
> add align_resource call back in pci_host_bridge structure and override
> pcibios_align_resource with it.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>
> [1] http://www.spinics.net/lists/linux-pci/msg41671.html
> ---
> arch/arm/kernel/bios32.c | 6 ------
> drivers/pci/host/pci-mvebu.c | 47 ++++++++++++++++++++++++++++----------------
> drivers/pci/setup-res.c | 27 ++++++++++++++++++++-----
> include/linux/pci.h | 3 +++
> 4 files changed, 55 insertions(+), 28 deletions(-)
>
> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
> index fcbbbb1..b01189f 100644
> --- a/arch/arm/kernel/bios32.c
> +++ b/arch/arm/kernel/bios32.c
> @@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
> 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)
> @@ -588,8 +587,6 @@ 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)
> @@ -597,9 +594,6 @@ 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;
> }
>
> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
> index 1ab8635..155d05f 100644
> --- a/drivers/pci/host/pci-mvebu.c
> +++ b/drivers/pci/host/pci-mvebu.c
> @@ -22,6 +22,8 @@
> #include <linux/of_pci.h>
> #include <linux/of_platform.h>
>
> +#include "../pci.h" /* HACK to see pci_find_host_bridge */
> +
> /*
> * PCIe unit register offsets.
> */
> @@ -751,27 +753,20 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
> return 1;
> }
>
> -static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> +static resource_size_t mvebu_pcie_align_resource(void *data,
> + const struct resource *res,
> + resource_size_t size,
> + resource_size_t align)
> {
> - struct mvebu_pcie *pcie = sys_to_pcie(sys);
> - struct pci_bus *bus;
> + struct pci_dev *dev = data;
>
> - bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
> - &mvebu_pcie_ops, sys, &sys->resources);
> - if (!bus)
> - return NULL;
> + resource_size_t start = res->start;
>
> - pci_scan_child_bus(bus);
> + if (res->flags & IORESOURCE_IO && start & 0x300)
> + start = (start + 0x3ff) & ~0x3ff;
>
> - return bus;
> -}
> + start = (start + align - 1) & ~(align - 1);
Honestly, I don't see here anything that is mvebu specific. Could you move
this function in the generic pci/host area and have a flag in the pci_host_bridge
structure whether the function should be called or not? I know that in a way
that looks very close to the existing implementation which uses pcibios_align_resource,
but the problem with pcibios_ version is that it is arch specific and not driver
specific the way we want.
Having this version as a generic implementation would also remove at least 2 more
arch version, possibly more after testing by the arch maintainers.
Best regards,
Liviu
>
> -static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
> - const struct resource *res,
> - resource_size_t start,
> - resource_size_t size,
> - resource_size_t align)
> -{
> if (dev->bus->number != 0)
> return start;
>
> @@ -796,6 +791,25 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
> return start;
> }
>
> +static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
> +{
> + struct mvebu_pcie *pcie = sys_to_pcie(sys);
> + struct pci_host_bridge *phb;
> + struct pci_bus *bus;
> +
> + bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
> + &mvebu_pcie_ops, sys, &sys->resources);
> + if (!bus)
> + return NULL;
> +
> + phb = pci_find_host_bridge(bus);
> + phb->align_resource = mvebu_pcie_align_resource;
> +
> + pci_scan_child_bus(bus);
> +
> + return bus;
> +}
> +
> static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
> {
> struct hw_pci hw;
> @@ -812,7 +826,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
> hw.scan = mvebu_pcie_scan_bus;
> hw.map_irq = of_irq_parse_and_map_pci;
> hw.ops = &mvebu_pcie_ops;
> - hw.align_resource = mvebu_pcie_align_resource;
>
> pci_common_init(&hw);
> }
> diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
> index 232f925..73abca7 100644
> --- a/drivers/pci/setup-res.c
> +++ b/drivers/pci/setup-res.c
> @@ -200,7 +200,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
> }
>
> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> - int resno, resource_size_t size, resource_size_t align)
> + int resno, resource_size_t size, resource_size_t align,
> + resource_size_t (*alignf)(void *,
> + const struct resource *,
> + resource_size_t,
> + resource_size_t))
> {
> struct resource *res = dev->resource + resno;
> resource_size_t min;
> @@ -217,7 +221,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> */
> ret = pci_bus_alloc_resource(bus, res, size, align, min,
> IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
> - pcibios_align_resource, dev);
> + alignf, dev);
> if (ret == 0)
> return 0;
>
> @@ -229,7 +233,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
> ret = pci_bus_alloc_resource(bus, res, size, align, min,
> IORESOURCE_PREFETCH,
> - pcibios_align_resource, dev);
> + alignf, dev);
> if (ret == 0)
> return 0;
> }
> @@ -242,7 +246,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
> */
> if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
> ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
> - pcibios_align_resource, dev);
> + alignf, dev);
>
> return ret;
> }
> @@ -251,10 +255,23 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
> resource_size_t size, resource_size_t min_align)
> {
> struct pci_bus *bus;
> + struct pci_host_bridge *phb;
> + resource_size_t (*alignf)(void *,
> + const struct resource *,
> + resource_size_t,
> + resource_size_t);
> int ret;
>
> bus = dev->bus;
> - while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
> + phb = pci_find_host_bridge(bus);
> +
> + if (phb->align_resource)
> + alignf = phb->align_resource;
> + else
> + alignf = pcibios_align_resource;
> +
> + while ((ret = __pci_assign_resource(bus, dev, resno, size,
> + min_align, alignf))) {
> if (!bus->parent || !bus->self->transparent)
> break;
> bus = bus->parent;
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 353db8d..39e48fc 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -404,6 +404,9 @@ struct pci_host_bridge {
> struct device dev;
> struct pci_bus *bus; /* root bus */
> struct list_head windows; /* resource_entry */
> + resource_size_t (*align_resource)(void *data,
> + const struct resource *res,
> + resource_size_t size, resource_size_t align);
> void (*release_fn)(struct pci_host_bridge *);
> void *release_data;
> unsigned int ignore_reset_delay:1; /* for entire hierarchy */
> --
> 1.9.1
>
--
====================
| I would like to |
| fix the world, |
| but they're not |
| giving me the |
\ source code! /
---------------
¯\_(ツ)_/¯
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource
2015-07-02 17:50 ` Liviu Dudau
@ 2015-07-07 5:44 ` Zhou Wang
[not found] ` <559B6721.4080305-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
0 siblings, 1 reply; 22+ messages in thread
From: Zhou Wang @ 2015-07-07 5:44 UTC (permalink / raw)
To: Liviu Dudau
Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni@huawei.com, James Morse,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, yuanzhichang@hisilicon.com,
zhudacai@hisilicon.com, zhangjukuo@huawei.com,
qiuzhenfa@hisilicon.com, liguozhu@hisilicon.com
On 2015/7/3 1:50, Liviu Dudau wrote:
> On Wed, Jul 01, 2015 at 10:43:33AM +0100, Zhou Wang wrote:
>> This patch had added by Arnd Bergmann during last reviewing of v1 patchset[1].
>>
>> PCI core codes call pcibios_align_resource(). In ARM specific one, it will
>> dereference pci_sys_data and call sys->align_resource. If we try to unify ARM
>> and ARM64 PCIe API in pcie-designware. it will bring kernel crash when run into
>> this dereferencing.
>>
>> However, in ARM there is only pci-mvebu which implements align_resource. So
>> add align_resource call back in pci_host_bridge structure and override
>> pcibios_align_resource with it.
>>
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
>> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>>
>> [1] http://www.spinics.net/lists/linux-pci/msg41671.html
>> ---
>> arch/arm/kernel/bios32.c | 6 ------
>> drivers/pci/host/pci-mvebu.c | 47 ++++++++++++++++++++++++++++----------------
>> drivers/pci/setup-res.c | 27 ++++++++++++++++++++-----
>> include/linux/pci.h | 3 +++
>> 4 files changed, 55 insertions(+), 28 deletions(-)
>>
>> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
>> index fcbbbb1..b01189f 100644
>> --- a/arch/arm/kernel/bios32.c
>> +++ b/arch/arm/kernel/bios32.c
>> @@ -468,7 +468,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
>> 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)
>> @@ -588,8 +587,6 @@ 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)
>> @@ -597,9 +594,6 @@ 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;
>> }
>>
>> diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
>> index 1ab8635..155d05f 100644
>> --- a/drivers/pci/host/pci-mvebu.c
>> +++ b/drivers/pci/host/pci-mvebu.c
>> @@ -22,6 +22,8 @@
>> #include <linux/of_pci.h>
>> #include <linux/of_platform.h>
>>
>> +#include "../pci.h" /* HACK to see pci_find_host_bridge */
>> +
>> /*
>> * PCIe unit register offsets.
>> */
>> @@ -751,27 +753,20 @@ static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
>> return 1;
>> }
>>
>> -static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
>> +static resource_size_t mvebu_pcie_align_resource(void *data,
>> + const struct resource *res,
>> + resource_size_t size,
>> + resource_size_t align)
>> {
>> - struct mvebu_pcie *pcie = sys_to_pcie(sys);
>> - struct pci_bus *bus;
>> + struct pci_dev *dev = data;
>>
>> - bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
>> - &mvebu_pcie_ops, sys, &sys->resources);
>> - if (!bus)
>> - return NULL;
>> + resource_size_t start = res->start;
>>
>> - pci_scan_child_bus(bus);
>> + if (res->flags & IORESOURCE_IO && start & 0x300)
>> + start = (start + 0x3ff) & ~0x3ff;
>>
>> - return bus;
>> -}
>> + start = (start + align - 1) & ~(align - 1);
>
> Honestly, I don't see here anything that is mvebu specific. Could you move
What I mean is that there is only mvebu who implemented sys->align_resource callback in ARM
arch.
> this function in the generic pci/host area and have a flag in the pci_host_bridge
> structure whether the function should be called or not? I know that in a way
> that looks very close to the existing implementation which uses pcibios_align_resource,
I am confused about "the existing implementation". Now pcibios_align_resource are
implemented by each arch code and are called directly. Did I miss anything about
pcibios_align_resource?
Best rgards,
Zhou
> but the problem with pcibios_ version is that it is arch specific and not driver
> specific the way we want.
>
> Having this version as a generic implementation would also remove at least 2 more
> arch version, possibly more after testing by the arch maintainers.
>
> Best regards,
> Liviu
>
>>
>> -static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
>> - const struct resource *res,
>> - resource_size_t start,
>> - resource_size_t size,
>> - resource_size_t align)
>> -{
>> if (dev->bus->number != 0)
>> return start;
>>
>> @@ -796,6 +791,25 @@ static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
>> return start;
>> }
>>
>> +static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
>> +{
>> + struct mvebu_pcie *pcie = sys_to_pcie(sys);
>> + struct pci_host_bridge *phb;
>> + struct pci_bus *bus;
>> +
>> + bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
>> + &mvebu_pcie_ops, sys, &sys->resources);
>> + if (!bus)
>> + return NULL;
>> +
>> + phb = pci_find_host_bridge(bus);
>> + phb->align_resource = mvebu_pcie_align_resource;
>> +
>> + pci_scan_child_bus(bus);
>> +
>> + return bus;
>> +}
>> +
>> static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
>> {
>> struct hw_pci hw;
>> @@ -812,7 +826,6 @@ static void mvebu_pcie_enable(struct mvebu_pcie *pcie)
>> hw.scan = mvebu_pcie_scan_bus;
>> hw.map_irq = of_irq_parse_and_map_pci;
>> hw.ops = &mvebu_pcie_ops;
>> - hw.align_resource = mvebu_pcie_align_resource;
>>
>> pci_common_init(&hw);
>> }
>> diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
>> index 232f925..73abca7 100644
>> --- a/drivers/pci/setup-res.c
>> +++ b/drivers/pci/setup-res.c
>> @@ -200,7 +200,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
>> }
>>
>> static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
>> - int resno, resource_size_t size, resource_size_t align)
>> + int resno, resource_size_t size, resource_size_t align,
>> + resource_size_t (*alignf)(void *,
>> + const struct resource *,
>> + resource_size_t,
>> + resource_size_t))
>> {
>> struct resource *res = dev->resource + resno;
>> resource_size_t min;
>> @@ -217,7 +221,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
>> */
>> ret = pci_bus_alloc_resource(bus, res, size, align, min,
>> IORESOURCE_PREFETCH | IORESOURCE_MEM_64,
>> - pcibios_align_resource, dev);
>> + alignf, dev);
>> if (ret == 0)
>> return 0;
>>
>> @@ -229,7 +233,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
>> (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) {
>> ret = pci_bus_alloc_resource(bus, res, size, align, min,
>> IORESOURCE_PREFETCH,
>> - pcibios_align_resource, dev);
>> + alignf, dev);
>> if (ret == 0)
>> return 0;
>> }
>> @@ -242,7 +246,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
>> */
>> if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64))
>> ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
>> - pcibios_align_resource, dev);
>> + alignf, dev);
>>
>> return ret;
>> }
>> @@ -251,10 +255,23 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,
>> resource_size_t size, resource_size_t min_align)
>> {
>> struct pci_bus *bus;
>> + struct pci_host_bridge *phb;
>> + resource_size_t (*alignf)(void *,
>> + const struct resource *,
>> + resource_size_t,
>> + resource_size_t);
>> int ret;
>>
>> bus = dev->bus;
>> - while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
>> + phb = pci_find_host_bridge(bus);
>> +
>> + if (phb->align_resource)
>> + alignf = phb->align_resource;
>> + else
>> + alignf = pcibios_align_resource;
>> +
>> + while ((ret = __pci_assign_resource(bus, dev, resno, size,
>> + min_align, alignf))) {
>> if (!bus->parent || !bus->self->transparent)
>> break;
>> bus = bus->parent;
>> diff --git a/include/linux/pci.h b/include/linux/pci.h
>> index 353db8d..39e48fc 100644
>> --- a/include/linux/pci.h
>> +++ b/include/linux/pci.h
>> @@ -404,6 +404,9 @@ struct pci_host_bridge {
>> struct device dev;
>> struct pci_bus *bus; /* root bus */
>> struct list_head windows; /* resource_entry */
>> + resource_size_t (*align_resource)(void *data,
>> + const struct resource *res,
>> + resource_size_t size, resource_size_t align);
>> void (*release_fn)(struct pci_host_bridge *);
>> void *release_data;
>> unsigned int ignore_reset_delay:1; /* for entire hierarchy */
>> --
>> 1.9.1
>>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 2/5] PCI: designware: Add ARM64 support
2015-07-01 9:43 [PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-07-01 9:43 ` [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
@ 2015-07-01 9:43 ` Zhou Wang
2015-07-01 13:29 ` Gabriele Paoloni
2015-07-01 9:43 ` [PATCH v3 3/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
` (2 subsequent siblings)
4 siblings, 1 reply; 22+ messages in thread
From: Zhou Wang @ 2015-07-01 9:43 UTC (permalink / raw)
To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni, James Morse, Liviu Dudau
Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
zhangjukuo, qiuzhenfa, liguozhu, Zhou Wang
This patch tries to unify ARM32 and ARM64 PCIe in designware driver. Delete
function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct hw_pci,
move related operations to dw_pcie_host_init. Also set pp->root_bus_nr = 0 in
each PCIe host driver which is based on pcie-designware. This patch also try
to use of_pci_get_host_bridge_resources for ARM32 and ARM64 according to the
suggestion for Gabriele[1]
I tested this patch on D02 board of Hisilicon. It works well.
I have compiled the driver with multi_v7_defconfig. However, I don't have
ARM32 PCIe related board to do test. It will be appreciated if someone could
help to test it.
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Tested-by: James Morse <james.morse@arm.com>
[1] http://www.spinics.net/lists/linux-pci/msg42194.html
---
drivers/pci/host/pci-dra7xx.c | 1 +
drivers/pci/host/pci-exynos.c | 2 +-
drivers/pci/host/pci-imx6.c | 2 +-
drivers/pci/host/pci-keystone-dw.c | 2 +-
drivers/pci/host/pci-keystone.c | 2 +-
drivers/pci/host/pci-layerscape.c | 2 +-
drivers/pci/host/pcie-designware.c | 242 +++++++++++++++----------------------
drivers/pci/host/pcie-designware.h | 10 +-
drivers/pci/host/pcie-spear13xx.c | 2 +-
9 files changed, 110 insertions(+), 155 deletions(-)
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 2d57e19..5c8b6ab 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
pp = &dra7xx->pp;
pp->dev = dev;
+ pp->root_bus_nr = 0;
pp->ops = &dra7xx_pcie_host_ops;
pp->irq = platform_get_irq(pdev, 1);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index c139237..4b6db6c 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
}
}
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
pp->ops = &exynos_pcie_host_ops;
ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index fdb9536..c4a80c5 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
}
}
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
pp->ops = &imx6_pcie_host_ops;
ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
index f34892e..b1e4135 100644
--- a/drivers/pci/host/pci-keystone-dw.c
+++ b/drivers/pci/host/pci-keystone-dw.c
@@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem *reg_virt)
void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
{
struct pcie_port *pp = &ks_pcie->pp;
- u32 start = pp->mem.start, end = pp->mem.end;
+ u32 start = pp->mem->start, end = pp->mem->end;
int i, tr_size;
/* Disable BARs for inbound access */
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
index 75333b0..df91f5e 100644
--- a/drivers/pci/host/pci-keystone.c
+++ b/drivers/pci/host/pci-keystone.c
@@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
return ret;
}
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
pp->ops = &keystone_pcie_host_ops;
ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
if (ret) {
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
index 4a6e62f..5c7a9c4 100644
--- a/drivers/pci/host/pci-layerscape.c
+++ b/drivers/pci/host/pci-layerscape.c
@@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
pp = &pcie->pp;
pp->dev = pcie->dev;
pp->dbi_base = pcie->dbi;
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
pp->ops = &ls_pcie_host_ops;
ret = dw_pcie_host_init(pp);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 2e9f84f..844febee 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -11,6 +11,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/hardirq.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
@@ -67,16 +68,7 @@
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
#define PCIE_ATU_UPPER_TARGET 0x91C
-static struct hw_pci dw_pci;
-
-static unsigned long global_io_offset;
-
-static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
-{
- BUG_ON(!sys->private_data);
-
- return sys->private_data;
-}
+static struct pci_ops dw_pcie_ops;
int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
{
@@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
{
int irq, pos0, i;
- struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
+ struct pcie_port *pp = desc->dev->bus->sysdata;
pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
order_base_2(no_irqs));
@@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
{
int irq, pos;
struct msi_msg msg;
- struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
+ struct pcie_port *pp = pdev->bus->sysdata;
if (desc->msi_attrib.is_msix)
return -EINVAL;
@@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
{
struct irq_data *data = irq_get_irq_data(irq);
struct msi_desc *msi = irq_data_get_msi(data);
- struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
+ struct pcie_port *pp = msi->dev->bus->sysdata;
clear_irq_range(pp, irq, 1, data->hwirq);
}
@@ -342,16 +334,24 @@ static const struct irq_domain_ops msi_domain_ops = {
.map = dw_pcie_msi_map,
};
-int dw_pcie_host_init(struct pcie_port *pp)
+int __init dw_pcie_host_init(struct pcie_port *pp)
{
struct device_node *np = pp->dev->of_node;
struct platform_device *pdev = to_platform_device(pp->dev);
- struct of_pci_range range;
- struct of_pci_range_parser parser;
+ struct pci_bus *bus;
struct resource *cfg_res;
+ LIST_HEAD(res);
u32 val, na, ns;
const __be32 *addrp;
int i, index, ret;
+ int rlen;
+ struct resource_entry *win;
+ const __be32 *parser_range_end = of_get_property(np, "ranges", &rlen);
+
+ if (parser_range_end == NULL)
+ return -ENOENT;
+ parser_range_end += rlen/sizeof(__be32);
+
/* Find the address cell size and the number of cells in order to get
* the untranslated address.
@@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
dev_err(pp->dev, "missing *config* reg space\n");
}
- if (of_pci_range_parser_init(&parser, np)) {
- dev_err(pp->dev, "missing ranges property\n");
- return -EINVAL;
- }
+ ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
+ if (ret)
+ return ret;
/* Get the I/O and memory ranges from DT */
- for_each_of_pci_range(&parser, &range) {
- unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
-
- if (restype == IORESOURCE_IO) {
- of_pci_range_to_resource(&range, np, &pp->io);
- pp->io.name = "I/O";
- pp->io.start = max_t(resource_size_t,
- PCIBIOS_MIN_IO,
- range.pci_addr + global_io_offset);
- pp->io.end = min_t(resource_size_t,
- IO_SPACE_LIMIT,
- range.pci_addr + range.size
- + global_io_offset - 1);
- pp->io_size = resource_size(&pp->io);
- pp->io_bus_addr = range.pci_addr;
- pp->io_base = range.cpu_addr;
-
- /* Find the untranslated IO space address */
- pp->io_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == IORESOURCE_MEM) {
- of_pci_range_to_resource(&range, np, &pp->mem);
- pp->mem.name = "MEM";
- pp->mem_size = resource_size(&pp->mem);
- pp->mem_bus_addr = range.pci_addr;
-
- /* Find the untranslated MEM space address */
- pp->mem_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- }
- if (restype == 0) {
- of_pci_range_to_resource(&range, np, &pp->cfg);
- pp->cfg0_size = resource_size(&pp->cfg)/2;
- pp->cfg1_size = resource_size(&pp->cfg)/2;
- pp->cfg0_base = pp->cfg.start;
- pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
+ resource_list_for_each_entry(win, &res) {
+ switch (resource_type(win->res)) {
+ case IORESOURCE_IO:
+ pp->io = win->res;
+ pp->io->name = "I/O";
+ pp->io_size = resource_size(pp->io);
+ pp->io_bus_addr = pp->io->start - win->offset;
+ /* magic 5 below comes from magic na and ns in
+ * of_pci_range_parser_init() */
+ pp->io_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ ret = pci_remap_iospace(pp->io, pp->io_base);
+ if (ret) {
+ dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
+ ret, pp->io);
+ continue;
+ }
+ break;
+ case IORESOURCE_MEM:
+ pp->mem = win->res;
+ pp->mem->name = "MEM";
+ pp->mem_size = resource_size(pp->mem);
+ pp->mem_bus_addr = pp->mem->start - win->offset;
+ pp->mem_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ break;
+ case 0:
+ pp->cfg = win->res;
+ pp->cfg0_size = resource_size(pp->cfg)/2;
+ pp->cfg1_size = resource_size(pp->cfg)/2;
+ pp->cfg0_base = pp->cfg->start;
+ pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
/* Find the untranslated configuration space address */
- pp->cfg0_mod_base = of_read_number(parser.range -
- parser.np + na, ns);
- pp->cfg1_mod_base = pp->cfg0_mod_base +
- pp->cfg0_size;
+ pp->cfg0_mod_base = of_read_number(parser_range_end -
+ of_n_addr_cells(np) - 5 + na, ns);
+ pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
+ break;
+ case IORESOURCE_BUS:
+ pp->busn = win->res;
+ break;
+ default:
+ continue;
}
}
- ret = of_pci_parse_bus_range(np, &pp->busn);
- if (ret < 0) {
- pp->busn.name = np->name;
- pp->busn.start = 0;
- pp->busn.end = 0xff;
- pp->busn.flags = IORESOURCE_BUS;
- dev_dbg(pp->dev, "failed to parse bus-range property: %d, using default %pR\n",
- ret, &pp->busn);
- }
-
if (!pp->dbi_base) {
- pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
- resource_size(&pp->cfg));
+ pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
+ resource_size(pp->cfg));
if (!pp->dbi_base) {
dev_err(pp->dev, "error with ioremap\n");
return -ENOMEM;
}
}
- pp->mem_base = pp->mem.start;
+ pp->mem_base = pp->mem->start;
if (!pp->va_cfg0_base) {
pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
@@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (pp->ops->host_init)
pp->ops->host_init(pp);
- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+ if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
/* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
+ if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
+
+ if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
-#ifdef CONFIG_PCI_MSI
- dw_pcie_msi_chip.dev = pp->dev;
- dw_pci.msi_ctrl = &dw_pcie_msi_chip;
+ if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
+ != PCIBIOS_SUCCESSFUL)
+ return -EINVAL;
+
+ bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
+ pp, &res);
+ if (!bus)
+ return -ENOMEM;
+
+#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+ bus->msi = container_of(&pp->irq_domain, struct msi_controller, domain);
+#else
+ bus->msi = &dw_pcie_msi_chip;
#endif
- dw_pci.nr_controllers = 1;
- dw_pci.private_data = (void **)&pp;
+ pci_scan_child_bus(bus);
+ if (pp->ops->scan_bus)
+ pp->ops->scan_bus(pp);
- pci_common_init_dev(pp->dev, &dw_pci);
+#ifdef CONFIG_ARM
+ /* support old dtbs that incorrectly describe IRQs */
+ pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
+
+ pci_assign_unassigned_bus_resources(bus);
+ pci_bus_add_devices(bus);
return 0;
}
@@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port *pp,
static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
@@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
- struct pcie_port *pp = sys_to_pcie(bus->sysdata);
+ struct pcie_port *pp = bus->sysdata;
int ret;
if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
@@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
.write = dw_pcie_wr_conf,
};
-static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
-{
- struct pcie_port *pp;
-
- pp = sys_to_pcie(sys);
-
- if (global_io_offset < SZ_1M && pp->io_size > 0) {
- sys->io_offset = global_io_offset - pp->io_bus_addr;
- pci_ioremap_io(global_io_offset, pp->io_base);
- global_io_offset += SZ_64K;
- pci_add_resource_offset(&sys->resources, &pp->io,
- sys->io_offset);
- }
-
- sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
- pci_add_resource_offset(&sys->resources, &pp->mem, sys->mem_offset);
- pci_add_resource(&sys->resources, &pp->busn);
-
- return 1;
-}
-
-static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)
-{
- struct pci_bus *bus;
- struct pcie_port *pp = sys_to_pcie(sys);
-
- pp->root_bus_nr = sys->busnr;
- bus = pci_create_root_bus(pp->dev, sys->busnr,
- &dw_pcie_ops, sys, &sys->resources);
- if (!bus)
- return NULL;
-
- pci_scan_child_bus(bus);
-
- if (bus && pp->ops->scan_bus)
- pp->ops->scan_bus(pp);
-
- return bus;
-}
-
-static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
-{
- struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
- int irq;
-
- irq = of_irq_parse_and_map_pci(dev, slot, pin);
- if (!irq)
- irq = pp->irq;
-
- return irq;
-}
-
-static struct hw_pci dw_pci = {
- .setup = dw_pcie_setup,
- .scan = dw_pcie_scan_bus,
- .map_irq = dw_pcie_map_irq,
-};
-
void dw_pcie_setup_rc(struct pcie_port *pp)
{
u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index d0bbd27..ab78710 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -34,7 +34,7 @@ struct pcie_port {
u64 cfg1_mod_base;
void __iomem *va_cfg1_base;
u32 cfg1_size;
- u64 io_base;
+ resource_size_t io_base;
u64 io_mod_base;
phys_addr_t io_bus_addr;
u32 io_size;
@@ -42,10 +42,10 @@ struct pcie_port {
u64 mem_mod_base;
phys_addr_t mem_bus_addr;
u32 mem_size;
- struct resource cfg;
- struct resource io;
- struct resource mem;
- struct resource busn;
+ struct resource *cfg;
+ struct resource *io;
+ struct resource *mem;
+ struct resource *busn;
int irq;
u32 lanes;
struct pcie_host_ops *ops;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index 020d788..e78ddf8 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
return ret;
}
- pp->root_bus_nr = -1;
+ pp->root_bus_nr = 0;
pp->ops = &spear13xx_pcie_host_ops;
ret = dw_pcie_host_init(pp);
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread* RE: [PATCH v3 2/5] PCI: designware: Add ARM64 support
2015-07-01 9:43 ` [PATCH v3 2/5] PCI: designware: Add ARM64 support Zhou Wang
@ 2015-07-01 13:29 ` Gabriele Paoloni
2015-07-01 14:26 ` James Morse
2015-07-02 1:16 ` Zhou Wang
0 siblings, 2 replies; 22+ messages in thread
From: Gabriele Paoloni @ 2015-07-01 13:29 UTC (permalink / raw)
To: Wangzhou (B), Bjorn Helgaas, Jingoo Han, Pratyush Anand,
Arnd Bergmann, James Morse, Liviu Dudau, kishon@ti.com,
xobs@kosagi.com, m-karicheri2@ti.com, Minghuan.Lian@freescale.com
Cc: linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, Yuanzhichang, Zhudacai, zhangjukuo,
qiuzhenfa, Liguozhu (Kenneth)
Adding to the recipients list the authors of the drivers that depend on Synopsys Designware and that are not included
Respectively:
pci-dra7xx Kishon Vijay Abraham I <kishon@ti.com>
pci-imx6 Sean Cross <xobs@kosagi.com>
pci-keystone Murali Karicheri <m-karicheri2@ti.com>
pci-layerscape Minghuan Lian <Minghuan.Lian@freescale.com>
Driver Authors already included:
pci-exynos Jingoo Han <jg1.han@samsung.com>
pcie-spear13xx Pratyush Anand <pratyush.anand@st.com>
Cheers
Gab
> -----Original Message-----
> From: Wangzhou (B)
> Sent: Wednesday, July 01, 2015 10:44 AM
> To: Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; Gabriele
> Paoloni; James Morse; Liviu Dudau
> Cc: linux-pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
> qiuzhenfa; Liguozhu (Kenneth); Wangzhou (B)
> Subject: [PATCH v3 2/5] PCI: designware: Add ARM64 support
>
> This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
> Delete
> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
> hw_pci,
> move related operations to dw_pcie_host_init. Also set pp->root_bus_nr
> = 0 in
> each PCIe host driver which is based on pcie-designware. This patch
> also try
> to use of_pci_get_host_bridge_resources for ARM32 and ARM64 according
> to the
> suggestion for Gabriele[1]
>
> I tested this patch on D02 board of Hisilicon. It works well.
> I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> ARM32 PCIe related board to do test. It will be appreciated if someone
> could
> help to test it.
>
> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> Tested-by: James Morse <james.morse@arm.com>
>
> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
> ---
> drivers/pci/host/pci-dra7xx.c | 1 +
> drivers/pci/host/pci-exynos.c | 2 +-
> drivers/pci/host/pci-imx6.c | 2 +-
> drivers/pci/host/pci-keystone-dw.c | 2 +-
> drivers/pci/host/pci-keystone.c | 2 +-
> drivers/pci/host/pci-layerscape.c | 2 +-
> drivers/pci/host/pcie-designware.c | 242 +++++++++++++++--------------
> --------
> drivers/pci/host/pcie-designware.h | 10 +-
> drivers/pci/host/pcie-spear13xx.c | 2 +-
> 9 files changed, 110 insertions(+), 155 deletions(-)
>
> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
> dra7xx.c
> index 2d57e19..5c8b6ab 100644
> --- a/drivers/pci/host/pci-dra7xx.c
> +++ b/drivers/pci/host/pci-dra7xx.c
> @@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct
> dra7xx_pcie *dra7xx,
>
> pp = &dra7xx->pp;
> pp->dev = dev;
> + pp->root_bus_nr = 0;
> pp->ops = &dra7xx_pcie_host_ops;
>
> pp->irq = platform_get_irq(pdev, 1);
> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
> exynos.c
> index c139237..4b6db6c 100644
> --- a/drivers/pci/host/pci-exynos.c
> +++ b/drivers/pci/host/pci-exynos.c
> @@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct
> pcie_port *pp,
> }
> }
>
> - pp->root_bus_nr = -1;
> + pp->root_bus_nr = 0;
> pp->ops = &exynos_pcie_host_ops;
>
> ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
> index fdb9536..c4a80c5 100644
> --- a/drivers/pci/host/pci-imx6.c
> +++ b/drivers/pci/host/pci-imx6.c
> @@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct
> pcie_port *pp,
> }
> }
>
> - pp->root_bus_nr = -1;
> + pp->root_bus_nr = 0;
> pp->ops = &imx6_pcie_host_ops;
>
> ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-
> keystone-dw.c
> index f34892e..b1e4135 100644
> --- a/drivers/pci/host/pci-keystone-dw.c
> +++ b/drivers/pci/host/pci-keystone-dw.c
> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem
> *reg_virt)
> void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
> {
> struct pcie_port *pp = &ks_pcie->pp;
> - u32 start = pp->mem.start, end = pp->mem.end;
> + u32 start = pp->mem->start, end = pp->mem->end;
> int i, tr_size;
>
> /* Disable BARs for inbound access */
> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
> keystone.c
> index 75333b0..df91f5e 100644
> --- a/drivers/pci/host/pci-keystone.c
> +++ b/drivers/pci/host/pci-keystone.c
> @@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct
> keystone_pcie *ks_pcie,
> return ret;
> }
>
> - pp->root_bus_nr = -1;
> + pp->root_bus_nr = 0;
> pp->ops = &keystone_pcie_host_ops;
> ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
> if (ret) {
> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-
> layerscape.c
> index 4a6e62f..5c7a9c4 100644
> --- a/drivers/pci/host/pci-layerscape.c
> +++ b/drivers/pci/host/pci-layerscape.c
> @@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
> pp = &pcie->pp;
> pp->dev = pcie->dev;
> pp->dbi_base = pcie->dbi;
> - pp->root_bus_nr = -1;
> + pp->root_bus_nr = 0;
> pp->ops = &ls_pcie_host_ops;
>
> ret = dw_pcie_host_init(pp);
> diff --git a/drivers/pci/host/pcie-designware.c
> b/drivers/pci/host/pcie-designware.c
> index 2e9f84f..844febee 100644
> --- a/drivers/pci/host/pcie-designware.c
> +++ b/drivers/pci/host/pcie-designware.c
> @@ -11,6 +11,7 @@
> * published by the Free Software Foundation.
> */
>
> +#include <linux/hardirq.h>
> #include <linux/irq.h>
> #include <linux/irqdomain.h>
> #include <linux/kernel.h>
> @@ -67,16 +68,7 @@
> #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
> #define PCIE_ATU_UPPER_TARGET 0x91C
>
> -static struct hw_pci dw_pci;
> -
> -static unsigned long global_io_offset;
> -
> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
> -{
> - BUG_ON(!sys->private_data);
> -
> - return sys->private_data;
> -}
> +static struct pci_ops dw_pcie_ops;
>
> int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
> {
> @@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
> *pp, int irq)
> static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
> {
> int irq, pos0, i;
> - struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
> + struct pcie_port *pp = desc->dev->bus->sysdata;
>
> pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
> order_base_2(no_irqs));
> @@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller
> *chip, struct pci_dev *pdev,
> {
> int irq, pos;
> struct msi_msg msg;
> - struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
> + struct pcie_port *pp = pdev->bus->sysdata;
>
> if (desc->msi_attrib.is_msix)
> return -EINVAL;
> @@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct
> msi_controller *chip, unsigned int irq)
> {
> struct irq_data *data = irq_get_irq_data(irq);
> struct msi_desc *msi = irq_data_get_msi(data);
> - struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
> + struct pcie_port *pp = msi->dev->bus->sysdata;
>
> clear_irq_range(pp, irq, 1, data->hwirq);
> }
> @@ -342,16 +334,24 @@ static const struct irq_domain_ops msi_domain_ops
> = {
> .map = dw_pcie_msi_map,
> };
>
> -int dw_pcie_host_init(struct pcie_port *pp)
> +int __init dw_pcie_host_init(struct pcie_port *pp)
> {
> struct device_node *np = pp->dev->of_node;
> struct platform_device *pdev = to_platform_device(pp->dev);
> - struct of_pci_range range;
> - struct of_pci_range_parser parser;
> + struct pci_bus *bus;
> struct resource *cfg_res;
> + LIST_HEAD(res);
> u32 val, na, ns;
> const __be32 *addrp;
> int i, index, ret;
> + int rlen;
> + struct resource_entry *win;
> + const __be32 *parser_range_end = of_get_property(np, "ranges",
> &rlen);
> +
> + if (parser_range_end == NULL)
> + return -ENOENT;
> + parser_range_end += rlen/sizeof(__be32);
> +
>
> /* Find the address cell size and the number of cells in order to
> get
> * the untranslated address.
> @@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
> dev_err(pp->dev, "missing *config* reg space\n");
> }
>
> - if (of_pci_range_parser_init(&parser, np)) {
> - dev_err(pp->dev, "missing ranges property\n");
> - return -EINVAL;
> - }
> + ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
> >io_base);
> + if (ret)
> + return ret;
>
> /* Get the I/O and memory ranges from DT */
> - for_each_of_pci_range(&parser, &range) {
> - unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
> -
> - if (restype == IORESOURCE_IO) {
> - of_pci_range_to_resource(&range, np, &pp->io);
> - pp->io.name = "I/O";
> - pp->io.start = max_t(resource_size_t,
> - PCIBIOS_MIN_IO,
> - range.pci_addr + global_io_offset);
> - pp->io.end = min_t(resource_size_t,
> - IO_SPACE_LIMIT,
> - range.pci_addr + range.size
> - + global_io_offset - 1);
> - pp->io_size = resource_size(&pp->io);
> - pp->io_bus_addr = range.pci_addr;
> - pp->io_base = range.cpu_addr;
> -
> - /* Find the untranslated IO space address */
> - pp->io_mod_base = of_read_number(parser.range -
> - parser.np + na, ns);
> - }
> - if (restype == IORESOURCE_MEM) {
> - of_pci_range_to_resource(&range, np, &pp->mem);
> - pp->mem.name = "MEM";
> - pp->mem_size = resource_size(&pp->mem);
> - pp->mem_bus_addr = range.pci_addr;
> -
> - /* Find the untranslated MEM space address */
> - pp->mem_mod_base = of_read_number(parser.range -
> - parser.np + na, ns);
> - }
> - if (restype == 0) {
> - of_pci_range_to_resource(&range, np, &pp->cfg);
> - pp->cfg0_size = resource_size(&pp->cfg)/2;
> - pp->cfg1_size = resource_size(&pp->cfg)/2;
> - pp->cfg0_base = pp->cfg.start;
> - pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
> + resource_list_for_each_entry(win, &res) {
> + switch (resource_type(win->res)) {
> + case IORESOURCE_IO:
> + pp->io = win->res;
> + pp->io->name = "I/O";
> + pp->io_size = resource_size(pp->io);
> + pp->io_bus_addr = pp->io->start - win->offset;
> + /* magic 5 below comes from magic na and ns in
> + * of_pci_range_parser_init() */
> + pp->io_mod_base = of_read_number(parser_range_end -
> + of_n_addr_cells(np) - 5 + na, ns);
> + ret = pci_remap_iospace(pp->io, pp->io_base);
> + if (ret) {
> + dev_warn(pp->dev, "error %d: failed to map
> resource %pR\n",
> + ret, pp->io);
> + continue;
> + }
> + break;
> + case IORESOURCE_MEM:
> + pp->mem = win->res;
> + pp->mem->name = "MEM";
> + pp->mem_size = resource_size(pp->mem);
> + pp->mem_bus_addr = pp->mem->start - win->offset;
> + pp->mem_mod_base = of_read_number(parser_range_end -
> + of_n_addr_cells(np) - 5 + na, ns);
> + break;
> + case 0:
> + pp->cfg = win->res;
> + pp->cfg0_size = resource_size(pp->cfg)/2;
> + pp->cfg1_size = resource_size(pp->cfg)/2;
> + pp->cfg0_base = pp->cfg->start;
> + pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
>
> /* Find the untranslated configuration space address
> */
> - pp->cfg0_mod_base = of_read_number(parser.range -
> - parser.np + na, ns);
> - pp->cfg1_mod_base = pp->cfg0_mod_base +
> - pp->cfg0_size;
> + pp->cfg0_mod_base = of_read_number(parser_range_end -
> + of_n_addr_cells(np) - 5 + na, ns);
> + pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
> + break;
> + case IORESOURCE_BUS:
> + pp->busn = win->res;
> + break;
> + default:
> + continue;
> }
> }
>
> - ret = of_pci_parse_bus_range(np, &pp->busn);
> - if (ret < 0) {
> - pp->busn.name = np->name;
> - pp->busn.start = 0;
> - pp->busn.end = 0xff;
> - pp->busn.flags = IORESOURCE_BUS;
> - dev_dbg(pp->dev, "failed to parse bus-range property: %d,
> using default %pR\n",
> - ret, &pp->busn);
> - }
> -
> if (!pp->dbi_base) {
> - pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
> - resource_size(&pp->cfg));
> + pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
> + resource_size(pp->cfg));
> if (!pp->dbi_base) {
> dev_err(pp->dev, "error with ioremap\n");
> return -ENOMEM;
> }
> }
>
> - pp->mem_base = pp->mem.start;
> + pp->mem_base = pp->mem->start;
>
> if (!pp->va_cfg0_base) {
> pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
> @@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
> if (pp->ops->host_init)
> pp->ops->host_init(pp);
>
> - dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
> + if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
> + != PCIBIOS_SUCCESSFUL)
> + return -EINVAL;
>
> /* program correct class for RC */
> - dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,
> PCI_CLASS_BRIDGE_PCI);
> + if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,
> PCI_CLASS_BRIDGE_PCI)
> + != PCIBIOS_SUCCESSFUL)
> + return -EINVAL;
> +
> + if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,
> &val)
> + != PCIBIOS_SUCCESSFUL)
> + return -EINVAL;
>
> - dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
> val |= PORT_LOGIC_SPEED_CHANGE;
> - dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>
> -#ifdef CONFIG_PCI_MSI
> - dw_pcie_msi_chip.dev = pp->dev;
> - dw_pci.msi_ctrl = &dw_pcie_msi_chip;
> + if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
> + != PCIBIOS_SUCCESSFUL)
> + return -EINVAL;
> +
> + bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
> + pp, &res);
> + if (!bus)
> + return -ENOMEM;
> +
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> + bus->msi = container_of(&pp->irq_domain, struct msi_controller,
> domain);
> +#else
> + bus->msi = &dw_pcie_msi_chip;
> #endif
>
> - dw_pci.nr_controllers = 1;
> - dw_pci.private_data = (void **)&pp;
> + pci_scan_child_bus(bus);
> + if (pp->ops->scan_bus)
> + pp->ops->scan_bus(pp);
>
> - pci_common_init_dev(pp->dev, &dw_pci);
> +#ifdef CONFIG_ARM
> + /* support old dtbs that incorrectly describe IRQs */
> + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
> +#endif
> +
> + pci_assign_unassigned_bus_resources(bus);
> + pci_bus_add_devices(bus);
>
> return 0;
> }
> @@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port
> *pp,
> static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
> int size, u32 *val)
> {
> - struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> + struct pcie_port *pp = bus->sysdata;
> int ret;
>
> if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
> @@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32
> devfn, int where,
> static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
> int where, int size, u32 val)
> {
> - struct pcie_port *pp = sys_to_pcie(bus->sysdata);
> + struct pcie_port *pp = bus->sysdata;
> int ret;
>
> if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
> @@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
> .write = dw_pcie_wr_conf,
> };
>
> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
> -{
> - struct pcie_port *pp;
> -
> - pp = sys_to_pcie(sys);
> -
> - if (global_io_offset < SZ_1M && pp->io_size > 0) {
> - sys->io_offset = global_io_offset - pp->io_bus_addr;
> - pci_ioremap_io(global_io_offset, pp->io_base);
> - global_io_offset += SZ_64K;
> - pci_add_resource_offset(&sys->resources, &pp->io,
> - sys->io_offset);
> - }
> -
> - sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
> - pci_add_resource_offset(&sys->resources, &pp->mem, sys-
> >mem_offset);
> - pci_add_resource(&sys->resources, &pp->busn);
> -
> - return 1;
> -}
> -
> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
> *sys)
> -{
> - struct pci_bus *bus;
> - struct pcie_port *pp = sys_to_pcie(sys);
> -
> - pp->root_bus_nr = sys->busnr;
> - bus = pci_create_root_bus(pp->dev, sys->busnr,
> - &dw_pcie_ops, sys, &sys->resources);
> - if (!bus)
> - return NULL;
> -
> - pci_scan_child_bus(bus);
> -
> - if (bus && pp->ops->scan_bus)
> - pp->ops->scan_bus(pp);
> -
> - return bus;
> -}
> -
> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> -{
> - struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
> - int irq;
> -
> - irq = of_irq_parse_and_map_pci(dev, slot, pin);
> - if (!irq)
> - irq = pp->irq;
> -
> - return irq;
> -}
> -
> -static struct hw_pci dw_pci = {
> - .setup = dw_pcie_setup,
> - .scan = dw_pcie_scan_bus,
> - .map_irq = dw_pcie_map_irq,
> -};
> -
> void dw_pcie_setup_rc(struct pcie_port *pp)
> {
> u32 val;
> diff --git a/drivers/pci/host/pcie-designware.h
> b/drivers/pci/host/pcie-designware.h
> index d0bbd27..ab78710 100644
> --- a/drivers/pci/host/pcie-designware.h
> +++ b/drivers/pci/host/pcie-designware.h
> @@ -34,7 +34,7 @@ struct pcie_port {
> u64 cfg1_mod_base;
> void __iomem *va_cfg1_base;
> u32 cfg1_size;
> - u64 io_base;
> + resource_size_t io_base;
> u64 io_mod_base;
> phys_addr_t io_bus_addr;
> u32 io_size;
> @@ -42,10 +42,10 @@ struct pcie_port {
> u64 mem_mod_base;
> phys_addr_t mem_bus_addr;
> u32 mem_size;
> - struct resource cfg;
> - struct resource io;
> - struct resource mem;
> - struct resource busn;
> + struct resource *cfg;
> + struct resource *io;
> + struct resource *mem;
> + struct resource *busn;
> int irq;
> u32 lanes;
> struct pcie_host_ops *ops;
> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-
> spear13xx.c
> index 020d788..e78ddf8 100644
> --- a/drivers/pci/host/pcie-spear13xx.c
> +++ b/drivers/pci/host/pcie-spear13xx.c
> @@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port
> *pp,
> return ret;
> }
>
> - pp->root_bus_nr = -1;
> + pp->root_bus_nr = 0;
> pp->ops = &spear13xx_pcie_host_ops;
>
> ret = dw_pcie_host_init(pp);
> --
> 1.9.1
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH v3 2/5] PCI: designware: Add ARM64 support
2015-07-01 13:29 ` Gabriele Paoloni
@ 2015-07-01 14:26 ` James Morse
[not found] ` <5593F899.6050306-5wv7dgnIgG8@public.gmane.org>
2015-07-02 1:16 ` Zhou Wang
1 sibling, 1 reply; 22+ messages in thread
From: James Morse @ 2015-07-01 14:26 UTC (permalink / raw)
To: Gabriele Paoloni, Wangzhou (B), Bjorn Helgaas, Jingoo Han,
Pratyush Anand, Arnd Bergmann, Liviu Dudau,
kishon-l0cyMroinI0@public.gmane.org,
xobs-nXMMniAx+RbQT0dZR+AlfA@public.gmane.org,
m-karicheri2-l0cyMroinI0@public.gmane.org,
Minghuan.Lian-KZfg59tc24xl57MIdRCFDg@public.gmane.org
Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Yuanzhichang,
Zhudacai, zhangjukuo, qiuzhenfa,
liguozhu-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org
Zhou Wang wrote:
> I tested this patch on D02 board of Hisilicon. It works well.
> I have compiled the driver with multi_v7_defconfig. However, I don't
> have
> ARM32 PCIe related board to do test. It will be appreciated if someone
> could
> help to test it.
>
> Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
> Signed-off-by: Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
> Signed-off-by: Gabriele Paoloni <gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
> Tested-by: Fabrice Gasnier <fabrice.gasnier-qxv4g6HH51o@public.gmane.org>
> Tested-by: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>
Tests on this new series, using the same i.MX 6Quad board, are not working.
The network card is no longer detected, and I get a lockup when removing
the root bridge and rescanning.
Partial dmesg output below. Significantly, the lines:
> [ 0.152128] PCI host bridge /soc/pcie@0x01000000 ranges:
> [ 0.152142] No bus range found for /soc/pcie@0x01000000, using [bus
00-ff]
are new.
Both series are applied to v4.1, use the same .config file, and the same dtb.
I will investigate further.
(Re-testing v2 works, so this isn't an interim hardware failure)
Thanks,
James
root@localhost:~# dmesg | grep -i pci
[ 0.126184] PCI: CLS 0 bytes, default 64
[ 0.152128] PCI host bridge /soc/pcie@0x01000000 ranges:
[ 0.152142] No bus range found for /soc/pcie@0x01000000, using [bus 00-ff]
[ 0.154183] imx6q-pcie 1ffc000.pcie: PCI host bridge to bus 0000:00
[ 0.154201] pci_bus 0000:00: root bus resource [bus 00-ff]
[ 0.154215] pci_bus 0000:00: root bus resource [???
0x01f00000-0x01f7ffff flags 0x0]
[ 0.154228] pci_bus 0000:00: root bus resource [io 0x0000-0xffff]
[ 0.154270] pci_bus 0000:00: root bus resource [mem 0x01000000-0x01efffff]
[ 0.154306] pci 0000:00:00.0: [16c3:abcd] type 01 class 0x060400
[ 0.154333] pci 0000:00:00.0: reg 0x10: [mem 0x00000000-0x000fffff]
[ 0.154352] pci 0000:00:00.0: reg 0x38: [mem 0x00000000-0x0000ffff pref]
[ 0.154377] pci 0000:00:00.0: IOMMU is currently not supported for PCI
[ 0.154429] pci 0000:00:00.0: supports D1
[ 0.154440] pci 0000:00:00.0: PME# supported from D0 D1 D3hot D3cold
[ 0.154683] PCI: bus0: Fast back to back transfers disabled
[ 0.154806] PCI: bus1: Fast back to back transfers enabled
[ 0.154884] pci 0000:00:00.0: BAR 0: assigned [mem 0x01000000-0x010fffff]
[ 0.154903] pci 0000:00:00.0: BAR 6: assigned [mem 0x01100000-0x0110ffff
pref]
[ 0.154917] pci 0000:00:00.0: PCI bridge to [bus 01]
[ 0.155145] pcieport 0000:00:00.0: Signaling PME through PCIe PME interrupt
[ 0.155161] pcie_pme 0000:00:00.0:pcie01: service driver pcie_pme loaded
[ 0.155279] aer 0000:00:00.0:pcie02: service driver aer loaded
[ 1.188840] ehci-pci: EHCI PCI platform driver
[ 1.232518] ohci-pci: OHCI PCI platform driver
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH v3 2/5] PCI: designware: Add ARM64 support
2015-07-01 13:29 ` Gabriele Paoloni
2015-07-01 14:26 ` James Morse
@ 2015-07-02 1:16 ` Zhou Wang
1 sibling, 0 replies; 22+ messages in thread
From: Zhou Wang @ 2015-07-02 1:16 UTC (permalink / raw)
To: Gabriele Paoloni
Cc: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
James Morse, Liviu Dudau, kishon@ti.com, xobs@kosagi.com,
m-karicheri2@ti.com, Minghuan.Lian@freescale.com,
linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
devicetree@vger.kernel.org, Yuanzhichang, Zhudacai, zhangjukuo,
qiuzhenfa, Liguozhu (Kenneth)
On 2015/7/1 21:29, Gabriele Paoloni wrote:
> Adding to the recipients list the authors of the drivers that depend on Synopsys Designware and that are not included
>
> Respectively:
> pci-dra7xx Kishon Vijay Abraham I <kishon@ti.com>
> pci-imx6 Sean Cross <xobs@kosagi.com>
> pci-keystone Murali Karicheri <m-karicheri2@ti.com>
> pci-layerscape Minghuan Lian <Minghuan.Lian@freescale.com>
>
> Driver Authors already included:
> pci-exynos Jingoo Han <jg1.han@samsung.com>
> pcie-spear13xx Pratyush Anand <pratyush.anand@st.com>
>
> Cheers
>
> Gab
>
Hi Gab,
Many thanks for adding the related guys.
Regards,
Zhou
>> -----Original Message-----
>> From: Wangzhou (B)
>> Sent: Wednesday, July 01, 2015 10:44 AM
>> To: Bjorn Helgaas; Jingoo Han; Pratyush Anand; Arnd Bergmann; Gabriele
>> Paoloni; James Morse; Liviu Dudau
>> Cc: linux-pci@vger.kernel.org; linux-arm-kernel@lists.infradead.org;
>> devicetree@vger.kernel.org; Yuanzhichang; Zhudacai; zhangjukuo;
>> qiuzhenfa; Liguozhu (Kenneth); Wangzhou (B)
>> Subject: [PATCH v3 2/5] PCI: designware: Add ARM64 support
>>
>> This patch tries to unify ARM32 and ARM64 PCIe in designware driver.
>> Delete
>> function dw_pcie_setup, dw_pcie_scan_bus, dw_pcie_map_irq and struct
>> hw_pci,
>> move related operations to dw_pcie_host_init. Also set pp->root_bus_nr
>> = 0 in
>> each PCIe host driver which is based on pcie-designware. This patch
>> also try
>> to use of_pci_get_host_bridge_resources for ARM32 and ARM64 according
>> to the
>> suggestion for Gabriele[1]
>>
>> I tested this patch on D02 board of Hisilicon. It works well.
>> I have compiled the driver with multi_v7_defconfig. However, I don't
>> have
>> ARM32 PCIe related board to do test. It will be appreciated if someone
>> could
>> help to test it.
>>
>> Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
>> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Gabriele Paoloni <gabriele.paoloni@huawei.com>
>> Tested-by: Fabrice Gasnier <fabrice.gasnier@st.com>
>> Tested-by: James Morse <james.morse@arm.com>
>>
>> [1] http://www.spinics.net/lists/linux-pci/msg42194.html
>> ---
>> drivers/pci/host/pci-dra7xx.c | 1 +
>> drivers/pci/host/pci-exynos.c | 2 +-
>> drivers/pci/host/pci-imx6.c | 2 +-
>> drivers/pci/host/pci-keystone-dw.c | 2 +-
>> drivers/pci/host/pci-keystone.c | 2 +-
>> drivers/pci/host/pci-layerscape.c | 2 +-
>> drivers/pci/host/pcie-designware.c | 242 +++++++++++++++--------------
>> --------
>> drivers/pci/host/pcie-designware.h | 10 +-
>> drivers/pci/host/pcie-spear13xx.c | 2 +-
>> 9 files changed, 110 insertions(+), 155 deletions(-)
>>
>> diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-
>> dra7xx.c
>> index 2d57e19..5c8b6ab 100644
>> --- a/drivers/pci/host/pci-dra7xx.c
>> +++ b/drivers/pci/host/pci-dra7xx.c
>> @@ -280,6 +280,7 @@ static int __init dra7xx_add_pcie_port(struct
>> dra7xx_pcie *dra7xx,
>>
>> pp = &dra7xx->pp;
>> pp->dev = dev;
>> + pp->root_bus_nr = 0;
>> pp->ops = &dra7xx_pcie_host_ops;
>>
>> pp->irq = platform_get_irq(pdev, 1);
>> diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-
>> exynos.c
>> index c139237..4b6db6c 100644
>> --- a/drivers/pci/host/pci-exynos.c
>> +++ b/drivers/pci/host/pci-exynos.c
>> @@ -534,7 +534,7 @@ static int __init exynos_add_pcie_port(struct
>> pcie_port *pp,
>> }
>> }
>>
>> - pp->root_bus_nr = -1;
>> + pp->root_bus_nr = 0;
>> pp->ops = &exynos_pcie_host_ops;
>>
>> ret = dw_pcie_host_init(pp);
>> diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
>> index fdb9536..c4a80c5 100644
>> --- a/drivers/pci/host/pci-imx6.c
>> +++ b/drivers/pci/host/pci-imx6.c
>> @@ -541,7 +541,7 @@ static int __init imx6_add_pcie_port(struct
>> pcie_port *pp,
>> }
>> }
>>
>> - pp->root_bus_nr = -1;
>> + pp->root_bus_nr = 0;
>> pp->ops = &imx6_pcie_host_ops;
>>
>> ret = dw_pcie_host_init(pp);
>> diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-
>> keystone-dw.c
>> index f34892e..b1e4135 100644
>> --- a/drivers/pci/host/pci-keystone-dw.c
>> +++ b/drivers/pci/host/pci-keystone-dw.c
>> @@ -327,7 +327,7 @@ static void ks_dw_pcie_clear_dbi_mode(void __iomem
>> *reg_virt)
>> void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
>> {
>> struct pcie_port *pp = &ks_pcie->pp;
>> - u32 start = pp->mem.start, end = pp->mem.end;
>> + u32 start = pp->mem->start, end = pp->mem->end;
>> int i, tr_size;
>>
>> /* Disable BARs for inbound access */
>> diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-
>> keystone.c
>> index 75333b0..df91f5e 100644
>> --- a/drivers/pci/host/pci-keystone.c
>> +++ b/drivers/pci/host/pci-keystone.c
>> @@ -312,7 +312,7 @@ static int __init ks_add_pcie_port(struct
>> keystone_pcie *ks_pcie,
>> return ret;
>> }
>>
>> - pp->root_bus_nr = -1;
>> + pp->root_bus_nr = 0;
>> pp->ops = &keystone_pcie_host_ops;
>> ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
>> if (ret) {
>> diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-
>> layerscape.c
>> index 4a6e62f..5c7a9c4 100644
>> --- a/drivers/pci/host/pci-layerscape.c
>> +++ b/drivers/pci/host/pci-layerscape.c
>> @@ -101,7 +101,7 @@ static int ls_add_pcie_port(struct ls_pcie *pcie)
>> pp = &pcie->pp;
>> pp->dev = pcie->dev;
>> pp->dbi_base = pcie->dbi;
>> - pp->root_bus_nr = -1;
>> + pp->root_bus_nr = 0;
>> pp->ops = &ls_pcie_host_ops;
>>
>> ret = dw_pcie_host_init(pp);
>> diff --git a/drivers/pci/host/pcie-designware.c
>> b/drivers/pci/host/pcie-designware.c
>> index 2e9f84f..844febee 100644
>> --- a/drivers/pci/host/pcie-designware.c
>> +++ b/drivers/pci/host/pcie-designware.c
>> @@ -11,6 +11,7 @@
>> * published by the Free Software Foundation.
>> */
>>
>> +#include <linux/hardirq.h>
>> #include <linux/irq.h>
>> #include <linux/irqdomain.h>
>> #include <linux/kernel.h>
>> @@ -67,16 +68,7 @@
>> #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
>> #define PCIE_ATU_UPPER_TARGET 0x91C
>>
>> -static struct hw_pci dw_pci;
>> -
>> -static unsigned long global_io_offset;
>> -
>> -static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)
>> -{
>> - BUG_ON(!sys->private_data);
>> -
>> - return sys->private_data;
>> -}
>> +static struct pci_ops dw_pcie_ops;
>>
>> int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)
>> {
>> @@ -238,7 +230,7 @@ static void dw_pcie_msi_set_irq(struct pcie_port
>> *pp, int irq)
>> static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
>> {
>> int irq, pos0, i;
>> - struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata);
>> + struct pcie_port *pp = desc->dev->bus->sysdata;
>>
>> pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
>> order_base_2(no_irqs));
>> @@ -281,7 +273,7 @@ static int dw_msi_setup_irq(struct msi_controller
>> *chip, struct pci_dev *pdev,
>> {
>> int irq, pos;
>> struct msi_msg msg;
>> - struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata);
>> + struct pcie_port *pp = pdev->bus->sysdata;
>>
>> if (desc->msi_attrib.is_msix)
>> return -EINVAL;
>> @@ -310,7 +302,7 @@ static void dw_msi_teardown_irq(struct
>> msi_controller *chip, unsigned int irq)
>> {
>> struct irq_data *data = irq_get_irq_data(irq);
>> struct msi_desc *msi = irq_data_get_msi(data);
>> - struct pcie_port *pp = sys_to_pcie(msi->dev->bus->sysdata);
>> + struct pcie_port *pp = msi->dev->bus->sysdata;
>>
>> clear_irq_range(pp, irq, 1, data->hwirq);
>> }
>> @@ -342,16 +334,24 @@ static const struct irq_domain_ops msi_domain_ops
>> = {
>> .map = dw_pcie_msi_map,
>> };
>>
>> -int dw_pcie_host_init(struct pcie_port *pp)
>> +int __init dw_pcie_host_init(struct pcie_port *pp)
>> {
>> struct device_node *np = pp->dev->of_node;
>> struct platform_device *pdev = to_platform_device(pp->dev);
>> - struct of_pci_range range;
>> - struct of_pci_range_parser parser;
>> + struct pci_bus *bus;
>> struct resource *cfg_res;
>> + LIST_HEAD(res);
>> u32 val, na, ns;
>> const __be32 *addrp;
>> int i, index, ret;
>> + int rlen;
>> + struct resource_entry *win;
>> + const __be32 *parser_range_end = of_get_property(np, "ranges",
>> &rlen);
>> +
>> + if (parser_range_end == NULL)
>> + return -ENOENT;
>> + parser_range_end += rlen/sizeof(__be32);
>> +
>>
>> /* Find the address cell size and the number of cells in order to
>> get
>> * the untranslated address.
>> @@ -375,78 +375,67 @@ int dw_pcie_host_init(struct pcie_port *pp)
>> dev_err(pp->dev, "missing *config* reg space\n");
>> }
>>
>> - if (of_pci_range_parser_init(&parser, np)) {
>> - dev_err(pp->dev, "missing ranges property\n");
>> - return -EINVAL;
>> - }
>> + ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp-
>>> io_base);
>> + if (ret)
>> + return ret;
>>
>> /* Get the I/O and memory ranges from DT */
>> - for_each_of_pci_range(&parser, &range) {
>> - unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
>> -
>> - if (restype == IORESOURCE_IO) {
>> - of_pci_range_to_resource(&range, np, &pp->io);
>> - pp->io.name = "I/O";
>> - pp->io.start = max_t(resource_size_t,
>> - PCIBIOS_MIN_IO,
>> - range.pci_addr + global_io_offset);
>> - pp->io.end = min_t(resource_size_t,
>> - IO_SPACE_LIMIT,
>> - range.pci_addr + range.size
>> - + global_io_offset - 1);
>> - pp->io_size = resource_size(&pp->io);
>> - pp->io_bus_addr = range.pci_addr;
>> - pp->io_base = range.cpu_addr;
>> -
>> - /* Find the untranslated IO space address */
>> - pp->io_mod_base = of_read_number(parser.range -
>> - parser.np + na, ns);
>> - }
>> - if (restype == IORESOURCE_MEM) {
>> - of_pci_range_to_resource(&range, np, &pp->mem);
>> - pp->mem.name = "MEM";
>> - pp->mem_size = resource_size(&pp->mem);
>> - pp->mem_bus_addr = range.pci_addr;
>> -
>> - /* Find the untranslated MEM space address */
>> - pp->mem_mod_base = of_read_number(parser.range -
>> - parser.np + na, ns);
>> - }
>> - if (restype == 0) {
>> - of_pci_range_to_resource(&range, np, &pp->cfg);
>> - pp->cfg0_size = resource_size(&pp->cfg)/2;
>> - pp->cfg1_size = resource_size(&pp->cfg)/2;
>> - pp->cfg0_base = pp->cfg.start;
>> - pp->cfg1_base = pp->cfg.start + pp->cfg0_size;
>> + resource_list_for_each_entry(win, &res) {
>> + switch (resource_type(win->res)) {
>> + case IORESOURCE_IO:
>> + pp->io = win->res;
>> + pp->io->name = "I/O";
>> + pp->io_size = resource_size(pp->io);
>> + pp->io_bus_addr = pp->io->start - win->offset;
>> + /* magic 5 below comes from magic na and ns in
>> + * of_pci_range_parser_init() */
>> + pp->io_mod_base = of_read_number(parser_range_end -
>> + of_n_addr_cells(np) - 5 + na, ns);
>> + ret = pci_remap_iospace(pp->io, pp->io_base);
>> + if (ret) {
>> + dev_warn(pp->dev, "error %d: failed to map
>> resource %pR\n",
>> + ret, pp->io);
>> + continue;
>> + }
>> + break;
>> + case IORESOURCE_MEM:
>> + pp->mem = win->res;
>> + pp->mem->name = "MEM";
>> + pp->mem_size = resource_size(pp->mem);
>> + pp->mem_bus_addr = pp->mem->start - win->offset;
>> + pp->mem_mod_base = of_read_number(parser_range_end -
>> + of_n_addr_cells(np) - 5 + na, ns);
>> + break;
>> + case 0:
>> + pp->cfg = win->res;
>> + pp->cfg0_size = resource_size(pp->cfg)/2;
>> + pp->cfg1_size = resource_size(pp->cfg)/2;
>> + pp->cfg0_base = pp->cfg->start;
>> + pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
>>
>> /* Find the untranslated configuration space address
>> */
>> - pp->cfg0_mod_base = of_read_number(parser.range -
>> - parser.np + na, ns);
>> - pp->cfg1_mod_base = pp->cfg0_mod_base +
>> - pp->cfg0_size;
>> + pp->cfg0_mod_base = of_read_number(parser_range_end -
>> + of_n_addr_cells(np) - 5 + na, ns);
>> + pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
>> + break;
>> + case IORESOURCE_BUS:
>> + pp->busn = win->res;
>> + break;
>> + default:
>> + continue;
>> }
>> }
>>
>> - ret = of_pci_parse_bus_range(np, &pp->busn);
>> - if (ret < 0) {
>> - pp->busn.name = np->name;
>> - pp->busn.start = 0;
>> - pp->busn.end = 0xff;
>> - pp->busn.flags = IORESOURCE_BUS;
>> - dev_dbg(pp->dev, "failed to parse bus-range property: %d,
>> using default %pR\n",
>> - ret, &pp->busn);
>> - }
>> -
>> if (!pp->dbi_base) {
>> - pp->dbi_base = devm_ioremap(pp->dev, pp->cfg.start,
>> - resource_size(&pp->cfg));
>> + pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
>> + resource_size(pp->cfg));
>> if (!pp->dbi_base) {
>> dev_err(pp->dev, "error with ioremap\n");
>> return -ENOMEM;
>> }
>> }
>>
>> - pp->mem_base = pp->mem.start;
>> + pp->mem_base = pp->mem->start;
>>
>> if (!pp->va_cfg0_base) {
>> pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
>> @@ -493,24 +482,47 @@ int dw_pcie_host_init(struct pcie_port *pp)
>> if (pp->ops->host_init)
>> pp->ops->host_init(pp);
>>
>> - dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
>> + if (dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0)
>> + != PCIBIOS_SUCCESSFUL)
>> + return -EINVAL;
>>
>> /* program correct class for RC */
>> - dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,
>> PCI_CLASS_BRIDGE_PCI);
>> + if (dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2,
>> PCI_CLASS_BRIDGE_PCI)
>> + != PCIBIOS_SUCCESSFUL)
>> + return -EINVAL;
>> +
>> + if (dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4,
>> &val)
>> + != PCIBIOS_SUCCESSFUL)
>> + return -EINVAL;
>>
>> - dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
>> val |= PORT_LOGIC_SPEED_CHANGE;
>> - dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
>>
>> -#ifdef CONFIG_PCI_MSI
>> - dw_pcie_msi_chip.dev = pp->dev;
>> - dw_pci.msi_ctrl = &dw_pcie_msi_chip;
>> + if (dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val)
>> + != PCIBIOS_SUCCESSFUL)
>> + return -EINVAL;
>> +
>> + bus = pci_create_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
>> + pp, &res);
>> + if (!bus)
>> + return -ENOMEM;
>> +
>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> + bus->msi = container_of(&pp->irq_domain, struct msi_controller,
>> domain);
>> +#else
>> + bus->msi = &dw_pcie_msi_chip;
>> #endif
>>
>> - dw_pci.nr_controllers = 1;
>> - dw_pci.private_data = (void **)&pp;
>> + pci_scan_child_bus(bus);
>> + if (pp->ops->scan_bus)
>> + pp->ops->scan_bus(pp);
>>
>> - pci_common_init_dev(pp->dev, &dw_pci);
>> +#ifdef CONFIG_ARM
>> + /* support old dtbs that incorrectly describe IRQs */
>> + pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
>> +#endif
>> +
>> + pci_assign_unassigned_bus_resources(bus);
>> + pci_bus_add_devices(bus);
>>
>> return 0;
>> }
>> @@ -653,7 +665,7 @@ static int dw_pcie_valid_config(struct pcie_port
>> *pp,
>> static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
>> int size, u32 *val)
>> {
>> - struct pcie_port *pp = sys_to_pcie(bus->sysdata);
>> + struct pcie_port *pp = bus->sysdata;
>> int ret;
>>
>> if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
>> @@ -677,7 +689,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32
>> devfn, int where,
>> static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
>> int where, int size, u32 val)
>> {
>> - struct pcie_port *pp = sys_to_pcie(bus->sysdata);
>> + struct pcie_port *pp = bus->sysdata;
>> int ret;
>>
>> if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
>> @@ -701,64 +713,6 @@ static struct pci_ops dw_pcie_ops = {
>> .write = dw_pcie_wr_conf,
>> };
>>
>> -static int dw_pcie_setup(int nr, struct pci_sys_data *sys)
>> -{
>> - struct pcie_port *pp;
>> -
>> - pp = sys_to_pcie(sys);
>> -
>> - if (global_io_offset < SZ_1M && pp->io_size > 0) {
>> - sys->io_offset = global_io_offset - pp->io_bus_addr;
>> - pci_ioremap_io(global_io_offset, pp->io_base);
>> - global_io_offset += SZ_64K;
>> - pci_add_resource_offset(&sys->resources, &pp->io,
>> - sys->io_offset);
>> - }
>> -
>> - sys->mem_offset = pp->mem.start - pp->mem_bus_addr;
>> - pci_add_resource_offset(&sys->resources, &pp->mem, sys-
>>> mem_offset);
>> - pci_add_resource(&sys->resources, &pp->busn);
>> -
>> - return 1;
>> -}
>> -
>> -static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data
>> *sys)
>> -{
>> - struct pci_bus *bus;
>> - struct pcie_port *pp = sys_to_pcie(sys);
>> -
>> - pp->root_bus_nr = sys->busnr;
>> - bus = pci_create_root_bus(pp->dev, sys->busnr,
>> - &dw_pcie_ops, sys, &sys->resources);
>> - if (!bus)
>> - return NULL;
>> -
>> - pci_scan_child_bus(bus);
>> -
>> - if (bus && pp->ops->scan_bus)
>> - pp->ops->scan_bus(pp);
>> -
>> - return bus;
>> -}
>> -
>> -static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>> -{
>> - struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata);
>> - int irq;
>> -
>> - irq = of_irq_parse_and_map_pci(dev, slot, pin);
>> - if (!irq)
>> - irq = pp->irq;
>> -
>> - return irq;
>> -}
>> -
>> -static struct hw_pci dw_pci = {
>> - .setup = dw_pcie_setup,
>> - .scan = dw_pcie_scan_bus,
>> - .map_irq = dw_pcie_map_irq,
>> -};
>> -
>> void dw_pcie_setup_rc(struct pcie_port *pp)
>> {
>> u32 val;
>> diff --git a/drivers/pci/host/pcie-designware.h
>> b/drivers/pci/host/pcie-designware.h
>> index d0bbd27..ab78710 100644
>> --- a/drivers/pci/host/pcie-designware.h
>> +++ b/drivers/pci/host/pcie-designware.h
>> @@ -34,7 +34,7 @@ struct pcie_port {
>> u64 cfg1_mod_base;
>> void __iomem *va_cfg1_base;
>> u32 cfg1_size;
>> - u64 io_base;
>> + resource_size_t io_base;
>> u64 io_mod_base;
>> phys_addr_t io_bus_addr;
>> u32 io_size;
>> @@ -42,10 +42,10 @@ struct pcie_port {
>> u64 mem_mod_base;
>> phys_addr_t mem_bus_addr;
>> u32 mem_size;
>> - struct resource cfg;
>> - struct resource io;
>> - struct resource mem;
>> - struct resource busn;
>> + struct resource *cfg;
>> + struct resource *io;
>> + struct resource *mem;
>> + struct resource *busn;
>> int irq;
>> u32 lanes;
>> struct pcie_host_ops *ops;
>> diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-
>> spear13xx.c
>> index 020d788..e78ddf8 100644
>> --- a/drivers/pci/host/pcie-spear13xx.c
>> +++ b/drivers/pci/host/pcie-spear13xx.c
>> @@ -287,7 +287,7 @@ static int spear13xx_add_pcie_port(struct pcie_port
>> *pp,
>> return ret;
>> }
>>
>> - pp->root_bus_nr = -1;
>> + pp->root_bus_nr = 0;
>> pp->ops = &spear13xx_pcie_host_ops;
>>
>> ret = dw_pcie_host_init(pp);
>> --
>> 1.9.1
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v3 3/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05
2015-07-01 9:43 [PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
2015-07-01 9:43 ` [PATCH v3 1/5] ARM/PCI: remove align_resource callback in pcibios_align_resource Zhou Wang
2015-07-01 9:43 ` [PATCH v3 2/5] PCI: designware: Add ARM64 support Zhou Wang
@ 2015-07-01 9:43 ` Zhou Wang
[not found] ` <1435743817-19083-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
2015-07-01 9:43 ` [PATCH v3 5/5] MAINTAINERS: Add pcie-hisi maintainer Zhou Wang
4 siblings, 0 replies; 22+ messages in thread
From: Zhou Wang @ 2015-07-01 9:43 UTC (permalink / raw)
To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni, James Morse, Liviu Dudau
Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
zhangjukuo, qiuzhenfa, liguozhu, Zhou Wang
This patch adds PCIe host support for Hisilicon Soc Hip05.
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
drivers/pci/host/Kconfig | 5 +
drivers/pci/host/Makefile | 1 +
drivers/pci/host/pcie-hisi.c | 258 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 264 insertions(+)
create mode 100644 drivers/pci/host/pcie-hisi.c
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 1dfb567..486d822 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -125,4 +125,9 @@ config PCIE_IPROC_PLATFORM
Say Y here if you want to use the Broadcom iProc PCIe controller
through the generic platform bus interface
+config PCI_HISI
+ depends on OF && ARM64
+ bool "Hisilicon Soc HIP05 PCIe controller"
+ select PCIE_DW
+
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index f733b4e..562142e 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
+obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
new file mode 100644
index 0000000..8328add
--- /dev/null
+++ b/drivers/pci/host/pcie-hisi.c
@@ -0,0 +1,258 @@
+/*
+ * PCIe host controller driver for Hisilicon Hip05 SoCs
+ *
+ * Copyright (C) 2015 Hisilicon Co., Ltd. http://www.hisilicon.com
+ *
+ * Author: Zhou Wang <wangzhou1@hisilicon.com>
+ * Dacai Zhu <zhudacai@hisilicon.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/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_pci.h>
+#include <linux/platform_device.h>
+
+#include "pcie-designware.h"
+
+#define PCIE_SUBCTRL_MODE_REG 0x2800
+#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
+#define PCIE_SLV_DBI_MODE 0x0
+#define PCIE_SLV_SYSCTRL_MODE 0x1
+#define PCIE_SLV_CONTENT_MODE 0x2
+#define PCIE_SLV_MSI_ASID 0x10
+#define PCIE_LTSSM_LINKUP_STATE 0x11
+#define PCIE_LTSSM_STATE_MASK 0x3F
+#define PCIE_MSI_ASID_ENABLE (0x1 << 12)
+#define PCIE_MSI_ASID_VALUE (0x1 << 16)
+#define PCIE_MSI_TRANS_ENABLE (0x1 << 12)
+#define PCIE_MSI_TRANS_REG 0x1c8
+#define PCIE_MSI_LOW_ADDRESS 0x1b4
+#define PCIE_MSI_HIGH_ADDRESS 0x1c4
+#define PCIE_MSI_ADDRESS_VAL 0xb7010040
+
+#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
+
+struct hisi_pcie {
+ void __iomem *subctrl_base;
+ void __iomem *reg_base;
+ struct msi_controller *msi;
+ u32 port_id;
+ struct pcie_port pp;
+};
+
+static inline void hisi_pcie_subctrl_writel(struct hisi_pcie *pcie,
+ u32 val, u32 reg)
+{
+ writel(val, pcie->subctrl_base + reg);
+}
+
+static inline u32 hisi_pcie_subctrl_readl(struct hisi_pcie *pcie, u32 reg)
+{
+ return readl(pcie->subctrl_base + reg);
+}
+
+static inline void hisi_pcie_apb_writel(struct hisi_pcie *pcie,
+ u32 val, u32 reg)
+{
+ writel(val, pcie->reg_base + reg);
+}
+
+static inline u32 hisi_pcie_apb_readl(struct hisi_pcie *pcie, u32 reg)
+{
+ return readl(pcie->reg_base + reg);
+}
+
+/*
+ * Change mode to indicate the same reg_base to base of PCIe host configure
+ * registers, base of RC configure space or base of vmid/asid context table
+ */
+static void hisi_pcie_change_apb_mode(struct hisi_pcie *pcie, u32 mode)
+{
+ u32 val;
+ u32 bit_mask;
+ u32 bit_shift;
+ u32 port_id = pcie->port_id;
+ u32 reg = PCIE_SUBCTRL_MODE_REG + 0x100 * port_id;
+
+ if ((port_id == 1) || (port_id == 2)) {
+ bit_mask = 0xc;
+ bit_shift = 0x2;
+ } else {
+ bit_mask = 0x6;
+ bit_shift = 0x1;
+ }
+
+ val = hisi_pcie_subctrl_readl(pcie, reg);
+ val = (val & (~bit_mask)) | (mode << bit_shift);
+ hisi_pcie_subctrl_writel(pcie, val, reg);
+}
+
+/* Configure vmid/asid table in PCIe host */
+static void hisi_pcie_config_context(struct hisi_pcie *pcie)
+{
+ int i;
+
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_CONTENT_MODE);
+
+ /*
+ * init vmid and asid tables for all PCIes device as 0
+ * vmid table: 0 ~ 0x3ff, asid table: 0x400 ~ 0x7ff
+ */
+ for (i = 0; i < 0x800; i++)
+ hisi_pcie_apb_writel(pcie, 0x0, i * 4);
+
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_SYSCTRL_MODE);
+
+ hisi_pcie_apb_writel(pcie, PCIE_MSI_ADDRESS_VAL, PCIE_MSI_LOW_ADDRESS);
+ hisi_pcie_apb_writel(pcie, 0x0, PCIE_MSI_HIGH_ADDRESS);
+ hisi_pcie_apb_writel(pcie, PCIE_MSI_ASID_ENABLE | PCIE_MSI_ASID_VALUE,
+ PCIE_SLV_MSI_ASID);
+ hisi_pcie_apb_writel(pcie, PCIE_MSI_TRANS_ENABLE, PCIE_MSI_TRANS_REG);
+
+ hisi_pcie_change_apb_mode(pcie, PCIE_SLV_DBI_MODE);
+}
+
+static int hisi_pcie_link_up(struct pcie_port *pp)
+{
+ u32 val;
+
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ val = hisi_pcie_subctrl_readl(hisi_pcie, PCIE_SUBCTRL_SYS_STATE4_REG +
+ 0x100 * hisi_pcie->port_id);
+
+ return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
+}
+
+static
+int hisi_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
+{
+ struct device_node *msi_node;
+ struct irq_domain *irq_domain;
+ struct device_node *np = pp->dev->of_node;
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ msi_node = of_parse_phandle(np, "msi-parent", 0);
+ if (!msi_node) {
+ pr_err("failed to find msi-parent\n");
+ return -ENODEV;
+ }
+
+ irq_domain = irq_find_host(msi_node);
+ if (!irq_domain) {
+ pr_err("failed to find irq domain\n");
+ return -ENODEV;
+ }
+
+ pp->irq_domain = irq_domain;
+
+ return 0;
+}
+
+static struct pcie_host_ops hisi_pcie_host_ops = {
+ .link_up = hisi_pcie_link_up,
+ .msi_host_init = hisi_pcie_msi_host_init,
+};
+
+static int __init hisi_add_pcie_port(struct pcie_port *pp,
+ struct platform_device *pdev)
+{
+ int ret;
+ u32 port_id;
+ struct resource busn;
+
+ struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
+
+ if (of_property_read_u32(pdev->dev.of_node, "port-id", &port_id)) {
+ dev_err(&pdev->dev, "failed to read port-id\n");
+ return -EINVAL;
+ }
+ if (port_id > 3) {
+ dev_err(&pdev->dev, "Invalid port-id\n");
+ return -EINVAL;
+ }
+
+ hisi_pcie->port_id = port_id;
+
+ if (of_pci_parse_bus_range(pdev->dev.of_node, &busn)) {
+ dev_err(&pdev->dev, "failed to parse bus-ranges\n");
+ return -EINVAL;
+ }
+
+ pp->root_bus_nr = busn.start;
+ pp->ops = &hisi_pcie_host_ops;
+
+ hisi_pcie_config_context(hisi_pcie);
+
+ ret = dw_pcie_host_init(pp);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to initialize host\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init hisi_pcie_probe(struct platform_device *pdev)
+{
+ struct hisi_pcie *hisi_pcie;
+ struct pcie_port *pp;
+ struct resource *reg;
+ struct resource *subctrl;
+ int ret;
+
+ hisi_pcie = devm_kzalloc(&pdev->dev, sizeof(*hisi_pcie), GFP_KERNEL);
+ if (!hisi_pcie)
+ return -ENOMEM;
+
+ pp = &hisi_pcie->pp;
+ pp->dev = &pdev->dev;
+
+ subctrl = platform_get_resource_byname(pdev, IORESOURCE_MEM, "subctrl");
+ hisi_pcie->subctrl_base = devm_ioremap_nocache(&pdev->dev,
+ subctrl->start, resource_size(subctrl));
+ if (IS_ERR(hisi_pcie->subctrl_base)) {
+ dev_err(pp->dev, "cannot get subctrl base\n");
+ return PTR_ERR(hisi_pcie->subctrl_base);
+ }
+
+ reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
+ hisi_pcie->reg_base = devm_ioremap_resource(&pdev->dev, reg);
+ if (IS_ERR(hisi_pcie->reg_base)) {
+ dev_err(pp->dev, "cannot get reg base\n");
+ return PTR_ERR(hisi_pcie->reg_base);
+ }
+
+ hisi_pcie->pp.dbi_base = hisi_pcie->reg_base;
+
+ ret = hisi_add_pcie_port(pp, pdev);
+ if (ret < 0)
+ return ret;
+
+ platform_set_drvdata(pdev, hisi_pcie);
+
+ return ret;
+}
+
+static const struct of_device_id hisi_pcie_of_match[] = {
+ {.compatible = "hisilicon,hip05-pcie",},
+ {},
+};
+
+MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
+
+static struct platform_driver hisi_pcie_driver = {
+ .probe = hisi_pcie_probe,
+ .driver = {
+ .name = "hisi-pcie",
+ .owner = THIS_MODULE,
+ .of_match_table = hisi_pcie_of_match,
+ },
+};
+
+module_platform_driver(hisi_pcie_driver);
+
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread[parent not found: <1435743817-19083-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>]
* [PATCH v3 4/5] Documentation: DT: Add Hisilicon PCIe host binding
[not found] ` <1435743817-19083-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
@ 2015-07-01 9:43 ` Zhou Wang
0 siblings, 0 replies; 22+ messages in thread
From: Zhou Wang @ 2015-07-01 9:43 UTC (permalink / raw)
To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni-hv44wF8Li93QT0dZR+AlfA, James Morse, Liviu Dudau
Cc: linux-pci-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA,
yuanzhichang-C8/M+/jPZTeaMJb+Lgu22Q,
zhudacai-C8/M+/jPZTeaMJb+Lgu22Q,
zhangjukuo-hv44wF8Li93QT0dZR+AlfA,
qiuzhenfa-C8/M+/jPZTeaMJb+Lgu22Q, liguozhu-C8/M+/jPZTeaMJb+Lgu22Q,
Zhou Wang
This patch adds related DTS binding document for Hisilicon PCIe host driver.
Signed-off-by: Zhou Wang <wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
---
.../devicetree/bindings/pci/hisilicon-pcie.txt | 46 ++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
new file mode 100644
index 0000000..6c9b827
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -0,0 +1,46 @@
+Hisilicon PCIe host bridge DT description
+
+Hisilicon PCIe host controller is based on Designware PCI core.
+It shares common functions with PCIe Designware core driver and inherits
+common properties defined in
+Documentation/devicetree/bindings/pci/designware-pci.txt.
+
+Additional properties are described here:
+
+Required properties:
+- compatible: Should contain "hisilicon,hip05-pcie".
+- reg: Should contain rc_dbi, subctrl, config registers location and length.
+- reg-names: Must include the following entries:
+ "rc_dbi": controller configuration registers;
+ "subctrl": whole PCIe hosts configuration registers;
+ "config": PCIe configuration space registers.
+- msi-parent: Should be its_pcie which is an its receiving MSI interrupts.
+- port-id: Should be 0, 1, 2 or 3.
+
+Optional properties:
+- status: Either "ok" or "disabled".
+- dma-coherent: Present if dma operations are coherent.
+
+Example:
+ pcie@0xb0080000 {
+ compatible = "hisilicon,hip05-pcie", "snps,dw-pcie";
+ reg = <0 0xb0080000 0 0x10000>, <0 0xb0000000 0 0x10000>,
+ <0x220 0x00000000 0 0x2000>;
+ reg-names = "rc_dbi", "subctrl", "config";
+ bus-range = <0 15>;
+ msi-parent = <&its_pcie>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ dma-coherent;
+ ranges = <0x82000000 0 0x00000000 0x220 0x00000000 0 0x10000000>;
+ num-lanes = <8>;
+ port-id = <1>;
+ #interrupts-cells = <1>;
+ interrupts-map-mask = <0xf800 0 0 7>;
+ interrupts-map = <0x0 0 0 1 &mbigen_pcie 1 10
+ 0x0 0 0 2 &mbigen_pcie 2 11
+ 0x0 0 0 3 &mbigen_pcie 3 12
+ 0x0 0 0 4 &mbigen_pcie 4 13>;
+ status = "ok";
+ };
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v3 5/5] MAINTAINERS: Add pcie-hisi maintainer
2015-07-01 9:43 [PATCH v3 0/5] PCI: hisi: Add PCIe host support for Hisilicon Soc Hip05 Zhou Wang
` (3 preceding siblings ...)
[not found] ` <1435743817-19083-1-git-send-email-wangzhou1-C8/M+/jPZTeaMJb+Lgu22Q@public.gmane.org>
@ 2015-07-01 9:43 ` Zhou Wang
4 siblings, 0 replies; 22+ messages in thread
From: Zhou Wang @ 2015-07-01 9:43 UTC (permalink / raw)
To: Bjorn Helgaas, Jingoo Han, Pratyush Anand, Arnd Bergmann,
gabriele.paoloni, James Morse, Liviu Dudau
Cc: linux-pci, linux-arm-kernel, devicetree, yuanzhichang, zhudacai,
zhangjukuo, qiuzhenfa, liguozhu, Zhou Wang
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
---
MAINTAINERS | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index d8afd29..3f083d0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7594,6 +7594,13 @@ L: linux-pci@vger.kernel.org
S: Maintained
F: drivers/pci/host/*spear*
+PCIE DRIVER FOR HISILICON
+M: Zhou Wang <wangzhou1@hisilicon.com>
+L: linux-pci@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+F: drivers/pci/host/pcie-hisi.c
+
PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: linux-pcmcia@lists.infradead.org
--
1.9.1
^ permalink raw reply related [flat|nested] 22+ messages in thread