6#if defined(BOARD_TLE9104_COUNT) && BOARD_TLE9104_COUNT > 0
20#define DRIVER_NAME "tle9104"
23#define TLE9104_POLL_INTERVAL_MS 100
35#define TLE9104_WR_REG(addr, val) (BIT(15) | (((addr) & 0x0f) << 8) | ((val) & 0xff))
36#define TLE9104_RD_REG(addr) (((addr) & 0x0f) << 8)
38#define TLE9104_GET_VAL(rx) ((rx) & 0xff)
39#define TLE9104_GET_ADDR(rx) (((rx) >> 8) & 0x0f)
41#define TLE9104_PARITY_MASK(val) ((val) & (~BIT(14)))
43#define TLE9104_FAULT_GLOBAL BIT(12)
44#define TLE9104_FAULT_COMM BIT(13)
46#define TLE9104_REG_CTRL 0x00
47#define TLE9104_REG_CFG 0x01
48#define TLE9104_REG_OFF_DIAG_CFG 0x02
49#define TLE9104_REG_ON_DIAG_CFG 0x03
50#define TLE9104_REG_DIAG_OUT_1_2_ON 0x04
51#define TLE9104_REG_DIAG_OUT_3_4_ON 0x05
52#define TLE9104_REG_DIAG_OFF 0x06
53#define TLE9104_REG_GLOBAL_STATUS 0x07
54#define TLE9104_REG_ICVID 0x08
69 void debug()
override;
71 int updateDiagState();
77 int spi_validate(uint16_t rx);
78 int spi_rw_array(
const uint16_t *tx, uint16_t *rx,
int n);
79 int spi_rw(uint16_t tx, uint16_t *rx);
80 int read_reg(uint8_t
addr, uint8_t *val);
81 int write_reg(uint8_t
addr, uint8_t val);
99 int spi_address_err_cnt;
101 int spi_parity_err_cnt;
104static Tle9104
chips[BOARD_TLE9104_COUNT];
112 int count = 1 + __builtin_popcount(val);
125 return (
count % 2) == 1;
129int Tle9104::spi_validate(uint16_t rx) {
133 spi_parity_err_cnt++;
137 if (rx & TLE9104_FAULT_GLOBAL) {
141 if (rx & TLE9104_FAULT_COMM) {
148int Tle9104::spi_rw(uint16_t tx, uint16_t *rx) {
149 SPIDriver *spi = cfg->spi_bus;
159 spiStart(spi, &cfg->spi_config);
163 uint16_t rxd = spiPolledExchange(spi, tx);
170 int ret = spi_validate(rxd);
185int Tle9104::spi_rw_array(
const uint16_t *tx, uint16_t *rx,
int n)
188 SPIDriver *spi = cfg->spi_bus;
190 if ((n <= 0) || (tx ==
nullptr)) {
197 spiStart(spi, &cfg->spi_config);
199 for (
int i = 0; i < n; i++) {
205 uint16_t rxdata = spiPolledExchange(spi, tx[i]);
213 ret = spi_validate(rxdata);
219 if (TLE9104_GET_ADDR(tx[i - 1] != TLE9104_GET_ADDR(rxdata))) {
220 spi_address_err_cnt++;
233int Tle9104::read_reg(uint8_t
addr, uint8_t *val) {
236 ret = spi_rw(TLE9104_RD_REG(
addr),
nullptr);
242 ret = spi_rw(TLE9104_RD_REG(
addr), &rxd);
248 *val = TLE9104_GET_VAL(rxd);
254int Tle9104::write_reg(uint8_t
addr, uint8_t val) {
256 return spi_rw(TLE9104_WR_REG(
addr, val),
nullptr);
259int Tle9104::chip_init() {
266 ret = write_reg(TLE9104_REG_CFG, 0x0F);
272 ret = updateDiagState();
276 ret = updateDiagState();
282 ret = write_reg(TLE9104_REG_GLOBAL_STATUS, BIT(7));
307 chRegSetThreadName(DRIVER_NAME);
311 chThdSleepMilliseconds(300);
315 msg = chSemWaitTimeout(&tle9104_wake, TIME_MS2I(TLE9104_POLL_INTERVAL_MS));
320 for (i = 0; i < BOARD_TLE9104_COUNT; i++) {
322 Tle9104& chip =
chips[i];
329 ret = chip.updateDiagState();
333 ret = chip.updateStatus();
345int Tle9104::writePad(
size_t pin,
int value) {
346 auto port = cfg->direct_io[
pin].port;
351 palClearPad(port, cfg->direct_io[
pin].pad);
353 palSetPad(port, cfg->direct_io[
pin].pad);
359int Tle9104::updateDiagState() {
363 ret = read_reg(TLE9104_REG_DIAG_OUT_1_2_ON, &diag_on12);
367 ret = read_reg(TLE9104_REG_DIAG_OUT_3_4_ON, &diag_on34);
371 ret = read_reg(TLE9104_REG_DIAG_OFF, &diag_off);
377 ret = write_reg(TLE9104_REG_DIAG_OUT_1_2_ON, 0);
381 ret = write_reg(TLE9104_REG_DIAG_OUT_3_4_ON, 0);
385 ret = write_reg(TLE9104_REG_DIAG_OFF, 0);
393int Tle9104::updateStatus() {
397 ret = read_reg(TLE9104_REG_GLOBAL_STATUS, &status);
403 if (status & BIT(0)) {
408 if (status & BIT(2)) {
433 on_diag = diag_on12 >> 3;
434 off_diag = diag_off >> 2;
438 off_diag = diag_off >> 4;
441 on_diag = diag_on34 >> 3;
442 off_diag = diag_off >> 6;
449 on_diag = on_diag & 0x7;
451 off_diag = off_diag & 0x3;
458 result |= PIN_SHORT_TO_BAT;
462 result |= PIN_DRIVER_OVERTEMP;
465 result |= PIN_OVERLOAD;
468 result |= PIN_DRIVER_OVERTEMP;
478 result |= PIN_SHORT_TO_GND;
485void Tle9104::debug() {
486 efiPrintf(
"spi transfers %d with patiry error %d with wrong address %d communication fault counter %d\n",
487 spi_cnt, spi_parity_err_cnt, spi_address_err_cnt, fault_comm_cnt);
488 efiPrintf(
"fault counter %d communication fault counter %d\n",
489 fault_cnt, fault_comm_cnt);
490 efiPrintf(
"POR counter %d reinit counter %d WD counter %d\n",
491 por_cnt, init_req_cnt, wdr_cnt);
497 m_resn.initPin(DRIVER_NAME
" RESN", cfg->resn);
498 m_en.initPin(DRIVER_NAME
" EN", cfg->en);
501 m_en.setValue(
false);
503 m_resn.setValue(
false);
506 for (
int i = 0; i < TLE9204_OUT_COUNT; i++) {
507 auto port = cfg->direct_io[i].port;
508 if (port ==
nullptr) {
513 palSetPadMode(cfg->direct_io[i].port, cfg->direct_io[i].pad, PAL_MODE_OUTPUT_PUSHPULL);
520 chThdSleepMilliseconds(1);
521 m_resn.setValue(
true);
522 chThdSleepMilliseconds(1);
527 ret = read_reg(TLE9104_REG_ICVID, &
id);
546 chThdCreateStatic(tle9104_thread_1_wa,
sizeof(tle9104_thread_1_wa),
547 PRIO_GPIOCHIP, tle9104_driver_thread,
nullptr);
555 Tle9104& chip =
chips[index];
558 if (chip.cfg !=
nullptr) {
569 for (
int chipIndex = 0;chipIndex < BOARD_TLE9104_COUNT;chipIndex++) {
572 criticalError(
"tle9104_add");
Single output pin reference and state.
int gpiochip_register(brain_pin_e base, const char *name, GpioChip &gpioChip, size_t size)
Register gpiochip.
void writePad(const char *msg, brain_pin_e pin, int bit)
bool isBrainPinValid(brain_pin_e brainPin)
bool gpio_pin_markUsed(ioportid_t port, ioportmask_t pin, const char *msg)
virtual brain_pin_diag_e getDiag(size_t)
virtual int writePad(size_t, int)
static Tle9104 chips[BOARD_TLE9104_COUNT]
SEMAPHORE_DECL(tle9104_wake, 10)
static bool drv_task_ready
void initAll9104(const tle9104_config *configs)
static THD_WORKING_AREA(tle9104_thread_1_wa, 256)
static bool parityBit(uint16_t val)
static THD_FUNCTION(tle9104_driver_thread, p)
static IgnVoltageGatekeeper gatekeeper
int tle9104_add(Gpio base, int index, const tle9104_config *cfg)