static ssize_t driver_override_show(struct device *_dev, struct device_attribute *attr, char *buf) { struct amba_device *dev = to_amba_device(_dev); ssize_t len; device_lock(_dev); len = sprintf(buf, "%s\n", dev->driver_override); device_unlock(_dev); return len; }
static int amba_match(struct device *dev, struct device_driver *drv) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(drv); /* When driver_override is set, only bind to the matching driver */ if (pcdev->driver_override) return !strcmp(pcdev->driver_override, drv->name); return amba_lookup(pcdrv->id_table, pcdev) != NULL; }
static int amba_legacy_suspend(struct device *dev, pm_message_t mesg) { struct amba_driver *adrv = to_amba_driver(dev->driver); struct amba_device *adev = to_amba_device(dev); int ret = 0; if (dev->driver && adrv->suspend) ret = adrv->suspend(adev, mesg); return ret; }
static int amba_legacy_resume(struct device *dev) { struct amba_driver *adrv = to_amba_driver(dev->driver); struct amba_device *adev = to_amba_device(dev); int ret = 0; if (dev->driver && adrv->resume) ret = adrv->resume(adev); return ret; }
static int amba_uevent(struct device *dev, struct kobj_uevent_env *env) { struct amba_device *pcdev = to_amba_device(dev); int retval = 0; retval = add_uevent_var(env, "AMBA_ID=%08x", pcdev->periphid); if (retval) return retval; retval = add_uevent_var(env, "MODALIAS=amba:d%08X", pcdev->periphid); return retval; }
/* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to * enable/disable the bus clock at runtime PM suspend/resume as this * does not result in loss of context. */ static int amba_pm_runtime_suspend(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); int ret = pm_generic_runtime_suspend(dev); if (ret == 0 && dev->driver) { if (pm_runtime_is_irq_safe(dev)) clk_disable(pcdev->pclk); else clk_disable_unprepare(pcdev->pclk); } return ret; }
static int amba_pm_runtime_resume(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); int ret; if (dev->driver) { ret = clk_enable(pcdev->pclk); /* Failure is probably fatal to the system, but... */ if (ret) return ret; } return pm_generic_runtime_resume(dev); }
static int amba_find_match(struct device *dev, void *data) { struct find_data *d = data; struct amba_device *pcdev = to_amba_device(dev); int r; r = (pcdev->periphid & d->mask) == d->id; if (d->parent) r &= d->parent == dev->parent; if (d->busid) r &= strcmp(dev_name(dev), d->busid) == 0; if (r) { get_device(dev); d->dev = pcdev; } return r; }
static int amba_remove(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *drv = to_amba_driver(dev->driver); int ret; pm_runtime_get_sync(dev); ret = drv->remove(pcdev); pm_runtime_put_noidle(dev); /* Undo the runtime PM settings in amba_probe() */ pm_runtime_disable(dev); pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); return ret; }
/* * These are the device model conversion veneers; they convert the * device model structures to our more specific structures. */ static int amba_probe(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(dev->driver); struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); int ret; do { ret = amba_get_enable_pclk(pcdev); if (ret) break; ret = pcdrv->probe(pcdev, id); if (ret == 0) break; amba_put_disable_pclk(pcdev); } while (0); return ret; }
/* * These are the device model conversion veneers; they convert the * device model structures to our more specific structures. */ static int amba_probe(struct device *dev) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(dev->driver); const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev); int ret; do { ret = of_clk_set_defaults(dev->of_node, false); if (ret < 0) break; ret = dev_pm_domain_attach(dev, true); if (ret == -EPROBE_DEFER) break; ret = amba_get_enable_pclk(pcdev); if (ret) { dev_pm_domain_detach(dev, true); break; } pm_runtime_get_noresume(dev); pm_runtime_set_active(dev); pm_runtime_enable(dev); ret = pcdrv->probe(pcdev, id); if (ret == 0) break; pm_runtime_disable(dev); pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); dev_pm_domain_detach(dev, true); } while (0); return ret; }
static int xen_amba_notifier(struct notifier_block *nb, unsigned long action, void *data) { struct amba_device *adev = to_amba_device(data); int r = 0; switch (action) { case BUS_NOTIFY_ADD_DEVICE: r = xen_map_device_mmio(&adev->res, 1); break; case BUS_NOTIFY_DEL_DEVICE: r = xen_unmap_device_mmio(&adev->res, 1); break; default: return NOTIFY_DONE; } if (r) dev_err(&adev->dev, "AMBA: Failed to %s device %s MMIO!\n", action == BUS_NOTIFY_ADD_DEVICE ? "map" : (action == BUS_NOTIFY_DEL_DEVICE ? "unmap" : "?"), adev->dev.init_name); return NOTIFY_OK; }
static void amba_shutdown(struct device *dev) { struct amba_driver *drv = to_amba_driver(dev->driver); drv->shutdown(to_amba_device(dev)); }
static int amba_remove(struct device *dev) { struct amba_driver *drv = to_amba_driver(dev->driver); return drv->remove(to_amba_device(dev)); }