diff options
author | Magnus Damm <damm@opensource.se> | 2014-02-17 21:11:21 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-02-18 15:20:11 -0500 |
commit | 546cadda3575153bdd0af4febfe958cc5945f95a (patch) | |
tree | 1763ec3a9bf606599935076da836d0a5177dbef2 /drivers/pci/host/pci-rcar-gen2.c | |
parent | e64a2a973e179613489a0ddb1bb550dff108164e (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/host/pci-rcar-gen2.c')
-rw-r--r-- | drivers/pci/host/pci-rcar-gen2.c | 80 |
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 | |||
97 | struct rcar_pci_priv { | 94 | struct 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 */ |
180 | static int __init rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 177 | static 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 */ |
229 | static int __init rcar_pci_setup(int nr, struct pci_sys_data *sys) | 226 | static 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 | ||
303 | static struct hw_pci rcar_hw_pci __initdata = { | 302 | static 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 | |||
309 | static int rcar_pci_count __initdata; | ||
310 | |||
311 | static 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 | |||
334 | add_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 | |||
340 | static 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 | ||
383 | static struct platform_driver rcar_pci_driver = { | 355 | static 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 | ||
389 | static int __init rcar_pci_init(void) | 364 | module_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 | |||
404 | subsys_initcall(rcar_pci_init); | ||
405 | 365 | ||
406 | MODULE_LICENSE("GPL v2"); | 366 | MODULE_LICENSE("GPL v2"); |
407 | MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI"); | 367 | MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI"); |