diff --git a/sw/device/lib/dif/dif_pwm.h b/sw/device/lib/dif/dif_pwm.h index 6e05ba8b152d07..696bd559688a68 100644 --- a/sw/device/lib/dif/dif_pwm.h +++ b/sw/device/lib/dif/dif_pwm.h @@ -155,7 +155,7 @@ typedef struct dif_pwm_channel_config { * software manages the conversion from "beats_per_cycle" to * "phase_counter_ticks" under the hood. */ - uint16_t duty_cycle_a; + uint32_t duty_cycle_a; /** * Secondary duty cycle, in number of "beats" / "pulse cycle", that is only * relevant in heartbeat and blink modes. @@ -164,14 +164,14 @@ typedef struct dif_pwm_channel_config { * * Note: above notes for `duty_cycle_a` apply here too. */ - uint16_t duty_cycle_b; + uint32_t duty_cycle_b; /** * Phase delay at the beginning of a "pulse cycle" to delay the active * duty cycle "beats" for, in number of "beats". * * Valid range: [0, beats_per_pulse_cycle) */ - uint16_t phase_delay; + uint32_t phase_delay; /** * The operation mode to configure the channel in, see `dif_pwm_mode_t`. */ @@ -191,7 +191,7 @@ typedef struct dif_pwm_channel_config { * - Blink mode: determines the number of "pulse cycles" to pulse at duty * cycle A, before switching to duty cycle B. */ - uint16_t blink_parameter_x; + uint32_t blink_parameter_x; /** * One of two blink parameters that only impact the "Heartbeat" and "Blink" * operation modes. @@ -208,7 +208,7 @@ typedef struct dif_pwm_channel_config { * "beats". However, for ease of configuration, the software manages this * conversion under the hood. */ - uint16_t blink_parameter_y; + uint32_t blink_parameter_y; } dif_pwm_channel_config_t; /** diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index 03137e356e301f..1dca9babada1d8 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD @@ -2763,6 +2763,29 @@ opentitan_test( ], ) +opentitan_test( + name = "pwm_smoketest", + srcs = ["pwm_smoketest.c"], + exec_env = dicts.add( + EARLGREY_TEST_ENVS, + EARLGREY_SILICON_OWNER_ROM_EXT_ENVS, + { + "//hw/top_earlgrey:fpga_cw340_rom_with_fake_keys": None, + "//hw/top_earlgrey:silicon_owner_sival_rom_ext": None, + } + ), + deps = [ + "//hw/top_earlgrey/sw/autogen:top_earlgrey", + "//sw/device/lib/dif:pinmux", + "//sw/device/lib/dif:pwm", + "//sw/device/lib/runtime:hart", + "//sw/device/lib/runtime:ibex", + "//sw/device/lib/runtime:irq", + "//sw/device/lib/runtime:log", + "//sw/device/lib/testing/test_framework:ottf_main", + ], +) + cc_library( name = "pwrmgr_sleep_resets_lib", srcs = ["pwrmgr_sleep_resets_lib.c"], diff --git a/sw/device/tests/pwm_smoketest.c b/sw/device/tests/pwm_smoketest.c new file mode 100644 index 00000000000000..882ae48b378d06 --- /dev/null +++ b/sw/device/tests/pwm_smoketest.c @@ -0,0 +1,59 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_pwm.h" +#include "sw/device/lib/runtime/hart.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/test_framework/check.h" +#include "sw/device/lib/testing/test_framework/ottf_main.h" + +#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" + +OTTF_DEFINE_TEST_CONFIG(); + +static status_t pwm_pinmux(void) { + + dif_pinmux_t pinmux; + mmio_region_t base_addr = + mmio_region_from_addr(TOP_EARLGREY_PINMUX_AON_BASE_ADDR); + CHECK_DIF_OK(dif_pinmux_init(base_addr, &pinmux)); + + TRY(dif_pinmux_output_select(&pinmux, kTopEarlgreyPinmuxMioOutIoa8, + kTopEarlgreyPinmuxOutselPwmAonPwm0)); + + return OK_STATUS(); +} + +bool test_main(void) { + dif_pwm_t pwm; + mmio_region_t base_addr = mmio_region_from_addr(TOP_EARLGREY_PWM_AON_BASE_ADDR); + CHECK_DIF_OK(dif_pwm_init(base_addr, &pwm)); + CHECK_STATUS_OK(pwm_pinmux()); + + const dif_pwm_config_t kPwmConfig = { + .clock_divisor = 0x08000, + .beats_per_pulse_cycle = 2, + }; + CHECK_DIF_OK(dif_pwm_configure(&pwm, kPwmConfig)); + + dif_pwm_channel_config_t channel_config = { + .duty_cycle_a = kPwmConfig.beats_per_pulse_cycle / 2, + .duty_cycle_b = 0, + .phase_delay = 0, + .mode = kDifPwmModeFirmware, + .polarity = kDifPwmPolarityActiveHigh, + .blink_parameter_x = 0, + .blink_parameter_y = 0, + }; + CHECK_DIF_OK(dif_pwm_configure_channel(&pwm, kDifPwmChannel0, channel_config)); + CHECK_DIF_OK(dif_pwm_phase_cntr_set_enabled(&pwm, kDifToggleEnabled)); + CHECK_DIF_OK(dif_pwm_channel_set_enabled(&pwm, kDifPwmChannel0, kDifToggleEnabled)); + + busy_spin_micros(500 * 1000); + return true; +}