diff mbox

[v4,2/5] reset: qcom: AOSS (always on subsystem) reset controller

Message ID 20180425150843.26657-3-sibis@codeaurora.org (mailing list archive)
State New, archived
Headers show

Commit Message

Sibi Sankar April 25, 2018, 3:08 p.m. UTC
Add reset controller driver for Qualcomm SDM845 SoC to
control reset signals provided by AOSS for Modem, Venus
ADSP, GPU, Camera, Wireless, Display subsystem

Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
---
 drivers/reset/Kconfig           |   9 +++
 drivers/reset/Makefile          |   1 +
 drivers/reset/reset-qcom-aoss.c | 133 ++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+)
 create mode 100644 drivers/reset/reset-qcom-aoss.c

Comments

Philipp Zabel April 27, 2018, 10:41 a.m. UTC | #1
On Wed, 2018-04-25 at 20:38 +0530, Sibi Sankar wrote:
> Add reset controller driver for Qualcomm SDM845 SoC to
> control reset signals provided by AOSS for Modem, Venus
> ADSP, GPU, Camera, Wireless, Display subsystem
> 
> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
> ---
>  drivers/reset/Kconfig           |   9 +++
>  drivers/reset/Makefile          |   1 +
>  drivers/reset/reset-qcom-aoss.c | 133 ++++++++++++++++++++++++++++++++
>  3 files changed, 143 insertions(+)
>  create mode 100644 drivers/reset/reset-qcom-aoss.c
> 
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index c0b292be1b72..756ad2b27d0f 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -82,6 +82,15 @@ config RESET_PISTACHIO
>  	help
>  	  This enables the reset driver for ImgTec Pistachio SoCs.
>  
> +config RESET_QCOM_AOSS
> +	bool "Qcom AOSS Reset Driver"
> +	depends on ARCH_QCOM || COMPILE_TEST
> +	help
> +	  This enables the AOSS (always on subsystem) reset driver
> +	  for Qualcomm SDM845 SoCs. Say Y if you want to control
> +	  reset signals provided by AOSS for Modem, Venus, ADSP,
> +	  GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
> +
>  config RESET_SIMPLE
>  	bool "Simple Reset Controller Driver" if COMPILE_TEST
>  	default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index c1261dcfe9ad..6881e4d287f0 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
>  obj-$(CONFIG_RESET_MESON) += reset-meson.o
>  obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
>  obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
> +obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
>  obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
>  obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
>  obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
> diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
> new file mode 100644
> index 000000000000..3b0bbb387f7b
> --- /dev/null
> +++ b/drivers/reset/reset-qcom-aoss.c
> @@ -0,0 +1,133 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2018 The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/of_device.h>
> +#include <dt-bindings/reset/qcom,sdm845-aoss.h>
> +
> +struct qcom_aoss_reset_map {
> +	unsigned int reg;
> +};
> +
> +struct qcom_aoss_desc {
> +	const struct qcom_aoss_reset_map *resets;
> +	size_t num_resets;
> +};
> +
> +struct qcom_aoss_reset_data {
> +	struct reset_controller_dev rcdev;
> +	void __iomem *base;
> +	const struct qcom_aoss_desc *desc;
> +};
> +
> +static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
> +	[AOSS_CC_MSS_RESTART] = {0x0},
> +	[AOSS_CC_CAMSS_RESTART] = {0x1000},
> +	[AOSS_CC_VENUS_RESTART] = {0x2000},
> +	[AOSS_CC_GPU_RESTART] = {0x3000},
> +	[AOSS_CC_DISPSS_RESTART] = {0x4000},
> +	[AOSS_CC_WCSS_RESTART] = {0x10000},
> +	[AOSS_CC_LPASS_RESTART] = {0x20000},
> +};
> +
> +static const struct qcom_aoss_desc sdm845_aoss_desc = {
> +	.resets = sdm845_aoss_resets,
> +	.num_resets = ARRAY_SIZE(sdm845_aoss_resets),
> +};
> +
> +static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
> +				struct reset_controller_dev *rcdev)
> +{
> +	return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
> +}
> +
> +static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
> +				    unsigned long idx)
> +{
> +	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
> +	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
> +
> +	writel(1, data->base + map->reg);
> +	/* Wait 6 32kHz sleep cycles for reset */
> +	usleep_range(200, 210);
> +	return 0;
> +}
> +
> +static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
> +				      unsigned long idx)
> +{
> +	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
> +	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
> +
> +	writel(0, data->base + map->reg);
> +	/* Wait 6 32kHz sleep cycles for reset */
> +	usleep_range(200, 210);

6 32 kHz cycles are about 188 µs (184 µs for 32.768 kHz).
Just out of curiosity, is the minimum increased to 200 µs on purpose, or
to have a nice round number? The maximum seems oddly small, unless it is
essential to wait less than 7 cycles.

The driver looks good to me now. I plan to apply patches 1 and 2 with
Rob's ack.
Is it ok to merge them independently from the remoteproc driver, or is
there a dependency?

regards
Philipp
--
To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sibi Sankar April 27, 2018, 11:15 a.m. UTC | #2
Hi Philipp,

Thanks for the review.

On 04/27/2018 04:11 PM, Philipp Zabel wrote:
> On Wed, 2018-04-25 at 20:38 +0530, Sibi Sankar wrote:
>> Add reset controller driver for Qualcomm SDM845 SoC to
>> control reset signals provided by AOSS for Modem, Venus
>> ADSP, GPU, Camera, Wireless, Display subsystem
>>
>> Signed-off-by: Sibi Sankar <sibis@codeaurora.org>
>> ---
>>   drivers/reset/Kconfig           |   9 +++
>>   drivers/reset/Makefile          |   1 +
>>   drivers/reset/reset-qcom-aoss.c | 133 ++++++++++++++++++++++++++++++++
>>   3 files changed, 143 insertions(+)
>>   create mode 100644 drivers/reset/reset-qcom-aoss.c
>>
>> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
>> index c0b292be1b72..756ad2b27d0f 100644
>> --- a/drivers/reset/Kconfig
>> +++ b/drivers/reset/Kconfig
>> @@ -82,6 +82,15 @@ config RESET_PISTACHIO
>>   	help
>>   	  This enables the reset driver for ImgTec Pistachio SoCs.
>>   
>> +config RESET_QCOM_AOSS
>> +	bool "Qcom AOSS Reset Driver"
>> +	depends on ARCH_QCOM || COMPILE_TEST
>> +	help
>> +	  This enables the AOSS (always on subsystem) reset driver
>> +	  for Qualcomm SDM845 SoCs. Say Y if you want to control
>> +	  reset signals provided by AOSS for Modem, Venus, ADSP,
>> +	  GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
>> +
>>   config RESET_SIMPLE
>>   	bool "Simple Reset Controller Driver" if COMPILE_TEST
>>   	default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
>> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
>> index c1261dcfe9ad..6881e4d287f0 100644
>> --- a/drivers/reset/Makefile
>> +++ b/drivers/reset/Makefile
>> @@ -14,6 +14,7 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
>>   obj-$(CONFIG_RESET_MESON) += reset-meson.o
>>   obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
>>   obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
>> +obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
>>   obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
>>   obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
>>   obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
>> diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
>> new file mode 100644
>> index 000000000000..3b0bbb387f7b
>> --- /dev/null
>> +++ b/drivers/reset/reset-qcom-aoss.c
>> @@ -0,0 +1,133 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2018 The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/reset-controller.h>
>> +#include <linux/delay.h>
>> +#include <linux/io.h>
>> +#include <linux/of_device.h>
>> +#include <dt-bindings/reset/qcom,sdm845-aoss.h>
>> +
>> +struct qcom_aoss_reset_map {
>> +	unsigned int reg;
>> +};
>> +
>> +struct qcom_aoss_desc {
>> +	const struct qcom_aoss_reset_map *resets;
>> +	size_t num_resets;
>> +};
>> +
>> +struct qcom_aoss_reset_data {
>> +	struct reset_controller_dev rcdev;
>> +	void __iomem *base;
>> +	const struct qcom_aoss_desc *desc;
>> +};
>> +
>> +static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
>> +	[AOSS_CC_MSS_RESTART] = {0x0},
>> +	[AOSS_CC_CAMSS_RESTART] = {0x1000},
>> +	[AOSS_CC_VENUS_RESTART] = {0x2000},
>> +	[AOSS_CC_GPU_RESTART] = {0x3000},
>> +	[AOSS_CC_DISPSS_RESTART] = {0x4000},
>> +	[AOSS_CC_WCSS_RESTART] = {0x10000},
>> +	[AOSS_CC_LPASS_RESTART] = {0x20000},
>> +};
>> +
>> +static const struct qcom_aoss_desc sdm845_aoss_desc = {
>> +	.resets = sdm845_aoss_resets,
>> +	.num_resets = ARRAY_SIZE(sdm845_aoss_resets),
>> +};
>> +
>> +static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
>> +				struct reset_controller_dev *rcdev)
>> +{
>> +	return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
>> +}
>> +
>> +static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
>> +				    unsigned long idx)
>> +{
>> +	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
>> +	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
>> +
>> +	writel(1, data->base + map->reg);
>> +	/* Wait 6 32kHz sleep cycles for reset */
>> +	usleep_range(200, 210);
>> +	return 0;
>> +}
>> +
>> +static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
>> +				      unsigned long idx)
>> +{
>> +	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
>> +	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
>> +
>> +	writel(0, data->base + map->reg);
>> +	/* Wait 6 32kHz sleep cycles for reset */
>> +	usleep_range(200, 210);
> 
> 6 32 kHz cycles are about 188 µs (184 µs for 32.768 kHz).
> Just out of curiosity, is the minimum increased to 200 µs on purpose, or
> to have a nice round number? The maximum seems oddly small, unless it is
> essential to wait less than 7 cycles.
> 

anything above 188 µs should be fine 200 µs is just a round number.

no it is not essential to wait less than 7 cycles so I can increase
the max limit to 300 µs.

> The driver looks good to me now. I plan to apply patches 1 and 2 with
> Rob's ack.
> Is it ok to merge them independently from the remoteproc driver, or is
> there a dependency?
>

Yes it should be fine to merge them independently. I can add a dt entry
to the dtsi and separate the 2 patches from the remoteproc patches if
that helps ?

> regards
> Philipp
>
Philipp Zabel April 27, 2018, 11:54 a.m. UTC | #3
Hi Sibi,

On Fri, 2018-04-27 at 16:45 +0530, Sibi S wrote:
[...]
> > > +	/* Wait 6 32kHz sleep cycles for reset */
> > > +	usleep_range(200, 210);
> > 
> > 6 32 kHz cycles are about 188 µs (184 µs for 32.768 kHz).
> > Just out of curiosity, is the minimum increased to 200 µs on purpose, or
> > to have a nice round number? The maximum seems oddly small, unless it is
> > essential to wait less than 7 cycles.
> 
> anything above 188 µs should be fine 200 µs is just a round number.
> 
> no it is not essential to wait less than 7 cycles so I can increase
> the max limit to 300 µs.

Ok, thanks for the info.

> > The driver looks good to me now. I plan to apply patches 1 and 2 with
> > Rob's ack.
> > Is it ok to merge them independently from the remoteproc driver, or is
> > there a dependency?
> 
> Yes it should be fine to merge them independently. I can add a dt entry
> to the dtsi and separate the 2 patches from the remoteproc patches if
> that helps ?

I plan to just pick up the reset DT binding documentation patch (1/5)
and the reset driver patch (2/5) then, whether they are sent separately
or as part of the larger remoteproc series does not matter to me.

The dtsi patch would have to go through the arm/qualcomm tree.
I can put the reset patches onto a separate branch that could be pulled
into the qcom tree ahead of the dtsi change, or you could send the dtsi
change with numbers at first, and only replace them with the header
defines after patch 1 is merged through the reset tree.

regards
Philipp
--
To unsubscribe from this list: send the line "unsubscribe linux-remoteproc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c0b292be1b72..756ad2b27d0f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -82,6 +82,15 @@  config RESET_PISTACHIO
 	help
 	  This enables the reset driver for ImgTec Pistachio SoCs.
 
+config RESET_QCOM_AOSS
+	bool "Qcom AOSS Reset Driver"
+	depends on ARCH_QCOM || COMPILE_TEST
+	help
+	  This enables the AOSS (always on subsystem) reset driver
+	  for Qualcomm SDM845 SoCs. Say Y if you want to control
+	  reset signals provided by AOSS for Modem, Venus, ADSP,
+	  GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
+
 config RESET_SIMPLE
 	bool "Simple Reset Controller Driver" if COMPILE_TEST
 	default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index c1261dcfe9ad..6881e4d287f0 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -14,6 +14,7 @@  obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
 obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
new file mode 100644
index 000000000000..3b0bbb387f7b
--- /dev/null
+++ b/drivers/reset/reset-qcom-aoss.c
@@ -0,0 +1,133 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <dt-bindings/reset/qcom,sdm845-aoss.h>
+
+struct qcom_aoss_reset_map {
+	unsigned int reg;
+};
+
+struct qcom_aoss_desc {
+	const struct qcom_aoss_reset_map *resets;
+	size_t num_resets;
+};
+
+struct qcom_aoss_reset_data {
+	struct reset_controller_dev rcdev;
+	void __iomem *base;
+	const struct qcom_aoss_desc *desc;
+};
+
+static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
+	[AOSS_CC_MSS_RESTART] = {0x0},
+	[AOSS_CC_CAMSS_RESTART] = {0x1000},
+	[AOSS_CC_VENUS_RESTART] = {0x2000},
+	[AOSS_CC_GPU_RESTART] = {0x3000},
+	[AOSS_CC_DISPSS_RESTART] = {0x4000},
+	[AOSS_CC_WCSS_RESTART] = {0x10000},
+	[AOSS_CC_LPASS_RESTART] = {0x20000},
+};
+
+static const struct qcom_aoss_desc sdm845_aoss_desc = {
+	.resets = sdm845_aoss_resets,
+	.num_resets = ARRAY_SIZE(sdm845_aoss_resets),
+};
+
+static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
+				struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
+}
+
+static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
+				    unsigned long idx)
+{
+	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+	writel(1, data->base + map->reg);
+	/* Wait 6 32kHz sleep cycles for reset */
+	usleep_range(200, 210);
+	return 0;
+}
+
+static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
+				      unsigned long idx)
+{
+	struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+	const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+	writel(0, data->base + map->reg);
+	/* Wait 6 32kHz sleep cycles for reset */
+	usleep_range(200, 210);
+	return 0;
+}
+
+static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
+					unsigned long idx)
+{
+	qcom_aoss_control_assert(rcdev, idx);
+
+	return qcom_aoss_control_deassert(rcdev, idx);
+}
+
+static const struct reset_control_ops qcom_aoss_reset_ops = {
+	.reset = qcom_aoss_control_reset,
+	.assert = qcom_aoss_control_assert,
+	.deassert = qcom_aoss_control_deassert,
+};
+
+static int qcom_aoss_reset_probe(struct platform_device *pdev)
+{
+	struct qcom_aoss_reset_data *data;
+	struct device *dev = &pdev->dev;
+	const struct qcom_aoss_desc *desc;
+	struct resource *res;
+
+	desc = of_device_get_match_data(dev);
+	if (!desc)
+		return -EINVAL;
+
+	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->desc = desc;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	data->base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(data->base))
+		return PTR_ERR(data->base);
+
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.ops = &qcom_aoss_reset_ops;
+	data->rcdev.nr_resets = desc->num_resets;
+	data->rcdev.of_node = dev->of_node;
+
+	return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static const struct of_device_id qcom_aoss_reset_of_match[] = {
+	{ .compatible = "qcom,sdm845-aoss-reset", .data = &sdm845_aoss_desc },
+	{}
+};
+
+static struct platform_driver qcom_aoss_reset_driver = {
+	.probe = qcom_aoss_reset_probe,
+	.driver  = {
+		.name = "qcom_aoss_reset",
+		.of_match_table = qcom_aoss_reset_of_match,
+	},
+};
+
+builtin_platform_driver(qcom_aoss_reset_driver);
+
+MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
+MODULE_LICENSE("GPL v2");