2020-03-09 08:24:19

by Tiezhu Yang

[permalink] [raw]
Subject: [PATCH 5/6] MIPS: Loongson: Add PCI support for 7A1000

Add PCI support for 7A1000 to detect PCI device.

Co-developed-by: Jianmin Lv <[email protected]>
Signed-off-by: Jianmin Lv <[email protected]>
Signed-off-by: Tiezhu Yang <[email protected]>
---
arch/mips/include/asm/mach-loongson64/pci.h | 1 +
arch/mips/loongson64/pci.c | 12 ++-
arch/mips/pci/Makefile | 2 +-
arch/mips/pci/ops-loongson3-ls7a.c | 132 ++++++++++++++++++++++++++++
4 files changed, 143 insertions(+), 4 deletions(-)
create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c

diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
index 8b59d64..42c9744 100644
--- a/arch/mips/include/asm/mach-loongson64/pci.h
+++ b/arch/mips/include/asm/mach-loongson64/pci.h
@@ -8,6 +8,7 @@
#define __ASM_MACH_LOONGSON64_PCI_H_

extern struct pci_ops loongson_pci_ops;
+extern struct pci_ops loongson_ls7a_pci_ops;

/* this is an offset from mips_io_port_base */
#define LOONGSON_PCI_IO_START 0x00004000UL
diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
index e84ae20..b79368f 100644
--- a/arch/mips/loongson64/pci.c
+++ b/arch/mips/loongson64/pci.c
@@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
.flags = IORESOURCE_IO,
};

