1 /*
2  * Copyright 2024 Microchip Technology Inc. and its subsidiaries.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #ifndef _MEC_BBLED_API_H
7 #define _MEC_BBLED_API_H
8 
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 #include "mec_defs.h"
14 #include "mec_retval.h"
15 
16 /* Interfaces to any C modules */
17 #ifdef __cplusplus
18 extern "C"
19 {
20 #endif
21 
22 enum mec_bbled_mode {
23     MEC_BBLED_MODE_OFF = 0,
24     MEC_BBLED_MODE_BREATHE,
25     MEC_BBLED_MODE_BLINK,
26     MEC_BBLED_MODE_ON,
27 };
28 
29 enum mec_bbled_blink_clk_sel {
30     MEC_BBLED_BLINK_CLK_SEL_32K = 0,
31     MEC_BBLED_BLINK_CLK_SEL_SYS,
32 };
33 
34 enum mec_bbled_breathe_pwm_width {
35     MEC_BBLED_PWM_WIDTH_8 = 0,
36     MEC_BBLED_PWM_WIDTH_7 = 1,
37     MEC_BBLED_PWM_WIDTH_6 = 2,
38 };
39 
40 /* BBLED initialization configuration */
41 #define MEC_BBLED_CFG_SOFT_RESET_POS    0
42 #define MEC_BBLED_CFG_SOFT_RESET        (1u << MEC_BBLED_CFG_SOFT_RESET_POS)
43 
44 /* Default breathing ramp up/down times are symmetric (same).
45  * Asymmetric mode allows ramp up and down to be different.
46  */
47 #define MEC_BBLED_CFG_WDT_ASYM_EN_POS   1
48 #define MEC_BBLED_CFG_WDT_ASYM_EN       MEC_BIT(MEC_BBLED_CFG_WDT_ASYM_EN_POS)
49 
50 #define MEC_BBLED_CFG_SET_WDT_RLD_POS   7
51 
52 #define MEC_BBLED_CFG_WDT_RELOAD_POS    8
53 #define MEC_BBLED_CFG_WDT_RELOAD_MSK0   0xffu
54 #define MEC_BBLED_CFG_WDT_RELOAD_MSK    0xff00u
55 #define MEC_BBLED_CFG_WDT_RELOAD_DFLT0  0x14u
56 #define MEC_BBLED_CFG_WDT_RELOAD_DFLT   0x1400u
57 
58 /* forward reference */
59 struct mec_bbled_regs;
60 
61 #define MEC_BBLED_BLINK_PWM_FREQ_32K 0
62 #define MEC_BBLED_BLINK_PWM_FREQ_SYS 1
63 
64 struct mec_bbled_blink_config {
65     uint16_t pwm_clk_prescaler;
66     uint8_t duty_cycle;
67     uint8_t flags; /* freq select (32KHz vs system clock) */
68 };
69 
70 struct mec_bbled_breathe_config {
71     uint32_t upd_intervals; /* 4-bit fields update intervals 0-7 */
72     uint32_t upd_steps; /* 4-bit fields update steps 0-7 */
73     uint16_t lo_delay; /* periods to wait before updating dc */
74     uint16_t hi_delay; /* periods to wait before updating dc */
75     uint8_t min_hold; /* current dc <= min_hold. Hold dc for low delay periods */
76     uint8_t max_hold; /* current dc >= max_hold. Hold dc for high delay periods */
77     uint8_t pwm_width; /* must be programmed before BBLED is set to Breathe mode */
78 };
79 
80 bool mec_hal_bbled_is_valid(struct mec_bbled_regs *regs);
81 
82 bool mec_hal_bbled_is_off(struct mec_bbled_regs *regs);
83 
84 int mec_hal_bbled_init(struct mec_bbled_regs *regs, uint32_t bbled_config);
85 
86 uint32_t mec_hal_bbled_clk_freq(struct mec_bbled_regs *regs);
87 
88 int mec_hal_bbled_mode(struct mec_bbled_regs *regs, uint8_t mode);
89 uint8_t mec_hal_bbled_mode_get(struct mec_bbled_regs *regs);
90 
91 /* Select Breathe mode PWM width: 8-bit(default), 7-bit, or 6-bit.
92  * PWM width is not latched into a holding register and changing it while
93  * Breathe mode is active will cause an immediate change in the output
94  * waveform. PWM width should be set while the BBLED is in OFF state.
95  */
96 int mec_hal_bbled_breathe_pwm_width(struct mec_bbled_regs *regs, uint8_t pwm_width);
97 uint8_t mec_hal_bbled_breathe_pwm_width_get(struct mec_bbled_regs *regs);
98 
99 /* Select clock source 32KHz vs system bus block (48MHz) for blink(PWM) mode
100  * Changing clock select while the BBLED is in Blink mode will cause the
101  * frequency to immediately change. Clock select is not latch like the duty
102  * cycle and prescaler are.
103  */
104 int mec_hal_bbled_blink_clk_sel(struct mec_bbled_regs *regs, uint8_t blink_clk_sel);
105 uint8_t mec_hal_bbled_blink_clk_sel_get(struct mec_bbled_regs *regs);
106 
107 void mec_hal_bbled_synchronize_enable(struct mec_bbled_regs *regs, uint8_t enable);
108 
109 void mec_hal_bbled_asym_enable(struct mec_bbled_regs *regs, uint8_t enable);
110 
111 /* Set BBLED to update load new values of its Delay, Step, and Interval
112  * registers when the current PWM period ends.
113  */
114 void mec_hal_bbled_enable_update(struct mec_bbled_regs *regs);
115 
116 /* If true the hardware is currently updating Delay, Step, and Interval registers.
117  * If false writes to Delay, Step, or Interval register are stored in internal
118  * holding registers until firmware sets the enable update bit.
119  */
120 bool mec_hal_bbled_enable_is_update(struct mec_bbled_regs *regs);
121 
122 /* Program LED breathing configuration.
123  * If BBLED is in Blink mode return an error
124  * If BBLED is in OFF OR ON mode the values are programmed and will take effect
125  * when BBLED is switched to Breathe mode.
126  * If BBLED is in Breathe mode the values are programmed and hardware latches
127  * the new values into holding registers. Firwmare must then call mec_hal_enable_update
128  * to cause hardware to load the new values at the end of the current PWM period.
129  */
130 int mec_hal_bbled_breathe_config(struct mec_bbled_regs *regs,
131                                  struct mec_bbled_breathe_config *br_cfg);
132 int mec_hal_bbled_breathe_config_get(struct mec_bbled_regs *regs,
133                                      struct mec_bbled_breathe_config *br_cfg);
134 
135 /* Program LED blinking configuration.
136  * If BBLED is in Breathe mode return an error
137  * If BBLED is in OFF OR ON mode the values are programmed and will take effect
138  * when BBLED is switched to Blink mode.
139  * If BBLED is in Blink mode the values are programmed and hardware latches
140  * the new values into holding registers. Firwmare must then call mec_hal_enable_update
141  * to cause hardware to load the new values at the end of the current PWM period.
142  * Blink mode clock select is not latched and should be done while BBLED is in the
143  * OFF state.
144  */
145 int mec_hal_bbled_blink_config(struct mec_bbled_regs *regs, struct mec_bbled_blink_config *bl_cfg);
146 int mec_hal_bbled_blink_config_get(struct mec_bbled_regs *regs,
147                                    struct mec_bbled_blink_config *bl_cfg);
148 
149 /* Compute the Blink mode PWM frequency based on current Blink and clock select configuration */
150 uint32_t mec_hal_bbled_blink_pwm_freq_get(struct mec_bbled_regs *regs);
151 
152 int mec_hal_bbled_girq_ctrl(struct mec_bbled_regs *regs, uint8_t enable);
153 
154 int mec_hal_bbled_girq_status_clr(struct mec_bbled_regs *regs);
155 
156 #ifdef __cplusplus
157 }
158 #endif
159 
160 #endif /* #ifndef _MEC_BBLED_API_H */
161