1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
3 * Amlogic Meson Reset Auxiliary driver
5 * Copyright (c) 2024 BayLibre, SAS.
6 * Author: Jerome Brunet <jbrunet@baylibre.com>
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
;
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
,
35 static const struct meson_reset_param meson_sm1_audio_param
= {
36 .reset_ops
= &meson_reset_toggle_ops
,
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
,
46 .name
= "axg-audio-clkc.rst-sm1",
47 .driver_data
= (kernel_ulong_t
)&meson_sm1_audio_param
,
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
);
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
,
89 const char *adev_name
)
91 struct meson_reset_adev
*raux
;
92 struct auxiliary_device
*adev
;
95 raux
= kzalloc(sizeof(*raux
), GFP_KERNEL
);
99 ret
= ida_alloc(&meson_rst_aux_ida
, GFP_KERNEL
);
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
);
116 ret
= __auxiliary_device_add(adev
, dev
->driver
->name
);
118 auxiliary_device_uninit(adev
);
122 return devm_add_action_or_reset(dev
, meson_rst_aux_unregister_adev
,
126 ida_free(&meson_rst_aux_ida
, adev
->id
);
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");