/* * USB-PD driver for Nintendo Switch's TI BM92T36 * * Copyright (c) 2020-2023 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 . */ #include #include "bm92t36.h" #include #include #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; } }