rusefi/firmware/hw_layer/smart_gpio.cpp

290 lines
8.2 KiB
C++
Raw Normal View History

2019-04-13 07:58:52 -07:00
/*
* @file smart_gpio.cpp
*
* @date Apr 13, 2019
2020-01-07 21:02:40 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2019-04-13 07:58:52 -07:00
*/
#include "global.h"
2019-04-13 08:22:40 -07:00
#if EFI_PROD_CODE
2019-04-13 07:58:52 -07:00
#include "smart_gpio.h"
#include "efi_gpio.h"
#include "engine_configuration.h"
#include "hardware.h"
#include "mpu_util.h"
2019-04-13 07:58:52 -07:00
#include "gpio_ext.h"
#include "pin_repository.h"
2019-04-13 07:58:52 -07:00
#include "drivers/gpio/tle6240.h"
#include "drivers/gpio/mc33972.h"
#include "drivers/gpio/mc33810.h"
2019-04-13 07:58:52 -07:00
#include "drivers/gpio/tle8888.h"
2020-09-09 14:16:51 -07:00
#include "drivers/gpio/drv8860.h"
2019-04-13 07:58:52 -07:00
EXTERN_CONFIG;
static OutputPin tle8888Cs;
static OutputPin tle6240Cs;
static OutputPin mc33972Cs;
2020-09-09 14:16:51 -07:00
static OutputPin drv8860Cs;
2019-04-13 07:58:52 -07:00
// todo: migrate to TS or board config
#ifndef TLE6240_RESET_PORT
#define TLE6240_RESET_PORT GPIOG
#endif /* TLE6240_RESET_PORT */
#ifndef TLE6240_RESET_PAD
#define TLE6240_RESET_PAD 3U
#endif /* TLE6240_RESET_PAD */
#ifndef TLE6240_DIRECT_IO
#define TLE6240_DIRECT_IO \
/* IN1 - D_TACH_OUT */ \
[0] = {.port = GPIOG, .pad = 2}, \
/* IN2..4 grounded */ \
[1] = {.port = NULL, .pad = 0}, \
[2] = {.port = NULL, .pad = 0}, \
[3] = {.port = NULL, .pad = 0}, \
/* IN9 - D_INJ_5 */ \
[4] = {.port = GPIOD, .pad = 15}, \
/* IN10 - D_WASTGATE */ \
[5] = {.port = GPIOD, .pad = 14}, \
/* IN11 - D_IDLE_OPEN */ \
[6] = {.port = GPIOC, .pad = 6}, \
/* IN12 - D_IDLE_CLOSE */ \
[7] = {.port = GPIOC, .pad = 7},
#endif /* TLE6240_DIRECT_IO */
2019-04-13 08:22:40 -07:00
#if (BOARD_TLE6240_COUNT > 0)
struct tle6240_config tle6240 = {
2019-04-13 07:58:52 -07:00
.spi_bus = NULL /* TODO software lookup &SPID4 */,
.spi_config = {
.circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
2019-04-13 07:58:52 -07:00
.cr1 =
SPI_CR1_16BIT_MODE |
2019-04-13 07:58:52 -07:00
SPI_CR1_SSM |
SPI_CR1_SSI |
/* SPI_CR1_LSBFIRST | */
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
SPI_CR1_MSTR |
/* SPI_CR1_CPOL | */ // = 0
SPI_CR1_CPHA | // = 1
0,
.cr2 = SPI_CR2_16BIT_MODE
},
.direct_io = {
TLE6240_DIRECT_IO
2019-04-13 07:58:52 -07:00
},
.reset = {.port = TLE6240_RESET_PORT, .pad = TLE6240_RESET_PAD}
2019-04-13 07:58:52 -07:00
};
2019-04-13 08:22:40 -07:00
#endif /* (BOARD_TLE6240_COUNT > 0) */
2019-04-13 07:58:52 -07:00
2019-04-13 08:22:40 -07:00
#if (BOARD_MC33972_COUNT > 0)
struct mc33972_config mc33972 = {
2019-04-13 07:58:52 -07:00
.spi_bus = NULL /* TODO software lookup &SPID4 */,
.spi_config = {
.circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
2019-04-13 07:58:52 -07:00
.cr1 =
SPI_CR1_24BIT_MODE |
2019-04-13 07:58:52 -07:00
SPI_CR1_SSM |
SPI_CR1_SSI |
/* SPI_CR1_LSBFIRST | */
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 16 */
SPI_CR1_MSTR |
/* SPI_CR1_CPOL | */ /* = 0 */
SPI_CR1_CPHA | /* = 1 */
0,
.cr2 = SPI_CR2_24BIT_MODE
},
};
2019-04-13 08:22:40 -07:00
#endif /* (BOARD_MC33972_COUNT > 0) */
2019-04-13 07:58:52 -07:00
#if (BOARD_TLE8888_COUNT > 0)
struct tle8888_config tle8888_cfg = {
.spi_bus = NULL,
.spi_config = {
.circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
.cr1 =
SPI_CR1_16BIT_MODE |
SPI_CR1_SSM |
SPI_CR1_SSI |
SPI_CR1_LSBFIRST | //LSB first
((3 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | // div = 16
SPI_CR1_MSTR |
SPI_CR1_CPHA |
0,
.cr2 = SPI_CR2_16BIT_MODE
},
.reset = {.port = NULL, .pad = 0},
.direct_io = {
[0] = {.port = GPIOE, .pad = 10, .output = 5},
[1] = {.port = GPIOE, .pad = 9, .output = 6},
[2] = {.port = GPIOE, .pad = 8, .output = 21},
[3] = {.port = NULL, .pad = 0, .output = 15},
// [3] = {.port = GPIOE, .pad = 7, .output = 22},
/*
[0] = {.port = NULL, .pad = 0, .output = 9},
[1] = {.port = NULL, .pad = 0, .output = 10},
[2] = {.port = NULL, .pad = 0, .output = 11},
[3] = {.port = NULL, .pad = 0, .output = 12},
*/
},
.ign_en = {.port = GPIOD, .pad = 10},
.inj_en = {.port = GPIOD, .pad = 11},
2020-04-23 16:49:22 -07:00
.mode = TL_AUTO,
};
#endif
2020-09-09 14:16:51 -07:00
#if (BOARD_DRV8860_COUNT > 0)
struct drv8860_config drv8860 = {
.spi_bus = NULL /* TODO software lookup &SPID4 */,
.spi_config = {
.circular = false,
.end_cb = NULL,
.ssport = NULL,
.sspad = 0,
.cr1 =
SPI_CR1_16BIT_MODE |
SPI_CR1_SSM |
SPI_CR1_SSI |
((7 << SPI_CR1_BR_Pos) & SPI_CR1_BR) | /* div = 32 */
SPI_CR1_MSTR |
SPI_CR1_CPOL |
0,
.cr2 = SPI_CR2_16BIT_MODE
},
.reset = {.port = DRV8860_RESET_PORT, .pad = DRV8860_RESET_PAD}
};
#endif /* (BOARD_DRV8860_COUNT > 0) */
2019-04-13 07:58:52 -07:00
void initSmartGpio() {
2020-09-09 14:16:51 -07:00
#if (BOARD_EXT_GPIOCHIPS > 0)
startSmartCsPins();
2020-09-09 14:16:51 -07:00
#endif /* BOARD_EXT_GPIOCHIPS */
int ret = -1;
2019-04-13 07:58:52 -07:00
#if (BOARD_TLE6240_COUNT > 0)
if (engineConfiguration->tle6240_cs != GPIO_UNASSIGNED) {
tle6240.spi_config.ssport = getHwPort("tle6240 CS", engineConfiguration->tle6240_cs);
tle6240.spi_config.sspad = getHwPin("tle6240 CS", engineConfiguration->tle6240_cs);
tle6240.spi_bus = getSpiDevice(engineConfiguration->tle6240spiDevice);
ret = tle6240_add(0, &tle6240);
} else {
ret = -1;
}
if (ret < 0)
/* whenever chip is disabled or error returned - occupy its gpio range */
gpiochip_use_gpio_base(TLE6240_OUTPUTS);
2020-09-09 14:16:51 -07:00
#endif /* (BOARD_TLE6240_COUNT > 0) */
2019-04-13 07:58:52 -07:00
#if (BOARD_MC33972_COUNT > 0)
if (engineConfiguration->mc33972_cs != GPIO_UNASSIGNED) {
// todo: reuse initSpiCs method?
mc33972.spi_config.ssport = getHwPort("mc33972 CS", engineConfiguration->mc33972_cs);
mc33972.spi_config.sspad = getHwPin("mc33972 CS", engineConfiguration->mc33972_cs);
mc33972.spi_bus = getSpiDevice(engineConfiguration->mc33972spiDevice);
// todo: propogate 'basePinOffset' parameter
ret = mc33972_add(0, &mc33972);
} else {
ret = -1;
}
if (ret < 0)
/* whenever chip is disabled or error returned - occupy its gpio range */
gpiochip_use_gpio_base(MC33972_INPUTS);
2020-09-09 14:16:51 -07:00
#endif /* (BOARD_MC33972_COUNT > 0) */
2019-04-13 07:58:52 -07:00
2019-04-13 09:02:34 -07:00
#if (BOARD_TLE8888_COUNT > 0)
2019-04-13 07:58:52 -07:00
if (engineConfiguration->tle8888_cs != GPIO_UNASSIGNED) {
// SPI pins are enabled in initSpiModules()
2019-04-13 07:58:52 -07:00
// todo: reuse initSpiCs method?
tle8888_cfg.spi_config.ssport = getHwPort("tle8888 CS", engineConfiguration->tle8888_cs);
tle8888_cfg.spi_config.sspad = getHwPin("tle8888 CS", engineConfiguration->tle8888_cs);
tle8888_cfg.spi_bus = getSpiDevice(engineConfiguration->tle8888spiDevice);
2020-04-23 13:57:37 -07:00
tle8888_cfg.mode = engineConfiguration->tle8888mode;
/* spi_bus == null checked in _add function */
ret = tle8888_add(0, &tle8888_cfg);
efiAssertVoid(OBD_PCM_Processor_Fault, ret == TLE8888_PIN_1, "tle8888");
2019-04-19 03:07:40 -07:00
} else {
ret = -1;
}
if (ret < 0)
/* whenever chip is disabled or error returned - occupy its gpio range */
gpiochip_use_gpio_base(TLE8888_OUTPUTS);
2020-09-09 14:16:51 -07:00
#endif /* (BOARD_TLE8888_COUNT > 0) */
#if (BOARD_DRV8860_COUNT > 0)
if (engineConfiguration->drv8860_cs != GPIO_UNASSIGNED) {
drv8860.spi_config.ssport = getHwPort("drv8860 CS", engineConfiguration->drv8860_cs);
drv8860.spi_config.sspad = getHwPin("drv8860 CS", engineConfiguration->drv8860_cs);
drv8860.spi_bus = getSpiDevice(engineConfiguration->drv8860spiDevice);
ret = drv8860_add(0, &drv8860);
efiAssertVoid(OBD_PCM_Processor_Fault, ret == DRV8860_PIN_1, "drv8860");
} else {
ret = -1;
}
if (ret < 0)
/* whenever chip is disabled or error returned - occupy its gpio range */
gpiochip_use_gpio_base(DRV8860_OUTPUTS);
#endif /* (BOARD_DRV8860_COUNT > 0) */
#if (BOARD_EXT_GPIOCHIPS > 0)
/* external chip init */
gpiochips_init();
#endif /* (BOARD_EXT_GPIOCHIPS > 0) */
}
#if (BOARD_EXT_GPIOCHIPS > 0)
void stopSmartCsPins() {
#if (BOARD_TLE8888_COUNT > 0)
brain_pin_markUnused(activeConfiguration.tle8888_cs);
#endif /* BOARD_TLE8888_COUNT */
#if (BOARD_TLE6240_COUNT > 0)
brain_pin_markUnused(activeConfiguration.tle6240_cs);
#endif /* BOARD_TLE6240_COUNT */
#if (BOARD_MC33972_COUNT > 0)
brain_pin_markUnused(activeConfiguration.mc33972_cs);
#endif /* BOARD_MC33972_COUNT */
2020-09-09 14:16:51 -07:00
#if (BOARD_DRV8860_COUNT > 0)
brain_pin_markUnused(activeConfiguration.drv8860_cs);
#endif /* BOARD_DRV8860_COUNT */
}
void startSmartCsPins() {
#if (BOARD_TLE8888_COUNT > 0)
tle8888Cs.initPin("tle8888 CS", engineConfiguration->tle8888_cs,
&engineConfiguration->tle8888_csPinMode);
tle8888Cs.setValue(true);
#endif /* BOARD_TLE8888_COUNT */
#if (BOARD_TLE6240_COUNT > 0)
tle6240Cs.initPin("tle6240 CS", engineConfiguration->tle6240_cs,
&engineConfiguration->tle6240_csPinMode);
tle6240Cs.setValue(true);
#endif /* BOARD_TLE6240_COUNT */
#if (BOARD_MC33972_COUNT > 0)
mc33972Cs.initPin("mc33972 CS", engineConfiguration->mc33972_cs,
&engineConfiguration->mc33972_csPinMode);
mc33972Cs.setValue(true);
#endif /* BOARD_MC33972_COUNT */
2020-09-09 14:16:51 -07:00
#if (BOARD_DRV8860_COUNT > 0)
drv8860Cs.initPin("drv8860 CS", engineConfiguration->drv8860_cs,
&engineConfiguration->drv8860_csPinMode);
drv8860Cs.setValue(true);
#endif /* BOARD_DRV8860_COUNT */
2019-04-13 07:58:52 -07:00
}
#endif /* (BOARD_EXT_GPIOCHIPS > 0) */
2019-04-13 08:22:40 -07:00
#endif /* EFI_PROD_CODE */