2020-07-21 14:18:28

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 0/5] MIPS: Loongson64: Process ISA Node in DeviceTree

Hi,

This series convert reservation of Loongson64 Logic PIO into DeviceTree based
method.

It can be used to replace Huacai's
"MIPS: Loongson64: Reserve legacy MMIO space according to bridge type".

Thanks.

v2:
- Address Rob and Huacai's review comments.

Jiaxun Yang (5):
of_address: Add bus type match for pci ranges parser
MIPS: Loongson64: Process ISA Node in DeviceTree
MIPS: Loongson64: Enlarge IO_SPACE_LIMIT
MIPS: Loongson64: DTS: Fix ISA range for RS780E PCH
MIPS: Loongson64: Add ISA node for LS7A PCH

arch/mips/boot/dts/loongson/ls7a-pch.dtsi | 7 ++
arch/mips/boot/dts/loongson/rs780e-pch.dtsi | 2 +-
arch/mips/include/asm/io.h | 3 +-
.../mips/include/asm/mach-loongson64/spaces.h | 3 +-
arch/mips/loongson64/init.c | 88 +++++++++++++------
drivers/of/address.c | 27 +++---
include/linux/of_address.h | 5 ++
7 files changed, 94 insertions(+), 41 deletions(-)

--
2.28.0.rc1


2020-07-21 14:19:10

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 1/5] of_address: Add bus type match for pci ranges parser

So the parser can be used to parse range property of ISA bus.

As they're all using PCI-like method of range property, there is no need
start a new parser.

Signed-off-by: Jiaxun Yang <[email protected]>

--
v2: Drop useless check, fix some na for bus_addr
add define of of_range_parser_init according to
Rob's suggestion.
---
drivers/of/address.c | 27 +++++++++++++++------------
include/linux/of_address.h | 5 +++++
2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index 8eea3f6e29a4..7406636cea87 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -698,9 +698,10 @@ static int parser_init(struct of_pci_range_parser *parser,

parser->node = node;
parser->pna = of_n_addr_cells(node);
- parser->na = of_bus_n_addr_cells(node);
- parser->ns = of_bus_n_size_cells(node);
parser->dma = !strcmp(name, "dma-ranges");
+ parser->bus = of_match_bus(node);
+
+ parser->bus->count_cells(parser->node, &parser->na, &parser->ns);

parser->range = of_get_property(node, name, &rlen);
if (parser->range == NULL)
@@ -732,6 +733,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
int na = parser->na;
int ns = parser->ns;
int np = parser->pna + na + ns;
+ int busflag_na = 0;

if (!range)
return NULL;
@@ -739,12 +741,14 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
if (!parser->range || parser->range + np > parser->end)
return NULL;

- if (parser->na == 3)
- range->flags = of_bus_pci_get_flags(parser->range);
- else
- range->flags = 0;
+ range->flags = parser->bus->get_flags(parser->range);
+
+ /* PCI and ISA have a extra cell for resource flags */
+ if (strcmp(parser->bus->name, "pci") ||
+ strcmp(parser->bus->name, "isa"))
+ busflag_na = 1;

- range->pci_addr = of_read_number(parser->range, na);
+ range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);

