Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PCI: loongson: Use generic 8/16/32-bit config ops on LS2K/LS7A

LS2K/LS7A support 8/16/32-bits PCI config access operations via CFG1, so
we can disable CFG0 for them and safely use pci_generic_config_read()/
pci_generic_config_write() instead of pci_generic_config_read32()/pci_
generic_config_write32().

Link: https://lore.kernel.org/r/20220714124216.1489304-3-chenhuacai@loongson.cn
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>

authored by

Huacai Chen and committed by
Bjorn Helgaas
dee449aa 40a6cc14

+46 -19
+46 -19
drivers/pci/controller/pci-loongson.c
··· 25 25 #define FLAG_CFG1 BIT(1) 26 26 #define FLAG_DEV_FIX BIT(2) 27 27 28 + struct loongson_pci_data { 29 + u32 flags; 30 + struct pci_ops *ops; 31 + }; 32 + 28 33 struct loongson_pci { 29 34 void __iomem *cfg0_base; 30 35 void __iomem *cfg1_base; 31 36 struct platform_device *pdev; 32 - u32 flags; 37 + const struct loongson_pci_data *data; 33 38 }; 34 39 35 40 /* Fixup wrong class code in PCIe bridges */ ··· 131 126 * Do not read more than one device on the bus other than 132 127 * the host bus. For our hardware the root bus is always bus 0. 133 128 */ 134 - if (priv->flags & FLAG_DEV_FIX && busnum != 0 && 135 - PCI_SLOT(devfn) > 0) 129 + if (priv->data->flags & FLAG_DEV_FIX && 130 + !pci_is_root_bus(bus) && PCI_SLOT(devfn) > 0) 136 131 return NULL; 137 132 138 133 /* CFG0 can only access standard space */ ··· 164 159 return val; 165 160 } 166 161 167 - /* H/w only accept 32-bit PCI operations */ 162 + /* LS2K/LS7A accept 8/16/32-bit PCI config operations */ 168 163 static struct pci_ops loongson_pci_ops = { 164 + .map_bus = pci_loongson_map_bus, 165 + .read = pci_generic_config_read, 166 + .write = pci_generic_config_write, 167 + }; 168 + 169 + /* RS780/SR5690 only accept 32-bit PCI config operations */ 170 + static struct pci_ops loongson_pci_ops32 = { 169 171 .map_bus = pci_loongson_map_bus, 170 172 .read = pci_generic_config_read32, 171 173 .write = pci_generic_config_write32, 172 174 }; 173 175 176 + static const struct loongson_pci_data ls2k_pci_data = { 177 + .flags = FLAG_CFG1 | FLAG_DEV_FIX, 178 + .ops = &loongson_pci_ops, 179 + }; 180 + 181 + static const struct loongson_pci_data ls7a_pci_data = { 182 + .flags = FLAG_CFG1 | FLAG_DEV_FIX, 183 + .ops = &loongson_pci_ops, 184 + }; 185 + 186 + static const struct loongson_pci_data rs780e_pci_data = { 187 + .flags = FLAG_CFG0, 188 + .ops = &loongson_pci_ops32, 189 + }; 190 + 174 191 static const struct of_device_id loongson_pci_of_match[] = { 175 192 { .compatible = "loongson,ls2k-pci", 176 - .data = (void *)(FLAG_CFG0 | FLAG_CFG1 | FLAG_DEV_FIX), }, 193 + .data = &ls2k_pci_data, }, 177 194 { .compatible = "loongson,ls7a-pci", 178 - .data = (void *)(FLAG_CFG0 | FLAG_CFG1 | FLAG_DEV_FIX), }, 195 + .data = &ls7a_pci_data, }, 179 196 { .compatible = "loongson,rs780e-pci", 180 - .data = (void *)(FLAG_CFG0), }, 197 + .data = &rs780e_pci_data, }, 181 198 {} 182 199 }; 183 200 ··· 220 193 221 194 priv = pci_host_bridge_priv(bridge); 222 195 priv->pdev = pdev; 223 - priv->flags = (unsigned long)of_device_get_match_data(dev); 196 + priv->data = of_device_get_match_data(dev); 224 197 225 - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 226 - if (!regs) { 227 - dev_err(dev, "missing mem resources for cfg0\n"); 228 - return -EINVAL; 198 + if (priv->data->flags & FLAG_CFG0) { 199 + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 200 + if (!regs) 201 + dev_err(dev, "missing mem resources for cfg0\n"); 202 + else { 203 + priv->cfg0_base = devm_pci_remap_cfg_resource(dev, regs); 204 + if (IS_ERR(priv->cfg0_base)) 205 + return PTR_ERR(priv->cfg0_base); 206 + } 229 207 } 230 208 231 - priv->cfg0_base = devm_pci_remap_cfg_resource(dev, regs); 232 - if (IS_ERR(priv->cfg0_base)) 233 - return PTR_ERR(priv->cfg0_base); 234 - 235 - /* CFG1 is optional */ 236 - if (priv->flags & FLAG_CFG1) { 209 + if (priv->data->flags & FLAG_CFG1) { 237 210 regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); 238 211 if (!regs) 239 212 dev_info(dev, "missing mem resource for cfg1\n"); ··· 245 218 } 246 219 247 220 bridge->sysdata = priv; 248 - bridge->ops = &loongson_pci_ops; 221 + bridge->ops = priv->data->ops; 249 222 bridge->map_irq = loongson_map_irq; 250 223 251 224 return pci_host_probe(bridge);