xref: /aosp_15_r20/external/pigweed/pw_digital_io_mcuxpresso/digital_io.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_digital_io/digital_io.h"
16 
17 #include <array>
18 
19 #include "fsl_clock.h"
20 #include "fsl_gpio.h"
21 #include "fsl_reset.h"
22 #include "pw_assert/check.h"
23 #include "pw_digital_io_mcuxpresso/digital_io.h"
24 #include "pw_status/status.h"
25 
26 namespace pw::digital_io {
27 namespace {
28 
29 constexpr std::array kGpioClocks = GPIO_CLOCKS;
30 constexpr std::array kGpioResets = GPIO_RSTS_N;
31 
32 }  // namespace
33 
McuxpressoDigitalOut(GPIO_Type * base,uint32_t port,uint32_t pin,pw::digital_io::State initial_state)34 McuxpressoDigitalOut::McuxpressoDigitalOut(GPIO_Type* base,
35                                            uint32_t port,
36                                            uint32_t pin,
37                                            pw::digital_io::State initial_state)
38     : base_(base), port_(port), pin_(pin), initial_state_(initial_state) {
39   PW_CHECK(base != nullptr);
40   PW_CHECK(port < kGpioClocks.size());
41   PW_CHECK(port < kGpioResets.size());
42 }
43 
DoEnable(bool enable)44 pw::Status McuxpressoDigitalOut::DoEnable(bool enable) {
45   if (enable) {
46     if (is_enabled()) {
47       return pw::OkStatus();
48     }
49 
50     CLOCK_EnableClock(kGpioClocks[port_]);
51     RESET_ClearPeripheralReset(kGpioResets[port_]);
52 
53     gpio_pin_config_t config = {
54         .pinDirection = kGPIO_DigitalOutput,
55         .outputLogic = static_cast<uint8_t>(
56             initial_state_ == pw::digital_io::State::kActive ? 1U : 0U),
57     };
58     GPIO_PinInit(base_, port_, pin_, &config);
59 
60   } else {
61     // Set to input on disable.
62     gpio_pin_config_t config = {
63         .pinDirection = kGPIO_DigitalInput,
64         .outputLogic = 0,
65     };
66 
67     // Must enable the clock, since GPIO can get disabled without ever
68     // being enabled.
69     CLOCK_EnableClock(kGpioClocks[port_]);
70     GPIO_PinInit(base_, port_, pin_, &config);
71 
72     // Can't disable clock as other users on same port may be active.
73   }
74   enabled_ = enable;
75   return pw::OkStatus();
76 }
77 
DoSetState(pw::digital_io::State state)78 pw::Status McuxpressoDigitalOut::DoSetState(pw::digital_io::State state) {
79   if (!is_enabled()) {
80     return pw::Status::FailedPrecondition();
81   }
82   GPIO_PinWrite(
83       base_, port_, pin_, state == pw::digital_io::State::kActive ? 1 : 0);
84   return pw::OkStatus();
85 }
86 
McuxpressoDigitalIn(GPIO_Type * base,uint32_t port,uint32_t pin)87 McuxpressoDigitalIn::McuxpressoDigitalIn(GPIO_Type* base,
88                                          uint32_t port,
89                                          uint32_t pin)
90     : base_(base), port_(port), pin_(pin) {
91   PW_CHECK(base != nullptr);
92   PW_CHECK(port < kGpioClocks.size());
93   PW_CHECK(port < kGpioResets.size());
94 }
95 
DoEnable(bool enable)96 pw::Status McuxpressoDigitalIn::DoEnable(bool enable) {
97   if (!enable) {
98     enabled_ = enable;
99     // Can't disable clock as other users on same port may be active.
100     return pw::OkStatus();
101   }
102 
103   if (is_enabled()) {
104     return pw::Status::FailedPrecondition();
105   }
106 
107   CLOCK_EnableClock(kGpioClocks[port_]);
108   RESET_ClearPeripheralReset(kGpioResets[port_]);
109 
110   gpio_pin_config_t config = {
111       .pinDirection = kGPIO_DigitalInput,
112       .outputLogic = 0,
113   };
114   GPIO_PinInit(base_, port_, pin_, &config);
115 
116   enabled_ = enable;
117   return pw::OkStatus();
118 }
119 
DoGetState()120 pw::Result<pw::digital_io::State> McuxpressoDigitalIn::DoGetState() {
121   if (!is_enabled()) {
122     return pw::Status::FailedPrecondition();
123   }
124   uint32_t value = GPIO_PinRead(base_, port_, pin_);
125   return value == 1 ? pw::digital_io::State::kActive
126                     : pw::digital_io::State::kInactive;
127 }
128 
129 }  // namespace pw::digital_io
130