-static struct pci_controller loongson_pci_controller = {
- .pci_ops = &loongson_pci_ops,
+static struct pci_controller loongson_pci_controller = {
+ .pci_ops = NULL,
.io_resource = &loongson_pci_io_resource,
.mem_resource = &loongson_pci_mem_resource,
.mem_offset = 0x00000000UL,
@@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);

static int __init pcibios_init(void)
{
+ if (strstr(eboard->name, "780E"))
+ loongson_pci_controller.pci_ops = &loongson_pci_ops;
+
+ if (strstr(eboard->name, "7A1000"))
+ loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;

loongson_pci_controller.io_map_base = mips_io_port_base;
loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
@@ -43,7 +48,8 @@ static int __init pcibios_init(void)

register_pci_controller(&loongson_pci_controller);

- sbx00_acpi_init();
+ if (strstr(eboard->name, "780E"))
+ sbx00_acpi_init();

return 0;
}
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index 342ce10..7256bb1 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
-obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o
+obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
new file mode 100644
index 0000000..4ed6c40
--- /dev/null
+++ b/arch/mips/pci/ops-loongson3-ls7a.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Loongson Technology Corporation Limited
+ *
+ * Author: Jianmin Lv <[email protected]>
+ * Author: Tiezhu Yang <[email protected]>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+
+#include <asm/mips-boards/bonito64.h>
+
+#include <loongson.h>
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+#define HT1LO_PCICFG_BASE 0x1a000000
+#define HT1LO_PCICFG_BASE_TP1 0x1b000000
+
+#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
+#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
+
+static int ls7a_pci_config_access(unsigned char access_type,
+ struct pci_bus *bus, unsigned int devfn,
+ int where, u32 *data)
+{
+ u_int64_t addr;
+ void *addrp;
+ unsigned char busnum = bus->number;
+ int device = PCI_SLOT(devfn);
+ int function = PCI_FUNC(devfn);
+ int reg = where & ~3;
+
+ if (where >= PCI_CFG_SPACE_EXP_SIZE)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (busnum == 0 && device > 23)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (where < PCI_CFG_SPACE_SIZE) { /* standard config */
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ if (busnum == 0) {
+ addr = HT1LO_PCICFG_BASE | addr;
+ addrp = (void *)TO_UNCAC(addr);
+ } else {
+ addr = HT1LO_PCICFG_BASE_TP1 | addr;
+ addrp = (void *)TO_UNCAC(addr);
+ }
+ } else { /* extended config */
+ reg = (reg & 0xff) | ((reg & 0xf00) << 16);
+ addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
+ if (busnum == 0) {
+ addr = HT1LO_PCICFG_BASE_EXT | addr;
+ addrp = (void *)TO_UNCAC(addr);
+ } else {
+ addr = HT1LO_PCICFG_BASE_TP1_EXT | addr;
+ addrp = (void *)TO_UNCAC(addr);
+ }
+ }
+
+ if (access_type == PCI_ACCESS_WRITE)
+ *(unsigned int *)addrp = cpu_to_le32(*data);
+ else {
+ *data = le32_to_cpu(*(unsigned int *)addrp);
+ if (busnum == 0 &&
+ reg == PCI_CLASS_REVISION && *data == 0x06000001)
+ *data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);
+
+ if (*data == 0xffffffff) {
+ *data = -1;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ int ret;
+ u32 data = 0;
+
+ ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ int ret;
+ u32 data = 0;
+
+ if (size == 4)
+ data = val;
+ else {
+ ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
+ devfn, where, &data);
+ if (ret != PCIBIOS_SUCCESSFUL)
+ return ret;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
+ devfn, where, &data);
+
+ return ret;
+}
+
+struct pci_ops loongson_ls7a_pci_ops = {
+ .read = ls7a_pci_pcibios_read,
+ .write = ls7a_pci_pcibios_write
+};
--
2.1.0


2020-03-09 08:50:10

by Jiaxun Yang

[permalink] [raw]
Subject: 回复:[PATCH 5/6] MIPS: Loongso n: Add PCI support for 7A1000



---- 在 星期一, 2020-03-09 16:23:25 Tiezhu Yang <[email protected]> 撰写 ----
> Add PCI support for 7A1000 to detect PCI device.
>
> Co-developed-by: Jianmin Lv <[email protected]>
> Signed-off-by: Jianmin Lv <[email protected]>
> Signed-off-by: Tiezhu Yang <[email protected]>
> ---
> arch/mips/include/asm/mach-loongson64/pci.h | 1 +
> arch/mips/loongson64/pci.c | 12 ++-
> arch/mips/pci/Makefile | 2 +-
> arch/mips/pci/ops-loongson3-ls7a.c | 132 ++++++++++++++++++++++++++++
> 4 files changed, 143 insertions(+), 4 deletions(-)
> create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c
>
> diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
> index 8b59d64..42c9744 100644
> --- a/arch/mips/include/asm/mach-loongson64/pci.h
> +++ b/arch/mips/include/asm/mach-loongson64/pci.h
> @@ -8,6 +8,7 @@
> #define __ASM_MACH_LOONGSON64_PCI_H_
>
> extern struct pci_ops loongson_pci_ops;
> +extern struct pci_ops loongson_ls7a_pci_ops;
>
> /* this is an offset from mips_io_port_base */
> #define LOONGSON_PCI_IO_START 0x00004000UL
> diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
> index e84ae20..b79368f 100644
> --- a/arch/mips/loongson64/pci.c
> +++ b/arch/mips/loongson64/pci.c
> @@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
> .flags = IORESOURCE_IO,
> };
>
> -static struct pci_controller loongson_pci_controller = {
> - .pci_ops = &loongson_pci_ops,
> +static struct pci_controller loongson_pci_controller = {
> + .pci_ops = NULL,
> .io_resource = &loongson_pci_io_resource,
> .mem_resource = &loongson_pci_mem_resource,
> .mem_offset = 0x00000000UL,
> @@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);
>
> static int __init pcibios_init(void)
> {
> + if (strstr(eboard->name, "780E"))
> + loongson_pci_controller.pci_ops = &loongson_pci_ops;
> +
> + if (strstr(eboard->name, "7A1000"))
> + loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;

Please do not check PCH type everywhere.

>
> loongson_pci_controller.io_map_base = mips_io_port_base;
> loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
> @@ -43,7 +48,8 @@ static int __init pcibios_init(void)
>
> register_pci_controller(&loongson_pci_controller);
>
> - sbx00_acpi_init();
> + if (strstr(eboard->name, "780E"))
> + sbx00_acpi_init();
>
> return 0;
> }
> diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> index 342ce10..7256bb1 100644
> --- a/arch/mips/pci/Makefile
> +++ b/arch/mips/pci/Makefile
> @@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
> obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
> obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
> obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
> -obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o
> +obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
> obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
> obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
> obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
> diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
> new file mode 100644
> index 0000000..4ed6c40
> --- /dev/null
> +++ b/arch/mips/pci/ops-loongson3-ls7a.c
> @@ -0,0 +1,132 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Loongson Technology Corporation Limited
> + *
> + * Author: Jianmin Lv <[email protected]>
> + * Author: Tiezhu Yang <[email protected]>
> + */
> +
> +#include <linux/types.h>
> +#include <linux/pci.h>
> +#include <linux/kernel.h>
> +
> +#include <asm/mips-boards/bonito64.h>

Why we need this?

> +
> +#include <loongson.h>
> +
> +#define PCI_ACCESS_READ 0
> +#define PCI_ACCESS_WRITE 1
> +
> +#define HT1LO_PCICFG_BASE 0x1a000000
> +#define HT1LO_PCICFG_BASE_TP1 0x1b000000
> +
> +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
> +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
> +
> +static int ls7a_pci_config_access(unsigned char access_type,
> + struct pci_bus *bus, unsigned int devfn,
> + int where, u32 *data)
> +{
> + u_int64_t addr;
> + void *addrp;
> + unsigned char busnum = bus->number;
> + int device = PCI_SLOT(devfn);
> + int function = PCI_FUNC(devfn);
> + int reg = where & ~3;
> +
> + if (where >= PCI_CFG_SPACE_EXP_SIZE)
> + return PCIBIOS_DEVICE_NOT_FOUND;
> +
> + if (busnum == 0 && device > 23)
> + return PCIBIOS_DEVICE_NOT_FOUND;
> +
> + if (where < PCI_CFG_SPACE_SIZE) { /* standard config */
> + addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> + if (busnum == 0) {
> + addr = HT1LO_PCICFG_BASE | addr;
> + addrp = (void *)TO_UNCAC(addr);
> + } else {
> + addr = HT1LO_PCICFG_BASE_TP1 | addr;
> + addrp = (void *)TO_UNCAC(addr);
> + }
> + } else { /* extended config */
> + reg = (reg & 0xff) | ((reg & 0xf00) << 16);
> + addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> + if (busnum == 0) {
> + addr = HT1LO_PCICFG_BASE_EXT | addr;
> + addrp = (void *)TO_UNCAC(addr);
> + } else {
> + addr = HT1LO_PCICFG_BASE_TP1_EXT | addr;
> + addrp = (void *)TO_UNCAC(addr);
> + }
> + }
> +
> + if (access_type == PCI_ACCESS_WRITE)
> + *(unsigned int *)addrp = cpu_to_le32(*data);
> + else {
> + *data = le32_to_cpu(*(unsigned int *)addrp);
> + if (busnum == 0 &&
> + reg == PCI_CLASS_REVISION && *data == 0x06000001)
> + *data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);

It should be a part of quirk. Not a part of accessing.

> +
> + if (*data == 0xffffffff) {
> + *data = -1;
> + return PCIBIOS_DEVICE_NOT_FOUND;
> + }
> + }
> +
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
> + int where, int size, u32 *val)
> +{
> + int ret;
> + u32 data = 0;
> +
> + ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
> + if (ret != PCIBIOS_SUCCESSFUL)
> + return ret;
> +
> + if (size == 1)
> + *val = (data >> ((where & 3) << 3)) & 0xff;
> + else if (size == 2)
> + *val = (data >> ((where & 3) << 3)) & 0xffff;
> + else
> + *val = data;

That loggic seems identical with RS780E one, can we reuse them?

> +
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
> + int where, int size, u32 val)
> +{
> + int ret;
> + u32 data = 0;
> +
> + if (size == 4)
> + data = val;
> + else {
> + ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
> + devfn, where, &data);
> + if (ret != PCIBIOS_SUCCESSFUL)
> + return ret;
> +
> + if (size == 1)
> + data = (data & ~(0xff << ((where & 3) << 3))) |
> + (val << ((where & 3) << 3));
> + else if (size == 2)
> + data = (data & ~(0xffff << ((where & 3) << 3))) |
> + (val << ((where & 3) << 3));
> + }
> +
> + ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
> + devfn, where, &data);
> +
> + return ret;
> +}
> +
> +struct pci_ops loongson_ls7a_pci_ops = {
> + .read = ls7a_pci_pcibios_read,
> + .write = ls7a_pci_pcibios_write
> +};
> --
> 2.1.0
>
>

