Lines Matching +full:bus +full:- +full:specific
2 * Bus driver for MIPS Common Device Memory Map (CDMM).
4 * Copyright (C) 2014-2015 Imagination Technologies Ltd.
45 /* Bus operations */
53 for (; table->type; ++table) { in mips_cdmm_lookup()
54 ret = (dev->type == table->type); in mips_cdmm_lookup()
67 return mips_cdmm_lookup(cdrv->id_table, cdev) != NULL; in mips_cdmm_match()
75 retval = add_uevent_var(env, "CDMM_CPU=%u", cdev->cpu); in mips_cdmm_uevent()
79 retval = add_uevent_var(env, "CDMM_TYPE=0x%02x", cdev->type); in mips_cdmm_uevent()
83 retval = add_uevent_var(env, "CDMM_REV=%u", cdev->rev); in mips_cdmm_uevent()
87 retval = add_uevent_var(env, "MODALIAS=mipscdmm:t%02X", cdev->type); in mips_cdmm_uevent()
102 CDMM_ATTR(cpu, "%u\n", dev->cpu);
103 CDMM_ATTR(type, "0x%02x\n", dev->type);
104 CDMM_ATTR(revision, "%u\n", dev->rev);
105 CDMM_ATTR(modalias, "mipscdmm:t%02X\n", dev->type);
107 (unsigned long long)dev->res.start,
108 (unsigned long long)dev->res.end,
109 dev->res.flags);
140 * struct mips_cdmm_work_dev - Data for per-device call work.
150 * mips_cdmm_void_work() - Call a void returning CDMM driver callback.
159 void (*fn)(struct mips_cdmm_device *) = work->fn; in mips_cdmm_void_work()
161 fn(work->dev); in mips_cdmm_void_work()
166 * mips_cdmm_int_work() - Call an int returning CDMM driver callback.
175 int (*fn)(struct mips_cdmm_device *) = work->fn; in mips_cdmm_int_work()
177 return fn(work->dev); in mips_cdmm_int_work()
184 * BUILD_PERCPU_HELPER() - Helper to call a CDMM driver callback on right CPU.
188 * Generates a specific device callback function to call a CDMM driver callback
196 struct mips_cdmm_driver *cdrv = to_mips_cdmm_driver(dev->driver); \
198 .fn = cdrv->_name, \
202 _BUILD_RET_##_ret work_on_cpu(cdev->cpu, \
215 * mips_cdmm_driver_register() - Register a CDMM driver. in BUILD_PERCPU_HELPER()
225 drv->drv.bus = &mips_cdmm_bustype; in BUILD_PERCPU_HELPER()
227 if (drv->probe) in BUILD_PERCPU_HELPER()
228 drv->drv.probe = mips_cdmm_probe; in BUILD_PERCPU_HELPER()
229 if (drv->remove) in BUILD_PERCPU_HELPER()
230 drv->drv.remove = mips_cdmm_remove; in BUILD_PERCPU_HELPER()
231 if (drv->shutdown) in BUILD_PERCPU_HELPER()
232 drv->drv.shutdown = mips_cdmm_shutdown; in BUILD_PERCPU_HELPER()
234 return driver_register(&drv->drv); in BUILD_PERCPU_HELPER()
239 * mips_cdmm_driver_unregister() - Unregister a CDMM driver.
246 driver_unregister(&drv->drv); in mips_cdmm_driver_unregister()
251 /* CDMM initialisation and bus discovery */
254 * struct mips_cdmm_bus - Info about CDMM bus.
259 * @discovered: Whether the devices on the bus have been discovered yet.
260 * @offline: Whether the CDMM bus is going offline (or very early
275 static atomic_t mips_cdmm_next_id = ATOMIC_INIT(-1);
278 * mips_cdmm_get_bus() - Get the per-CPU CDMM bus information.
280 * Get information about the per-CPU CDMM bus, if the bus is present.
283 * pre-emption or by running from a pinned kernel thread.
285 * Returns: Pointer to CDMM bus information for the current CPU.
286 * May return ERR_PTR(-errno) in case of error, so check with
291 struct mips_cdmm_bus *bus, **bus_p; in mips_cdmm_get_bus() local
296 return ERR_PTR(-ENODEV); in mips_cdmm_get_bus()
299 /* Avoid early use of per-cpu primitives before initialised */ in mips_cdmm_get_bus()
303 /* Get bus pointer */ in mips_cdmm_get_bus()
306 bus = *bus_p; in mips_cdmm_get_bus()
308 if (unlikely(!bus)) { in mips_cdmm_get_bus()
309 bus = kzalloc(sizeof(*bus), GFP_ATOMIC); in mips_cdmm_get_bus()
310 if (unlikely(!bus)) in mips_cdmm_get_bus()
311 bus = ERR_PTR(-ENOMEM); in mips_cdmm_get_bus()
313 *bus_p = bus; in mips_cdmm_get_bus()
316 return bus; in mips_cdmm_get_bus()
320 * mips_cdmm_cur_base() - Find current physical base address of CDMM region.
337 * mips_cdmm_phys_base() - Choose a physical base address for CDMM region.
340 * platform specific, so this weak function can be overridden by platform
342 * By default this method tries to find a CDMM-specific node in the system
351 np = of_find_compatible_node(NULL, NULL, "mti,mips-cdmm"); in mips_cdmm_phys_base()
363 * mips_cdmm_setup() - Ensure the CDMM bus is initialised and usable.
364 * @bus: Pointer to bus information for current CPU.
365 * IS_ERR(bus) is checked, so no need for caller to check.
368 * pre-emption or by running from a pinned kernel thread.
370 * Returns 0 on success, -errno on failure.
372 static int mips_cdmm_setup(struct mips_cdmm_bus *bus) in mips_cdmm_setup() argument
377 if (IS_ERR(bus)) in mips_cdmm_setup()
378 return PTR_ERR(bus); in mips_cdmm_setup()
381 /* Don't set up bus a second time unless marked offline */ in mips_cdmm_setup()
382 if (bus->offline) { in mips_cdmm_setup()
384 if (bus->phys == mips_cdmm_cur_base()) in mips_cdmm_setup()
390 bus->offline = false; in mips_cdmm_setup()
391 } else if (bus->phys > 1) { in mips_cdmm_setup()
396 if (!bus->phys) in mips_cdmm_setup()
397 bus->phys = mips_cdmm_cur_base(); in mips_cdmm_setup()
399 if (!bus->phys) in mips_cdmm_setup()
400 bus->phys = mips_cdmm_phys_base(); in mips_cdmm_setup()
402 if (!bus->phys) in mips_cdmm_setup()
403 bus->phys = mips_cdmm_default_base; in mips_cdmm_setup()
405 if (!bus->phys) { in mips_cdmm_setup()
406 bus->phys = 1; in mips_cdmm_setup()
416 if (bus->phys == 1) { in mips_cdmm_setup()
417 ret = -ENOMEM; in mips_cdmm_setup()
421 mips_cdmm_default_base = bus->phys; in mips_cdmm_setup()
424 smp_processor_id(), &bus->phys); in mips_cdmm_setup()
428 cdmmbase &= (1ul << MIPS_CDMMBASE_ADDR_SHIFT) - 1; in mips_cdmm_setup()
429 cdmmbase |= (bus->phys >> MIPS_CDMMBASE_ADDR_START) in mips_cdmm_setup()
435 bus->regs = (void __iomem *)CKSEG1ADDR(bus->phys); in mips_cdmm_setup()
436 bus->drbs = 1 + ((cdmmbase & MIPS_CDMMBASE_SIZE) >> in mips_cdmm_setup()
438 bus->drbs_reserved = !!(cdmmbase & MIPS_CDMMBASE_CI); in mips_cdmm_setup()
446 * mips_cdmm_early_probe() - Minimally probe for a specific device on CDMM.
449 * Minimally configure the in-CPU Common Device Memory Map (CDMM) and look for a
450 * specific device. This can be used to find a device very early in boot for
454 * pre-emption or by running from a pinned kernel thread.
459 * May return IOMEM_ERR_PTR(-errno) in case of error, so check with
464 struct mips_cdmm_bus *bus; in mips_cdmm_early_probe() local
471 return IOMEM_ERR_PTR(-ENODEV); in mips_cdmm_early_probe()
473 bus = mips_cdmm_get_bus(); in mips_cdmm_early_probe()
474 err = mips_cdmm_setup(bus); in mips_cdmm_early_probe()
479 drb = bus->drbs_reserved; in mips_cdmm_early_probe()
480 cdmm = bus->regs; in mips_cdmm_early_probe()
482 /* Look for a specific device type */ in mips_cdmm_early_probe()
483 for (; drb < bus->drbs; drb += size + 1) { in mips_cdmm_early_probe()
491 return IOMEM_ERR_PTR(-ENODEV); in mips_cdmm_early_probe()
496 * mips_cdmm_release() - Release a removed CDMM device.
510 * mips_cdmm_bus_discover() - Discover the devices on the CDMM bus.
511 * @bus: CDMM bus information, must already be set up.
513 static void mips_cdmm_bus_discover(struct mips_cdmm_bus *bus) in mips_cdmm_bus_discover() argument
524 drb = bus->drbs_reserved; in mips_cdmm_bus_discover()
525 cdmm = bus->regs; in mips_cdmm_bus_discover()
528 bus->discovered = true; in mips_cdmm_bus_discover()
529 pr_info("cdmm%u discovery (%u blocks)\n", cpu, bus->drbs); in mips_cdmm_bus_discover()
530 for (; drb < bus->drbs; drb += size + 1) { in mips_cdmm_bus_discover()
539 pr_info("cdmm%u-%u: @%u (%#x..%#x), type 0x%02x, rev %u\n", in mips_cdmm_bus_discover()
541 (drb + size + 1) * CDMM_DRB_SIZE - 1, in mips_cdmm_bus_discover()
548 dev->cpu = cpu; in mips_cdmm_bus_discover()
549 dev->res.start = bus->phys + drb * CDMM_DRB_SIZE; in mips_cdmm_bus_discover()
550 dev->res.end = bus->phys + in mips_cdmm_bus_discover()
551 (drb + size + 1) * CDMM_DRB_SIZE - 1; in mips_cdmm_bus_discover()
552 dev->res.flags = IORESOURCE_MEM; in mips_cdmm_bus_discover()
553 dev->type = type; in mips_cdmm_bus_discover()
554 dev->rev = rev; in mips_cdmm_bus_discover()
555 dev->dev.parent = get_cpu_device(cpu); in mips_cdmm_bus_discover()
556 dev->dev.bus = &mips_cdmm_bustype; in mips_cdmm_bus_discover()
557 dev->dev.id = atomic_inc_return(&mips_cdmm_next_id); in mips_cdmm_bus_discover()
558 dev->dev.release = mips_cdmm_release; in mips_cdmm_bus_discover()
560 dev_set_name(&dev->dev, "cdmm%u-%u", cpu, id); in mips_cdmm_bus_discover()
562 ret = device_register(&dev->dev); in mips_cdmm_bus_discover()
564 put_device(&dev->dev); in mips_cdmm_bus_discover()
580 * BUILD_PERDEV_HELPER() - Helper to call a CDMM driver callback if CPU matches.
583 * Generates a bus_for_each_dev callback function to call a specific CDMM driver
599 if (cdev->cpu != cpu || !dev->driver) \
602 cdrv = to_mips_cdmm_driver(dev->driver); \
603 if (!cdrv->_name) \
605 return cdrv->_name(cdev); \
613 * mips_cdmm_cpu_down_prep() - Callback for CPUHP DOWN_PREP: in BUILD_PERDEV_HELPER()
614 * Tear down the CDMM bus. in BUILD_PERDEV_HELPER()
622 struct mips_cdmm_bus *bus; in BUILD_PERDEV_HELPER() local
625 /* Inform all the devices on the bus */ in BUILD_PERDEV_HELPER()
630 * While bus is offline, each use of it should reconfigure it just in in BUILD_PERDEV_HELPER()
633 bus = mips_cdmm_get_bus(); in BUILD_PERDEV_HELPER()
634 if (!IS_ERR(bus)) in BUILD_PERDEV_HELPER()
635 bus->offline = true; in BUILD_PERDEV_HELPER()
641 * mips_cdmm_cpu_online() - Callback for CPUHP ONLINE: Bring up the CDMM bus.
654 struct mips_cdmm_bus *bus; in mips_cdmm_cpu_online() local
657 bus = mips_cdmm_get_bus(); in mips_cdmm_cpu_online()
658 ret = mips_cdmm_setup(bus); in mips_cdmm_cpu_online()
662 /* Bus now set up, so we can drop the offline flag if still set */ in mips_cdmm_cpu_online()
663 bus->offline = false; in mips_cdmm_cpu_online()
665 if (!bus->discovered) in mips_cdmm_cpu_online()
666 mips_cdmm_bus_discover(bus); in mips_cdmm_cpu_online()
668 /* Inform all the devices on the bus */ in mips_cdmm_cpu_online()
676 * mips_cdmm_init() - Initialise CDMM bus.
678 * Initialise CDMM bus, discover CDMM devices for online CPUs, and arrange for
685 /* Register the bus */ in mips_cdmm_init()
691 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "bus/cdmm:online", in mips_cdmm_init()