-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathpmic.hh
138 lines (114 loc) · 2.8 KB
/
pmic.hh
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#pragma once
#include "delay.h"
#include "drivers/i2c.hh"
#include "drivers/i2c_conf.hh"
#include "print_messages.hh"
// TODO: use Board Conf to set the voltage values
// It just so happens that the OSD32-BRK and STM Disco boards use the same values
class STPMIC1 {
public:
STPMIC1(const I2C_Config &conf)
: i2c{PMIC_I2C_Address, conf}
{
verify_chip_id();
}
bool setup_vddcore_pwr()
{
BUCKx_CR vddcore{.bits = {
.enable = 1,
.low_power = 0,
.vout = BUCKx_1200mV,
}};
return i2c.write_register_byte(RegisterMain::BUCK1_CR, vddcore.val);
}
bool setup_ddr3_pwr()
{
LDOx_CR vtt{.bits = {
.enable = 1,
.vout = LDO3_VOUT2DIV2,
.bypass = 0,
}};
BUCKx_CR vddr{.bits = {
.enable = 1,
.low_power = 0,
.vout = BUCK2_1350mV,
}};
REFDDRx_CR ref{.bits = {
.enable = 1,
}};
if (!i2c.write_register_byte(RegisterMain::LDO3_CR, vtt.val))
return false;
if (!i2c.write_register_byte(RegisterMain::BUCK2_CR, vddr.val))
return false;
udelay(1000);
if (!i2c.write_register_byte(RegisterMain::REFDDR_CR, ref.val))
return false;
udelay(1000);
debug("Wrote PMIC reg ", RegisterMain::LDO3_CR, " (LDO3_CR) = 0x", Hex{vtt.val}, "\n");
debug("Wrote PMIC reg ", RegisterMain::BUCK2_CR, " (BUCK2_CR) = 0x", Hex{vddr.val}, "\n");
debug("Wrote PMIC reg ", RegisterMain::REFDDR_CR, " (REFDDR_CR) = 0x", Hex{ref.val}, "\n");
return true;
}
bool verify_chip_id()
{
auto id = i2c.read_register_byte(RegisterMain::ID);
if (!id) {
pr_err("Failed to read from PMIC\n");
return false;
}
log("Read ID from PMIC: ", Hex{id.value()}, "\n");
return true;
}
void print_reg(uint8_t reg)
{
auto val = i2c.read_register_byte(reg);
if (val.has_value())
log("Read reg 0x", Hex{reg}, " = 0x", Hex{val.value()}, "\n");
else
log("Failed to read register ", Hex{reg}, "\n");
}
private:
I2C_Controller i2c;
constexpr static uint32_t PMIC_I2C_Address = 0x33;
enum RegisterMain : uint8_t {
ID = 0x06,
BUCK1_CR = 0x20,
BUCK2_CR = 0x21,
BUCK3_CR = 0x22,
BUCK4_CR = 0x23,
REFDDR_CR = 0x24,
LDO1_CR = 0x25,
LDO2_CR = 0x26,
LDO3_CR = 0x27,
LDO4_CR = 0x28,
};
enum RegisterAlt : uint8_t {
};
union BUCKx_CR {
struct {
uint8_t enable : 1;
uint8_t low_power : 1;
uint8_t vout : 6;
} bits;
uint8_t val;
};
union LDOx_CR {
struct {
uint8_t enable : 1;
uint8_t _resv : 1;
uint8_t vout : 5;
uint8_t bypass : 1;
} bits;
uint8_t val;
};
union REFDDRx_CR {
struct {
uint8_t enable : 1;
uint8_t _resv : 7;
} bits;
uint8_t val;
};
constexpr static uint8_t LDO3_VOUT2DIV2 = 31; // See datasheet, Table 9
constexpr static uint8_t BUCK2_1350mV = 30; // See datasheet, Table 10
constexpr static uint8_t BUCKx_1200mV = 24; // See datasheet, Table 10
};