if (parser->dma)
range->cpu_addr = of_translate_dma_address(parser->node,
@@ -759,11 +763,10 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
/* Now consume following elements while they are contiguous */
while (parser->range + np <= parser->end) {
u32 flags = 0;
- u64 pci_addr, cpu_addr, size;
+ u64 bus_addr, cpu_addr, size;

- if (parser->na == 3)
- flags = of_bus_pci_get_flags(parser->range);
- pci_addr = of_read_number(parser->range, na);
+ flags = parser->bus->get_flags(parser->range);
+ bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
if (parser->dma)
cpu_addr = of_translate_dma_address(parser->node,
parser->range + na);
@@ -774,7 +777,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,

if (flags != range->flags)
break;
- if (pci_addr != range->pci_addr + range->size ||
+ if (bus_addr != range->bus_addr + range->size ||
cpu_addr != range->cpu_addr + range->size)
break;

diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 763022ed3456..3e8d6489cbf1 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -6,8 +6,11 @@
#include <linux/of.h>
#include <linux/io.h>

+struct of_bus;
+
struct of_pci_range_parser {
struct device_node *node;
+ struct of_bus *bus;
const __be32 *range;
const __be32 *end;
int na;
@@ -53,6 +56,7 @@ extern const __be32 *of_get_address(struct device_node *dev, int index,

extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
struct device_node *node);
+#define of_range_parser_init of_pci_range_parser_init
extern int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
struct device_node *node);
extern struct of_pci_range *of_pci_range_parser_one(
@@ -83,6 +87,7 @@ static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
{
return -ENOSYS;
}
+#define of_range_parser_init of_pci_range_parser_init

static inline int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
struct device_node *node)
--
2.28.0.rc1

2020-07-21 14:19:25

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 2/5] MIPS: Loongson64: Process ISA Node in DeviceTree

Previously, we're hardcoding resserved ISA I/O Space in code, now
we're processing reverved I/O via DeviceTree directly. Using the ranges
property to determine the size and address of reserved I/O space.

Signed-off-by: Jiaxun Yang <[email protected]>
--
v2: Use range_parser instead of pci_range_parser
---
arch/mips/loongson64/init.c | 88 ++++++++++++++++++++++++++-----------
1 file changed, 63 insertions(+), 25 deletions(-)

diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index 59ddadace83f..67e95193758e 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -7,6 +7,8 @@
#include <linux/irqchip.h>
#include <linux/logic_pio.h>
#include <linux/memblock.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/bootinfo.h>
#include <asm/traps.h>
#include <asm/smp-ops.h>
@@ -63,41 +65,77 @@ void __init prom_free_prom_memory(void)
{
}

-static __init void reserve_pio_range(void)
+static int __init add_legacy_isa_io(struct fwnode_handle *fwnode, resource_size_t hw_start,
+ resource_size_t size)
{
+ int ret = 0;
struct logic_pio_hwaddr *range;
+ unsigned long vaddr;

range = kzalloc(sizeof(*range), GFP_ATOMIC);
if (!range)
- return;
+ return -ENOMEM;

- range->fwnode = &of_root->fwnode;
- range->size = MMIO_LOWER_RESERVED;
- range->hw_start = LOONGSON_PCIIO_BASE;
+ range->fwnode = fwnode;
+ range->size = size;
+ range->hw_start = hw_start;
range->flags = LOGIC_PIO_CPU_MMIO;

- if (logic_pio_register_range(range)) {
- pr_err("Failed to reserve PIO range for legacy ISA\n");
- goto free_range;
+ ret = logic_pio_register_range(range);
+ if (ret) {
+ kfree(range);
+ return ret;
+ }
+
+ /* Legacy ISA must placed at the start of PCI_IOBASE */
+ if (range->io_start != 0) {
+ logic_pio_unregister_range(range);
+ kfree(range);
+ return -EINVAL;
}

- if (WARN(range->io_start != 0,
- "Reserved PIO range does not start from 0\n"))
- goto unregister;
-
- /*
- * i8259 would access I/O space, so mapping must be done here.
- * Please remove it when all drivers can be managed by logic_pio.
- */
- ioremap_page_range(PCI_IOBASE, PCI_IOBASE + MMIO_LOWER_RESERVED,
- LOONGSON_PCIIO_BASE,
- pgprot_device(PAGE_KERNEL));
-
- return;
-unregister:
- logic_pio_unregister_range(range);
-free_range:
- kfree(range);
+ vaddr = PCI_IOBASE + range->io_start;
+
+ ioremap_page_range(vaddr, vaddr + size, hw_start, pgprot_device(PAGE_KERNEL));
+
+ return 0;
+}
+
+static __init void reserve_pio_range(void)
+{
+ struct device_node *np;
+
+ for_each_node_by_name(np, "isa") {
+ struct of_range range;
+ struct of_range_parser parser;
+
+ pr_info("ISA Bridge: %pOF\n", np);
+
+ if (of_range_parser_init(&parser, np)) {
+ pr_info("Failed to parse resources.\n");
+ break;
+ }
+
+ for_each_of_range(&parser, &range) {
+ switch (range.flags & IORESOURCE_TYPE_BITS) {
+ case IORESOURCE_IO:
+ pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n",
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1,
+ range.bus_addr);
+ if (add_legacy_isa_io(&np->fwnode, range.cpu_addr + range.bus_addr,
+ range.size))
+ pr_warn("Failed to reserve legacy IO in Logic PIO\n");
+ break;
+ case IORESOURCE_MEM:
+ pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx\n",
+ range.cpu_addr,
+ range.cpu_addr + range.size - 1,
+ range.bus_addr);
+ break;
+ }
+ }
+ }
}

void __init arch_init_irq(void)
--
2.28.0.rc1

2020-07-21 14:20:00

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 4/5] MIPS: Loongson64: DTS: Fix ISA range for RS780E PCH

