mirror of
https://github.com/CTCaer/hekate
synced 2024-11-05 11:26:35 +00:00
ee3fc499cd
If bm92t i2c comms are broken, it can hang hekate. So sanitize buffer and max profile print supported.
104 lines
2.9 KiB
C
104 lines
2.9 KiB
C
/*
|
|
* USB-PD driver for Nintendo Switch's TI BM92T36
|
|
*
|
|
* Copyright (c) 2020 CTCaer
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <string.h>
|
|
|
|
#include "bm92t36.h"
|
|
#include <soc/i2c.h>
|
|
#include <utils/util.h>
|
|
|
|
#define ALERT_STATUS_REG 0x2
|
|
#define STATUS1_REG 0x3
|
|
#define STATUS2_REG 0x4
|
|
#define COMMAND_REG 0x5
|
|
#define CONFIG1_REG 0x6
|
|
#define DEV_CAPS_REG 0x7
|
|
#define READ_PDOS_SRC_REG 0x8
|
|
#define CONFIG2_REG 0x17
|
|
#define DP_STATUS_REG 0x18
|
|
#define DP_ALERT_EN_REG 0x19
|
|
#define VENDOR_CONFIG_REG 0x1A
|
|
#define AUTO_NGT_FIXED_REG 0x20
|
|
#define AUTO_NGT_BATT_REG 0x23
|
|
#define SYS_CONFIG1_REG 0x26
|
|
#define SYS_CONFIG2_REG 0x27
|
|
#define CURRENT_PDO_REG 0x28
|
|
#define CURRENT_RDO_REG 0x2B
|
|
#define ALERT_ENABLE_REG 0x2E
|
|
#define SYS_CONFIG3_REG 0x2F
|
|
#define SET_RDO_REG 0x30
|
|
#define PDOS_SNK_REG 0x33
|
|
#define PDOS_SRC_PROV_REG 0x3C
|
|
#define FW_TYPE_REG 0x4B
|
|
#define FW_REVISION_REG 0x4C
|
|
#define MAN_ID_REG 0x4D
|
|
#define DEV_ID_REG 0x4E
|
|
#define REV_ID_REG 0x4F
|
|
#define INCOMING_VDM_REG 0x50
|
|
#define OUTGOING_VDM_REG 0x60
|
|
|
|
#define STATUS1_INSERT BIT(7) // Cable inserted.
|
|
|
|
typedef struct _pd_object_t {
|
|
unsigned int amp:10;
|
|
unsigned int volt:10;
|
|
unsigned int info:10;
|
|
unsigned int type:2;
|
|
} __attribute__((packed)) pd_object_t;
|
|
|
|
static int _bm92t36_read_reg(u8 *buf, u32 size, u32 reg)
|
|
{
|
|
return i2c_recv_buf_big(buf, size, I2C_1, BM92T36_I2C_ADDR, reg);
|
|
}
|
|
|
|
void bm92t36_get_sink_info(bool *inserted, usb_pd_objects_t *usb_pd)
|
|
{
|
|
u8 buf[32];
|
|
pd_object_t pdos[7];
|
|
|
|
if (inserted)
|
|
{
|
|
memset(buf, 0, sizeof(buf));
|
|
_bm92t36_read_reg(buf, 2, STATUS1_REG);
|
|
*inserted = buf[0] & STATUS1_INSERT ? true : false;
|
|
}
|
|
|
|
if (usb_pd)
|
|
{
|
|
memset(buf, 0, sizeof(buf));
|
|
_bm92t36_read_reg(buf, 29, READ_PDOS_SRC_REG);
|
|
memcpy(pdos, &buf[1], 28);
|
|
|
|
memset(usb_pd, 0, sizeof(usb_pd_objects_t));
|
|
usb_pd->pdo_no = buf[0] / sizeof(pd_object_t);
|
|
|
|
if (usb_pd->pdo_no > 7)
|
|
usb_pd->pdo_no = 7;
|
|
|
|
for (u32 i = 0; i < usb_pd->pdo_no; i++)
|
|
{
|
|
usb_pd->pdos[i].amperage = pdos[i].amp * 10;
|
|
usb_pd->pdos[i].voltage = (pdos[i].volt * 50) / 1000;
|
|
}
|
|
|
|
_bm92t36_read_reg(buf, 5, CURRENT_PDO_REG);
|
|
memcpy(pdos, &buf[1], 4);
|
|
usb_pd->selected_pdo.amperage = pdos[0].amp * 10;
|
|
usb_pd->selected_pdo.voltage = (pdos[0].volt * 50) / 1000;
|
|
}
|
|
}
|