2020-03-10 03:04:03

by Tiezhu Yang

[permalink] [raw]
Subject: Re: 回复:[PATCH 5/6] MIPS: Loongson: Add PC I support for 7A1000

On 03/09/2020 04:47 PM, Jiaxun Yang wrote:
>
> ---- 在 星期一, 2020-03-09 16:23:25 Tiezhu Yang <[email protected]> 撰写 ----
> > Add PCI support for 7A1000 to detect PCI device.
> >
> > Co-developed-by: Jianmin Lv <[email protected]>
> > Signed-off-by: Jianmin Lv <[email protected]>
> > Signed-off-by: Tiezhu Yang <[email protected]>
> > ---
> > arch/mips/include/asm/mach-loongson64/pci.h | 1 +
> > arch/mips/loongson64/pci.c | 12 ++-
> > arch/mips/pci/Makefile | 2 +-
> > arch/mips/pci/ops-loongson3-ls7a.c | 132 ++++++++++++++++++++++++++++
> > 4 files changed, 143 insertions(+), 4 deletions(-)
> > create mode 100644 arch/mips/pci/ops-loongson3-ls7a.c
> >
> > diff --git a/arch/mips/include/asm/mach-loongson64/pci.h b/arch/mips/include/asm/mach-loongson64/pci.h
> > index 8b59d64..42c9744 100644
> > --- a/arch/mips/include/asm/mach-loongson64/pci.h
> > +++ b/arch/mips/include/asm/mach-loongson64/pci.h
> > @@ -8,6 +8,7 @@
> > #define __ASM_MACH_LOONGSON64_PCI_H_
> >
> > extern struct pci_ops loongson_pci_ops;
> > +extern struct pci_ops loongson_ls7a_pci_ops;
> >
> > /* this is an offset from mips_io_port_base */
> > #define LOONGSON_PCI_IO_START 0x00004000UL
> > diff --git a/arch/mips/loongson64/pci.c b/arch/mips/loongson64/pci.c
> > index e84ae20..b79368f 100644
> > --- a/arch/mips/loongson64/pci.c
> > +++ b/arch/mips/loongson64/pci.c
> > @@ -23,8 +23,8 @@ static struct resource loongson_pci_io_resource = {
> > .flags = IORESOURCE_IO,
> > };
> >
> > -static struct pci_controller loongson_pci_controller = {
> > - .pci_ops = &loongson_pci_ops,
> > +static struct pci_controller loongson_pci_controller = {
> > + .pci_ops = NULL,
> > .io_resource = &loongson_pci_io_resource,
> > .mem_resource = &loongson_pci_mem_resource,
> > .mem_offset = 0x00000000UL,
> > @@ -36,6 +36,11 @@ extern int sbx00_acpi_init(void);
> >
> > static int __init pcibios_init(void)
> > {
> > + if (strstr(eboard->name, "780E"))
> > + loongson_pci_controller.pci_ops = &loongson_pci_ops;
> > +
> > + if (strstr(eboard->name, "7A1000"))
> > + loongson_pci_controller.pci_ops = &loongson_ls7a_pci_ops;
>
> Please do not check PCH type everywhere.

Yes, you are right.

>
> >
> > loongson_pci_controller.io_map_base = mips_io_port_base;
> > loongson_pci_mem_resource.start = loongson_sysconf.pci_mem_start_addr;
> > @@ -43,7 +48,8 @@ static int __init pcibios_init(void)
> >
> > register_pci_controller(&loongson_pci_controller);
> >
> > - sbx00_acpi_init();
> > + if (strstr(eboard->name, "780E"))
> > + sbx00_acpi_init();
> >
> > return 0;
> > }
> > diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
> > index 342ce10..7256bb1 100644
> > --- a/arch/mips/pci/Makefile
> > +++ b/arch/mips/pci/Makefile
> > @@ -35,7 +35,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o
> > obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o
> > obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o
> > obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o
> > -obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o
> > +obj-$(CONFIG_MACH_LOONGSON64) += fixup-loongson3.o ops-loongson3.o ops-loongson3-ls7a.o
> > obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o
> > obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o
> > obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o
> > diff --git a/arch/mips/pci/ops-loongson3-ls7a.c b/arch/mips/pci/ops-loongson3-ls7a.c
> > new file mode 100644
> > index 0000000..4ed6c40
> > --- /dev/null
> > +++ b/arch/mips/pci/ops-loongson3-ls7a.c
> > @@ -0,0 +1,132 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (C) 2020 Loongson Technology Corporation Limited
> > + *
> > + * Author: Jianmin Lv <[email protected]>
> > + * Author: Tiezhu Yang <[email protected]>
> > + */
> > +
> > +#include <linux/types.h>
> > +#include <linux/pci.h>
> > +#include <linux/kernel.h>
> > +
> > +#include <asm/mips-boards/bonito64.h>
>
> Why we need this?

I will check it, if it is useless, I will remove it.

>
> > +
> > +#include <loongson.h>
> > +
> > +#define PCI_ACCESS_READ 0
> > +#define PCI_ACCESS_WRITE 1
> > +
> > +#define HT1LO_PCICFG_BASE 0x1a000000
> > +#define HT1LO_PCICFG_BASE_TP1 0x1b000000
> > +
> > +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000
> > +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000
> > +
> > +static int ls7a_pci_config_access(unsigned char access_type,
> > + struct pci_bus *bus, unsigned int devfn,
> > + int where, u32 *data)
> > +{
> > + u_int64_t addr;
> > + void *addrp;
> > + unsigned char busnum = bus->number;
> > + int device = PCI_SLOT(devfn);
> > + int function = PCI_FUNC(devfn);
> > + int reg = where & ~3;
> > +
> > + if (where >= PCI_CFG_SPACE_EXP_SIZE)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > + if (busnum == 0 && device > 23)
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > + if (where < PCI_CFG_SPACE_SIZE) { /* standard config */
> > + addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> > + if (busnum == 0) {
> > + addr = HT1LO_PCICFG_BASE | addr;
> > + addrp = (void *)TO_UNCAC(addr);
> > + } else {
> > + addr = HT1LO_PCICFG_BASE_TP1 | addr;
> > + addrp = (void *)TO_UNCAC(addr);
> > + }
> > + } else { /* extended config */
> > + reg = (reg & 0xff) | ((reg & 0xf00) << 16);
> > + addr = (busnum << 16) | (device << 11) | (function << 8) | reg;
> > + if (busnum == 0) {
> > + addr = HT1LO_PCICFG_BASE_EXT | addr;
> > + addrp = (void *)TO_UNCAC(addr);
> > + } else {
> > + addr = HT1LO_PCICFG_BASE_TP1_EXT | addr;
> > + addrp = (void *)TO_UNCAC(addr);
> > + }
> > + }
> > +
> > + if (access_type == PCI_ACCESS_WRITE)
> > + *(unsigned int *)addrp = cpu_to_le32(*data);
> > + else {
> > + *data = le32_to_cpu(*(unsigned int *)addrp);
> > + if (busnum == 0 &&
> > + reg == PCI_CLASS_REVISION && *data == 0x06000001)
> > + *data = (PCI_CLASS_BRIDGE_PCI << 16) | (*data & 0xffff);
>
> It should be a part of quirk. Not a part of accessing.
>
> > +
> > + if (*data == 0xffffffff) {
> > + *data = -1;
> > + return PCIBIOS_DEVICE_NOT_FOUND;
> > + }
> > + }
> > +
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int ls7a_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 *val)
> > +{
> > + int ret;
> > + u32 data = 0;
> > +
> > + ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
> > + if (ret != PCIBIOS_SUCCESSFUL)
> > + return ret;
> > +
> > + if (size == 1)
> > + *val = (data >> ((where & 3) << 3)) & 0xff;
> > + else if (size == 2)
> > + *val = (data >> ((where & 3) << 3)) & 0xffff;
> > + else
> > + *val = data;
>
> That loggic seems identical with RS780E one, can we reuse them?

OK, I will do it.

Thanks,

Tiezhu Yang

>
>> +
> > + return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int ls7a_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn,
> > + int where, int size, u32 val)
> > +{
> > + int ret;
> > + u32 data = 0;
> > +
> > + if (size == 4)
> > + data = val;
> > + else {
> > + ret = ls7a_pci_config_access(PCI_ACCESS_READ, bus,
> > + devfn, where, &data);
> > + if (ret != PCIBIOS_SUCCESSFUL)
> > + return ret;
> > +
> > + if (size == 1)
> > + data = (data & ~(0xff << ((where & 3) << 3))) |
> > + (val << ((where & 3) << 3));
> > + else if (size == 2)
> > + data = (data & ~(0xffff << ((where & 3) << 3))) |
> > + (val << ((where & 3) << 3));
> > + }
> > +
> > + ret = ls7a_pci_config_access(PCI_ACCESS_WRITE, bus,
> > + devfn, where, &data);
> > +
> > + return ret;
> > +}
> > +
> > +struct pci_ops loongson_ls7a_pci_ops = {
> > + .read = ls7a_pci_pcibios_read,
> > + .write = ls7a_pci_pcibios_write
> > +};
> > --
> > 2.1.0
> >
> >