Ranges should express the actual physical address on bus.

Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/boot/dts/loongson/rs780e-pch.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/boot/dts/loongson/rs780e-pch.dtsi b/arch/mips/boot/dts/loongson/rs780e-pch.dtsi
index d4c803d74036..99174b52dfb8 100644
--- a/arch/mips/boot/dts/loongson/rs780e-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/rs780e-pch.dtsi
@@ -25,7 +25,7 @@ isa {
compatible = "isa";
#address-cells = <2>;
#size-cells = <1>;
- ranges = <1 0 0 0 0x4000>;
+ ranges = <1 0 0 0x18000000 0x4000>;

rtc0: rtc@70 {
compatible = "motorola,mc146818";
--
2.28.0.rc1

2020-07-21 14:21:32

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 3/5] MIPS: Loongson64: Enlarge IO_SPACE_LIMIT

It can be very big on LS7A PCH systems.

Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/include/asm/io.h | 3 ++-
arch/mips/include/asm/mach-loongson64/spaces.h | 3 +--
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 346fffd9e972..0072489325fa 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -50,8 +50,9 @@
# define __relaxed_ioswabq ioswabq

/* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
-
+#ifndef IO_SPACE_LIMIT
#define IO_SPACE_LIMIT 0xffff
+#endif

/*
* On MIPS I/O ports are memory mapped, so we access them using normal
diff --git a/arch/mips/include/asm/mach-loongson64/spaces.h b/arch/mips/include/asm/mach-loongson64/spaces.h
index 3de0ac9d8829..fa5ea4ee8b6c 100644
--- a/arch/mips/include/asm/mach-loongson64/spaces.h
+++ b/arch/mips/include/asm/mach-loongson64/spaces.h
@@ -11,8 +11,7 @@
#define PCI_IOSIZE SZ_16M
#define MAP_BASE (PCI_IOBASE + PCI_IOSIZE)

-/* Reserved at the start of PCI_IOBASE for legacy drivers */
-#define MMIO_LOWER_RESERVED 0x10000
+#define IO_SPACE_LIMIT PCI_IOSIZE

#include <asm/mach-generic/spaces.h>
#endif
--
2.28.0.rc1

2020-07-21 14:22:17

by Jiaxun Yang

[permalink] [raw]
Subject: [PATCH v2 5/5] MIPS: Loongson64: Add ISA node for LS7A PCH

Although currently we're not enabling any ISA device in devicetree,
but this node is required to express the ranges of address reserved
for ISA.

Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/boot/dts/loongson/ls7a-pch.dtsi | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
index 1c286bb8c703..e574a062dfae 100644
--- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
@@ -367,5 +367,12 @@ pci_bridge@14,0 {
interrupt-map = <0 0 0 0 &pic 39 IRQ_TYPE_LEVEL_HIGH>;
};
};
+
+ isa {
+ compatible = "isa";
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0 0x18000000 0x20000>;
+ };
};
};
--
2.28.0.rc1

