Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
CTCaer
GitHub Repository: CTCaer/hekate
Path: blob/master/bdk/power/bm92t36.c
3694 views
1
/*
2
* USB-PD driver for Nintendo Switch's TI BM92T36
3
*
4
* Copyright (c) 2020-2026 CTCaer
5
*
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms and conditions of the GNU General Public License,
8
* version 2, as published by the Free Software Foundation.
9
*
10
* This program is distributed in the hope it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
* more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <string.h>
20
21
#include "bm92t36.h"
22
#include <soc/i2c.h>
23
#include <utils/util.h>
24
25
#define ALERT_STATUS_REG 0x2
26
#define STATUS1_REG 0x3
27
#define STATUS2_REG 0x4
28
#define COMMAND_REG 0x5
29
#define CONFIG1_REG 0x6
30
#define DEV_CAPS_REG 0x7
31
#define READ_PDOS_SRC_REG 0x8
32
#define CONFIG2_REG 0x17
33
#define DP_STATUS_REG 0x18
34
#define DP_ALERT_EN_REG 0x19
35
#define VENDOR_CONFIG_REG 0x1A
36
#define AUTO_NGT_FIXED_REG 0x20
37
#define AUTO_NGT_BATT_REG 0x23
38
#define SYS_CONFIG1_REG 0x26
39
#define SYS_CONFIG2_REG 0x27
40
#define CURRENT_PDO_REG 0x28
41
#define CURRENT_RDO_REG 0x2B
42
#define ALERT_ENABLE_REG 0x2E
43
#define SYS_CONFIG3_REG 0x2F
44
#define SET_RDO_REG 0x30
45
#define PDOS_SNK_REG 0x33
46
#define PDOS_SRC_PROV_REG 0x3C
47
#define FW_TYPE_REG 0x4B
48
#define FW_REVISION_REG 0x4C
49
#define MAN_ID_REG 0x4D
50
#define DEV_ID_REG 0x4E
51
#define REV_ID_REG 0x4F
52
#define INCOMING_VDM_REG 0x50
53
#define OUTGOING_VDM_REG 0x60
54
55
#define STATUS1_INSERT BIT(7) // Cable inserted.
56
57
#define VER_36 0x36
58
#define MAN_ROHM 0x4B5
59
#define DEV_BM92T 0x3B0
60
61
#define PDO_TYPE_FIXED 0
62
#define PDO_TYPE_BATT 1
63
#define PDO_TYPE_VAR 2
64
#define PDO_TYPE_APDO 3
65
66
typedef struct _pd_object_t {
67
unsigned int amp:10;
68
unsigned int volt:10;
69
unsigned int info:10;
70
unsigned int type:2;
71
} __attribute__((packed)) pd_object_t;
72
73
static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
74
{
75
memset(buf, 0, size);
76
return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
77
}
78
79
int bm92t36_get_version(u32 *value)
80
{
81
u8 buf[2];
82
u16 version, man, dev;
83
_bm92t36_read_reg(buf, 2, FW_TYPE_REG);
84
version = (buf[0] << 4) | buf[1];
85
_bm92t36_read_reg(buf, 2, MAN_ID_REG);
86
man = (buf[1] << 8) | buf[0];
87
_bm92t36_read_reg(buf, 2, DEV_ID_REG);
88
dev = (buf[1] << 8) | buf[0];
89
if (value)
90
*value = (dev << 16) | version;
91
92
if (version == VER_36 && man == MAN_ROHM && dev == DEV_BM92T)
93
return 0;
94
else
95
return 1;
96
}
97
98
void bm92t36_get_source_info(bool *inserted, usb_pd_objects_t *usb_pd)
99
{
100
u8 buf[32];
101
pd_object_t pdos[7];
102
103
if (inserted)
104
{
105
_bm92t36_read_reg(buf, 2, STATUS1_REG);
106
*inserted = (buf[0] & STATUS1_INSERT) ? true : false;
107
}
108
109
if (usb_pd)
110
{
111
_bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
112
memcpy(pdos, &buf[1], 28);
113
114
memset(usb_pd, 0, sizeof(usb_pd_objects_t));
115
usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
116
117
if (usb_pd->pdo_no > 7)
118
usb_pd->pdo_no = 7;
119
120
u32 idx = 0;
121
for (u32 i = 0; i < usb_pd->pdo_no; i++)
122
{
123
// Parse fixed type pdos only.
124
if (pdos[i].type != PDO_TYPE_FIXED)
125
continue;
126
127
usb_pd->pdos[idx].amperage = pdos[i].amp * 10;
128
usb_pd->pdos[idx].voltage = (pdos[i].volt * 50) / 1000;
129
idx++;
130
}
131
usb_pd->pdo_no = idx;
132
133
_bm92t36_read_reg(buf, 5, CURRENT_PDO_REG);
134
memcpy(pdos, &buf[1], 4);
135
usb_pd->selected_pdo.amperage = pdos[0].amp * 10;
136
usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000;
137
}
138
}
139
140