diff options
Diffstat (limited to 'drivers/spmi/spmi.c')
| -rw-r--r-- | drivers/spmi/spmi.c | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c index c16b60f645a4..3cf8d9bd4566 100644 --- a/drivers/spmi/spmi.c +++ b/drivers/spmi/spmi.c @@ -23,6 +23,7 @@ static DEFINE_IDA(ctrl_ida); static void spmi_dev_release(struct device *dev) { struct spmi_device *sdev = to_spmi_device(dev); + kfree(sdev); } @@ -33,7 +34,8 @@ static const struct device_type spmi_dev_type = { static void spmi_ctrl_release(struct device *dev) { struct spmi_controller *ctrl = to_spmi_controller(dev); - ida_simple_remove(&ctrl_ida, ctrl->nr); + + ida_free(&ctrl_ida, ctrl->nr); kfree(ctrl); } @@ -41,7 +43,7 @@ static const struct device_type spmi_ctrl_type = { .release = spmi_ctrl_release, }; -static int spmi_device_match(struct device *dev, struct device_driver *drv) +static int spmi_device_match(struct device *dev, const struct device_driver *drv) { if (of_driver_match_device(dev, drv)) return 1; @@ -343,21 +345,29 @@ fail_probe: return err; } -static int spmi_drv_remove(struct device *dev) +static void spmi_drv_remove(struct device *dev) { const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); pm_runtime_get_sync(dev); - sdrv->remove(to_spmi_device(dev)); + if (sdrv->remove) + sdrv->remove(to_spmi_device(dev)); pm_runtime_put_noidle(dev); pm_runtime_disable(dev); pm_runtime_set_suspended(dev); pm_runtime_put_noidle(dev); - return 0; } -static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) +static void spmi_drv_shutdown(struct device *dev) +{ + const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); + + if (sdrv && sdrv->shutdown) + sdrv->shutdown(to_spmi_device(dev)); +} + +static int spmi_drv_uevent(const struct device *dev, struct kobj_uevent_env *env) { int ret; @@ -368,16 +378,37 @@ static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) return 0; } -static struct bus_type spmi_bus_type = { +static const struct bus_type spmi_bus_type = { .name = "spmi", .match = spmi_device_match, .probe = spmi_drv_probe, .remove = spmi_drv_remove, + .shutdown = spmi_drv_shutdown, .uevent = spmi_drv_uevent, }; /** - * spmi_controller_alloc() - Allocate a new SPMI device + * spmi_find_device_by_of_node() - look up an SPMI device from a device node + * + * @np: device node + * + * Takes a reference to the embedded struct device which needs to be dropped + * after use. + * + * Returns the struct spmi_device associated with a device node or NULL. + */ +struct spmi_device *spmi_find_device_by_of_node(struct device_node *np) +{ + struct device *dev = bus_find_device_by_of_node(&spmi_bus_type, np); + + if (dev) + return to_spmi_device(dev); + return NULL; +} +EXPORT_SYMBOL_GPL(spmi_find_device_by_of_node); + +/** + * spmi_device_alloc() - Allocate a new SPMI device * @ctrl: associated controller * * Caller is responsible for either calling spmi_device_add() to add the @@ -417,11 +448,11 @@ struct spmi_controller *spmi_controller_alloc(struct device *parent, int id; if (WARN_ON(!parent)) - return NULL; + return ERR_PTR(-EINVAL); ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL); if (!ctrl) - return NULL; + return ERR_PTR(-ENOMEM); device_initialize(&ctrl->dev); ctrl->dev.type = &spmi_ctrl_type; @@ -430,12 +461,12 @@ struct spmi_controller *spmi_controller_alloc(struct device *parent, ctrl->dev.of_node = parent->of_node; spmi_controller_set_drvdata(ctrl, &ctrl[1]); - id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); + id = ida_alloc(&ctrl_ida, GFP_KERNEL); if (id < 0) { dev_err(parent, "unable to allocate SPMI controller identifier.\n"); spmi_controller_put(ctrl); - return NULL; + return ERR_PTR(id); } ctrl->nr = id; @@ -486,8 +517,8 @@ static void of_spmi_register_devices(struct spmi_controller *ctrl) if (!sdev) continue; - sdev->dev.of_node = node; - sdev->usid = (u8) reg[0]; + device_set_node(&sdev->dev, of_fwnode_handle(node)); + sdev->usid = (u8)reg[0]; err = spmi_device_add(sdev); if (err) { @@ -531,6 +562,7 @@ EXPORT_SYMBOL_GPL(spmi_controller_add); static int spmi_ctrl_remove_device(struct device *dev, void *data) { struct spmi_device *spmidev = to_spmi_device(dev); + if (dev->type == &spmi_dev_type) spmi_device_remove(spmidev); return 0; @@ -545,20 +577,18 @@ static int spmi_ctrl_remove_device(struct device *dev, void *data) */ void spmi_controller_remove(struct spmi_controller *ctrl) { - int dummy; - if (!ctrl) return; - dummy = device_for_each_child(&ctrl->dev, NULL, - spmi_ctrl_remove_device); + device_for_each_child(&ctrl->dev, NULL, spmi_ctrl_remove_device); device_del(&ctrl->dev); } EXPORT_SYMBOL_GPL(spmi_controller_remove); /** - * spmi_driver_register() - Register client driver with SPMI core + * __spmi_driver_register() - Register client driver with SPMI core * @sdrv: client driver to be associated with client-device. + * @owner: module owner * * This API will register the client driver with the SPMI framework. * It is typically called from the driver's module-init function. |
