From a54a5e7f90ab783edd3618c20e4804bc8fb9cfb4 Mon Sep 17 00:00:00 2001 From: Matthew Kennedy Date: Thu, 10 Jun 2021 01:11:01 -0700 Subject: [PATCH] convert gpiochips to c++ (#2761) * core * basic header * tests are happy * tle6240 * tle8888 * 33972 * 33810 * tle8888_req_init * unused warning * warning * unsigned * 8888 debug * fix * don't qualify Co-authored-by: Matthew Kennedy --- firmware/hw_layer/drivers/gpio/core.cpp | 80 ++-- firmware/hw_layer/drivers/gpio/drv8860.cpp | 111 +++--- firmware/hw_layer/drivers/gpio/gpio_ext.h | 18 +- firmware/hw_layer/drivers/gpio/mc33810.cpp | 188 ++++----- firmware/hw_layer/drivers/gpio/mc33972.cpp | 170 ++++---- firmware/hw_layer/drivers/gpio/tle6240.cpp | 180 ++++----- firmware/hw_layer/drivers/gpio/tle8888.cpp | 443 +++++++++++---------- firmware/hw_layer/drivers/gpio/tle8888.h | 6 +- firmware/hw_layer/pin_repository.cpp | 18 - firmware/hw_layer/pin_repository.h | 1 - unit_tests/tests/test_gpiochip.cpp | 121 ++---- 11 files changed, 591 insertions(+), 745 deletions(-) diff --git a/firmware/hw_layer/drivers/gpio/core.cpp b/firmware/hw_layer/drivers/gpio/core.cpp index 107408ae88..84c479a17c 100644 --- a/firmware/hw_layer/drivers/gpio/core.cpp +++ b/firmware/hw_layer/drivers/gpio/core.cpp @@ -32,12 +32,10 @@ struct gpiochip { brain_pin_e base; size_t size; - gpiochip_ops *ops; + GpioChip *chip; const char *name; /* optional names of each gpio */ const char **gpio_names; - /* private driver data passed to ops */ - void *priv; }; static gpiochip chips[BOARD_EXT_GPIOCHIPS]; @@ -58,7 +56,7 @@ static gpiochip *gpiochip_find(brain_pin_e pin) return chip; } - return NULL; + return nullptr; } /*==========================================================================*/ @@ -92,7 +90,7 @@ const char *gpiochips_getChipName(brain_pin_e pin) { if (chip) return chip->name; - return NULL; + return nullptr; } /** @@ -111,7 +109,7 @@ const char *gpiochips_getPinName(brain_pin_e pin) return chip->gpio_names[offset]; } - return NULL; + return nullptr; } /** @@ -123,24 +121,18 @@ const char *gpiochips_getPinName(brain_pin_e pin) * else returns chip base */ -int gpiochip_register(brain_pin_e base, const char *name, gpiochip_ops *ops, size_t size, void *priv) +int gpiochip_register(brain_pin_e base, const char *name, GpioChip& gpioChip, size_t size) { - int i; - - /* no ops provided, zero size? */ - if ((!ops) || (!size)) + /* zero size? */ + if (!size) return -1; /* outside? */ if (((size_t)base + size - 1 > BRAIN_PIN_LAST) || (base <= BRAIN_PIN_ONCHIP_LAST)) return -1; - /* no 'writePad' and no 'readPad' implementation? return error code */ - if ((!ops->writePad) && (!ops->readPad)) - return -1; - /* check for overlap with other chips */ - for (i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { + for (int i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { if (chips[i].base != 0) { #define in_range(a, b, c) (((a) > (b)) && ((a) < (c))) if (in_range(base, chips[i].base, chips[i].base + chips[i].size)) @@ -150,9 +142,10 @@ int gpiochip_register(brain_pin_e base, const char *name, gpiochip_ops *ops, siz } } - gpiochip *chip = NULL; + gpiochip *chip = nullptr; + /* find free gpiochip struct */ - for (i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { + for (int i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { if (chips[i].base == 0) { chip = &chips[i]; break; @@ -166,13 +159,12 @@ int gpiochip_register(brain_pin_e base, const char *name, gpiochip_ops *ops, siz /* register chip */ chip->name = name; - chip->ops = ops; + chip->chip = &gpioChip; chip->base = base; chip->size = size; - chip->gpio_names = NULL; - chip->priv = priv; + chip->gpio_names = nullptr; - return (chip->base); + return base; } @@ -194,12 +186,11 @@ int gpiochip_unregister(brain_pin_e base) return -1; /* unregister chip */ - chip->name = NULL; - chip->ops = NULL; + chip->name = nullptr; + chip->chip = nullptr; chip->base = GPIO_UNASSIGNED; chip->size = 0; - chip->gpio_names = NULL; - chip->priv = NULL; + chip->gpio_names = nullptr; return 0; } @@ -230,20 +221,15 @@ int gpiochips_setPinNames(brain_pin_e base, const char **names) int gpiochips_init(void) { - int i; - int ret = -1; int pins_added = 0; - for (i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { + for (int i = 0; i < BOARD_EXT_GPIOCHIPS; i++) { gpiochip *chip = &chips[i]; if (!chip->base) continue; - if (chip->ops->init) - ret = chip->ops->init(chip->priv); - - if (ret < 0) { + if (chip->chip->init() < 0) { /* remove chip if it fails to init */ /* TODO: we will have a gap, is it ok? */ chip->base = GPIO_UNASSIGNED; @@ -270,10 +256,7 @@ int gpiochips_setPadMode(brain_pin_e pin, iomode_t mode) if (!chip) return -1; - if ((chip->ops->setPadMode)) - return chip->ops->setPadMode(chip->priv, pin - chip->base, mode); - - return -1; + return chip->chip->setPadMode(pin - chip->base, mode); } /** @@ -292,10 +275,7 @@ int gpiochips_writePad(brain_pin_e pin, int value) if (!chip) return -1; - if (chip->ops->writePad) - return chip->ops->writePad(chip->priv, pin - chip->base, value); - - return -1; + return chip->chip->writePad(pin - chip->base, value); } /** @@ -313,10 +293,7 @@ int gpiochips_readPad(brain_pin_e pin) if (!chip) return -1; - if (chip->ops->readPad) - return chip->ops->readPad(chip->priv, pin - chip->base); - - return -1; + return chip->chip->readPad(pin - chip->base); } /** @@ -334,10 +311,7 @@ brain_pin_diag_e gpiochips_getDiag(brain_pin_e pin) if (!chip) return PIN_INVALID; - if (chip->ops->getDiag) - return chip->ops->getDiag(chip->priv, pin - chip->base); - - return PIN_OK; + return chip->chip->getDiag(pin - chip->base); } /** @@ -374,18 +348,18 @@ int gpiochips_getPinOffset(brain_pin_e pin) { const char *gpiochips_getChipName(brain_pin_e pin) { (void)pin; - return NULL; + return nullptr; } const char *gpiochips_getPinName(brain_pin_e pin) { (void)pin; - return NULL; + return nullptr; } -int gpiochip_register(brain_pin_e base, const char *name, gpiochip_ops *ops, size_t size, void *priv) +int gpiochip_register(brain_pin_e base, const char *name, GpioChip&, size_t size) { - (void)base; (void)name; (void)ops; (void)size; (void)priv; + (void)base; (void)name; (void)size; return 0; } diff --git a/firmware/hw_layer/drivers/gpio/drv8860.cpp b/firmware/hw_layer/drivers/gpio/drv8860.cpp index f52160289d..e3e96abf69 100644 --- a/firmware/hw_layer/drivers/gpio/drv8860.cpp +++ b/firmware/hw_layer/drivers/gpio/drv8860.cpp @@ -49,7 +49,20 @@ SEMAPHORE_DECL(drv8860_wake, 10 /* or BOARD_DRV8860_COUNT ? */); static THD_WORKING_AREA(drv8860_thread_1_wa, 256); /* Driver */ -struct drv8860_priv { +struct Drv8860 : public GpioChip { + int init() override; + + int writePad(size_t pin, int value) override; + brain_pin_diag_e getDiag(size_t pin) override; + + // Internal helpers + int chip_init(); + + void spi_send(uint16_t tx); + + void update_outputs(); + int wake_driver(); + const drv8860_config *cfg; /* cached output state - state last send to chip */ uint16_t o_state_cached; @@ -59,7 +72,7 @@ struct drv8860_priv { drv8860_drv_state drv_state; }; -static drv8860_priv chips[BOARD_DRV8860_COUNT]; +static Drv8860 chips[BOARD_DRV8860_COUNT]; static const char* drv8860_pin_names[DRV8860_OUTPUTS] = { "drv8860.OUT1", "drv8860.OUT2", "drv8860.OUT3", "drv8860.OUT4", @@ -72,23 +85,18 @@ static const char* drv8860_pin_names[DRV8860_OUTPUTS] = { /* Driver local functions. */ /*==========================================================================*/ -static SPIDriver *get_bus(drv8860_priv *chip) { - /* return non-const SPIDriver* from const struct cfg */ - return chip->cfg->spi_bus; -} - /** * @brief DRV8860 send routine. * @details Sends 8/16 bits. CS asserted before and released after transaction. */ -static void drv8860_spi_send(drv8860_priv *chip, uint16_t tx) { - SPIDriver *spi = get_bus(chip); +void Drv8860::spi_send(uint16_t tx) { + SPIDriver *spi = cfg->spi_bus; /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); /* Slave Select assertion. */ spiSelect(spi); /* Atomic transfer operations. */ @@ -103,16 +111,16 @@ static void drv8860_spi_send(drv8860_priv *chip, uint16_t tx) { * @brief DRV8860 send output data. */ -static void drv8860_update_outputs(drv8860_priv *chip) { +void Drv8860::update_outputs() { /* TODO: lock? */ /* atomic */ /* set value only for non-direct driven pins */ - drv8860_spi_send(chip, chip->o_state & 0xffff); + spi_send(o_state & 0xffff); /* atomic */ - chip->o_state_cached = chip->o_state; - + o_state_cached = o_state; + /* TODO: unlock? */ } @@ -122,9 +130,9 @@ static void drv8860_update_outputs(drv8860_priv *chip) { * @todo: Checks direct io signals integrity, read initial diagnostic state. */ -static int drv8860_chip_init(drv8860_priv *chip) { +int Drv8860::chip_init() { /* upload pin states */ - drv8860_update_outputs(chip); + update_outputs(); return 0; } @@ -134,14 +142,11 @@ static int drv8860_chip_init(drv8860_priv *chip) { * @details Wake up driver. Will cause output register update. */ -static int drv8860_wake_driver(drv8860_priv *chip) { - (void)chip; +int Drv8860::wake_driver() { + /* Entering a reentrant critical zone.*/ + chibios_rt::CriticalSectionLocker csl; - /* Entering a reentrant critical zone.*/ - syssts_t sts = chSysGetStatusAndLockX(); chSemSignalI(&drv8860_wake); - /* Leaving the critical zone.*/ - chSysRestoreStatusX(sts); return 0; } @@ -165,15 +170,13 @@ static THD_FUNCTION(drv8860_driver_thread, p) { (void)msg; for (i = 0; i < BOARD_DRV8860_COUNT; i++) { - drv8860_priv *chip; - - chip = &chips[i]; + auto chip = &chips[i]; if ((chip->cfg == NULL) || (chip->drv_state == DRV8860_DISABLED) || (chip->drv_state == DRV8860_FAILED)) continue; - drv8860_update_outputs(chip); + chip->update_outputs(); } } } @@ -188,41 +191,34 @@ static THD_FUNCTION(drv8860_driver_thread, p) { /* Driver exported functions. */ /*==========================================================================*/ -int drv8860_writePad(void *data, unsigned int pin, int value) { - drv8860_priv *chip; - - if ((pin >= DRV8860_OUTPUTS) || (data == NULL)) +int Drv8860::writePad(size_t pin, int value) { + if (pin >= DRV8860_OUTPUTS) return -1; - chip = (drv8860_priv *)data; - /* TODO: lock */ if (value) - chip->o_state |= (1 << pin); + o_state |= (1 << pin); else - chip->o_state &= ~(1 << pin); + o_state &= ~(1 << pin); /* TODO: unlock */ - drv8860_wake_driver(chip); + wake_driver(); return 0; } -brain_pin_diag_e drv8860_getDiag(void* /*data*/, unsigned int /*pin*/) { +brain_pin_diag_e Drv8860::getDiag(size_t /*pin*/) { // todo: implement diag return PIN_OK; } -int drv8860_init(void * data) { +int Drv8860::init() { int ret; - drv8860_priv *chip; - chip = (drv8860_priv *)data; - - ret = drv8860_chip_init(chip); + ret = chip_init(); if (ret) return ret; - chip->drv_state = DRV8860_READY; + drv_state = DRV8860_READY; if (!drv_task_ready) { chThdCreateStatic(drv8860_thread_1_wa, sizeof(drv8860_thread_1_wa), @@ -233,22 +229,6 @@ int drv8860_init(void * data) { return 0; } -int drv8860_deinit(void *data) { - (void)data; - - /* TODO: set all pins to inactive state, stop task? */ - return 0; -} - -struct gpiochip_ops drv8860_ops = { - .setPadMode = nullptr, - .writePad = drv8860_writePad, - .readPad = NULL, /* chip outputs only */ - .getDiag = drv8860_getDiag, - .init = drv8860_init, - .deinit = drv8860_deinit, -}; - /** * @brief DRV8860 driver add. * @details Checks for valid config @@ -256,7 +236,6 @@ struct gpiochip_ops drv8860_ops = { int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg) { int ret; - drv8860_priv *chip; /* no config or no such chip */ if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_DRV8860_COUNT)) @@ -267,19 +246,19 @@ int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg) //if (cfg->spi_config.ssport == NULL) // return -1; - chip = &chips[index]; + auto& chip = chips[index]; /* already initted? */ - if (chip->cfg != NULL) + if (!chip.cfg) return -1; - chip->cfg = cfg; - chip->o_state = 0; - chip->o_state_cached = 0; - chip->drv_state = DRV8860_WAIT_INIT; + chip.cfg = cfg; + chip.o_state = 0; + chip.o_state_cached = 0; + chip.drv_state = DRV8860_WAIT_INIT; /* register, return gpio chip base */ - ret = gpiochip_register(base, DRIVER_NAME, &drv8860_ops, DRV8860_OUTPUTS, chip); + ret = gpiochip_register(base, DRIVER_NAME, chip, DRV8860_OUTPUTS); if (ret < 0) return ret; diff --git a/firmware/hw_layer/drivers/gpio/gpio_ext.h b/firmware/hw_layer/drivers/gpio/gpio_ext.h index b48408666c..8e1b7af71d 100644 --- a/firmware/hw_layer/drivers/gpio/gpio_ext.h +++ b/firmware/hw_layer/drivers/gpio/gpio_ext.h @@ -19,14 +19,16 @@ /* Checks */ /*==========================================================================*/ -struct gpiochip_ops { +struct GpioChip { + virtual int init() = 0; + + // These functions need not be implemented if not supported by the particular chip. /* pin argument is pin number within gpio chip, not a global number */ - int (*setPadMode)(void *data, unsigned int pin, iomode_t mode); - int (*writePad)(void *data, unsigned int pin, int value); - int (*readPad)(void *data, unsigned int pin); - brain_pin_diag_e (*getDiag)(void *data, unsigned int pin); - int (*init)(void *data); - int (*deinit)(void *data); + virtual int setPadMode(size_t /*pin*/, iomode_t /*mode*/) { return -1; } + virtual int writePad(size_t /*pin*/, int /*value*/) { return -1; } + virtual int readPad(size_t /*pin*/) { return -1; } + virtual brain_pin_diag_e getDiag(size_t /*pin*/) { return PIN_OK; } + virtual int deinit() { return 0; } }; int gpiochips_getPinOffset(brain_pin_e pin); @@ -34,7 +36,7 @@ const char *gpiochips_getChipName(brain_pin_e pin); const char *gpiochips_getPinName(brain_pin_e pin); /* register/unregister GPIO chip */ -int gpiochip_register(brain_pin_e base, const char *name, gpiochip_ops *ops, size_t size, void *priv); +int gpiochip_register(brain_pin_e base, const char *name, GpioChip& chip, size_t size); int gpiochip_unregister(brain_pin_e base); /* Set individual names for pins */ diff --git a/firmware/hw_layer/drivers/gpio/mc33810.cpp b/firmware/hw_layer/drivers/gpio/mc33810.cpp index 63a253b570..9d021f73bf 100644 --- a/firmware/hw_layer/drivers/gpio/mc33810.cpp +++ b/firmware/hw_layer/drivers/gpio/mc33810.cpp @@ -90,7 +90,22 @@ SEMAPHORE_DECL(mc33810_wake, 10 /* or BOARD_MC33810_COUNT ? */); static THD_WORKING_AREA(mc33810_thread_1_wa, 256); /* Driver */ -struct mc33810_priv { +struct Mc33810 : public GpioChip { + int init() override; + + int writePad(size_t pin, int value) override; + brain_pin_diag_e getDiag(size_t pin) override; + + + + // internal functions + int spi_rw(uint16_t tx, uint16_t* rx); + int update_output_and_diag(); + + int chip_init(); + void wake_driver(); + + const mc33810_config *cfg; /* cached output state - state last send to chip */ uint8_t o_state_cached; @@ -114,7 +129,7 @@ struct mc33810_priv { mc33810_drv_state drv_state; }; -static mc33810_priv chips[BOARD_MC33810_COUNT]; +static Mc33810 chips[BOARD_MC33810_COUNT]; static const char* mc33810_pin_names[MC33810_OUTPUTS] = { "mc33810.OUT1", "mc33810.OUT2", "mc33810.OUT3", "mc33810.OUT4", @@ -125,27 +140,21 @@ static const char* mc33810_pin_names[MC33810_OUTPUTS] = { /* Driver local functions. */ /*==========================================================================*/ -static SPIDriver *get_bus(mc33810_priv *chip) -{ - /* return non-const SPIDriver* from const struct cfg */ - return chip->cfg->spi_bus; -} - /** * @brief MC33810 send and receive routine. * @details Sends and receives 16 bits. CS asserted before and released * after transaction. */ -static int mc33810_spi_rw(mc33810_priv *chip, uint16_t tx, uint16_t *rx) +int Mc33810::spi_rw(uint16_t tx, uint16_t *rx) { uint16_t rxb; - SPIDriver *spi = get_bus(chip); + SPIDriver *spi = cfg->spi_bus; /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); /* Slave Select assertion. */ spiSelect(spi); /* Atomic transfer operations. */ @@ -161,13 +170,13 @@ static int mc33810_spi_rw(mc33810_priv *chip, uint16_t tx, uint16_t *rx) *rx = rxb; /* if reply on previous command is ALL STATUS RESPONSE */ - if (chip->all_status_requested) { - chip->all_status_value = rxb; - chip->all_status_updated = true; + if (all_status_requested) { + all_status_value = rxb; + all_status_updated = true; } /* if next reply will be ALL STATUS RESPONSE */ - chip->all_status_requested = + all_status_requested = (((TX_GET_CMD(tx) >= 0x1) && (TX_GET_CMD(tx) <= 0xa)) || (tx == MC_CMD_READ_REG(REG_ALL_STAT))); @@ -180,74 +189,74 @@ static int mc33810_spi_rw(mc33810_priv *chip, uint16_t tx, uint16_t *rx) * @details Sends ORed data to register, also receive diagnostic. */ -static int mc33810_update_output_and_diag(mc33810_priv *chip) +int Mc33810::update_output_and_diag() { int ret = 0; /* TODO: lock? */ /* we need to get updates status */ - chip->all_status_updated = false; + all_status_updated = false; /* if any pin is driven over SPI */ - if (chip->o_direct_mask != 0xff) { + if (o_direct_mask != 0xff) { uint16_t out_data; - out_data = chip->o_state & (~chip->o_direct_mask); - ret = mc33810_spi_rw(chip, MC_CMD_DRIVER_EN(out_data), NULL); + out_data = o_state & (~o_direct_mask); + ret = spi_rw(MC_CMD_DRIVER_EN(out_data), NULL); if (ret) return ret; - chip->o_state_cached = chip->o_state; + o_state_cached = o_state; } /* this comlicated logic to save few spi transfers in case we will receive status as reply on other command */ - if (!chip->all_status_requested) { - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), NULL); + if (!all_status_requested) { + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), NULL); if (ret) return ret; } /* get reply */ - if (!chip->all_status_updated) { - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), NULL); + if (!all_status_updated) { + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), NULL); if (ret) return ret; } /* now we have updated ALL STATUS register in chip data */ /* check OUT (injectors) first */ - if (chip->all_status_value & 0x000f) { + if (all_status_value & 0x000f) { /* request diagnostic of OUT0 and OUT1 */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_OUT10_FAULT), NULL); + ret = spi_rw(MC_CMD_READ_REG(REG_OUT10_FAULT), NULL); if (ret) return ret; /* get diagnostic for OUT0 and OUT1 and request diagnostic for OUT2 and OUT3 */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_OUT32_FAULT), &chip->out_fault[0]); + ret = spi_rw(MC_CMD_READ_REG(REG_OUT32_FAULT), &out_fault[0]); if (ret) return ret; /* get diagnostic for OUT2 and OUT2 and requset ALL STATUS */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), &chip->out_fault[1]); + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), &out_fault[1]); if (ret) return ret; } /* check GPGD - mode not supported yet */ - if (chip->all_status_value & 0x00f0) { + if (all_status_value & 0x00f0) { /* request diagnostic of GPGD */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_GPGD_FAULT), NULL); + ret = spi_rw(MC_CMD_READ_REG(REG_GPGD_FAULT), NULL); if (ret) return ret; /* get diagnostic for GPGD and requset ALL STATUS */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), &chip->gpgd_fault); + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), &gpgd_fault); if (ret) return ret; } /* check IGN */ - if (chip->all_status_value & 0x0f00) { + if (all_status_value & 0x0f00) { /* request diagnostic of IGN */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_IGN_FAULT), NULL); + ret = spi_rw(MC_CMD_READ_REG(REG_IGN_FAULT), NULL); if (ret) return ret; /* get diagnostic for IGN and requset ALL STATUS */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), &chip->ign_fault); + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), &ign_fault); if (ret) return ret; } @@ -262,12 +271,11 @@ static int mc33810_update_output_and_diag(mc33810_priv *chip) * @details Checks communication. Check chip presense. */ -static int mc33810_chip_init(mc33810_priv *chip) +int Mc33810::chip_init() { int n; int ret; uint16_t rx; - const mc33810_config *cfg = chip->cfg; /* mark pins used */ //ret = gpio_pin_markUsed(cfg->spi_config.ssport, cfg->spi_config.sspad, DRIVER_NAME " CS"); @@ -289,9 +297,9 @@ static int mc33810_chip_init(mc33810_priv *chip) /* check SPI communication */ /* 0. set echo mode, chip number - don't care */ - ret = mc33810_spi_rw(chip, MC_CMD_SPI_CHECK, NULL); + ret = spi_rw(MC_CMD_SPI_CHECK, NULL); /* 1. check loopback */ - ret |= mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_REV), &rx); + ret |= spi_rw(MC_CMD_READ_REG(REG_REV), &rx); if (ret) { ret = -1; goto err_gpios; @@ -303,7 +311,7 @@ static int mc33810_chip_init(mc33810_priv *chip) } /* 2. read revision */ - ret = mc33810_spi_rw(chip, MC_CMD_READ_REG(REG_ALL_STAT), &rx); + ret = spi_rw(MC_CMD_READ_REG(REG_ALL_STAT), &rx); if (ret) { ret = -1; goto err_gpios; @@ -328,12 +336,12 @@ static int mc33810_chip_init(mc33810_priv *chip) (3 << 2) | /* Open Secondary OSFLT = 100 uS, default */ (1 << 0) | /* End Spark THreshold: VPWR +5.5V, defaul */ 0; - ret = mc33810_spi_rw(chip, MC_CMD_SPARK(spark_settings), NULL); + ret = spi_rw(MC_CMD_SPARK(spark_settings), NULL); if (ret) { goto err_gpios; } - ret = mc33810_spi_rw(chip, MC_CMD_MODE_SELECT(0xf << 8), NULL); + ret = spi_rw(MC_CMD_MODE_SELECT(0xf << 8), NULL); if (ret) { goto err_gpios; } @@ -372,10 +380,8 @@ err_gpios: * diagnostic update. */ -static int mc33810_wake_driver(mc33810_priv *chip) +void Mc33810::wake_driver() { - (void)chip; - /* Entering a reentrant critical zone.*/ chibios_rt::CriticalSectionLocker csl; chSemSignalI(&mc33810_wake); @@ -386,8 +392,6 @@ static int mc33810_wake_driver(mc33810_priv *chip) */ chSchRescheduleS(); } - - return 0; } /*==========================================================================*/ @@ -410,17 +414,15 @@ static THD_FUNCTION(mc33810_driver_thread, p) (void)msg; for (i = 0; i < BOARD_MC33810_COUNT; i++) { - int ret; - mc33810_priv *chip; + auto chip = &chips[i]; - chip = &chips[i]; if ((chip->cfg == NULL) || (chip->drv_state == MC33810_DISABLED) || (chip->drv_state == MC33810_FAILED)) continue; /* TODO: implemet indirect driven gpios */ - ret = mc33810_update_output_and_diag(chip); + int ret = chip->update_output_and_diag(); if (ret) { /* set state to MC33810_FAILED? */ } @@ -438,54 +440,49 @@ static THD_FUNCTION(mc33810_driver_thread, p) /* Driver exported functions. */ /*==========================================================================*/ -int mc33810_writePad(void *data, unsigned int pin, int value) +int Mc33810::writePad(size_t pin, int value) { - if ((pin >= MC33810_OUTPUTS) || !data) { + if (pin >= MC33810_OUTPUTS){ return -1; } - auto chip = (mc33810_priv*)data; - { // mutate driver state under lock chibios_rt::CriticalSectionLocker csl; if (value) - chip->o_state |= BIT(pin); + o_state |= BIT(pin); else - chip->o_state &= ~BIT(pin); + o_state &= ~BIT(pin); } /* direct driven? */ - if (chip->o_direct_mask & BIT(pin)) { + if (o_direct_mask & BIT(pin)) { /* TODO: ensure that output driver enabled */ if (value) - palSetPort(chip->cfg->direct_io[pin].port, - PAL_PORT_BIT(chip->cfg->direct_io[pin].pad)); + palSetPort(cfg->direct_io[pin].port, + PAL_PORT_BIT(cfg->direct_io[pin].pad)); else - palClearPort(chip->cfg->direct_io[pin].port, - PAL_PORT_BIT(chip->cfg->direct_io[pin].pad)); + palClearPort(cfg->direct_io[pin].port, + PAL_PORT_BIT(cfg->direct_io[pin].pad)); } else { - mc33810_wake_driver(chip); + wake_driver(); } return 0; } -brain_pin_diag_e mc33810_getDiag(void *data, unsigned int pin) +brain_pin_diag_e Mc33810::getDiag(size_t pin) { int val; - mc33810_priv *chip; int diag = PIN_OK; - if ((pin >= MC33810_DIRECT_OUTPUTS) || (data == NULL)) + if (pin >= MC33810_DIRECT_OUTPUTS) return PIN_INVALID; - chip = (mc33810_priv *)data; - if (pin < 4) { /* OUT drivers */ - val = chip->out_fault[pin < 2 ? 0 : 1] >> (4 * (pin & 0x01)); + val = out_fault[pin < 2 ? 0 : 1] >> (4 * (pin & 0x01)); /* ON open fault */ if (val & BIT(0)) @@ -499,7 +496,7 @@ brain_pin_diag_e mc33810_getDiag(void *data, unsigned int pin) diag |= PIN_DRIVER_OVERTEMP; } else { /* INJ drivers, GPGD mode is not supported */ - val = chip->ign_fault >> (3 * (pin - 4)); + val = ign_fault >> (3 * (pin - 4)); /* open load */ if (val & BIT(0)) @@ -515,45 +512,25 @@ brain_pin_diag_e mc33810_getDiag(void *data, unsigned int pin) return static_cast(diag); } -int mc33810_init(void * data) +int Mc33810::init() { int ret; - mc33810_priv *chip; - chip = (mc33810_priv *)data; - - ret = mc33810_chip_init(chip); + ret = chip_init(); if (ret) return ret; - chip->drv_state = MC33810_READY; + drv_state = MC33810_READY; if (!drv_task_ready) { chThdCreateStatic(mc33810_thread_1_wa, sizeof(mc33810_thread_1_wa), - PRIO_GPIOCHIP, mc33810_driver_thread, NULL); + PRIO_GPIOCHIP, mc33810_driver_thread, nullptr); drv_task_ready = true; } return 0; } -int mc33810_deinit(void *data) -{ - (void)data; - - /* TODO: set all pins to inactive state, stop task? */ - return 0; -} - -struct gpiochip_ops mc33810_ops = { - .setPadMode = nullptr, - .writePad = mc33810_writePad, - .readPad = NULL, /* chip outputs only */ - .getDiag = mc33810_getDiag, - .init = mc33810_init, - .deinit = mc33810_deinit, -}; - /** * @brief MC33810 driver add. * @details Checks for valid config @@ -563,7 +540,6 @@ int mc33810_add(brain_pin_e base, unsigned int index, const mc33810_config *cfg) { int i; int ret; - mc33810_priv *chip; /* no config or no such chip */ if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_MC33810_COUNT)) @@ -574,36 +550,36 @@ int mc33810_add(brain_pin_e base, unsigned int index, const mc33810_config *cfg) //if (cfg->spi_config.ssport == NULL) // return -1; - chip = &chips[index]; + Mc33810& chip = chips[index]; /* already initted? */ - if (chip->cfg != NULL) + if (chip.cfg != NULL) return -1; - chip->cfg = cfg; - chip->o_state = 0; - chip->o_state_cached = 0; - chip->o_direct_mask = 0; - chip->drv_state = MC33810_WAIT_INIT; + chip.cfg = cfg; + chip.o_state = 0; + chip.o_state_cached = 0; + chip.o_direct_mask = 0; + chip.drv_state = MC33810_WAIT_INIT; for (i = 0; i < MC33810_DIRECT_OUTPUTS; i++) { if (cfg->direct_io[i].port != 0) - chip->o_direct_mask |= BIT(i); + chip.o_direct_mask |= BIT(i); } /* GPGD mode is not supported yet, ignition mode does not support spi on/off commands * so ignition signals should be directly driven */ - if ((chip->o_direct_mask & 0xf0) != 0xf0) + if ((chip.o_direct_mask & 0xf0) != 0xf0) return -1; /* register, return gpio chip base */ - ret = gpiochip_register(base, DRIVER_NAME, &mc33810_ops, MC33810_OUTPUTS, chip); + ret = gpiochip_register(base, DRIVER_NAME, chip, MC33810_OUTPUTS); if (ret < 0) return ret; /* set default pin names, board init code can rewrite */ gpiochips_setPinNames(static_cast(ret), mc33810_pin_names); - chip->drv_state = MC33810_WAIT_INIT; + chip.drv_state = MC33810_WAIT_INIT; return ret; } diff --git a/firmware/hw_layer/drivers/gpio/mc33972.cpp b/firmware/hw_layer/drivers/gpio/mc33972.cpp index acc6be4d0c..7caad59c03 100644 --- a/firmware/hw_layer/drivers/gpio/mc33972.cpp +++ b/firmware/hw_layer/drivers/gpio/mc33972.cpp @@ -79,7 +79,30 @@ typedef enum { /*==========================================================================*/ /* Driver */ -struct mc33972_priv { +struct Mc33972 : public GpioChip { + int init() override; + int deinit() override; + + // These functions need not be implemented if not supported by the particular chip. + /* pin argument is pin number within gpio chip, not a global number */ + int setPadMode(size_t pin, iomode_t mode) override; + int readPad(size_t pin) override; + brain_pin_diag_e getDiag(size_t pin) override; + + // internal functions + + int chip_init(); + int update_pullups(); + int update_status(); + + void wake_driver(); + + int spi_w(uint32_t tx); + + int comm_test(); + + + const struct mc33972_config *cfg; /* thread stuff */ @@ -97,18 +120,12 @@ struct mc33972_priv { mc33972_drv_state drv_state; }; -static mc33972_priv chips[BOARD_MC33972_COUNT]; +static Mc33972 chips[BOARD_MC33972_COUNT]; /*==========================================================================*/ /* Driver local functions. */ /*==========================================================================*/ -static SPIDriver *get_bus(mc33972_priv *chip) -{ - /* return non-const SPIDriver* from const struct cfg */ - return chip->cfg->spi_bus; -} - /** * @brief MC33972 send cmd routine. * @details Sends 24 bits of data. CS asserted before and released @@ -116,12 +133,12 @@ static SPIDriver *get_bus(mc33972_priv *chip) * of diagnostic. This routine save it to chip->i_state */ -static int mc33972_spi_w(mc33972_priv *chip, uint32_t tx) +int Mc33972::spi_w(uint32_t tx) { int i; uint8_t rxb[3]; uint8_t txb[3]; - SPIDriver *spi = get_bus(chip); + SPIDriver *spi = cfg->spi_bus; txb[0] = (tx >> 16) & 0xff; txb[1] = (tx >> 8) & 0xff; @@ -129,7 +146,7 @@ static int mc33972_spi_w(mc33972_priv *chip, uint32_t tx) /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); /* Slave Select assertion. */ spiSelect(spi); /* Atomic transfer operations. */ @@ -141,7 +158,7 @@ static int mc33972_spi_w(mc33972_priv *chip, uint32_t tx) spiReleaseBus(spi); /* save received data */ - chip->i_state = (rxb[0] << 16) | (rxb[1] << 8) | (rxb[2] << 0); + i_state = (rxb[0] << 16) | (rxb[1] << 8) | (rxb[2] << 0); /* no errors for now */ return 0; @@ -152,25 +169,25 @@ static int mc33972_spi_w(mc33972_priv *chip, uint32_t tx) * @details Chip reply with input data and two bits of diag */ -static int mc33972_update_status(mc33972_priv *chip) +int Mc33972::update_status() { - return mc33972_spi_w(chip, CMD_STATUS); + return spi_w(CMD_STATUS); } -static int mc33972_update_pullups(mc33972_priv *chip) +int Mc33972::update_pullups() { int ret; /* enable tri-state for all unused pins */ - ret = mc33972_spi_w(chip, CMD_TRI_STATE(SP_BANK, SP_PINS_EXTRACT(~chip->en_pins))); + ret = spi_w(CMD_TRI_STATE(SP_BANK, SP_PINS_EXTRACT(~en_pins))); if (ret) return ret; - ret = mc33972_spi_w(chip, CMD_TRI_STATE(SG_BANK, SG_PINS_EXTRACT(~chip->en_pins))); + ret = spi_w(CMD_TRI_STATE(SG_BANK, SG_PINS_EXTRACT(~en_pins))); return ret; } -static int mc33972_comm_test(mc33972_priv *chip) +int Mc33972::comm_test() { int ret; @@ -182,14 +199,14 @@ static int mc33972_comm_test(mc33972_priv *chip) * check that muxed input bit is zero */ for (int i = 0; i < MC33972_INPUTS; i++) { /* indexed starting from 1 */ - ret = mc33972_spi_w(chip, CMD_ANALOG(0, i + 1)); + ret = spi_w(CMD_ANALOG(0, i + 1)); if (ret) return ret; - ret = mc33972_update_status(chip); + ret = update_status(); if (ret) return ret; - if (chip->i_state & PIN_MASK(i)) + if (i_state & PIN_MASK(i)) return -1; } @@ -202,12 +219,12 @@ static int mc33972_comm_test(mc33972_priv *chip) * Performs reset. */ -static int mc33972_chip_init(mc33972_priv *chip) +int Mc33972::chip_init() { int ret; /* reset first */ - ret = mc33972_spi_w(chip, CMD_RST); + ret = spi_w(CMD_RST); if (ret) return ret; @@ -226,20 +243,20 @@ static int mc33972_chip_init(mc33972_priv *chip) */ /* check communication */ - ret = mc33972_comm_test(chip); + ret = comm_test(); if (ret) return ret; /* disable tri-state for used pins only */ - ret = mc33972_update_pullups(chip); + ret = update_pullups(); if (ret) return ret; /* Set wetting current to 2 mA */ - ret = mc33972_spi_w(chip, CMD_METALLIC(SP_BANK, 0)); + ret = spi_w(CMD_METALLIC(SP_BANK, 0)); if (ret) return ret; - ret = mc33972_spi_w(chip, CMD_METALLIC(SG_BANK, 0)); + ret = spi_w(CMD_METALLIC(SG_BANK, 0)); if (ret) return ret; @@ -251,11 +268,12 @@ static int mc33972_chip_init(mc33972_priv *chip) * @details Wake up driver. Will cause input and diagnostic * update */ -static int mc33972_wake_driver(mc33972_priv *chip) +void Mc33972::wake_driver() { - /* Entering a reentrant critical zone.*/ - syssts_t sts = chSysGetStatusAndLockX(); - chSemSignalI(&chip->wake); + /* Entering a reentrant critical zone */ + chibios_rt::CriticalSectionLocker csl; + + chSemSignalI(&wake); if (!port_is_isr_context()) { /** * chSemSignalI above requires rescheduling @@ -263,10 +281,6 @@ static int mc33972_wake_driver(mc33972_priv *chip) */ chSchRescheduleS(); } - /* Leaving the critical zone.*/ - chSysRestoreStatusX(sts); - - return 0; } /*==========================================================================*/ @@ -276,13 +290,13 @@ static int mc33972_wake_driver(mc33972_priv *chip) static THD_FUNCTION(mc33972_driver_thread, p) { int ret; - mc33972_priv *chip = reinterpret_cast(p); + Mc33972 *chip = reinterpret_cast(p); chRegSetThreadName(DRIVER_NAME); /* repeat init until success */ do { - ret = mc33972_chip_init(chip); + ret = chip->chip_init(); if (ret) { chThdSleepMilliseconds(1000); continue; @@ -301,11 +315,11 @@ static THD_FUNCTION(mc33972_driver_thread, p) if (msg == MSG_TIMEOUT) { /* only input state update */ - ret = mc33972_update_status(chip); + ret = chip->update_status(); } else { /* someone waked thread and asks us to update pin config */ - /* inputs state is also readed */ - ret = mc33972_update_pullups(chip); + /* inputs state is also read */ + ret = chip->update_pullups(); } if (ret) { @@ -324,14 +338,10 @@ static THD_FUNCTION(mc33972_driver_thread, p) /* Driver exported functions. */ /*==========================================================================*/ -static int mc33972_setPadMode(void *data, unsigned int pin, iomode_t mode) { - mc33972_priv *chip; - - if ((pin >= MC33972_INPUTS) || (data == NULL)) +int Mc33972::setPadMode(size_t pin, iomode_t mode) { + if (pin >= MC33972_INPUTS) return -1; - chip = (mc33972_priv *)data; - /* currently driver doesn't know how to hanlde different modes */ (void)mode; @@ -341,84 +351,60 @@ static int mc33972_setPadMode(void *data, unsigned int pin, iomode_t mode) { * if this function is called for pin, that means someone * wants to read this pin and we can enable pull-up * Also pull down is not supported yet */ - chip->en_pins |= PIN_MASK(pin); + en_pins |= PIN_MASK(pin); /* ask for reinit */ - mc33972_wake_driver(chip); + wake_driver(); return 0; } -static int mc33972_readPad(void *data, unsigned int pin) { - mc33972_priv *chip; - - if ((pin >= MC33972_INPUTS) || (data == NULL)) +int Mc33972::readPad(size_t pin) { + if (pin >= MC33972_INPUTS) return -1; - chip = (mc33972_priv *)data; - /* convert to some common enum? */ - return !!(chip->i_state & PIN_MASK(pin)); + return !!(i_state & PIN_MASK(pin)); } -static brain_pin_diag_e mc33972_getDiag(void *data, unsigned int pin) { +brain_pin_diag_e Mc33972::getDiag(size_t pin) { brain_pin_diag_e diag = PIN_OK; - mc33972_priv *chip; - if ((pin >= MC33972_INPUTS) || (data == NULL)) + if (pin >= MC33972_INPUTS) return PIN_INVALID; - chip = (mc33972_priv *)data; - /* one diag bit for all pins */ - if (chip->i_state & FLAG_THERM) + if (i_state & FLAG_THERM) diag = PIN_DRIVER_OVERTEMP; return diag; } -static int mc33972_init(void * data) +int Mc33972::init() { - mc33972_priv *chip; - - chip = (mc33972_priv *)data; - /* no pins enabled yet */ - chip->en_pins = 0x0000; + en_pins = 0x0000; /* init semaphore */ - chSemObjectInit(&chip->wake, 0); + chSemObjectInit(&wake, 0); /* start thread */ - chip->thread = chThdCreateStatic(chip->thread_wa, sizeof(chip->thread_wa), - PRIO_GPIOCHIP, mc33972_driver_thread, chip); + thread = chThdCreateStatic(thread_wa, sizeof(thread_wa), + PRIO_GPIOCHIP, mc33972_driver_thread, this); return 0; } -static int mc33972_deinit(void *data) +int Mc33972::deinit() { - mc33972_priv *chip; - - chip = (mc33972_priv *)data; - /* TODO: disable pulls for all pins? */ /* stop thread */ - chThdTerminate(chip->thread); + chThdTerminate(thread); return 0; } -struct gpiochip_ops mc33972_ops = { - .setPadMode = mc33972_setPadMode, - .writePad = NULL, /* chip input only */ - .readPad = mc33972_readPad, - .getDiag = mc33972_getDiag, - .init = mc33972_init, - .deinit = mc33972_deinit, -}; - /** * @brief MC33972 driver add. * @details Checks for valid config @@ -426,8 +412,6 @@ struct gpiochip_ops mc33972_ops = { int mc33972_add(brain_pin_e base, unsigned int index, const struct mc33972_config *cfg) { - mc33972_priv *chip; - /* no config or no such chip */ if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_MC33972_COUNT)) return -1; @@ -438,18 +422,18 @@ int mc33972_add(brain_pin_e base, unsigned int index, const struct mc33972_confi return -1; } - chip = &chips[index]; + Mc33972& chip = chips[index]; /* already initted? */ - if (chip->cfg != NULL) + if (chip.cfg != NULL) return -1; - chip->cfg = cfg; - chip->i_state = 0; - chip->drv_state = MC33972_WAIT_INIT; + chip.cfg = cfg; + chip.i_state = 0; + chip.drv_state = MC33972_WAIT_INIT; /* register, return gpio chip base */ - return gpiochip_register(base, DRIVER_NAME, &mc33972_ops, MC33972_INPUTS, chip); + return gpiochip_register(base, DRIVER_NAME, chip, MC33972_INPUTS); } #else /* BOARD_MC33972_COUNT > 0 */ diff --git a/firmware/hw_layer/drivers/gpio/tle6240.cpp b/firmware/hw_layer/drivers/gpio/tle6240.cpp index 8fd114537c..32869d5c9c 100644 --- a/firmware/hw_layer/drivers/gpio/tle6240.cpp +++ b/firmware/hw_layer/drivers/gpio/tle6240.cpp @@ -83,7 +83,19 @@ SEMAPHORE_DECL(tle6240_wake, 10 /* or BOARD_TLE6240_COUNT ? */); static THD_WORKING_AREA(tle6240_thread_1_wa, 256); /* Driver */ -struct tle6240_priv { +struct Tle6240 : public GpioChip { + int init() override; + + int writePad(size_t pin, int value) override; + brain_pin_diag_e getDiag(size_t pin) override; + + + // internal functions + int spi_rw(uint16_t tx, uint16_t *rx); + int update_output_and_diag(); + int chip_init(); + + const tle6240_config *cfg; /* cached output state - state last send to chip */ uint16_t o_state_cached; @@ -100,7 +112,7 @@ struct tle6240_priv { tle6240_drv_state drv_state; }; -static tle6240_priv chips[BOARD_TLE6240_COUNT]; +static Tle6240 chips[BOARD_TLE6240_COUNT]; static const char* tle6240_pin_names[TLE6240_OUTPUTS] = { "tle6240.OUT1", "tle6240.OUT2", "tle6240.OUT3", "tle6240.OUT4", @@ -113,27 +125,21 @@ static const char* tle6240_pin_names[TLE6240_OUTPUTS] = { /* Driver local functions. */ /*==========================================================================*/ -static SPIDriver *get_bus(tle6240_priv *chip) -{ - /* return non-const SPIDriver* from const struct cfg */ - return chip->cfg->spi_bus; -} - /** * @brief TLE6240 send and receive routine. * @details Sends and receives 16 bits. CS asserted before and released * after transaction. */ -static int tle6240_spi_rw(tle6240_priv *chip, uint16_t tx, uint16_t *rx) +int Tle6240::spi_rw(uint16_t tx, uint16_t *rx) { uint16_t rxb; - SPIDriver *spi = get_bus(chip); + SPIDriver *spi = cfg->spi_bus; /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); /* Slave Select assertion. */ spiSelect(spi); /* Atomic transfer operations. */ @@ -155,30 +161,30 @@ static int tle6240_spi_rw(tle6240_priv *chip, uint16_t tx, uint16_t *rx) * @details Sends ORed data to register, also receive 2-bit diagnostic. */ -static int tle6240_update_output_and_diag(tle6240_priv *chip) +int Tle6240::update_output_and_diag() { int ret; uint16_t out_data; /* atomic */ /* set value only for non-direct driven pins */ - out_data = chip->o_state & (~chip->o_direct_mask); - if (chip->diag_8_reguested) { + out_data = o_state & (~o_direct_mask); + if (diag_8_reguested) { /* diagnostic for OUT8..15 was requested on prev access */ - ret = tle6240_spi_rw(chip, CMD_OR_DIAG(0, (out_data >> 0) & 0xff), &chip->diag[1]); - ret |= tle6240_spi_rw(chip, CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &chip->diag[0]); + ret = spi_rw(CMD_OR_DIAG(0, (out_data >> 0) & 0xff), &diag[1]); + ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[0]); } else { - ret = tle6240_spi_rw(chip, CMD_OR_DIAG(0, (out_data >> 0) & 0xff), NULL); - ret |= tle6240_spi_rw(chip, CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &chip->diag[0]); + ret = spi_rw(CMD_OR_DIAG(0, (out_data >> 0) & 0xff), NULL); + ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[0]); /* send same one more time to receive OUT8..15 diagnostic */ - ret |= tle6240_spi_rw(chip, CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &chip->diag[1]); + ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[1]); } - chip->diag_8_reguested = false; + diag_8_reguested = false; if (ret == 0) { /* atomic */ - chip->o_state_cached = out_data; - chip->diag_8_reguested = true; + o_state_cached = out_data; + diag_8_reguested = true; } return ret; @@ -191,12 +197,11 @@ static int tle6240_update_output_and_diag(tle6240_priv *chip) * Reads initial diagnostic state. */ -static int tle6240_chip_init(tle6240_priv *chip) +int Tle6240::chip_init() { int n; int ret; uint16_t rx; - const tle6240_config *cfg = chip->cfg; /* mark pins used */ //ret = gpio_pin_markUsed(cfg->spi_config.ssport, cfg->spi_config.sspad, DRIVER_NAME " CS"); @@ -213,7 +218,7 @@ static int tle6240_chip_init(tle6240_priv *chip) } /* release reset */ - if (cfg->reset.port != NULL) { + if (!cfg->reset.port) { palClearPort(cfg->reset.port, PAL_PORT_BIT(cfg->reset.pad)); chThdSleepMilliseconds(1); @@ -224,9 +229,9 @@ static int tle6240_chip_init(tle6240_priv *chip) /* check SPI communication */ /* 0. set echo mode, chip number - don't care */ - ret = tle6240_spi_rw(chip, CMD_ECHO(0), NULL); + ret = spi_rw(CMD_ECHO(0), nullptr); /* 1. check loopback */ - ret |= tle6240_spi_rw(chip, 0x5555, &rx); + ret |= spi_rw(0x5555, &rx); if (ret || (rx != 0x5555)) { //print(DRIVER_NAME " spi loopback test failed\n"); ret = -2; @@ -237,23 +242,23 @@ static int tle6240_chip_init(tle6240_priv *chip) /* 0. set all direct out to 0 */ for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++) { int i = (n < 4) ? n : (n + 4); - if (chip->o_direct_mask & (1 << i)) { + if (o_direct_mask & (1 << i)) { palClearPort(cfg->direct_io[n].port, PAL_PORT_BIT(cfg->direct_io[n].pad)); } } /* 1. disable IN0..7 outputs first (ADNed with 0x00) * also will get full diag on next access */ - ret = tle6240_spi_rw(chip, CMD_AND_DIAG(0, 0x00), NULL); + ret = spi_rw(CMD_AND_DIAG(0, 0x00), NULL); /* 2. get diag for OUT0..7 and send disable OUT8..15 */ - ret |= tle6240_spi_rw(chip, CMD_AND_DIAG(8, 0x00), &chip->diag[0]); + ret |= spi_rw(CMD_AND_DIAG(8, 0x00), &diag[0]); /* 3. get diag for OUT8..15 and readback input status */ - ret |= tle6240_spi_rw(chip, CMD_IO_SHORTDIAG(0), &chip->diag[1]); + ret |= spi_rw(CMD_IO_SHORTDIAG(0), &diag[1]); /* 4. send dummy short diag command and get 8 bit of input data and * 8 bit of short diag */ - ret |= tle6240_spi_rw(chip, CMD_IO_SHORTDIAG(0), &rx); + ret |= spi_rw(CMD_IO_SHORTDIAG(0), &rx); rx = ((rx >> 4) & 0x0f00) | ((rx >> 8) & 0x000f); - if (ret || (rx & chip->o_direct_mask)) { + if (ret || (rx & o_direct_mask)) { //print(DRIVER_NAME " direct io test #1 failed (invalid io mask %04x)\n", (rx & chip->o_direct_mask)); ret = -3; goto err_gpios; @@ -262,23 +267,23 @@ static int tle6240_chip_init(tle6240_priv *chip) /* 5. set all direct io to 1 */ for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++) { int i = (n < 4) ? n : (n + 4); - if (chip->o_direct_mask & (1 << i)) { + if (o_direct_mask & (1 << i)) { palSetPort(cfg->direct_io[n].port, PAL_PORT_BIT(cfg->direct_io[n].pad)); } } /* 6. read chort diagnostic again */ - ret |= tle6240_spi_rw(chip, CMD_IO_SHORTDIAG(0), &rx); + ret |= spi_rw(CMD_IO_SHORTDIAG(0), &rx); rx = ((rx >> 4) & 0x0f00) | ((rx >> 8) & 0x000f); - rx &= chip->o_direct_mask; - if (ret || (rx != chip->o_direct_mask)) { + rx &= o_direct_mask; + if (ret || (rx != o_direct_mask)) { //print(DRIVER_NAME " direct io test #2 failed (invalid io mask %04x)\n", (rx ^ (~chip->o_direct_mask))); ret = -4; goto err_gpios; } /* 7. set all all pins to OR mode, and upload pin states */ - ret = tle6240_update_output_and_diag(chip); + ret = update_output_and_diag(); if (ret) { //print(DRIVER_NAME " final setup error\n"); ret = -5; @@ -305,12 +310,11 @@ err_gpios: * diagnostic update. */ -static int tle6240_wake_driver(tle6240_priv *chip) +static int tle6240_wake_driver() { - (void)chip; - /* Entering a reentrant critical zone.*/ - syssts_t sts = chSysGetStatusAndLockX(); + chibios_rt::CriticalSectionLocker csl; + chSemSignalI(&tle6240_wake); if (!port_is_isr_context()) { /** @@ -319,8 +323,6 @@ static int tle6240_wake_driver(tle6240_priv *chip) */ chSchRescheduleS(); } - /* Leaving the critical zone.*/ - chSysRestoreStatusX(sts); return 0; } @@ -346,15 +348,14 @@ static THD_FUNCTION(tle6240_driver_thread, p) for (i = 0; i < BOARD_TLE6240_COUNT; i++) { int ret; - tle6240_priv *chip; + Tle6240& chip = chips[i]; - chip = &chips[i]; - if ((chip->cfg == NULL) || - (chip->drv_state == TLE6240_DISABLED) || - (chip->drv_state == TLE6240_FAILED)) + if (!chip.cfg || + (chip.drv_state == TLE6240_DISABLED) || + (chip.drv_state == TLE6240_FAILED)) continue; - ret = tle6240_update_output_and_diag(chip); + ret = chip.update_output_and_diag(); if (ret) { /* set state to TLE6240_FAILED? */ } @@ -372,106 +373,77 @@ static THD_FUNCTION(tle6240_driver_thread, p) /* Driver exported functions. */ /*==========================================================================*/ -static int tle6240_writePad(void *data, unsigned int pin, int value) +int Tle6240::writePad(unsigned int pin, int value) { - tle6240_priv *chip; - - if ((pin >= TLE6240_OUTPUTS) || (data == NULL)) + if (pin >= TLE6240_OUTPUTS) return -1; - chip = (tle6240_priv *)data; - { chibios_rt::CriticalSectionLocker csl; if (value) - chip->o_state |= (1 << pin); + o_state |= (1 << pin); else - chip->o_state &= ~(1 << pin); + o_state &= ~(1 << pin); } /* direct driven? */ - if (chip->o_direct_mask & (1 << pin)) { + if (o_direct_mask & (1 << pin)) { int n = (pin < 8) ? pin : (pin - 4); /* TODO: ensure that TLE6240 configured in active high mode */ if (value) - palSetPort(chip->cfg->direct_io[n].port, - PAL_PORT_BIT(chip->cfg->direct_io[n].pad)); + palSetPort(cfg->direct_io[n].port, + PAL_PORT_BIT(cfg->direct_io[n].pad)); else - palClearPort(chip->cfg->direct_io[n].port, - PAL_PORT_BIT(chip->cfg->direct_io[n].pad)); + palClearPort(cfg->direct_io[n].port, + PAL_PORT_BIT(cfg->direct_io[n].pad)); } else { - tle6240_wake_driver(chip); + tle6240_wake_driver(); } return 0; } -static brain_pin_diag_e tle6240_getDiag(void *data, unsigned int pin) +brain_pin_diag_e Tle6240::getDiag(size_t pin) { int val; - int diag; - tle6240_priv *chip; + int diagVal; - if ((pin >= TLE6240_OUTPUTS) || (data == NULL)) + if (pin >= TLE6240_OUTPUTS) return PIN_INVALID; - chip = (tle6240_priv *)data; - - val = (chip->diag[(pin > 7) ? 1 : 0] >> ((pin % 8) * 2)) & 0x03; + val = (diag[(pin > 7) ? 1 : 0] >> ((pin % 8) * 2)) & 0x03; if (val == 0x3) - diag = PIN_OK; + diagVal = PIN_OK; else if (val == 0x2) /* Overload, shorted load or overtemperature */ - diag = PIN_OVERLOAD | PIN_DRIVER_OVERTEMP; + diagVal = PIN_OVERLOAD | PIN_DRIVER_OVERTEMP; else if (val == 0x1) - diag = PIN_OPEN; + diagVal = PIN_OPEN; else if (val == 0x0) - diag = PIN_SHORT_TO_GND; + diagVal = PIN_SHORT_TO_GND; - return static_cast(diag); + return static_cast(diagVal); } -static int tle6240_init(void * data) +int Tle6240::init() { - int ret; - tle6240_priv *chip; - - chip = (tle6240_priv *)data; - - ret = tle6240_chip_init(chip); + int ret = chip_init(); if (ret) return ret; - chip->drv_state = TLE6240_READY; + drv_state = TLE6240_READY; if (!drv_task_ready) { chThdCreateStatic(tle6240_thread_1_wa, sizeof(tle6240_thread_1_wa), - PRIO_GPIOCHIP, tle6240_driver_thread, NULL); + PRIO_GPIOCHIP, tle6240_driver_thread, nullptr); drv_task_ready = true; } return 0; } -static int tle6240_deinit(void *data) -{ - (void)data; - - /* TODO: set all pins to inactive state, stop task? */ - return 0; -} - -struct gpiochip_ops tle6240_ops = { - .setPadMode = nullptr, - .writePad = tle6240_writePad, - .readPad = NULL, /* chip outputs only */ - .getDiag = tle6240_getDiag, - .init = tle6240_init, - .deinit = tle6240_deinit, -}; - /** * @brief TLE6240 driver add. * @details Checks for valid config @@ -481,7 +453,7 @@ int tle6240_add(brain_pin_e base, unsigned int index, const tle6240_config *cfg) { int i; int ret; - tle6240_priv *chip; + Tle6240 *chip; /* no config or no such chip */ if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_TLE6240_COUNT)) @@ -511,7 +483,7 @@ int tle6240_add(brain_pin_e base, unsigned int index, const tle6240_config *cfg) chip->drv_state = TLE6240_WAIT_INIT; /* register, return gpio chip base */ - ret = gpiochip_register(base, DRIVER_NAME, &tle6240_ops, TLE6240_OUTPUTS, chip); + ret = gpiochip_register(base, DRIVER_NAME, *chip, TLE6240_OUTPUTS); if (ret < 0) return ret; diff --git a/firmware/hw_layer/drivers/gpio/tle8888.cpp b/firmware/hw_layer/drivers/gpio/tle8888.cpp index d24c7fbbaa..96d5043820 100644 --- a/firmware/hw_layer/drivers/gpio/tle8888.cpp +++ b/firmware/hw_layer/drivers/gpio/tle8888.cpp @@ -175,7 +175,41 @@ static int lowVoltageResetCounter = 0; float vBattForTle8888 = 0; /* Driver private data */ -struct tle8888_priv { +struct Tle8888 : public GpioChip { + int init() override; + int deinit() override; + + int setPadMode(size_t pin, iomode_t mode) override; + int writePad(size_t pin, int value) override; + int readPad(size_t pin) override; + brain_pin_diag_e getDiag(size_t pin) override; + + // internal functions + void read_reg(uint16_t reg, uint16_t* val); + int spi_rw(uint16_t tx, uint16_t *rx_ptr); + int spi_validate(uint16_t rx); + int spi_rw_array(const uint16_t *tx, uint16_t *rx, int n); + int update_status_and_diag(); + + int update_output(); + int update_direct_output(size_t pin, int value); + int wake_driver(); + + int chip_reset(); + + int chip_init(); + + int wwd_feed(); + int fwd_feed(); + int wd_get_status(); + int wd_feed(); + int calc_sleep_interval(); + + brain_pin_diag_e getOutputDiag(size_t pin); + brain_pin_diag_e getInputDiag(size_t pin); + + int chip_init_data(); + const tle8888_config *cfg; /* thread stuff */ @@ -241,7 +275,7 @@ struct tle8888_priv { uint16_t rx; }; -static tle8888_priv chips[BOARD_TLE8888_COUNT]; +static Tle8888 chips[BOARD_TLE8888_COUNT]; static const char* tle8888_pin_names[TLE8888_SIGNALS] = { "TLE8888.INJ1", "TLE8888.INJ2", "TLE8888.INJ3", "TLE8888.INJ4", @@ -257,7 +291,7 @@ static const char* tle8888_pin_names[TLE8888_SIGNALS] = { #if EFI_TUNER_STUDIO // set debug_mode 31 void tle8888PostState(TsDebugChannels *debugChannels) { - tle8888_priv *chip = &chips[0]; + Tle8888 *chip = &chips[0]; debugChannels->debugIntField1 = chip->wwd_err_cnt; debugChannels->debugIntField2 = chip->fwd_err_cnt; @@ -278,40 +312,34 @@ void tle8888PostState(TsDebugChannels *debugChannels) { /* Driver local functions. */ /*==========================================================================*/ -static SPIDriver *get_bus(tle8888_priv *chip) -{ - /* return non-const SPIDriver* from const struct cfg */ - return chip->cfg->spi_bus; -} - -static int tle8888_spi_validate(tle8888_priv *chip, uint16_t rx) +int Tle8888::spi_validate(uint16_t rx) { uint8_t reg = getRegisterFromResponse(rx); - if ((chip->last_reg != REG_INVALID) && (chip->last_reg != reg)) { + if ((last_reg != REG_INVALID) && (last_reg != reg)) { /* unexpected SPI answers */ if (reg == REG_OPSTAT(0)) { /* after power on reset: the address and the content of the * status register OpStat0 is transmitted with the next SPI * transmission */ - chip->por_cnt++; + por_cnt++; } else if (reg == REG_FWDSTAT(1)) { /* after watchdog reset: the address and the content of the * diagnosis register FWDStat1 is transmitted with the first * SPI transmission after the low to high transition of RST */ - chip->wdr_cnt++; + wdr_cnt++; } else if (reg == REG_DIAG(0)) { /* after an invalid communication frame: the address and the * content of the diagnosis register Diag0 is transmitted * with the next SPI transmission and the bit COMFE in * diagnosis register ComDiag is set to "1" */ - chip->comfe_cnt++; + comfe_cnt++; } /* during power on reset: SPI commands are ignored, SDO is always * tristate */ /* during watchdog reset: SPI commands are ignored, SDO has the * value of the status flag */ - chip->need_init = true; + need_init = true; return -1; } @@ -322,11 +350,11 @@ static int tle8888_spi_validate(tle8888_priv *chip, uint16_t rx) /** * @returns -1 in case of communication error */ -static int tle8888_spi_rw(tle8888_priv *chip, uint16_t tx, uint16_t *rx_ptr) +int Tle8888::spi_rw(uint16_t tx, uint16_t *rx_ptr) { int ret; uint16_t rx; - SPIDriver *spi = get_bus(chip); + SPIDriver *spi = cfg->spi_bus; /** * 15.1 SPI Protocol @@ -339,7 +367,7 @@ static int tle8888_spi_rw(tle8888_priv *chip, uint16_t tx, uint16_t *rx_ptr) /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); /* Slave Select assertion. */ spiSelect(spi); /* Atomic transfer operations. */ @@ -350,16 +378,16 @@ static int tle8888_spi_rw(tle8888_priv *chip, uint16_t tx, uint16_t *rx_ptr) spiReleaseBus(spi); /* statisctic and debug */ - chip->tx = tx; - chip->rx = rx; - chip->spi_cnt++; + this->tx = tx; + this->rx = rx; + this->spi_cnt++; if (rx_ptr) *rx_ptr = rx; /* validate reply and save last accessed register */ - ret = tle8888_spi_validate(chip, rx); - chip->last_reg = getRegisterFromResponse(tx); + ret = spi_validate(rx); + last_reg = getRegisterFromResponse(tx); /* no errors for now */ return ret; @@ -368,11 +396,11 @@ static int tle8888_spi_rw(tle8888_priv *chip, uint16_t tx, uint16_t *rx_ptr) /** * @return -1 in case of communication error */ -static int tle8888_spi_rw_array(tle8888_priv *chip, const uint16_t *tx, uint16_t *rx, int n) +int Tle8888::spi_rw_array(const uint16_t *tx, uint16_t *rx, int n) { int ret; uint16_t rxdata; - SPIDriver *spi = get_bus(chip); + SPIDriver *spi = cfg->spi_bus; /** * 15.1 SPI Protocol @@ -385,7 +413,7 @@ static int tle8888_spi_rw_array(tle8888_priv *chip, const uint16_t *tx, uint16_t /* Acquire ownership of the bus. */ spiAcquireBus(spi); /* Setup transfer parameters. */ - spiStart(spi, &chip->cfg->spi_config); + spiStart(spi, &cfg->spi_config); for (int i = 0; i < n; i++) { /* Slave Select assertion. */ @@ -399,13 +427,13 @@ static int tle8888_spi_rw_array(tle8888_priv *chip, const uint16_t *tx, uint16_t spiUnselect(spi); /* statistic and debug */ - chip->tx = tx[i]; - chip->rx = rxdata; - chip->spi_cnt++; + this->tx = tx[i]; + this->rx = rxdata; + this->spi_cnt++; /* validate reply and save last accessed register */ - ret = tle8888_spi_validate(chip, rxdata); - chip->last_reg = getRegisterFromResponse(tx[i]); + ret = spi_validate(rxdata); + last_reg = getRegisterFromResponse(tx[i]); if (ret < 0) break; @@ -422,7 +450,7 @@ static int tle8888_spi_rw_array(tle8888_priv *chip, const uint16_t *tx, uint16_t * @details Sends ORed data to register. */ -static int tle8888_update_output(tle8888_priv *chip) +int Tle8888::update_output() { int i; int ret; @@ -431,8 +459,8 @@ static int tle8888_update_output(tle8888_priv *chip) /* calculate briconfig0 */ for (i = 20; i < 24; i++) { - if (chip->o_pp_mask & BIT(i)) { - if (chip->o_state & BIT(i)) { + if (o_pp_mask & BIT(i)) { + if (o_state & BIT(i)) { /* low-side switch mode */ } else { /* else enable high-side switch mode */ @@ -444,11 +472,11 @@ static int tle8888_update_output(tle8888_priv *chip) /* TODO: apply hi-Z mask when support will be added */ /* set value only for non-direct driven pins */ - uint32_t o_data = chip->o_state & ~chip->o_direct_mask; + uint32_t o_data = o_state & ~o_direct_mask; /* output for push-pull pins is allways enabled * (at least until we start supporting hi-Z state) */ - o_data |= chip->o_pp_mask; + o_data |= o_pp_mask; uint16_t tx[] = { /* bridge config */ @@ -459,14 +487,14 @@ static int tle8888_update_output(tle8888_priv *chip) CMD_CONT(2, o_data >> 16), CMD_CONT(3, o_data >> 24), /* Main Relay output: manual vs auto-mode */ - CMD_CMD0((chip->mr_manual ? REG_CMD0_MRSE : 0x0) | + CMD_CMD0((mr_manual ? REG_CMD0_MRSE : 0x0) | ((o_data & BIT(TLE8888_OUTPUT_MR)) ? REG_CMD0_MRON : 0x0)) }; - ret = tle8888_spi_rw_array(chip, tx, NULL, ARRAY_SIZE(tx)); + ret = spi_rw_array(tx, NULL, ARRAY_SIZE(tx)); if (ret == 0) { /* atomic */ - chip->o_data_cached = o_data; + o_data_cached = o_data; } return ret; @@ -476,7 +504,7 @@ static int tle8888_update_output(tle8888_priv *chip) * @brief read TLE8888 diagnostic registers data. * @details Chained read of several registers */ -static int tle8888_update_status_and_diag(tle8888_priv *chip) +int Tle8888::update_status_and_diag() { int ret = 0; const uint16_t tx[] = { @@ -495,22 +523,22 @@ static int tle8888_update_status_and_diag(tle8888_priv *chip) }; uint16_t rx[ARRAY_SIZE(tx)]; - ret = tle8888_spi_rw_array(chip, tx, rx, ARRAY_SIZE(tx)); + ret = spi_rw_array(tx, rx, ARRAY_SIZE(tx)); if (ret == 0) { /* the address and content of the selected register is transmitted with the * next SPI transmission */ - chip->OutDiag[0] = getDataFromResponse(rx[0 + 1]); - chip->OutDiag[1] = getDataFromResponse(rx[1 + 1]); - chip->OutDiag[2] = getDataFromResponse(rx[2 + 1]); - chip->OutDiag[3] = getDataFromResponse(rx[3 + 1]); - chip->OutDiag[4] = getDataFromResponse(rx[4 + 1]); - chip->PPOVDiag = getDataFromResponse(rx[5 + 1]); - chip->BriDiag[0] = getDataFromResponse(rx[6 + 1]); - chip->BriDiag[1] = getDataFromResponse(rx[7 + 1]); - chip->IgnDiag = getDataFromResponse(rx[8 + 1]); - chip->OpStat[0] = getDataFromResponse(rx[9 + 1]); - chip->OpStat[1] = getDataFromResponse(rx[10 + 1]); + OutDiag[0] = getDataFromResponse(rx[0 + 1]); + OutDiag[1] = getDataFromResponse(rx[1 + 1]); + OutDiag[2] = getDataFromResponse(rx[2 + 1]); + OutDiag[3] = getDataFromResponse(rx[3 + 1]); + OutDiag[4] = getDataFromResponse(rx[4 + 1]); + PPOVDiag = getDataFromResponse(rx[5 + 1]); + BriDiag[0] = getDataFromResponse(rx[6 + 1]); + BriDiag[1] = getDataFromResponse(rx[7 + 1]); + IgnDiag = getDataFromResponse(rx[8 + 1]); + OpStat[0] = getDataFromResponse(rx[9 + 1]); + OpStat[1] = getDataFromResponse(rx[10 + 1]); } return ret; @@ -521,10 +549,9 @@ static int tle8888_update_status_and_diag(tle8888_priv *chip) * @details This is faster than updating Cont registers over SPI */ -static int tle8888_update_direct_output(tle8888_priv *chip, int pin, int value) +int Tle8888::update_direct_output(size_t pin, int value) { int index = -1; - const tle8888_config *cfg = chip->cfg; if (pin < 4) { /* OUT1..4 */ @@ -561,11 +588,11 @@ static int tle8888_update_direct_output(tle8888_priv *chip, int pin, int value) * @details Wake up driver. Will cause output register update */ -static int tle8888_wake_driver(tle8888_priv *chip) +int Tle8888::wake_driver() { /* Entering a reentrant critical zone.*/ chibios_rt::CriticalSectionLocker csl; - chSemSignalI(&chip->wake); + chSemSignalI(&wake); if (!port_is_isr_context()) { /** * chSemSignalI above requires rescheduling @@ -598,35 +625,35 @@ static brain_pin_diag_e tle8888_2b_to_diag_with_temp(unsigned int bits) return static_cast(diag); } -static int tle8888_chip_reset(tle8888_priv *chip) { +int Tle8888::chip_reset() { int ret; - ret = tle8888_spi_rw(chip, CMD_SR, NULL); + ret = spi_rw(CMD_SR, NULL); /** * Table 8. Reset Times. All reset times not more than 20uS */ chThdSleepMilliseconds(3); - chip->last_reg = REG_INVALID; + last_reg = REG_INVALID; return ret; } -static int tle8888_chip_init(tle8888_priv *chip) +int Tle8888::chip_init() { int ret; /* statistic */ - chip->init_cnt++; + init_cnt++; uint16_t tx[] = { /* unlock */ CMD_UNLOCK, /* set INCONFIG - aux input mapping */ - CMD_INCONFIG(0, chip->InConfig[0]), - CMD_INCONFIG(1, chip->InConfig[1]), - CMD_INCONFIG(2, chip->InConfig[2]), - CMD_INCONFIG(3, chip->InConfig[3]), + CMD_INCONFIG(0, InConfig[0]), + CMD_INCONFIG(1, InConfig[1]), + CMD_INCONFIG(2, InConfig[2]), + CMD_INCONFIG(3, InConfig[3]), /* Diagnnostic settings */ /* Enable open load detection and disable switch off * in case of overcurrent for OUTPUT1..4 */ @@ -659,27 +686,25 @@ static int tle8888_chip_init(tle8888_priv *chip) * in case of overcurrent for OUTPUT18..20 */ CMD_OUTCONFIG(5, BIT(5) | BIT(3) | BIT(1)), /* set OE and DD registers */ - CMD_OECONFIG(0, chip->o_oe_mask >> 0), - CMD_DDCONFIG(0, chip->o_direct_mask >> 0), - CMD_OECONFIG(1, chip->o_oe_mask >> 8), - CMD_DDCONFIG(1, chip->o_direct_mask >> 8), - CMD_OECONFIG(2, chip->o_oe_mask >> 16), - CMD_DDCONFIG(2, chip->o_direct_mask >> 16), - CMD_OECONFIG(3, chip->o_oe_mask >> 24), - CMD_DDCONFIG(3, chip->o_direct_mask >> 24), + CMD_OECONFIG(0, o_oe_mask >> 0), + CMD_DDCONFIG(0, o_direct_mask >> 0), + CMD_OECONFIG(1, o_oe_mask >> 8), + CMD_DDCONFIG(1, o_direct_mask >> 8), + CMD_OECONFIG(2, o_oe_mask >> 16), + CMD_DDCONFIG(2, o_direct_mask >> 16), + CMD_OECONFIG(3, o_oe_mask >> 24), + CMD_DDCONFIG(3, o_direct_mask >> 24), /* set VR mode: VRS/Hall */ CMD_VRSCONFIG(1, (0 << 4) | - (chip->cfg->mode << 2) | + (cfg->mode << 2) | (0 << 0)), /* enable outputs */ CMD_OE_SET }; - ret = tle8888_spi_rw_array(chip, tx, NULL, ARRAY_SIZE(tx)); + ret = spi_rw_array(tx, NULL, ARRAY_SIZE(tx)); if (ret == 0) { - const tle8888_config *cfg = chip->cfg; - /* enable pins */ if (cfg->ign_en.port) palSetPort(cfg->ign_en.port, PAL_PORT_BIT(cfg->ign_en.pad)); @@ -694,18 +719,18 @@ static int tle8888_chip_init(tle8888_priv *chip) return ret; } -static int tle8888_wwd_feed(tle8888_priv *chip) { - tle8888_spi_rw(chip, CMD_WWDSERVICECMD, NULL); +int Tle8888::wwd_feed() { + spi_rw(CMD_WWDSERVICECMD, NULL); return 0; } -static int tle8888_fwd_feed(tle8888_priv *chip) { +int Tle8888::fwd_feed() { uint16_t reg; - tle8888_spi_rw(chip, CMD_FWDSTAT(1), NULL); + spi_rw(CMD_FWDSTAT(1), NULL); /* here we get response of the 'FWDStat1' above */ - tle8888_spi_rw(chip, CMD_WDDIAG, ®); + spi_rw(CMD_WDDIAG, ®); uint8_t data = getDataFromResponse(reg); uint8_t fwdquest = data & 0xF; @@ -713,30 +738,30 @@ static int tle8888_fwd_feed(tle8888_priv *chip) { /* Table lines are filled in reverse order (like in DS) */ uint8_t response = tle8888_fwd_responses[fwdquest][3 - fwdrespc]; if (fwdrespc != 0) { - tle8888_spi_rw(chip, CMD_FWDRESPCMD(response), NULL); + spi_rw(CMD_FWDRESPCMD(response), NULL); } else { /* to restart heartbeat timer, sync command should be used for response 0 */ - tle8888_spi_rw(chip, CMD_FWDRESPSYNCCMD(response), NULL); + spi_rw(CMD_FWDRESPSYNCCMD(response), NULL); } return 0; } -static int tle8888_wd_get_status(tle8888_priv *chip) { +int Tle8888::wd_get_status() { uint16_t reg; - tle8888_spi_rw(chip, CMD_WDDIAG, NULL); - tle8888_spi_rw(chip, CMD_WDDIAG, ®); + spi_rw(CMD_WDDIAG, NULL); + spi_rw(CMD_WDDIAG, ®); - chip->wd_diag = getDataFromResponse(reg); + wd_diag = getDataFromResponse(reg); - if (chip->wd_diag & 0x70) { + if (wd_diag & 0x70) { /* Reset caused by TEC * Reset caused by FWD * Reset caused by WWD */ return -1; } - if (chip->wd_diag & 0x0f) { + if (wd_diag & 0x0f) { /* Some error in WD handling */ return 1; } @@ -744,50 +769,50 @@ static int tle8888_wd_get_status(tle8888_priv *chip) { return 0; } -static int tle8888_wd_feed(tle8888_priv *chip) { +int Tle8888::wd_feed() { bool update_status; - if (chip->wwd_ts <= chVTGetSystemTimeX()) { + if (wwd_ts <= chVTGetSystemTimeX()) { update_status = true; - if (tle8888_wwd_feed(chip) == 0) { - chip->wwd_ts = chTimeAddX(chVTGetSystemTimeX(), TIME_MS2I(WWD_PERIOD_MS)); + if (wwd_feed() == 0) { + wwd_ts = chTimeAddX(chVTGetSystemTimeX(), TIME_MS2I(WWD_PERIOD_MS)); } } - if (chip->fwd_ts <= chVTGetSystemTimeX()) { + if (fwd_ts <= chVTGetSystemTimeX()) { update_status = true; - if (tle8888_fwd_feed(chip) == 0) { - chip->fwd_ts = chTimeAddX(chVTGetSystemTimeX(), TIME_MS2I(FWD_PERIOD_MS)); + if (fwd_feed() == 0) { + fwd_ts = chTimeAddX(chVTGetSystemTimeX(), TIME_MS2I(FWD_PERIOD_MS)); } } if (update_status) { uint16_t wwd_reg, fwd_reg, tec_reg; - tle8888_spi_rw(chip, CMD_WWDSTAT, NULL); - tle8888_spi_rw(chip, CMD_FWDSTAT(0), &wwd_reg); - tle8888_spi_rw(chip, CMD_TECSTAT, &fwd_reg); - tle8888_spi_rw(chip, CMD_TECSTAT, &tec_reg); + spi_rw(CMD_WWDSTAT, NULL); + spi_rw(CMD_FWDSTAT(0), &wwd_reg); + spi_rw(CMD_TECSTAT, &fwd_reg); + spi_rw(CMD_TECSTAT, &tec_reg); - chip->wwd_err_cnt = getDataFromResponse(wwd_reg) & 0x7f; - chip->fwd_err_cnt = getDataFromResponse(fwd_reg) & 0x7f; - chip->tot_err_cnt = getDataFromResponse(tec_reg) & 0x7f; + wwd_err_cnt = getDataFromResponse(wwd_reg) & 0x7f; + fwd_err_cnt = getDataFromResponse(fwd_reg) & 0x7f; + tot_err_cnt = getDataFromResponse(tec_reg) & 0x7f; - chip->wd_happy = ((chip->wwd_err_cnt == 0) && - (chip->fwd_err_cnt == 0)); + wd_happy = ((wwd_err_cnt == 0) && + (fwd_err_cnt == 0)); - return tle8888_wd_get_status(chip); + return wd_get_status(); } else { return 0; } } -static int tle8888_calc_sleep_interval(tle8888_priv *chip) { +int Tle8888::calc_sleep_interval() { systime_t now = chVTGetSystemTimeX(); - sysinterval_t wwd_delay = chTimeDiffX(now, chip->wwd_ts); - sysinterval_t fwd_delay = chTimeDiffX(now, chip->fwd_ts); - sysinterval_t diag_delay = chTimeDiffX(now, chip->diag_ts); + sysinterval_t wwd_delay = chTimeDiffX(now, wwd_ts); + sysinterval_t fwd_delay = chTimeDiffX(now, fwd_ts); + sysinterval_t diag_delay = chTimeDiffX(now, diag_ts); if ((diag_delay <= wwd_delay) && (diag_delay <= fwd_delay)) return diag_delay; @@ -801,7 +826,7 @@ static int tle8888_calc_sleep_interval(tle8888_priv *chip) { /*==========================================================================*/ static THD_FUNCTION(tle8888_driver_thread, p) { - tle8888_priv *chip = reinterpret_cast(p); + Tle8888 *chip = reinterpret_cast(p); sysinterval_t poll_interval = 0; chRegSetThreadName(DRIVER_NAME); @@ -838,13 +863,13 @@ static THD_FUNCTION(tle8888_driver_thread, p) { /* update outputs only if WD is happy */ if ((wd_happy) || (1)) { - ret = tle8888_update_output(chip); + ret = chip->update_output(); if (ret) { /* set state to TLE8888_FAILED? */ } } - ret = tle8888_wd_feed(chip); + ret = chip->wd_feed(); if (ret < 0) { /* WD is not happy */ continue; @@ -858,14 +883,14 @@ static THD_FUNCTION(tle8888_driver_thread, p) { /* clear first, as flag can be raised again during init */ chip->need_init = false; /* re-init chip! */ - tle8888_chip_init(chip); + chip->chip_init(); /* sync pins state */ - tle8888_update_output(chip); + chip->update_output(); } if (chip->diag_ts <= chVTGetSystemTimeX()) { /* this is expensive call, will do a lot of spi transfers... */ - ret = tle8888_update_status_and_diag(chip); + ret = chip->update_status_and_diag(); if (ret) { /* set state to TLE8888_FAILED or force reinit? */ } @@ -881,7 +906,7 @@ static THD_FUNCTION(tle8888_driver_thread, p) { chip->diag_ts = chTimeAddX(chVTGetSystemTimeX(), TIME_MS2I(DIAG_PERIOD_MS)); } - poll_interval = tle8888_calc_sleep_interval(chip); + poll_interval = chip->calc_sleep_interval(); } } @@ -893,16 +918,13 @@ static THD_FUNCTION(tle8888_driver_thread, p) { /* Driver exported functions. */ /*==========================================================================*/ -static int tle8888_setPadMode(void *data, unsigned int pin, iomode_t mode) { - - if ((pin >= TLE8888_SIGNALS) || (data == NULL)) +int Tle8888::setPadMode(unsigned int pin, iomode_t mode) { + if (pin >= TLE8888_SIGNALS) return -1; - tle8888_priv *chip = (tle8888_priv *)data; - /* if someone has requested MR pin - switch it to manual mode */ if (pin == TLE8888_OUTPUT_MR) { - chip->mr_manual = true; + mr_manual = true; } /* do not enalbe PP mode yet */ @@ -915,9 +937,9 @@ static int tle8888_setPadMode(void *data, unsigned int pin, iomode_t mode) { * values to tle8888 driver... But this is how gpios * currently implemented */ if ((mode & PAL_STM32_OTYPE_MASK) == PAL_STM32_OTYPE_OPENDRAIN) { - chip->o_pp_mask &= ~BIT(pin); + o_pp_mask &= ~BIT(pin); } else { - chip->o_pp_mask |= BIT(pin); + o_pp_mask |= BIT(pin); } #else (void)mode; @@ -926,63 +948,59 @@ static int tle8888_setPadMode(void *data, unsigned int pin, iomode_t mode) { return 0; } -static int tle8888_writePad(void *data, unsigned int pin, int value) { +int Tle8888::writePad(unsigned int pin, int value) { - if ((pin >= TLE8888_OUTPUTS) || (data == NULL)) + if (pin >= TLE8888_OUTPUTS) return -1; - tle8888_priv *chip = (tle8888_priv *)data; - { chibios_rt::CriticalSectionLocker csl; if (value) { - chip->o_state |= (1 << pin); + o_state |= (1 << pin); } else { - chip->o_state &= ~(1 << pin); + o_state &= ~(1 << pin); } } /* direct driven? */ - if (chip->o_direct_mask & (1 << pin)) { - return tle8888_update_direct_output(chip, pin, value); + if (o_direct_mask & (1 << pin)) { + return update_direct_output(pin, value); } else { - return tle8888_wake_driver(chip); + return wake_driver(); } return 0; } -static int tle8888_readPad(void *data, unsigned int pin) { - if ((pin >= TLE8888_OUTPUTS) || (data == NULL)) +int Tle8888::readPad(size_t pin) { + if (pin >= TLE8888_OUTPUTS) return -1; - tle8888_priv *chip = (tle8888_priv *)data; - if (pin < TLE8888_OUTPUTS_REGULAR) { /* return output state */ /* DOTO: check that pins is disabled by diagnostic? */ - return !!(chip->o_data_cached & BIT(pin)); + return !!(o_data_cached & BIT(pin)); } else if (pin == TLE8888_OUTPUT_MR) { /* Main relay can be enabled by KEY input, so report real state */ - return !!(chip->OpStat[0] & REG_OPSTAT_MR); + return !!(OpStat[0] & REG_OPSTAT_MR); } else if (pin == TLE8888_INPUT_KEY) { - return !!(chip->OpStat[0] & REG_OPSTAT_KEY); + return !!(OpStat[0] & REG_OPSTAT_KEY); } if (pin == TLE8888_INPUT_WAKE) { - return !!(chip->OpStat[0] & REG_OPSTAT_WAKE); + return !!(OpStat[0] & REG_OPSTAT_WAKE); } /* unknown pin */ return -1; } -static brain_pin_diag_e tle8888_getOutputDiag(tle8888_priv *chip, unsigned int pin) +brain_pin_diag_e Tle8888::getOutputDiag(size_t pin) { /* OUT1..OUT4, indexes 0..3 */ if (pin < 4) - return tle8888_2b_to_diag_with_temp((chip->OutDiag[0] >> ((pin - 0) * 2)) & 0x03); + return tle8888_2b_to_diag_with_temp((OutDiag[0] >> ((pin - 0) * 2)) & 0x03); /* OUT5..OUT7, indexes 4..6 */ if (pin < 7) { - return tle8888_2b_to_diag_with_temp((chip->OutDiag[1] >> ((pin - 4) * 2)) & 0x03); + return tle8888_2b_to_diag_with_temp((OutDiag[1] >> ((pin - 4) * 2)) & 0x03); } /* OUT8 to OUT13, indexes 7..12 */ if (pin < 13) { @@ -990,79 +1008,75 @@ static brain_pin_diag_e tle8888_getOutputDiag(tle8888_priv *chip, unsigned int p /* OUT8 */ if (pin == 7) - ret = tle8888_2b_to_diag_no_temp((chip->OutDiag[1] >> 6) & 0x03); + ret = tle8888_2b_to_diag_no_temp((OutDiag[1] >> 6) & 0x03); /* OUT9..OUT12 */ else if (pin < 12) - ret = tle8888_2b_to_diag_no_temp((chip->OutDiag[2] >> ((pin - 8) * 2)) & 0x03); + ret = tle8888_2b_to_diag_no_temp((OutDiag[2] >> ((pin - 8) * 2)) & 0x03); /* OUT13 */ else /* if (pin == 12) */ - ret = tle8888_2b_to_diag_no_temp((chip->OutDiag[3] >> 0) & 0x03); + ret = tle8888_2b_to_diag_no_temp((OutDiag[3] >> 0) & 0x03); /* overvoltage bit */ - if (chip->PPOVDiag & BIT(pin - 7)) + if (PPOVDiag & BIT(pin - 7)) ret |= PIN_SHORT_TO_BAT; return static_cast(ret); } /* OUT14 to OUT16, indexes 13..15 */ if (pin < 16) - return tle8888_2b_to_diag_with_temp((chip->OutDiag[3] >> ((pin - 13 + 1) * 2)) & 0x03); + return tle8888_2b_to_diag_with_temp((OutDiag[3] >> ((pin - 13 + 1) * 2)) & 0x03); /* OUT17 to OUT20, indexes 16..19 */ if (pin < 20) - return tle8888_2b_to_diag_with_temp((chip->OutDiag[4] >> ((pin - 16) * 2)) & 0x03); + return tle8888_2b_to_diag_with_temp((OutDiag[4] >> ((pin - 16) * 2)) & 0x03); /* OUT21..OUT24, indexes 20..23 */ if (pin < 24) { /* half bridges */ int diag; - diag = tle8888_2b_to_diag_no_temp((chip->BriDiag[0] >> ((pin - 20) * 2)) & 0x03); + diag = tle8888_2b_to_diag_no_temp((BriDiag[0] >> ((pin - 20) * 2)) & 0x03); if (((pin == 22) || (pin == 23)) && - (chip->BriDiag[1] & BIT(5))) + (BriDiag[1] & BIT(5))) diag |= PIN_DRIVER_OVERTEMP; if (((pin == 20) || (pin == 21)) && - (chip->BriDiag[1] & BIT(4))) + (BriDiag[1] & BIT(4))) diag |= PIN_DRIVER_OVERTEMP; - if (chip->BriDiag[1] & BIT(pin - 20)) + if (BriDiag[1] & BIT(pin - 20)) diag |= PIN_OVERLOAD; /* overcurrent */ return static_cast(diag); } if (pin < 28) - return tle8888_2b_to_diag_with_temp((chip->IgnDiag >> ((pin - 24) * 2)) & 0x03); + return tle8888_2b_to_diag_with_temp((IgnDiag >> ((pin - 24) * 2)) & 0x03); return PIN_OK; } -static brain_pin_diag_e tle8888_getInputDiag(tle8888_priv *chip, unsigned int pin) +brain_pin_diag_e Tle8888::getInputDiag(unsigned int pin) { - (void)chip; (void)pin; + (void)pin; return PIN_OK; } -static brain_pin_diag_e tle8888_getDiag(void *data, unsigned int pin) +brain_pin_diag_e Tle8888::getDiag(size_t pin) { - if ((pin >= TLE8888_SIGNALS) || (data == NULL)) + if (pin >= TLE8888_SIGNALS) return PIN_INVALID; - tle8888_priv *chip = (tle8888_priv *)data; - if (pin < TLE8888_OUTPUTS) - return tle8888_getOutputDiag(chip, pin); + return getOutputDiag(pin); else - return tle8888_getInputDiag(chip, pin); + return getInputDiag(pin); } -static int tle8888_chip_init_data(void * data) { +int Tle8888::chip_init_data() { int i; - tle8888_priv *chip = (tle8888_priv *)data; - const tle8888_config *cfg = chip->cfg; int ret = 0; - chip->o_direct_mask = 0; - chip->o_oe_mask = 0; - chip->o_pp_mask = 0; + o_direct_mask = 0; + o_oe_mask = 0; + o_pp_mask = 0; /* mark pins used */ if (cfg->reset.port != NULL) { @@ -1104,7 +1118,7 @@ static int tle8888_chip_init_data(void * data) { mask = BIT(out); /* check if output already occupied */ - if (chip->o_direct_mask & mask) { + if (o_direct_mask & mask) { /* incorrect config? */ ret = -1; goto err_gpios; @@ -1120,7 +1134,7 @@ static int tle8888_chip_init_data(void * data) { palClearPort(cfg->direct_gpio[i].port, PAL_PORT_BIT(cfg->direct_gpio[i].pad)); /* enable direct drive */ - chip->o_direct_mask |= mask; + o_direct_mask |= mask; /* calculate INCONFIG - aux input mapping for IN9..IN12 */ if (i >= 8) { @@ -1128,21 +1142,21 @@ static int tle8888_chip_init_data(void * data) { ret = -1; goto err_gpios; } - chip->InConfig[i - 8] = out - 4; + InConfig[i - 8] = out - 4; } } /* Enable Push-Pull mode for OUT21..OUT24 */ if (cfg->stepper) { - chip->o_pp_mask |= BIT(20) | BIT(21) | BIT(22) | BIT(23); + o_pp_mask |= BIT(20) | BIT(21) | BIT(22) | BIT(23); } /* enable all direct driven */ - chip->o_oe_mask |= chip->o_direct_mask; + o_oe_mask |= o_direct_mask; /* enable all ouputs * TODO: add API to enable/disable? */ - chip->o_oe_mask |= 0x0ffffff0; + o_oe_mask |= 0x0ffffff0; return 0; @@ -1163,46 +1177,40 @@ err_gpios: return ret; } -static int tle8888_init(void * data) +int Tle8888::init() { int ret; - tle8888_priv *chip; - - chip = (tle8888_priv *)data; /* check for multiple init */ - if (chip->drv_state != TLE8888_WAIT_INIT) + if (drv_state != TLE8888_WAIT_INIT) return -1; - ret = tle8888_chip_reset(chip); + ret = chip_reset(); if (ret) return ret; - ret = tle8888_chip_init_data(chip); + ret = chip_init_data(); if (ret) return ret; /* force init from driver thread */ - chip->need_init = true; + need_init = true; /* instance is ready */ - chip->drv_state = TLE8888_READY; + drv_state = TLE8888_READY; /* init semaphore */ - chSemObjectInit(&chip->wake, 10); + chSemObjectInit(&wake, 10); /* start thread */ - chip->thread = chThdCreateStatic(chip->thread_wa, sizeof(chip->thread_wa), - PRIO_GPIOCHIP, tle8888_driver_thread, chip); + thread = chThdCreateStatic(thread_wa, sizeof(thread_wa), + PRIO_GPIOCHIP, tle8888_driver_thread, this); return 0; } -static int tle8888_deinit(void *data) +int Tle8888::deinit() { - tle8888_priv *chip = (tle8888_priv *)data; - const tle8888_config *cfg = chip->cfg; - /* disable pins */ if (cfg->ign_en.port) palClearPort(cfg->ign_en.port, PAL_PORT_BIT(cfg->ign_en.pad)); @@ -1210,20 +1218,11 @@ static int tle8888_deinit(void *data) palClearPort(cfg->inj_en.port, PAL_PORT_BIT(cfg->inj_en.pad)); /* stop thread */ - chThdTerminate(chip->thread); + chThdTerminate(thread); return 0; } -struct gpiochip_ops tle8888_ops = { - .setPadMode = tle8888_setPadMode, - .writePad = tle8888_writePad, - .readPad = tle8888_readPad, - .getDiag = tle8888_getDiag, - .init = tle8888_init, - .deinit = tle8888_deinit, -}; - /** * @brief TLE8888 driver add. * @details Checks for valid config @@ -1243,10 +1242,10 @@ int tle8888_add(brain_pin_e base, unsigned int index, const tle8888_config *cfg) if (cfg->spi_config.ssport == NULL) return -1; - tle8888_priv *chip = &chips[index]; + Tle8888* chip = &chips[index]; /* already initted? */ - if (chip->cfg != NULL) + if (chip->cfg) return -1; chip->cfg = cfg; @@ -1256,7 +1255,7 @@ int tle8888_add(brain_pin_e base, unsigned int index, const tle8888_config *cfg) chip->drv_state = TLE8888_WAIT_INIT; /* register */ - int ret = gpiochip_register(base, DRIVER_NAME, &tle8888_ops, TLE8888_OUTPUTS, chip); + int ret = gpiochip_register(base, DRIVER_NAME, *chip, TLE8888_OUTPUTS); if (ret < 0) return ret; @@ -1269,19 +1268,33 @@ int tle8888_add(brain_pin_e base, unsigned int index, const tle8888_config *cfg) /*==========================================================================*/ /* Driver exported debug functions. */ /*==========================================================================*/ -void tle8888_read_reg(uint16_t reg, uint16_t *val) +void Tle8888::read_reg(uint16_t reg, uint16_t *val) { - tle8888_priv *chip = &chips[0]; - - tle8888_spi_rw(chip, CMD_R(reg), val); + spi_rw(CMD_R(reg), val); } -void tle8888_req_init(void) -{ - tle8888_priv *chip = &chips[0]; +void tle8888_req_init() { + auto& tle = chips[0]; - chip->need_init = true; - chip->init_req_cnt++; + tle.need_init = true; + tle.init_req_cnt++; +} + +void tle8888_dump_regs() { + auto& chip = chips[0]; + + // since responses are always in the NEXT transmission we will have this one first + chip.read_reg(0, NULL); + + efiPrintf("register: data"); + for (int request = 0; request <= 0x7e + 1; request++) { + uint16_t tmp; + chip.read_reg(request < (0x7e + 1) ? request : 0x7e, &tmp); + uint8_t reg = getRegisterFromResponse(tmp); + uint8_t data = getDataFromResponse(tmp); + + efiPrintf("%02x: %02x", reg, data); + } } #else /* BOARD_TLE8888_COUNT > 0 */ diff --git a/firmware/hw_layer/drivers/gpio/tle8888.h b/firmware/hw_layer/drivers/gpio/tle8888.h index fc48e7fce7..c90c09224d 100644 --- a/firmware/hw_layer/drivers/gpio/tle8888.h +++ b/firmware/hw_layer/drivers/gpio/tle8888.h @@ -56,7 +56,7 @@ struct tle8888_config { /* IN9..IN12 to output mapping */ struct { /* ...used to drive output (starts from 1, as in DS, coders gonna hate) */ - int output; + uint8_t output; } direct_maps[TLE8888_DIRECT_MISC]; struct { ioportid_t port; @@ -78,8 +78,8 @@ struct tle8888_config { int tle8888_add(brain_pin_e base, unsigned int index, const struct tle8888_config *cfg); /* debug */ -void tle8888_read_reg(uint16_t reg, uint16_t *val); -void tle8888_req_init(void); +void tle8888_req_init(); +void tle8888_dump_regs(); #if EFI_TUNER_STUDIO #include "tunerstudio_debug_struct.h" diff --git a/firmware/hw_layer/pin_repository.cpp b/firmware/hw_layer/pin_repository.cpp index f367fde2fd..15723b3463 100644 --- a/firmware/hw_layer/pin_repository.cpp +++ b/firmware/hw_layer/pin_repository.cpp @@ -69,24 +69,6 @@ PinRepository::PinRepository() { initBrainUsedPins(); } -#if (BOARD_TLE8888_COUNT > 0) -void tle8888_dump_regs(void) -{ - // since responses are always in the NEXT transmission we will have this one first - tle8888_read_reg(0, NULL); - - efiPrintf("register: data"); - for (int request = 0; request <= 0x7e + 1; request++) { - uint16_t tmp; - tle8888_read_reg(request < (0x7e + 1) ? request : 0x7e, &tmp); - uint8_t reg = getRegisterFromResponse(tmp); - uint8_t data = getDataFromResponse(tmp); - - efiPrintf("%02x: %02x", reg, data); - } -} -#endif - static void reportPins(void) { for (unsigned int i = 0; i < getBrainPinOnchipNum(); i++) { const char *pin_user = getBrainUsedPin(i); diff --git a/firmware/hw_layer/pin_repository.h b/firmware/hw_layer/pin_repository.h index 4143cee284..394701c19e 100644 --- a/firmware/hw_layer/pin_repository.h +++ b/firmware/hw_layer/pin_repository.h @@ -32,7 +32,6 @@ bool isBrainPinValid(brain_pin_e brainPin); void initPinRepository(void); EXTERNC bool brain_pin_is_onchip(brain_pin_e brainPin); EXTERNC bool brain_pin_is_ext(brain_pin_e brainPin); -EXTERNC void tle8888_dump_regs(void); /** * Usually high-level code would invoke efiSetPadMode, not this method directly diff --git a/unit_tests/tests/test_gpiochip.cpp b/unit_tests/tests/test_gpiochip.cpp index 21aa170c53..ad708bb731 100644 --- a/unit_tests/tests/test_gpiochip.cpp +++ b/unit_tests/tests/test_gpiochip.cpp @@ -10,85 +10,53 @@ using ::testing::_; -static int testchip_readPad(void *data, unsigned int pin) -{ - if (pin & 0x01) - return 1; - return 0; -} - static int io_state = 0; -static int testchip_writePad(void *data, unsigned int pin, int value) -{ - if (value) - io_state |= (1 << value); - else - io_state &= ~(1 << value); - - return 0; -} - static int initcalls = 0; +struct GoodChip : public GpioChip { + int init() override { + initcalls++; + return 0; + } +}; -static int testchip_init(void *data) -{ - initcalls++; +class TestChip1 : public GoodChip { + int readPad(size_t pin) override { + if (pin & 0x01) + return 1; + return 0; + } +}; - return 0; -} +static TestChip1 testchip1; + +class TestChip2 : public GoodChip { + int writePad(size_t pin, int value) override { + if (value) + io_state |= (1 << value); + else + io_state &= ~(1 << value); + + return 0; + } +}; + +static TestChip2 testchip2; static int calls_to_failed_chip = 0; -static int testchip_failed_writePad(void *data, unsigned int pin, int value) -{ - calls_to_failed_chip++; - return 0; -} +// This chip fails to start +class TestChip3 : public GpioChip { + int writePad(size_t pin, int value) override { + calls_to_failed_chip++; + return 0; + } -static int testchip_failed_init(void *data) -{ - return -1; -} - -/* invalid chip */ -struct gpiochip_ops testchip0 = { - /*.setPadMode =*/ NULL, - /*.writePad =*/ NULL, - /*.readPad =*/ NULL, - /*.getDiag =*/ NULL, - /*.init =*/ testchip_init, - /*.deinit =*/ NULL, + int init() override { + return -1; + } }; -/* Input only chip */ -struct gpiochip_ops testchip1 = { - /*.setPadMode =*/ NULL, - /*.writePad =*/ NULL, - /*.readPad =*/ testchip_readPad, - /*.getDiag =*/ NULL, - /*.init =*/ testchip_init, - /*.deinit =*/ NULL, -}; - -/* Input only chip */ -struct gpiochip_ops testchip2 = { - /*.setPadMode =*/ NULL, - /*.writePad =*/ testchip_writePad, - /*.readPad =*/ NULL, - /*.getDiag =*/ NULL, - /*.init =*/ testchip_init, - /*.deinit =*/ NULL, -}; - -/* testchi[ failed to init */ -struct gpiochip_ops testchip3 = { - /*.setPadMode =*/ NULL, - /*.writePad =*/ testchip_failed_writePad, - /*.readPad =*/ NULL, - /*.getDiag =*/ NULL, - /*.init =*/ testchip_failed_init, - /*.deinit =*/ NULL, -}; +static TestChip3 testchip3; TEST(gpioext, testGpioExt) { int ret; @@ -96,28 +64,25 @@ TEST(gpioext, testGpioExt) { printf("====================================================================================== testGpioExt\r\n"); - /* should fail to register chip with no readPad and writePad */ - EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1), "invalid", &testchip0, 16, NULL) > 0); - /* should fail to register chip with zero gpios */ - EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1), "invalid", &testchip1, 0, NULL) > 0); + EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1), "invalid", testchip1, 0) > 0); /* should fail to register chip with base overlapig on-chip gpios */ - EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST - 1), "invalid", &testchip1, 0, NULL) > 0); + EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST - 1), "invalid", testchip1, 0) > 0); - chip1_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1), "input only", &testchip1, 16, NULL); + chip1_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1), "input only", testchip1, 16); EXPECT_TRUE(chip1_base > 0); EXPECT_EQ(16, gpiochips_get_total_pins()); /* should fail to register chip overlapping other one */ - EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 15), "output only", &testchip2, 16, NULL) > 0); + EXPECT_FALSE(gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 15), "output only", testchip2, 16) > 0); - chip2_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 16), "output only", &testchip2, 16, NULL); + chip2_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 16), "output only", testchip2, 16); EXPECT_TRUE(chip2_base > 0); /* this chip will fail to init, but should be registered without errors */ - chip3_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 16 + 16), "failed chip", &testchip3, 16, NULL); + chip3_base = gpiochip_register((brain_pin_e)(BRAIN_PIN_ONCHIP_LAST + 1 + 16 + 16), "failed chip", testchip3, 16); EXPECT_TRUE(chip2_base > 0); EXPECT_EQ(48, gpiochips_get_total_pins());