1 /* USRP E310 TP54478 driver
2 * Copyright (C) 2014 Ettus Research
3 * This file is part of the USRP E310 Firmware
4 * The USRP E310 Firmware is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 * The USRP E310 Firmware is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with the USRP E310 Firmware. If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 #include "mcu_settings.h"
17 #include "io.h"
18 #include "tps54478.h"
19
20 #include <stdlib.h>
21
22 #include <util/delay.h>
23 #include <util/atomic.h>
24
25 static io_pin_t CORE_PWR_EN = IO_PA(3);
26 static io_pin_t CORE_PGOOD = IO_PB(0);
27
28 /* per spec we should wait 3 ms here,
29 * but 10 is better to give external PSU some time
30 * to settle down*/
31 static const uint8_t TPS54478_START_DELAY = 10;
32
33 /* we'll use this to check for events in the event handler */
34 static volatile bool tps54478_event = false;
35
tps54478_get_power_good(void)36 bool tps54478_get_power_good(void)
37 {
38 return io_test_pin(CORE_PGOOD);
39 }
40
tps54478_set_regulator(pmu_regulator_t * pmu_reg,bool on)41 static int8_t tps54478_set_regulator(pmu_regulator_t *pmu_reg, bool on)
42 {
43 (void) pmu_reg;
44
45 if (on) {
46 io_input_pin(CORE_PWR_EN);
47 _delay_ms(TPS54478_START_DELAY);
48 } else {
49 io_output_pin(CORE_PWR_EN);
50 /* no delay here as we can't detect this state anyway */
51 return 0;
52 }
53 /* return zero on success ... */
54 return !(on == tps54478_get_power_good());
55 }
56
tps54478_init(bool enable)57 void tps54478_init(bool enable)
58 {
59 /* enable pull-up for open drain */
60 io_input_pin(CORE_PGOOD);
61 io_set_pin(CORE_PGOOD);
62
63 tps54478_set_regulator(NULL, enable);
64
65 io_clear_pin(CORE_PWR_EN);
66 }
67
tps54478_check_events(pmu_regulator_t * reg)68 int8_t tps54478_check_events(pmu_regulator_t *reg)
69 {
70 bool power_good;
71 bool event;
72
73 event = false;
74 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
75 if (tps54478_event) {
76 tps54478_event = false;
77 event = true;
78 }
79 }
80
81 if (event) {
82 power_good = tps54478_get_power_good();
83 if (!power_good)
84 return -1;
85 }
86 return 0;
87 }
88
89 const pmu_regulator_ops_t tps54478_ops = {
90 .set_voltage = NULL,
91 .set_regulator = tps54478_set_regulator,
92 .check_events = tps54478_check_events,
93 };
94
tps54478_irq_handler(void)95 irqreturn_t tps54478_irq_handler(void)
96 {
97 bool power_good;
98 power_good = tps54478_get_power_good();
99
100 /* check if the device indicates power is good,
101 * if it is probably we're not the source of the IRQ,
102 * if it is *not* set the event flag to deal with it later */
103 if (power_good) {
104 return IRQ_NONE;
105 } else {
106 tps54478_event = true;
107 return IRQ_HANDLED;
108 }
109 return IRQ_HANDLED;
110 }
111