28 #if defined(BOARD_TLE6240_COUNT) && (BOARD_TLE6240_COUNT > 0)
47 #define DRIVER_NAME "tle6240"
59 #define CMD_CHIP(ch) ((ch < 8) ? 0x00 : 0x0f)
61 #define CMD_FULL_DIAG(ch) (((0x00 | CMD_CHIP(ch)) << 8) | 0x00)
63 #define CMD_IO_SHORTDIAG(ch) (((0xc0 | CMD_CHIP(ch)) << 8) | 0x00)
65 #define CMD_ECHO(ch) (((0xA0 | CMD_CHIP(ch)) << 8) | 0x00)
67 #define CMD_OR_DIAG(ch, data) (((0x30 | CMD_CHIP(ch)) << 8) | (data & 0xff))
69 #define CMD_AND_DIAG(ch, data) (((0xf0 | CMD_CHIP(ch)) << 8) | (data & 0xff))
87 int writePad(
size_t pin,
int value)
override;
92 int spi_rw(uint16_t tx, uint16_t *rx);
93 int update_output_and_diag();
99 uint16_t o_state_cached;
103 uint16_t o_direct_mask;
108 bool diag_8_reguested;
113 static Tle6240
chips[BOARD_TLE6240_COUNT];
116 "tle6240.OUT1",
"tle6240.OUT2",
"tle6240.OUT3",
"tle6240.OUT4",
117 "tle6240.OUT5",
"tle6240.OUT6",
"tle6240.OUT7",
"tle6240.OUT8",
118 "tle6240.OUT9",
"tle6240.OUT10",
"tle6240.OUT11",
"tle6240.OUT12",
119 "tle6240.OUT13",
"tle6240.OUT14",
"tle6240.OUT15",
"tle6240.OUT16",
132 int Tle6240::spi_rw(uint16_t tx, uint16_t *rx)
135 SPIDriver *
spi = cfg->spi_bus;
140 spiStart(
spi, &cfg->spi_config);
144 rxb = spiPolledExchange(
spi, tx);
162 int Tle6240::update_output_and_diag()
169 out_data = o_state & (~o_direct_mask);
170 if (diag_8_reguested) {
172 ret = spi_rw(CMD_OR_DIAG(0, (out_data >> 0) & 0xff), &diag[1]);
173 ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[0]);
175 ret = spi_rw(CMD_OR_DIAG(0, (out_data >> 0) & 0xff), NULL);
176 ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[0]);
178 ret |= spi_rw(CMD_OR_DIAG(8, (out_data >> 8) & 0xff), &diag[1]);
181 diag_8_reguested =
false;
184 o_state_cached = out_data;
185 diag_8_reguested =
true;
198 int Tle6240::chip_init()
207 if (cfg->reset.port != NULL)
209 for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++)
210 if (cfg->direct_io[n].port)
211 ret |=
gpio_pin_markUsed(cfg->direct_io[n].port, cfg->direct_io[n].pad, DRIVER_NAME
" DIRECT IO");
219 if (cfg->reset.port) {
220 palClearPort(cfg->reset.port,
221 PAL_PORT_BIT(cfg->reset.pad));
222 chThdSleepMilliseconds(1);
223 palSetPort(cfg->reset.port,
224 PAL_PORT_BIT(cfg->reset.pad));
225 chThdSleepMilliseconds(10);
230 ret = spi_rw(CMD_ECHO(0),
nullptr);
232 ret |= spi_rw(0x5555, &rx);
233 if (ret || (rx != 0x5555)) {
241 for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++) {
242 int i = (n < 4) ? n : (n + 4);
243 if (o_direct_mask & (1 << i)) {
244 palClearPort(cfg->direct_io[n].port,
245 PAL_PORT_BIT(cfg->direct_io[n].pad));
250 ret = spi_rw(CMD_AND_DIAG(0, 0x00), NULL);
252 ret |= spi_rw(CMD_AND_DIAG(8, 0x00), &diag[0]);
254 ret |= spi_rw(CMD_IO_SHORTDIAG(0), &diag[1]);
257 ret |= spi_rw(CMD_IO_SHORTDIAG(0), &rx);
258 rx = ((rx >> 4) & 0x0f00) | ((rx >> 8) & 0x000f);
259 if (ret || (rx & o_direct_mask)) {
266 for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++) {
267 int i = (n < 4) ? n : (n + 4);
268 if (o_direct_mask & (1 << i)) {
269 palSetPort(cfg->direct_io[n].port,
270 PAL_PORT_BIT(cfg->direct_io[n].pad));
274 ret |= spi_rw(CMD_IO_SHORTDIAG(0), &rx);
275 rx = ((rx >> 4) & 0x0f00) | ((rx >> 8) & 0x000f);
277 if (ret || (rx != o_direct_mask)) {
284 ret = update_output_and_diag();
296 if (cfg->reset.port != NULL)
298 for (n = 0; n < TLE6240_DIRECT_OUTPUTS; n++)
299 if (cfg->direct_io[n].port)
314 chibios_rt::CriticalSectionLocker csl;
316 chSemSignalI(&tle6240_wake);
317 if (!port_is_isr_context()) {
339 chRegSetThreadName(DRIVER_NAME);
342 msg = chSemWaitTimeout(&tle6240_wake, TIME_MS2I(TLE6240_POLL_INTERVAL_MS));
347 for (i = 0; i < BOARD_TLE6240_COUNT; i++) {
349 Tle6240& chip =
chips[i];
356 ret = chip.update_output_and_diag();
376 if (pin >= TLE6240_OUTPUTS)
380 chibios_rt::CriticalSectionLocker csl;
383 o_state |= (1 << pin);
385 o_state &= ~(1 << pin);
389 if (o_direct_mask & (1 << pin)) {
390 int n = (pin < 8) ? pin : (pin - 4);
394 palSetPort(cfg->direct_io[n].port,
395 PAL_PORT_BIT(cfg->direct_io[n].pad));
397 palClearPort(cfg->direct_io[n].port,
398 PAL_PORT_BIT(cfg->direct_io[n].pad));
411 if (pin >= TLE6240_OUTPUTS)
414 val = (diag[(pin > 7) ? 1 : 0] >> ((pin % 8) * 2)) & 0x03;
419 diagVal = PIN_OVERLOAD | PIN_DRIVER_OVERTEMP;
423 diagVal = PIN_SHORT_TO_GND;
430 int ret = chip_init();
437 chThdCreateStatic(tle6240_thread_1_wa,
sizeof(tle6240_thread_1_wa),
438 PRIO_GPIOCHIP, tle6240_driver_thread,
nullptr);
457 if ((!cfg) || (!cfg->
spi_bus) || (index >= BOARD_TLE6240_COUNT))
465 chip = &
chips[index];
468 if (chip->cfg != NULL)
473 chip->o_state_cached = 0;
474 chip->o_direct_mask = 0;
476 for (i = 0; i < TLE6240_DIRECT_OUTPUTS; i++) {
478 chip->o_direct_mask |= (1 << ((i < 4) ? i : (i + 4)));
496 (void)base; (void)index; (void)cfg;
int gpiochip_register(brain_pin_e base, const char *name, GpioChip &gpioChip, size_t size)
Register gpiochip.
int gpiochips_setPinNames(brain_pin_e base, const char **names)
Set pins names for registered gpiochip.
void writePad(const char *msg, brain_pin_e pin, int bit)
void gpio_pin_markUnused(ioportid_t port, ioportmask_t pin)
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)
struct tle6240_config::@37 direct_io[TLE6240_DIRECT_OUTPUTS]
int tle6240_add(brain_pin_e base, unsigned int index, const tle6240_config *cfg)
TLE6240 driver add.
static bool drv_task_ready
SEMAPHORE_DECL(tle6240_wake, 10)
static THD_WORKING_AREA(tle6240_thread_1_wa, 256)
static int tle6240_wake_driver()
TLE6240 chip driver wakeup.
static Tle6240 chips[BOARD_TLE6240_COUNT]
static const char * tle6240_pin_names[TLE6240_OUTPUTS]
static THD_FUNCTION(tle6240_driver_thread, p)