zephyr/drivers/can/can_sja1000.h
Henrik Brix Andersen f8a88cdb27 drivers: can: use flags fields for can_frame and can_filter structs
The can_frame and can_filter structs support a number of different flags
(standard/extended CAN ID type, Remote Transmission Request, CAN-FD format,
Bit Rate Switch, ...). Each of these flags is represented as a discrete bit
in the given structure.

This design pattern requires every user of these structs to initialize all
of these flags to either 0 or 1, which does not scale well for future flag
additions.

Some of these flags have associated enumerations to be used for assignment,
some do not. CAN drivers and protocols tend to rely on the logical value of
the flag instead of using the enumeration, leading to a very fragile
API. The enumerations are used inconsistently between the can_frame and
can_filter structures, which further complicates the API.

Instead, convert these flags to bitfields with separate flag definitions
for the can_frame and can_filter structures. This API allows for future
extensions without having to revisit existing users of the two
structures. Furthermore, this allows driver to easily check for unsupported
flags in the respective API calls.

As this change leads to the "id_mask" field of the can_filter to be the
only mask present in that structure, rename it to "mask" for simplicity.

Fixes: #50776

Signed-off-by: Henrik Brix Andersen <hebad@vestas.com>
2022-10-25 16:32:10 +02:00

158 lines
5.8 KiB
C