2020-07-22 05:58:21

by Jiaxun Yang

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] MIPS: Loongson64: Enlarge IO_SPACE_LIMIT



?? 2020/7/21 ????10:17, Jiaxun Yang ะด??:
> It can be very big on LS7A PCH systems.
>
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> arch/mips/include/asm/io.h | 3 ++-
> arch/mips/include/asm/mach-loongson64/spaces.h | 3 +--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
> index 346fffd9e972..0072489325fa 100644
> --- a/arch/mips/include/asm/io.h
> +++ b/arch/mips/include/asm/io.h
> @@ -50,8 +50,9 @@
> # define __relaxed_ioswabq ioswabq
>
> /* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
> -
> +#ifndef IO_SPACE_LIMIT
> #define IO_SPACE_LIMIT 0xffff
> +#endif
>
> /*
> * On MIPS I/O ports are memory mapped, so we access them using normal
> diff --git a/arch/mips/include/asm/mach-loongson64/spaces.h b/arch/mips/include/asm/mach-loongson64/spaces.h
> index 3de0ac9d8829..fa5ea4ee8b6c 100644
> --- a/arch/mips/include/asm/mach-loongson64/spaces.h
> +++ b/arch/mips/include/asm/mach-loongson64/spaces.h
> @@ -11,8 +11,7 @@
> #define PCI_IOSIZE SZ_16M
> #define MAP_BASE (PCI_IOBASE + PCI_IOSIZE)
>
> -/* Reserved at the start of PCI_IOBASE for legacy drivers */
> -#define MMIO_LOWER_RESERVED 0x10000
> +#define IO_SPACE_LIMIT PCI_IOSIZE
Oops, it should be (PCI_IOSIZE - 1), will fix in next revision.

Sorry for the noise.

Thanks.

- Jiaxun

>
> #include <asm/mach-generic/spaces.h>
> #endif

2020-07-22 09:34:06

by Thomas Bogendoerfer

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] MIPS: Loongson64: Enlarge IO_SPACE_LIMIT

On Tue, Jul 21, 2020 at 10:17:31PM +0800, Jiaxun Yang wrote:
> It can be very big on LS7A PCH systems.
>
> Signed-off-by: Jiaxun Yang <[email protected]>
> ---
> arch/mips/include/asm/io.h | 3 ++-
> arch/mips/include/asm/mach-loongson64/spaces.h | 3 +--
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
> index 346fffd9e972..0072489325fa 100644
> --- a/arch/mips/include/asm/io.h
> +++ b/arch/mips/include/asm/io.h
> @@ -50,8 +50,9 @@
> # define __relaxed_ioswabq ioswabq
>
> /* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
> -
> +#ifndef IO_SPACE_LIMIT
> #define IO_SPACE_LIMIT 0xffff
> +#endif

please move this to include/asm/mach-generic/spaces.h

Thomas.

--
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea. [ RFC1925, 2.3 ]

2020-07-22 15:56:28

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] of_address: Add bus type match for pci ranges parser

On Tue, Jul 21, 2020 at 8:18 AM Jiaxun Yang <[email protected]> wrote:
>
> So the parser can be used to parse range property of ISA bus.
>
> As they're all using PCI-like method of range property, there is no need
> start a new parser.
>
> Signed-off-by: Jiaxun Yang <[email protected]>
>
> --
> v2: Drop useless check, fix some na for bus_addr
> add define of of_range_parser_init according to
> Rob's suggestion.
> ---
> drivers/of/address.c | 27 +++++++++++++++------------
> include/linux/of_address.h | 5 +++++
> 2 files changed, 20 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/of/address.c b/drivers/of/address.c
> index 8eea3f6e29a4..7406636cea87 100644
> --- a/drivers/of/address.c
> +++ b/drivers/of/address.c
> @@ -698,9 +698,10 @@ static int parser_init(struct of_pci_range_parser *parser,
>
> parser->node = node;
> parser->pna = of_n_addr_cells(node);
> - parser->na = of_bus_n_addr_cells(node);
> - parser->ns = of_bus_n_size_cells(node);
> parser->dma = !strcmp(name, "dma-ranges");
> + parser->bus = of_match_bus(node);
> +
> + parser->bus->count_cells(parser->node, &parser->na, &parser->ns);
>
> parser->range = of_get_property(node, name, &rlen);
> if (parser->range == NULL)
> @@ -732,6 +733,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> int na = parser->na;
> int ns = parser->ns;
> int np = parser->pna + na + ns;
> + int busflag_na = 0;
>
> if (!range)
> return NULL;
> @@ -739,12 +741,14 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> if (!parser->range || parser->range + np > parser->end)
> return NULL;
>
> - if (parser->na == 3)
> - range->flags = of_bus_pci_get_flags(parser->range);
> - else
> - range->flags = 0;
> + range->flags = parser->bus->get_flags(parser->range);
> +
> + /* PCI and ISA have a extra cell for resource flags */
> + if (strcmp(parser->bus->name, "pci") ||
> + strcmp(parser->bus->name, "isa"))
> + busflag_na = 1;

