drivers: can: mcp2515: add transceiver support
Add support for CAN transceivers to the Microchip MCP2515 CAN driver. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
63358621bd
commit
000661db21
2 changed files with 41 additions and 1 deletions
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <device.h>
|
#include <device.h>
|
||||||
|
#include <drivers/can/transceiver.h>
|
||||||
#include <drivers/spi.h>
|
#include <drivers/spi.h>
|
||||||
#include <drivers/gpio.h>
|
#include <drivers/gpio.h>
|
||||||
#include <logging/log.h>
|
#include <logging/log.h>
|
||||||
|
@ -334,6 +335,15 @@ int mcp2515_get_max_filters(const struct device *dev, enum can_ide id_type)
|
||||||
return CONFIG_CAN_MAX_FILTER;
|
return CONFIG_CAN_MAX_FILTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mcp2515_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate)
|
||||||
|
{
|
||||||
|
const struct mcp2515_config *dev_cfg = dev->config;
|
||||||
|
|
||||||
|
*max_bitrate = dev_cfg->max_bitrate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int mcp2515_set_timing(const struct device *dev,
|
static int mcp2515_set_timing(const struct device *dev,
|
||||||
const struct can_timing *timing,
|
const struct can_timing *timing,
|
||||||
const struct can_timing *timing_data)
|
const struct can_timing *timing_data)
|
||||||
|
@ -452,18 +462,34 @@ done:
|
||||||
|
|
||||||
static int mcp2515_set_mode(const struct device *dev, enum can_mode mode)
|
static int mcp2515_set_mode(const struct device *dev, enum can_mode mode)
|
||||||
{
|
{
|
||||||
|
const struct mcp2515_config *dev_cfg = dev->config;
|
||||||
struct mcp2515_data *dev_data = dev->data;
|
struct mcp2515_data *dev_data = dev->data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
k_mutex_lock(&dev_data->mutex, K_FOREVER);
|
k_mutex_lock(&dev_data->mutex, K_FOREVER);
|
||||||
|
|
||||||
|
if (dev_cfg->phy != NULL) {
|
||||||
|
ret = can_transceiver_enable(dev_cfg->phy);
|
||||||
|
if (ret != 0) {
|
||||||
|
LOG_ERR("failed to enable CAN transceiver (err %d)", ret);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
k_usleep(MCP2515_OSC_STARTUP_US);
|
k_usleep(MCP2515_OSC_STARTUP_US);
|
||||||
|
|
||||||
ret = mcp2515_set_mode_int(dev,
|
ret = mcp2515_set_mode_int(dev,
|
||||||
mcp2515_convert_canmode_to_mcp2515mode(mode));
|
mcp2515_convert_canmode_to_mcp2515mode(mode));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
LOG_ERR("Failed to set the mode [%d]", ret);
|
LOG_ERR("Failed to set the mode [%d]", ret);
|
||||||
|
|
||||||
|
if (dev_cfg->phy != NULL) {
|
||||||
|
/* Attempt to disable the CAN transceiver in case of error */
|
||||||
|
(void)can_transceiver_disable(dev_cfg->phy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
k_mutex_unlock(&dev_data->mutex);
|
k_mutex_unlock(&dev_data->mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -816,6 +842,7 @@ static const struct can_driver_api can_api_funcs = {
|
||||||
.set_state_change_callback = mcp2515_set_state_change_callback,
|
.set_state_change_callback = mcp2515_set_state_change_callback,
|
||||||
.get_core_clock = mcp2515_get_core_clock,
|
.get_core_clock = mcp2515_get_core_clock,
|
||||||
.get_max_filters = mcp2515_get_max_filters,
|
.get_max_filters = mcp2515_get_max_filters,
|
||||||
|
.get_max_bitrate = mcp2515_get_max_bitrate,
|
||||||
.timing_min = {
|
.timing_min = {
|
||||||
.sjw = 0x1,
|
.sjw = 0x1,
|
||||||
.prop_seg = 0x01,
|
.prop_seg = 0x01,
|
||||||
|
@ -850,6 +877,13 @@ static int mcp2515_init(const struct device *dev)
|
||||||
dev_data->tx_cb[i].cb = NULL;
|
dev_data->tx_cb[i].cb = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dev_cfg->phy != NULL) {
|
||||||
|
if (!device_is_ready(dev_cfg->phy)) {
|
||||||
|
LOG_ERR("CAN transceiver not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!spi_is_ready(&dev_cfg->bus)) {
|
if (!spi_is_ready(&dev_cfg->bus)) {
|
||||||
LOG_ERR("SPI bus %s not ready", dev_cfg->bus.bus->name);
|
LOG_ERR("SPI bus %s not ready", dev_cfg->bus.bus->name);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -948,7 +982,9 @@ static const struct mcp2515_config mcp2515_config_1 = {
|
||||||
.tq_bs2 = DT_INST_PROP_OR(0, phase_seg2, 0),
|
.tq_bs2 = DT_INST_PROP_OR(0, phase_seg2, 0),
|
||||||
.bus_speed = DT_INST_PROP(0, bus_speed),
|
.bus_speed = DT_INST_PROP(0, bus_speed),
|
||||||
.osc_freq = DT_INST_PROP(0, osc_freq),
|
.osc_freq = DT_INST_PROP(0, osc_freq),
|
||||||
.sample_point = DT_INST_PROP_OR(0, sample_point, 0)
|
.sample_point = DT_INST_PROP_OR(0, sample_point, 0),
|
||||||
|
.phy = DEVICE_DT_GET_OR_NULL(DT_INST_PHANDLE(0, phys)),
|
||||||
|
.max_bitrate = DT_INST_CAN_TRANSCEIVER_MAX_BITRATE(0, 1000000),
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE_DT_INST_DEFINE(0, &mcp2515_init, NULL,
|
DEVICE_DT_INST_DEFINE(0, &mcp2515_init, NULL,
|
||||||
|
|
|
@ -65,6 +65,10 @@ struct mcp2515_config {
|
||||||
uint32_t bus_speed;
|
uint32_t bus_speed;
|
||||||
uint32_t osc_freq;
|
uint32_t osc_freq;
|
||||||
uint16_t sample_point;
|
uint16_t sample_point;
|
||||||
|
|
||||||
|
/* CAN transceiver */
|
||||||
|
const struct device *phy;
|
||||||
|
uint32_t max_bitrate;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue