Lines Matching +full:gpu +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0
3 * T-HEAD TH1520 GPU Power Sequencer Driver
8 * This driver implements the power sequence for the Imagination BXM-4-64
9 * GPU on the T-HEAD TH1520 SoC. The sequence requires coordinating resources
10 * from both the sequencer's parent device node (clkgen_reset) and the GPU's
13 * The `match` function is used to acquire the GPU's resources when the
14 * GPU driver requests the "gpu-power" sequence target.
26 #include <dt-bindings/power/thead,th1520-power.h>
45 if (!ctx->clks || !ctx->gpu_reset) in pwrseq_thead_gpu_enable()
46 return -ENODEV; in pwrseq_thead_gpu_enable()
48 ret = clk_bulk_prepare_enable(ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_enable()
52 ret = reset_control_deassert(ctx->clkgen_reset); in pwrseq_thead_gpu_enable()
58 * cycles is required between de-asserting the clkgen reset and in pwrseq_thead_gpu_enable()
59 * de-asserting the GPU reset. Assuming a worst-case scenario with in pwrseq_thead_gpu_enable()
60 * a very high GPU clock frequency, a delay of 1 microsecond is in pwrseq_thead_gpu_enable()
62 * feasible GPU clock speeds. in pwrseq_thead_gpu_enable()
66 ret = reset_control_deassert(ctx->gpu_reset); in pwrseq_thead_gpu_enable()
73 reset_control_assert(ctx->clkgen_reset); in pwrseq_thead_gpu_enable()
75 clk_bulk_disable_unprepare(ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_enable()
84 if (!ctx->clks || !ctx->gpu_reset) in pwrseq_thead_gpu_disable()
85 return -ENODEV; in pwrseq_thead_gpu_disable()
87 err = reset_control_assert(ctx->gpu_reset); in pwrseq_thead_gpu_disable()
91 err = reset_control_assert(ctx->clkgen_reset); in pwrseq_thead_gpu_disable()
95 clk_bulk_disable_unprepare(ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_disable()
102 .name = "gpu-power-sequence",
108 .name = "gpu-power",
125 /* We only match the specific T-HEAD TH1520 GPU compatible */ in pwrseq_thead_gpu_match()
126 if (!of_device_is_compatible(dev->of_node, "thead,th1520-gpu")) in pwrseq_thead_gpu_match()
129 ret = of_parse_phandle_with_args(dev->of_node, "power-domains", in pwrseq_thead_gpu_match()
130 "#power-domain-cells", 0, &pwr_spec); in pwrseq_thead_gpu_match()
134 /* Additionally verify consumer device has AON as power-domain */ in pwrseq_thead_gpu_match()
135 if (pwr_spec.np != ctx->aon_node || pwr_spec.args[0] != TH1520_GPU_PD) { in pwrseq_thead_gpu_match()
142 /* If a consumer is already bound, only allow a re-match from it */ in pwrseq_thead_gpu_match()
143 if (ctx->consumer_node) in pwrseq_thead_gpu_match()
144 return ctx->consumer_node == dev->of_node ? in pwrseq_thead_gpu_match()
147 ctx->num_clks = ARRAY_SIZE(clk_names); in pwrseq_thead_gpu_match()
148 ctx->clks = kcalloc(ctx->num_clks, sizeof(*ctx->clks), GFP_KERNEL); in pwrseq_thead_gpu_match()
149 if (!ctx->clks) in pwrseq_thead_gpu_match()
150 return -ENOMEM; in pwrseq_thead_gpu_match()
152 for (i = 0; i < ctx->num_clks; i++) in pwrseq_thead_gpu_match()
153 ctx->clks[i].id = clk_names[i]; in pwrseq_thead_gpu_match()
155 ret = clk_bulk_get(dev, ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_match()
159 ctx->gpu_reset = reset_control_get_shared(dev, NULL); in pwrseq_thead_gpu_match()
160 if (IS_ERR(ctx->gpu_reset)) { in pwrseq_thead_gpu_match()
161 ret = PTR_ERR(ctx->gpu_reset); in pwrseq_thead_gpu_match()
165 ctx->consumer_node = of_node_get(dev->of_node); in pwrseq_thead_gpu_match()
170 clk_bulk_put(ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_match()
172 kfree(ctx->clks); in pwrseq_thead_gpu_match()
173 ctx->clks = NULL; in pwrseq_thead_gpu_match()
179 const struct auxiliary_device_id *id) in pwrseq_thead_gpu_probe() argument
181 struct device *dev = &adev->dev; in pwrseq_thead_gpu_probe()
182 struct device *parent_dev = dev->parent; in pwrseq_thead_gpu_probe()
188 return -ENOMEM; in pwrseq_thead_gpu_probe()
190 ctx->aon_node = parent_dev->of_node; in pwrseq_thead_gpu_probe()
192 ctx->clkgen_reset = in pwrseq_thead_gpu_probe()
193 devm_reset_control_get_exclusive(parent_dev, "gpu-clkgen"); in pwrseq_thead_gpu_probe()
194 if (IS_ERR(ctx->clkgen_reset)) in pwrseq_thead_gpu_probe()
196 dev, PTR_ERR(ctx->clkgen_reset), in pwrseq_thead_gpu_probe()
197 "Failed to get GPU clkgen reset from parent\n"); in pwrseq_thead_gpu_probe()
205 ctx->pwrseq = devm_pwrseq_device_register(dev, &config); in pwrseq_thead_gpu_probe()
206 if (IS_ERR(ctx->pwrseq)) in pwrseq_thead_gpu_probe()
207 return dev_err_probe(dev, PTR_ERR(ctx->pwrseq), in pwrseq_thead_gpu_probe()
219 if (ctx->gpu_reset) in pwrseq_thead_gpu_remove()
220 reset_control_put(ctx->gpu_reset); in pwrseq_thead_gpu_remove()
222 if (ctx->clks) { in pwrseq_thead_gpu_remove()
223 clk_bulk_put(ctx->num_clks, ctx->clks); in pwrseq_thead_gpu_remove()
224 kfree(ctx->clks); in pwrseq_thead_gpu_remove()
227 if (ctx->consumer_node) in pwrseq_thead_gpu_remove()
228 of_node_put(ctx->consumer_node); in pwrseq_thead_gpu_remove()
232 { .name = "th1520_pm_domains.pwrseq-gpu" },
239 .name = "pwrseq-thead-gpu",
248 MODULE_DESCRIPTION("T-HEAD TH1520 GPU power sequencer driver");