mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-11 17:08:15 +00:00
feat(core): introduce stwlc38 driver
[no changelog]
This commit is contained in:
parent
e46c2eace2
commit
3b4e451dad
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#define NPM1300_I2C_INSTANCE 0
|
#define NPM1300_I2C_INSTANCE 0
|
||||||
|
|
||||||
|
#define STWLC38_I2C_INSTANCE 1
|
||||||
|
|
||||||
#define I2C_COUNT 4
|
#define I2C_COUNT 4
|
||||||
|
|
||||||
#define I2C_INSTANCE_0 I2C1
|
#define I2C_INSTANCE_0 I2C1
|
||||||
|
430
core/embed/sys/powerctl/stwlc38/stwlc38.c
Normal file
430
core/embed/sys/powerctl/stwlc38/stwlc38.c
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that 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 <trezor_bsp.h>
|
||||||
|
#include <trezor_rtl.h>
|
||||||
|
|
||||||
|
#include <io/i2c_bus.h>
|
||||||
|
#include <sys/irq.h>
|
||||||
|
#include <sys/systimer.h>
|
||||||
|
|
||||||
|
#include "stwlc38.h"
|
||||||
|
#include "stwlc38_defs.h"
|
||||||
|
|
||||||
|
#ifdef KERNEL_MODE
|
||||||
|
|
||||||
|
// !@# TODO: put following constants the board file
|
||||||
|
#define STWLC38_INT_PIN GPIO_PIN_15
|
||||||
|
#define STWLC38_INT_PORT GPIOG
|
||||||
|
#define STWLC38_INT_PIN_CLK_ENA __HAL_RCC_GPIOG_CLK_ENABLE
|
||||||
|
#define STWLC38_EXTI_INTERRUPT_GPIOSEL EXTI_GPIOG
|
||||||
|
#define STWLC38_EXTI_INTERRUPT_LINE EXTI_LINE_15
|
||||||
|
#define STWLC38_EXTI_INTERRUPT_NUM EXTI15_IRQn
|
||||||
|
#define STWLC38_EXTI_INTERRUPT_HANDLER EXTI15_IRQHandler
|
||||||
|
#define STWLC38_ENB_PIN GPIO_PIN_3
|
||||||
|
#define STWLC37_ENB_PORT GPIOD
|
||||||
|
#define STWLC38_ENB_PIN_CLK_ENA __HAL_RCC_GPIOD_CLK_ENABLE
|
||||||
|
|
||||||
|
// Period of the report readout [ms]
|
||||||
|
#define STWLC38_REPORT_READOUT_INTERVAL_MS 500
|
||||||
|
|
||||||
|
// STWLC38 FSM states
|
||||||
|
typedef enum {
|
||||||
|
STWLC38_STATE_POWER_DOWN = 0,
|
||||||
|
STWLC38_STATE_IDLE,
|
||||||
|
STWLC38_STATE_VOUT_ENABLE,
|
||||||
|
STWLC38_STATE_VOUT_DISABLE,
|
||||||
|
STWLC38_STATE_REPORT_READOUT,
|
||||||
|
} stwlc38_fsm_state_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Rectified voltage [mV]
|
||||||
|
uint16_t vrect;
|
||||||
|
// Main LDO voltage output [mV]
|
||||||
|
uint16_t vout;
|
||||||
|
// Output current [mA]
|
||||||
|
uint16_t icur;
|
||||||
|
// Chip temperature [°C * 10]
|
||||||
|
uint16_t tmeas;
|
||||||
|
// Operating frequency [kHz]
|
||||||
|
uint16_t opfreq;
|
||||||
|
// NTC Temperature [°C * 10]
|
||||||
|
uint16_t ntc;
|
||||||
|
// RX Int Status 0
|
||||||
|
uint8_t status0;
|
||||||
|
|
||||||
|
} stwlc38_report_regs_t;
|
||||||
|
|
||||||
|
// STWLC38 driver state
|
||||||
|
typedef struct {
|
||||||
|
// Set if the driver is initialized
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
|
// I2C bus where the STWLC38 is connected
|
||||||
|
i2c_bus_t* i2c_bus;
|
||||||
|
// Storage for the pending I2C packet
|
||||||
|
i2c_packet_t pending_i2c_packet;
|
||||||
|
// Report register (global buffer used for report readout)
|
||||||
|
stwlc38_report_regs_t report_regs;
|
||||||
|
// Timer used for periodic report readout
|
||||||
|
systimer_t* timer;
|
||||||
|
|
||||||
|
// Main LDO output current state
|
||||||
|
bool vout_enabled;
|
||||||
|
// Main LDO output requested state
|
||||||
|
bool vout_enabled_requested;
|
||||||
|
// Flags set if report readout is scheduled
|
||||||
|
bool report_readout_requested;
|
||||||
|
|
||||||
|
// Current report
|
||||||
|
stwlc38_report_t report;
|
||||||
|
// Current state of the FSM
|
||||||
|
stwlc38_fsm_state_t state;
|
||||||
|
|
||||||
|
} stwlc38_driver_t;
|
||||||
|
|
||||||
|
// STWLC38 driver instance
|
||||||
|
static stwlc38_driver_t g_stwlc38_driver = {
|
||||||
|
.initialized = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
// forward declarations
|
||||||
|
static void stwlc38_timer_callback(void* context);
|
||||||
|
static void stwlc38_i2c_callback(void* context, i2c_packet_t* packet);
|
||||||
|
static void stwlc38_fsm_continue(stwlc38_driver_t* drv);
|
||||||
|
|
||||||
|
void stwlc38_deinit(void) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
i2c_bus_close(drv->i2c_bus);
|
||||||
|
systimer_delete(drv->timer);
|
||||||
|
memset(drv, 0, sizeof(stwlc38_driver_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stwlc38_init(void) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
if (drv->initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(drv, 0, sizeof(stwlc38_driver_t));
|
||||||
|
|
||||||
|
drv->state = STWLC38_STATE_POWER_DOWN;
|
||||||
|
|
||||||
|
// Main LDO output is enabled by default
|
||||||
|
drv->vout_enabled = true;
|
||||||
|
drv->vout_enabled_requested = true;
|
||||||
|
|
||||||
|
drv->i2c_bus = i2c_bus_open(STWLC38_I2C_INSTANCE);
|
||||||
|
if (drv->i2c_bus == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->timer = systimer_create(stwlc38_timer_callback, drv);
|
||||||
|
if (drv->timer == NULL) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
STWLC38_INT_PIN_CLK_ENA();
|
||||||
|
STWLC38_ENB_PIN_CLK_ENA();
|
||||||
|
|
||||||
|
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
||||||
|
|
||||||
|
// INT pin, active low, external pull-up
|
||||||
|
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
|
||||||
|
GPIO_InitStructure.Pull = GPIO_PULLUP; // NOPULL;
|
||||||
|
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
|
GPIO_InitStructure.Pin = STWLC38_INT_PIN;
|
||||||
|
HAL_GPIO_Init(STWLC38_INT_PORT, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
// ENB pin, active low, external pull-down
|
||||||
|
GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
|
||||||
|
GPIO_InitStructure.Pull = GPIO_NOPULL;
|
||||||
|
GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
|
||||||
|
GPIO_InitStructure.Pin = STWLC38_ENB_PIN;
|
||||||
|
HAL_GPIO_WritePin(STWLC37_ENB_PORT, STWLC38_ENB_PIN, GPIO_PIN_RESET);
|
||||||
|
HAL_GPIO_Init(STWLC37_ENB_PORT, &GPIO_InitStructure);
|
||||||
|
|
||||||
|
// Setup interrupt line for the STWLC38
|
||||||
|
EXTI_HandleTypeDef EXTI_Handle = {0};
|
||||||
|
EXTI_ConfigTypeDef EXTI_Config = {0};
|
||||||
|
EXTI_Config.GPIOSel = STWLC38_EXTI_INTERRUPT_GPIOSEL;
|
||||||
|
EXTI_Config.Line = STWLC38_EXTI_INTERRUPT_LINE;
|
||||||
|
EXTI_Config.Mode = EXTI_MODE_INTERRUPT;
|
||||||
|
EXTI_Config.Trigger = EXTI_TRIGGER_FALLING;
|
||||||
|
HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config);
|
||||||
|
NVIC_SetPriority(STWLC38_EXTI_INTERRUPT_NUM, IRQ_PRI_NORMAL);
|
||||||
|
__HAL_GPIO_EXTI_CLEAR_FLAG(STWLC38_INT_PIN);
|
||||||
|
NVIC_EnableIRQ(STWLC38_EXTI_INTERRUPT_NUM);
|
||||||
|
|
||||||
|
drv->initialized = true;
|
||||||
|
|
||||||
|
// Try to readout stwlc38 report, it may be already powered up
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
drv->report_readout_requested = true;
|
||||||
|
stwlc38_fsm_continue(drv);
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
stwlc38_deinit();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stwlc38_enable(bool enable) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
HAL_GPIO_WritePin(STWLC37_ENB_PORT, STWLC38_ENB_PIN, GPIO_PIN_RESET);
|
||||||
|
} else {
|
||||||
|
HAL_GPIO_WritePin(STWLC37_ENB_PORT, STWLC38_ENB_PIN, GPIO_PIN_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stwlc38_enable_vout(bool enable) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
|
||||||
|
if (drv->vout_enabled_requested != enable) {
|
||||||
|
drv->vout_enabled_requested = enable;
|
||||||
|
stwlc38_fsm_continue(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C operation for writing 8-bit constant value to the STWLC38 register
|
||||||
|
#define STWLC_WRITE_CONST8(reg, value) \
|
||||||
|
{ \
|
||||||
|
.flags = I2C_FLAG_TX | I2C_FLAG_EMBED | I2C_FLAG_START, .size = 3, \
|
||||||
|
.data = {(reg) >> 8, (reg) & 0xFF, (value)}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C operations for reading 16-bit STWLC38 register into the
|
||||||
|
// specified field in `g_stwlc38_driver` structure
|
||||||
|
#define STWLC_READ_FIELD16(reg, field) \
|
||||||
|
{ \
|
||||||
|
.flags = I2C_FLAG_TX | I2C_FLAG_EMBED | I2C_FLAG_START, \
|
||||||
|
.size = 2, \
|
||||||
|
.data = {(reg) >> 8, (reg) & 0xFF}, \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.flags = I2C_FLAG_RX, .size = 2, .ptr = &g_stwlc38_driver.field, \
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C operations for reading 8-bit STWLC38 register into the
|
||||||
|
// specified field in `g_stwlc38_driver` structure
|
||||||
|
#define STWLC_READ_FIELD8(reg, field) \
|
||||||
|
{ \
|
||||||
|
.flags = I2C_FLAG_TX | I2C_FLAG_EMBED | I2C_FLAG_START, \
|
||||||
|
.size = 2, \
|
||||||
|
.data = {(reg) >> 8, (reg) & 0xFF}, \
|
||||||
|
}, \
|
||||||
|
{ \
|
||||||
|
.flags = I2C_FLAG_RX, .size = 1, .ptr = &g_stwlc38_driver.field, \
|
||||||
|
}
|
||||||
|
|
||||||
|
// I2C operations for readout of the current state into the
|
||||||
|
// `g_stwlc38.state` structure
|
||||||
|
static const i2c_op_t stwlc38_ops_report_readout[] = {
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_VRECT, report_regs.vrect),
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_VOUT, report_regs.vout),
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_ICUR, report_regs.icur),
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_TMEAS, report_regs.tmeas),
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_OPFREQ, report_regs.opfreq),
|
||||||
|
STWLC_READ_FIELD16(STWLC38_REG_NTC, report_regs.ntc),
|
||||||
|
STWLC_READ_FIELD8(STWLC38_REG_RXINT_STATUS0, report_regs.status0),
|
||||||
|
};
|
||||||
|
|
||||||
|
// I2C operations for enabling of the main LDO
|
||||||
|
static const i2c_op_t stwlc38_ops_vout_enable[] = {
|
||||||
|
STWLC_WRITE_CONST8(STWLC38_RX_COMMAND, 0x01), // RX VOUT ON
|
||||||
|
};
|
||||||
|
|
||||||
|
// I2C operations for disabling of the main LDO
|
||||||
|
static const i2c_op_t stwlc38_ops_vout_disable[] = {
|
||||||
|
STWLC_WRITE_CONST8(STWLC38_RX_COMMAND, 0x02), // RX VOUT OFF
|
||||||
|
};
|
||||||
|
|
||||||
|
#define stwlc38_i2c_submit(drv, ops) \
|
||||||
|
_stwlc38_i2c_submit(drv, ops, ARRAY_LENGTH(ops))
|
||||||
|
|
||||||
|
// helper function for submitting I2C operations
|
||||||
|
static void _stwlc38_i2c_submit(stwlc38_driver_t* drv, const i2c_op_t* ops,
|
||||||
|
size_t op_count) {
|
||||||
|
i2c_packet_t* pkt = &drv->pending_i2c_packet;
|
||||||
|
|
||||||
|
memset(pkt, 0, sizeof(i2c_packet_t));
|
||||||
|
pkt->address = STWLC38_I2C_ADDRESS;
|
||||||
|
pkt->context = drv;
|
||||||
|
pkt->callback = stwlc38_i2c_callback;
|
||||||
|
pkt->timeout = 0;
|
||||||
|
pkt->ops = (i2c_op_t*)ops;
|
||||||
|
pkt->op_count = op_count;
|
||||||
|
|
||||||
|
i2c_status_t status = i2c_bus_submit(drv->i2c_bus, pkt);
|
||||||
|
|
||||||
|
if (status != I2C_STATUS_OK) {
|
||||||
|
// This should never happen
|
||||||
|
error_shutdown("STWLC38 I2C submit error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool stwlc38_get_report(stwlc38_report_t* report) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
if (!drv->initialized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_key_t irq_key = irq_lock();
|
||||||
|
*report = drv->report;
|
||||||
|
irq_unlock(irq_key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stwlc38_timer_callback(void* context) {
|
||||||
|
stwlc38_driver_t* drv = (stwlc38_driver_t*)context;
|
||||||
|
|
||||||
|
// Schedule the report readout
|
||||||
|
drv->report_readout_requested = true;
|
||||||
|
stwlc38_fsm_continue(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stwlc38_i2c_callback(void* context, i2c_packet_t* packet) {
|
||||||
|
stwlc38_driver_t* drv = (stwlc38_driver_t*)context;
|
||||||
|
|
||||||
|
if (packet->status != I2C_STATUS_OK) {
|
||||||
|
memset(&drv->report, 0, sizeof(stwlc38_report_t));
|
||||||
|
// Kill periodic timer
|
||||||
|
systimer_unset(drv->timer);
|
||||||
|
// !@# retry on error?????
|
||||||
|
drv->state = STWLC38_STATE_POWER_DOWN;
|
||||||
|
drv->report_readout_requested = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (drv->state) {
|
||||||
|
case STWLC38_STATE_REPORT_READOUT:
|
||||||
|
drv->report_readout_requested = false;
|
||||||
|
|
||||||
|
bool was_ready = drv->report.ready;
|
||||||
|
|
||||||
|
// Status registers readout completed
|
||||||
|
memset(&drv->report, 0, sizeof(stwlc38_report_t));
|
||||||
|
drv->report.ready = true;
|
||||||
|
drv->report.vout_ready = drv->report_regs.status0 & 0x40;
|
||||||
|
drv->report.vrect = drv->report_regs.vrect / 1000.0;
|
||||||
|
drv->report.vout = drv->report_regs.vout / 1000.0;
|
||||||
|
drv->report.icur = drv->report_regs.icur;
|
||||||
|
drv->report.tmeas = drv->report_regs.tmeas / 10.0;
|
||||||
|
drv->report.opfreq = drv->report_regs.opfreq;
|
||||||
|
drv->report.ntc = drv->report_regs.ntc / 10.0;
|
||||||
|
|
||||||
|
// Just powered-up ?
|
||||||
|
if (!was_ready) {
|
||||||
|
// After power-up, ensure that the main LDO is in the requested state
|
||||||
|
drv->vout_enabled = !drv->vout_enabled_requested;
|
||||||
|
// Start the periodic timer
|
||||||
|
systimer_set_periodic(drv->timer, STWLC38_REPORT_READOUT_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STWLC38_STATE_VOUT_ENABLE:
|
||||||
|
// Main LDO output enabled
|
||||||
|
drv->vout_enabled = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STWLC38_STATE_VOUT_DISABLE:
|
||||||
|
// Main LDO output disabled
|
||||||
|
drv->vout_enabled = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// This should never happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
drv->state = STWLC38_STATE_IDLE;
|
||||||
|
stwlc38_fsm_continue(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void STWLC38_EXTI_INTERRUPT_HANDLER(void) {
|
||||||
|
stwlc38_driver_t* drv = &g_stwlc38_driver;
|
||||||
|
|
||||||
|
// Clear the EXTI line pending bit
|
||||||
|
__HAL_GPIO_EXTI_CLEAR_FLAG(STWLC38_INT_PIN);
|
||||||
|
|
||||||
|
if (drv->state == STWLC38_STATE_POWER_DOWN) {
|
||||||
|
// Inform the powerctl module about the WPC
|
||||||
|
// wakeup_flags_set(WAKEUP_FLAGS_WPC);
|
||||||
|
drv->report_readout_requested = true;
|
||||||
|
stwlc38_fsm_continue(drv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stwlc38_fsm_continue(stwlc38_driver_t* drv) {
|
||||||
|
// The order of the following conditions defines the priority
|
||||||
|
|
||||||
|
if (drv->state == STWLC38_STATE_POWER_DOWN && drv->report_readout_requested) {
|
||||||
|
// Check if the i2c interface is ready
|
||||||
|
stwlc38_i2c_submit(drv, stwlc38_ops_report_readout);
|
||||||
|
drv->state = STWLC38_STATE_REPORT_READOUT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv->state != STWLC38_STATE_IDLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drv->vout_enabled != drv->vout_enabled_requested) {
|
||||||
|
// Enable/Disable the main LDO output
|
||||||
|
if (drv->vout_enabled_requested) {
|
||||||
|
stwlc38_i2c_submit(drv, stwlc38_ops_vout_enable);
|
||||||
|
drv->state = STWLC38_STATE_VOUT_ENABLE;
|
||||||
|
} else {
|
||||||
|
stwlc38_i2c_submit(drv, stwlc38_ops_vout_disable);
|
||||||
|
drv->state = STWLC38_STATE_VOUT_DISABLE;
|
||||||
|
}
|
||||||
|
} else if (drv->report_readout_requested) {
|
||||||
|
// Read status registers
|
||||||
|
stwlc38_i2c_submit(drv, stwlc38_ops_report_readout);
|
||||||
|
drv->state = STWLC38_STATE_REPORT_READOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // KERNEL_MODE
|
73
core/embed/sys/powerctl/stwlc38/stwlc38.h
Normal file
73
core/embed/sys/powerctl/stwlc38/stwlc38.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TREZORHAL_STWLC38_H
|
||||||
|
#define TREZORHAL_STWLC38_H
|
||||||
|
|
||||||
|
#include <trezor_types.h>
|
||||||
|
|
||||||
|
// Initializes STWLC38 driver
|
||||||
|
//
|
||||||
|
// After initialization, the STWLC38 is enabled by default.
|
||||||
|
bool stwlc38_init(void);
|
||||||
|
|
||||||
|
// Deinitializes STWLC38 driver
|
||||||
|
void stwlc38_deinit(void);
|
||||||
|
|
||||||
|
// Enables or disables the STWLC38. This can be used to enable/disable
|
||||||
|
// wireless charging functionality.
|
||||||
|
//
|
||||||
|
// If the STWLC38 is disabled, it's not self-powered and is unable to
|
||||||
|
// communicate over I2C. STWLC38 is disabled by default after initialization.
|
||||||
|
//
|
||||||
|
// Returns true if the STWLC38 was successfully enabled or disabled.
|
||||||
|
bool stwlc38_enable(bool enable);
|
||||||
|
|
||||||
|
// Enables or disables the main LDO output.
|
||||||
|
//
|
||||||
|
// Main LDO output is enabled by default after initialization.
|
||||||
|
//
|
||||||
|
// Returns true if the main LDO output was successfully enabled or disabled.
|
||||||
|
bool stwlc38_enable_vout(bool enable);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
// Powered-up and initialized
|
||||||
|
bool ready;
|
||||||
|
// Providing power to the system
|
||||||
|
bool vout_ready;
|
||||||
|
|
||||||
|
// Rectified voltage [V]
|
||||||
|
float vrect;
|
||||||
|
// Main LDO voltage output [V]
|
||||||
|
float vout;
|
||||||
|
// Output current [mA]
|
||||||
|
float icur;
|
||||||
|
// Chip temperature [°C]
|
||||||
|
float tmeas;
|
||||||
|
// Operating frequency [kHz]
|
||||||
|
uint16_t opfreq;
|
||||||
|
// NTC Temperature [°C]
|
||||||
|
float ntc;
|
||||||
|
|
||||||
|
} stwlc38_report_t;
|
||||||
|
|
||||||
|
// Gets the current report from the STWLC38
|
||||||
|
bool stwlc38_get_report(stwlc38_report_t* status);
|
||||||
|
|
||||||
|
#endif // TREZORHAL_STWLC38_H
|
47
core/embed/sys/powerctl/stwlc38/stwlc38_defs.h
Normal file
47
core/embed/sys/powerctl/stwlc38/stwlc38_defs.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Trezor project, https://trezor.io/
|
||||||
|
*
|
||||||
|
* Copyright (c) SatoshiLabs
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TREZORHAL_STWLC38_DEFS_H
|
||||||
|
#define TREZORHAL_STWLC38_DEFS_H
|
||||||
|
|
||||||
|
// I2C address of the STWLC38 on the I2C bus.
|
||||||
|
#define STWLC38_I2C_ADDRESS 0x61
|
||||||
|
|
||||||
|
// RX Command register
|
||||||
|
#define STWLC38_RX_COMMAND 0x90
|
||||||
|
|
||||||
|
// Rectified voltage [mV/16-bit]
|
||||||
|
#define STWLC38_REG_VRECT 0x92
|
||||||
|
// Main LDO voltage output [mV/16-bit]
|
||||||
|
#define STWLC38_REG_VOUT 0x94
|
||||||
|
// Output current [mA]
|
||||||
|
#define STWLC38_REG_ICUR 0x96
|
||||||
|
// Chip temperature [°C * 10]
|
||||||
|
#define STWLC38_REG_TMEAS 0x98
|
||||||
|
// Operating frequency [kHz]
|
||||||
|
#define STWLC38_REG_OPFREQ 0x9A
|
||||||
|
// NTC Temperature [°C * 10]
|
||||||
|
#define STWLC38_REG_NTC 0x9C
|
||||||
|
|
||||||
|
// 3-byte status register
|
||||||
|
#define STWLC38_REG_RXINT_STATUS0 0x8C
|
||||||
|
#define STWLC38_REG_RXINT_STATUS1 0x8D
|
||||||
|
#define STWLC38_REG_RXINT_STATUS2 0x8E
|
||||||
|
|
||||||
|
#endif // TREZORHAL_STWLC38_DEFS_H
|
@ -147,7 +147,10 @@ def configure(
|
|||||||
("USE_RESET_TO_BOOT", "1"),
|
("USE_RESET_TO_BOOT", "1"),
|
||||||
]
|
]
|
||||||
|
|
||||||
sources += ["embed/sys/powerctl/npm1300/npm1300.c"]
|
sources += [
|
||||||
|
"embed/sys/powerctl/npm1300/npm1300.c",
|
||||||
|
"embed/sys/powerctl/stwlc38/stwlc38.c"
|
||||||
|
]
|
||||||
|
|
||||||
env.get("ENV")["LINKER_SCRIPT"] = linker_script
|
env.get("ENV")["LINKER_SCRIPT"] = linker_script
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user