compatible = "sandbox,clk-test";
clocks = <&clk_fixed>,
<&clk_sandbox 1>,
- <&clk_sandbox 0>;
- clock-names = "fixed", "i2c", "spi";
+ <&clk_sandbox 0>,
+ <&clk_sandbox 3>,
+ <&clk_sandbox 2>;
+ clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
};
ccf: clk-ccf {
enum sandbox_clk_id {
SANDBOX_CLK_ID_SPI,
SANDBOX_CLK_ID_I2C,
+ SANDBOX_CLK_ID_UART1,
+ SANDBOX_CLK_ID_UART2,
SANDBOX_CLK_ID_COUNT,
};
SANDBOX_CLK_TEST_ID_FIXED,
SANDBOX_CLK_TEST_ID_SPI,
SANDBOX_CLK_TEST_ID_I2C,
+ SANDBOX_CLK_TEST_ID_DEVM1,
+ SANDBOX_CLK_TEST_ID_DEVM2,
+ SANDBOX_CLK_TEST_ID_DEVM_NULL,
SANDBOX_CLK_TEST_ID_COUNT,
};
+#define SANDBOX_CLK_TEST_NON_DEVM_COUNT SANDBOX_CLK_TEST_ID_DEVM1
+
/**
* sandbox_clk_query_rate - Query the current rate of a sandbox clock.
*
* @return: The rate of the clock.
*/
int sandbox_clk_query_enable(struct udevice *dev, int id);
+/**
+ * sandbox_clk_query_requested - Query the requested state of a sandbox clock.
+ *
+ * @dev: The sandbox clock provider device.
+ * @id: The clock to query.
+ * @return: The rate of the clock.
+ */
+int sandbox_clk_query_requested(struct udevice *dev, int id);
/**
* sandbox_clk_test_get - Ask the sandbox clock test device to request its
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_get(struct udevice *dev);
+
+/**
+ * sandbox_clk_test_devm_get - Ask the sandbox clock test device to request its
+ * clocks using the managed API.
+ *
+ * @dev: The sandbox clock test (client) devivce.
+ * @return: 0 if OK, or a negative error code.
+ */
+int sandbox_clk_test_devm_get(struct udevice *dev);
+
/**
* sandbox_clk_test_get_bulk - Ask the sandbox clock test device to request its
* clocks with the bulk clk API.
* @return: 0 if OK, or a negative error code.
*/
int sandbox_clk_test_valid(struct udevice *dev);
+/**
+ * sandbox_clk_test_valid - Ask the sandbox clock test device to check its
+ * clocks are valid.
+ *
+ * @dev: The sandbox clock test (client) devivce.
+ * @return: 0 if OK, or a negative error code.
+ */
+struct clk *sandbox_clk_test_get_devm_clk(struct udevice *dev, int id);
#endif
struct sandbox_clk_priv {
ulong rate[SANDBOX_CLK_ID_COUNT];
bool enabled[SANDBOX_CLK_ID_COUNT];
+ bool requested[SANDBOX_CLK_ID_COUNT];
};
static ulong sandbox_clk_get_rate(struct clk *clk)
return 0;
}
+static int sandbox_clk_request(struct clk *clk)
+{
+ struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ return -EINVAL;
+
+ priv->requested[clk->id] = true;
+ return 0;
+}
+
+static int sandbox_clk_free(struct clk *clk)
+{
+ struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+ if (clk->id >= SANDBOX_CLK_ID_COUNT)
+ return -EINVAL;
+
+ priv->requested[clk->id] = false;
+ return 0;
+}
+
static struct clk_ops sandbox_clk_ops = {
.get_rate = sandbox_clk_get_rate,
.set_rate = sandbox_clk_set_rate,
.enable = sandbox_clk_enable,
.disable = sandbox_clk_disable,
+ .request = sandbox_clk_request,
+ .free = sandbox_clk_free,
};
static const struct udevice_id sandbox_clk_ids[] = {
return priv->enabled[id];
}
+
+int sandbox_clk_query_requested(struct udevice *dev, int id)
+{
+ struct sandbox_clk_priv *priv = dev_get_priv(dev);
+
+ if (id < 0 || id >= SANDBOX_CLK_ID_COUNT)
+ return -EINVAL;
+ return priv->requested[id];
+}
#include <asm/clk.h>
struct sandbox_clk_test {
- struct clk clks[SANDBOX_CLK_TEST_ID_COUNT];
+ struct clk clks[SANDBOX_CLK_TEST_NON_DEVM_COUNT];
+ struct clk *clkps[SANDBOX_CLK_TEST_ID_COUNT];
struct clk_bulk bulk;
};
struct sandbox_clk_test *sbct = dev_get_priv(dev);
int i, ret;
- for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+ for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
ret = clk_get_by_name(dev, sandbox_clk_test_names[i],
&sbct->clks[i]);
if (ret)
return 0;
}
+int sandbox_clk_test_devm_get(struct udevice *dev)
+{
+ struct sandbox_clk_test *sbct = dev_get_priv(dev);
+ struct clk *clk;
+
+ clk = devm_clk_get(dev, "no-an-existing-clock");
+ if (!IS_ERR(clk)) {
+ dev_err(dev, "devm_clk_get() should have failed\n");
+ return -EINVAL;
+ }
+
+ clk = devm_clk_get(dev, "uart2");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1] = clk;
+
+ clk = devm_clk_get_optional(dev, "uart1");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM2] = clk;
+
+ sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM_NULL] = NULL;
+ clk = devm_clk_get_optional(dev, "not_an_existing_clock");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ if (clk)
+ return -EINVAL;
+
+ return 0;
+}
+
int sandbox_clk_test_get_bulk(struct udevice *dev)
{
struct sandbox_clk_test *sbct = dev_get_priv(dev);
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
- return clk_get_rate(&sbct->clks[id]);
+ return clk_get_rate(sbct->clkps[id]);
}
ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
- return clk_set_rate(&sbct->clks[id], rate);
+ return clk_set_rate(sbct->clkps[id], rate);
}
int sandbox_clk_test_enable(struct udevice *dev, int id)
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
- return clk_enable(&sbct->clks[id]);
+ return clk_enable(sbct->clkps[id]);
}
int sandbox_clk_test_enable_bulk(struct udevice *dev)
if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
return -EINVAL;
- return clk_disable(&sbct->clks[id]);
+ return clk_disable(sbct->clkps[id]);
}
int sandbox_clk_test_disable_bulk(struct udevice *dev)
struct sandbox_clk_test *sbct = dev_get_priv(dev);
int i, ret;
- for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
+ devm_clk_put(dev, sbct->clkps[SANDBOX_CLK_TEST_ID_DEVM1]);
+ for (i = 0; i < SANDBOX_CLK_TEST_NON_DEVM_COUNT; i++) {
ret = clk_free(&sbct->clks[i]);
if (ret)
return ret;
int i;
for (i = 0; i < SANDBOX_CLK_TEST_ID_COUNT; i++) {
- if (!clk_valid(&sbct->clks[i]))
- return -EINVAL;
+ if (!clk_valid(sbct->clkps[i]))
+ if (i != SANDBOX_CLK_TEST_ID_DEVM_NULL)
+ return -EINVAL;
}
return 0;
}
+static int sandbox_clk_test_probe(struct udevice *dev)
+{
+ struct sandbox_clk_test *sbct = dev_get_priv(dev);
+ int i;
+
+ for (i = 0; i < SANDBOX_CLK_TEST_ID_DEVM1; i++)
+ sbct->clkps[i] = &sbct->clks[i];
+ for (i = SANDBOX_CLK_TEST_ID_DEVM1; i < SANDBOX_CLK_TEST_ID_COUNT; i++)
+ sbct->clkps[i] = NULL;
+
+ return 0;
+}
+
static const struct udevice_id sandbox_clk_test_ids[] = {
{ .compatible = "sandbox,clk-test" },
{ }
.name = "sandbox_clk_test",
.id = UCLASS_MISC,
.of_match = sandbox_clk_test_ids,
+ .probe = sandbox_clk_test_probe,
.priv_auto_alloc_size = sizeof(struct sandbox_clk_test),
};
#include <dm.h>
#include <asm/clk.h>
#include <dm/test.h>
+#include <dm/device-internal.h>
#include <linux/err.h>
#include <test/ut.h>
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test",
&dev_test));
ut_assertok(sandbox_clk_test_get(dev_test));
+ ut_assertok(sandbox_clk_test_devm_get(dev_test));
ut_assertok(sandbox_clk_test_valid(dev_test));
+ ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM_NULL));
+ ut_asserteq(0, sandbox_clk_test_set_rate(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM_NULL,
+ 0));
+ ut_asserteq(0, sandbox_clk_test_enable(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM_NULL));
+ ut_asserteq(0, sandbox_clk_test_disable(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM_NULL));
+
ut_asserteq(1234,
sandbox_clk_test_get_rate(dev_test,
SANDBOX_CLK_TEST_ID_FIXED));
SANDBOX_CLK_TEST_ID_SPI));
ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
SANDBOX_CLK_TEST_ID_I2C));
+ ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM1));
+ ut_asserteq(0, sandbox_clk_test_get_rate(dev_test,
+ SANDBOX_CLK_TEST_ID_DEVM2));
rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_FIXED,
12345);
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
+ ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_SPI));
+ ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_I2C));
+ ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_UART2));
ut_assertok(sandbox_clk_test_free(dev_test));
-
+ ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_SPI));
+ ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_I2C));
+ ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_UART2));
+
+ ut_asserteq(1, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_UART1));
+ ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL));
+ ut_asserteq(0, sandbox_clk_query_requested(dev_clk,
+ SANDBOX_CLK_ID_UART1));
return 0;
}
DM_TEST(dm_test_clk, DM_TESTF_SCAN_FDT);
ut_assertok(sandbox_clk_test_release_bulk(dev_test));
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_SPI));
ut_asserteq(0, sandbox_clk_query_enable(dev_clk, SANDBOX_CLK_ID_I2C));
+ ut_assertok(device_remove(dev_test, DM_REMOVE_NORMAL));
return 0;
}