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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
/* SPDX-License-Identifier: MIT */
#include "tps6598x.h"
#include "adt.h"
#include "i2c.h"
#include "iodev.h"
#include "malloc.h"
#include "types.h"
#include "utils.h"
#define TPS_REG_CMD1 0x08
#define TPS_REG_DATA1 0x09
#define TPS_REG_INT_EVENT1 0x14
#define TPS_REG_INT_MASK1 0x16
#define TPS_REG_INT_CLEAR1 0x18
#define TPS_REG_POWER_STATE 0x20
#define TPS_CMD_INVALID 0x21434d44 // !CMD
struct tps6598x_dev {
i2c_dev_t *i2c;
u8 addr;
};
tps6598x_dev_t *tps6598x_init(const char *adt_node, i2c_dev_t *i2c)
{
int adt_offset;
adt_offset = adt_path_offset(adt, adt_node);
if (adt_offset < 0) {
printf("tps6598x: Error getting %s node\n", adt_node);
return NULL;
}
const u8 *iic_addr = adt_getprop(adt, adt_offset, "hpm-iic-addr", NULL);
if (iic_addr == NULL) {
printf("tps6598x: Error getting %s hpm-iic-addr\n.", adt_node);
return NULL;
}
tps6598x_dev_t *dev = malloc(sizeof(*dev));
if (!dev)
return NULL;
dev->i2c = i2c;
dev->addr = *iic_addr;
return dev;
}
void tps6598x_shutdown(tps6598x_dev_t *dev)
{
free(dev);
}
int tps6598x_command(tps6598x_dev_t *dev, const char *cmd, const u8 *data_in, size_t len_in,
u8 *data_out, size_t len_out)
{
if (len_in) {
if (i2c_smbus_write(dev->i2c, dev->addr, TPS_REG_DATA1, data_in, len_in) < 0)
return -1;
}
if (i2c_smbus_write(dev->i2c, dev->addr, TPS_REG_CMD1, (const u8 *)cmd, 4) < 0)
return -1;
u32 cmd_status;
do {
if (i2c_smbus_read32(dev->i2c, dev->addr, TPS_REG_CMD1, &cmd_status))
return -1;
if (cmd_status == TPS_CMD_INVALID)
return -1;
udelay(100);
} while (cmd_status != 0);
if (len_out) {
if (i2c_smbus_read(dev->i2c, dev->addr, TPS_REG_DATA1, data_out, len_out) !=
(ssize_t)len_out)
return -1;
}
return 0;
}
int tps6598x_disable_irqs(tps6598x_dev_t *dev, tps6598x_irq_state_t *state)
{
size_t read;
int written;
static const u8 zeros[CD3218B12_IRQ_WIDTH] = {0x00};
static const u8 ones[CD3218B12_IRQ_WIDTH] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF};
// store IntEvent 1 to restore it later
read = i2c_smbus_read(dev->i2c, dev->addr, TPS_REG_INT_MASK1, state->int_mask1,
sizeof(state->int_mask1));
if (read != CD3218B12_IRQ_WIDTH) {
printf("tps6598x: reading TPS_REG_INT_MASK1 failed\n");
return -1;
}
state->valid = 1;
// mask interrupts and ack all interrupt flags
written = i2c_smbus_write(dev->i2c, dev->addr, TPS_REG_INT_CLEAR1, ones, sizeof(ones));
if (written != sizeof(zeros)) {
printf("tps6598x: writing TPS_REG_INT_CLEAR1 failed, written: %d\n", written);
return -1;
}
written = i2c_smbus_write(dev->i2c, dev->addr, TPS_REG_INT_MASK1, zeros, sizeof(zeros));
if (written != sizeof(ones)) {
printf("tps6598x: writing TPS_REG_INT_MASK1 failed, written: %d\n", written);
return -1;
}
#ifdef DEBUG
u8 tmp[CD3218B12_IRQ_WIDTH] = {0x00};
read = i2c_smbus_read(dev->i2c, dev->addr, TPS_REG_INT_MASK1, tmp, CD3218B12_IRQ_WIDTH);
if (read != CD3218B12_IRQ_WIDTH)
printf("tps6598x: failed verifcation, can't read TPS_REG_INT_MASK1\n");
else {
printf("tps6598x: verify: TPS_REG_INT_MASK1 vs. saved IntMask1\n");
hexdump(tmp, sizeof(tmp));
hexdump(state->int_mask1, sizeof(state->int_mask1));
}
#endif
return 0;
}
int tps6598x_restore_irqs(tps6598x_dev_t *dev, tps6598x_irq_state_t *state)
{
int written;
written = i2c_smbus_write(dev->i2c, dev->addr, TPS_REG_INT_MASK1, state->int_mask1,
sizeof(state->int_mask1));
if (written != sizeof(state->int_mask1)) {
printf("tps6598x: restoring TPS_REG_INT_MASK1 failed\n");
return -1;
}
#ifdef DEBUG
int read;
u8 tmp[CD3218B12_IRQ_WIDTH];
read = i2c_smbus_read(dev->i2c, dev->addr, TPS_REG_INT_MASK1, tmp, sizeof(tmp));
if (read != sizeof(tmp))
printf("tps6598x: failed verifcation, can't read TPS_REG_INT_MASK1\n");
else {
printf("tps6598x: verify saved IntMask1 vs. TPS_REG_INT_MASK1:\n");
hexdump(state->int_mask1, sizeof(state->int_mask1));
hexdump(tmp, sizeof(tmp));
}
#endif
return 0;
}
int tps6598x_powerup(tps6598x_dev_t *dev)
{
u8 power_state;
if (i2c_smbus_read8(dev->i2c, dev->addr, TPS_REG_POWER_STATE, &power_state))
return -1;
if (power_state == 0)
return 0;
const u8 data = 0;
tps6598x_command(dev, "SSPS", &data, 1, NULL, 0);
if (i2c_smbus_read8(dev->i2c, dev->addr, TPS_REG_POWER_STATE, &power_state))
return -1;
if (power_state != 0)
return -1;
return 0;
}
|