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