drivers: can: add support for getting the maximum supported bitrate
Add support for getting the maximum supported bitrate in bits/s for CAN controller/transceiver combination and check that a requested bitrate is within the supported range. Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
This commit is contained in:
parent
0783b51ee1
commit
0bae208778
2 changed files with 60 additions and 4 deletions
|
@ -22,7 +22,6 @@ static inline int z_vrfy_can_set_timing(const struct device *dev,
|
||||||
static inline int z_vrfy_can_get_core_clock(const struct device *dev,
|
static inline int z_vrfy_can_get_core_clock(const struct device *dev,
|
||||||
uint32_t *rate)
|
uint32_t *rate)
|
||||||
{
|
{
|
||||||
|
|
||||||
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_core_clock));
|
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_core_clock));
|
||||||
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(rate, sizeof(rate)));
|
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(rate, sizeof(rate)));
|
||||||
|
|
||||||
|
@ -30,6 +29,16 @@ static inline int z_vrfy_can_get_core_clock(const struct device *dev,
|
||||||
}
|
}
|
||||||
#include <syscalls/can_get_core_clock_mrsh.c>
|
#include <syscalls/can_get_core_clock_mrsh.c>
|
||||||
|
|
||||||
|
static inline int z_vrfy_can_get_max_bitrate(const struct device *dev,
|
||||||
|
uint32_t *max_bitrate)
|
||||||
|
{
|
||||||
|
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, get_max_bitrate));
|
||||||
|
Z_OOPS(Z_SYSCALL_MEMORY_WRITE(max_bitrate, sizeof(*max_bitrate)));
|
||||||
|
|
||||||
|
return z_impl_can_get_max_bitrate(dev, max_bitrate);
|
||||||
|
}
|
||||||
|
#include <syscalls/can_get_max_bitrate_mrsh.c>
|
||||||
|
|
||||||
static inline int z_vrfy_can_send(const struct device *dev,
|
static inline int z_vrfy_can_send(const struct device *dev,
|
||||||
const struct zcan_frame *frame,
|
const struct zcan_frame *frame,
|
||||||
k_timeout_t timeout,
|
k_timeout_t timeout,
|
||||||
|
@ -73,7 +82,6 @@ static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev,
|
||||||
|
|
||||||
static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int filter_id)
|
static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int filter_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, remove_rx_filter));
|
Z_OOPS(Z_SYSCALL_DRIVER_CAN(dev, remove_rx_filter));
|
||||||
|
|
||||||
z_impl_can_remove_rx_filter((const struct device *)dev, (int)filter_id);
|
z_impl_can_remove_rx_filter((const struct device *)dev, (int)filter_id);
|
||||||
|
@ -84,7 +92,6 @@ static inline
|
||||||
int z_vrfy_can_get_state(const struct device *dev, enum can_state *state,
|
int z_vrfy_can_get_state(const struct device *dev, enum can_state *state,
|
||||||
struct can_bus_err_cnt *err_cnt)
|
struct can_bus_err_cnt *err_cnt)
|
||||||
{
|
{
|
||||||
|
|
||||||
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN));
|
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN));
|
||||||
|
|
||||||
if (state != NULL) {
|
if (state != NULL) {
|
||||||
|
@ -103,7 +110,6 @@ int z_vrfy_can_get_state(const struct device *dev, enum can_state *state,
|
||||||
static inline int z_vrfy_can_recover(const struct device *dev,
|
static inline int z_vrfy_can_recover(const struct device *dev,
|
||||||
k_timeout_t timeout)
|
k_timeout_t timeout)
|
||||||
{
|
{
|
||||||
|
|
||||||
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN));
|
Z_OOPS(Z_SYSCALL_OBJ(dev, K_OBJ_DRIVER_CAN));
|
||||||
|
|
||||||
return z_impl_can_recover(dev, k_timeout_t timeout);
|
return z_impl_can_recover(dev, k_timeout_t timeout);
|
||||||
|
|
|
@ -371,6 +371,13 @@ typedef int (*can_get_core_clock_t)(const struct device *dev, uint32_t *rate);
|
||||||
*/
|
*/
|
||||||
typedef int (*can_get_max_filters_t)(const struct device *dev, enum can_ide id_type);
|
typedef int (*can_get_max_filters_t)(const struct device *dev, enum can_ide id_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef can_get_max_bitrate_t
|
||||||
|
* @brief Callback API upon getting the maximum supported bitrate
|
||||||
|
* See @a can_get_max_bitrate() for argument description
|
||||||
|
*/
|
||||||
|
typedef int (*can_get_max_bitrate_t)(const struct device *dev, uint32_t *max_bitrate);
|
||||||
|
|
||||||
__subsystem struct can_driver_api {
|
__subsystem struct can_driver_api {
|
||||||
can_set_mode_t set_mode;
|
can_set_mode_t set_mode;
|
||||||
can_set_timing_t set_timing;
|
can_set_timing_t set_timing;
|
||||||
|
@ -384,6 +391,7 @@ __subsystem struct can_driver_api {
|
||||||
can_set_state_change_callback_t set_state_change_callback;
|
can_set_state_change_callback_t set_state_change_callback;
|
||||||
can_get_core_clock_t get_core_clock;
|
can_get_core_clock_t get_core_clock;
|
||||||
can_get_max_filters_t get_max_filters;
|
can_get_max_filters_t get_max_filters;
|
||||||
|
can_get_max_bitrate_t get_max_bitrate;
|
||||||
/* Min values for the timing registers */
|
/* Min values for the timing registers */
|
||||||
struct can_timing timing_min;
|
struct can_timing timing_min;
|
||||||
/* Max values for the timing registers */
|
/* Max values for the timing registers */
|
||||||
|
@ -624,6 +632,30 @@ static inline int z_impl_can_get_core_clock(const struct device *dev, uint32_t *
|
||||||
return api->get_core_clock(dev, rate);
|
return api->get_core_clock(dev, rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get maximum supported bitrate
|
||||||
|
*
|
||||||
|
* Get the maximum supported bitrate for the CAN controller/transceiver combination.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param[out] max_bitrate Maximum supported bitrate in bits/s
|
||||||
|
*
|
||||||
|
* @retval -EIO General input/output error.
|
||||||
|
* @retval -ENOSYS If this function is not implemented by the driver.
|
||||||
|
*/
|
||||||
|
__syscall int can_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate);
|
||||||
|
|
||||||
|
static inline int z_impl_can_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate)
|
||||||
|
{
|
||||||
|
const struct can_driver_api *api = (const struct can_driver_api *)dev->api;
|
||||||
|
|
||||||
|
if (api->get_max_bitrate == NULL) {
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return api->get_max_bitrate(dev, max_bitrate);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calculate timing parameters from bitrate and sample point
|
* @brief Calculate timing parameters from bitrate and sample point
|
||||||
*
|
*
|
||||||
|
@ -755,6 +787,7 @@ static inline int z_impl_can_set_mode(const struct device *dev, enum can_mode mo
|
||||||
* @param bitrate_data Desired data phase bitrate.
|
* @param bitrate_data Desired data phase bitrate.
|
||||||
*
|
*
|
||||||
* @retval 0 If successful.
|
* @retval 0 If successful.
|
||||||
|
* @retval -ENOTSUP bitrate not supported by CAN controller/transceiver combination
|
||||||
* @retval -EINVAL bitrate cannot be met.
|
* @retval -EINVAL bitrate cannot be met.
|
||||||
* @retval -EIO General input/output error, failed to set bitrate.
|
* @retval -EIO General input/output error, failed to set bitrate.
|
||||||
*/
|
*/
|
||||||
|
@ -766,8 +799,21 @@ static inline int can_set_bitrate(const struct device *dev,
|
||||||
#ifdef CONFIG_CAN_FD_MODE
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
struct can_timing timing_data;
|
struct can_timing timing_data;
|
||||||
#endif
|
#endif
|
||||||
|
uint32_t max_bitrate;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
ret = can_get_max_bitrate(dev, &max_bitrate);
|
||||||
|
if (ret == -ENOSYS) {
|
||||||
|
/* Maximum bitrate unknown */
|
||||||
|
max_bitrate = 0;
|
||||||
|
} else if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((max_bitrate > 0) && (bitrate > max_bitrate)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
ret = can_calc_timing(dev, &timing, bitrate, 875);
|
ret = can_calc_timing(dev, &timing, bitrate, 875);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -776,6 +822,10 @@ static inline int can_set_bitrate(const struct device *dev,
|
||||||
timing.sjw = CAN_SJW_NO_CHANGE;
|
timing.sjw = CAN_SJW_NO_CHANGE;
|
||||||
|
|
||||||
#ifdef CONFIG_CAN_FD_MODE
|
#ifdef CONFIG_CAN_FD_MODE
|
||||||
|
if ((max_bitrate > 0) && (bitrate_data > max_bitrate)) {
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
ret = can_calc_timing_data(dev, &timing_data, bitrate_data, 875);
|
ret = can_calc_timing_data(dev, &timing_data, bitrate_data, 875);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue