@@ -36,6 +36,7 @@ static clock_management_state_t dev2_shared =
3636static clock_management_state_t dev2_locking =
3737 CLOCK_MANAGEMENT_DT_GET_STATE (DT_NODELABEL (emul_dev2 ), default , locking );
3838
39+
3940/* Define a second output using the same clock as emul_dev1 */
4041CLOCK_MANAGEMENT_DEFINE_OUTPUT (DT_PHANDLE_BY_IDX (DT_NODELABEL (emul_dev1 ), clock_outputs ,
4142 DT_CLOCK_OUTPUT_NAME_IDX (DT_NODELABEL (emul_dev1 ), default )),
@@ -293,6 +294,75 @@ ZTEST(clock_management_api, test_ranked)
293294 zassert_true (ret > 0 , "Consumer 2 could not remove clock restrictions" );
294295}
295296
297+ #if DT_HAS_COMPAT_STATUS_OKAY (vnd_emul_clock_gateable )
298+ /* Only run this test if the gateable clock is present- this is all emulated,
299+ * so it likely only needs to run on native_sim
300+ */
301+
302+ CLOCK_MANAGEMENT_DT_DEFINE_OUTPUT_BY_NAME (DT_NODELABEL (emul_dev3 ), default );
303+
304+ static const struct clock_output * dev3_out =
305+ CLOCK_MANAGEMENT_DT_GET_OUTPUT_BY_NAME (DT_NODELABEL (emul_dev3 ), default );
306+
307+ /*
308+ * Define a basic driver here for the gateable clock
309+ */
310+
311+ #define DT_DRV_COMPAT vnd_emul_clock_gateable
312+
313+ static bool clock_is_gated ;
314+
315+ struct gateable_clock_data {
316+ STANDARD_CLK_SUBSYS_DATA_DEFINE
317+ };
318+
319+ static clock_freq_t gateable_clock_recalc_rate (const struct clk * clk_hw , clock_freq_t parent_rate )
320+ {
321+ return clock_is_gated ? parent_rate : 0 ;
322+ }
323+
324+ static int gateable_clock_onoff (const struct clk * clk_hw , bool on )
325+ {
326+ clock_is_gated = !on ;
327+ return 0 ;
328+ }
329+
330+ const struct clock_management_standard_api gateable_clock_api = {
331+ .recalc_rate = gateable_clock_recalc_rate ,
332+ .shared .on_off = gateable_clock_onoff ,
333+ };
334+
335+ #define GATEABLE_CLOCK_DEFINE (inst ) \
336+ static struct gateable_clock_data gate_clk_##inst = { \
337+ STANDARD_CLK_SUBSYS_DATA_INIT(CLOCK_DT_GET(DT_INST_PARENT(inst))) \
338+ }; \
339+ CLOCK_DT_INST_DEFINE(inst, \
340+ &gate_clk_##inst, \
341+ &gateable_clock_api);
342+
343+ DT_INST_FOREACH_STATUS_OKAY (GATEABLE_CLOCK_DEFINE )
344+
345+ ZTEST (clock_management_api , test_onoff )
346+ {
347+ /* First disable all unused clocks. We should see the gateable one switch off. */
348+ clock_management_disable_unused ();
349+ zassert_true (clock_is_gated , "Emulated clock is unused but did not gate" );
350+ /* Now enable the clock for dev3 */
351+ clock_management_on (dev3_out );
352+ zassert_false (clock_is_gated , "Emulated clock is in use but gated" );
353+ /* Make sure the clock doesn't turn off now, it is in use */
354+ clock_management_disable_unused ();
355+ zassert_false (clock_is_gated , "Emulated clock is in use but gated during disabled_unused" );
356+ /* Raise reference count to clock */
357+ clock_management_on (dev3_out );
358+ /* Lower reference count */
359+ clock_management_off (dev3_out );
360+ zassert_false (clock_is_gated , "Emulated clock should not gate, one reference still exists" );
361+ /* Turn off the clock */
362+ clock_management_off (dev3_out );
363+ zassert_true (clock_is_gated , "Emulated clock is off but did not gate" );
364+ }
296365
366+ #endif /* DT_HAS_COMPAT_STATUS_OKAY(vnd_emul_clock_gateable) */
297367
298368ZTEST_SUITE (clock_management_api , NULL , NULL , reset_clock_states , NULL , NULL );
0 commit comments