esp_hal/gpio/lp_io/low_level/
esp32p4.rs1use crate::{
2 gpio::{
3 LpPin,
4 lp_io::{LpFunction, LpInputSignal, LpOutputSignal},
5 },
6 peripherals::{HP_SYS, LP_GPIO, LP_IO_MUX},
7};
8
9for_each_lp_function! {
10 (($_lp_pin_name:ident, LP_GPIOn, $lp_pin:literal), $gpio:ident, $_af:ident, $_lp_in:tt $_lp_out:tt) => {
11 impl LpPin for crate::peripherals::$gpio<'_> {
12 fn lp_number(&self) -> u8 {
13 $lp_pin
14 }
15 }
16 };
17
18 (LP_GPIOn $((
20 ($_lp_pin_name:ident, LP_GPIOn, $lp_pin:literal),
21 $gpio:ident,
22 $_af:ident,
23 ($( $lp_in_af:ident => $lp_in_signal:ident )*)
24 ($( $lp_out_af:ident => $lp_out_signal:ident )*)
25 )),*) => {
26 pub(crate) fn input_signals(lp: u8) -> &'static [(LpFunction, LpInputSignal)] {
27 match lp {
28 $( $lp_pin => &[$( (LpFunction::$lp_in_af, LpInputSignal::$lp_in_signal) ),*], )*
29 _ => unreachable!(),
30 }
31 }
32
33 pub(crate) fn output_signals(lp: u8) -> &'static [(LpFunction, LpOutputSignal)] {
34 match lp {
35 $( $lp_pin => &[$( (LpFunction::$lp_out_af, LpOutputSignal::$lp_out_signal) ),*], )*
36 _ => unreachable!(),
37 }
38 }
39 };
40}
41
42pub(crate) fn set_config(lp: u8, input_enable: bool, mux: bool, func: LpFunction) {
43 if mux {
44 LP_GPIO::regs()
45 .clk_en()
46 .modify(|_, w| w.reg_clk_en().set_bit());
47 while LP_GPIO::regs().clk_en().read().reg_clk_en().bit_is_clear() {}
48 }
49
50 LP_IO_MUX::regs().pad(lp as usize).modify(|_, w| unsafe {
51 w.mux_sel().bit(mux);
52 w.fun_ie().bit(input_enable);
53 w.fun_sel().bits(func as u8)
54 });
55}
56
57pub(crate) fn init_pin(lp: u8, input_enable: bool) -> u8 {
58 set_config(lp, input_enable, true, LpFunction::LP_GPIO);
59 lp
60}
61
62pub(crate) fn output_enable(lp: u8, enable: bool) {
63 if enable {
64 LP_GPIO::regs()
65 .enable_w1ts()
66 .write(|w| unsafe { w.bits(1 << lp) });
67 } else {
68 LP_GPIO::regs()
69 .enable_w1tc()
70 .write(|w| unsafe { w.bits(1 << lp) });
71 }
72}
73
74pub(crate) fn input_enable(lp: u8, enable: bool) {
75 LP_IO_MUX::regs()
76 .pad(lp as usize)
77 .modify(|_, w| w.slp_ie().bit(enable));
78}
79
80pub(crate) fn pullup_enable(lp: u8, enable: bool) {
81 LP_IO_MUX::regs()
82 .pad(lp as usize)
83 .modify(|_, w| w.rue().bit(enable));
84}
85
86pub(crate) fn pulldown_enable(lp: u8, enable: bool) {
87 LP_IO_MUX::regs()
88 .pad(lp as usize)
89 .modify(|_, w| w.rde().bit(enable));
90}
91
92pub(crate) fn pad_hold(lp: u8, enable: bool) {
93 let mask = 1 << lp;
94 LP_IO_MUX::regs().lp_pad_hold().modify(|r, w| unsafe {
95 let bits = r.reg_lp_gpio_hold().bits();
96 w.reg_lp_gpio_hold()
97 .bits(if enable { bits | mask } else { bits & !mask })
98 });
99}
100
101pub(crate) fn is_pad_held(lp: u8) -> bool {
103 LP_IO_MUX::regs()
104 .lp_pad_hold()
105 .read()
106 .reg_lp_gpio_hold()
107 .bits()
108 & (1 << lp)
109 != 0
110}
111
112pub(crate) fn digital_pad_hold(gpio: u8, enable: bool) {
116 let Some(bit) = gpio.checked_sub(16) else {
117 return;
118 };
119
120 if bit < 32 {
121 let mask = 1 << bit;
122 HP_SYS::regs().gpio_o_hold_ctrl0().modify(|r, w| unsafe {
123 let bits = r.reg_gpio_0_hold_low().bits();
124 w.reg_gpio_0_hold_low()
125 .bits(if enable { bits | mask } else { bits & !mask })
126 });
127 } else {
128 let mask = 1 << (bit - 32);
129 HP_SYS::regs().gpio_o_hold_ctrl1().modify(|r, w| unsafe {
130 let bits = r.reg_gpio_0_hold_high().bits();
131 w.reg_gpio_0_hold_high()
132 .bits(if enable { bits | mask } else { bits & !mask })
133 });
134 }
135}
136
137pub(crate) fn is_digital_pad_held(gpio: u8) -> bool {
139 let Some(bit) = gpio.checked_sub(16) else {
140 return false;
141 };
142
143 if bit < 32 {
144 HP_SYS::regs()
145 .gpio_o_hold_ctrl0()
146 .read()
147 .reg_gpio_0_hold_low()
148 .bits()
149 & (1 << bit)
150 != 0
151 } else {
152 HP_SYS::regs()
153 .gpio_o_hold_ctrl1()
154 .read()
155 .reg_gpio_0_hold_high()
156 .bits()
157 & (1 << (bit - 32))
158 != 0
159 }
160}
161
162pub(crate) fn set_open_drain_output(gpio: u8, enable: bool) {
165 crate::peripherals::GPIO::regs()
166 .pin(gpio as usize)
167 .modify(|_, w| w.pad_driver().bit(enable));
168}
169
170#[cfg(lp_i2c_master_driver_supported)]
171pub(crate) fn reset_pin(lp: u8) {
172 LP_GPIO::regs()
173 .clk_en()
174 .modify(|_, w| w.reg_clk_en().set_bit());
175 while LP_GPIO::regs().clk_en().read().reg_clk_en().bit_is_clear() {}
176
177 output_enable(lp, false);
178 set_open_drain_output(lp, false);
180
181 LP_IO_MUX::regs().pad(lp as usize).reset();
184}