17#if EFI_PROD_CODE && (BOARD_TLE9201_COUNT > 0)
23#define DRIVER_NAME "tle9201"
25#define TLE9201_REG_RD_DIA 0x00
26#define TLE9201_REG_RES_DIA 0x80
27#define TLE9201_REG_RD_REV 0x20
28#define TLE9201_REG_RD_CTRL 0x60
29#define TLE9201_REG_WR_CTRL 0xE0
30#define TLE9201_REG_WR_CTRL_RD_DIA 0xC0
32#define TLE9201_REV_MAJOR_MASK 0xF0
33#define TLE9201_REV_MAJOR 0x20
35#define TLE9201_DIAG_CL (1<<4)
36#define TLE9201_DIAG_TV (1<<5)
37#define TLE9201_DIAG_OT (1<<6)
38#define TLE9201_DIAG_EN (1<<7)
39#define TLE9201_DIAG_OUT_MASK 0xf
41#define TLE9201_GET_VAL(rx) ((rx) & 0xff)
66 "Short to Bat at OUT1 and OUT2",
67 "Short to GND at OUT1, short to Bat at OUT2",
68 "Short to Bat at OUT2",
70 "Short to Bat at OUT1, short to GND at OUT2",
71 "Short to GND at OUT1 and OUT2",
72 "Short to GND at OUT2",
73 DRIVER_NAME
" Open Load",
74 "Short to Bat at OUT1",
75 "Short to GND at OUT1",
87 int spi_rw(uint16_t tx, uint16_t *rx);
88 int read_reg(uint8_t
addr, uint8_t *val);
90 bool get_diag_and_rev(uint8_t *diag, uint8_t *rev);
91 void process_diag_and_rev(uint8_t diag, uint8_t rev);
98 uint8_t savedDiag = 0;
102static Tle9201
chips[BOARD_TLE9201_COUNT];
112int Tle9201::spi_rw(uint16_t tx, uint16_t *rx) {
118 spiStart(spi, &cfg->spi_config);
122 uint16_t rxd = spiPolledExchange(spi, tx);
136int Tle9201::read_reg(uint8_t
addr, uint8_t *val) {
139 ret = spi_rw(
addr,
nullptr);
145 ret = spi_rw(
addr, &rxd);
151 *val = TLE9201_GET_VAL(rxd);
157bool Tle9201::get_diag_and_rev(uint8_t *diag, uint8_t *rev) {
158 int retDiag = read_reg(TLE9201_REG_RD_DIA, diag);
159 int retRev = read_reg(TLE9201_REG_RD_REV, rev);
160 return (retDiag == 0 && retRev == 0);
163void Tle9201::process_diag_and_rev(uint8_t diag, uint8_t rev) {
165 if (rev != detectedRev) {
166 if ((rev & TLE9201_REV_MAJOR_MASK) == TLE9201_REV_MAJOR) {
167 efiPrintf(
"%s Detected! (rev=%08x)", name, rev);
169 efiPrintf(
"%s ERROR: Unknown revision (%08x)!", name, rev);
176 if (diag != savedDiag) {
177 efiPrintf(
"%s Diag (%08x):", name, diag);
179 if (diag & TLE9201_DIAG_TV) {
180 efiPrintf(
"* Diag status incorrect!");
183 if (!(diag & TLE9201_DIAG_CL)) {
184 efiPrintf(
"* Overcurrent shutdown!");
186 if (!(diag & TLE9201_DIAG_OT)) {
187 efiPrintf(
"* Overtemperature shutdown!");
189 if (!(diag & TLE9201_DIAG_EN)) {
190 efiPrintf(
"* Outputs disabled.");
192 size_t statusCode = diag & TLE9201_DIAG_OUT_MASK;
208 bool wasSpiFailure =
false;
212 chRegSetThreadName(DRIVER_NAME);
215 chThdSleepMilliseconds(TLE9201_POLL_INTERVAL_MS);
217static bool isInitialized =
false;
221 efiPrintf(
"Power loss? Would have to re-init TLE9201?");
222 isInitialized =
false;
228 for (
int i = 0; i < BOARD_TLE9201_COUNT; i++) {
229 auto chip = &
chips[i];
230 if ((chip->cfg == NULL) ||
238 if (!chip->get_diag_and_rev(&diag, &rev)) {
239 if (!wasSpiFailure) {
240 efiPrintf(
"%s ERROR: SPI failure!", chip->name);
241 wasSpiFailure =
true;
244 wasSpiFailure =
false;
247 chip->process_diag_and_rev(diag, rev);
260int Tle9201::init(
int i) {
263 sprintf(name,
"TLE9201[%d]", idx);
266 chThdCreateStatic(tle9201_thread_1_wa,
sizeof(tle9201_thread_1_wa),
267 PRIO_GPIOCHIP, tle9201_driver_thread, NULL);
281 if ((!cfg) || (!cfg->
spi_bus) || (index >= BOARD_TLE9201_COUNT)) {
287 auto chip = &
chips[0];
288 chip->spi_rw(TLE9201_REG_RES_DIA,
nullptr);
289 efiPrintf(DRIVER_NAME
"reset!");
298 auto& chip =
chips[index];
301 if (chip.cfg != NULL)
313 (void)index; (void)cfg;
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
int tle9201_add(unsigned int index, const tle9201_config *cfg)
TLE9201 driver add.
static bool drv_task_ready
static THD_WORKING_AREA(tle9201_thread_1_wa, 256)
static Tle9201 chips[BOARD_TLE9201_COUNT]
static THD_FUNCTION(tle9201_driver_thread, p)
static const char * diagDiaOut[16]
static size_t diagOkCounter
SEMAPHORE_DECL(tle9201_wake, 10)