1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 The Linux Foundation. All rights reserved.
6 #include <linux/module.h>
7 #include <linux/platform_device.h>
8 #include <linux/reset-controller.h>
9 #include <linux/delay.h>
11 #include <linux/of_device.h>
12 #include <dt-bindings/reset/qcom,sdm845-aoss.h>
14 struct qcom_aoss_reset_map
{
18 struct qcom_aoss_desc
{
19 const struct qcom_aoss_reset_map
*resets
;
23 struct qcom_aoss_reset_data
{
24 struct reset_controller_dev rcdev
;
26 const struct qcom_aoss_desc
*desc
;
29 static const struct qcom_aoss_reset_map sdm845_aoss_resets
[] = {
30 [AOSS_CC_MSS_RESTART
] = {0x10000},
31 [AOSS_CC_CAMSS_RESTART
] = {0x11000},
32 [AOSS_CC_VENUS_RESTART
] = {0x12000},
33 [AOSS_CC_GPU_RESTART
] = {0x13000},
34 [AOSS_CC_DISPSS_RESTART
] = {0x14000},
35 [AOSS_CC_WCSS_RESTART
] = {0x20000},
36 [AOSS_CC_LPASS_RESTART
] = {0x30000},
39 static const struct qcom_aoss_desc sdm845_aoss_desc
= {
40 .resets
= sdm845_aoss_resets
,
41 .num_resets
= ARRAY_SIZE(sdm845_aoss_resets
),
44 static inline struct qcom_aoss_reset_data
*to_qcom_aoss_reset_data(
45 struct reset_controller_dev
*rcdev
)
47 return container_of(rcdev
, struct qcom_aoss_reset_data
, rcdev
);
50 static int qcom_aoss_control_assert(struct reset_controller_dev
*rcdev
,
53 struct qcom_aoss_reset_data
*data
= to_qcom_aoss_reset_data(rcdev
);
54 const struct qcom_aoss_reset_map
*map
= &data
->desc
->resets
[idx
];
56 writel(1, data
->base
+ map
->reg
);
57 /* Wait 6 32kHz sleep cycles for reset */
58 usleep_range(200, 300);
62 static int qcom_aoss_control_deassert(struct reset_controller_dev
*rcdev
,
65 struct qcom_aoss_reset_data
*data
= to_qcom_aoss_reset_data(rcdev
);
66 const struct qcom_aoss_reset_map
*map
= &data
->desc
->resets
[idx
];
68 writel(0, data
->base
+ map
->reg
);
69 /* Wait 6 32kHz sleep cycles for reset */
70 usleep_range(200, 300);
74 static int qcom_aoss_control_reset(struct reset_controller_dev
*rcdev
,
77 qcom_aoss_control_assert(rcdev
, idx
);
79 return qcom_aoss_control_deassert(rcdev
, idx
);
82 static const struct reset_control_ops qcom_aoss_reset_ops
= {
83 .reset
= qcom_aoss_control_reset
,
84 .assert = qcom_aoss_control_assert
,
85 .deassert
= qcom_aoss_control_deassert
,
88 static int qcom_aoss_reset_probe(struct platform_device
*pdev
)
90 struct qcom_aoss_reset_data
*data
;
91 struct device
*dev
= &pdev
->dev
;
92 const struct qcom_aoss_desc
*desc
;
95 desc
= of_device_get_match_data(dev
);
99 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
104 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
105 data
->base
= devm_ioremap_resource(dev
, res
);
106 if (IS_ERR(data
->base
))
107 return PTR_ERR(data
->base
);
109 data
->rcdev
.owner
= THIS_MODULE
;
110 data
->rcdev
.ops
= &qcom_aoss_reset_ops
;
111 data
->rcdev
.nr_resets
= desc
->num_resets
;
112 data
->rcdev
.of_node
= dev
->of_node
;
114 return devm_reset_controller_register(dev
, &data
->rcdev
);
117 static const struct of_device_id qcom_aoss_reset_of_match
[] = {
118 { .compatible
= "qcom,sdm845-aoss-cc", .data
= &sdm845_aoss_desc
},
121 MODULE_DEVICE_TABLE(of
, qcom_aoss_reset_of_match
);
123 static struct platform_driver qcom_aoss_reset_driver
= {
124 .probe
= qcom_aoss_reset_probe
,
126 .name
= "qcom_aoss_reset",
127 .of_match_table
= qcom_aoss_reset_of_match
,
131 module_platform_driver(qcom_aoss_reset_driver
);
133 MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
134 MODULE_LICENSE("GPL v2");