[Xenomai-git] Wolfgang Grandegger : rtcan: add bit-timing calulation from Linux-CAN

2012-12-14 Thread GIT version control
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

2012-10-09 Thread GIT version control
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)