/*
* Copyright (c) 2022 Henrik Brix Andersen <henrik@brixandersen.dk>
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_DRIVERS_CAN_SJA1000_H_
#define ZEPHYR_DRIVERS_CAN_SJA1000_H_
#include <zephyr/drivers/can.h>
/* Output Control Register (OCR) bits */
#define CAN_SJA1000_OCR_OCMODE_MASK GENMASK(1, 0)
#define CAN_SJA1000_OCR_OCPOL0 BIT(2)
#define CAN_SJA1000_OCR_OCTN0 BIT(3)
#define CAN_SJA1000_OCR_OCTP0 BIT(4)
#define CAN_SJA1000_OCR_OCPOL1 BIT(5)
#define CAN_SJA1000_OCR_OCTN1 BIT(6)
#define CAN_SJA1000_OCR_OCTP1 BIT(7)
#define CAN_SJA1000_OCR_OCMODE_BIPHASE FIELD_PREP(CAN_SJA1000_OCR_OCMODE_MASK, 0U)
#define CAN_SJA1000_OCR_OCMODE_TEST FIELD_PREP(CAN_SJA1000_OCR_OCMODE_MASK, 1U)
#define CAN_SJA1000_OCR_OCMODE_NORMAL FIELD_PREP(CAN_SJA1000_OCR_OCMODE_MASK, 2U)
#define CAN_SJA1000_OCR_OCMODE_CLOCK FIELD_PREP(CAN_SJA1000_OCR_OCMODE_MASK, 3U)
/* Clock Divider Register (CDR) bits */
#define CAN_SJA1000_CDR_CD_MASK GENMASK(2, 0)
#define CAN_SJA1000_CDR_CLOCK_OFF BIT(3)
#define CAN_SJA1000_CDR_RXINTEN BIT(5)
#define CAN_SJA1000_CDR_CBP BIT(6)
#define CAN_SJA1000_CDR_CAN_MODE BIT(7)
#define CAN_SJA1000_CDR_CD_DIV1 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 7U)
#define CAN_SJA1000_CDR_CD_DIV2 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 0U)
#define CAN_SJA1000_CDR_CD_DIV4 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 1U)
#define CAN_SJA1000_CDR_CD_DIV6 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 2U)
#define CAN_SJA1000_CDR_CD_DIV8 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 3U)
#define CAN_SJA1000_CDR_CD_DIV10 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 4U)
#define CAN_SJA1000_CDR_CD_DIV12 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 5U)
#define CAN_SJA1000_CDR_CD_DIV14 FIELD_PREP(CAN_SJA1000_CDR_CD_MASK, 6U)
#define CAN_SJA1000_TIMING_MIN_INITIALIZER \
{ \
.sjw = 1, \
.prop_seg = 0, \
.phase_seg1 = 1, \
.phase_seg2 = 1, \
.prescaler = 1 \
}
#define CAN_SJA1000_TIMING_MAX_INITIALIZER \
{ \
.sjw = 4, \
.prop_seg = 0, \
.phase_seg1 = 16, \
.phase_seg2 = 8, \
.prescaler = 64 \
}
typedef void (*can_sja1000_write_reg_t)(const struct device *dev, uint8_t reg, uint8_t val);
typedef uint8_t (*can_sja1000_read_reg_t)(const struct device *dev, uint8_t reg);
struct can_sja1000_config {
can_sja1000_read_reg_t read_reg;
can_sja1000_write_reg_t write_reg;
uint32_t bitrate;
uint32_t sample_point;
uint32_t sjw;
uint32_t phase_seg1;
uint32_t phase_seg2;
const struct device *phy;
uint32_t max_bitrate;
uint8_t ocr;
uint8_t cdr;
const void *custom;
};
#define CAN_SJA1000_DT_CONFIG_GET(node_id, _custom, _read_reg, _write_reg, _ocr, _cdr) \
{ \
.read_reg = _read_reg, .write_reg = _write_reg, \
.bitrate = DT_PROP(node_id, bus_speed), .sjw = DT_PROP(node_id, sjw), \
.phase_seg1 = DT_PROP_OR(node_id, phase_seg1, 0), \
.phase_seg2 = DT_PROP_OR(node_id, phase_seg2, 0), \
.sample_point = DT_PROP_OR(node_id, sample_point, 0), \
.max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, 1000000), \
.phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \
.ocr = _ocr, .cdr = _cdr, .custom = _custom, \
}
#define CAN_SJA1000_DT_CONFIG_INST_GET(inst, _custom, _read_reg, _write_reg, _ocr, _cdr) \
CAN_SJA1000_DT_CONFIG_GET(DT_DRV_INST(inst), _custom, _read_reg, _write_reg, _ocr, _cdr)
struct can_sja1000_rx_filter {
struct can_filter filter;
can_rx_callback_t callback;
void *user_data;
};
struct can_sja1000_data {
ATOMIC_DEFINE(rx_allocs, CONFIG_CAN_MAX_FILTER);
struct can_sja1000_rx_filter filters[CONFIG_CAN_MAX_FILTER];
struct k_mutex mod_lock;
bool started;
can_mode_t mode;
enum can_state state;
can_state_change_callback_t state_change_cb;
void *state_change_cb_data;
struct k_sem tx_idle;
can_tx_callback_t tx_callback;
void *tx_user_data;
uint32_t sjw;
void *custom;
};
#define CAN_SJA1000_DATA_INITIALIZER(_custom) \
{ \
.custom = _custom, \
}
int can_sja1000_set_timing(const struct device *dev, const struct can_timing *timing);
int can_sja1000_get_capabilities(const struct device *dev, can_mode_t *cap);
int can_sja1000_start(const struct device *dev);
int can_sja1000_stop(const struct device *dev);
int can_sja1000_set_mode(const struct device *dev, can_mode_t mode);
int can_sja1000_send(const struct device *dev, const struct can_frame *frame, k_timeout_t timeout,
can_tx_callback_t callback, void *user_data);
int can_sja1000_add_rx_filter(const struct device *dev, can_rx_callback_t callback, void *user_data,
const struct can_filter *filter);
void can_sja1000_remove_rx_filter(const struct device *dev, int filter_id);
#ifndef CONFIG_CAN_AUTO_BUS_OFF_RECOVERY
int can_sja1000_recover(const struct device *dev, k_timeout_t timeout);
#endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */
int can_sja1000_get_state(const struct device *dev, enum can_state *state,
struct can_bus_err_cnt *err_cnt);
void can_sja1000_set_state_change_callback(const struct device *dev,
can_state_change_callback_t callback, void *user_data);
int can_sja1000_get_max_filters(const struct device *dev, bool ide);
int can_sja1000_get_max_bitrate(const struct device *dev, uint32_t *max_bitrate);
void can_sja1000_isr(const struct device *dev);
int can_sja1000_init(const struct device *dev);
#endif /* ZEPHYR_DRIVERS_CAN_SJA1000_H_ */