aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2014-02-17 21:11:21 -0500
committerBjorn Helgaas <bhelgaas@google.com>2014-02-18 15:20:11 -0500
commit546cadda3575153bdd0af4febfe958cc5945f95a (patch)
tree1763ec3a9bf606599935076da836d0a5177dbef2 /drivers/pci
parente64a2a973e179613489a0ddb1bb550dff108164e (diff)
PCI: rcar: Register each instance independently
Convert the code to allow per-device probe() like other device drivers. This also delays driver registration due to change from subsys_initcall() to regular module_platform_driver(). Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Simon Horman <horms+renesas@verge.net.au>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/host/pci-rcar-gen2.c80
1 files changed, 20 insertions, 60 deletions
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c
index 6288476576a7..967997b2890b 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/host/pci-rcar-gen2.c
@@ -91,9 +91,6 @@
91 91
92#define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48) 92#define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
93 93
94/* Number of internal PCI controllers */
95#define RCAR_PCI_NR_CONTROLLERS 3
96
97struct rcar_pci_priv { 94struct rcar_pci_priv {
98 struct device *dev; 95 struct device *dev;
99 void __iomem *reg; 96 void __iomem *reg;
@@ -177,7 +174,7 @@ static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn,
177} 174}
178 175
179/* PCI interrupt mapping */ 176/* PCI interrupt mapping */
180static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 177static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
181{ 178{
182 struct pci_sys_data *sys = dev->bus->sysdata; 179 struct pci_sys_data *sys = dev->bus->sysdata;
183 struct rcar_pci_priv *priv = sys->private_data; 180 struct rcar_pci_priv *priv = sys->private_data;
@@ -226,7 +223,7 @@ static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { }
226#endif 223#endif
227 224
228/* PCI host controller setup */ 225/* PCI host controller setup */
229static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) 226static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
230{ 227{
231 struct rcar_pci_priv *priv = sys->private_data; 228 struct rcar_pci_priv *priv = sys->private_data;
232 void __iomem *reg = priv->reg; 229 void __iomem *reg = priv->reg;
@@ -292,6 +289,8 @@ static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys)
292 pci_add_resource(&sys->resources, &priv->io_res); 289 pci_add_resource(&sys->resources, &priv->io_res);
293 pci_add_resource(&sys->resources, &priv->mem_res); 290 pci_add_resource(&sys->resources, &priv->mem_res);
294 291
292 /* Setup bus number based on platform device id */
293 sys->busnr = to_platform_device(priv->dev)->id;
295 return 1; 294 return 1;
296} 295}
297 296
@@ -300,48 +299,13 @@ static struct pci_ops rcar_pci_ops = {
300 .write = rcar_pci_write_config, 299 .write = rcar_pci_write_config,
301}; 300};
302 301
303static struct hw_pci rcar_hw_pci __initdata = { 302static int rcar_pci_probe(struct platform_device *pdev)
304 .map_irq = rcar_pci_map_irq,
305 .ops = &rcar_pci_ops,
306 .setup = rcar_pci_setup,
307};
308
309static int rcar_pci_count __initdata;
310
311static int __init rcar_pci_add_controller(struct rcar_pci_priv *priv)
312{
313 void **private_data;
314 int count;
315
316 if (rcar_hw_pci.nr_controllers < rcar_pci_count)
317 goto add_priv;
318
319 /* (Re)allocate private data pointer array if needed */
320 count = rcar_pci_count + RCAR_PCI_NR_CONTROLLERS;
321 private_data = kzalloc(count * sizeof(void *), GFP_KERNEL);
322 if (!private_data)
323 return -ENOMEM;
324
325 rcar_pci_count = count;
326 if (rcar_hw_pci.private_data) {
327 memcpy(private_data, rcar_hw_pci.private_data,
328 rcar_hw_pci.nr_controllers * sizeof(void *));
329 kfree(rcar_hw_pci.private_data);
330 }
331
332 rcar_hw_pci.private_data = private_data;
333
334add_priv:
335 /* Add private data pointer to the array */
336 rcar_hw_pci.private_data[rcar_hw_pci.nr_controllers++] = priv;
337 return 0;
338}
339
340static int __init rcar_pci_probe(struct platform_device *pdev)
341{ 303{
342 struct resource *cfg_res, *mem_res; 304 struct resource *cfg_res, *mem_res;
343 struct rcar_pci_priv *priv; 305 struct rcar_pci_priv *priv;
344 void __iomem *reg; 306 void __iomem *reg;
307 struct hw_pci hw;
308 void *hw_private[1];
345 309
346 cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 310 cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
347 reg = devm_ioremap_resource(&pdev->dev, cfg_res); 311 reg = devm_ioremap_resource(&pdev->dev, cfg_res);
@@ -377,31 +341,27 @@ static int __init rcar_pci_probe(struct platform_device *pdev)
377 return priv->irq; 341 return priv->irq;
378 } 342 }
379 343
380 return rcar_pci_add_controller(priv); 344 hw_private[0] = priv;
345 memset(&hw, 0, sizeof(hw));
346 hw.nr_controllers = ARRAY_SIZE(hw_private);
347 hw.private_data = hw_private;
348 hw.map_irq = rcar_pci_map_irq;
349 hw.ops = &rcar_pci_ops;
350 hw.setup = rcar_pci_setup;
351 pci_common_init_dev(&pdev->dev, &hw);
352 return 0;
381} 353}
382 354
383static struct platform_driver rcar_pci_driver = { 355static struct platform_driver rcar_pci_driver = {
384 .driver = { 356 .driver = {
385 .name = "pci-rcar-gen2", 357 .name = "pci-rcar-gen2",
358 .owner = THIS_MODULE,
359 .suppress_bind_attrs = true,
386 }, 360 },
361 .probe = rcar_pci_probe,
387}; 362};
388 363
389static int __init rcar_pci_init(void) 364module_platform_driver(rcar_pci_driver);
390{
391 int retval;
392
393 retval = platform_driver_probe(&rcar_pci_driver, rcar_pci_probe);
394 if (!retval)
395 pci_common_init(&rcar_hw_pci);
396
397 /* Private data pointer array is not needed any more */
398 kfree(rcar_hw_pci.private_data);
399 rcar_hw_pci.private_data = NULL;
400
401 return retval;
402}
403
404subsys_initcall(rcar_pci_init);
405 365
406MODULE_LICENSE("GPL v2"); 366MODULE_LICENSE("GPL v2");
407MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI"); 367MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI");