Skip to content

Commit dee449a

Browse files
chenhuacaibjorn-helgaas
authored andcommitted
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>
1 parent 40a6cc1 commit dee449a

1 file changed

Lines changed: 46 additions & 19 deletions

File tree

drivers/pci/controller/pci-loongson.c

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,16 @@
2525
#define FLAG_CFG1 BIT(1)
2626
#define FLAG_DEV_FIX BIT(2)
2727

28+
struct loongson_pci_data {
29+
u32 flags;
30+
struct pci_ops *ops;
31+
};
32+
2833
struct loongson_pci {
2934
void __iomem *cfg0_base;
3035
void __iomem *cfg1_base;
3136
struct platform_device *pdev;
32-
u32 flags;
37+
const struct loongson_pci_data *data;
3338
};
3439

3540
/* Fixup wrong class code in PCIe bridges */
@@ -126,8 +131,8 @@ static void __iomem *pci_loongson_map_bus(struct pci_bus *bus, unsigned int devf
126131
* Do not read more than one device on the bus other than
127132
* the host bus. For our hardware the root bus is always bus 0.
128133
*/
129-
if (priv->flags & FLAG_DEV_FIX && busnum != 0 &&
130-
PCI_SLOT(devfn) > 0)
134+
if (priv->data->flags & FLAG_DEV_FIX &&
135+
!pci_is_root_bus(bus) && PCI_SLOT(devfn) > 0)
131136
return NULL;
132137

133138
/* CFG0 can only access standard space */
@@ -159,20 +164,42 @@ static int loongson_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
159164
return val;
160165
}
161166

162-
/* H/w only accept 32-bit PCI operations */
167+
/* LS2K/LS7A accept 8/16/32-bit PCI config operations */
163168
static struct pci_ops loongson_pci_ops = {
169+
.map_bus = pci_loongson_map_bus,
170+
.read = pci_generic_config_read,
171+
.write = pci_generic_config_write,
172+
};
173+
174+
/* RS780/SR5690 only accept 32-bit PCI config operations */
175+
static struct pci_ops loongson_pci_ops32 = {
164176
.map_bus = pci_loongson_map_bus,
165177
.read = pci_generic_config_read32,
166178
.write = pci_generic_config_write32,
167179
};
168180

181+
static const struct loongson_pci_data ls2k_pci_data = {
182+
.flags = FLAG_CFG1 | FLAG_DEV_FIX,
183+
.ops = &loongson_pci_ops,
184+
};
185+
186+
static const struct loongson_pci_data ls7a_pci_data = {
187+
.flags = FLAG_CFG1 | FLAG_DEV_FIX,
188+
.ops = &loongson_pci_ops,
189+
};
190+
191+
static const struct loongson_pci_data rs780e_pci_data = {
192+
.flags = FLAG_CFG0,
193+
.ops = &loongson_pci_ops32,
194+
};
195+
169196
static const struct of_device_id loongson_pci_of_match[] = {
170197
{ .compatible = "loongson,ls2k-pci",
171-
.data = (void *)(FLAG_CFG0 | FLAG_CFG1 | FLAG_DEV_FIX), },
198+
.data = &ls2k_pci_data, },
172199
{ .compatible = "loongson,ls7a-pci",
173-
.data = (void *)(FLAG_CFG0 | FLAG_CFG1 | FLAG_DEV_FIX), },
200+
.data = &ls7a_pci_data, },
174201
{ .compatible = "loongson,rs780e-pci",
175-
.data = (void *)(FLAG_CFG0), },
202+
.data = &rs780e_pci_data, },
176203
{}
177204
};
178205

@@ -193,20 +220,20 @@ static int loongson_pci_probe(struct platform_device *pdev)
193220

194221
priv = pci_host_bridge_priv(bridge);
195222
priv->pdev = pdev;
196-
priv->flags = (unsigned long)of_device_get_match_data(dev);
223+
priv->data = of_device_get_match_data(dev);
197224

198-
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
199-
if (!regs) {
200-
dev_err(dev, "missing mem resources for cfg0\n");
201-
return -EINVAL;
225+
if (priv->data->flags & FLAG_CFG0) {
226+
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
227+
if (!regs)
228+
dev_err(dev, "missing mem resources for cfg0\n");
229+
else {
230+
priv->cfg0_base = devm_pci_remap_cfg_resource(dev, regs);
231+
if (IS_ERR(priv->cfg0_base))
232+
return PTR_ERR(priv->cfg0_base);
233+
}
202234
}
203235

204-
priv->cfg0_base = devm_pci_remap_cfg_resource(dev, regs);
205-
if (IS_ERR(priv->cfg0_base))
206-
return PTR_ERR(priv->cfg0_base);
207-
208-
/* CFG1 is optional */
209-
if (priv->flags & FLAG_CFG1) {
236+
if (priv->data->flags & FLAG_CFG1) {
210237
regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
211238
if (!regs)
212239
dev_info(dev, "missing mem resource for cfg1\n");
@@ -218,7 +245,7 @@ static int loongson_pci_probe(struct platform_device *pdev)
218245
}
219246

220247
bridge->sysdata = priv;
221-
bridge->ops = &loongson_pci_ops;
248+
bridge->ops = priv->data->ops;
222249
bridge->map_irq = loongson_map_irq;
223250

224251
return pci_host_probe(bridge);

0 commit comments

Comments
 (0)