This should be abstracted out. Probably the easiest is to add a
'has_flags' boolean to the of_bus struct.

>
> - range->pci_addr = of_read_number(parser->range, na);
> + range->bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
>
> if (parser->dma)
> range->cpu_addr = of_translate_dma_address(parser->node,
> @@ -759,11 +763,10 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
> /* Now consume following elements while they are contiguous */
> while (parser->range + np <= parser->end) {
> u32 flags = 0;
> - u64 pci_addr, cpu_addr, size;
> + u64 bus_addr, cpu_addr, size;
>
> - if (parser->na == 3)
> - flags = of_bus_pci_get_flags(parser->range);
> - pci_addr = of_read_number(parser->range, na);
> + flags = parser->bus->get_flags(parser->range);
> + bus_addr = of_read_number(parser->range + busflag_na, na - busflag_na);
> if (parser->dma)
> cpu_addr = of_translate_dma_address(parser->node,
> parser->range + na);
> @@ -774,7 +777,7 @@ struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
>
> if (flags != range->flags)
> break;
> - if (pci_addr != range->pci_addr + range->size ||
> + if (bus_addr != range->bus_addr + range->size ||
> cpu_addr != range->cpu_addr + range->size)
> break;
>
> diff --git a/include/linux/of_address.h b/include/linux/of_address.h
> index 763022ed3456..3e8d6489cbf1 100644
> --- a/include/linux/of_address.h
> +++ b/include/linux/of_address.h
> @@ -6,8 +6,11 @@
> #include <linux/of.h>
> #include <linux/io.h>
>
> +struct of_bus;
> +
> struct of_pci_range_parser {
> struct device_node *node;
> + struct of_bus *bus;
> const __be32 *range;
> const __be32 *end;
> int na;
> @@ -53,6 +56,7 @@ extern const __be32 *of_get_address(struct device_node *dev, int index,
>
> extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> struct device_node *node);
> +#define of_range_parser_init of_pci_range_parser_init
> extern int of_pci_dma_range_parser_init(struct of_pci_range_parser *parser,
> struct device_node *node);
> extern struct of_pci_range *of_pci_range_parser_one(
> @@ -83,6 +87,7 @@ static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
> {
> return -ENOSYS;
> }
> +#define of_range_parser_init of_pci_range_parser_init

No need for 2 defines. Move this outside of the ifdef like the others.