Gpiochips integration (#740)

* gpio-chips core function renames

* efi_gpio, pin_repository: add support for external gpios

* gpio-chips update

* gpio-chips: add api to name each pin of gpiochip

* tle6240: provide individual names for each pin
This commit is contained in:
dron0gus 2019-04-10 15:43:54 +03:00 committed by rusefi
parent 4011372da8
commit 551f2f5883
8 changed files with 252 additions and 74 deletions

View File

@ -7,6 +7,7 @@
#include "global.h" #include "global.h"
#include "rusefi_enums.h" #include "rusefi_enums.h"
#include "drivers/gpio/gpio_ext.h"
const char *getEngine_type_e(engine_type_e value){ const char *getEngine_type_e(engine_type_e value){
switch(value) { switch(value) {
case ACURA_RSX: case ACURA_RSX:
@ -805,6 +806,11 @@ case GPIOH_8:
return "GPIOH_8"; return "GPIOH_8";
case GPIOH_9: case GPIOH_9:
return "GPIOH_9"; return "GPIOH_9";
#if (BOARD_EXT_GPIOCHIPS > 0)
default:
/* gpichips */
return gpiochips_getPinName(value);
#endif
} }
return NULL; return NULL;
} }

View File

@ -9,6 +9,7 @@
#include "global.h" #include "global.h"
#include "engine.h" #include "engine.h"
#include "efi_gpio.h" #include "efi_gpio.h"
#include "drivers/gpio/gpio_ext.h"
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__) #if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
#include "pin_repository.h" #include "pin_repository.h"
@ -68,7 +69,17 @@ EnginePins::EnginePins() {
(outputPin)->currentLogicValue = (logicValue); \ (outputPin)->currentLogicValue = (logicValue); \
} \ } \
} }
#define gpiochip_setPinValue(outputPin, electricalValue, logicValue) \
{ \
if ((outputPin)->currentLogicValue != (logicValue)) { \
gpiochips_writePad((outputPin)->brainPin, (electricalValue)); \
(outputPin)->currentLogicValue = (logicValue); \
} \
}
#else /* EFI_PROD_CODE */ #else /* EFI_PROD_CODE */
#define setPinValue(outputPin, electricalValue, logicValue) \ #define setPinValue(outputPin, electricalValue, logicValue) \
{ \ { \
if ((outputPin)->currentLogicValue != (logicValue)) { \ if ((outputPin)->currentLogicValue != (logicValue)) { \
@ -295,13 +306,26 @@ void OutputPin::toggle() {
} }
void OutputPin::setValue(int logicValue) { void OutputPin::setValue(int logicValue) {
#if EFI_PROD_CODE #if EFI_PROD_CODE
if (port != GPIO_NULL) { efiAssertVoid(CUSTOM_ERR_6621, modePtr!=NULL, "pin mode not initialized");
efiAssertVoid(CUSTOM_ERR_6621, modePtr!=NULL, "pin mode not initialized"); pin_output_mode_e mode = *modePtr;
pin_output_mode_e mode = *modePtr; efiAssertVoid(CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e");
efiAssertVoid(CUSTOM_ERR_6622, mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e"); int eValue = getElectricalValue(logicValue, mode);
int eValue = getElectricalValue(logicValue, mode);
setPinValue(this, eValue, logicValue); #if (BOARD_EXT_GPIOCHIPS > 0)
} if (!this->ext) {
/* onchip pin */
if (port != GPIO_NULL) {
setPinValue(this, eValue, logicValue);
}
} else {
/* external pin */
gpiochip_setPinValue(this, this->brainPin, logicValue);
}
#else
if (port != GPIO_NULL) {
setPinValue(this, eValue, logicValue);
}
#endif
#else /* EFI_PROD_CODE */ #else /* EFI_PROD_CODE */
setPinValue(this, eValue, logicValue); setPinValue(this, eValue, logicValue);
@ -381,37 +405,50 @@ void OutputPin::initPin(const char *msg, brain_pin_e brainPin, const pin_output_
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__) #if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
if (brainPin == GPIO_UNASSIGNED) if (brainPin == GPIO_UNASSIGNED)
return; return;
ioportid_t port = getHwPort(msg, brainPin);
int pin = getHwPin(msg, brainPin);
/**
* This method is used for digital GPIO pins only, for peripheral pins see mySetPadMode
*/
if (port == GPIO_NULL) {
// that's for GRIO_NONE
this->port = port;
return;
}
assertOMode(*outputMode); assertOMode(*outputMode);
iomode_t mode = (*outputMode == OM_DEFAULT || *outputMode == OM_INVERTED) ? iomode_t mode = (*outputMode == OM_DEFAULT || *outputMode == OM_INVERTED) ?
PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN; PAL_MODE_OUTPUT_PUSHPULL : PAL_MODE_OUTPUT_OPENDRAIN;
/** #if (BOARD_EXT_GPIOCHIPS > 0)
* @brief Initialize the hardware output pin while also assigning it a logical name this->ext = false;
*/ #endif
if (this->port != NULL && (this->port != port || this->pin != pin)) { if (brain_pin_is_onchip(brainPin)) {
ioportid_t port = getHwPort(msg, brainPin);
int pin = getHwPin(msg, brainPin);
/** /**
* here we check if another physical pin is already assigned to this logical output * This method is used for digital GPIO pins only, for peripheral pins see mySetPadMode
*/ */
// todo: need to clear '&outputs' in io_pins.c if (port == GPIO_NULL) {
warning(CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned to %x%d", msg, this->port, this->pin); // that's for GRIO_NONE
engine->withError = true; this->port = port;
return; return;
}
/**
* @brief Initialize the hardware output pin while also assigning it a logical name
*/
if (this->port != NULL && (this->port != port || this->pin != pin)) {
/**
* here we check if another physical pin is already assigned to this logical output
*/
// todo: need to clear '&outputs' in io_pins.c
warning(CUSTOM_OBD_PIN_CONFLICT, "outputPin [%s] already assigned to %x%d", msg, this->port, this->pin);
engine->withError = true;
return;
}
this->port = port;
this->pin = pin;
} }
#if (BOARD_EXT_GPIOCHIPS > 0)
else {
this->ext = true;
this->brainPin = brainPin;
}
#endif
this->currentLogicValue = INITIAL_PIN_STATE; this->currentLogicValue = INITIAL_PIN_STATE;
this->port = port;
this->pin = pin;
efiSetPadMode(msg, brainPin, mode); efiSetPadMode(msg, brainPin, mode);
@ -492,5 +529,3 @@ const char *hwPortname(brain_pin_e brainPin) {
return "N/A"; return "N/A";
} }
#endif /* EFI_GPIO_HARDWARE */ #endif /* EFI_GPIO_HARDWARE */

View File

@ -51,6 +51,11 @@ public:
#if EFI_GPIO_HARDWARE || defined(__DOXYGEN__) #if EFI_GPIO_HARDWARE || defined(__DOXYGEN__)
ioportid_t port; ioportid_t port;
uint8_t pin; uint8_t pin;
#if (BOARD_EXT_GPIOCHIPS > 0)
/* used for external pins */
brain_pin_e brainPin;
bool ext;
#endif
#endif /* EFI_GPIO_HARDWARE */ #endif /* EFI_GPIO_HARDWARE */
int8_t currentLogicValue; int8_t currentLogicValue;
/** /**

View File

@ -16,8 +16,8 @@
/*==========================================================================*/ /*==========================================================================*/
/* fist available gpio number after on-chip gpios */ /* fist available gpio number after on-chip gpios */
#define EXT_GPIOS_FIRST (GPIOH_15 + 1) #define EXT_GPIOS_FIRST (BRAIN_PIN_LAST_ONCHIP + 1)
static size_t gpio_base_free = EXT_GPIOS_FIRST; static brain_pin_e gpio_base_free = EXT_GPIOS_FIRST;
/*==========================================================================*/ /*==========================================================================*/
/* Exported variables. */ /* Exported variables. */
@ -29,7 +29,7 @@ static size_t gpio_base_free = EXT_GPIOS_FIRST;
/* TODO: chnage array to list? */ /* TODO: chnage array to list? */
struct gpiochip { struct gpiochip {
size_t base; brain_pin_e base;
size_t size; size_t size;
struct gpiochip_ops *ops; struct gpiochip_ops *ops;
const char *name; const char *name;
@ -68,7 +68,7 @@ static struct gpiochip *gpiochip_find(unsigned int pin)
* @details * @details
*/ */
int getHwPinExt(unsigned int pin) int gpiochips_getPinOffset(unsigned int pin)
{ {
struct gpiochip *chip = gpiochip_find(pin); struct gpiochip *chip = gpiochip_find(pin);
@ -78,18 +78,36 @@ int getHwPinExt(unsigned int pin)
return EFI_ERROR_CODE; return EFI_ERROR_CODE;
} }
/** /**
* @brief Register gpiochip * @brief Get external chip name
* @details return pin name or gpiochip name (if no pins names provided) * @details return gpiochip name
*/ */
const char *portNameExt(unsigned int pin) const char *gpiochips_getChipName(unsigned int pin)
{ {
struct gpiochip *chip = gpiochip_find(pin); struct gpiochip *chip = gpiochip_find(pin);
if (chip)
return chip->name;
return NULL;
}
/**
* @brief Get external chip port name
* @details return pin name or gpiochip name (if no pins names provided)
*/
const char *gpiochips_getPinName(unsigned int pin)
{
int offset;
struct gpiochip *chip = gpiochip_find(pin);
if (chip) { if (chip) {
if (chip->gpio_names) offset = pin - chip->base;
return chip->gpio_names[pin - chip->base]; if ((chip->gpio_names) && (chip->gpio_names[offset]))
return chip->gpio_names[offset];
else else
return chip->name; return chip->name;
} }
@ -142,6 +160,24 @@ int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, v
return (chip->base); return (chip->base);
} }
/**
* @brief Set pins names for registered gpiochip
* @details should be called after chip registration. May be called several times
* Names array size should be aqual to chip gpio count
*/
int gpiochips_setPinNames(brain_pin_e pin, const char **names)
{
struct gpiochip *chip = gpiochip_find(pin);
if (!chip)
return -1;
chip->gpio_names = names;
return 0;
}
/** /**
* @brief Init all registered gpiochips * @brief Init all registered gpiochips
* @details will call gpiochip init ops for all registered chips * @details will call gpiochip init ops for all registered chips
@ -251,14 +287,21 @@ int gpiochips_get_total_pins(void)
#else /* BOARD_EXT_GPIOCHIPS > 0 */ #else /* BOARD_EXT_GPIOCHIPS > 0 */
int getHwPinExt(unsigned int pin) int gpiochips_getPinOffset(unsigned int pin)
{ {
(void)pin; (void)pin;
return -1; return -1;
} }
const char *portNameExt(unsigned int pin) const char *gpiochips_getChipName(unsigned int pin)
{
(void)pin;
return NULL;
}
const char *gpiochips_getPinName(unsigned int pin)
{ {
(void)pin; (void)pin;
@ -275,6 +318,13 @@ int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, v
return 0; return 0;
} }
int gpiochips_setPinNames(brain_pin_e pin, const char **names)
{
(void)pin; (void)names;
return 0;
}
int gpiochips_init(void) int gpiochips_init(void)
{ {
return 0; return 0;

View File

@ -38,12 +38,16 @@ struct gpiochip_ops {
int (*deinit)(void *data); int (*deinit)(void *data);
}; };
int getHwPinExt(unsigned int pin); int gpiochips_getPinOffset(unsigned int pin);
const char *portNameExt(unsigned int pin); const char *gpiochips_getChipName(unsigned int pin);
const char *gpiochips_getPinName(unsigned int pin);
/* register gpio cgip */ /* register gpio cgip */
int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, void *priv); int gpiochip_register(const char *name, struct gpiochip_ops *ops, size_t size, void *priv);
/* Set individual names for pins */
int gpiochips_setPinNames(brain_pin_e pin, const char **names);
/* gpio extenders subsystem init */ /* gpio extenders subsystem init */
int gpiochips_init(void); int gpiochips_init(void);

View File

@ -104,6 +104,13 @@ struct tle6240_priv {
static struct tle6240_priv chips[BOARD_TLE6240_COUNT]; static struct tle6240_priv chips[BOARD_TLE6240_COUNT];
static const char* tle6240_pin_names[TLE6240_OUTPUTS] = {
"tle6240.OUT1", "tle6240.OUT2", "tle6240.OUT3", "tle6240.OUT4",
"tle6240.OUT5", "tle6240.OUT6", "tle6240.OUT7", "tle6240.OUT8",
"tle6240.OUT9", "tle6240.OUT10", "tle6240.OUT11", "tle6240.OUT12",
"tle6240.OUT13", "tle6240.OUT14", "tle6240.OUT15", "tle6240.OUT16",
};
/*==========================================================================*/ /*==========================================================================*/
/* Driver local functions. */ /* Driver local functions. */
/*==========================================================================*/ /*==========================================================================*/
@ -456,6 +463,7 @@ struct gpiochip_ops tle6240_ops = {
int tle6240_add(unsigned int index, const struct tle6240_config *cfg) int tle6240_add(unsigned int index, const struct tle6240_config *cfg)
{ {
int i; int i;
int ret;
struct tle6240_priv *chip; struct tle6240_priv *chip;
/* no config or no such chip */ /* no config or no such chip */
@ -485,7 +493,12 @@ int tle6240_add(unsigned int index, const struct tle6240_config *cfg)
chip->drv_state = TLE6240_WAIT_INIT; chip->drv_state = TLE6240_WAIT_INIT;
/* register, return gpio chip base */ /* register, return gpio chip base */
return gpiochip_register(DRIVER_NAME, &tle6240_ops, TLE6240_OUTPUTS, chip); ret = gpiochip_register(DRIVER_NAME, &tle6240_ops, TLE6240_OUTPUTS, chip);
/* set default pin names, board init code can rewrite */
gpiochips_setPinNames(ret, tle6240_pin_names);
return ret;
} }
#else /* BOARD_TLE6240_COUNT > 0 */ #else /* BOARD_TLE6240_COUNT > 0 */

View File

@ -12,6 +12,7 @@
#if EFI_PROD_CODE #if EFI_PROD_CODE
#include "io_pins.h" #include "io_pins.h"
#include "efi_gpio.h" #include "efi_gpio.h"
#include "drivers/gpio/gpio_ext.h"
#include "pin_repository.h" #include "pin_repository.h"
#include "status_loop.h" #include "status_loop.h"
@ -40,29 +41,48 @@ ioportid_t getHwPort(const char *msg, brain_pin_e brainPin) {
} }
bool efiReadPin(brain_pin_e pin) { bool efiReadPin(brain_pin_e pin) {
return palReadPad(getHwPort("readPin", pin), getHwPin("readPin", pin)); if (brain_pin_is_onchip(pin))
return palReadPad(getHwPort("readPin", pin), getHwPin("readPin", pin));
#if (BOARD_EXT_GPIOCHIPS > 0)
else if (brain_pin_is_ext(pin))
return (gpiochips_readPad(pin) > 0);
#endif
/* incorrect pin */
return false;
} }
/** /**
* This method would set an error condition if pin is already used * This method would set an error condition if pin is already used
*/ */
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode) { void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
ioportid_t port = getHwPort(msg, brainPin); {
ioportmask_t pin = getHwPin(msg, brainPin); bool wasUsed;
if (port == GPIO_NULL) { //efiAssertVoid(OBD_PCM_Processor_Fault, pin != EFI_ERROR_CODE, "pin_error");
return;
scheduleMsg(&logger, "%s on %s", msg, getBrain_pin_e(brainPin));
wasUsed = brain_pin_markUsed(brainPin, msg);
if (!wasUsed) {
/*check if on-chip pin or external */
if (brain_pin_is_onchip(brainPin)) {
/* on-cip */
ioportid_t port = getHwPort(msg, brainPin);
ioportmask_t pin = getHwPin(msg, brainPin);
/* paranoid */
if (port == GPIO_NULL)
return;
palSetPadMode(port, pin, mode);
}
#if (BOARD_EXT_GPIOCHIPS > 0)
else {
gpiochips_setPadMode(brainPin, mode);
}
#endif
} }
efiAssertVoid(OBD_PCM_Processor_Fault, pin != EFI_ERROR_CODE, "pin_error");
scheduleMsg(&logger, "%s on %s%d", msg, portname(port), pin);
bool wasUsed = gpio_pin_markUsed(port, pin, msg);
if (wasUsed) {
return;
}
palSetPadMode(port, pin, mode);
} }
iomode_t getInputMode(pin_input_mode_e mode) { iomode_t getInputMode(pin_input_mode_e mode) {

View File

@ -15,6 +15,11 @@
#include "eficonsole.h" #include "eficonsole.h"
#include "memstreams.h" #include "memstreams.h"
#include "chprintf.h" #include "chprintf.h"
#include "drivers/gpio/gpio_ext.h"
#ifndef BOARD_EXT_PINREPOPINS
#define BOARD_EXT_PINREPOPINS 0
#endif
static ioportid_t ports[] = {GPIOA, static ioportid_t ports[] = {GPIOA,
GPIOB, GPIOB,
@ -44,7 +49,7 @@ static ioportid_t ports[] = {GPIOA,
#define PIN_REPO_SIZE (sizeof(ports) / sizeof(ports[0])) * PORT_SIZE #define PIN_REPO_SIZE (sizeof(ports) / sizeof(ports[0])) * PORT_SIZE
// todo: move this into PinRepository class // todo: move this into PinRepository class
const char *PIN_USED[PIN_REPO_SIZE]; const char *PIN_USED[PIN_REPO_SIZE + BOARD_EXT_PINREPOPINS];
static int initialized = FALSE; static int initialized = FALSE;
static LoggingWithStorage logger("pin repos"); static LoggingWithStorage logger("pin repos");
@ -110,15 +115,38 @@ static void reportPins(void) {
unsigned int i; unsigned int i;
for (i = 0; i < PIN_REPO_SIZE; i++) { for (i = 0; i < PIN_REPO_SIZE; i++) {
const char *name = PIN_USED[i]; const char *pin_user = PIN_USED[i];
int portIndex = i / PORT_SIZE;
int pin = i % PORT_SIZE; /* show used pins */
ioportid_t port = ports[portIndex]; if (pin_user != NULL) {
if (name != NULL) { int portIndex = i / PORT_SIZE;
scheduleMsg(&logger, "pin %s%d: %s", portname(port), pin, name); int pin = i % PORT_SIZE;
ioportid_t port = ports[portIndex];
scheduleMsg(&logger, "pin %s%d: %s\n", portname(port), pin, pin_user);
} }
} }
#if (BOARD_EXT_GPIOCHIPS > 0)
for (i = PIN_REPO_SIZE ; i < PIN_REPO_SIZE + BOARD_EXT_PINREPOPINS /* gpiochips_get_total_pins()*/ ; i++) {
const char *pin_name;
const char *pin_user;
brain_pin_e brainPin = index_to_brainPin(i);
pin_name = gpiochips_getPinName(brainPin);
pin_user = PIN_USED[i];
/* here show all pins, unused too */
if (pin_name != NULL) {
scheduleMsg(&logger, "ext %s: %s\n",
pin_name, pin_user ? pin_user : "free");
} else {
scheduleMsg(&logger, "ext %s.%d: %s\n",
gpiochips_getChipName(brainPin), gpiochips_getPinOffset(brainPin), pin_user ? pin_user : "free");
}
}
#endif
scheduleMsg(&logger, "Total pins count: %d", totalPinsUsed); scheduleMsg(&logger, "Total pins count: %d", totalPinsUsed);
} }
@ -155,14 +183,25 @@ const char *hwPortname(brain_pin_e brainPin) {
if (brainPin == GPIO_INVALID) { if (brainPin == GPIO_INVALID) {
return "INVALID"; return "INVALID";
} }
ioportid_t hwPort = getHwPort("hostname", brainPin);
if (hwPort == GPIO_NULL) {
return "NONE";
}
int hwPin = getHwPin("hostname", brainPin);
portNameStream.eos = 0; // reset portNameStream.eos = 0; // reset
chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin); if (brain_pin_is_onchip(brainPin)) {
int hwPin;
ioportid_t hwPort = getHwPort("hostname", brainPin);
if (hwPort == GPIO_NULL) {
return "NONE";
}
hwPin = getHwPin("hostname", brainPin);
chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin);
}
#if (BOARD_EXT_GPIOCHIPS > 0)
else {
chprintf((BaseSequentialStream *) &portNameStream, "ext:%s.%d (%s)",
gpiochips_getChipName(brainPin), gpiochips_getPinOffset(brainPin), gpiochips_getPinName(brainPin));
}
#endif
portNameStream.buffer[portNameStream.eos] = 0; // need to terminate explicitly portNameStream.buffer[portNameStream.eos] = 0; // need to terminate explicitly
return portNameBuffer; return portNameBuffer;
} }
@ -176,6 +215,12 @@ void initPinRepository(void) {
memset(PIN_USED, 0, sizeof(PIN_USED)); memset(PIN_USED, 0, sizeof(PIN_USED));
initialized = true; initialized = true;
#if (BOARD_EXT_GPIOCHIPS > 0)
/* external chip init */
gpiochips_init();
#endif
addConsoleAction("pins", reportPins); addConsoleAction("pins", reportPins);
} }