blob: c69967bf6935d8fda54395627b8953ec1c3e3a14 [file] [log] [blame]
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020, Linaro Limited
4 */
5
6#include <common.h>
7#include <clk.h>
8#include <dm.h>
9#include <malloc.h>
Etienne Carriere8b9b6892020-09-09 18:44:07 +020010#include <reset.h>
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020011#include <asm/io.h>
12#include <asm/scmi_test.h>
13#include <dm/device_compat.h>
14
15/*
16 * Simulate to some extent a SCMI exchange.
17 * This drivers gets SCMI resources and offers API function to the
Etienne Carriere8b9b6892020-09-09 18:44:07 +020018 * SCMI test sequence manipulate the resources, currently clock
19 * and reset controllers.
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020020 */
21
22#define SCMI_TEST_DEVICES_CLK_COUNT 3
Etienne Carriere8b9b6892020-09-09 18:44:07 +020023#define SCMI_TEST_DEVICES_RD_COUNT 1
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020024
25/*
26 * struct sandbox_scmi_device_priv - Storage for device handles used by test
27 * @clk: Array of clock instances used by tests
Etienne Carriere8b9b6892020-09-09 18:44:07 +020028 * @reset_clt: Array of the reset controller instances used by tests
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020029 * @devices: Resources exposed by sandbox_scmi_devices_ctx()
30 */
31struct sandbox_scmi_device_priv {
32 struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT];
Etienne Carriere8b9b6892020-09-09 18:44:07 +020033 struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT];
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020034 struct sandbox_scmi_devices devices;
35};
36
37struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev)
38{
39 struct sandbox_scmi_device_priv *priv = dev_get_priv(dev);
40
41 if (priv)
42 return &priv->devices;
43
44 return NULL;
45}
46
Etienne Carriere8b9b6892020-09-09 18:44:07 +020047static int sandbox_scmi_devices_remove(struct udevice *dev)
48{
49 struct sandbox_scmi_devices *devices = sandbox_scmi_devices_ctx(dev);
50 int ret = 0;
51 size_t n;
52
53 for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) {
54 int ret2 = reset_free(devices->reset + n);
55
56 if (ret2 && !ret)
57 ret = ret2;
58 }
59
60 return ret;
61}
62
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020063static int sandbox_scmi_devices_probe(struct udevice *dev)
64{
65 struct sandbox_scmi_device_priv *priv = dev_get_priv(dev);
66 int ret;
67 size_t n;
68
69 priv->devices = (struct sandbox_scmi_devices){
70 .clk = priv->clk,
71 .clk_count = SCMI_TEST_DEVICES_CLK_COUNT,
Etienne Carriere8b9b6892020-09-09 18:44:07 +020072 .reset = priv->reset_ctl,
73 .reset_count = SCMI_TEST_DEVICES_RD_COUNT,
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020074 };
75
76 for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) {
77 ret = clk_get_by_index(dev, n, priv->devices.clk + n);
78 if (ret) {
79 dev_err(dev, "%s: Failed on clk %zu\n", __func__, n);
80 return ret;
81 }
82 }
83
Etienne Carriere8b9b6892020-09-09 18:44:07 +020084 for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) {
85 ret = reset_get_by_index(dev, n, priv->devices.reset + n);
86 if (ret) {
87 dev_err(dev, "%s: Failed on reset %zu\n", __func__, n);
88 goto err_reset;
89 }
90 }
91
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020092 return 0;
Etienne Carriere8b9b6892020-09-09 18:44:07 +020093
94err_reset:
95 for (; n > 0; n--)
96 reset_free(priv->devices.reset + n - 1);
97
98 return ret;
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020099}
100
101static const struct udevice_id sandbox_scmi_devices_ids[] = {
102 { .compatible = "sandbox,scmi-devices" },
103 { }
104};
105
106U_BOOT_DRIVER(sandbox_scmi_devices) = {
107 .name = "sandbox-scmi_devices",
108 .id = UCLASS_MISC,
109 .of_match = sandbox_scmi_devices_ids,
110 .priv_auto_alloc_size = sizeof(struct sandbox_scmi_device_priv),
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200111 .remove = sandbox_scmi_devices_remove,
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200112 .probe = sandbox_scmi_devices_probe,
113};