|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | * Copyright 2023 Google LLC. | 
|  | */ | 
|  |  | 
|  | #include <linux/device.h> | 
|  | #include <linux/spmi.h> | 
|  |  | 
|  | static void devm_spmi_controller_release(struct device *parent, void *res) | 
|  | { | 
|  | spmi_controller_put(*(struct spmi_controller **)res); | 
|  | } | 
|  |  | 
|  | struct spmi_controller *devm_spmi_controller_alloc(struct device *parent, size_t size) | 
|  | { | 
|  | struct spmi_controller **ptr, *ctrl; | 
|  |  | 
|  | ptr = devres_alloc(devm_spmi_controller_release, sizeof(*ptr), GFP_KERNEL); | 
|  | if (!ptr) | 
|  | return ERR_PTR(-ENOMEM); | 
|  |  | 
|  | ctrl = spmi_controller_alloc(parent, size); | 
|  | if (IS_ERR(ctrl)) { | 
|  | devres_free(ptr); | 
|  | return ctrl; | 
|  | } | 
|  |  | 
|  | *ptr = ctrl; | 
|  | devres_add(parent, ptr); | 
|  |  | 
|  | return ctrl; | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(devm_spmi_controller_alloc); | 
|  |  | 
|  | static void devm_spmi_controller_remove(struct device *parent, void *res) | 
|  | { | 
|  | spmi_controller_remove(*(struct spmi_controller **)res); | 
|  | } | 
|  |  | 
|  | int devm_spmi_controller_add(struct device *parent, struct spmi_controller *ctrl) | 
|  | { | 
|  | struct spmi_controller **ptr; | 
|  | int ret; | 
|  |  | 
|  | ptr = devres_alloc(devm_spmi_controller_remove, sizeof(*ptr), GFP_KERNEL); | 
|  | if (!ptr) | 
|  | return -ENOMEM; | 
|  |  | 
|  | ret = spmi_controller_add(ctrl); | 
|  | if (ret) { | 
|  | devres_free(ptr); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | *ptr = ctrl; | 
|  | devres_add(parent, ptr); | 
|  |  | 
|  | return 0; | 
|  |  | 
|  | } | 
|  | EXPORT_SYMBOL_GPL(devm_spmi_controller_add); | 
|  |  | 
|  | MODULE_LICENSE("GPL"); | 
|  | MODULE_DESCRIPTION("SPMI devres helpers"); |