* [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
@ 2010-01-14 12:07 Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 1/3] rtcan: mscan: use tabs for indention and white space cleanup Wolfgang Grandegger
2010-01-15 14:08 ` [Xenomai-core] [PATCH xenomai-2.5 0/3] " Gilles Chanteperdrix
0 siblings, 2 replies; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: Wolfgang Grandegger
From: Wolfgang Grandegger <wg@domain.hid>
This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
from Freescale by introducing a new OF platform driver for both, the
MPC521x and MPC5200, while still keeping the old driver for the MPC5200
for compatibility with older kernel versions.
Wolfgang
Wolfgang Grandegger (3):
rtcan: mscan: use tabs for indention and white space cleanup
rtcan: mscan: use proper io accessor functions for register access
rtcan: mscan: new OF platform driver for MPC521x and MPC5200
ksrc/drivers/can/mscan/Kconfig | 21 +-
ksrc/drivers/can/mscan/Makefile | 11 +-
ksrc/drivers/can/mscan/rtcan_mscan.c | 1245 +++++++++++---------------
ksrc/drivers/can/mscan/rtcan_mscan.h | 38 +
ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c | 254 ++++++
ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c | 374 ++++++++
ksrc/drivers/can/mscan/rtcan_mscan_proc.c | 184 ++--
ksrc/drivers/can/mscan/rtcan_mscan_regs.h | 74 +-
8 files changed, 1371 insertions(+), 830 deletions(-)
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan.h
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Xenomai-core] [PATCH xenomai-2.5 1/3] rtcan: mscan: use tabs for indention and white space cleanup
2010-01-14 12:07 [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
@ 2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 2/3] rtcan: mscan: use proper io accessor functions for register access Wolfgang Grandegger
2010-01-15 14:08 ` [Xenomai-core] [PATCH xenomai-2.5 0/3] " Gilles Chanteperdrix
1 sibling, 1 reply; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: Wolfgang Grandegger
From: Wolfgang Grandegger <wg@domain.hid>
This patch introduces tabs for indention, deletes training white space
and corrects some other white space issues.
Signed-off-by: Wolfgang Grandegger <wg@domain.hid>
---
ksrc/drivers/can/mscan/Makefile | 4 +-
ksrc/drivers/can/mscan/rtcan_mscan.c | 1226 ++++++++++++++---------------
ksrc/drivers/can/mscan/rtcan_mscan_proc.c | 172 ++--
ksrc/drivers/can/mscan/rtcan_mscan_regs.h | 66 +-
4 files changed, 732 insertions(+), 736 deletions(-)
diff --git a/ksrc/drivers/can/mscan/Makefile b/ksrc/drivers/can/mscan/Makefile
index 20e29e4..8976ffe 100644
--- a/ksrc/drivers/can/mscan/Makefile
+++ b/ksrc/drivers/can/mscan/Makefile
@@ -14,9 +14,9 @@ else
O_TARGET := built-in.o
-obj-$(CONFIG_XENO_DRIVERS_CAN_MSCAN) := xeno_can_mscan.o
+obj-$(CONFIG_XENO_DRIVERS_CAN_MSCAN) := xeno_can_mscan.o
-list-multi := xeno_can_mscan.o
+list-multi := xeno_can_mscan.o
xeno_can_mscan-objs := rtcan_mscan.o rtcan_mscan_proc.o
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan.c b/ksrc/drivers/can/mscan/rtcan_mscan.c
index 9618057..b5b6489 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan.c
@@ -74,9 +74,9 @@ int port[RTCAN_MSCAN_DEVS] = {
compat_module_param_array(port, int, RTCAN_MSCAN_DEVS, 0444);
MODULE_PARM_DESC(port, "Enabled CAN ports (1,1 or 0,1 or 0,1)");
-/*
- * Note: on the MPC5200 the MSCAN clock source is the IP bus
- * clock (IP_CLK) while on the MPC5200B it is the oscillator
+/*
+ * Note: on the MPC5200 the MSCAN clock source is the IP bus
+ * clock (IP_CLK) while on the MPC5200B it is the oscillator
* clock (SYS_XTAL_IN).
*/
unsigned int mscan_clock = CONFIG_XENO_DRIVERS_CAN_MSCAN_CLOCK;
@@ -86,11 +86,10 @@ MODULE_PARM_DESC(mscan_clock, "Clock frequency in Hz");
char *mscan_pins = NULL;
module_param(mscan_pins, charp, 0444);
MODULE_PARM_DESC(mscan_pins, "Routing to GPIO pins (PSC2 or I2C1/TMR01)");
-
+
static struct rtcan_device *rtcan_mscan_devs[RTCAN_MSCAN_DEVS];
static int rtcan_mscan_count;
-
/**
* Reception Interrupt handler
*
@@ -103,224 +102,220 @@ static int rtcan_mscan_count;
* @param[in] dev Device ID
*/
static inline void rtcan_mscan_rx_interrupt(struct rtcan_device *dev,
- struct rtcan_skb *skb
- )
+ struct rtcan_skb *skb)
{
- int i;
- unsigned char size;
- struct rtcan_rb_frame *frame = &skb->rb_frame;
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-
- skb->rb_frame_size = EMPTY_RB_FRAME_SIZE;
-
- frame->can_dlc = regs->canrxfg.dlr & 0x0F;
-
- /* If DLC exceeds 8 bytes adjust it to 8 (for the payload size) */
- size = (frame->can_dlc > 8) ? 8 : frame->can_dlc;
-
- if (regs->canrxfg.idr[1] & MSCAN_BUF_EXTENDED) {
- frame->can_id = ((regs->canrxfg.idr[0] << 21) |
- ((regs->canrxfg.idr[1] & 0xE0) << 13) |
- ((regs->canrxfg.idr[1] & 0x07) << 15) |
- (regs->canrxfg.idr[4] << 7) |
- (regs->canrxfg.idr[5] >> 1));
-
- frame->can_id |= CAN_EFF_FLAG;
-
- if ((regs->canrxfg.idr[5] & MSCAN_BUF_EXT_RTR)) {
- frame->can_id |= CAN_RTR_FLAG;
- } else {
- for (i = 0; i < size; i++)
- frame->data[i] = regs->canrxfg.dsr[i + (i / 2) * 2];
- skb->rb_frame_size += size;
- }
-
- } else {
- frame->can_id = ((regs->canrxfg.idr[0] << 3) |
- (regs->canrxfg.idr[1] >> 5));
-
- if ((regs->canrxfg.idr[1] & MSCAN_BUF_STD_RTR)) {
- frame->can_id |= CAN_RTR_FLAG;
- } else {
- for (i = 0; i < size; i++)
- frame->data[i] = regs->canrxfg.dsr[i + (i / 2) * 2];
- skb->rb_frame_size += size;
- }
- }
-
-
- /* Store the interface index */
- frame->can_ifindex = dev->ifindex;
-}
-
+ int i;
+ unsigned char size;
+ struct rtcan_rb_frame *frame = &skb->rb_frame;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-static can_state_t mscan_stat_map[4] = {
- CAN_STATE_ACTIVE,
- CAN_STATE_BUS_WARNING,
- CAN_STATE_BUS_PASSIVE,
- CAN_STATE_BUS_OFF
-};
+ skb->rb_frame_size = EMPTY_RB_FRAME_SIZE;
-static inline void rtcan_mscan_err_interrupt(struct rtcan_device *dev,
- struct rtcan_skb *skb,
- int r_status)
-{
- u8 rstat, tstat;
- struct rtcan_rb_frame *frame = &skb->rb_frame;
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-
- skb->rb_frame_size = EMPTY_RB_FRAME_SIZE + CAN_ERR_DLC;
+ frame->can_dlc = regs->canrxfg.dlr & 0x0F;
- frame->can_id = CAN_ERR_FLAG;
- frame->can_dlc = CAN_ERR_DLC;
+ /* If DLC exceeds 8 bytes adjust it to 8 (for the payload size) */
+ size = (frame->can_dlc > 8) ? 8 : frame->can_dlc;
- memset(&frame->data[0], 0, frame->can_dlc);
+ if (regs->canrxfg.idr[1] & MSCAN_BUF_EXTENDED) {
+ frame->can_id = ((regs->canrxfg.idr[0] << 21) |
+ ((regs->canrxfg.idr[1] & 0xE0) << 13) |
+ ((regs->canrxfg.idr[1] & 0x07) << 15) |
+ (regs->canrxfg.idr[4] << 7) |
+ (regs->canrxfg.idr[5] >> 1));
- if ((r_status & MSCAN_OVRIF)) {
- frame->can_id |= CAN_ERR_CRTL;
- frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ frame->can_id |= CAN_EFF_FLAG;
- } else if ((r_status & (MSCAN_CSCIF))) {
-
- rstat = (r_status & (MSCAN_TSTAT0 |
- MSCAN_TSTAT1)) >> 2 & 0x3;
- tstat = (r_status & (MSCAN_RSTAT0 |
- MSCAN_RSTAT1)) >> 4 & 0x3;
- dev->state = mscan_stat_map[max(rstat, tstat)];
+ if ((regs->canrxfg.idr[5] & MSCAN_BUF_EXT_RTR)) {
+ frame->can_id |= CAN_RTR_FLAG;
+ } else {
+ for (i = 0; i < size; i++)
+ frame->data[i] =
+ regs->canrxfg.dsr[i + (i / 2) * 2];
+ skb->rb_frame_size += size;
+ }
- switch (dev->state) {
- case CAN_STATE_BUS_OFF:
- /* Bus-off condition */
- frame->can_id |= CAN_ERR_BUSOFF;
- dev->state = CAN_STATE_BUS_OFF;
- /* Disable receiver interrupts */
- regs->canrier = 0;
- /* Wake up waiting senders */
- rtdm_sem_destroy(&dev->tx_sem);
- break;
+ } else {
+ frame->can_id = ((regs->canrxfg.idr[0] << 3) |
+ (regs->canrxfg.idr[1] >> 5));
+
+ if ((regs->canrxfg.idr[1] & MSCAN_BUF_STD_RTR)) {
+ frame->can_id |= CAN_RTR_FLAG;
+ } else {
+ for (i = 0; i < size; i++)
+ frame->data[i] =
+ regs->canrxfg.dsr[i + (i / 2) * 2];
+ skb->rb_frame_size += size;
+ }
+ }
- case CAN_STATE_BUS_PASSIVE:
- frame->can_id |= CAN_ERR_CRTL;
- if (tstat > rstat)
- frame->data[1] = CAN_ERR_CRTL_TX_PASSIVE;
- else
- frame->data[1] = CAN_ERR_CRTL_RX_PASSIVE;
- break;
- case CAN_STATE_BUS_WARNING:
- frame->can_id |= CAN_ERR_CRTL;
- if (tstat > rstat)
- frame->data[1] = CAN_ERR_CRTL_TX_WARNING;
- else
- frame->data[1] = CAN_ERR_CRTL_RX_WARNING;
- break;
+ /* Store the interface index */
+ frame->can_ifindex = dev->ifindex;
+}
- default:
- break;
+static can_state_t mscan_stat_map[4] = {
+ CAN_STATE_ACTIVE,
+ CAN_STATE_BUS_WARNING,
+ CAN_STATE_BUS_PASSIVE,
+ CAN_STATE_BUS_OFF
+};
+static inline void rtcan_mscan_err_interrupt(struct rtcan_device *dev,
+ struct rtcan_skb *skb,
+ int r_status)
+{
+ u8 rstat, tstat;
+ struct rtcan_rb_frame *frame = &skb->rb_frame;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
+
+ skb->rb_frame_size = EMPTY_RB_FRAME_SIZE + CAN_ERR_DLC;
+
+ frame->can_id = CAN_ERR_FLAG;
+ frame->can_dlc = CAN_ERR_DLC;
+
+ memset(&frame->data[0], 0, frame->can_dlc);
+
+ if ((r_status & MSCAN_OVRIF)) {
+ frame->can_id |= CAN_ERR_CRTL;
+ frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+ } else if ((r_status & (MSCAN_CSCIF))) {
+
+ rstat = (r_status & (MSCAN_TSTAT0 |
+ MSCAN_TSTAT1)) >> 2 & 0x3;
+ tstat = (r_status & (MSCAN_RSTAT0 |
+ MSCAN_RSTAT1)) >> 4 & 0x3;
+ dev->state = mscan_stat_map[max(rstat, tstat)];
+
+ switch (dev->state) {
+ case CAN_STATE_BUS_OFF:
+ /* Bus-off condition */
+ frame->can_id |= CAN_ERR_BUSOFF;
+ dev->state = CAN_STATE_BUS_OFF;
+ /* Disable receiver interrupts */
+ regs->canrier = 0;
+ /* Wake up waiting senders */
+ rtdm_sem_destroy(&dev->tx_sem);
+ break;
+
+ case CAN_STATE_BUS_PASSIVE:
+ frame->can_id |= CAN_ERR_CRTL;
+ if (tstat > rstat)
+ frame->data[1] = CAN_ERR_CRTL_TX_PASSIVE;
+ else
+ frame->data[1] = CAN_ERR_CRTL_RX_PASSIVE;
+ break;
+
+ case CAN_STATE_BUS_WARNING:
+ frame->can_id |= CAN_ERR_CRTL;
+ if (tstat > rstat)
+ frame->data[1] = CAN_ERR_CRTL_TX_WARNING;
+ else
+ frame->data[1] = CAN_ERR_CRTL_RX_WARNING;
+ break;
+
+ default:
+ break;
+
+ }
}
- }
- /* Store the interface index */
- frame->can_ifindex = dev->ifindex;
+ /* Store the interface index */
+ frame->can_ifindex = dev->ifindex;
}
-
-
/** Interrupt handler */
static int rtcan_mscan_interrupt(rtdm_irq_t *irq_handle)
{
- struct rtcan_skb skb;
- struct rtcan_device *dev;
- struct mscan_regs *regs;
- u8 canrflg;
- int recv_lock_free = 1;
- int ret = RTDM_IRQ_NONE;
+ struct rtcan_skb skb;
+ struct rtcan_device *dev;
+ struct mscan_regs *regs;
+ u8 canrflg;
+ int recv_lock_free = 1;
+ int ret = RTDM_IRQ_NONE;
- dev = (struct rtcan_device *)rtdm_irq_get_arg(irq_handle, void);
- regs = (struct mscan_regs *)dev->base_addr;
+ dev = (struct rtcan_device *)rtdm_irq_get_arg(irq_handle, void);
+ regs = (struct mscan_regs *)dev->base_addr;
- rtdm_lock_get(&dev->device_lock);
+ rtdm_lock_get(&dev->device_lock);
- canrflg = regs->canrflg;
+ canrflg = regs->canrflg;
- ret = RTDM_IRQ_HANDLED;
+ ret = RTDM_IRQ_HANDLED;
- /* Transmit Interrupt? */
- if ((regs->cantier & MSCAN_TXIE0) && (regs->cantflg & MSCAN_TXE0)) {
- regs->cantier = 0;
- /* Wake up a sender */
- rtdm_sem_up(&dev->tx_sem);
+ /* Transmit Interrupt? */
+ if ((regs->cantier & MSCAN_TXIE0) && (regs->cantflg & MSCAN_TXE0)) {
+ regs->cantier = 0;
+ /* Wake up a sender */
+ rtdm_sem_up(&dev->tx_sem);
- if (rtcan_loopback_pending(dev)) {
+ if (rtcan_loopback_pending(dev)) {
- if (recv_lock_free) {
- recv_lock_free = 0;
- rtdm_lock_get(&rtcan_recv_list_lock);
- rtdm_lock_get(&rtcan_socket_lock);
- }
+ if (recv_lock_free) {
+ recv_lock_free = 0;
+ rtdm_lock_get(&rtcan_recv_list_lock);
+ rtdm_lock_get(&rtcan_socket_lock);
+ }
- rtcan_loopback(dev);
+ rtcan_loopback(dev);
+ }
}
- }
-
- /* Wakeup interrupt? */
- if ((canrflg & MSCAN_WUPIF)) {
- rtdm_printk("WUPIF interrupt\n");
- }
-
- /* Receive Interrupt? */
- if ((canrflg & MSCAN_RXF)) {
-
- /* Read out HW registers */
- rtcan_mscan_rx_interrupt(dev, &skb);
-
- /* Take more locks. Ensure that they are taken and
- * released only once in the IRQ handler. */
- /* WARNING: Nested locks are dangerous! But they are
- * nested only in this routine so a deadlock should
- * not be possible. */
- if (recv_lock_free) {
- recv_lock_free = 0;
- rtdm_lock_get(&rtcan_recv_list_lock);
- rtdm_lock_get(&rtcan_socket_lock);
+
+ /* Wakeup interrupt? */
+ if ((canrflg & MSCAN_WUPIF)) {
+ rtdm_printk("WUPIF interrupt\n");
}
-
- /* Pass received frame out to the sockets */
- rtcan_rcv(dev, &skb);
- }
-
- /* Error Interrupt? */
- if ((canrflg & (MSCAN_CSCIF | MSCAN_OVRIF))) {
- /* Check error condition and fill error frame */
- rtcan_mscan_err_interrupt(dev, &skb, canrflg);
-
- if (recv_lock_free) {
- recv_lock_free = 0;
- rtdm_lock_get(&rtcan_recv_list_lock);
- rtdm_lock_get(&rtcan_socket_lock);
+
+ /* Receive Interrupt? */
+ if ((canrflg & MSCAN_RXF)) {
+
+ /* Read out HW registers */
+ rtcan_mscan_rx_interrupt(dev, &skb);
+
+ /* Take more locks. Ensure that they are taken and
+ * released only once in the IRQ handler. */
+ /* WARNING: Nested locks are dangerous! But they are
+ * nested only in this routine so a deadlock should
+ * not be possible. */
+ if (recv_lock_free) {
+ recv_lock_free = 0;
+ rtdm_lock_get(&rtcan_recv_list_lock);
+ rtdm_lock_get(&rtcan_socket_lock);
+ }
+
+ /* Pass received frame out to the sockets */
+ rtcan_rcv(dev, &skb);
}
-
- /* Pass error frame out to the sockets */
- rtcan_rcv(dev, &skb);
- }
-
- /* Acknowledge the handled interrupt within the controller.
- * Only do so for the receiver interrupts.
- */
- if (canrflg)
- regs->canrflg = canrflg;
-
- if (!recv_lock_free) {
- rtdm_lock_put(&rtcan_socket_lock);
- rtdm_lock_put(&rtcan_recv_list_lock);
- }
- rtdm_lock_put(&dev->device_lock);
-
- return ret;
-}
+ /* Error Interrupt? */
+ if ((canrflg & (MSCAN_CSCIF | MSCAN_OVRIF))) {
+ /* Check error condition and fill error frame */
+ rtcan_mscan_err_interrupt(dev, &skb, canrflg);
+ if (recv_lock_free) {
+ recv_lock_free = 0;
+ rtdm_lock_get(&rtcan_recv_list_lock);
+ rtdm_lock_get(&rtcan_socket_lock);
+ }
+
+ /* Pass error frame out to the sockets */
+ rtcan_rcv(dev, &skb);
+ }
+
+ /* Acknowledge the handled interrupt within the controller.
+ * Only do so for the receiver interrupts.
+ */
+ if (canrflg)
+ regs->canrflg = canrflg;
+
+ if (!recv_lock_free) {
+ rtdm_lock_put(&rtcan_socket_lock);
+ rtdm_lock_put(&rtcan_recv_list_lock);
+ }
+ rtdm_lock_put(&dev->device_lock);
+
+ return ret;
+}
/**
* Set controller into reset mode. Called from @ref rtcan_mscan_ioctl
@@ -345,45 +340,43 @@ static int rtcan_mscan_interrupt(rtdm_irq_t *irq_handle)
static int rtcan_mscan_mode_stop(struct rtcan_device *dev,
rtdm_lockctx_t *lock_ctx)
{
- int ret = 0;
- int rinit = 0;
- can_state_t state;
- volatile struct mscan_regs *regs =
- (struct mscan_regs *)dev->base_addr;
- u8 reg;
-
- state = dev->state;
- /* If controller is not operating anyway, go out */
- if (!CAN_STATE_OPERATING(state))
- goto out;
-
- /* Switch to sleep mode */
- regs->canctl0 |= MSCAN_SLPRQ;
- regs->canctl0 |= MSCAN_INITRQ;
-
- reg = regs->canctl1;
- while (!(reg & MSCAN_SLPAK) ||
- !(reg & MSCAN_INITAK)) {
- if (likely(lock_ctx != NULL))
- rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
- /* Busy sleep 1 microsecond */
- rtdm_task_busy_sleep(1000);
- if (likely(lock_ctx != NULL))
- rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
- rinit++;
- reg = regs->canctl1;
- }
+ int ret = 0;
+ int rinit = 0;
+ can_state_t state;
+ volatile struct mscan_regs *regs =
+ (struct mscan_regs *)dev->base_addr;
+ u8 reg;
- /* Volatile state could have changed while we slept busy. */
- dev->state = CAN_STATE_STOPPED;
- /* Wake up waiting senders */
- rtdm_sem_destroy(&dev->tx_sem);
+ state = dev->state;
+ /* If controller is not operating anyway, go out */
+ if (!CAN_STATE_OPERATING(state))
+ goto out;
- out:
- return ret;
-}
+ /* Switch to sleep mode */
+ regs->canctl0 |= MSCAN_SLPRQ;
+ regs->canctl0 |= MSCAN_INITRQ;
+ reg = regs->canctl1;
+ while (!(reg & MSCAN_SLPAK) ||
+ !(reg & MSCAN_INITAK)) {
+ if (likely(lock_ctx != NULL))
+ rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
+ /* Busy sleep 1 microsecond */
+ rtdm_task_busy_sleep(1000);
+ if (likely(lock_ctx != NULL))
+ rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
+ rinit++;
+ reg = regs->canctl1;
+ }
+ /* Volatile state could have changed while we slept busy. */
+ dev->state = CAN_STATE_STOPPED;
+ /* Wake up waiting senders */
+ rtdm_sem_destroy(&dev->tx_sem);
+
+out:
+ return ret;
+}
/**
* Set controller into operating mode.
@@ -405,183 +398,185 @@ static int rtcan_mscan_mode_stop(struct rtcan_device *dev,
static int rtcan_mscan_mode_start(struct rtcan_device *dev,
rtdm_lockctx_t *lock_ctx)
{
- int ret = 0, retries = 0;
- can_state_t state;
- volatile struct mscan_regs *regs =
- (struct mscan_regs *)dev->base_addr;
-
- /* We won't forget that state in the device structure is volatile and
- * access to it will not be optimized by the compiler. So ... */
- state = dev->state;
-
- switch (state) {
- case CAN_STATE_ACTIVE:
- case CAN_STATE_BUS_WARNING:
- case CAN_STATE_BUS_PASSIVE:
- break;
-
- case CAN_STATE_SLEEPING:
- case CAN_STATE_STOPPED:
- /* Set error active state */
- state = CAN_STATE_ACTIVE;
- /* Set up sender "mutex" */
- rtdm_sem_init(&dev->tx_sem, 1);
-
- if ((dev->ctrl_mode & CAN_CTRLMODE_LISTENONLY)) {
- regs->canctl1 |= MSCAN_LISTEN;
- } else {
- regs->canctl1 &= ~MSCAN_LISTEN;
- }
- if ((dev->ctrl_mode & CAN_CTRLMODE_LOOPBACK)) {
- regs->canctl1 |= MSCAN_LOOPB;
- } else {
- regs->canctl1 &= ~MSCAN_LOOPB;
- }
+ int ret = 0, retries = 0;
+ can_state_t state;
+ volatile struct mscan_regs *regs =
+ (struct mscan_regs *)dev->base_addr;
- /* Switch to normal mode */
- regs->canctl0 &= ~MSCAN_INITRQ;
- regs->canctl0 &= ~MSCAN_SLPRQ;
- while ((regs->canctl1 & MSCAN_INITAK) ||
- (regs->canctl1 & MSCAN_SLPAK)) {
- if (likely(lock_ctx != NULL))
- rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
- /* Busy sleep 1 microsecond */
- rtdm_task_busy_sleep(1000);
- if (likely(lock_ctx != NULL))
- rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
- retries++;
- }
- /* Enable interrupts */
- regs->canrier |= MSCAN_RIER;
+ /* We won't forget that state in the device structure is volatile and
+ * access to it will not be optimized by the compiler. So ... */
+ state = dev->state;
- break;
+ switch (state) {
+ case CAN_STATE_ACTIVE:
+ case CAN_STATE_BUS_WARNING:
+ case CAN_STATE_BUS_PASSIVE:
+ break;
- case CAN_STATE_BUS_OFF:
- /* Trigger bus-off recovery */
- regs->canrier = MSCAN_RIER;
- /* Set up sender "mutex" */
- rtdm_sem_init(&dev->tx_sem, 1);
- /* Set error active state */
- state = CAN_STATE_ACTIVE;
+ case CAN_STATE_SLEEPING:
+ case CAN_STATE_STOPPED:
+ /* Set error active state */
+ state = CAN_STATE_ACTIVE;
+ /* Set up sender "mutex" */
+ rtdm_sem_init(&dev->tx_sem, 1);
+
+ if ((dev->ctrl_mode & CAN_CTRLMODE_LISTENONLY)) {
+ regs->canctl1 |= MSCAN_LISTEN;
+ } else {
+ regs->canctl1 &= ~MSCAN_LISTEN;
+ }
+ if ((dev->ctrl_mode & CAN_CTRLMODE_LOOPBACK)) {
+ regs->canctl1 |= MSCAN_LOOPB;
+ } else {
+ regs->canctl1 &= ~MSCAN_LOOPB;
+ }
+
+ /* Switch to normal mode */
+ regs->canctl0 &= ~MSCAN_INITRQ;
+ regs->canctl0 &= ~MSCAN_SLPRQ;
+ while ((regs->canctl1 & MSCAN_INITAK) ||
+ (regs->canctl1 & MSCAN_SLPAK)) {
+ if (likely(lock_ctx != NULL))
+ rtdm_lock_put_irqrestore(&dev->device_lock,
+ *lock_ctx);
+ /* Busy sleep 1 microsecond */
+ rtdm_task_busy_sleep(1000);
+ if (likely(lock_ctx != NULL))
+ rtdm_lock_get_irqsave(&dev->device_lock,
+ *lock_ctx);
+ retries++;
+ }
+ /* Enable interrupts */
+ regs->canrier |= MSCAN_RIER;
- break;
+ break;
+
+ case CAN_STATE_BUS_OFF:
+ /* Trigger bus-off recovery */
+ regs->canrier = MSCAN_RIER;
+ /* Set up sender "mutex" */
+ rtdm_sem_init(&dev->tx_sem, 1);
+ /* Set error active state */
+ state = CAN_STATE_ACTIVE;
- default:
- /* Never reached, but we don't want nasty compiler warnings ... */
- break;
- }
- /* Store new state in device structure (or old state) */
- dev->state = state;
+ break;
- return ret;
+ default:
+ /* Never reached, but we don't want nasty compiler warnings */
+ break;
+ }
+ /* Store new state in device structure (or old state) */
+ dev->state = state;
+
+ return ret;
}
-int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
+int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
struct can_bittime *bit_time,
rtdm_lockctx_t *lock_ctx)
{
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
- u8 btr0, btr1;
-
- switch (bit_time->type) {
- case CAN_BITTIME_BTR:
- btr0 = bit_time->btr.btr0;
- btr1 = bit_time->btr.btr1;
- break;
-
- case CAN_BITTIME_STD:
- btr0 = (BTR0_SET_BRP(bit_time->std.brp) |
- BTR0_SET_SJW(bit_time->std.sjw));
- btr1 = (BTR1_SET_TSEG1(bit_time->std.prop_seg +
- bit_time->std.phase_seg1) |
- BTR1_SET_TSEG2(bit_time->std.phase_seg2) |
- BTR1_SET_SAM(bit_time->std.sam));
- break;
-
- default:
- return -EINVAL;
- }
-
- regs->canbtr0 = btr0;
- regs->canbtr1 = btr1;
-
- rtdm_printk("%s: btr0=0x%02x btr1=0x%02x\n", dev->name, btr0, btr1);
-
- return 0;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
+ u8 btr0, btr1;
+
+ switch (bit_time->type) {
+ case CAN_BITTIME_BTR:
+ btr0 = bit_time->btr.btr0;
+ btr1 = bit_time->btr.btr1;
+ break;
+
+ case CAN_BITTIME_STD:
+ btr0 = (BTR0_SET_BRP(bit_time->std.brp) |
+ BTR0_SET_SJW(bit_time->std.sjw));
+ btr1 = (BTR1_SET_TSEG1(bit_time->std.prop_seg +
+ bit_time->std.phase_seg1) |
+ BTR1_SET_TSEG2(bit_time->std.phase_seg2) |
+ BTR1_SET_SAM(bit_time->std.sam));
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ regs->canbtr0 = btr0;
+ regs->canbtr1 = btr1;
+
+ rtdm_printk("%s: btr0=0x%02x btr1=0x%02x\n", dev->name, btr0, btr1);
+
+ return 0;
}
-int rtcan_mscan_set_mode(struct rtcan_device *dev,
+int rtcan_mscan_set_mode(struct rtcan_device *dev,
can_mode_t mode,
rtdm_lockctx_t *lock_ctx)
{
- int ret = 0, retries = 0;
- can_state_t state;
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-
- switch (mode) {
+ int ret = 0, retries = 0;
+ can_state_t state;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
- case CAN_MODE_STOP:
- ret = rtcan_mscan_mode_stop(dev, lock_ctx);
- break;
+ switch (mode) {
- case CAN_MODE_START:
- ret = rtcan_mscan_mode_start(dev, lock_ctx);
- break;
+ case CAN_MODE_STOP:
+ ret = rtcan_mscan_mode_stop(dev, lock_ctx);
+ break;
- case CAN_MODE_SLEEP:
-
- state = dev->state;
-
- /* Controller must operate, otherwise go out */
- if (!CAN_STATE_OPERATING(state)) {
- ret = -ENETDOWN;
- goto mode_sleep_out;
- }
-
- /* Is controller sleeping yet? If yes, go out */
- if (state == CAN_STATE_SLEEPING)
- goto mode_sleep_out;
-
- /* Remember into which state to return when we
- * wake up */
- dev->state_before_sleep = state;
- state = CAN_STATE_SLEEPING;
-
- /* Let's take a nap. (Now I REALLY understand
- * the meaning of interrupts ...) */
- regs->canrier = 0;
- regs->cantier = 0;
- regs->canctl0 |= MSCAN_SLPRQ /*| MSCAN_INITRQ*/ | MSCAN_WUPE;
- while (!(regs->canctl1 & MSCAN_SLPAK)) {
- rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
- /* Busy sleep 1 microsecond */
- rtdm_task_busy_sleep(1000);
- rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
- if (retries++ >= 1000)
+ case CAN_MODE_START:
+ ret = rtcan_mscan_mode_start(dev, lock_ctx);
break;
- }
- rtdm_printk("Fallen asleep after %d tries.\n", retries);
- regs->canctl0 &= ~MSCAN_INITRQ;
- while ((regs->canctl1 & MSCAN_INITAK)) {
- rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
- /* Busy sleep 1 microsecond */
- rtdm_task_busy_sleep(1000);
- rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
- if (retries++ >= 1000)
+
+ case CAN_MODE_SLEEP:
+
+ state = dev->state;
+
+ /* Controller must operate, otherwise go out */
+ if (!CAN_STATE_OPERATING(state)) {
+ ret = -ENETDOWN;
+ goto mode_sleep_out;
+ }
+
+ /* Is controller sleeping yet? If yes, go out */
+ if (state == CAN_STATE_SLEEPING)
+ goto mode_sleep_out;
+
+ /* Remember into which state to return when we
+ * wake up */
+ dev->state_before_sleep = state;
+ state = CAN_STATE_SLEEPING;
+
+ /* Let's take a nap. (Now I REALLY understand
+ * the meaning of interrupts ...) */
+ regs->canrier = 0;
+ regs->cantier = 0;
+ regs->canctl0 |= MSCAN_SLPRQ /*| MSCAN_INITRQ*/ | MSCAN_WUPE;
+ while (!(regs->canctl1 & MSCAN_SLPAK)) {
+ rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
+ /* Busy sleep 1 microsecond */
+ rtdm_task_busy_sleep(1000);
+ rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
+ if (retries++ >= 1000)
+ break;
+ }
+ rtdm_printk("Fallen asleep after %d tries.\n", retries);
+ regs->canctl0 &= ~MSCAN_INITRQ;
+ while ((regs->canctl1 & MSCAN_INITAK)) {
+ rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
+ /* Busy sleep 1 microsecond */
+ rtdm_task_busy_sleep(1000);
+ rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
+ if (retries++ >= 1000)
+ break;
+ }
+ rtdm_printk("Back to normal after %d tries.\n", retries);
+ regs->canrier = MSCAN_WUPIE;
+
+ mode_sleep_out:
+ dev->state = state;
break;
- }
- rtdm_printk("Back to normal after %d tries.\n", retries);
- regs->canrier = MSCAN_WUPIE;
-
- mode_sleep_out:
- dev->state = state;
- break;
- default:
- ret = -EOPNOTSUPP;
- }
+ default:
+ ret = -EOPNOTSUPP;
+ }
- return ret;
+ return ret;
}
/**
@@ -594,81 +589,80 @@ int rtcan_mscan_set_mode(struct rtcan_device *dev,
* @param[in] frame Pointer to CAN frame which is about to be sent
* @param[in] dev Device ID
*/
-static int rtcan_mscan_start_xmit(struct rtcan_device *dev,
- can_frame_t *frame)
+static int rtcan_mscan_start_xmit(struct rtcan_device *dev, can_frame_t *frame)
{
- int i, id;
- /* "Real" size of the payload */
- unsigned char size;
- /* Content of frame information register */
- unsigned char dlc;
-
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
-
- /* Is TX buffer empty? */
- if (!(regs->cantflg & MSCAN_TXE0)) {
- rtdm_printk("rtcan_mscan_start_xmit: TX buffer not empty");
- return -EIO;
- }
- /* Select the buffer we've found. */
- regs->cantbsel = MSCAN_TXE0;
-
- /* Get DLC and ID */
- dlc = frame->can_dlc;
-
- /* If DLC exceeds 8 bytes adjust it to 8 (for the payload) */
- size = (dlc > 8) ? 8 : dlc;
-
- id = frame->can_id;
- if (frame->can_id & CAN_EFF_FLAG) {
- regs->cantxfg.idr[0] = (id & 0x1fe00000) >> 21;
- regs->cantxfg.idr[1] = (id & 0x001c0000) >> 13;
- regs->cantxfg.idr[1] |= (id & 0x00038000) >> 15;
- regs->cantxfg.idr[1] |= 0x18; /* set SRR and IDE bits */
-
- regs->cantxfg.idr[4] = (id & 0x00007f80) >> 7 ;
- regs->cantxfg.idr[5] = (id & 0x0000007f) << 1 ;
-
- /* RTR? */
- if (frame->can_id & CAN_RTR_FLAG)
- regs->cantxfg.idr[5] |= 0x1;
- else {
- regs->cantxfg.idr[5] &= ~0x1;
- /* No RTR, write data bytes */
- for (i = 0; i < size; i++)
- regs->cantxfg.dsr[i + (i / 2) * 2] = frame->data[i];
- }
-
- } else {
- /* Send standard frame */
-
- regs->cantxfg.idr[0] = (id & 0x000007f8) >> 3;
- regs->cantxfg.idr[1] = (id & 0x00000007) << 5;
-
- /* RTR? */
- if (frame->can_id & CAN_RTR_FLAG)
- regs->cantxfg.idr[1] |= 0x10;
- else {
- regs->cantxfg.idr[1] &= ~0x10;
- /* No RTR, write data bytes */
- for (i = 0; i < size; i++)
- regs->cantxfg.dsr[i + (i / 2) * 2] = frame->data[i];
- }
- }
-
- regs->cantxfg.dlr = frame->can_dlc;
- regs->cantxfg.tbpr = 0; /* all messages have the same prio */
-
- /* Trigger transmission. */
- regs->cantflg = MSCAN_TXE0;
-
- /* Enable interrupt. */
- regs->cantier |= MSCAN_TXIE0;
-
- return 0;
-}
+ int i, id;
+ /* "Real" size of the payload */
+ unsigned char size;
+ /* Content of frame information register */
+ unsigned char dlc;
+
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
+
+ /* Is TX buffer empty? */
+ if (!(regs->cantflg & MSCAN_TXE0)) {
+ rtdm_printk("rtcan_mscan_start_xmit: TX buffer not empty");
+ return -EIO;
+ }
+ /* Select the buffer we've found. */
+ regs->cantbsel = MSCAN_TXE0;
+
+ /* Get DLC and ID */
+ dlc = frame->can_dlc;
+
+ /* If DLC exceeds 8 bytes adjust it to 8 (for the payload) */
+ size = (dlc > 8) ? 8 : dlc;
+
+ id = frame->can_id;
+ if (frame->can_id & CAN_EFF_FLAG) {
+ regs->cantxfg.idr[0] = (id & 0x1fe00000) >> 21;
+ regs->cantxfg.idr[1] = (id & 0x001c0000) >> 13;
+ regs->cantxfg.idr[1] |= (id & 0x00038000) >> 15;
+ regs->cantxfg.idr[1] |= 0x18; /* set SRR and IDE bits */
+
+ regs->cantxfg.idr[4] = (id & 0x00007f80) >> 7 ;
+ regs->cantxfg.idr[5] = (id & 0x0000007f) << 1 ;
+
+ /* RTR? */
+ if (frame->can_id & CAN_RTR_FLAG)
+ regs->cantxfg.idr[5] |= 0x1;
+ else {
+ regs->cantxfg.idr[5] &= ~0x1;
+ /* No RTR, write data bytes */
+ for (i = 0; i < size; i++)
+ regs->cantxfg.dsr[i + (i / 2) * 2] =
+ frame->data[i];
+ }
+ } else {
+ /* Send standard frame */
+
+ regs->cantxfg.idr[0] = (id & 0x000007f8) >> 3;
+ regs->cantxfg.idr[1] = (id & 0x00000007) << 5;
+
+ /* RTR? */
+ if (frame->can_id & CAN_RTR_FLAG)
+ regs->cantxfg.idr[1] |= 0x10;
+ else {
+ regs->cantxfg.idr[1] &= ~0x10;
+ /* No RTR, write data bytes */
+ for (i = 0; i < size; i++)
+ regs->cantxfg.dsr[i + (i / 2) * 2] =
+ frame->data[i];
+ }
+ }
+ regs->cantxfg.dlr = frame->can_dlc;
+ regs->cantxfg.tbpr = 0; /* all messages have the same prio */
+
+ /* Trigger transmission. */
+ regs->cantflg = MSCAN_TXE0;
+
+ /* Enable interrupt. */
+ regs->cantier |= MSCAN_TXIE0;
+
+ return 0;
+}
/**
* MSCAN Chip configuration
@@ -682,231 +676,231 @@ static int rtcan_mscan_start_xmit(struct rtcan_device *dev,
*/
static inline void __init mscan_chip_config(struct mscan_regs *regs)
{
- /* Choose IP bus as clock source.
- */
- regs->canctl1 |= MSCAN_CLKSRC;
- regs->canctl1 &= ~MSCAN_LISTEN;
-
- /* Configure MSCAN to accept all incoming messages.
- */
- regs->canidar0 = regs->canidar1 = 0x00;
- regs->canidar2 = regs->canidar3 = 0x00;
- regs->canidmr0 = regs->canidmr1 = 0xFF;
- regs->canidmr2 = regs->canidmr3 = 0xFF;
- regs->canidar4 = regs->canidar5 = 0x00;
- regs->canidar6 = regs->canidar7 = 0x00;
- regs->canidmr4 = regs->canidmr5 = 0xFF;
- regs->canidmr6 = regs->canidmr7 = 0xFF;
- regs->canidac &= ~(MSCAN_IDAM0 | MSCAN_IDAM1);
+ /* Choose IP bus as clock source.
+ */
+ regs->canctl1 |= MSCAN_CLKSRC;
+ regs->canctl1 &= ~MSCAN_LISTEN;
+
+ /* Configure MSCAN to accept all incoming messages.
+ */
+ regs->canidar0 = regs->canidar1 = 0x00;
+ regs->canidar2 = regs->canidar3 = 0x00;
+ regs->canidmr0 = regs->canidmr1 = 0xFF;
+ regs->canidmr2 = regs->canidmr3 = 0xFF;
+ regs->canidar4 = regs->canidar5 = 0x00;
+ regs->canidar6 = regs->canidar7 = 0x00;
+ regs->canidmr4 = regs->canidmr5 = 0xFF;
+ regs->canidmr6 = regs->canidmr7 = 0xFF;
+ regs->canidac &= ~(MSCAN_IDAM0 | MSCAN_IDAM1);
}
static inline void __init mscan_gpio_config(void)
{
- struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
- int can_to_psc2 = -1;
+ struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
+ int can_to_psc2 = -1;
#if defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_ALT)
- can_to_psc2 = 0;
+ can_to_psc2 = 0;
#elif defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_PSC2)
- can_to_psc2 = 1;
+ can_to_psc2 = 1;
#endif
- /* Configure CAN routing to GPIO pins.
- */
- if (mscan_pins != NULL) {
- if (strncmp(mscan_pins, "psc2", 4) == 0 ||
- !strncmp(mscan_pins, "PSC2", 4))
- can_to_psc2 = 1;
- else if (strncmp(mscan_pins, "i2c1/tmr01", 10) == 0 ||
- strncmp(mscan_pins, "I2C1/TMR01", 10) == 0)
- can_to_psc2 = 0;
- else {
- printk("Module parameter mscan_pins=%s is invalid. "
- "Please use PSC2 or I2C1/TMR01.\n", mscan_pins);
+ /* Configure CAN routing to GPIO pins.
+ */
+ if (mscan_pins != NULL) {
+ if (strncmp(mscan_pins, "psc2", 4) == 0 ||
+ !strncmp(mscan_pins, "PSC2", 4))
+ can_to_psc2 = 1;
+ else if (strncmp(mscan_pins, "i2c1/tmr01", 10) == 0 ||
+ strncmp(mscan_pins, "I2C1/TMR01", 10) == 0)
+ can_to_psc2 = 0;
+ else {
+ printk("Module parameter mscan_pins=%s is invalid. "
+ "Please use PSC2 or I2C1/TMR01.\n", mscan_pins);
+ }
+ }
+
+ if (!gpio || can_to_psc2 < 0) {
+ printk("%s: use pre-configure CAN routing\n", RTCAN_DRV_NAME);
+ return;
+ }
+
+ if (can_to_psc2) {
+ gpio->port_config &= ~0x10000070;
+ gpio->port_config |= 0x00000010;
+ printk("%s: CAN 1 and 2 routed to PSC2 pins\n", RTCAN_DRV_NAME);
+ } else {
+ gpio->port_config |= 0x10000000;
+ printk("%s: CAN 1 routed to I2C1 pins and CAN2 to TMR01 pins\n",
+ RTCAN_DRV_NAME);
}
- }
-
- if (!gpio || can_to_psc2 < 0) {
- printk("%s: use pre-configure CAN routing\n", RTCAN_DRV_NAME);
- return;
- }
-
- if (can_to_psc2) {
- gpio->port_config &= ~0x10000070;
- gpio->port_config |= 0x00000010;
- printk("%s: CAN 1 and 2 routed to PSC2 pins\n", RTCAN_DRV_NAME);
- } else {
- gpio->port_config |= 0x10000000;
- printk("%s: CAN 1 routed to I2C1 pins and CAN2 to TMR01 pins\n",
- RTCAN_DRV_NAME);
- }
}
-static inline int mscan_get_config(unsigned long *addr,
- unsigned int *irq)
+static inline int mscan_get_config(unsigned long *addr, unsigned int *irq)
{
#if defined(CONFIG_PPC_MERGE) || LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
- /* Use Open Firmware device tree */
- struct device_node *np = NULL;
- unsigned int i;
- int ret;
-
- for (i = 0; i < RTCAN_MSCAN_DEVS; i++) {
- struct resource r[2] = {};
-
- np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan");
- if (np == NULL)
- np = of_find_compatible_node(np, NULL, "mpc5200-mscan");
- if (np == NULL)
- break;
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- return ret;
- of_irq_to_resource(np, 0, &r[1]);
- addr[i] = r[0].start;
- irq[i] = r[1].start;
- rtcan_mscan_count++;
- }
+ /* Use Open Firmware device tree */
+ struct device_node *np = NULL;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < RTCAN_MSCAN_DEVS; i++) {
+ struct resource r[2] = {};
+
+ np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan");
+ if (np == NULL)
+ np = of_find_compatible_node(np, NULL, "mpc5200-mscan");
+ if (np == NULL)
+ break;
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ return ret;
+ of_irq_to_resource(np, 0, &r[1]);
+ addr[i] = r[0].start;
+ irq[i] = r[1].start;
+ rtcan_mscan_count++;
+ }
#else
- addr[0] = MSCAN_CAN1_ADDR;
- irq[0] = MSCAN_CAN1_IRQ;
- addr[1] = MSCAN_CAN2_ADDR;
- irq[1] = MSCAN_CAN2_IRQ;
- rtcan_mscan_count = 2;
+ addr[0] = MSCAN_CAN1_ADDR;
+ irq[0] = MSCAN_CAN1_IRQ;
+ addr[1] = MSCAN_CAN2_ADDR;
+ irq[1] = MSCAN_CAN2_IRQ;
+ rtcan_mscan_count = 2;
#endif
- return 0;
+ return 0;
}
int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
{
- int ret;
- struct rtcan_device *dev;
- struct mscan_regs *regs;
+ int ret;
+ struct rtcan_device *dev;
+ struct mscan_regs *regs;
- if ((dev = rtcan_dev_alloc(0, 0)) == NULL) {
- return -ENOMEM;
- }
+ if ((dev = rtcan_dev_alloc(0, 0)) == NULL) {
+ return -ENOMEM;
+ }
- dev->ctrl_name = mscan_ctlr_name;
- dev->board_name = mscan_board_name;
+ dev->ctrl_name = mscan_ctlr_name;
+ dev->board_name = mscan_board_name;
- dev->can_sys_clock = mscan_clock;
+ dev->can_sys_clock = mscan_clock;
- dev->base_addr = (unsigned long)ioremap(addr, MSCAN_SIZE);
- if (dev->base_addr == 0) {
- ret = -ENOMEM;
- printk("ERROR! ioremap of %#lx failed\n", addr);
- goto out_dev_free;
- }
+ dev->base_addr = (unsigned long)ioremap(addr, MSCAN_SIZE);
+ if (dev->base_addr == 0) {
+ ret = -ENOMEM;
+ printk("ERROR! ioremap of %#lx failed\n", addr);
+ goto out_dev_free;
+ }
- regs = (struct mscan_regs *)dev->base_addr;
+ regs = (struct mscan_regs *)dev->base_addr;
- /* Enable MSCAN module. */
- regs->canctl1 |= MSCAN_CANE;
- udelay(100);
+ /* Enable MSCAN module. */
+ regs->canctl1 |= MSCAN_CANE;
+ udelay(100);
- /* Set dummy state for following call */
- dev->state = CAN_STATE_ACTIVE;
+ /* Set dummy state for following call */
+ dev->state = CAN_STATE_ACTIVE;
- /* Enter reset mode */
- rtcan_mscan_mode_stop(dev, NULL);
+ /* Enter reset mode */
+ rtcan_mscan_mode_stop(dev, NULL);
- /* Give device an interface name (so that programs using this driver
- don't need to know the device ID) */
+ /* Give device an interface name (so that programs using this driver
+ don't need to know the device ID) */
- strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ);
+ strncpy(dev->name, RTCAN_DEV_NAME, IFNAMSIZ);
- 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;
+ 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;
- /* Register IRQ handler and pass device structure as arg */
- ret = rtdm_irq_request(&dev->irq_handle, irq,
- rtcan_mscan_interrupt,
- 0, RTCAN_DRV_NAME, (void *)dev);
- if (ret) {
- printk("ERROR! rtdm_irq_request for IRQ %d failed\n", irq);
- goto out_iounmap;
- }
+ /* Register IRQ handler and pass device structure as arg */
+ ret = rtdm_irq_request(&dev->irq_handle, irq,
+ rtcan_mscan_interrupt,
+ 0, RTCAN_DRV_NAME, (void *)dev);
+ if (ret) {
+ printk("ERROR! rtdm_irq_request for IRQ %d failed\n", irq);
+ goto out_iounmap;
+ }
- mscan_chip_config(regs);
+ mscan_chip_config(regs);
- /* Register RTDM device */
- ret = rtcan_dev_register(dev);
- if (ret) {
- printk(KERN_ERR "ERROR while trying to register RTCAN device!\n");
- goto out_irq_free;
- }
+ /* Register RTDM device */
+ ret = rtcan_dev_register(dev);
+ if (ret) {
+ printk(KERN_ERR
+ "ERROR while trying to register RTCAN device!\n");
+ goto out_irq_free;
+ }
- rtcan_mscan_create_proc(dev);
+ rtcan_mscan_create_proc(dev);
- /* Remember initialized devices */
- rtcan_mscan_devs[idx] = dev;
+ /* Remember initialized devices */
+ rtcan_mscan_devs[idx] = dev;
- printk("%s: %s driver loaded (port %d, base-addr 0x%lx irq %d)\n",
- dev->name, RTCAN_DRV_NAME, idx + 1, addr, irq);
+ printk("%s: %s driver loaded (port %d, base-addr 0x%lx irq %d)\n",
+ dev->name, RTCAN_DRV_NAME, idx + 1, addr, irq);
- return 0;
+ return 0;
out_irq_free:
- rtdm_irq_free(&dev->irq_handle);
+ rtdm_irq_free(&dev->irq_handle);
out_iounmap:
- /* Disable MSCAN module. */
- regs->canctl1 &= ~MSCAN_CANE;
- iounmap((void *)dev->base_addr);
+ /* Disable MSCAN module. */
+ regs->canctl1 &= ~MSCAN_CANE;
+ iounmap((void *)dev->base_addr);
out_dev_free:
- rtcan_dev_free(dev);
+ rtcan_dev_free(dev);
- return ret;
+ return ret;
}
static void rtcan_mscan_exit(void)
{
- int i;
- struct rtcan_device *dev;
+ int i;
+ struct rtcan_device *dev;
- for (i = 0; i < rtcan_mscan_count; i++) {
+ for (i = 0; i < rtcan_mscan_count; i++) {
- if ((dev = rtcan_mscan_devs[i]) == NULL)
- continue;
+ if ((dev = rtcan_mscan_devs[i]) == NULL)
+ continue;
- printk("Unloading %s device %s\n", RTCAN_DRV_NAME, dev->name);
+ printk("Unloading %s device %s\n", RTCAN_DRV_NAME, dev->name);
- rtcan_mscan_mode_stop(dev, NULL);
- rtdm_irq_free(&dev->irq_handle);
- rtcan_mscan_remove_proc(dev);
- rtcan_dev_unregister(dev);
- iounmap((void *)dev->base_addr);
- rtcan_dev_free(dev);
- }
+ rtcan_mscan_mode_stop(dev, NULL);
+ rtdm_irq_free(&dev->irq_handle);
+ rtcan_mscan_remove_proc(dev);
+ rtcan_dev_unregister(dev);
+ iounmap((void *)dev->base_addr);
+ rtcan_dev_free(dev);
+ }
}
static int __init rtcan_mscan_init(void)
{
- int i, err;
- int unsigned long addr[RTCAN_MSCAN_DEVS];
- int irq[RTCAN_MSCAN_DEVS];
-
- if ((err = mscan_get_config(addr, irq)))
- return err;
- mscan_gpio_config();
-
- for (i = 0; i < rtcan_mscan_count; i++) {
- if (!port[i])
- continue;
-
- err = rtcan_mscan_init_one(i, addr[i], irq[i]);
- if (err) {
- rtcan_mscan_exit();
- return err;
+ int i, err;
+ int unsigned long addr[RTCAN_MSCAN_DEVS];
+ int irq[RTCAN_MSCAN_DEVS];
+
+ if ((err = mscan_get_config(addr, irq)))
+ return err;
+ mscan_gpio_config();
+
+ for (i = 0; i < rtcan_mscan_count; i++) {
+ if (!port[i])
+ continue;
+
+ err = rtcan_mscan_init_one(i, addr[i], irq[i]);
+ if (err) {
+ rtcan_mscan_exit();
+ return err;
+ }
}
- }
- return 0;
+ return 0;
}
module_init(rtcan_mscan_init);
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
index c4e02da..5671cad 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
@@ -35,104 +35,104 @@
static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
int count, int *eof, void *data)
{
- struct rtcan_device *dev = (struct rtcan_device *)data;
- struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
- struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
- RTCAN_PROC_PRINT_VARS(80);
-
- if (!RTCAN_PROC_PRINT("MSCAN registers at %p\n", regs))
- goto done;
- if (!RTCAN_PROC_PRINT("canctl0 0x%02x%s%s%s%s%s%s%s%s\n",
- regs->canctl0,
- (regs->canctl0 & MSCAN_RXFRM) ? " rxfrm" :"",
- (regs->canctl0 & MSCAN_RXACT) ? " rxact" :"",
- (regs->canctl0 & MSCAN_CSWAI) ? " cswai" :"",
- (regs->canctl0 & MSCAN_SYNCH) ? " synch" :"",
- (regs->canctl0 & MSCAN_TIME) ? " time" :"",
- (regs->canctl0 & MSCAN_WUPE) ? " wupe" :"",
- (regs->canctl0 & MSCAN_SLPRQ) ? " slprq" :"",
- (regs->canctl0 & MSCAN_INITRQ)? " initrq":"" ))
- goto done;
- if (!RTCAN_PROC_PRINT("canctl1 0x%02x%s%s%s%s%s%s%s\n",
- regs->canctl1,
- (regs->canctl1 & MSCAN_CANE) ? " cane" :"",
- (regs->canctl1 & MSCAN_CLKSRC)? " clksrc":"",
- (regs->canctl1 & MSCAN_LOOPB) ? " loopb" :"",
- (regs->canctl1 & MSCAN_LISTEN)? " listen":"",
- (regs->canctl1 & MSCAN_WUPM) ? " wump" :"",
- (regs->canctl1 & MSCAN_SLPAK) ? " slpak" :"",
- (regs->canctl1 & MSCAN_INITAK)? " initak":""))
- goto done;
- if (!RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr0 )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr1 )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrflg )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrier )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantflg )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantier )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantarq )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantaak )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantbsel)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidac )) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrxerr)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantxerr)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar0)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar1)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar2)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar3)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr0)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr1)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr2)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr3)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar4)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar5)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar6)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar7)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr4)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr5)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr6)) |
- !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr7)))
- goto done;
-
- if (!RTCAN_PROC_PRINT("GPIO registers\n"))
- goto done;
- if (!RTCAN_PROC_PRINT("port_config 0x%08x %s\n", gpio->port_config,
- (gpio->port_config & 0x10000000 ?
- "CAN1 on I2C1, CAN2 on TMR0/1 pins":
- (gpio->port_config & 0x70) == 0x10 ?
- "CAN1/2 on PSC2 pins": "MSCAN1/2 not routed")))
- goto done;
-
- done:
- RTCAN_PROC_PRINT_DONE;
+ struct rtcan_device *dev = (struct rtcan_device *)data;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
+ struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
+ RTCAN_PROC_PRINT_VARS(80);
+
+ if (!RTCAN_PROC_PRINT("MSCAN registers at %p\n", regs))
+ goto done;
+ if (!RTCAN_PROC_PRINT("canctl0 0x%02x%s%s%s%s%s%s%s%s\n",
+ regs->canctl0,
+ (regs->canctl0 & MSCAN_RXFRM) ? " rxfrm" :"",
+ (regs->canctl0 & MSCAN_RXACT) ? " rxact" :"",
+ (regs->canctl0 & MSCAN_CSWAI) ? " cswai" :"",
+ (regs->canctl0 & MSCAN_SYNCH) ? " synch" :"",
+ (regs->canctl0 & MSCAN_TIME) ? " time" :"",
+ (regs->canctl0 & MSCAN_WUPE) ? " wupe" :"",
+ (regs->canctl0 & MSCAN_SLPRQ) ? " slprq" :"",
+ (regs->canctl0 & MSCAN_INITRQ)? " initrq":"" ))
+ goto done;
+ if (!RTCAN_PROC_PRINT("canctl1 0x%02x%s%s%s%s%s%s%s\n",
+ regs->canctl1,
+ (regs->canctl1 & MSCAN_CANE) ? " cane" :"",
+ (regs->canctl1 & MSCAN_CLKSRC)? " clksrc":"",
+ (regs->canctl1 & MSCAN_LOOPB) ? " loopb" :"",
+ (regs->canctl1 & MSCAN_LISTEN)? " listen":"",
+ (regs->canctl1 & MSCAN_WUPM) ? " wump" :"",
+ (regs->canctl1 & MSCAN_SLPAK) ? " slpak" :"",
+ (regs->canctl1 & MSCAN_INITAK)? " initak":""))
+ goto done;
+ if (!RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr0 )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr1 )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrflg )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrier )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantflg )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantier )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantarq )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantaak )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantbsel)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidac )) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canrxerr)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(cantxerr)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar0)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar1)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar2)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar3)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr0)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr1)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr2)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr3)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar4)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar5)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar6)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidar7)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr4)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr5)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr6)) |
+ !RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr7)))
+ goto done;
+
+ if (!RTCAN_PROC_PRINT("GPIO registers\n"))
+ goto done;
+ if (!RTCAN_PROC_PRINT("port_config 0x%08x %s\n", gpio->port_config,
+ (gpio->port_config & 0x10000000 ?
+ "CAN1 on I2C1, CAN2 on TMR0/1 pins":
+ (gpio->port_config & 0x70) == 0x10 ?
+ "CAN1/2 on PSC2 pins": "MSCAN1/2 not routed")))
+ goto done;
+
+done:
+ RTCAN_PROC_PRINT_DONE;
}
int rtcan_mscan_create_proc(struct rtcan_device* dev)
{
- struct proc_dir_entry *proc_entry;
+ struct proc_dir_entry *proc_entry;
- if (!dev->proc_root)
- return -EINVAL;
+ if (!dev->proc_root)
+ return -EINVAL;
- proc_entry = create_proc_entry("registers", S_IFREG | S_IRUGO | S_IWUSR,
- dev->proc_root);
- if (!proc_entry)
- goto error;
- proc_entry->read_proc = rtcan_mscan_proc_regs;
- proc_entry->data = dev;
+ proc_entry = create_proc_entry("registers", S_IFREG | S_IRUGO | S_IWUSR,
+ dev->proc_root);
+ if (!proc_entry)
+ goto error;
+ proc_entry->read_proc = rtcan_mscan_proc_regs;
+ proc_entry->data = dev;
- return 0;
+ return 0;
- error:
- printk("%s: unable to create /proc entries for MSCAN\n", dev->name);
- return -1;
+error:
+ printk("%s: unable to create /proc entries for MSCAN\n", dev->name);
+ return -1;
}
void rtcan_mscan_remove_proc(struct rtcan_device* dev)
{
- if (!dev->proc_root)
- return;
+ if (!dev->proc_root)
+ return;
- remove_proc_entry("registers", dev->proc_root);
+ remove_proc_entry("registers", dev->proc_root);
}
#else /* !CONFIG_XENO_DRIVERS_CAN_DEBUG */
@@ -143,6 +143,6 @@ void rtcan_mscan_remove_proc(struct rtcan_device* dev)
int rtcan_mscan_create_proc(struct rtcan_device* dev)
{
- return 0;
+ return 0;
}
#endif /* CONFIG_XENO_DRIVERS_CAN_DEBUG */
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_regs.h b/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
index e6fd7ed..b4652f5 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
@@ -39,12 +39,12 @@ static inline void __iomem *mpc5xxx_gpio_find_and_map(void)
struct device_node *ofn;
ofn = of_find_compatible_node(NULL, NULL, "mpc5200-gpio");
if (!ofn)
- ofn = of_find_compatible_node(NULL, NULL, "fsl,mpc5200-gpio");
+ ofn = of_find_compatible_node(NULL, NULL, "fsl,mpc5200-gpio");
return ofn ? of_iomap(ofn, 0) : NULL;
}
-#define MPC5xxx_GPIO mpc5xxx_gpio_find_and_map()
+#define MPC5xxx_GPIO mpc5xxx_gpio_find_and_map()
#else
-#define MPC5xxx_GPIO mpc52xx_find_and_map("mpc5200-gpio")
+#define MPC5xxx_GPIO mpc52xx_find_and_map("mpc5200-gpio")
#endif
#define mpc5xxx_gpio mpc52xx_gpio
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
@@ -63,7 +63,7 @@ static inline void __iomem *mpc5xxx_gpio_find_and_map(void)
#define MSCAN_CAN1_ADDR (MSCAN_MBAR + 0x0900) /* MSCAN Module 1 */
#define MSCAN_CAN2_ADDR (MSCAN_MBAR + 0x0980) /* MSCAN Module 2 */
-#define MSCAN_SIZE 0x80
+#define MSCAN_SIZE 0x80
/* MSCAN control register 0 (CANCTL0) bits */
#define MSCAN_RXFRM 0x80
@@ -202,35 +202,37 @@ struct mscan_regs {
/* Message type access macros.
*/
-#define MSCAN_BUF_STD_RTR 0x10
-#define MSCAN_BUF_EXT_RTR 0x01
-#define MSCAN_BUF_EXTENDED 0x08
+#define MSCAN_BUF_STD_RTR 0x10
+#define MSCAN_BUF_EXT_RTR 0x01
+#define MSCAN_BUF_EXTENDED 0x08
-#define MSCAN_IDAM1 0x20
+#define MSCAN_IDAM1 0x20
/* Value for the interrupt enable register */
-#define MSCAN_RIER (MSCAN_OVRIE | \
- MSCAN_RXFIE | \
- MSCAN_WUPIF | \
- MSCAN_CSCIE | \
- MSCAN_RSTATE0 | \
- MSCAN_RSTATE1 | \
- MSCAN_TSTATE0 | \
- MSCAN_TSTATE1)
-
-#define BTR0_BRP_MASK 0x3f
-#define BTR0_SJW_SHIFT 6
-#define BTR0_SJW_MASK (0x3 << BTR0_SJW_SHIFT)
-
-#define BTR1_TSEG1_MASK 0xf
-#define BTR1_TSEG2_SHIFT 4
-#define BTR1_TSEG2_MASK (0x7 << BTR1_TSEG2_SHIFT)
-#define BTR1_SAM_SHIFT 7
-
-#define BTR0_SET_BRP(brp) (((brp) - 1) & BTR0_BRP_MASK)
-#define BTR0_SET_SJW(sjw) ((((sjw) - 1) << BTR0_SJW_SHIFT) & BTR0_SJW_MASK)
-
-#define BTR1_SET_TSEG1(tseg1) (((tseg1) - 1) & BTR1_TSEG1_MASK)
-#define BTR1_SET_TSEG2(tseg2) ((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & BTR1_TSEG2_MASK)
-#define BTR1_SET_SAM(sam) (((sam) & 1) << BTR1_SAM_SHIFT)
+#define MSCAN_RIER (MSCAN_OVRIE | \
+ MSCAN_RXFIE | \
+ MSCAN_WUPIF | \
+ MSCAN_CSCIE | \
+ MSCAN_RSTATE0 | \
+ MSCAN_RSTATE1 | \
+ MSCAN_TSTATE0 | \
+ MSCAN_TSTATE1)
+
+#define BTR0_BRP_MASK 0x3f
+#define BTR0_SJW_SHIFT 6
+#define BTR0_SJW_MASK (0x3 << BTR0_SJW_SHIFT)
+
+#define BTR1_TSEG1_MASK 0xf
+#define BTR1_TSEG2_SHIFT 4
+#define BTR1_TSEG2_MASK (0x7 << BTR1_TSEG2_SHIFT)
+#define BTR1_SAM_SHIFT 7
+
+#define BTR0_SET_BRP(brp) (((brp) - 1) & BTR0_BRP_MASK)
+#define BTR0_SET_SJW(sjw) ((((sjw) - 1) << BTR0_SJW_SHIFT) & \
+ BTR0_SJW_MASK)
+
+#define BTR1_SET_TSEG1(tseg1) (((tseg1) - 1) & BTR1_TSEG1_MASK)
+#define BTR1_SET_TSEG2(tseg2) ((((tseg2) - 1) << BTR1_TSEG2_SHIFT) & \
+ BTR1_TSEG2_MASK)
+#define BTR1_SET_SAM(sam) (((sam) & 1) << BTR1_SAM_SHIFT)
#endif /* __RTCAN_MSCAN_REGS_H_ */
--
1.6.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Xenomai-core] [PATCH xenomai-2.5 2/3] rtcan: mscan: use proper io accessor functions for register access
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 1/3] rtcan: mscan: use tabs for indention and white space cleanup Wolfgang Grandegger
@ 2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
0 siblings, 1 reply; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: Wolfgang Grandegger
From: Wolfgang Grandegger <wg@domain.hid>
Signed-off-by: Wolfgang Grandegger <wg@domain.hid>
---
ksrc/drivers/can/mscan/rtcan_mscan.c | 180 +++++++++++++++-------------
ksrc/drivers/can/mscan/rtcan_mscan_proc.c | 48 +++++----
2 files changed, 123 insertions(+), 105 deletions(-)
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan.c b/ksrc/drivers/can/mscan/rtcan_mscan.c
index b5b6489..4975320 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan.c
@@ -111,39 +111,41 @@ static inline void rtcan_mscan_rx_interrupt(struct rtcan_device *dev,
skb->rb_frame_size = EMPTY_RB_FRAME_SIZE;
- frame->can_dlc = regs->canrxfg.dlr & 0x0F;
+ frame->can_dlc = in_8(®s->canrxfg.dlr) & 0x0F;
/* If DLC exceeds 8 bytes adjust it to 8 (for the payload size) */
size = (frame->can_dlc > 8) ? 8 : frame->can_dlc;
- if (regs->canrxfg.idr[1] & MSCAN_BUF_EXTENDED) {
- frame->can_id = ((regs->canrxfg.idr[0] << 21) |
- ((regs->canrxfg.idr[1] & 0xE0) << 13) |
- ((regs->canrxfg.idr[1] & 0x07) << 15) |
- (regs->canrxfg.idr[4] << 7) |
- (regs->canrxfg.idr[5] >> 1));
+ if (in_8(®s->canrxfg.idr[1]) & MSCAN_BUF_EXTENDED) {
+ frame->can_id = ((in_8(®s->canrxfg.idr[0]) << 21) |
+ ((in_8(®s->canrxfg.idr[1]) & 0xE0) << 13) |
+ ((in_8(®s->canrxfg.idr[1]) & 0x07) << 15) |
+ (in_8(®s->canrxfg.idr[4]) << 7) |
+ (in_8(®s->canrxfg.idr[5]) >> 1));
frame->can_id |= CAN_EFF_FLAG;
- if ((regs->canrxfg.idr[5] & MSCAN_BUF_EXT_RTR)) {
+ if ((in_8(®s->canrxfg.idr[5]) & MSCAN_BUF_EXT_RTR)) {
frame->can_id |= CAN_RTR_FLAG;
} else {
for (i = 0; i < size; i++)
frame->data[i] =
- regs->canrxfg.dsr[i + (i / 2) * 2];
+ in_8(®s->canrxfg.dsr[i +
+ (i / 2) * 2]);
skb->rb_frame_size += size;
}
} else {
- frame->can_id = ((regs->canrxfg.idr[0] << 3) |
- (regs->canrxfg.idr[1] >> 5));
+ frame->can_id = ((in_8(®s->canrxfg.idr[0]) << 3) |
+ (in_8(®s->canrxfg.idr[1]) >> 5));
- if ((regs->canrxfg.idr[1] & MSCAN_BUF_STD_RTR)) {
+ if ((in_8(®s->canrxfg.idr[1]) & MSCAN_BUF_STD_RTR)) {
frame->can_id |= CAN_RTR_FLAG;
} else {
for (i = 0; i < size; i++)
frame->data[i] =
- regs->canrxfg.dsr[i + (i / 2) * 2];
+ in_8(®s->canrxfg.dsr[i +
+ (i / 2) * 2]);
skb->rb_frame_size += size;
}
}
@@ -193,7 +195,7 @@ static inline void rtcan_mscan_err_interrupt(struct rtcan_device *dev,
frame->can_id |= CAN_ERR_BUSOFF;
dev->state = CAN_STATE_BUS_OFF;
/* Disable receiver interrupts */
- regs->canrier = 0;
+ out_8(®s->canrier, 0);
/* Wake up waiting senders */
rtdm_sem_destroy(&dev->tx_sem);
break;
@@ -239,13 +241,14 @@ static int rtcan_mscan_interrupt(rtdm_irq_t *irq_handle)
rtdm_lock_get(&dev->device_lock);
- canrflg = regs->canrflg;
+ canrflg = in_8(®s->canrflg);
ret = RTDM_IRQ_HANDLED;
/* Transmit Interrupt? */
- if ((regs->cantier & MSCAN_TXIE0) && (regs->cantflg & MSCAN_TXE0)) {
- regs->cantier = 0;
+ if ((in_8(®s->cantier) & MSCAN_TXIE0) &&
+ (in_8(®s->cantflg) & MSCAN_TXE0)) {
+ out_8(®s->cantier, 0);
/* Wake up a sender */
rtdm_sem_up(&dev->tx_sem);
@@ -306,7 +309,7 @@ static int rtcan_mscan_interrupt(rtdm_irq_t *irq_handle)
* Only do so for the receiver interrupts.
*/
if (canrflg)
- regs->canrflg = canrflg;
+ out_8(®s->canrflg, canrflg);
if (!recv_lock_free) {
rtdm_lock_put(&rtcan_socket_lock);
@@ -343,8 +346,7 @@ static int rtcan_mscan_mode_stop(struct rtcan_device *dev,
int ret = 0;
int rinit = 0;
can_state_t state;
- volatile struct mscan_regs *regs =
- (struct mscan_regs *)dev->base_addr;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
u8 reg;
state = dev->state;
@@ -353,10 +355,10 @@ static int rtcan_mscan_mode_stop(struct rtcan_device *dev,
goto out;
/* Switch to sleep mode */
- regs->canctl0 |= MSCAN_SLPRQ;
- regs->canctl0 |= MSCAN_INITRQ;
+ setbits8(®s->canctl0, MSCAN_SLPRQ);
+ setbits8(®s->canctl0, MSCAN_INITRQ);
- reg = regs->canctl1;
+ reg = in_8(®s->canctl1);
while (!(reg & MSCAN_SLPAK) ||
!(reg & MSCAN_INITAK)) {
if (likely(lock_ctx != NULL))
@@ -366,7 +368,7 @@ static int rtcan_mscan_mode_stop(struct rtcan_device *dev,
if (likely(lock_ctx != NULL))
rtdm_lock_get_irqsave(&dev->device_lock, *lock_ctx);
rinit++;
- reg = regs->canctl1;
+ reg = in_8(®s->canctl1);
}
/* Volatile state could have changed while we slept busy. */
@@ -400,8 +402,7 @@ static int rtcan_mscan_mode_start(struct rtcan_device *dev,
{
int ret = 0, retries = 0;
can_state_t state;
- volatile struct mscan_regs *regs =
- (struct mscan_regs *)dev->base_addr;
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
/* We won't forget that state in the device structure is volatile and
* access to it will not be optimized by the compiler. So ... */
@@ -421,21 +422,21 @@ static int rtcan_mscan_mode_start(struct rtcan_device *dev,
rtdm_sem_init(&dev->tx_sem, 1);
if ((dev->ctrl_mode & CAN_CTRLMODE_LISTENONLY)) {
- regs->canctl1 |= MSCAN_LISTEN;
+ setbits8(®s->canctl1, MSCAN_LISTEN);
} else {
- regs->canctl1 &= ~MSCAN_LISTEN;
+ clrbits8(®s->canctl1, MSCAN_LISTEN);
}
if ((dev->ctrl_mode & CAN_CTRLMODE_LOOPBACK)) {
- regs->canctl1 |= MSCAN_LOOPB;
+ setbits8(®s->canctl1, MSCAN_LOOPB);
} else {
- regs->canctl1 &= ~MSCAN_LOOPB;
+ clrbits8(®s->canctl1, MSCAN_LOOPB);
}
/* Switch to normal mode */
- regs->canctl0 &= ~MSCAN_INITRQ;
- regs->canctl0 &= ~MSCAN_SLPRQ;
- while ((regs->canctl1 & MSCAN_INITAK) ||
- (regs->canctl1 & MSCAN_SLPAK)) {
+ clrbits8(®s->canctl0, MSCAN_INITRQ);
+ clrbits8(®s->canctl0, MSCAN_SLPRQ);
+ while ((in_8(®s->canctl1) & MSCAN_INITAK) ||
+ (in_8(®s->canctl1) & MSCAN_SLPAK)) {
if (likely(lock_ctx != NULL))
rtdm_lock_put_irqrestore(&dev->device_lock,
*lock_ctx);
@@ -447,13 +448,13 @@ static int rtcan_mscan_mode_start(struct rtcan_device *dev,
retries++;
}
/* Enable interrupts */
- regs->canrier |= MSCAN_RIER;
+ setbits8(®s->canrier, MSCAN_RIER);
break;
case CAN_STATE_BUS_OFF:
/* Trigger bus-off recovery */
- regs->canrier = MSCAN_RIER;
+ out_8(®s->canrier, MSCAN_RIER);
/* Set up sender "mutex" */
rtdm_sem_init(&dev->tx_sem, 1);
/* Set error active state */
@@ -497,8 +498,8 @@ int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
return -EINVAL;
}
- regs->canbtr0 = btr0;
- regs->canbtr1 = btr1;
+ out_8(®s->canbtr0, btr0);
+ out_8(®s->canbtr1, btr1);
rtdm_printk("%s: btr0=0x%02x btr1=0x%02x\n", dev->name, btr0, btr1);
@@ -544,10 +545,11 @@ int rtcan_mscan_set_mode(struct rtcan_device *dev,
/* Let's take a nap. (Now I REALLY understand
* the meaning of interrupts ...) */
- regs->canrier = 0;
- regs->cantier = 0;
- regs->canctl0 |= MSCAN_SLPRQ /*| MSCAN_INITRQ*/ | MSCAN_WUPE;
- while (!(regs->canctl1 & MSCAN_SLPAK)) {
+ out_8(®s->canrier, 0);
+ out_8(®s->cantier, 0);
+ setbits8(®s->canctl0,
+ MSCAN_SLPRQ /*| MSCAN_INITRQ*/ | MSCAN_WUPE);
+ while (!(in_8(®s->canctl1) & MSCAN_SLPAK)) {
rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
/* Busy sleep 1 microsecond */
rtdm_task_busy_sleep(1000);
@@ -556,8 +558,8 @@ int rtcan_mscan_set_mode(struct rtcan_device *dev,
break;
}
rtdm_printk("Fallen asleep after %d tries.\n", retries);
- regs->canctl0 &= ~MSCAN_INITRQ;
- while ((regs->canctl1 & MSCAN_INITAK)) {
+ clrbits8(®s->canctl0, MSCAN_INITRQ);
+ while ((in_8(®s->canctl1) & MSCAN_INITAK)) {
rtdm_lock_put_irqrestore(&dev->device_lock, *lock_ctx);
/* Busy sleep 1 microsecond */
rtdm_task_busy_sleep(1000);
@@ -566,7 +568,7 @@ int rtcan_mscan_set_mode(struct rtcan_device *dev,
break;
}
rtdm_printk("Back to normal after %d tries.\n", retries);
- regs->canrier = MSCAN_WUPIE;
+ out_8(®s->canrier, MSCAN_WUPIE);
mode_sleep_out:
dev->state = state;
@@ -596,16 +598,15 @@ static int rtcan_mscan_start_xmit(struct rtcan_device *dev, can_frame_t *frame)
unsigned char size;
/* Content of frame information register */
unsigned char dlc;
-
struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
/* Is TX buffer empty? */
- if (!(regs->cantflg & MSCAN_TXE0)) {
+ if (!(in_8(®s->cantflg) & MSCAN_TXE0)) {
rtdm_printk("rtcan_mscan_start_xmit: TX buffer not empty");
return -EIO;
}
/* Select the buffer we've found. */
- regs->cantbsel = MSCAN_TXE0;
+ out_8(®s->cantbsel, MSCAN_TXE0);
/* Get DLC and ID */
dlc = frame->can_dlc;
@@ -615,51 +616,51 @@ static int rtcan_mscan_start_xmit(struct rtcan_device *dev, can_frame_t *frame)
id = frame->can_id;
if (frame->can_id & CAN_EFF_FLAG) {
- regs->cantxfg.idr[0] = (id & 0x1fe00000) >> 21;
- regs->cantxfg.idr[1] = (id & 0x001c0000) >> 13;
- regs->cantxfg.idr[1] |= (id & 0x00038000) >> 15;
- regs->cantxfg.idr[1] |= 0x18; /* set SRR and IDE bits */
+ out_8(®s->cantxfg.idr[0], (id & 0x1fe00000) >> 21);
+ out_8(®s->cantxfg.idr[1], ((id & 0x001c0000) >> 13) |
+ ((id & 0x00038000) >> 15) |
+ 0x18); /* set SRR and IDE bits */
- regs->cantxfg.idr[4] = (id & 0x00007f80) >> 7 ;
- regs->cantxfg.idr[5] = (id & 0x0000007f) << 1 ;
+ out_8(®s->cantxfg.idr[4], (id & 0x00007f80) >> 7);
+ out_8(®s->cantxfg.idr[5], (id & 0x0000007f) << 1);
/* RTR? */
if (frame->can_id & CAN_RTR_FLAG)
- regs->cantxfg.idr[5] |= 0x1;
+ setbits8(®s->cantxfg.idr[5], 0x1);
else {
- regs->cantxfg.idr[5] &= ~0x1;
+ clrbits8(®s->cantxfg.idr[5], 0x1);
/* No RTR, write data bytes */
for (i = 0; i < size; i++)
- regs->cantxfg.dsr[i + (i / 2) * 2] =
- frame->data[i];
+ out_8(®s->cantxfg.dsr[i + (i / 2) * 2],
+ frame->data[i]);
}
} else {
/* Send standard frame */
- regs->cantxfg.idr[0] = (id & 0x000007f8) >> 3;
- regs->cantxfg.idr[1] = (id & 0x00000007) << 5;
+ out_8(®s->cantxfg.idr[0], (id & 0x000007f8) >> 3);
+ out_8(®s->cantxfg.idr[1], (id & 0x00000007) << 5);
/* RTR? */
if (frame->can_id & CAN_RTR_FLAG)
- regs->cantxfg.idr[1] |= 0x10;
+ setbits8(®s->cantxfg.idr[1], 0x10);
else {
- regs->cantxfg.idr[1] &= ~0x10;
+ clrbits8(®s->cantxfg.idr[1], 0x10);
/* No RTR, write data bytes */
for (i = 0; i < size; i++)
- regs->cantxfg.dsr[i + (i / 2) * 2] =
- frame->data[i];
+ out_8(®s->cantxfg.dsr[i + (i / 2) * 2],
+ frame->data[i]);
}
}
- regs->cantxfg.dlr = frame->can_dlc;
- regs->cantxfg.tbpr = 0; /* all messages have the same prio */
+ out_8(®s->cantxfg.dlr, frame->can_dlc);
+ out_8(®s->cantxfg.tbpr, 0); /* all messages have the same prio */
/* Trigger transmission. */
- regs->cantflg = MSCAN_TXE0;
+ out_8(®s->cantflg, MSCAN_TXE0);
/* Enable interrupt. */
- regs->cantier |= MSCAN_TXIE0;
+ setbits8(®s->cantier, MSCAN_TXIE0);
return 0;
}
@@ -678,26 +679,35 @@ static inline void __init mscan_chip_config(struct mscan_regs *regs)
{
/* Choose IP bus as clock source.
*/
- regs->canctl1 |= MSCAN_CLKSRC;
- regs->canctl1 &= ~MSCAN_LISTEN;
+ setbits8(®s->canctl1, MSCAN_CLKSRC);
+ clrbits8(®s->canctl1, MSCAN_LISTEN);
/* Configure MSCAN to accept all incoming messages.
*/
- regs->canidar0 = regs->canidar1 = 0x00;
- regs->canidar2 = regs->canidar3 = 0x00;
- regs->canidmr0 = regs->canidmr1 = 0xFF;
- regs->canidmr2 = regs->canidmr3 = 0xFF;
- regs->canidar4 = regs->canidar5 = 0x00;
- regs->canidar6 = regs->canidar7 = 0x00;
- regs->canidmr4 = regs->canidmr5 = 0xFF;
- regs->canidmr6 = regs->canidmr7 = 0xFF;
- regs->canidac &= ~(MSCAN_IDAM0 | MSCAN_IDAM1);
+ out_8(®s->canidar0, 0x00);
+ out_8(®s->canidar1, 0x00);
+ out_8(®s->canidar2, 0x00);
+ out_8(®s->canidar3, 0x00);
+ out_8(®s->canidmr0, 0xFF);
+ out_8(®s->canidmr1, 0xFF);
+ out_8(®s->canidmr2, 0xFF);
+ out_8(®s->canidmr3, 0xFF);
+ out_8(®s->canidar4, 0x00);
+ out_8(®s->canidar5, 0x00);
+ out_8(®s->canidar6, 0x00);
+ out_8(®s->canidar7, 0x00);
+ out_8(®s->canidmr4, 0xFF);
+ out_8(®s->canidmr5, 0xFF);
+ out_8(®s->canidmr6, 0xFF);
+ out_8(®s->canidmr7, 0xFF);
+ clrbits8(®s->canidac, MSCAN_IDAM0 | MSCAN_IDAM1);
}
static inline void __init mscan_gpio_config(void)
{
struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
int can_to_psc2 = -1;
+ u32 port_config;
#if defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_ALT)
can_to_psc2 = 0;
@@ -725,15 +735,17 @@ static inline void __init mscan_gpio_config(void)
return;
}
+ port_config = in_be32(&gpio->port_config);
if (can_to_psc2) {
- gpio->port_config &= ~0x10000070;
- gpio->port_config |= 0x00000010;
+ port_config &= ~0x10000070;
+ port_config |= 0x00000010;
printk("%s: CAN 1 and 2 routed to PSC2 pins\n", RTCAN_DRV_NAME);
} else {
- gpio->port_config |= 0x10000000;
+ port_config |= 0x10000000;
printk("%s: CAN 1 routed to I2C1 pins and CAN2 to TMR01 pins\n",
RTCAN_DRV_NAME);
}
+ out_be32(&gpio->port_config, port_config);
}
static inline int mscan_get_config(unsigned long *addr, unsigned int *irq)
@@ -795,7 +807,7 @@ int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
regs = (struct mscan_regs *)dev->base_addr;
/* Enable MSCAN module. */
- regs->canctl1 |= MSCAN_CANE;
+ setbits8(®s->canctl1, MSCAN_CANE);
udelay(100);
/* Set dummy state for following call */
@@ -847,7 +859,7 @@ out_irq_free:
out_iounmap:
/* Disable MSCAN module. */
- regs->canctl1 &= ~MSCAN_CANE;
+ clrbits8(®s->canctl1, MSCAN_CANE);
iounmap((void *)dev->base_addr);
out_dev_free:
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
index 5671cad..cfddfb7 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
@@ -28,7 +28,8 @@
#include "rtcan_internal.h"
#include "rtcan_mscan_regs.h"
-#define MSCAN_REG_ARGS(reg) "%-8s 0x%02x\n", #reg, (int)((regs)->reg) & 0xff
+#define MSCAN_REG_ARGS(reg) \
+ "%-8s 0x%02x\n", #reg, (int)(in_8(®s->reg)) & 0xff
#ifdef CONFIG_XENO_DRIVERS_CAN_DEBUG
@@ -38,30 +39,34 @@ static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
struct rtcan_device *dev = (struct rtcan_device *)data;
struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
+ u8 canctl0, canctl1;
+ u32 port_config;
RTCAN_PROC_PRINT_VARS(80);
if (!RTCAN_PROC_PRINT("MSCAN registers at %p\n", regs))
goto done;
+ canctl0 = in_8(®s->canctl0);
if (!RTCAN_PROC_PRINT("canctl0 0x%02x%s%s%s%s%s%s%s%s\n",
- regs->canctl0,
- (regs->canctl0 & MSCAN_RXFRM) ? " rxfrm" :"",
- (regs->canctl0 & MSCAN_RXACT) ? " rxact" :"",
- (regs->canctl0 & MSCAN_CSWAI) ? " cswai" :"",
- (regs->canctl0 & MSCAN_SYNCH) ? " synch" :"",
- (regs->canctl0 & MSCAN_TIME) ? " time" :"",
- (regs->canctl0 & MSCAN_WUPE) ? " wupe" :"",
- (regs->canctl0 & MSCAN_SLPRQ) ? " slprq" :"",
- (regs->canctl0 & MSCAN_INITRQ)? " initrq":"" ))
+ canctl0,
+ (canctl0 & MSCAN_RXFRM) ? " rxfrm" :"",
+ (canctl0 & MSCAN_RXACT) ? " rxact" :"",
+ (canctl0 & MSCAN_CSWAI) ? " cswai" :"",
+ (canctl0 & MSCAN_SYNCH) ? " synch" :"",
+ (canctl0 & MSCAN_TIME) ? " time" :"",
+ (canctl0 & MSCAN_WUPE) ? " wupe" :"",
+ (canctl0 & MSCAN_SLPRQ) ? " slprq" :"",
+ (canctl0 & MSCAN_INITRQ)? " initrq":"" ))
goto done;
+ canctl1 = in_8(®s->canctl1);
if (!RTCAN_PROC_PRINT("canctl1 0x%02x%s%s%s%s%s%s%s\n",
- regs->canctl1,
- (regs->canctl1 & MSCAN_CANE) ? " cane" :"",
- (regs->canctl1 & MSCAN_CLKSRC)? " clksrc":"",
- (regs->canctl1 & MSCAN_LOOPB) ? " loopb" :"",
- (regs->canctl1 & MSCAN_LISTEN)? " listen":"",
- (regs->canctl1 & MSCAN_WUPM) ? " wump" :"",
- (regs->canctl1 & MSCAN_SLPAK) ? " slpak" :"",
- (regs->canctl1 & MSCAN_INITAK)? " initak":""))
+ canctl1,
+ (canctl1 & MSCAN_CANE) ? " cane" :"",
+ (canctl1 & MSCAN_CLKSRC)? " clksrc":"",
+ (canctl1 & MSCAN_LOOPB) ? " loopb" :"",
+ (canctl1 & MSCAN_LISTEN)? " listen":"",
+ (canctl1 & MSCAN_WUPM) ? " wump" :"",
+ (canctl1 & MSCAN_SLPAK) ? " slpak" :"",
+ (canctl1 & MSCAN_INITAK)? " initak":""))
goto done;
if (!RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr0 )) |
!RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canbtr1 )) |
@@ -95,10 +100,11 @@ static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
if (!RTCAN_PROC_PRINT("GPIO registers\n"))
goto done;
- if (!RTCAN_PROC_PRINT("port_config 0x%08x %s\n", gpio->port_config,
- (gpio->port_config & 0x10000000 ?
+ port_config = in_be32(&gpio->port_config);
+ if (!RTCAN_PROC_PRINT("port_config 0x%08x %s\n", port_config,
+ (port_config & 0x10000000 ?
"CAN1 on I2C1, CAN2 on TMR0/1 pins":
- (gpio->port_config & 0x70) == 0x10 ?
+ (port_config & 0x70) == 0x10 ?
"CAN1/2 on PSC2 pins": "MSCAN1/2 not routed")))
goto done;
--
1.6.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 2/3] rtcan: mscan: use proper io accessor functions for register access Wolfgang Grandegger
@ 2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` Wolfgang Grandegger
0 siblings, 1 reply; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: Wolfgang Grandegger
From: Wolfgang Grandegger <wg@domain.hid>
This patch introduces support for the MPC512x from Freescale. To re-use
the driver initialization code from the new "mpc5xxx_can" driver from
the mainline kernel, the old initialization code for the MPC5200 from
"rtcan_mscan.c" has been moved to "rtcan_mscan_mpc52xx.c", mainly for
backward compatibility with older kernel version. If required, it can
be selected via Kconfig option. The new file "rtcan_mscan_mpc5xxx.c"
adds OF platform driver support for the MPC5200 *and* the MPC512x.
Port and clock selection is done as described for the mpc5xxx_can
mainline driver in "Documentation/powerpc/dts-bindings/fsl/can.txt".
Signed-off-by: Wolfgang Grandegger <wg@domain.hid>
---
ksrc/drivers/can/mscan/Kconfig | 21 ++-
ksrc/drivers/can/mscan/Makefile | 7 +-
ksrc/drivers/can/mscan/rtcan_mscan.c | 255 +++---------------
ksrc/drivers/can/mscan/rtcan_mscan.h | 38 +++
ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c | 254 +++++++++++++++++
ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c | 374 ++++++++++++++++++++++++++
ksrc/drivers/can/mscan/rtcan_mscan_proc.c | 6 +-
ksrc/drivers/can/mscan/rtcan_mscan_regs.h | 8 +
8 files changed, 745 insertions(+), 218 deletions(-)
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan.h
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c
create mode 100644 ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
diff --git a/ksrc/drivers/can/mscan/Kconfig b/ksrc/drivers/can/mscan/Kconfig
index eadad97..c624c88 100644
--- a/ksrc/drivers/can/mscan/Kconfig
+++ b/ksrc/drivers/can/mscan/Kconfig
@@ -1,7 +1,22 @@
config XENO_DRIVERS_CAN_MSCAN
- depends on XENO_DRIVERS_CAN && PPC_MPC52xx
- tristate "MSCAN driver for MPC52xx"
+ depends on XENO_DRIVERS_CAN && (PPC_MPC52xx || PPC_MPC512x)
+ tristate "MSCAN driver for MPC52xx and MPC512x"
default n
+ help
+
+ This driver is for the MSCAN on the MPC5200 and MPC512x processor
+ from Freescale.
+
+config XENO_DRIVERS_CAN_MSCAN_OLD
+ depends on XENO_DRIVERS_CAN_MSCAN && PPC_MPC52xx
+ bool "Use old MSCAN driver for old kernel version"
+ default n
+ help
+
+ For backward compatibility with older kernel versions, you may
+ want to select the old MSCAN driver for the MPC5200.
+
+if XENO_DRIVERS_CAN_MSCAN_OLD
config XENO_DRIVERS_CAN_MSCAN_1
depends on XENO_DRIVERS_CAN_MSCAN
@@ -41,3 +56,5 @@ config XENO_DRIVERS_CAN_MSCAN_PSC2
endchoice
+endif
+
diff --git a/ksrc/drivers/can/mscan/Makefile b/ksrc/drivers/can/mscan/Makefile
index 8976ffe..7ce9249 100644
--- a/ksrc/drivers/can/mscan/Makefile
+++ b/ksrc/drivers/can/mscan/Makefile
@@ -7,6 +7,11 @@ EXTRA_CFLAGS += -D__IN_XENOMAI__ -Iinclude/xenomai -Idrivers/xenomai/can -Idrive
obj-$(CONFIG_XENO_DRIVERS_CAN_MSCAN) += xeno_can_mscan.o
xeno_can_mscan-y := rtcan_mscan.o rtcan_mscan_proc.o
+ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_OLD
+xeno_can_mscan-y += rtcan_mscan_mpc52xx.o
+else
+xeno_can_mscan-y += rtcan_mscan_mpc5xxx.o
+endif
else
@@ -18,7 +23,7 @@ obj-$(CONFIG_XENO_DRIVERS_CAN_MSCAN) := xeno_can_mscan.o
list-multi := xeno_can_mscan.o
-xeno_can_mscan-objs := rtcan_mscan.o rtcan_mscan_proc.o
+xeno_can_mscan-objs := rtcan_mscan.o rtcan_mscan_proc.o rtcan_mscan_mpc52xx.o
export-objs := $(xeno_can_mscan-objs)
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan.c b/ksrc/drivers/can/mscan/rtcan_mscan.c
index 4975320..d25fc5a 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006 Wolfgang Grandegger <wg@domain.hid>
+ * Copyright (C) 2006-2010 Wolfgang Grandegger <wg@domain.hid>
*
* Copyright (C) 2005, 2006 Sebastian Smolorz
* <Sebastian.Smolorz@domain.hid>
@@ -38,57 +38,7 @@
#include "rtcan_raw.h"
#include "rtcan_internal.h"
#include "rtcan_mscan_regs.h"
-
-extern int rtcan_mscan_create_proc(struct rtcan_device* dev);
-extern void rtcan_mscan_remove_proc(struct rtcan_device* dev);
-
-#define RTCAN_DEV_NAME "rtcan%d"
-#define RTCAN_DRV_NAME "MSCAN"
-#define RTCAN_MSCAN_DEVS 2
-
-static char *mscan_ctlr_name = "MSCAN-MPC5200";
-static char *mscan_board_name = "unkown";
-
-MODULE_AUTHOR("Wolfgang Grandegger <wg@domain.hid>");
-MODULE_DESCRIPTION("RT-Socket-CAN driver for MSCAN-MPC2500");
-MODULE_SUPPORTED_DEVICE("MSCAN-MPC5200 CAN controller");
-MODULE_LICENSE("GPL");
-
-/** Module parameter for the CAN controllers' */
-
-int port[RTCAN_MSCAN_DEVS] = {
-#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_1
-#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_2
- 1, 1 /* Enable CAN 1 and 2 */
-#else
- 1, 0 /* Enable CAN 1 only */
-#endif
-#else
-#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_2
- 0, 1 /* Enable CAN 2 only */
-#else
-#error "No CAN controller enabled, fix configuration!"
-#endif
-#endif
-};
-compat_module_param_array(port, int, RTCAN_MSCAN_DEVS, 0444);
-MODULE_PARM_DESC(port, "Enabled CAN ports (1,1 or 0,1 or 0,1)");
-
-/*
- * Note: on the MPC5200 the MSCAN clock source is the IP bus
- * clock (IP_CLK) while on the MPC5200B it is the oscillator
- * clock (SYS_XTAL_IN).
- */
-unsigned int mscan_clock = CONFIG_XENO_DRIVERS_CAN_MSCAN_CLOCK;
-module_param(mscan_clock, int, 0444);
-MODULE_PARM_DESC(mscan_clock, "Clock frequency in Hz");
-
-char *mscan_pins = NULL;
-module_param(mscan_pins, charp, 0444);
-MODULE_PARM_DESC(mscan_pins, "Routing to GPIO pins (PSC2 or I2C1/TMR01)");
-
-static struct rtcan_device *rtcan_mscan_devs[RTCAN_MSCAN_DEVS];
-static int rtcan_mscan_count;
+#include "rtcan_mscan.h"
/**
* Reception Interrupt handler
@@ -472,9 +422,9 @@ static int rtcan_mscan_mode_start(struct rtcan_device *dev,
return ret;
}
-int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
- struct can_bittime *bit_time,
- rtdm_lockctx_t *lock_ctx)
+static int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
+ struct can_bittime *bit_time,
+ rtdm_lockctx_t *lock_ctx)
{
struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
u8 btr0, btr1;
@@ -506,9 +456,9 @@ int rtcan_mscan_set_bit_time(struct rtcan_device *dev,
return 0;
}
-int rtcan_mscan_set_mode(struct rtcan_device *dev,
- can_mode_t mode,
- rtdm_lockctx_t *lock_ctx)
+static int rtcan_mscan_set_mode(struct rtcan_device *dev,
+ can_mode_t mode,
+ rtdm_lockctx_t *lock_ctx)
{
int ret = 0, retries = 0;
can_state_t state;
@@ -675,11 +625,13 @@ static int rtcan_mscan_start_xmit(struct rtcan_device *dev, can_frame_t *frame)
*
* @param[in] dev Device ID of the controller to be configured
*/
-static inline void __init mscan_chip_config(struct mscan_regs *regs)
+static inline void __init mscan_chip_config(struct mscan_regs *regs,
+ int mscan_clksrc)
{
/* Choose IP bus as clock source.
*/
- setbits8(®s->canctl1, MSCAN_CLKSRC);
+ if (mscan_clksrc)
+ setbits8(®s->canctl1, MSCAN_CLKSRC);
clrbits8(®s->canctl1, MSCAN_LISTEN);
/* Configure MSCAN to accept all incoming messages.
@@ -703,107 +655,19 @@ static inline void __init mscan_chip_config(struct mscan_regs *regs)
clrbits8(®s->canidac, MSCAN_IDAM0 | MSCAN_IDAM1);
}
-static inline void __init mscan_gpio_config(void)
-{
- struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
- int can_to_psc2 = -1;
- u32 port_config;
-
-#if defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_ALT)
- can_to_psc2 = 0;
-#elif defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_PSC2)
- can_to_psc2 = 1;
-#endif
-
- /* Configure CAN routing to GPIO pins.
- */
- if (mscan_pins != NULL) {
- if (strncmp(mscan_pins, "psc2", 4) == 0 ||
- !strncmp(mscan_pins, "PSC2", 4))
- can_to_psc2 = 1;
- else if (strncmp(mscan_pins, "i2c1/tmr01", 10) == 0 ||
- strncmp(mscan_pins, "I2C1/TMR01", 10) == 0)
- can_to_psc2 = 0;
- else {
- printk("Module parameter mscan_pins=%s is invalid. "
- "Please use PSC2 or I2C1/TMR01.\n", mscan_pins);
- }
- }
-
- if (!gpio || can_to_psc2 < 0) {
- printk("%s: use pre-configure CAN routing\n", RTCAN_DRV_NAME);
- return;
- }
-
- port_config = in_be32(&gpio->port_config);
- if (can_to_psc2) {
- port_config &= ~0x10000070;
- port_config |= 0x00000010;
- printk("%s: CAN 1 and 2 routed to PSC2 pins\n", RTCAN_DRV_NAME);
- } else {
- port_config |= 0x10000000;
- printk("%s: CAN 1 routed to I2C1 pins and CAN2 to TMR01 pins\n",
- RTCAN_DRV_NAME);
- }
- out_be32(&gpio->port_config, port_config);
-}
-
-static inline int mscan_get_config(unsigned long *addr, unsigned int *irq)
-{
-#if defined(CONFIG_PPC_MERGE) || LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
- /* Use Open Firmware device tree */
- struct device_node *np = NULL;
- unsigned int i;
- int ret;
-
- for (i = 0; i < RTCAN_MSCAN_DEVS; i++) {
- struct resource r[2] = {};
-
- np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan");
- if (np == NULL)
- np = of_find_compatible_node(np, NULL, "mpc5200-mscan");
- if (np == NULL)
- break;
- ret = of_address_to_resource(np, 0, &r[0]);
- if (ret)
- return ret;
- of_irq_to_resource(np, 0, &r[1]);
- addr[i] = r[0].start;
- irq[i] = r[1].start;
- rtcan_mscan_count++;
- }
-#else
- addr[0] = MSCAN_CAN1_ADDR;
- irq[0] = MSCAN_CAN1_IRQ;
- addr[1] = MSCAN_CAN2_ADDR;
- irq[1] = MSCAN_CAN2_IRQ;
- rtcan_mscan_count = 2;
-#endif
- return 0;
-}
-
-int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
+/**
+ * MSCAN Chip registration
+ *
+ * Called during @ref init_module.
+ *
+ * @param[in] dev Device ID of the controller to be registered
+ * @param[in] mscan_clksrc clock source to be used
+ */
+int rtcan_mscan_register(struct rtcan_device *dev, int irq, int mscan_clksrc)
{
int ret;
- struct rtcan_device *dev;
struct mscan_regs *regs;
- if ((dev = rtcan_dev_alloc(0, 0)) == NULL) {
- return -ENOMEM;
- }
-
- dev->ctrl_name = mscan_ctlr_name;
- dev->board_name = mscan_board_name;
-
- dev->can_sys_clock = mscan_clock;
-
- dev->base_addr = (unsigned long)ioremap(addr, MSCAN_SIZE);
- if (dev->base_addr == 0) {
- ret = -ENOMEM;
- printk("ERROR! ioremap of %#lx failed\n", addr);
- goto out_dev_free;
- }
-
regs = (struct mscan_regs *)dev->base_addr;
/* Enable MSCAN module. */
@@ -826,15 +690,14 @@ int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
dev->do_set_bit_time = rtcan_mscan_set_bit_time;
/* Register IRQ handler and pass device structure as arg */
- ret = rtdm_irq_request(&dev->irq_handle, irq,
- rtcan_mscan_interrupt,
+ ret = rtdm_irq_request(&dev->irq_handle, irq, rtcan_mscan_interrupt,
0, RTCAN_DRV_NAME, (void *)dev);
if (ret) {
printk("ERROR! rtdm_irq_request for IRQ %d failed\n", irq);
- goto out_iounmap;
+ goto out_can_disable;
}
- mscan_chip_config(regs);
+ mscan_chip_config(regs, mscan_clksrc);
/* Register RTDM device */
ret = rtcan_dev_register(dev);
@@ -846,74 +709,38 @@ int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
rtcan_mscan_create_proc(dev);
- /* Remember initialized devices */
- rtcan_mscan_devs[idx] = dev;
-
- printk("%s: %s driver loaded (port %d, base-addr 0x%lx irq %d)\n",
- dev->name, RTCAN_DRV_NAME, idx + 1, addr, irq);
-
return 0;
out_irq_free:
rtdm_irq_free(&dev->irq_handle);
-out_iounmap:
+out_can_disable:
/* Disable MSCAN module. */
clrbits8(®s->canctl1, MSCAN_CANE);
- iounmap((void *)dev->base_addr);
-
-out_dev_free:
- rtcan_dev_free(dev);
return ret;
-
}
-static void rtcan_mscan_exit(void)
+/**
+ * MSCAN Chip deregistration
+ *
+ * Called during @ref cleanup_module
+ *
+ * @param[in] dev Device ID of the controller to be registered
+ */
+int rtcan_mscan_unregister(struct rtcan_device *dev)
{
- int i;
- struct rtcan_device *dev;
-
- for (i = 0; i < rtcan_mscan_count; i++) {
-
- if ((dev = rtcan_mscan_devs[i]) == NULL)
- continue;
-
- printk("Unloading %s device %s\n", RTCAN_DRV_NAME, dev->name);
+ struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
- rtcan_mscan_mode_stop(dev, NULL);
- rtdm_irq_free(&dev->irq_handle);
- rtcan_mscan_remove_proc(dev);
- rtcan_dev_unregister(dev);
- iounmap((void *)dev->base_addr);
- rtcan_dev_free(dev);
- }
+ printk("Unregistering %s device %s\n", RTCAN_DRV_NAME, dev->name);
-}
+ rtcan_mscan_mode_stop(dev, NULL);
+ rtdm_irq_free(&dev->irq_handle);
+ rtcan_mscan_remove_proc(dev);
+ rtcan_dev_unregister(dev);
-static int __init rtcan_mscan_init(void)
-{
- int i, err;
- int unsigned long addr[RTCAN_MSCAN_DEVS];
- int irq[RTCAN_MSCAN_DEVS];
-
- if ((err = mscan_get_config(addr, irq)))
- return err;
- mscan_gpio_config();
-
- for (i = 0; i < rtcan_mscan_count; i++) {
- if (!port[i])
- continue;
-
- err = rtcan_mscan_init_one(i, addr[i], irq[i]);
- if (err) {
- rtcan_mscan_exit();
- return err;
- }
- }
+ /* Disable MSCAN module. */
+ clrbits8(®s->canctl1, MSCAN_CANE);
return 0;
}
-
-module_init(rtcan_mscan_init);
-module_exit(rtcan_mscan_exit);
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan.h b/ksrc/drivers/can/mscan/rtcan_mscan.h
new file mode 100644
index 0000000..654a0f5
--- /dev/null
+++ b/ksrc/drivers/can/mscan/rtcan_mscan.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Wolfgang Grandegger <wg@domain.hid>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __RTCAN_MSCAN_H_
+#define __RTCAN_MSCAN_H_
+
+#define RTCAN_DEV_NAME "rtcan%d"
+#define RTCAN_DRV_NAME "rtcan_mscan"
+
+/* MSCAN type variants */
+enum {
+ MSCAN_TYPE_MPC5200,
+ MSCAN_TYPE_MPC5121
+};
+
+extern int rtcan_mscan_register(struct rtcan_device *dev, int irq,
+ int mscan_clksrc);
+extern int rtcan_mscan_unregister(struct rtcan_device *dev);
+
+extern int rtcan_mscan_create_proc(struct rtcan_device* dev);
+extern void rtcan_mscan_remove_proc(struct rtcan_device* dev);
+
+#endif /* __RTCAN_MSCAN_H_ */
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c b/ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c
new file mode 100644
index 0000000..27feaf8
--- /dev/null
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_mpc52xx.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2006-2010 Wolfgang Grandegger <wg@domain.hid>
+ *
+ * Copyright (C) 2005, 2006 Sebastian Smolorz
+ * <Sebastian.Smolorz@domain.hid>
+ *
+ * Derived from the PCAN project file driver/src/pcan_mpc5200.c:
+ *
+ * Copyright (c) 2003 Wolfgang Denk, DENX Software Engineering, wd@domain.hid.
+ *
+ * Copyright (c) 2005 Felix Daners, Plugit AG, felix.daners@domain.hid
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+
+#include <rtdm/rtdm_driver.h>
+
+/* CAN device profile */
+#include <rtdm/rtcan.h>
+#include "rtcan_dev.h"
+#include "rtcan_raw.h"
+#include "rtcan_internal.h"
+#include "rtcan_mscan_regs.h"
+#include "rtcan_mscan.h"
+
+#define RTCAN_MSCAN_DEVS 2
+
+static char *mscan_ctlr_name = "MSCAN-MPC5200";
+static char *mscan_board_name = "unkown";
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@domain.hid>");
+MODULE_DESCRIPTION("RT-Socket-CAN driver for MSCAN-MPC2500");
+MODULE_SUPPORTED_DEVICE("MSCAN-MPC5200 CAN controller");
+MODULE_LICENSE("GPL");
+
+/** Module parameter for the CAN controllers' */
+
+int port[RTCAN_MSCAN_DEVS] = {
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_1
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_2
+ 1, 1 /* Enable CAN 1 and 2 */
+#else
+ 1, 0 /* Enable CAN 1 only */
+#endif
+#else
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_2
+ 0, 1 /* Enable CAN 2 only */
+#else
+#error "No CAN controller enabled, fix configuration!"
+#endif
+#endif
+};
+compat_module_param_array(port, int, RTCAN_MSCAN_DEVS, 0444);
+MODULE_PARM_DESC(port, "Enabled CAN ports (1,1 or 0,1 or 0,1)");
+
+/*
+ * Note: on the MPC5200 the MSCAN clock source is the IP bus
+ * clock (IP_CLK) while on the MPC5200B it is the oscillator
+ * clock (SYS_XTAL_IN).
+ */
+unsigned int mscan_clock = CONFIG_XENO_DRIVERS_CAN_MSCAN_CLOCK;
+module_param(mscan_clock, int, 0444);
+MODULE_PARM_DESC(mscan_clock, "Clock frequency in Hz");
+
+char *mscan_pins = NULL;
+module_param(mscan_pins, charp, 0444);
+MODULE_PARM_DESC(mscan_pins, "Routing to GPIO pins (PSC2 or I2C1/TMR01)");
+
+static struct rtcan_device *rtcan_mscan_devs[RTCAN_MSCAN_DEVS];
+static int rtcan_mscan_count;
+
+static inline void __init mscan_gpio_config(void)
+{
+ struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
+ int can_to_psc2 = -1;
+ u32 port_config;
+
+#if defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_ALT)
+ can_to_psc2 = 0;
+#elif defined(CONFIG_XENO_DRIVERS_CAN_MSCAN_PSC2)
+ can_to_psc2 = 1;
+#endif
+
+ /* Configure CAN routing to GPIO pins.
+ */
+ if (mscan_pins != NULL) {
+ if (strncmp(mscan_pins, "psc2", 4) == 0 ||
+ !strncmp(mscan_pins, "PSC2", 4))
+ can_to_psc2 = 1;
+ else if (strncmp(mscan_pins, "i2c1/tmr01", 10) == 0 ||
+ strncmp(mscan_pins, "I2C1/TMR01", 10) == 0)
+ can_to_psc2 = 0;
+ else {
+ printk("Module parameter mscan_pins=%s is invalid. "
+ "Please use PSC2 or I2C1/TMR01.\n", mscan_pins);
+ }
+ }
+
+ if (!gpio || can_to_psc2 < 0) {
+ printk("%s: use pre-configure CAN routing\n", RTCAN_DRV_NAME);
+ return;
+ }
+
+ port_config = in_be32(&gpio->port_config);
+ if (can_to_psc2) {
+ port_config &= ~0x10000070;
+ port_config |= 0x00000010;
+ printk("%s: CAN 1 and 2 routed to PSC2 pins\n", RTCAN_DRV_NAME);
+ } else {
+ port_config |= 0x10000000;
+ printk("%s: CAN 1 routed to I2C1 pins and CAN2 to TMR01 pins\n",
+ RTCAN_DRV_NAME);
+ }
+ out_be32(&gpio->port_config, port_config);
+}
+
+static inline int mscan_get_config(unsigned long *addr, unsigned int *irq)
+{
+#if defined(CONFIG_PPC_MERGE) || LINUX_VERSION_CODE > KERNEL_VERSION(2,6,27)
+ /* Use Open Firmware device tree */
+ struct device_node *np = NULL;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < RTCAN_MSCAN_DEVS; i++) {
+ struct resource r[2] = {};
+
+ np = of_find_compatible_node(np, NULL, "fsl,mpc5200-mscan");
+ if (np == NULL)
+ np = of_find_compatible_node(np, NULL, "mpc5200-mscan");
+ if (np == NULL)
+ break;
+ ret = of_address_to_resource(np, 0, &r[0]);
+ if (ret)
+ return ret;
+ of_irq_to_resource(np, 0, &r[1]);
+ addr[i] = r[0].start;
+ irq[i] = r[1].start;
+ rtcan_mscan_count++;
+ }
+#else
+ addr[0] = MSCAN_CAN1_ADDR;
+ irq[0] = MSCAN_CAN1_IRQ;
+ addr[1] = MSCAN_CAN2_ADDR;
+ irq[1] = MSCAN_CAN2_IRQ;
+ rtcan_mscan_count = 2;
+#endif
+ return 0;
+}
+
+static int __init rtcan_mscan_init_one(int idx, unsigned long addr, int irq)
+{
+ struct rtcan_device *dev;
+ int ret;
+
+ dev = rtcan_dev_alloc(0, 0);
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev->base_addr = (unsigned long)ioremap(addr, MSCAN_SIZE);
+ if (dev->base_addr == 0) {
+ ret = -ENOMEM;
+ printk("ERROR! ioremap of %#lx failed\n", addr);
+ goto out_dev_free;
+ }
+
+ dev->ctrl_name = mscan_ctlr_name;
+ dev->board_name = mscan_board_name;
+ dev->can_sys_clock = mscan_clock;
+
+ ret = rtcan_mscan_register(dev, irq, 1);
+ if (ret)
+ goto out_iounmap;
+
+ /* Remember initialized devices */
+ rtcan_mscan_devs[idx] = dev;
+
+ printk("%s: %s driver: MSCAN port %d, base-addr 0x%lx, irq %d\n",
+ dev->name, RTCAN_DRV_NAME, idx + 1, addr, irq);
+
+ return 0;
+
+out_iounmap:
+ iounmap((void *)dev->base_addr);
+
+out_dev_free:
+ rtcan_dev_free(dev);
+
+ return ret;
+
+}
+
+static void rtcan_mscan_exit(void)
+{
+ int i;
+ struct rtcan_device *dev;
+
+ for (i = 0; i < rtcan_mscan_count; i++) {
+
+ if ((dev = rtcan_mscan_devs[i]) == NULL)
+ continue;
+
+ printk("Unloading %s device %s\n", RTCAN_DRV_NAME, dev->name);
+
+ rtcan_mscan_unregister(dev);
+ iounmap((void *)dev->base_addr);
+ rtcan_dev_free(dev);
+ }
+
+}
+
+static int __init rtcan_mscan_init(void)
+{
+ int i, err;
+ int unsigned long addr[RTCAN_MSCAN_DEVS];
+ int irq[RTCAN_MSCAN_DEVS];
+
+ if ((err = mscan_get_config(addr, irq)))
+ return err;
+ mscan_gpio_config();
+
+ for (i = 0; i < rtcan_mscan_count; i++) {
+ if (!port[i])
+ continue;
+
+ err = rtcan_mscan_init_one(i, addr[i], irq[i]);
+ if (err) {
+ rtcan_mscan_exit();
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+module_init(rtcan_mscan_init);
+module_exit(rtcan_mscan_exit);
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c b/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
new file mode 100644
index 0000000..48abd89
--- /dev/null
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
@@ -0,0 +1,374 @@
+/*
+ * CAN bus driver for the Freescale MPC5xxx embedded CPU.
+ *
+ * Copyright (C) 2004-2005 Andrey Volkov <avolkov@domain.hid>,
+ * Varma Electronics Oy
+ * Copyright (C) 2008-2010 Wolfgang Grandegger <wg@domain.hid>
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix <w.sang@domain.hid>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/of_platform.h>
+#include <sysdev/fsl_soc.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <asm/mpc52xx.h>
+
+#include "rtcan_dev.h"
+#include "rtcan_mscan_regs.h"
+#include "rtcan_mscan.h"
+
+static char mscan_ctrl_name_mpc5200[] = "MSCAN-MPC5200";
+static char mscan_ctrl_name_mpc512x[] = "MSCAN-MPC512x";
+static char mscan_board_name[] = "unkown";
+
+struct mpc5xxx_can_data {
+ unsigned int type;
+ u32 (*get_clock)(struct of_device *ofdev, const char *clock_name,
+ int *mscan_clksrc);
+};
+
+#ifdef CONFIG_PPC_MPC52xx
+static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = {
+ { .compatible = "fsl,mpc5200-cdm", },
+ {}
+};
+
+static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
+ const char *clock_name,
+ int *mscan_clksrc)
+{
+ unsigned int pvr;
+ struct mpc52xx_cdm __iomem *cdm;
+ struct device_node *np_cdm;
+ unsigned int freq;
+ u32 val;
+
+ pvr = mfspr(SPRN_PVR);
+
+ /*
+ * Either the oscillator clock (SYS_XTAL_IN) or the IP bus clock
+ * (IP_CLK) can be selected as MSCAN clock source. According to
+ * the MPC5200 user's manual, the oscillator clock is the better
+ * choice as it has less jitter. For this reason, it is selected
+ * by default. Unfortunately, it can not be selected for the old
+ * MPC5200 Rev. A chips due to a hardware bug (check errata).
+ */
+ if (clock_name && strcmp(clock_name, "ip") == 0)
+ *mscan_clksrc = MSCAN_CLKSRC_BUS;
+ else
+ *mscan_clksrc = MSCAN_CLKSRC_XTAL;
+
+ freq = mpc5xxx_get_bus_frequency(ofdev->node);
+ if (!freq)
+ return 0;
+
+ if (*mscan_clksrc == MSCAN_CLKSRC_BUS || pvr == 0x80822011)
+ return freq;
+
+ /* Determine SYS_XTAL_IN frequency from the clock domain settings */
+ np_cdm = of_find_matching_node(NULL, mpc52xx_cdm_ids);
+ if (!np_cdm) {
+ dev_err(&ofdev->dev, "can't get clock node!\n");
+ return 0;
+ }
+ cdm = of_iomap(np_cdm, 0);
+
+ if (in_8(&cdm->ipb_clk_sel) & 0x1)
+ freq *= 2;
+ val = in_be32(&cdm->rstcfg);
+
+ freq *= (val & (1 << 5)) ? 8 : 4;
+ freq /= (val & (1 << 6)) ? 12 : 16;
+
+ of_node_put(np_cdm);
+ iounmap(cdm);
+
+ return freq;
+}
+#else /* !CONFIG_PPC_MPC5200 */
+static u32 __devinit mpc52xx_can_get_clock(struct of_device *ofdev,
+ const char *clock_name,
+ int *mscan_clksrc)
+{
+ return 0;
+}
+#endif /* CONFIG_PPC_MPC52xx */
+
+#ifdef CONFIG_PPC_MPC512x
+struct mpc512x_clockctl {
+ u32 spmr; /* System PLL Mode Reg */
+ u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */
+ u32 scfr1; /* System Clk Freq Reg 1 */
+ u32 scfr2; /* System Clk Freq Reg 2 */
+ u32 reserved;
+ u32 bcr; /* Bread Crumb Reg */
+ u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */
+ u32 spccr; /* SPDIF Clk Ctrl Reg */
+ u32 cccr; /* CFM Clk Ctrl Reg */
+ u32 dccr; /* DIU Clk Cnfg Reg */
+ u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */
+};
+
+static struct of_device_id __devinitdata mpc512x_clock_ids[] = {
+ { .compatible = "fsl,mpc5121-clock", },
+ {}
+};
+
+static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
+ const char *clock_name,
+ int *mscan_clksrc)
+{
+ struct mpc512x_clockctl __iomem *clockctl;
+ struct device_node *np_clock;
+ struct clk *sys_clk, *ref_clk;
+ int plen, clockidx, clocksrc = -1;
+ u32 sys_freq, val, clockdiv = 1, freq = 0;
+ const u32 *pval;
+
+ np_clock = of_find_matching_node(NULL, mpc512x_clock_ids);
+ if (!np_clock) {
+ dev_err(&ofdev->dev, "couldn't find clock node\n");
+ return -ENODEV;
+ }
+ clockctl = of_iomap(np_clock, 0);
+ if (!clockctl) {
+ dev_err(&ofdev->dev, "couldn't map clock registers\n");
+ return 0;
+ }
+
+ /* Determine the MSCAN device index from the physical address */
+ pval = of_get_property(ofdev->node, "reg", &plen);
+ BUG_ON(!pval || plen < sizeof(*pval));
+ clockidx = (*pval & 0x80) ? 1 : 0;
+ if (*pval & 0x2000)
+ clockidx += 2;
+
+ /*
+ * Clock source and divider selection: 3 different clock sources
+ * can be selected: "ip", "ref" or "sys". For the latter two, a
+ * clock divider can be defined as well. If the clock source is
+ * not specified by the device tree, we first try to find an
+ * optimal CAN source clock based on the system clock. If that
+ * is not posslible, the reference clock will be used.
+ */
+ if (clock_name && !strcmp(clock_name, "ip")) {
+ *mscan_clksrc = MSCAN_CLKSRC_IPS;
+ freq = mpc5xxx_get_bus_frequency(ofdev->node);
+ } else {
+ *mscan_clksrc = MSCAN_CLKSRC_BUS;
+
+ pval = of_get_property(ofdev->node,
+ "fsl,mscan-clock-divider", &plen);
+ if (pval && plen == sizeof(*pval))
+ clockdiv = *pval;
+ if (!clockdiv)
+ clockdiv = 1;
+
+ if (!clock_name || !strcmp(clock_name, "sys")) {
+ sys_clk = clk_get(&ofdev->dev, "sys_clk");
+ if (!sys_clk) {
+ dev_err(&ofdev->dev, "couldn't get sys_clk\n");
+ goto exit_unmap;
+ }
+ /* Get and round up/down sys clock rate */
+ sys_freq = 1000000 *
+ ((clk_get_rate(sys_clk) + 499999) / 1000000);
+
+ if (!clock_name) {
+ /* A multiple of 16 MHz would be optimal */
+ if ((sys_freq % 16000000) == 0) {
+ clocksrc = 0;
+ clockdiv = sys_freq / 16000000;
+ freq = sys_freq / clockdiv;
+ }
+ } else {
+ clocksrc = 0;
+ freq = sys_freq / clockdiv;
+ }
+ }
+
+ if (clocksrc < 0) {
+ ref_clk = clk_get(&ofdev->dev, "ref_clk");
+ if (!ref_clk) {
+ dev_err(&ofdev->dev, "couldn't get ref_clk\n");
+ goto exit_unmap;
+ }
+ clocksrc = 1;
+ freq = clk_get_rate(ref_clk) / clockdiv;
+ }
+ }
+
+ /* Disable clock */
+ out_be32(&clockctl->mccr[clockidx], 0x0);
+ if (clocksrc >= 0) {
+ /* Set source and divider */
+ val = (clocksrc << 14) | ((clockdiv - 1) << 17);
+ out_be32(&clockctl->mccr[clockidx], val);
+ /* Enable clock */
+ out_be32(&clockctl->mccr[clockidx], val | 0x10000);
+ }
+
+ /* Enable MSCAN clock domain */
+ val = in_be32(&clockctl->sccr[1]);
+ if (!(val & (1 << 25)))
+ out_be32(&clockctl->sccr[1], val | (1 << 25));
+
+ dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n",
+ *mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" :
+ clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv);
+
+exit_unmap:
+ of_node_put(np_clock);
+ iounmap(clockctl);
+
+ return freq;
+}
+#else /* !CONFIG_PPC_MPC512x */
+static u32 __devinit mpc512x_can_get_clock(struct of_device *ofdev,
+ const char *clock_name,
+ int *mscan_clksrc)
+{
+ return 0;
+}
+#endif /* CONFIG_PPC_MPC512x */
+
+static int __devinit mpc5xxx_can_probe(struct of_device *ofdev,
+ const struct of_device_id *id)
+{
+ struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
+ struct device_node *np = ofdev->node;
+ struct rtcan_device *dev;
+ void __iomem *base;
+ const char *clock_name = NULL;
+ int irq, mscan_clksrc = 0;
+ int err = -ENOMEM;
+
+ base = of_iomap(np, 0);
+ if (!base) {
+ dev_err(&ofdev->dev, "couldn't ioremap\n");
+ return err;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ if (!irq) {
+ dev_err(&ofdev->dev, "no irq found\n");
+ err = -ENODEV;
+ goto exit_unmap_mem;
+ }
+
+ dev = rtcan_dev_alloc(0, 0);
+ if (!dev)
+ goto exit_dispose_irq;
+
+ clock_name = of_get_property(np, "fsl,mscan-clock-source", NULL);
+
+ BUG_ON(!data);
+ dev->can_sys_clock = data->get_clock(ofdev, clock_name,
+ &mscan_clksrc);
+ if (!dev->can_sys_clock) {
+ dev_err(&ofdev->dev, "couldn't get MSCAN clock properties\n");
+ goto exit_free_mscan;
+ }
+
+ if (data->type == MSCAN_TYPE_MPC5121)
+ dev->ctrl_name = mscan_ctrl_name_mpc512x;
+ else
+ dev->ctrl_name = mscan_ctrl_name_mpc5200;
+ dev->board_name = mscan_board_name;
+ dev->base_addr = (unsigned long)base;
+
+ err = rtcan_mscan_register(dev, irq, mscan_clksrc);
+ if (err) {
+ dev_err(&ofdev->dev, "registering %s failed (err=%d)\n",
+ RTCAN_DRV_NAME, err);
+ goto exit_free_mscan;
+ }
+
+ dev_set_drvdata(&ofdev->dev, dev);
+
+ dev_info(&ofdev->dev, "MSCAN at 0x%p, irq %d, clock %d Hz\n",
+ base, irq, dev->can_sys_clock);
+
+ return 0;
+
+exit_free_mscan:
+ rtcan_dev_free(dev);
+exit_dispose_irq:
+ irq_dispose_mapping(irq);
+exit_unmap_mem:
+ iounmap(base);
+
+ return err;
+}
+
+static int __devexit mpc5xxx_can_remove(struct of_device *ofdev)
+{
+ struct rtcan_device *dev = dev_get_drvdata(&ofdev->dev);
+
+ dev_set_drvdata(&ofdev->dev, NULL);
+
+ rtcan_mscan_unregister(dev);
+ iounmap((void *)dev->base_addr);
+ rtcan_dev_free(dev);
+
+ return 0;
+}
+
+static struct mpc5xxx_can_data __devinitdata mpc5200_can_data = {
+ .type = MSCAN_TYPE_MPC5200,
+ .get_clock = mpc52xx_can_get_clock,
+};
+
+static struct mpc5xxx_can_data __devinitdata mpc5121_can_data = {
+ .type = MSCAN_TYPE_MPC5121,
+ .get_clock = mpc512x_can_get_clock,
+};
+
+static struct of_device_id __devinitdata mpc5xxx_can_table[] = {
+ { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, },
+ /* Note that only MPC5121 Rev. 2 (and later) is supported */
+ { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
+ {},
+};
+
+static struct of_platform_driver mpc5xxx_can_driver = {
+ .owner = THIS_MODULE,
+ .name = RTCAN_DRV_NAME,
+ .probe = mpc5xxx_can_probe,
+ .remove = __devexit_p(mpc5xxx_can_remove),
+ .match_table = mpc5xxx_can_table,
+};
+
+static int __init mpc5xxx_can_init(void)
+{
+ return of_register_platform_driver(&mpc5xxx_can_driver);
+}
+module_init(mpc5xxx_can_init);
+
+static void __exit mpc5xxx_can_exit(void)
+{
+ return of_unregister_platform_driver(&mpc5xxx_can_driver);
+};
+module_exit(mpc5xxx_can_exit);
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@domain.hid>");
+MODULE_DESCRIPTION("RT-Socket-CAN driver for MPC5200 and MPC521x");
+MODULE_LICENSE("GPL v2");
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
index cfddfb7..13ba8e4 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_proc.c
@@ -38,9 +38,11 @@ static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
{
struct rtcan_device *dev = (struct rtcan_device *)data;
struct mscan_regs *regs = (struct mscan_regs *)dev->base_addr;
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_OLD
struct mpc5xxx_gpio *gpio = (struct mpc5xxx_gpio *)MPC5xxx_GPIO;
- u8 canctl0, canctl1;
u32 port_config;
+#endif
+ u8 canctl0, canctl1;
RTCAN_PROC_PRINT_VARS(80);
if (!RTCAN_PROC_PRINT("MSCAN registers at %p\n", regs))
@@ -98,6 +100,7 @@ static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
!RTCAN_PROC_PRINT(MSCAN_REG_ARGS(canidmr7)))
goto done;
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_OLD
if (!RTCAN_PROC_PRINT("GPIO registers\n"))
goto done;
port_config = in_be32(&gpio->port_config);
@@ -107,6 +110,7 @@ static int rtcan_mscan_proc_regs(char *buf, char **start, off_t offset,
(port_config & 0x70) == 0x10 ?
"CAN1/2 on PSC2 pins": "MSCAN1/2 not routed")))
goto done;
+#endif
done:
RTCAN_PROC_PRINT_DONE;
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_regs.h b/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
index b4652f5..e623b9a 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_regs.h
@@ -25,6 +25,7 @@
#ifndef __RTCAN_MSCAN_REGS_H_
#define __RTCAN_MSCAN_REGS_H_
+#ifdef CONFIG_XENO_DRIVERS_CAN_MSCAN_OLD
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,20)
#include <sysdev/fsl_soc.h>
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)
@@ -60,6 +61,7 @@ static inline void __iomem *mpc5xxx_gpio_find_and_map(void)
#define MPC5xxx_GPIO MPC52xx_VA(MPC52xx_GPIO_OFFSET)
#define mpc5xxx_gpio mpc52xx_gpio
#endif
+#endif
#define MSCAN_CAN1_ADDR (MSCAN_MBAR + 0x0900) /* MSCAN Module 1 */
#define MSCAN_CAN2_ADDR (MSCAN_MBAR + 0x0980) /* MSCAN Module 2 */
@@ -200,6 +202,12 @@ struct mscan_regs {
struct mscan_msgbuf cantxfg; /* MSCAN + 0x60 */ /* Foreground transmit buffer */
};
+/* Clock source selection
+ */
+#define MSCAN_CLKSRC_BUS 0
+#define MSCAN_CLKSRC_XTAL MSCAN_CLKSRC
+#define MSCAN_CLKSRC_IPS MSCAN_CLKSRC
+
/* Message type access macros.
*/
#define MSCAN_BUF_STD_RTR 0x10
--
1.6.2.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
@ 2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:14 ` Wolfgang Grandegger
0 siblings, 2 replies; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: /bin/bash
pdir=../send-rtcan-mscan-mpc5xxx/
sprefix="PATCH xenomai-2.5"
commitid=b197fe0f370d92ee1838b370fbf927ca50a0e573
subject="rtcan: mscan: new OF platform driver for MPC521x and MPC5200"
blurb="\
This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x\\
from Freescale by introducing a new OF platform driver for both, the\\
MPC521x and MPC5200, while still keeping the old driver for the MPC5200\\
for compatibility with older kernel versions.\\
\\
Wolfgang"
rm -f $pdir/*.patch
mkdir $pdir
opt="--dry-run"
test "$1" = "send" && opt=""
git format-patch -n -o $pdir --cover-letter --subject-prefix="$sprefix" \
$commitid
mv $pdir/0000-cover-letter.patch /tmp/0000-cover-letter.patch
sed "
s/\*\*\* SUBJECT HERE \*\*\*/$subject/
s/\*\*\* BLURB HERE \*\*\*/$blurb/
" /tmp/0000-cover-letter.patch > $pdir/0000-cover-letter.patch
echo "====================================================================="
cat $pdir/0000-cover-letter.patch
echo "====================================================================="
opt="--dry-run"
test "$1" = "send" && opt=""
git format-patch -o $pdir --subject-prefix="$sprefix" $commitid
echo "opt=$opt"
git send-email $opt \
--to "Xenomai-core@domain.hid" \
--from="Wolfgang Grandegger <wg@domain.hid>" \
$pdir
^ permalink raw reply [flat|nested] 14+ messages in thread
* [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:07 ` Wolfgang Grandegger
@ 2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:14 ` Wolfgang Grandegger
1 sibling, 0 replies; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:07 UTC (permalink / raw)
To: Xenomai-core; +Cc: /bin/bash
pdir=../send-rtcan-mscan-mpc5xxx/
sprefix="PATCH xenomai-2.5"
commitid=b197fe0f370d92ee1838b370fbf927ca50a0e573
subject="rtcan: mscan: new OF platform driver for MPC521x and MPC5200"
blurb="\
This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
from Freescale by introducing a new OF platform driver for both, the\\
MPC521x and MPC5200, while still keeping the old driver for the MPC5200\\
for compatibility with older kernel versions\\
\\
Wolfgang"
rm -f $pdir/*.patch
mkdir $pdir
opt="--dry-run"
test "$1" = "send" && opt=""
git format-patch -n -o $pdir --cover-letter --subject-prefix="$sprefix" \
$commitid
mv $pdir/0000-cover-letter.patch /tmp/0000-cover-letter.patch
sed "
s/\*\*\* SUBJECT HERE \*\*\*/$subject/
s/\*\*\* BLURB HERE \*\*\*/$blurb/
" /tmp/0000-cover-letter.patch > $pdir/0000-cover-letter.patch
echo "====================================================================="
cat $pdir/0000-cover-letter.patch
echo "====================================================================="
opt="--dry-run"
test "$1" = "send" && opt=""
git format-patch -o $pdir --subject-prefix="$sprefix" $commitid
echo "opt=$opt"
git send-email $opt \
--to "Xenomai-core@domain.hid" \
--from="Wolfgang Grandegger <wg@domain.hid>" \
$pdir
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` Wolfgang Grandegger
@ 2010-01-14 12:14 ` Wolfgang Grandegger
2010-01-14 14:57 ` Gilles Chanteperdrix
1 sibling, 1 reply; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 12:14 UTC (permalink / raw)
To: Xenomai-core
Wolfgang Grandegger wrote:
> pdir=../send-rtcan-mscan-mpc5xxx/
> sprefix="PATCH xenomai-2.5"
> commitid=b197fe0f370d92ee1838b370fbf927ca50a0e573
> subject="rtcan: mscan: new OF platform driver for MPC521x and MPC5200"
> blurb="\
> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x\\
> from Freescale by introducing a new OF platform driver for both, the\\
> MPC521x and MPC5200, while still keeping the old driver for the MPC5200\\
> for compatibility with older kernel versions.\\
> \\
> Wolfgang"
>
> rm -f $pdir/*.patch
> mkdir $pdir
> opt="--dry-run"
> test "$1" = "send" && opt=""
>
> git format-patch -n -o $pdir --cover-letter --subject-prefix="$sprefix" \
> $commitid
>
> mv $pdir/0000-cover-letter.patch /tmp/0000-cover-letter.patch
> sed "
> s/\*\*\* SUBJECT HERE \*\*\*/$subject/
> s/\*\*\* BLURB HERE \*\*\*/$blurb/
> " /tmp/0000-cover-letter.patch > $pdir/0000-cover-letter.patch
>
> echo "====================================================================="
> cat $pdir/0000-cover-letter.patch
> echo "====================================================================="
>
> opt="--dry-run"
> test "$1" = "send" && opt=""
>
> git format-patch -o $pdir --subject-prefix="$sprefix" $commitid
>
> echo "opt=$opt"
> git send-email $opt \
> --to "Xenomai-core@domain.hid" \
> --from="Wolfgang Grandegger <wg@domain.hid>" \
> $pdir
s/$pdir/$pdir/*.patch/
Grrr, due to that mistake in my git-patch-prepare-and-send script, the
script file (and backup) has also been sent to the list as well. Please
ignore the last two patch. Sorry for the noise
Wolfgang.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:14 ` Wolfgang Grandegger
@ 2010-01-14 14:57 ` Gilles Chanteperdrix
2010-01-14 15:05 ` Wolfgang Grandegger
0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-14 14:57 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Xenomai-core
Wolfgang Grandegger wrote:
> Wolfgang Grandegger wrote:
>> pdir=../send-rtcan-mscan-mpc5xxx/
>> sprefix="PATCH xenomai-2.5"
>> commitid=b197fe0f370d92ee1838b370fbf927ca50a0e573
>> subject="rtcan: mscan: new OF platform driver for MPC521x and MPC5200"
>> blurb="\
>> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x\\
>> from Freescale by introducing a new OF platform driver for both, the\\
>> MPC521x and MPC5200, while still keeping the old driver for the MPC5200\\
>> for compatibility with older kernel versions.\\
>> \\
>> Wolfgang"
>>
>> rm -f $pdir/*.patch
>> mkdir $pdir
>> opt="--dry-run"
>> test "$1" = "send" && opt=""
>>
>> git format-patch -n -o $pdir --cover-letter --subject-prefix="$sprefix" \
>> $commitid
>>
>> mv $pdir/0000-cover-letter.patch /tmp/0000-cover-letter.patch
>> sed "
>> s/\*\*\* SUBJECT HERE \*\*\*/$subject/
>> s/\*\*\* BLURB HERE \*\*\*/$blurb/
>> " /tmp/0000-cover-letter.patch > $pdir/0000-cover-letter.patch
>>
>> echo "====================================================================="
>> cat $pdir/0000-cover-letter.patch
>> echo "====================================================================="
>>
>> opt="--dry-run"
>> test "$1" = "send" && opt=""
>>
>> git format-patch -o $pdir --subject-prefix="$sprefix" $commitid
>>
>> echo "opt=$opt"
>> git send-email $opt \
>> --to "Xenomai-core@domain.hid" \
>> --from="Wolfgang Grandegger <wg@domain.hid>" \
>> $pdir
>
> s/$pdir/$pdir/*.patch/
>
> Grrr, due to that mistake in my git-patch-prepare-and-send script, the
> script file (and backup) has also been sent to the list as well. Please
> ignore the last two patch. Sorry for the noise
Hi Wolfgang,
Would you want a git tree on Xenomai server? This way you could use git
push and git-request-pull ?
There is not much point for me in proof-reading your patches, since I do
not know much about rt-socket-can.
Regards.
--
Gilles.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 14:57 ` Gilles Chanteperdrix
@ 2010-01-14 15:05 ` Wolfgang Grandegger
0 siblings, 0 replies; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-14 15:05 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: Xenomai-core
Hi Gilles,
Gilles Chanteperdrix wrote:
...
> Would you want a git tree on Xenomai server? This way you could use git
> push and git-request-pull ?
Well, seems a bit overkill to me at the moment. There are only a few
patches per year related to RT-Socket-CAN. If you think it does easy
your work, please let me know.
> There is not much point for me in proof-reading your patches, since I do
> not know much about rt-socket-can.
No problem. I'm happy if you just apply it ;-).
Thanks,
Wolfgang.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-14 12:07 [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 1/3] rtcan: mscan: use tabs for indention and white space cleanup Wolfgang Grandegger
@ 2010-01-15 14:08 ` Gilles Chanteperdrix
2010-01-15 14:26 ` Wolfgang Grandegger
1 sibling, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-15 14:08 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Xenomai-core, Wolfgang Grandegger
Wolfgang Grandegger wrote:
> From: Wolfgang Grandegger <wg@domain.hid>
>
> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
> from Freescale by introducing a new OF platform driver for both, the
> MPC521x and MPC5200, while still keeping the old driver for the MPC5200
> for compatibility with older kernel versions.
Hi Wolfgang,
there seems to be something missing, because I get a compilation error
on lite-5200:
http://sisyphus.hd.free.fr/~gilles/bx/#powerpc
Regards.
--
Gilles.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-15 14:08 ` [Xenomai-core] [PATCH xenomai-2.5 0/3] " Gilles Chanteperdrix
@ 2010-01-15 14:26 ` Wolfgang Grandegger
2010-01-15 18:10 ` Gilles Chanteperdrix
0 siblings, 1 reply; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-15 14:26 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: Xenomai-core, Wolfgang Grandegger
Gilles Chanteperdrix wrote:
> Wolfgang Grandegger wrote:
>> From: Wolfgang Grandegger <wg@domain.hid>
>>
>> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
>> from Freescale by introducing a new OF platform driver for both, the
>> MPC521x and MPC5200, while still keeping the old driver for the MPC5200
>> for compatibility with older kernel versions.
>
> Hi Wolfgang,
>
> there seems to be something missing, because I get a compilation error
> on lite-5200:
> http://sisyphus.hd.free.fr/~gilles/bx/#powerpc
Well, I obviously did not test the driver with old versions of the Linux
kernel, sorry. For 2.6.29 and 2.6.30 the following patch should fix the
build:
diff --git a/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
b/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
index 48abd89..47e34b6 100644
--- a/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
+++ b/ksrc/drivers/can/mscan/rtcan_mscan_mpc5xxx.c
@@ -76,7 +76,11 @@ static u32 __devinit mpc52xx_can_get_clock(struct
of_device *ofdev,
else
*mscan_clksrc = MSCAN_CLKSRC_XTAL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+ freq = mpc52xx_find_ipb_freq(ofdev->node);
+#else
freq = mpc5xxx_get_bus_frequency(ofdev->node);
+#endif
if (!freq)
return 0;
For 2.4 I will have a close look now.
This proves, your regression test build tool is really useful.
Thanks,
Wolfgang.
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-15 14:26 ` Wolfgang Grandegger
@ 2010-01-15 18:10 ` Gilles Chanteperdrix
[not found] ` <4B50D9C7.8090901@domain.hid>
0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-15 18:10 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Xenomai-core, Wolfgang Grandegger
Wolfgang Grandegger wrote:
> Gilles Chanteperdrix wrote:
>> Wolfgang Grandegger wrote:
>>> From: Wolfgang Grandegger <wg@domain.hid>
>>>
>>> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
>>> from Freescale by introducing a new OF platform driver for both, the
>>> MPC521x and MPC5200, while still keeping the old driver for the MPC5200
>>> for compatibility with older kernel versions.
>> Hi Wolfgang,
>>
>> there seems to be something missing, because I get a compilation error
>> on lite-5200:
>> http://sisyphus.hd.free.fr/~gilles/bx/#powerpc
>
> Well, I obviously did not test the driver with old versions of the Linux
> kernel, sorry.
No problem, that is what the build test is for.
> For 2.6.29 and 2.6.30 the following patch should fix the build:
Ok. I applied a slightly different modification (fixing in wrappers.h).
I am waiting for your fix for 2.4 for pushing.
> For 2.4 I will have a close look now.
>
> This proves, your regression test build tool is really useful.
That is, if you assume people in the wild are trying older versions...
--
Gilles.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
[not found] ` <4B50D9C7.8090901@domain.hid>
@ 2010-01-16 9:37 ` Gilles Chanteperdrix
2010-01-16 20:38 ` Wolfgang Grandegger
0 siblings, 1 reply; 14+ messages in thread
From: Gilles Chanteperdrix @ 2010-01-16 9:37 UTC (permalink / raw)
To: Wolfgang Grandegger; +Cc: Xenomai-core
Wolfgang Grandegger wrote:
> Hi Gilles
>
> Gilles Chanteperdrix wrote:
>> Wolfgang Grandegger wrote:
>>> Gilles Chanteperdrix wrote:
>>>> Wolfgang Grandegger wrote:
>>>>> From: Wolfgang Grandegger <wg@domain.hid>
>>>>>
>>>>> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
>>>>> from Freescale by introducing a new OF platform driver for both, the
>>>>> MPC521x and MPC5200, while still keeping the old driver for the MPC5200
>>>>> for compatibility with older kernel versions.
>>>> Hi Wolfgang,
>>>>
>>>> there seems to be something missing, because I get a compilation error
>>>> on lite-5200:
>>>> http://sisyphus.hd.free.fr/~gilles/bx/#powerpc
>>> Well, I obviously did not test the driver with old versions of the Linux
>>> kernel, sorry.
>> No problem, that is what the build test is for.
>>
>>
>>> For 2.6.29 and 2.6.30 the following patch should fix the build:
>> Ok. I applied a slightly different modification (fixing in wrappers.h).
>> I am waiting for your fix for 2.4 for pushing.
>
> See patch below. It will contain your fixes in wrappers.h. I will do some
> final testing on real hardware on monday.
All green, pushed. Only with one change: I removed the explicit
inclusion of wrappers.h in rtcan_mscan_mpc52xx.c, as it is already
included thanks to rtdm_driver.h, and Jan told us that we should not do
that if we want the code to be compiled for rtdm-native.
--
Gilles.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200
2010-01-16 9:37 ` Gilles Chanteperdrix
@ 2010-01-16 20:38 ` Wolfgang Grandegger
0 siblings, 0 replies; 14+ messages in thread
From: Wolfgang Grandegger @ 2010-01-16 20:38 UTC (permalink / raw)
To: Gilles Chanteperdrix; +Cc: Xenomai-core, Wolfgang Grandegger
Gilles Chanteperdrix wrote:
> Wolfgang Grandegger wrote:
>> Hi Gilles
>>
>> Gilles Chanteperdrix wrote:
>>> Wolfgang Grandegger wrote:
>>>> Gilles Chanteperdrix wrote:
>>>>> Wolfgang Grandegger wrote:
>>>>>> From: Wolfgang Grandegger <wg@domain.hid>
>>>>>>
>>>>>> This patch series adds RT-Socket-CAN support for the MSCAN on the MPC512x
>>>>>> from Freescale by introducing a new OF platform driver for both, the
>>>>>> MPC521x and MPC5200, while still keeping the old driver for the MPC5200
>>>>>> for compatibility with older kernel versions.
>>>>> Hi Wolfgang,
>>>>>
>>>>> there seems to be something missing, because I get a compilation error
>>>>> on lite-5200:
>>>>> http://sisyphus.hd.free.fr/~gilles/bx/#powerpc
>>>> Well, I obviously did not test the driver with old versions of the Linux
>>>> kernel, sorry.
>>> No problem, that is what the build test is for.
>>>
>>>
>>>> For 2.6.29 and 2.6.30 the following patch should fix the build:
>>> Ok. I applied a slightly different modification (fixing in wrappers.h).
>>> I am waiting for your fix for 2.4 for pushing.
>> See patch below. It will contain your fixes in wrappers.h. I will do some
>> final testing on real hardware on monday.
>
> All green, pushed. Only with one change: I removed the explicit
> inclusion of wrappers.h in rtcan_mscan_mpc52xx.c, as it is already
> included thanks to rtdm_driver.h, and Jan told us that we should not do
> that if we want the code to be compiled for rtdm-native.
And it is not even needed, as I just verified.
Thanks,
Wolfgang.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2010-01-16 20:38 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-14 12:07 [Xenomai-core] [PATCH xenomai-2.5 0/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 1/3] rtcan: mscan: use tabs for indention and white space cleanup Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 2/3] rtcan: mscan: use proper io accessor functions for register access Wolfgang Grandegger
2010-01-14 12:07 ` [Xenomai-core] [PATCH xenomai-2.5 3/3] rtcan: mscan: new OF platform driver for MPC521x and MPC5200 Wolfgang Grandegger
2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:07 ` Wolfgang Grandegger
2010-01-14 12:14 ` Wolfgang Grandegger
2010-01-14 14:57 ` Gilles Chanteperdrix
2010-01-14 15:05 ` Wolfgang Grandegger
2010-01-15 14:08 ` [Xenomai-core] [PATCH xenomai-2.5 0/3] " Gilles Chanteperdrix
2010-01-15 14:26 ` Wolfgang Grandegger
2010-01-15 18:10 ` Gilles Chanteperdrix
[not found] ` <4B50D9C7.8090901@domain.hid>
2010-01-16 9:37 ` Gilles Chanteperdrix
2010-01-16 20:38 ` Wolfgang Grandegger
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.