blob: 66a67928817f83950795fb3f80efe957b07008be [file] [log] [blame]
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +02001// SPDX-License-Identifier: GPL-2.0
2/*
Etienne Carriereb8f15cd2021-03-08 22:38:07 +01003 * Copyright (C) 2020-2021, Linaro Limited
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +02004 */
5
Patrick Delaunay5dd84d42021-02-24 11:19:44 +01006#define LOG_CATEGORY UCLASS_MISC
7
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +02008#include <common.h>
9#include <clk.h>
10#include <dm.h>
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010011#include <log.h>
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020012#include <malloc.h>
Etienne Carriere8b9b6892020-09-09 18:44:07 +020013#include <reset.h>
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020014#include <asm/io.h>
15#include <asm/scmi_test.h>
16#include <dm/device_compat.h>
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010017#include <power/regulator.h>
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020018
19/*
20 * Simulate to some extent a SCMI exchange.
21 * This drivers gets SCMI resources and offers API function to the
Etienne Carriere8b9b6892020-09-09 18:44:07 +020022 * SCMI test sequence manipulate the resources, currently clock
23 * and reset controllers.
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020024 */
25
26#define SCMI_TEST_DEVICES_CLK_COUNT 3
Etienne Carriere8b9b6892020-09-09 18:44:07 +020027#define SCMI_TEST_DEVICES_RD_COUNT 1
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010028#define SCMI_TEST_DEVICES_VOLTD_COUNT 2
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020029
30/*
31 * struct sandbox_scmi_device_priv - Storage for device handles used by test
32 * @clk: Array of clock instances used by tests
Etienne Carriere8b9b6892020-09-09 18:44:07 +020033 * @reset_clt: Array of the reset controller instances used by tests
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010034 * @regulators: Array of regulator device references used by the tests
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020035 * @devices: Resources exposed by sandbox_scmi_devices_ctx()
36 */
37struct sandbox_scmi_device_priv {
38 struct clk clk[SCMI_TEST_DEVICES_CLK_COUNT];
Etienne Carriere8b9b6892020-09-09 18:44:07 +020039 struct reset_ctl reset_ctl[SCMI_TEST_DEVICES_RD_COUNT];
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010040 struct udevice *regulators[SCMI_TEST_DEVICES_VOLTD_COUNT];
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020041 struct sandbox_scmi_devices devices;
42};
43
44struct sandbox_scmi_devices *sandbox_scmi_devices_ctx(struct udevice *dev)
45{
46 struct sandbox_scmi_device_priv *priv = dev_get_priv(dev);
47
48 if (priv)
49 return &priv->devices;
50
51 return NULL;
52}
53
Etienne Carriere8b9b6892020-09-09 18:44:07 +020054static int sandbox_scmi_devices_remove(struct udevice *dev)
55{
56 struct sandbox_scmi_devices *devices = sandbox_scmi_devices_ctx(dev);
57 int ret = 0;
58 size_t n;
59
Heinrich Schuchardt748cbaa2021-02-01 03:01:54 +010060 if (!devices)
61 return 0;
62
Etienne Carriere8b9b6892020-09-09 18:44:07 +020063 for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) {
64 int ret2 = reset_free(devices->reset + n);
65
66 if (ret2 && !ret)
67 ret = ret2;
68 }
69
70 return ret;
71}
72
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020073static int sandbox_scmi_devices_probe(struct udevice *dev)
74{
75 struct sandbox_scmi_device_priv *priv = dev_get_priv(dev);
76 int ret;
77 size_t n;
78
79 priv->devices = (struct sandbox_scmi_devices){
80 .clk = priv->clk,
81 .clk_count = SCMI_TEST_DEVICES_CLK_COUNT,
Etienne Carriere8b9b6892020-09-09 18:44:07 +020082 .reset = priv->reset_ctl,
83 .reset_count = SCMI_TEST_DEVICES_RD_COUNT,
Etienne Carriereb8f15cd2021-03-08 22:38:07 +010084 .regul = priv->regulators,
85 .regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT,
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +020086 };
87
88 for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) {
89 ret = clk_get_by_index(dev, n, priv->devices.clk + n);
90 if (ret) {
91 dev_err(dev, "%s: Failed on clk %zu\n", __func__, n);
92 return ret;
93 }
94 }
95
Etienne Carriere8b9b6892020-09-09 18:44:07 +020096 for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) {
97 ret = reset_get_by_index(dev, n, priv->devices.reset + n);
98 if (ret) {
99 dev_err(dev, "%s: Failed on reset %zu\n", __func__, n);
100 goto err_reset;
101 }
102 }
103
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100104 for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) {
105 char name[32];
106
107 ret = snprintf(name, sizeof(name), "regul%zu-supply", n);
108 assert(ret >= 0 && ret < sizeof(name));
109
110 ret = device_get_supply_regulator(dev, name,
111 priv->devices.regul + n);
112 if (ret) {
113 dev_err(dev, "%s: Failed on voltd %zu\n", __func__, n);
114 goto err_regul;
115 }
116 }
117
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200118 return 0;
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200119
Etienne Carriereb8f15cd2021-03-08 22:38:07 +0100120err_regul:
121 n = SCMI_TEST_DEVICES_RD_COUNT;
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200122err_reset:
123 for (; n > 0; n--)
124 reset_free(priv->devices.reset + n - 1);
125
126 return ret;
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200127}
128
129static const struct udevice_id sandbox_scmi_devices_ids[] = {
130 { .compatible = "sandbox,scmi-devices" },
131 { }
132};
133
134U_BOOT_DRIVER(sandbox_scmi_devices) = {
135 .name = "sandbox-scmi_devices",
136 .id = UCLASS_MISC,
137 .of_match = sandbox_scmi_devices_ids,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700138 .priv_auto = sizeof(struct sandbox_scmi_device_priv),
Etienne Carriere8b9b6892020-09-09 18:44:07 +0200139 .remove = sandbox_scmi_devices_remove,
Etienne Carriere2d94c08fa2020-09-09 18:44:05 +0200140 .probe = sandbox_scmi_devices_probe,
141};