[Xenomai-git] Wolfgang Grandegger : rtcan: add bit-timing calulation from Linux-CAN
Module: xenomai-forge Branch: master Commit: ef036723abcf7e05737c34c099a1efebf69362ae URL: http://git.xenomai.org/?p=xenomai-forge.git;a=commit;h=ef036723abcf7e05737c34c099a1efebf69362ae Author: Wolfgang Grandegger Date: Thu Sep 27 17:29:14 2012 +0200 rtcan: add bit-timing calulation from Linux-CAN So far we use a very simple method to calculate bit-timing parameters from the bitrate. This works fine for the SJA1000 and MSCAN but fails for the Flexcan. This patch introduces the more general bit-timing algorithm from Linux-CAN, which is based on bit-timing constants. The Kconfig option XENO_DRIVERS_CAN_CALC_BITTIME_OLD allows to set the old algorithm for backward compatibility. Signed-off-by: Wolfgang Grandegger --- kernel/drivers/can/Kconfig |6 ++ kernel/drivers/can/mscan/rtcan_mscan.c | 17 kernel/drivers/can/rtcan_dev.h | 17 kernel/drivers/can/rtcan_raw_dev.c | 127 +++- kernel/drivers/can/sja1000/rtcan_sja1000.c | 18 5 files changed, 184 insertions(+), 1 deletions(-) diff --git a/kernel/drivers/can/Kconfig b/kernel/drivers/can/Kconfig index ac602ad..f1f31c6 100644 --- a/kernel/drivers/can/Kconfig +++ b/kernel/drivers/can/Kconfig @@ -61,6 +61,12 @@ config XENO_DRIVERS_CAN_BUS_ERR processing. This option is automatically selected for CAN controllers supporting bus error interrupts like the SJA1000. +config XENO_DRIVERS_CAN_CALC_BITTIME_OLD + depends on XENO_DRIVERS_CAN + bool "Old bit-time calculation algorithm" + default n + help + config XENO_DRIVERS_CAN_VIRT depends on XENO_DRIVERS_CAN tristate "Virtual CAN bus driver" diff --git a/kernel/drivers/can/mscan/rtcan_mscan.c b/kernel/drivers/can/mscan/rtcan_mscan.c index edd590e..2b53e79 100644 --- a/kernel/drivers/can/mscan/rtcan_mscan.c +++ b/kernel/drivers/can/mscan/rtcan_mscan.c @@ -42,6 +42,20 @@ #define MSCAN_SET_MODE_RETRIES 255 +#ifndef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD +static struct can_bittiming_const mscan_bittiming_const = { + .name = "mscan", + .tseg1_min = 4, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; +#endif + /** * Reception Interrupt handler * @@ -722,6 +736,9 @@ int rtcan_mscan_register(struct rtcan_device *dev, int irq, int mscan_clksrc) dev->hard_start_xmit = rtcan_mscan_start_xmit; dev->do_set_mode = rtcan_mscan_set_mode; dev->do_set_bit_time = rtcan_mscan_set_bit_time; +#ifndef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD + dev->bittiming_const = &mscan_bittiming_const; +#endif /* Register IRQ handler and pass device structure as arg */ ret = rtdm_irq_request(&dev->irq_handle, irq, rtcan_mscan_interrupt, diff --git a/kernel/drivers/can/rtcan_dev.h b/kernel/drivers/can/rtcan_dev.h index 4b563b7..a852c30 100644 --- a/kernel/drivers/can/rtcan_dev.h +++ b/kernel/drivers/can/rtcan_dev.h @@ -49,6 +49,22 @@ #define RTCAN_USE_REFCOUNT #endif +/* + * CAN harware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ +struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ + __u32 tseg1_min;/* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; + __u32 tseg2_min;/* Time segement 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ + __u32 brp_max; + __u32 brp_inc; +}; struct rtcan_device { unsigned intversion; @@ -92,6 +108,7 @@ struct rtcan_device { can_baudrate_t baudrate; struct can_bittime bit_time; +const struct can_bittiming_const *bittiming_const; /* State which the controller is in. Protected by device_lock in all * device structures. */ diff --git a/kernel/drivers/can/rtcan_raw_dev.c b/kernel/drivers/can/rtcan_raw_dev.c index 5e7e260..c5fd1b6 100644 --- a/kernel/drivers/can/rtcan_raw_dev.c +++ b/kernel/drivers/can/rtcan_raw_dev.c @@ -28,6 +28,8 @@ #include "rtcan_raw.h" #include "rtcan_internal.h" +#ifdef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD + #define RTCAN_MAX_TSEG1 15 #define RTCAN_MAX_TSEG2 7 @@ -108,6 +110,128 @@ static int rtcan_calc_bit_time(struct rtcan_device *dev, return 0; } +#else /* !CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD */ + +/* This is the bit-time calculation method from the Linux kernel */ + +#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ + +static int can_update_spt(const struct can_bittiming_const *btc, + unsigned int sampl_pt, unsigned int tseg, + unsigned int *tseg1, unsigned int *tseg2) +{ +*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; +*tseg2 =
[Xenomai-git] Wolfgang Grandegger : rtcan: add bit-timing calulation from Linux-CAN
Module: xenomai-2.6 Branch: master Commit: 6164940ed41cff831cd410b14ec22940228566e4 URL: http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=6164940ed41cff831cd410b14ec22940228566e4 Author: Wolfgang Grandegger Date: Thu Sep 27 17:29:14 2012 +0200 rtcan: add bit-timing calulation from Linux-CAN So far we use a very simple method to calculate bit-timing parameters from the bitrate. This works fine for the SJA1000 and MSCAN but fails for the Flexcan. This patch introduces the more general bit-timing algorithm from Linux-CAN, which is based on bit-timing constants. The Kconfig option XENO_DRIVERS_CAN_CALC_BITTIME_OLD allows to set the old algorithm for backward compatibility. Signed-off-by: Wolfgang Grandegger --- ksrc/drivers/can/Kconfig |6 ++ ksrc/drivers/can/mscan/rtcan_mscan.c | 17 ksrc/drivers/can/rtcan_dev.h | 17 ksrc/drivers/can/rtcan_raw_dev.c | 127 +- ksrc/drivers/can/sja1000/rtcan_sja1000.c | 18 5 files changed, 184 insertions(+), 1 deletions(-) diff --git a/ksrc/drivers/can/Kconfig b/ksrc/drivers/can/Kconfig index e659a3c..a3917da 100644 --- a/ksrc/drivers/can/Kconfig +++ b/ksrc/drivers/can/Kconfig @@ -62,6 +62,12 @@ config XENO_DRIVERS_CAN_BUS_ERR processing. This option is automatically selected for CAN controllers supporting bus error interrupts like the SJA1000. +config XENO_DRIVERS_CAN_CALC_BITTIME_OLD + depends on XENO_DRIVERS_CAN + bool "Old bit-time calculation algorithm" + default n + help + config XENO_DRIVERS_CAN_VIRT depends on XENO_DRIVERS_CAN tristate "Virtual CAN bus driver" diff --git a/ksrc/drivers/can/mscan/rtcan_mscan.c b/ksrc/drivers/can/mscan/rtcan_mscan.c index edd590e..2b53e79 100644 --- a/ksrc/drivers/can/mscan/rtcan_mscan.c +++ b/ksrc/drivers/can/mscan/rtcan_mscan.c @@ -42,6 +42,20 @@ #define MSCAN_SET_MODE_RETRIES 255 +#ifndef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD +static struct can_bittiming_const mscan_bittiming_const = { + .name = "mscan", + .tseg1_min = 4, + .tseg1_max = 16, + .tseg2_min = 2, + .tseg2_max = 8, + .sjw_max = 4, + .brp_min = 1, + .brp_max = 64, + .brp_inc = 1, +}; +#endif + /** * Reception Interrupt handler * @@ -722,6 +736,9 @@ int rtcan_mscan_register(struct rtcan_device *dev, int irq, int mscan_clksrc) dev->hard_start_xmit = rtcan_mscan_start_xmit; dev->do_set_mode = rtcan_mscan_set_mode; dev->do_set_bit_time = rtcan_mscan_set_bit_time; +#ifndef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD + dev->bittiming_const = &mscan_bittiming_const; +#endif /* Register IRQ handler and pass device structure as arg */ ret = rtdm_irq_request(&dev->irq_handle, irq, rtcan_mscan_interrupt, diff --git a/ksrc/drivers/can/rtcan_dev.h b/ksrc/drivers/can/rtcan_dev.h index ab0431c..65fed69 100644 --- a/ksrc/drivers/can/rtcan_dev.h +++ b/ksrc/drivers/can/rtcan_dev.h @@ -51,6 +51,22 @@ #define RTCAN_USE_REFCOUNT #endif +/* + * CAN harware-dependent bit-timing constant + * + * Used for calculating and checking bit-timing parameters + */ +struct can_bittiming_const { + char name[16]; /* Name of the CAN controller hardware */ + __u32 tseg1_min;/* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_max; + __u32 tseg2_min;/* Time segement 2 = phase_seg2 */ + __u32 tseg2_max; + __u32 sjw_max; /* Synchronisation jump width */ + __u32 brp_min; /* Bit-rate prescaler */ + __u32 brp_max; + __u32 brp_inc; +}; struct rtcan_device { unsigned intversion; @@ -94,6 +110,7 @@ struct rtcan_device { can_baudrate_t baudrate; struct can_bittime bit_time; +const struct can_bittiming_const *bittiming_const; /* State which the controller is in. Protected by device_lock in all * device structures. */ diff --git a/ksrc/drivers/can/rtcan_raw_dev.c b/ksrc/drivers/can/rtcan_raw_dev.c index 5e7e260..c5fd1b6 100644 --- a/ksrc/drivers/can/rtcan_raw_dev.c +++ b/ksrc/drivers/can/rtcan_raw_dev.c @@ -28,6 +28,8 @@ #include "rtcan_raw.h" #include "rtcan_internal.h" +#ifdef CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD + #define RTCAN_MAX_TSEG1 15 #define RTCAN_MAX_TSEG2 7 @@ -108,6 +110,128 @@ static int rtcan_calc_bit_time(struct rtcan_device *dev, return 0; } +#else /* !CONFIG_XENO_DRIVERS_CAN_CALC_BITTIME_OLD */ + +/* This is the bit-time calculation method from the Linux kernel */ + +#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */ + +static int can_update_spt(const struct can_bittiming_const *btc, + unsigned int sampl_pt, unsigned int tseg, + unsigned int *tseg1, unsigned int *tseg2) +{ +*tseg2 = tseg + 1 - (sampl_pt * (tseg + 1)) / 1000; +*tseg2 = clamp(*tseg2, btc->tseg2_min, btc->tseg2_max)