Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / drivers / reset / amlogic / reset-meson-aux.c
blob61ce515d92a2d1fd0bb7b9a6d52cc7aa788c2ee9
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3 * Amlogic Meson Reset Auxiliary driver
5 * Copyright (c) 2024 BayLibre, SAS.
6 * Author: Jerome Brunet <jbrunet@baylibre.com>
7 */
9 #include <linux/err.h>
10 #include <linux/module.h>
11 #include <linux/auxiliary_bus.h>
12 #include <linux/regmap.h>
13 #include <linux/reset-controller.h>
14 #include <linux/slab.h>
16 #include "reset-meson.h"
17 #include <soc/amlogic/reset-meson-aux.h>
19 static DEFINE_IDA(meson_rst_aux_ida);
21 struct meson_reset_adev {
22 struct auxiliary_device adev;
23 struct regmap *map;
26 #define to_meson_reset_adev(_adev) \
27 container_of((_adev), struct meson_reset_adev, adev)
29 static const struct meson_reset_param meson_g12a_audio_param = {
30 .reset_ops = &meson_reset_toggle_ops,
31 .reset_num = 26,
32 .level_offset = 0x24,
35 static const struct meson_reset_param meson_sm1_audio_param = {
36 .reset_ops = &meson_reset_toggle_ops,
37 .reset_num = 39,
38 .level_offset = 0x28,
41 static const struct auxiliary_device_id meson_reset_aux_ids[] = {
43 .name = "axg-audio-clkc.rst-g12a",
44 .driver_data = (kernel_ulong_t)&meson_g12a_audio_param,
45 }, {
46 .name = "axg-audio-clkc.rst-sm1",
47 .driver_data = (kernel_ulong_t)&meson_sm1_audio_param,
48 }, {}
50 MODULE_DEVICE_TABLE(auxiliary, meson_reset_aux_ids);
52 static int meson_reset_aux_probe(struct auxiliary_device *adev,
53 const struct auxiliary_device_id *id)
55 const struct meson_reset_param *param =
56 (const struct meson_reset_param *)(id->driver_data);
57 struct meson_reset_adev *raux =
58 to_meson_reset_adev(adev);
60 return meson_reset_controller_register(&adev->dev, raux->map, param);
63 static struct auxiliary_driver meson_reset_aux_driver = {
64 .probe = meson_reset_aux_probe,
65 .id_table = meson_reset_aux_ids,
67 module_auxiliary_driver(meson_reset_aux_driver);
69 static void meson_rst_aux_release(struct device *dev)
71 struct auxiliary_device *adev = to_auxiliary_dev(dev);
72 struct meson_reset_adev *raux =
73 to_meson_reset_adev(adev);
75 ida_free(&meson_rst_aux_ida, adev->id);
76 kfree(raux);
79 static void meson_rst_aux_unregister_adev(void *_adev)
81 struct auxiliary_device *adev = _adev;
83 auxiliary_device_delete(adev);
84 auxiliary_device_uninit(adev);
87 int devm_meson_rst_aux_register(struct device *dev,
88 struct regmap *map,
89 const char *adev_name)
91 struct meson_reset_adev *raux;
92 struct auxiliary_device *adev;
93 int ret;
95 raux = kzalloc(sizeof(*raux), GFP_KERNEL);
96 if (!raux)
97 return -ENOMEM;
99 ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL);
100 if (ret < 0)
101 goto raux_free;
103 raux->map = map;
105 adev = &raux->adev;
106 adev->id = ret;
107 adev->name = adev_name;
108 adev->dev.parent = dev;
109 adev->dev.release = meson_rst_aux_release;
110 device_set_of_node_from_dev(&adev->dev, dev);
112 ret = auxiliary_device_init(adev);
113 if (ret)
114 goto ida_free;
116 ret = __auxiliary_device_add(adev, dev->driver->name);
117 if (ret) {
118 auxiliary_device_uninit(adev);
119 return ret;
122 return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev,
123 adev);
125 ida_free:
126 ida_free(&meson_rst_aux_ida, adev->id);
127 raux_free:
128 kfree(raux);
129 return ret;
131 EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register);
133 MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver");
134 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
135 MODULE_LICENSE("Dual BSD/GPL");
136 MODULE_IMPORT_NS("MESON_RESET");