Message ID | 1584932355-3642-4-git-send-email-yangtiezhu@loongson.cn (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Add basic support for Loongson 7A1000 bridge chip | expand |
于 2020年3月23日 GMT+08:00 上午10:59:15, Tiezhu Yang <yangtiezhu@loongson.cn> 写到: >Add PCI support for 7A1000 to detect PCI device. > >Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Hi Tiezhu, See my comments below. >--- > arch/mips/include/asm/mach-loongson64/boot_param.h | 9 +++ > arch/mips/loongson64/env.c | 2 + >arch/mips/pci/ops-loongson3.c | 72 >++++++++++++++++++++-- > 3 files changed, 79 insertions(+), 4 deletions(-) > >diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h >b/arch/mips/include/asm/mach-loongson64/boot_param.h >index c759b7c..d766a36 100644 >--- a/arch/mips/include/asm/mach-loongson64/boot_param.h >+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h >@@ -195,6 +195,7 @@ enum loongson_bridge_type { > LS7A1000 = 2 > }; > >+struct pci_bus; > struct loongson_system_configuration { > u32 nr_cpus; > u32 nr_nodes; >@@ -220,6 +221,8 @@ struct loongson_system_configuration { > struct sensor_device sensors[MAX_SENSORS]; > u64 workarounds; > void (*early_config)(void); >+ int (*pci_config_access)(unsigned char access_type, struct pci_bus >*bus, >+ unsigned int devfn, int where, u32 *data); > }; > > extern struct efi_memory_map_loongson *loongson_memmap; >@@ -228,5 +231,11 @@ extern struct loongson_system_configuration >loongson_sysconf; > extern u32 node_id_offset; > extern void rs780e_early_config(void); > extern void ls7a1000_early_config(void); >+extern int rs780e_pci_config_access(unsigned char access_type, >+ struct pci_bus *bus, unsigned int devfn, >+ int where, u32 *data); >+extern int ls7a1000_pci_config_access(unsigned char access_type, >+ struct pci_bus *bus, unsigned int devfn, >+ int where, u32 *data); > > #endif >diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c >index 32a3822..1c27f46 100644 >--- a/arch/mips/loongson64/env.c >+++ b/arch/mips/loongson64/env.c >@@ -168,9 +168,11 @@ void __init prom_init_env(void) > pr_info("The bridge chip is Loongson 7A1000\n"); > loongson_sysconf.bridgetype = LS7A1000; > loongson_sysconf.early_config = ls7a1000_early_config; >+ loongson_sysconf.pci_config_access = ls7a1000_pci_config_access; > } else { > pr_info("The bridge chip is AMD RS780E or SR5690\n"); > loongson_sysconf.bridgetype = RS780E; > loongson_sysconf.early_config = rs780e_early_config; >+ loongson_sysconf.pci_config_access = rs780e_pci_config_access; > } > } >diff --git a/arch/mips/pci/ops-loongson3.c >b/arch/mips/pci/ops-loongson3.c >index 2f6ad36..0b8fc5e 100644 >--- a/arch/mips/pci/ops-loongson3.c >+++ b/arch/mips/pci/ops-loongson3.c >@@ -13,7 +13,10 @@ > #define HT1LO_PCICFG_BASE 0x1a000000 > #define HT1LO_PCICFG_BASE_TP1 0x1b000000 > >-static int loongson3_pci_config_access(unsigned char access_type, >+#define HT1LO_PCICFG_BASE_EXT 0xefe00000000 >+#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000 >+ >+int rs780e_pci_config_access(unsigned char access_type, > struct pci_bus *bus, unsigned int devfn, > int where, u32 *data) > { >@@ -62,11 +65,72 @@ static int loongson3_pci_config_access(unsigned >char access_type, > return PCIBIOS_SUCCESSFUL; > } > >+ >+int ls7a1000_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 (*data == 0xffffffff) { >+ *data = -1; >+ return PCIBIOS_DEVICE_NOT_FOUND; >+ } >+ } >+ >+ return PCIBIOS_SUCCESSFUL; >+} >+ >+static void ls7a1000_pci_class_quirk(struct pci_dev *dev) >+{ >+ dev->class = PCI_CLASS_BRIDGE_PCI << 8; >+} >+ >+DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a09, ls7a1000_pci_class_quirk); >+DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a19, ls7a1000_pci_class_quirk); >+DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a29, ls7a1000_pci_class_quirk); Please place them to fixup-loongson3.c, don't mess up with operations. And you've already added vendor ID to pci_ids.h. You can use it and tell us "it depends on pci-next tree's commit". >+ >static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int >devfn, > int where, int size, u32 *val) > { > u32 data = 0; >- int ret = loongson3_pci_config_access(PCI_ACCESS_READ, >+ int ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, > bus, devfn, where, &data); > > if (ret != PCIBIOS_SUCCESSFUL) >@@ -91,7 +155,7 @@ static int loongson3_pci_pcibios_write(struct >pci_bus *bus, unsigned int devfn, > if (size == 4) > data = val; > else { >- ret = loongson3_pci_config_access(PCI_ACCESS_READ, >+ ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, > bus, devfn, where, &data); > if (ret != PCIBIOS_SUCCESSFUL) > return ret; >@@ -104,7 +168,7 @@ static int loongson3_pci_pcibios_write(struct >pci_bus *bus, unsigned int devfn, > (val << ((where & 3) << 3)); > } > >- ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, >+ ret = loongson_sysconf.pci_config_access(PCI_ACCESS_WRITE, > bus, devfn, where, &data); > > return ret;
On 03/24/2020 03:28 PM, Jiaxun Yang wrote: > > 于 2020年3月23日 GMT+08:00 上午10:59:15, Tiezhu Yang <yangtiezhu@loongson.cn> 写到: >> Add PCI support for 7A1000 to detect PCI device. >> >> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> > Hi Tiezhu, > > See my comments below. > >> --- >> arch/mips/include/asm/mach-loongson64/boot_param.h | 9 +++ >> arch/mips/loongson64/env.c | 2 + >> arch/mips/pci/ops-loongson3.c | 72 >> ++++++++++++++++++++-- >> 3 files changed, 79 insertions(+), 4 deletions(-) >> >> diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h >> b/arch/mips/include/asm/mach-loongson64/boot_param.h >> index c759b7c..d766a36 100644 >> --- a/arch/mips/include/asm/mach-loongson64/boot_param.h >> +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h >> @@ -195,6 +195,7 @@ enum loongson_bridge_type { >> LS7A1000 = 2 >> }; >> >> +struct pci_bus; >> struct loongson_system_configuration { >> u32 nr_cpus; >> u32 nr_nodes; >> @@ -220,6 +221,8 @@ struct loongson_system_configuration { >> struct sensor_device sensors[MAX_SENSORS]; >> u64 workarounds; >> void (*early_config)(void); >> + int (*pci_config_access)(unsigned char access_type, struct pci_bus >> *bus, >> + unsigned int devfn, int where, u32 *data); >> }; >> >> extern struct efi_memory_map_loongson *loongson_memmap; >> @@ -228,5 +231,11 @@ extern struct loongson_system_configuration >> loongson_sysconf; >> extern u32 node_id_offset; >> extern void rs780e_early_config(void); >> extern void ls7a1000_early_config(void); >> +extern int rs780e_pci_config_access(unsigned char access_type, >> + struct pci_bus *bus, unsigned int devfn, >> + int where, u32 *data); >> +extern int ls7a1000_pci_config_access(unsigned char access_type, >> + struct pci_bus *bus, unsigned int devfn, >> + int where, u32 *data); >> >> #endif >> diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c >> index 32a3822..1c27f46 100644 >> --- a/arch/mips/loongson64/env.c >> +++ b/arch/mips/loongson64/env.c >> @@ -168,9 +168,11 @@ void __init prom_init_env(void) >> pr_info("The bridge chip is Loongson 7A1000\n"); >> loongson_sysconf.bridgetype = LS7A1000; >> loongson_sysconf.early_config = ls7a1000_early_config; >> + loongson_sysconf.pci_config_access = ls7a1000_pci_config_access; >> } else { >> pr_info("The bridge chip is AMD RS780E or SR5690\n"); >> loongson_sysconf.bridgetype = RS780E; >> loongson_sysconf.early_config = rs780e_early_config; >> + loongson_sysconf.pci_config_access = rs780e_pci_config_access; >> } >> } >> diff --git a/arch/mips/pci/ops-loongson3.c >> b/arch/mips/pci/ops-loongson3.c >> index 2f6ad36..0b8fc5e 100644 >> --- a/arch/mips/pci/ops-loongson3.c >> +++ b/arch/mips/pci/ops-loongson3.c >> @@ -13,7 +13,10 @@ >> #define HT1LO_PCICFG_BASE 0x1a000000 >> #define HT1LO_PCICFG_BASE_TP1 0x1b000000 >> >> -static int loongson3_pci_config_access(unsigned char access_type, >> +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000 >> +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000 >> + >> +int rs780e_pci_config_access(unsigned char access_type, >> struct pci_bus *bus, unsigned int devfn, >> int where, u32 *data) >> { >> @@ -62,11 +65,72 @@ static int loongson3_pci_config_access(unsigned >> char access_type, >> return PCIBIOS_SUCCESSFUL; >> } >> >> + >> +int ls7a1000_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 (*data == 0xffffffff) { >> + *data = -1; >> + return PCIBIOS_DEVICE_NOT_FOUND; >> + } >> + } >> + >> + return PCIBIOS_SUCCESSFUL; >> +} >> + >> +static void ls7a1000_pci_class_quirk(struct pci_dev *dev) >> +{ >> + dev->class = PCI_CLASS_BRIDGE_PCI << 8; >> +} >> + >> +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a09, ls7a1000_pci_class_quirk); >> +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a19, ls7a1000_pci_class_quirk); >> +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a29, ls7a1000_pci_class_quirk); > Please place them to fixup-loongson3.c, > don't mess up with operations. > > And you've already added vendor ID to pci_ids.h. > You can use it and tell us "it depends on pci-next tree's commit". OK, I will do it. Thank you very much. > >> + >> static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int >> devfn, >> int where, int size, u32 *val) >> { >> u32 data = 0; >> - int ret = loongson3_pci_config_access(PCI_ACCESS_READ, >> + int ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, >> bus, devfn, where, &data); >> >> if (ret != PCIBIOS_SUCCESSFUL) >> @@ -91,7 +155,7 @@ static int loongson3_pci_pcibios_write(struct >> pci_bus *bus, unsigned int devfn, >> if (size == 4) >> data = val; >> else { >> - ret = loongson3_pci_config_access(PCI_ACCESS_READ, >> + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, >> bus, devfn, where, &data); >> if (ret != PCIBIOS_SUCCESSFUL) >> return ret; >> @@ -104,7 +168,7 @@ static int loongson3_pci_pcibios_write(struct >> pci_bus *bus, unsigned int devfn, >> (val << ((where & 3) << 3)); >> } >> >> - ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, >> + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_WRITE, >> bus, devfn, where, &data); >> >> return ret;
diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h index c759b7c..d766a36 100644 --- a/arch/mips/include/asm/mach-loongson64/boot_param.h +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h @@ -195,6 +195,7 @@ enum loongson_bridge_type { LS7A1000 = 2 }; +struct pci_bus; struct loongson_system_configuration { u32 nr_cpus; u32 nr_nodes; @@ -220,6 +221,8 @@ struct loongson_system_configuration { struct sensor_device sensors[MAX_SENSORS]; u64 workarounds; void (*early_config)(void); + int (*pci_config_access)(unsigned char access_type, struct pci_bus *bus, + unsigned int devfn, int where, u32 *data); }; extern struct efi_memory_map_loongson *loongson_memmap; @@ -228,5 +231,11 @@ extern struct loongson_system_configuration loongson_sysconf; extern u32 node_id_offset; extern void rs780e_early_config(void); extern void ls7a1000_early_config(void); +extern int rs780e_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data); +extern int ls7a1000_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, + int where, u32 *data); #endif diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c index 32a3822..1c27f46 100644 --- a/arch/mips/loongson64/env.c +++ b/arch/mips/loongson64/env.c @@ -168,9 +168,11 @@ void __init prom_init_env(void) pr_info("The bridge chip is Loongson 7A1000\n"); loongson_sysconf.bridgetype = LS7A1000; loongson_sysconf.early_config = ls7a1000_early_config; + loongson_sysconf.pci_config_access = ls7a1000_pci_config_access; } else { pr_info("The bridge chip is AMD RS780E or SR5690\n"); loongson_sysconf.bridgetype = RS780E; loongson_sysconf.early_config = rs780e_early_config; + loongson_sysconf.pci_config_access = rs780e_pci_config_access; } } diff --git a/arch/mips/pci/ops-loongson3.c b/arch/mips/pci/ops-loongson3.c index 2f6ad36..0b8fc5e 100644 --- a/arch/mips/pci/ops-loongson3.c +++ b/arch/mips/pci/ops-loongson3.c @@ -13,7 +13,10 @@ #define HT1LO_PCICFG_BASE 0x1a000000 #define HT1LO_PCICFG_BASE_TP1 0x1b000000 -static int loongson3_pci_config_access(unsigned char access_type, +#define HT1LO_PCICFG_BASE_EXT 0xefe00000000 +#define HT1LO_PCICFG_BASE_TP1_EXT 0xefe10000000 + +int rs780e_pci_config_access(unsigned char access_type, struct pci_bus *bus, unsigned int devfn, int where, u32 *data) { @@ -62,11 +65,72 @@ static int loongson3_pci_config_access(unsigned char access_type, return PCIBIOS_SUCCESSFUL; } + +int ls7a1000_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 (*data == 0xffffffff) { + *data = -1; + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +static void ls7a1000_pci_class_quirk(struct pci_dev *dev) +{ + dev->class = PCI_CLASS_BRIDGE_PCI << 8; +} + +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a09, ls7a1000_pci_class_quirk); +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a19, ls7a1000_pci_class_quirk); +DECLARE_PCI_FIXUP_EARLY(0x0014, 0x7a29, ls7a1000_pci_class_quirk); + static int loongson3_pci_pcibios_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) { u32 data = 0; - int ret = loongson3_pci_config_access(PCI_ACCESS_READ, + int ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data); if (ret != PCIBIOS_SUCCESSFUL) @@ -91,7 +155,7 @@ static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, if (size == 4) data = val; else { - ret = loongson3_pci_config_access(PCI_ACCESS_READ, + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data); if (ret != PCIBIOS_SUCCESSFUL) return ret; @@ -104,7 +168,7 @@ static int loongson3_pci_pcibios_write(struct pci_bus *bus, unsigned int devfn, (val << ((where & 3) << 3)); } - ret = loongson3_pci_config_access(PCI_ACCESS_WRITE, + ret = loongson_sysconf.pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data); return ret;
Add PCI support for 7A1000 to detect PCI device. Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> --- arch/mips/include/asm/mach-loongson64/boot_param.h | 9 +++ arch/mips/loongson64/env.c | 2 + arch/mips/pci/ops-loongson3.c | 72 ++++++++++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-)