Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CAN termination GPIO support #83422

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion drivers/can/transceiver/can_transceiver_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,20 @@
#define INST_HAS_STANDBY_GPIOS_OR(inst) DT_INST_NODE_HAS_PROP(inst, standby_gpios) ||
#define ANY_INST_HAS_STANDBY_GPIOS DT_INST_FOREACH_STATUS_OKAY(INST_HAS_STANDBY_GPIOS_OR) 0

/* Does any devicetree instance have a term-gpios property? */
#define INST_HAS_TERM_GPIOS_OR(inst) DT_INST_NODE_HAS_PROP(inst, termination_gpios) ||
#define ANY_INST_HAS_TERM_GPIOS DT_INST_FOREACH_STATUS_OKAY(INST_HAS_TERM_GPIOS_OR) 0

struct can_transceiver_gpio_config {
#if ANY_INST_HAS_ENABLE_GPIOS
struct gpio_dt_spec enable_gpio;
#endif /* ANY_INST_HAS_ENABLE_GPIOS */
#if ANY_INST_HAS_STANDBY_GPIOS
struct gpio_dt_spec standby_gpio;
#endif /* ANY_INST_HAS_STANDBY_GPIOS */
#if ANY_INST_HAS_TERM_GPIOS
struct gpio_dt_spec termination_gpio;
#endif /* ANY_INST_HAS_TERM_GPIOS */
};

static int can_transceiver_gpio_set_state(const struct device *dev, bool enabled)
Expand Down Expand Up @@ -110,9 +117,37 @@
return 0;
}

static int can_transceiver_gpio_set_termination(const struct device *dev,
bool enabled)

Check warning on line 121 in drivers/can/transceiver/can_transceiver_gpio.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

drivers/can/transceiver/can_transceiver_gpio.c:121 line length of 109 exceeds 100 columns
{
#if ANY_INST_HAS_TERM_GPIOS
if (config->termination_gpio.port != NULL) {
err = gpio_pin_set_dt(&config->termination_gpio, enabled ? 0 : 1);
if (err != 0) {
LOG_ERR("failed to set termination GPIO pin (err %d)", err);
return -EIO;
}
}
#endif /* ANY_INST_HAS_TERM_GPIOS */

return 0;
}

static int can_transceiver_gpio_termination_enable(const struct device *dev)
{
return can_transceiver_gpio_set_termination(dev, true);
}

static int can_transceiver_gpio_termination_disable(const struct device *dev)
{
return can_transceiver_gpio_set_termination(dev, false);
}

static DEVICE_API(can_transceiver, can_transceiver_gpio_driver_api) = {
.enable = can_transceiver_gpio_enable,
.disable = can_transceiver_gpio_disable,
.termination_enable = can_transceiver_gpio_termination_enable,
.termination_disable = can_transceiver_gpio_termination_disable,
};

#define CAN_TRANSCEIVER_GPIO_COND(inst, name) \
Expand All @@ -121,13 +156,16 @@

#define CAN_TRANSCEIVER_GPIO_INIT(inst) \
BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, enable_gpios) || \
DT_INST_NODE_HAS_PROP(inst, standby_gpios), \
DT_INST_NODE_HAS_PROP(inst, standby_gpios), \
DT_INST_NODE_HAS_PROP(inst, termination_gpios), \
"Missing GPIO property on " \
DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \
\
static const struct can_transceiver_gpio_config can_transceiver_gpio_config_##inst = { \
CAN_TRANSCEIVER_GPIO_COND(inst, enable) \
CAN_TRANSCEIVER_GPIO_COND(inst, standby) \
CAN_TRANSCEIVER_GPIO_COND(inst, termination_enable) \
CAN_TRANSCEIVER_GPIO_COND(inst, termination_disable) \
}; \
\
DEVICE_DT_INST_DEFINE(inst, &can_transceiver_gpio_init, \
Expand Down
6 changes: 6 additions & 0 deletions dts/bindings/phy/can-transceiver-gpio.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ properties:
GPIO to use to put the CAN transceiver into standby. This GPIO is driven
inactive when the CAN transceiver is enabled and active when the CAN
transceiver is disabled.

termination-gpios:
type: phandle-array
description: |
GPIO to use to enable/disable the CAN transceiver termination resistor.
This GPIO will be not changed during CAN transceiver initialzation phase.
48 changes: 48 additions & 0 deletions include/zephyr/drivers/can/transceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,23 @@ typedef int (*can_transceiver_enable_t)(const struct device *dev, can_mode_t mod
*/
typedef int (*can_transceiver_disable_t)(const struct device *dev);

/**
* @brief Callback API upon enabling CAN transceiver termination
* See @a can_transceiver_termination_enable() for argument description
*/
typedef int (*can_transceiver_termination_enable_t)(const struct device *dev);

/**
* @brief Callback API upon disabling CAN transceiver termination
* See @a can_transceiver_termination_disable() for argument description
*/
typedef int (*can_transceiver_termination_disable_t)(const struct device *dev);

__subsystem struct can_transceiver_driver_api {
can_transceiver_enable_t enable;
can_transceiver_disable_t disable;
can_transceiver_termination_enable_t termination_enable;
can_transceiver_termination_disable_t termination_disable;
};

/** @endcond */
Expand Down Expand Up @@ -87,6 +101,40 @@ static inline int can_transceiver_disable(const struct device *dev)
return DEVICE_API_GET(can_transceiver, dev)->disable(dev);
}

/**
* @brief Enable CAN transceiver termination
*
* Enable CAN transceiver termination by puttig 120ohm between CAN_H and CAN_L.
*
* @note The CAN transceiver is controlled by the CAN controller driver and
* should not normally be controlled by the application.
*
* @param dev Pointer to the device structure for the driver instance.
* @retval 0 If successful.
* @retval -EIO General input/output error, failed to enable device.
*/
static inline int can_transceiver_termination_enable(const struct device *dev)
{
return DEVICE_API_GET(can_transceiver, dev)->termination_enable(dev);
}

/**
* @brief Disable CAN transceiver termination
*
* Disable CAN transceiver termination by puttig 120ohm between CAN_H and CAN_L.
*
* @note The CAN transceiver is controlled by the CAN controller driver and
* should not normally be controlled by the application.
*
* @param dev Pointer to the device structure for the driver instance.
* @retval 0 If successful.
* @retval -EIO General input/output error, failed to enable device.
*/
static inline int can_transceiver_termination_disable(const struct device *dev)
{
return DEVICE_API_GET(can_transceiver, dev)->termination_disable(dev);
}

/**
* @}
*/
Expand Down
Loading