-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'reset-amlogic-aux' into clk-meson-next
Pull amlogic auxiliary reset support to continue removing reset drivers from amlogic clocks * tag 'reset-amlogic-aux': reset: amlogic: Fix small whitespace issue reset: amlogic: add auxiliary reset driver support reset: amlogic: split the device core and platform probe reset: amlogic: move drivers to a dedicated directory reset: amlogic: add reset status support reset: amlogic: use reset number instead of register count reset: amlogic: add driver parameters reset: amlogic: make parameters unsigned reset: amlogic: use generic data matching function reset: amlogic: convert driver to regmap
- Loading branch information
Showing
11 changed files
with
467 additions
and
175 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
config RESET_MESON_COMMON | ||
tristate | ||
select REGMAP | ||
|
||
config RESET_MESON | ||
tristate "Meson Reset Driver" | ||
depends on ARCH_MESON || COMPILE_TEST | ||
default ARCH_MESON | ||
select REGMAP_MMIO | ||
select RESET_MESON_COMMON | ||
help | ||
This enables the reset driver for Amlogic SoCs. | ||
|
||
config RESET_MESON_AUX | ||
tristate "Meson Reset Auxiliary Driver" | ||
depends on ARCH_MESON || COMPILE_TEST | ||
select AUXILIARY_BUS | ||
select RESET_MESON_COMMON | ||
help | ||
This enables the reset auxiliary driver for Amlogic SoCs. | ||
|
||
config RESET_MESON_AUDIO_ARB | ||
tristate "Meson Audio Memory Arbiter Reset Driver" | ||
depends on ARCH_MESON || COMPILE_TEST | ||
help | ||
This enables the reset driver for Audio Memory Arbiter of | ||
Amlogic's A113 based SoCs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
obj-$(CONFIG_RESET_MESON) += reset-meson.o | ||
obj-$(CONFIG_RESET_MESON_AUX) += reset-meson-aux.o | ||
obj-$(CONFIG_RESET_MESON_COMMON) += reset-meson-common.o | ||
obj-$(CONFIG_RESET_MESON_AUDIO_ARB) += reset-meson-audio-arb.o |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | ||
/* | ||
* Amlogic Meson Reset Auxiliary driver | ||
* | ||
* Copyright (c) 2024 BayLibre, SAS. | ||
* Author: Jerome Brunet <jbrunet@baylibre.com> | ||
*/ | ||
|
||
#include <linux/err.h> | ||
#include <linux/module.h> | ||
#include <linux/auxiliary_bus.h> | ||
#include <linux/regmap.h> | ||
#include <linux/reset-controller.h> | ||
#include <linux/slab.h> | ||
|
||
#include "reset-meson.h" | ||
#include <soc/amlogic/reset-meson-aux.h> | ||
|
||
static DEFINE_IDA(meson_rst_aux_ida); | ||
|
||
struct meson_reset_adev { | ||
struct auxiliary_device adev; | ||
struct regmap *map; | ||
}; | ||
|
||
#define to_meson_reset_adev(_adev) \ | ||
container_of((_adev), struct meson_reset_adev, adev) | ||
|
||
static const struct meson_reset_param meson_g12a_audio_param = { | ||
.reset_ops = &meson_reset_toggle_ops, | ||
.reset_num = 26, | ||
.level_offset = 0x24, | ||
}; | ||
|
||
static const struct meson_reset_param meson_sm1_audio_param = { | ||
.reset_ops = &meson_reset_toggle_ops, | ||
.reset_num = 39, | ||
.level_offset = 0x28, | ||
}; | ||
|
||
static const struct auxiliary_device_id meson_reset_aux_ids[] = { | ||
{ | ||
.name = "axg-audio-clkc.rst-g12a", | ||
.driver_data = (kernel_ulong_t)&meson_g12a_audio_param, | ||
}, { | ||
.name = "axg-audio-clkc.rst-sm1", | ||
.driver_data = (kernel_ulong_t)&meson_sm1_audio_param, | ||
}, {} | ||
}; | ||
MODULE_DEVICE_TABLE(auxiliary, meson_reset_aux_ids); | ||
|
||
static int meson_reset_aux_probe(struct auxiliary_device *adev, | ||
const struct auxiliary_device_id *id) | ||
{ | ||
const struct meson_reset_param *param = | ||
(const struct meson_reset_param *)(id->driver_data); | ||
struct meson_reset_adev *raux = | ||
to_meson_reset_adev(adev); | ||
|
||
return meson_reset_controller_register(&adev->dev, raux->map, param); | ||
} | ||
|
||
static struct auxiliary_driver meson_reset_aux_driver = { | ||
.probe = meson_reset_aux_probe, | ||
.id_table = meson_reset_aux_ids, | ||
}; | ||
module_auxiliary_driver(meson_reset_aux_driver); | ||
|
||
static void meson_rst_aux_release(struct device *dev) | ||
{ | ||
struct auxiliary_device *adev = to_auxiliary_dev(dev); | ||
struct meson_reset_adev *raux = | ||
to_meson_reset_adev(adev); | ||
|
||
ida_free(&meson_rst_aux_ida, adev->id); | ||
kfree(raux); | ||
} | ||
|
||
static void meson_rst_aux_unregister_adev(void *_adev) | ||
{ | ||
struct auxiliary_device *adev = _adev; | ||
|
||
auxiliary_device_delete(adev); | ||
auxiliary_device_uninit(adev); | ||
} | ||
|
||
int devm_meson_rst_aux_register(struct device *dev, | ||
struct regmap *map, | ||
const char *adev_name) | ||
{ | ||
struct meson_reset_adev *raux; | ||
struct auxiliary_device *adev; | ||
int ret; | ||
|
||
raux = kzalloc(sizeof(*raux), GFP_KERNEL); | ||
if (!raux) | ||
return -ENOMEM; | ||
|
||
ret = ida_alloc(&meson_rst_aux_ida, GFP_KERNEL); | ||
if (ret < 0) | ||
goto raux_free; | ||
|
||
raux->map = map; | ||
|
||
adev = &raux->adev; | ||
adev->id = ret; | ||
adev->name = adev_name; | ||
adev->dev.parent = dev; | ||
adev->dev.release = meson_rst_aux_release; | ||
device_set_of_node_from_dev(&adev->dev, dev); | ||
|
||
ret = auxiliary_device_init(adev); | ||
if (ret) | ||
goto ida_free; | ||
|
||
ret = __auxiliary_device_add(adev, dev->driver->name); | ||
if (ret) { | ||
auxiliary_device_uninit(adev); | ||
return ret; | ||
} | ||
|
||
return devm_add_action_or_reset(dev, meson_rst_aux_unregister_adev, | ||
adev); | ||
|
||
ida_free: | ||
ida_free(&meson_rst_aux_ida, adev->id); | ||
raux_free: | ||
kfree(raux); | ||
return ret; | ||
} | ||
EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register); | ||
|
||
MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver"); | ||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); | ||
MODULE_LICENSE("Dual BSD/GPL"); | ||
MODULE_IMPORT_NS(MESON_RESET); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | ||
/* | ||
* Amlogic Meson Reset core functions | ||
* | ||
* Copyright (c) 2016-2024 BayLibre, SAS. | ||
* Authors: Neil Armstrong <narmstrong@baylibre.com> | ||
* Jerome Brunet <jbrunet@baylibre.com> | ||
*/ | ||
|
||
#include <linux/device.h> | ||
#include <linux/module.h> | ||
#include <linux/regmap.h> | ||
#include <linux/reset-controller.h> | ||
|
||
#include "reset-meson.h" | ||
|
||
struct meson_reset { | ||
const struct meson_reset_param *param; | ||
struct reset_controller_dev rcdev; | ||
struct regmap *map; | ||
}; | ||
|
||
static void meson_reset_offset_and_bit(struct meson_reset *data, | ||
unsigned long id, | ||
unsigned int *offset, | ||
unsigned int *bit) | ||
{ | ||
unsigned int stride = regmap_get_reg_stride(data->map); | ||
|
||
*offset = (id / (stride * BITS_PER_BYTE)) * stride; | ||
*bit = id % (stride * BITS_PER_BYTE); | ||
} | ||
|
||
static int meson_reset_reset(struct reset_controller_dev *rcdev, | ||
unsigned long id) | ||
{ | ||
struct meson_reset *data = | ||
container_of(rcdev, struct meson_reset, rcdev); | ||
unsigned int offset, bit; | ||
|
||
meson_reset_offset_and_bit(data, id, &offset, &bit); | ||
offset += data->param->reset_offset; | ||
|
||
return regmap_write(data->map, offset, BIT(bit)); | ||
} | ||
|
||
static int meson_reset_level(struct reset_controller_dev *rcdev, | ||
unsigned long id, bool assert) | ||
{ | ||
struct meson_reset *data = | ||
container_of(rcdev, struct meson_reset, rcdev); | ||
unsigned int offset, bit; | ||
|
||
meson_reset_offset_and_bit(data, id, &offset, &bit); | ||
offset += data->param->level_offset; | ||
assert ^= data->param->level_low_reset; | ||
|
||
return regmap_update_bits(data->map, offset, | ||
BIT(bit), assert ? BIT(bit) : 0); | ||
} | ||
|
||
static int meson_reset_status(struct reset_controller_dev *rcdev, | ||
unsigned long id) | ||
{ | ||
struct meson_reset *data = | ||
container_of(rcdev, struct meson_reset, rcdev); | ||
unsigned int val, offset, bit; | ||
|
||
meson_reset_offset_and_bit(data, id, &offset, &bit); | ||
offset += data->param->level_offset; | ||
|
||
regmap_read(data->map, offset, &val); | ||
val = !!(BIT(bit) & val); | ||
|
||
return val ^ data->param->level_low_reset; | ||
} | ||
|
||
static int meson_reset_assert(struct reset_controller_dev *rcdev, | ||
unsigned long id) | ||
{ | ||
return meson_reset_level(rcdev, id, true); | ||
} | ||
|
||
static int meson_reset_deassert(struct reset_controller_dev *rcdev, | ||
unsigned long id) | ||
{ | ||
return meson_reset_level(rcdev, id, false); | ||
} | ||
|
||
static int meson_reset_level_toggle(struct reset_controller_dev *rcdev, | ||
unsigned long id) | ||
{ | ||
int ret; | ||
|
||
ret = meson_reset_assert(rcdev, id); | ||
if (ret) | ||
return ret; | ||
|
||
return meson_reset_deassert(rcdev, id); | ||
} | ||
|
||
const struct reset_control_ops meson_reset_ops = { | ||
.reset = meson_reset_reset, | ||
.assert = meson_reset_assert, | ||
.deassert = meson_reset_deassert, | ||
.status = meson_reset_status, | ||
}; | ||
EXPORT_SYMBOL_NS_GPL(meson_reset_ops, MESON_RESET); | ||
|
||
const struct reset_control_ops meson_reset_toggle_ops = { | ||
.reset = meson_reset_level_toggle, | ||
.assert = meson_reset_assert, | ||
.deassert = meson_reset_deassert, | ||
.status = meson_reset_status, | ||
}; | ||
EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, MESON_RESET); | ||
|
||
int meson_reset_controller_register(struct device *dev, struct regmap *map, | ||
const struct meson_reset_param *param) | ||
{ | ||
struct meson_reset *data; | ||
|
||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); | ||
if (!data) | ||
return -ENOMEM; | ||
|
||
data->param = param; | ||
data->map = map; | ||
data->rcdev.owner = dev->driver->owner; | ||
data->rcdev.nr_resets = param->reset_num; | ||
data->rcdev.ops = data->param->reset_ops; | ||
data->rcdev.of_node = dev->of_node; | ||
|
||
return devm_reset_controller_register(dev, &data->rcdev); | ||
} | ||
EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register, MESON_RESET); | ||
|
||
MODULE_DESCRIPTION("Amlogic Meson Reset Core function"); | ||
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); | ||
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); | ||
MODULE_LICENSE("Dual BSD/GPL"); | ||
MODULE_IMPORT_NS(MESON_RESET); |
Oops, something went wrong.