Reset controller changes for v4.14
- constify zx2967 reset_ops - add a convenience API to manage an array of resets - let deassert report success and let assert report success for shared resets if the reset controller driver does not implement (de)assert. - add HSDKv1 reset driver - remove Gemini reset controller, the driver is made obsolete by a combined clock/reset driver in drivers/clk - fix the total number of reset lines in the sunxi driver - various uniphier updates and fixes: - remove sLD3 SoC support - simplify system reset register and bit definitions - add audio systems, video input subsystem, and analog amplifiers reset controls -----BEGIN PGP SIGNATURE----- iQJMBAABCAA2FiEEBsBxhV1FaKwXuCOBUMKIHHCeYOsFAlmWg5MYHHBoaWxpcHAu emFiZWxAZ21haWwuY29tAAoJEFDCiBxwnmDrEqoQAKSQDhwA5ZyBd216PoUSaLqf tTGrJc/atfs+cDiqSyQDQ5vN0dTMnPV+YjGmwITg55ZGQTJRTq5nVhwM6y0CaASN PE7U/9Ma/8GWOjtC+6hun6tAHeuX3fMq2cYK8BSL+D7MQr+zkIgEQx3YsbR/0Np7 qmawpZSKAvIxrpVkQiVrsxmVvxi23GdncGUPDHtKhAW4N1T3ywogpW/7t6AcDZZl XIa09fIRxfB9VECIXPfe/CDkTHPcKgrxP80/AQJksRmWKBtFU3dRktYVscqUplz7 gS3EelAJ3NYscqWQevCXSvGsSpiNJfePKNLRrDSTKX+eKbAignHvcRhJ6YuP4QrY t7ZGm7VZf+HSY/XYXbcXEO8zcaf3LFT1lO3KAQ3/nmFie/CuVCC+Dpl74OPsBvcD +3uhQHqvm8AwnxBmTRtMNH3AtaDFPxT9hbebhsoJKujSb5+5aC4ygDAnY0E6QWfJ wYG/qKz6+dtrFVIOZG3TFjz2/kgjXRd8zegYtxn20KH1Qk/i+JqaIofbwPvPWAKS A5vi6sLt6AruRUh213E9+Pi+EWQs1Qhexqjk1rtna9RUkMmu2Qbx50hKkgdgE4Q7 EWcQSB43bpGRo5xt4zhy7fnBPj3zxjJK9gAzeGNrbN16z5gulHarpLWb9X5ujli4 9zv7wk00SQIaSqlVFKBM =YW4N -----END PGP SIGNATURE----- Merge tag 'reset-for-4.14' of git://git.pengutronix.de/git/pza/linux into next/drivers Pull "Reset controller changes for v4.14" from Philipp Zabel: - constify zx2967 reset_ops - add a convenience API to manage an array of resets - let deassert report success and let assert report success for shared resets if the reset controller driver does not implement (de)assert. - add HSDKv1 reset driver - remove Gemini reset controller, the driver is made obsolete by a combined clock/reset driver in drivers/clk - fix the total number of reset lines in the sunxi driver - various uniphier updates and fixes: - remove sLD3 SoC support - simplify system reset register and bit definitions - add audio systems, video input subsystem, and analog amplifiers reset controls * tag 'reset-for-4.14' of git://git.pengutronix.de/git/pza/linux: reset: uniphier: add analog amplifiers reset control reset: uniphier: add video input subsystem reset control reset: uniphier: add audio systems reset control reset: sunxi: fix number of reset lines reset: uniphier: do not use per-SoC macro for system reset block reset: uniphier: remove sLD3 SoC support Revert "reset: Add a Gemini reset controller" ARC: reset: introduce HSDKv1 reset driver reset: make (de)assert report success for self-deasserting reset drivers reset: Add APIs to manage array of resets reset: zx2967: constify zx2967_reset_ops.
This commit is contained in:
commit
e517030e26
|
@ -6,7 +6,6 @@ System reset
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should be one of the following:
|
- compatible: should be one of the following:
|
||||||
"socionext,uniphier-sld3-reset" - for sLD3 SoC
|
|
||||||
"socionext,uniphier-ld4-reset" - for LD4 SoC
|
"socionext,uniphier-ld4-reset" - for LD4 SoC
|
||||||
"socionext,uniphier-pro4-reset" - for Pro4 SoC
|
"socionext,uniphier-pro4-reset" - for Pro4 SoC
|
||||||
"socionext,uniphier-sld8-reset" - for sLD8 SoC
|
"socionext,uniphier-sld8-reset" - for sLD8 SoC
|
||||||
|
@ -37,7 +36,6 @@ Media I/O (MIO) reset, SD reset
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: should be one of the following:
|
- compatible: should be one of the following:
|
||||||
"socionext,uniphier-sld3-mio-reset" - for sLD3 SoC
|
|
||||||
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC
|
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC
|
||||||
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
|
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
|
||||||
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
|
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
|
||||||
|
@ -92,3 +90,28 @@ Example:
|
||||||
|
|
||||||
other nodes ...
|
other nodes ...
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Analog signal amplifier reset
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: should be one of the following:
|
||||||
|
"socionext,uniphier-ld11-adamv-reset" - for LD11 SoC
|
||||||
|
"socionext,uniphier-ld20-adamv-reset" - for LD20 SoC
|
||||||
|
- #reset-cells: should be 1.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
adamv@57920000 {
|
||||||
|
compatible = "socionext,uniphier-ld11-adamv",
|
||||||
|
"simple-mfd", "syscon";
|
||||||
|
reg = <0x57920000 0x1000>;
|
||||||
|
|
||||||
|
adamv_rst: reset {
|
||||||
|
compatible = "socionext,uniphier-ld11-adamv-reset";
|
||||||
|
#reset-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
other nodes ...
|
||||||
|
};
|
||||||
|
|
|
@ -12643,6 +12643,13 @@ L: linux-mmc@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/mmc/host/dw_mmc*
|
F: drivers/mmc/host/dw_mmc*
|
||||||
|
|
||||||
|
SYNOPSYS HSDK RESET CONTROLLER DRIVER
|
||||||
|
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
|
||||||
|
S: Supported
|
||||||
|
F: drivers/reset/reset-hsdk-v1.c
|
||||||
|
F: include/dt-bindings/reset/snps,hsdk-v1-reset.h
|
||||||
|
F: Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt
|
||||||
|
|
||||||
SYSTEM CONFIGURATION (SYSCON)
|
SYSTEM CONFIGURATION (SYSCON)
|
||||||
M: Lee Jones <lee.jones@linaro.org>
|
M: Lee Jones <lee.jones@linaro.org>
|
||||||
M: Arnd Bergmann <arnd@arndb.de>
|
M: Arnd Bergmann <arnd@arndb.de>
|
||||||
|
|
|
@ -34,12 +34,11 @@ config RESET_BERLIN
|
||||||
help
|
help
|
||||||
This enables the reset controller driver for Marvell Berlin SoCs.
|
This enables the reset controller driver for Marvell Berlin SoCs.
|
||||||
|
|
||||||
config RESET_GEMINI
|
config RESET_HSDK_V1
|
||||||
bool "Gemini Reset Driver" if COMPILE_TEST
|
bool "HSDK v1 Reset Driver"
|
||||||
default ARCH_GEMINI
|
default n
|
||||||
select MFD_SYSCON
|
|
||||||
help
|
help
|
||||||
This enables the reset controller driver for Cortina Systems Gemini.
|
This enables the reset controller driver for HSDK v1.
|
||||||
|
|
||||||
config RESET_IMX7
|
config RESET_IMX7
|
||||||
bool "i.MX7 Reset Driver" if COMPILE_TEST
|
bool "i.MX7 Reset Driver" if COMPILE_TEST
|
||||||
|
|
|
@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
|
||||||
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
|
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
|
||||||
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
|
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
|
||||||
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
|
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
|
||||||
obj-$(CONFIG_RESET_GEMINI) += reset-gemini.o
|
obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o
|
||||||
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
|
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
|
||||||
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
|
||||||
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
obj-$(CONFIG_RESET_MESON) += reset-meson.o
|
||||||
|
|
|
@ -43,10 +43,23 @@ struct reset_control {
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
struct kref refcnt;
|
struct kref refcnt;
|
||||||
bool shared;
|
bool shared;
|
||||||
|
bool array;
|
||||||
atomic_t deassert_count;
|
atomic_t deassert_count;
|
||||||
atomic_t triggered_count;
|
atomic_t triggered_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct reset_control_array - an array of reset controls
|
||||||
|
* @base: reset control for compatibility with reset control API functions
|
||||||
|
* @num_rstcs: number of reset controls
|
||||||
|
* @rstc: array of reset controls
|
||||||
|
*/
|
||||||
|
struct reset_control_array {
|
||||||
|
struct reset_control base;
|
||||||
|
unsigned int num_rstcs;
|
||||||
|
struct reset_control *rstc[];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* of_reset_simple_xlate - translate reset_spec to the reset line number
|
* of_reset_simple_xlate - translate reset_spec to the reset line number
|
||||||
* @rcdev: a pointer to the reset controller device
|
* @rcdev: a pointer to the reset controller device
|
||||||
|
@ -135,6 +148,65 @@ int devm_reset_controller_register(struct device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(devm_reset_controller_register);
|
EXPORT_SYMBOL_GPL(devm_reset_controller_register);
|
||||||
|
|
||||||
|
static inline struct reset_control_array *
|
||||||
|
rstc_to_array(struct reset_control *rstc) {
|
||||||
|
return container_of(rstc, struct reset_control_array, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_control_array_reset(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++) {
|
||||||
|
ret = reset_control_reset(resets->rstc[i]);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_control_array_assert(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++) {
|
||||||
|
ret = reset_control_assert(resets->rstc[i]);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
while (i--)
|
||||||
|
reset_control_deassert(resets->rstc[i]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_control_array_deassert(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++) {
|
||||||
|
ret = reset_control_deassert(resets->rstc[i]);
|
||||||
|
if (ret)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
while (i--)
|
||||||
|
reset_control_assert(resets->rstc[i]);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool reset_control_is_array(struct reset_control *rstc)
|
||||||
|
{
|
||||||
|
return rstc->array;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset_control_reset - reset the controlled device
|
* reset_control_reset - reset the controlled device
|
||||||
* @rstc: reset controller
|
* @rstc: reset controller
|
||||||
|
@ -158,6 +230,9 @@ int reset_control_reset(struct reset_control *rstc)
|
||||||
if (WARN_ON(IS_ERR(rstc)))
|
if (WARN_ON(IS_ERR(rstc)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (reset_control_is_array(rstc))
|
||||||
|
return reset_control_array_reset(rstc_to_array(rstc));
|
||||||
|
|
||||||
if (!rstc->rcdev->ops->reset)
|
if (!rstc->rcdev->ops->reset)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
@ -202,8 +277,8 @@ int reset_control_assert(struct reset_control *rstc)
|
||||||
if (WARN_ON(IS_ERR(rstc)))
|
if (WARN_ON(IS_ERR(rstc)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rstc->rcdev->ops->assert)
|
if (reset_control_is_array(rstc))
|
||||||
return -ENOTSUPP;
|
return reset_control_array_assert(rstc_to_array(rstc));
|
||||||
|
|
||||||
if (rstc->shared) {
|
if (rstc->shared) {
|
||||||
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
|
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
|
||||||
|
@ -214,6 +289,21 @@ int reset_control_assert(struct reset_control *rstc)
|
||||||
|
|
||||||
if (atomic_dec_return(&rstc->deassert_count) != 0)
|
if (atomic_dec_return(&rstc->deassert_count) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared reset controls allow the reset line to be in any state
|
||||||
|
* after this call, so doing nothing is a valid option.
|
||||||
|
*/
|
||||||
|
if (!rstc->rcdev->ops->assert)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* If the reset controller does not implement .assert(), there
|
||||||
|
* is no way to guarantee that the reset line is asserted after
|
||||||
|
* this call.
|
||||||
|
*/
|
||||||
|
if (!rstc->rcdev->ops->assert)
|
||||||
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
|
||||||
|
@ -240,8 +330,8 @@ int reset_control_deassert(struct reset_control *rstc)
|
||||||
if (WARN_ON(IS_ERR(rstc)))
|
if (WARN_ON(IS_ERR(rstc)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!rstc->rcdev->ops->deassert)
|
if (reset_control_is_array(rstc))
|
||||||
return -ENOTSUPP;
|
return reset_control_array_deassert(rstc_to_array(rstc));
|
||||||
|
|
||||||
if (rstc->shared) {
|
if (rstc->shared) {
|
||||||
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
|
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
|
||||||
|
@ -251,6 +341,16 @@ int reset_control_deassert(struct reset_control *rstc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the reset controller does not implement .deassert(), we assume
|
||||||
|
* that it handles self-deasserting reset lines via .reset(). In that
|
||||||
|
* case, the reset lines are deasserted by default. If that is not the
|
||||||
|
* case, the reset controller driver should implement .deassert() and
|
||||||
|
* return -ENOTSUPP.
|
||||||
|
*/
|
||||||
|
if (!rstc->rcdev->ops->deassert)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(reset_control_deassert);
|
EXPORT_SYMBOL_GPL(reset_control_deassert);
|
||||||
|
@ -266,7 +366,7 @@ int reset_control_status(struct reset_control *rstc)
|
||||||
if (!rstc)
|
if (!rstc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (WARN_ON(IS_ERR(rstc)))
|
if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (rstc->rcdev->ops->status)
|
if (rstc->rcdev->ops->status)
|
||||||
|
@ -404,6 +504,16 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__reset_control_get);
|
EXPORT_SYMBOL_GPL(__reset_control_get);
|
||||||
|
|
||||||
|
static void reset_control_array_put(struct reset_control_array *resets)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
mutex_lock(&reset_list_mutex);
|
||||||
|
for (i = 0; i < resets->num_rstcs; i++)
|
||||||
|
__reset_control_put_internal(resets->rstc[i]);
|
||||||
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* reset_control_put - free the reset controller
|
* reset_control_put - free the reset controller
|
||||||
* @rstc: reset controller
|
* @rstc: reset controller
|
||||||
|
@ -413,6 +523,11 @@ void reset_control_put(struct reset_control *rstc)
|
||||||
if (IS_ERR_OR_NULL(rstc))
|
if (IS_ERR_OR_NULL(rstc))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (reset_control_is_array(rstc)) {
|
||||||
|
reset_control_array_put(rstc_to_array(rstc));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_lock(&reset_list_mutex);
|
mutex_lock(&reset_list_mutex);
|
||||||
__reset_control_put_internal(rstc);
|
__reset_control_put_internal(rstc);
|
||||||
mutex_unlock(&reset_list_mutex);
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
@ -472,3 +587,116 @@ int device_reset(struct device *dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(device_reset);
|
EXPORT_SYMBOL_GPL(device_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APIs to manage an array of reset controls.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* of_reset_control_get_count - Count number of resets available with a device
|
||||||
|
*
|
||||||
|
* @node: device node that contains 'resets'.
|
||||||
|
*
|
||||||
|
* Returns positive reset count on success, or error number on failure and
|
||||||
|
* on count being zero.
|
||||||
|
*/
|
||||||
|
static int of_reset_control_get_count(struct device_node *node)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
if (!node)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
count = of_count_phandle_with_args(node, "resets", "#reset-cells");
|
||||||
|
if (count == 0)
|
||||||
|
count = -ENOENT;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* of_reset_control_array_get - Get a list of reset controls using
|
||||||
|
* device node.
|
||||||
|
*
|
||||||
|
* @np: device node for the device that requests the reset controls array
|
||||||
|
* @shared: whether reset controls are shared or not
|
||||||
|
* @optional: whether it is optional to get the reset controls
|
||||||
|
*
|
||||||
|
* Returns pointer to allocated reset_control_array on success or
|
||||||
|
* error on failure
|
||||||
|
*/
|
||||||
|
struct reset_control *
|
||||||
|
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
|
||||||
|
{
|
||||||
|
struct reset_control_array *resets;
|
||||||
|
struct reset_control *rstc;
|
||||||
|
int num, i;
|
||||||
|
|
||||||
|
num = of_reset_control_get_count(np);
|
||||||
|
if (num < 0)
|
||||||
|
return optional ? NULL : ERR_PTR(num);
|
||||||
|
|
||||||
|
resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * num,
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!resets)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
rstc = __of_reset_control_get(np, NULL, i, shared, optional);
|
||||||
|
if (IS_ERR(rstc))
|
||||||
|
goto err_rst;
|
||||||
|
resets->rstc[i] = rstc;
|
||||||
|
}
|
||||||
|
resets->num_rstcs = num;
|
||||||
|
resets->base.array = true;
|
||||||
|
|
||||||
|
return &resets->base;
|
||||||
|
|
||||||
|
err_rst:
|
||||||
|
mutex_lock(&reset_list_mutex);
|
||||||
|
while (--i >= 0)
|
||||||
|
__reset_control_put_internal(resets->rstc[i]);
|
||||||
|
mutex_unlock(&reset_list_mutex);
|
||||||
|
|
||||||
|
kfree(resets);
|
||||||
|
|
||||||
|
return rstc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(of_reset_control_array_get);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* devm_reset_control_array_get - Resource managed reset control array get
|
||||||
|
*
|
||||||
|
* @dev: device that requests the list of reset controls
|
||||||
|
* @shared: whether reset controls are shared or not
|
||||||
|
* @optional: whether it is optional to get the reset controls
|
||||||
|
*
|
||||||
|
* The reset control array APIs are intended for a list of resets
|
||||||
|
* that just have to be asserted or deasserted, without any
|
||||||
|
* requirements on the order.
|
||||||
|
*
|
||||||
|
* Returns pointer to allocated reset_control_array on success or
|
||||||
|
* error on failure
|
||||||
|
*/
|
||||||
|
struct reset_control *
|
||||||
|
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||||
|
{
|
||||||
|
struct reset_control **devres;
|
||||||
|
struct reset_control *rstc;
|
||||||
|
|
||||||
|
devres = devres_alloc(devm_reset_control_release, sizeof(*devres),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!devres)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
rstc = of_reset_control_array_get(dev->of_node, shared, optional);
|
||||||
|
if (IS_ERR(rstc)) {
|
||||||
|
devres_free(devres);
|
||||||
|
return rstc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*devres = rstc;
|
||||||
|
devres_add(dev, devres);
|
||||||
|
|
||||||
|
return rstc;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
|
||||||
|
|
|
@ -1,110 +0,0 @@
|
||||||
/*
|
|
||||||
* Cortina Gemini Reset controller driver
|
|
||||||
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/err.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/mfd/syscon.h>
|
|
||||||
#include <linux/regmap.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <linux/reset-controller.h>
|
|
||||||
#include <dt-bindings/reset/cortina,gemini-reset.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* struct gemini_reset - gemini reset controller
|
|
||||||
* @map: regmap to access the containing system controller
|
|
||||||
* @rcdev: reset controller device
|
|
||||||
*/
|
|
||||||
struct gemini_reset {
|
|
||||||
struct regmap *map;
|
|
||||||
struct reset_controller_dev rcdev;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GEMINI_GLOBAL_SOFT_RESET 0x0c
|
|
||||||
|
|
||||||
#define to_gemini_reset(p) \
|
|
||||||
container_of((p), struct gemini_reset, rcdev)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is a self-deasserting reset controller.
|
|
||||||
*/
|
|
||||||
static int gemini_reset(struct reset_controller_dev *rcdev,
|
|
||||||
unsigned long id)
|
|
||||||
{
|
|
||||||
struct gemini_reset *gr = to_gemini_reset(rcdev);
|
|
||||||
|
|
||||||
/* Manual says to always set BIT 30 (CPU1) to 1 */
|
|
||||||
return regmap_write(gr->map,
|
|
||||||
GEMINI_GLOBAL_SOFT_RESET,
|
|
||||||
BIT(GEMINI_RESET_CPU1) | BIT(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int gemini_reset_status(struct reset_controller_dev *rcdev,
|
|
||||||
unsigned long id)
|
|
||||||
{
|
|
||||||
struct gemini_reset *gr = to_gemini_reset(rcdev);
|
|
||||||
u32 val;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
return !!(val & BIT(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct reset_control_ops gemini_reset_ops = {
|
|
||||||
.reset = gemini_reset,
|
|
||||||
.status = gemini_reset_status,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int gemini_reset_probe(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct gemini_reset *gr;
|
|
||||||
struct device *dev = &pdev->dev;
|
|
||||||
struct device_node *np = dev->of_node;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL);
|
|
||||||
if (!gr)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
gr->map = syscon_node_to_regmap(np);
|
|
||||||
if (IS_ERR(gr->map)) {
|
|
||||||
ret = PTR_ERR(gr->map);
|
|
||||||
dev_err(dev, "unable to get regmap (%d)", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
gr->rcdev.owner = THIS_MODULE;
|
|
||||||
gr->rcdev.nr_resets = 32;
|
|
||||||
gr->rcdev.ops = &gemini_reset_ops;
|
|
||||||
gr->rcdev.of_node = pdev->dev.of_node;
|
|
||||||
|
|
||||||
ret = devm_reset_controller_register(&pdev->dev, &gr->rcdev);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
dev_info(dev, "registered Gemini reset controller\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct of_device_id gemini_reset_dt_ids[] = {
|
|
||||||
{ .compatible = "cortina,gemini-syscon", },
|
|
||||||
{ /* sentinel */ },
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct platform_driver gemini_reset_driver = {
|
|
||||||
.probe = gemini_reset_probe,
|
|
||||||
.driver = {
|
|
||||||
.name = "gemini-reset",
|
|
||||||
.of_match_table = gemini_reset_dt_ids,
|
|
||||||
.suppress_bind_attrs = true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
builtin_platform_driver(gemini_reset_driver);
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Synopsys.
|
||||||
|
*
|
||||||
|
* Synopsys HSDKv1 SDP reset driver.
|
||||||
|
*
|
||||||
|
* This file is licensed under the terms of the GNU General Public
|
||||||
|
* License version 2. This program is licensed "as is" without any
|
||||||
|
* warranty of any kind, whether express or implied.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev)
|
||||||
|
|
||||||
|
struct hsdkv1_rst {
|
||||||
|
void __iomem *regs_ctl;
|
||||||
|
void __iomem *regs_rst;
|
||||||
|
spinlock_t lock;
|
||||||
|
struct reset_controller_dev rcdev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 rst_map[] = {
|
||||||
|
BIT(16), /* APB_RST */
|
||||||
|
BIT(17), /* AXI_RST */
|
||||||
|
BIT(18), /* ETH_RST */
|
||||||
|
BIT(19), /* USB_RST */
|
||||||
|
BIT(20), /* SDIO_RST */
|
||||||
|
BIT(21), /* HDMI_RST */
|
||||||
|
BIT(22), /* GFX_RST */
|
||||||
|
BIT(25), /* DMAC_RST */
|
||||||
|
BIT(31), /* EBI_RST */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map)
|
||||||
|
|
||||||
|
#define CGU_SYS_RST_CTRL 0x0
|
||||||
|
#define CGU_IP_SW_RESET 0x0
|
||||||
|
#define CGU_IP_SW_RESET_DELAY_SHIFT 16
|
||||||
|
#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT)
|
||||||
|
#define CGU_IP_SW_RESET_DELAY 0
|
||||||
|
#define CGU_IP_SW_RESET_RESET BIT(0)
|
||||||
|
#define SW_RESET_TIMEOUT 10000
|
||||||
|
|
||||||
|
static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id)
|
||||||
|
{
|
||||||
|
writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hsdkv1_reset_do(struct hsdkv1_rst *rst)
|
||||||
|
{
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = readl(rst->regs_rst + CGU_IP_SW_RESET);
|
||||||
|
reg &= ~CGU_IP_SW_RESET_DELAY_MASK;
|
||||||
|
reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT;
|
||||||
|
reg |= CGU_IP_SW_RESET_RESET;
|
||||||
|
writel(reg, rst->regs_rst + CGU_IP_SW_RESET);
|
||||||
|
|
||||||
|
/* wait till reset bit is back to 0 */
|
||||||
|
return readl_poll_timeout_atomic(rst->regs_rst + CGU_IP_SW_RESET, reg,
|
||||||
|
!(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev,
|
||||||
|
unsigned long id)
|
||||||
|
{
|
||||||
|
struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev);
|
||||||
|
unsigned long flags;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&rst->lock, flags);
|
||||||
|
hsdkv1_reset_config(rst, id);
|
||||||
|
ret = hsdkv1_reset_do(rst);
|
||||||
|
spin_unlock_irqrestore(&rst->lock, flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct reset_control_ops hsdkv1_reset_ops = {
|
||||||
|
.reset = hsdkv1_reset_reset,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int hsdkv1_reset_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct hsdkv1_rst *rst;
|
||||||
|
struct resource *mem;
|
||||||
|
|
||||||
|
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
|
||||||
|
if (!rst)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem);
|
||||||
|
if (IS_ERR(rst->regs_ctl))
|
||||||
|
return PTR_ERR(rst->regs_ctl);
|
||||||
|
|
||||||
|
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
|
rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
|
||||||
|
if (IS_ERR(rst->regs_rst))
|
||||||
|
return PTR_ERR(rst->regs_rst);
|
||||||
|
|
||||||
|
spin_lock_init(&rst->lock);
|
||||||
|
|
||||||
|
rst->rcdev.owner = THIS_MODULE;
|
||||||
|
rst->rcdev.ops = &hsdkv1_reset_ops;
|
||||||
|
rst->rcdev.of_node = pdev->dev.of_node;
|
||||||
|
rst->rcdev.nr_resets = HSDK_MAX_RESETS;
|
||||||
|
rst->rcdev.of_reset_n_cells = 1;
|
||||||
|
|
||||||
|
return reset_controller_register(&rst->rcdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id hsdkv1_reset_dt_match[] = {
|
||||||
|
{ .compatible = "snps,hsdk-v1.0-reset" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver hsdkv1_reset_driver = {
|
||||||
|
.probe = hsdkv1_reset_probe,
|
||||||
|
.driver = {
|
||||||
|
.name = "hsdk-v1.0-reset",
|
||||||
|
.of_match_table = hsdkv1_reset_dt_match,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
builtin_platform_driver(hsdkv1_reset_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>");
|
||||||
|
MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
|
@ -107,7 +107,7 @@ static int sunxi_reset_init(struct device_node *np)
|
||||||
spin_lock_init(&data->lock);
|
spin_lock_init(&data->lock);
|
||||||
|
|
||||||
data->rcdev.owner = THIS_MODULE;
|
data->rcdev.owner = THIS_MODULE;
|
||||||
data->rcdev.nr_resets = size * 32;
|
data->rcdev.nr_resets = size * 8;
|
||||||
data->rcdev.ops = &sunxi_reset_ops;
|
data->rcdev.ops = &sunxi_reset_ops;
|
||||||
data->rcdev.of_node = np;
|
data->rcdev.of_node = np;
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static int sunxi_reset_probe(struct platform_device *pdev)
|
||||||
spin_lock_init(&data->lock);
|
spin_lock_init(&data->lock);
|
||||||
|
|
||||||
data->rcdev.owner = THIS_MODULE;
|
data->rcdev.owner = THIS_MODULE;
|
||||||
data->rcdev.nr_resets = resource_size(res) * 32;
|
data->rcdev.nr_resets = resource_size(res) * 8;
|
||||||
data->rcdev.ops = &sunxi_reset_ops;
|
data->rcdev.ops = &sunxi_reset_ops;
|
||||||
data->rcdev.of_node = pdev->dev.of_node;
|
data->rcdev.of_node = pdev->dev.of_node;
|
||||||
|
|
||||||
|
|
|
@ -50,59 +50,35 @@ struct uniphier_reset_data {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* System reset data */
|
/* System reset data */
|
||||||
#define UNIPHIER_SLD3_SYS_RESET_NAND(id) \
|
static const struct uniphier_reset_data uniphier_ld4_sys_reset_data[] = {
|
||||||
UNIPHIER_RESETX((id), 0x2004, 2)
|
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
|
||||||
|
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (Ether, HSC, MIO) */
|
||||||
#define UNIPHIER_LD11_SYS_RESET_NAND(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x200c, 0)
|
|
||||||
|
|
||||||
#define UNIPHIER_LD11_SYS_RESET_EMMC(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x200c, 2)
|
|
||||||
|
|
||||||
#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x2000, 10)
|
|
||||||
|
|
||||||
#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x200c, 8)
|
|
||||||
|
|
||||||
#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x2000, 6)
|
|
||||||
|
|
||||||
#define UNIPHIER_LD20_SYS_RESET_GIO(id) \
|
|
||||||
UNIPHIER_RESETX((id), 0x200c, 5)
|
|
||||||
|
|
||||||
#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \
|
|
||||||
UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
|
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
|
|
||||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
|
||||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */
|
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
|
||||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
|
||||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */
|
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, MIO, RLE) */
|
||||||
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */
|
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
|
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
|
||||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
|
||||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */
|
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC) */
|
||||||
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */
|
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (PCIe, USB3) */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
|
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
||||||
UNIPHIER_SLD3_SYS_RESET_NAND(2),
|
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
|
||||||
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */
|
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, RLE) */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
|
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
|
||||||
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
|
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
|
||||||
UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */
|
UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */
|
||||||
UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */
|
UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */
|
||||||
UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */
|
UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */
|
||||||
|
@ -114,21 +90,27 @@ static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
|
||||||
UNIPHIER_LD11_SYS_RESET_NAND(2),
|
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
|
||||||
UNIPHIER_LD11_SYS_RESET_EMMC(4),
|
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
|
||||||
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */
|
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */
|
||||||
|
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
|
||||||
|
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
|
||||||
|
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
||||||
UNIPHIER_LD11_SYS_RESET_NAND(2),
|
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
|
||||||
UNIPHIER_LD11_SYS_RESET_EMMC(4),
|
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
|
||||||
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */
|
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */
|
||||||
UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */
|
UNIPHIER_RESETX(12, 0x200c, 5), /* GIO (PCIe, USB3) */
|
||||||
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
|
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
|
||||||
UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
|
UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
|
||||||
UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
|
UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
|
||||||
UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
|
UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
|
||||||
|
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
|
||||||
|
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
|
||||||
|
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,7 +133,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
|
||||||
#define UNIPHIER_MIO_RESET_DMAC(id) \
|
#define UNIPHIER_MIO_RESET_DMAC(id) \
|
||||||
UNIPHIER_RESETX((id), 0x110, 17)
|
UNIPHIER_RESETX((id), 0x110, 17)
|
||||||
|
|
||||||
static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
|
static const struct uniphier_reset_data uniphier_ld4_mio_reset_data[] = {
|
||||||
UNIPHIER_MIO_RESET_SD(0, 0),
|
UNIPHIER_MIO_RESET_SD(0, 0),
|
||||||
UNIPHIER_MIO_RESET_SD(1, 1),
|
UNIPHIER_MIO_RESET_SD(1, 1),
|
||||||
UNIPHIER_MIO_RESET_SD(2, 2),
|
UNIPHIER_MIO_RESET_SD(2, 2),
|
||||||
|
@ -163,11 +145,9 @@ static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
|
||||||
UNIPHIER_MIO_RESET_USB2(8, 0),
|
UNIPHIER_MIO_RESET_USB2(8, 0),
|
||||||
UNIPHIER_MIO_RESET_USB2(9, 1),
|
UNIPHIER_MIO_RESET_USB2(9, 1),
|
||||||
UNIPHIER_MIO_RESET_USB2(10, 2),
|
UNIPHIER_MIO_RESET_USB2(10, 2),
|
||||||
UNIPHIER_MIO_RESET_USB2(11, 3),
|
|
||||||
UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
|
UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
|
||||||
UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
|
UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
|
||||||
UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
|
UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
|
||||||
UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
|
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,6 +196,12 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
|
||||||
UNIPHIER_RESET_END,
|
UNIPHIER_RESET_END,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Analog signal amplifiers reset data */
|
||||||
|
static const struct uniphier_reset_data uniphier_ld11_adamv_reset_data[] = {
|
||||||
|
UNIPHIER_RESETX(0, 0x10, 6), /* EVEA */
|
||||||
|
UNIPHIER_RESET_END,
|
||||||
|
};
|
||||||
|
|
||||||
/* core implementaton */
|
/* core implementaton */
|
||||||
struct uniphier_reset_priv {
|
struct uniphier_reset_priv {
|
||||||
struct reset_controller_dev rcdev;
|
struct reset_controller_dev rcdev;
|
||||||
|
@ -345,13 +331,9 @@ static int uniphier_reset_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
static const struct of_device_id uniphier_reset_match[] = {
|
static const struct of_device_id uniphier_reset_match[] = {
|
||||||
/* System reset */
|
/* System reset */
|
||||||
{
|
|
||||||
.compatible = "socionext,uniphier-sld3-reset",
|
|
||||||
.data = uniphier_sld3_sys_reset_data,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-ld4-reset",
|
.compatible = "socionext,uniphier-ld4-reset",
|
||||||
.data = uniphier_sld3_sys_reset_data,
|
.data = uniphier_ld4_sys_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-pro4-reset",
|
.compatible = "socionext,uniphier-pro4-reset",
|
||||||
|
@ -359,7 +341,7 @@ static const struct of_device_id uniphier_reset_match[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-sld8-reset",
|
.compatible = "socionext,uniphier-sld8-reset",
|
||||||
.data = uniphier_sld3_sys_reset_data,
|
.data = uniphier_ld4_sys_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-pro5-reset",
|
.compatible = "socionext,uniphier-pro5-reset",
|
||||||
|
@ -378,21 +360,17 @@ static const struct of_device_id uniphier_reset_match[] = {
|
||||||
.data = uniphier_ld20_sys_reset_data,
|
.data = uniphier_ld20_sys_reset_data,
|
||||||
},
|
},
|
||||||
/* Media I/O reset, SD reset */
|
/* Media I/O reset, SD reset */
|
||||||
{
|
|
||||||
.compatible = "socionext,uniphier-sld3-mio-reset",
|
|
||||||
.data = uniphier_sld3_mio_reset_data,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-ld4-mio-reset",
|
.compatible = "socionext,uniphier-ld4-mio-reset",
|
||||||
.data = uniphier_sld3_mio_reset_data,
|
.data = uniphier_ld4_mio_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-pro4-mio-reset",
|
.compatible = "socionext,uniphier-pro4-mio-reset",
|
||||||
.data = uniphier_sld3_mio_reset_data,
|
.data = uniphier_ld4_mio_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-sld8-mio-reset",
|
.compatible = "socionext,uniphier-sld8-mio-reset",
|
||||||
.data = uniphier_sld3_mio_reset_data,
|
.data = uniphier_ld4_mio_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-pro5-sd-reset",
|
.compatible = "socionext,uniphier-pro5-sd-reset",
|
||||||
|
@ -404,7 +382,7 @@ static const struct of_device_id uniphier_reset_match[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-ld11-mio-reset",
|
.compatible = "socionext,uniphier-ld11-mio-reset",
|
||||||
.data = uniphier_sld3_mio_reset_data,
|
.data = uniphier_ld4_mio_reset_data,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.compatible = "socionext,uniphier-ld11-sd-reset",
|
.compatible = "socionext,uniphier-ld11-sd-reset",
|
||||||
|
@ -443,6 +421,15 @@ static const struct of_device_id uniphier_reset_match[] = {
|
||||||
.compatible = "socionext,uniphier-ld20-peri-reset",
|
.compatible = "socionext,uniphier-ld20-peri-reset",
|
||||||
.data = uniphier_pro4_peri_reset_data,
|
.data = uniphier_pro4_peri_reset_data,
|
||||||
},
|
},
|
||||||
|
/* Analog signal amplifiers reset */
|
||||||
|
{
|
||||||
|
.compatible = "socionext,uniphier-ld11-adamv-reset",
|
||||||
|
.data = uniphier_ld11_adamv_reset_data,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "socionext,uniphier-ld20-adamv-reset",
|
||||||
|
.data = uniphier_ld11_adamv_reset_data,
|
||||||
|
},
|
||||||
{ /* sentinel */ }
|
{ /* sentinel */ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, uniphier_reset_match);
|
MODULE_DEVICE_TABLE(of, uniphier_reset_match);
|
||||||
|
|
|
@ -55,7 +55,7 @@ static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
|
||||||
return zx2967_reset_act(rcdev, id, false);
|
return zx2967_reset_act(rcdev, id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct reset_control_ops zx2967_reset_ops = {
|
static const struct reset_control_ops zx2967_reset_ops = {
|
||||||
.assert = zx2967_reset_assert,
|
.assert = zx2967_reset_assert,
|
||||||
.deassert = zx2967_reset_deassert,
|
.deassert = zx2967_reset_deassert,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* This header provides index for the HSDK v1 reset controller.
|
||||||
|
*/
|
||||||
|
#ifndef _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
|
||||||
|
#define _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
|
||||||
|
|
||||||
|
#define HSDK_V1_APB_RESET 0
|
||||||
|
#define HSDK_V1_AXI_RESET 1
|
||||||
|
#define HSDK_V1_ETH_RESET 2
|
||||||
|
#define HSDK_V1_USB_RESET 3
|
||||||
|
#define HSDK_V1_SDIO_RESET 4
|
||||||
|
#define HSDK_V1_HDMI_RESET 5
|
||||||
|
#define HSDK_V1_GFX_RESET 6
|
||||||
|
#define HSDK_V1_DMAC_RESET 7
|
||||||
|
#define HSDK_V1_EBI_RESET 8
|
||||||
|
|
||||||
|
#endif /*_DT_BINDINGS_RESET_CONTROLLER_HSDK_V1*/
|
|
@ -25,6 +25,11 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
|
||||||
|
|
||||||
int __must_check device_reset(struct device *dev);
|
int __must_check device_reset(struct device *dev);
|
||||||
|
|
||||||
|
struct reset_control *devm_reset_control_array_get(struct device *dev,
|
||||||
|
bool shared, bool optional);
|
||||||
|
struct reset_control *of_reset_control_array_get(struct device_node *np,
|
||||||
|
bool shared, bool optional);
|
||||||
|
|
||||||
static inline int device_reset_optional(struct device *dev)
|
static inline int device_reset_optional(struct device *dev)
|
||||||
{
|
{
|
||||||
return device_reset(dev);
|
return device_reset(dev);
|
||||||
|
@ -89,6 +94,18 @@ static inline struct reset_control *__devm_reset_control_get(
|
||||||
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
|
||||||
|
{
|
||||||
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
|
||||||
|
{
|
||||||
|
return optional ? NULL : ERR_PTR(-ENOTSUPP);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_RESET_CONTROLLER */
|
#endif /* CONFIG_RESET_CONTROLLER */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -374,4 +391,55 @@ static inline struct reset_control *devm_reset_control_get_by_index(
|
||||||
{
|
{
|
||||||
return devm_reset_control_get_exclusive_by_index(dev, index);
|
return devm_reset_control_get_exclusive_by_index(dev, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APIs to manage a list of reset controllers
|
||||||
|
*/
|
||||||
|
static inline struct reset_control *
|
||||||
|
devm_reset_control_array_get_exclusive(struct device *dev)
|
||||||
|
{
|
||||||
|
return devm_reset_control_array_get(dev, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
devm_reset_control_array_get_shared(struct device *dev)
|
||||||
|
{
|
||||||
|
return devm_reset_control_array_get(dev, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
devm_reset_control_array_get_optional_exclusive(struct device *dev)
|
||||||
|
{
|
||||||
|
return devm_reset_control_array_get(dev, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
devm_reset_control_array_get_optional_shared(struct device *dev)
|
||||||
|
{
|
||||||
|
return devm_reset_control_array_get(dev, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get_exclusive(struct device_node *node)
|
||||||
|
{
|
||||||
|
return of_reset_control_array_get(node, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get_shared(struct device_node *node)
|
||||||
|
{
|
||||||
|
return of_reset_control_array_get(node, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get_optional_exclusive(struct device_node *node)
|
||||||
|
{
|
||||||
|
return of_reset_control_array_get(node, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct reset_control *
|
||||||
|
of_reset_control_array_get_optional_shared(struct device_node *node)
|
||||||
|
{
|
||||||
|
return of_reset_control_array_get(node, true, true);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue