imix/
power.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Implements a helper function for enabling/disabling power on the imix
6//! submodules.
7//  On imix, submodules are powered on/off via power gate ICs. The MCU has an
8//  enable pin connected to each power gate. Setting an enable pin high or low
9//  turns on or off the corresponding submodule.
10//
11//  For the RF233, NRF, and sensors, there is an additional IC which electrically
12//  connects/disconnects the I2C and SPI busses to the appropriate submodules,
13//  depending on their power state. This is because the busses can inadvertently
14//  supply power to the connected submodules. The correct behavior is all handled
15//  in hardware via the enable pins.
16//
17//  For the RF233 and NRF, there are still some remaining GPIO pins that need to
18//  be configured when these submodules are turned off. These pins are not gated
19//  by a switch like the I2C and SPI busses are, so if the kernel does not
20//  explicitly pull them to ground, the submodule will be powered through the GPIO.
21//
22//  This file exports `configure_submodules`, which hides the complexity
23//  of correctly turning the submodules on and off. It allows the caller to
24//  conveniently disable and enable the individual submodules at will.
25
26use kernel::hil::Controller;
27use sam4l::gpio::GPIOPin;
28use sam4l::gpio::PeripheralFunction::{A, B, E};
29use sam4l::gpio::{PeripheralFunction, Port};
30
31struct DetachablePin {
32    pin: &'static GPIOPin<'static>,
33    function: Option<PeripheralFunction>,
34}
35
36impl DetachablePin {
37    fn detach(&self) {
38        self.pin.configure(None);
39        self.pin.enable_output();
40        self.pin.clear();
41    }
42
43    fn restore(&self) {
44        self.pin.configure(self.function);
45    }
46}
47
48struct Submodule<'a> {
49    gate_pin: &'static GPIOPin<'static>,
50    detachable_pins: &'a [DetachablePin],
51}
52
53impl Submodule<'_> {
54    fn power(&self, state: bool) {
55        self.gate_pin.enable_output();
56        match state {
57            true => {
58                for d in self.detachable_pins.iter() {
59                    d.restore();
60                }
61                self.gate_pin.set();
62            }
63            false => {
64                self.gate_pin.clear();
65                for d in self.detachable_pins.iter() {
66                    d.detach();
67                }
68            }
69        }
70    }
71}
72
73pub struct SubmoduleConfig {
74    pub rf233: bool,
75    pub nrf51422: bool,
76    pub sensors: bool,
77    pub trng: bool,
78}
79
80pub unsafe fn configure_submodules(
81    pa: &'static Port,
82    pb: &'static Port,
83    pc: &'static Port,
84    enabled_submodules: SubmoduleConfig,
85) {
86    let rf233_detachable_pins = [
87        DetachablePin {
88            pin: &pa[08],
89            function: None,
90        },
91        DetachablePin {
92            pin: &pa[09],
93            function: None,
94        },
95        DetachablePin {
96            pin: &pa[10],
97            function: None,
98        },
99    ];
100    let rf233 = Submodule {
101        gate_pin: &pc[18],
102        detachable_pins: &rf233_detachable_pins,
103    };
104
105    let nrf_detachable_pins = [
106        DetachablePin {
107            pin: &pb[07],
108            function: None,
109        },
110        DetachablePin {
111            pin: &pa[17],
112            function: None,
113        },
114        DetachablePin {
115            pin: &pa[18],
116            function: Some(A),
117        },
118        DetachablePin {
119            pin: &pc[07],
120            function: Some(B),
121        },
122        DetachablePin {
123            pin: &pc[08],
124            function: Some(E),
125        },
126        DetachablePin {
127            pin: &pc[09],
128            function: None,
129        },
130    ];
131    let nrf = Submodule {
132        gate_pin: &pc[17],
133        detachable_pins: &nrf_detachable_pins,
134    };
135
136    let sensors = Submodule {
137        gate_pin: &pc[16],
138        detachable_pins: &[],
139    };
140
141    let trng = Submodule {
142        gate_pin: &pc[19],
143        detachable_pins: &[],
144    };
145
146    rf233.power(enabled_submodules.rf233);
147    nrf.power(enabled_submodules.nrf51422);
148    sensors.power(enabled_submodules.sensors);
149    trng.power(enabled_submodules.trng);
150}