lkml.org 
[lkml]   [2011]   [Feb]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 09/13] can: pruss CAN driver.
    Date
    This patch adds support for the CAN device emulated on PRUSS.

    Signed-off-by: Subhasish Ghosh <subhasish@mistralsolutions.com>
    ---
    drivers/net/can/Kconfig | 1 +
    drivers/net/can/Makefile | 1 +
    drivers/net/can/da8xx_pruss/Kconfig | 73 ++
    drivers/net/can/da8xx_pruss/Makefile | 7 +
    drivers/net/can/da8xx_pruss/pruss_can.c | 758 +++++++++++++++++
    drivers/net/can/da8xx_pruss/pruss_can_api.c | 1227 +++++++++++++++++++++++++++
    drivers/net/can/da8xx_pruss/pruss_can_api.h | 290 +++++++
    7 files changed, 2357 insertions(+), 0 deletions(-)
    create mode 100644 drivers/net/can/da8xx_pruss/Kconfig
    create mode 100644 drivers/net/can/da8xx_pruss/Makefile
    create mode 100644 drivers/net/can/da8xx_pruss/pruss_can.c
    create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.c
    create mode 100644 drivers/net/can/da8xx_pruss/pruss_can_api.h

    diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
    index d5a9db6..ae8f0f9 100644
    --- a/drivers/net/can/Kconfig
    +++ b/drivers/net/can/Kconfig
    @@ -112,6 +112,7 @@ config PCH_CAN
    This driver can access CAN bus.

    source "drivers/net/can/mscan/Kconfig"
    +source "drivers/net/can/da8xx_pruss/Kconfig"

    source "drivers/net/can/sja1000/Kconfig"

    diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
    index 07ca159..849cdbf 100644
    --- a/drivers/net/can/Makefile
    +++ b/drivers/net/can/Makefile
    @@ -14,6 +14,7 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000/
    obj-$(CONFIG_CAN_MSCAN) += mscan/
    obj-$(CONFIG_CAN_AT91) += at91_can.o
    obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
    +obj-$(CONFIG_CAN_TI_DA8XX_PRU) += da8xx_pruss/
    obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
    obj-$(CONFIG_CAN_BFIN) += bfin_can.o
    obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o
    diff --git a/drivers/net/can/da8xx_pruss/Kconfig b/drivers/net/can/da8xx_pruss/Kconfig
    new file mode 100644
    index 0000000..8b68f68
    --- /dev/null
    +++ b/drivers/net/can/da8xx_pruss/Kconfig
    @@ -0,0 +1,73 @@
    +#
    +# CAN Lite Kernel Configuration
    +#
    +config CAN_TI_DA8XX_PRU
    + depends on CAN_DEV && ARCH_DAVINCI && ARCH_DAVINCI_DA850
    + tristate "PRU based CAN emulation for DA8XX"
    + ---help---
    + Enable this to emulate a CAN controller on the PRU of DA8XX.
    + If not sure, mark N
    +
    +config DA8XX_PRU_CANID_MBX0
    + hex "CANID for mailbox 0"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 0
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX1
    + hex "CANID for mailbox 1"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 1
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX2
    + hex "CANID for mailbox 2"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 2
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX3
    + hex "CANID for mailbox 3"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 3
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX4
    + hex "CANID for mailbox 4"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 4
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX5
    + hex "CANID for mailbox 5"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 5
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX6
    + hex "CANID for mailbox 6"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 6
    + Default value is set to 0x123, change this as required.
    +
    +config DA8XX_PRU_CANID_MBX7
    + hex "CANID for mailbox 7"
    + depends on CAN_TI_DA8XX_PRU
    + default "0x123"
    + ---help---
    + Enter the CANID for mailbox 7
    + Default value is set to 0x123, change this as required.
    diff --git a/drivers/net/can/da8xx_pruss/Makefile b/drivers/net/can/da8xx_pruss/Makefile
    new file mode 100644
    index 0000000..48f3055
    --- /dev/null
    +++ b/drivers/net/can/da8xx_pruss/Makefile
    @@ -0,0 +1,7 @@
    +#
    +# Makefile for CAN Lite emulation
    +#
    +can_emu-objs := pruss_can.o \
    + pruss_can_api.o
    +
    +obj-$(CONFIG_CAN_TI_DA8XX_PRU) += can_emu.o
    diff --git a/drivers/net/can/da8xx_pruss/pruss_can.c b/drivers/net/can/da8xx_pruss/pruss_can.c
    new file mode 100644
    index 0000000..1b3afde
    --- /dev/null
    +++ b/drivers/net/can/da8xx_pruss/pruss_can.c
    @@ -0,0 +1,758 @@
    +/*
    + * TI DA8XX PRU CAN Emulation device driver
    + * Author: subhasish@mistralsolutions.com
    + *
    + * This driver supports TI's PRU CAN Emulation and the
    + * specs for the same is available at <http://www.ti.com>
    + *
    + * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
    + *
    + * 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 version 2.
    + *
    + * This program is distributed as is WITHOUT ANY WARRANTY of any
    + * kind, whether express or implied; without even the implied warranty
    + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + */
    +
    +#include <linux/module.h>
    +#include <linux/init.h>
    +#include <linux/kernel.h>
    +#include <linux/bitops.h>
    +#include <linux/interrupt.h>
    +#include <linux/errno.h>
    +#include <linux/netdevice.h>
    +#include <linux/skbuff.h>
    +#include <linux/platform_device.h>
    +#include <linux/firmware.h>
    +#include <linux/clk.h>
    +#include <linux/types.h>
    +
    +#include <linux/can.h>
    +#include <linux/can/dev.h>
    +#include <linux/can/error.h>
    +#include <mach/da8xx.h>
    +#include "pruss_can_api.h"
    +
    +#define DRV_NAME "da8xx_pruss_can"
    +#define DRV_DESC "TI PRU CAN Controller Driver v0.1"
    +#define PRU_CAN_START 1
    +#define PRU_CAN_STOP 0
    +#define MB_MIN 0
    +#define MB_MAX 7
    +
    +#define PRU_CANMID_IDE BIT(29) /* Extended frame format */
    +
    +#define PRU_CAN_ISR_BIT_CCI BIT(15)
    +#define PRU_CAN_ISR_BIT_ESI BIT(14)
    +#define PRU_CAN_ISR_BIT_SRDI BIT(13)
    +#define PRU_CAN_ISR_BIT_RRI BIT(8)
    +
    +#define PRU_CAN_MBXSR_BIT_STATE BIT(7)
    +#define PRU_CAN_MBXSR_BIT_TC BIT(6)
    +#define PRU_CAN_MBXSR_BIT_ERR BIT(5)
    +#define PRU_CAN_MBXSR_BIT_OF BIT(0)
    +
    +#define PRU_CAN_GSR_BIT_TXM BIT(7)
    +#define PRU_CAN_GSR_BIT_RXM BIT(6)
    +#define PRU_CAN_GSR_BIT_CM BIT(5)
    +#define PRU_CAN_GSR_BIT_EPM BIT(4)
    +#define PRU_CAN_GSR_BIT_BFM BIT(3)
    +#define RTR_MBX_NO 8
    +#define MAX_INIT_RETRIES 20
    +#define L138_PRU_ARM_FREQ 312000
    +#define DFLT_PRU_FREQ 156000000
    +#define DFLT_PRU_BITRATE 125000
    +
    +#define CONFIG_DA8XX_PRU_CANID_MBX0 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX1 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX2 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX3 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX4 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX5 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX6 0x123
    +#define CONFIG_DA8XX_PRU_CANID_MBX7 0x123
    +
    +#ifdef __CAN_DEBUG
    +#define __can_debug(fmt, args...) printk(KERN_DEBUG "can_debug: " fmt, ## args)
    +#else
    +#define __can_debug(fmt, args...)
    +#endif
    +#define __can_err(fmt, args...) printk(KERN_ERR "can_err: " fmt, ## args)
    +
    +/*
    + * omapl_pru can private data
    + */
    +struct omapl_pru_can_priv {
    + struct can_priv can;
    + struct workqueue_struct *pru_can_wQ;
    + struct work_struct rx_work;
    + struct net_device *ndev;
    + struct device *dev; /* pdev->dev */
    + struct clk *clk_timer;
    + u32 timer_freq;
    + can_emu_app_hndl can_tx_hndl;
    + can_emu_app_hndl can_rx_hndl;
    + const struct firmware *fw_rx;
    + const struct firmware *fw_tx;
    + spinlock_t mbox_lock;
    + u32 trx_irq;
    + u32 tx_head;
    + u32 tx_tail;
    + u32 tx_next;
    + u32 rx_next;
    +};
    +
    +static int omapl_pru_can_get_state(const struct net_device *ndev,
    + enum can_state *state)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + *state = priv->can.state;
    + return 0;
    +}
    +
    +static int omapl_pru_can_set_bittiming(struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + struct can_bittiming *bt = &priv->can.bittiming;
    + long bit_error = 0;
    +
    + if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) {
    + dev_warn(priv->dev, "WARN: Triple"
    + "sampling not set due to h/w limitations");
    + }
    + if (pru_can_calc_timing(priv->dev, priv->can.clock.freq,
    + bt->bitrate) != 0)
    + return -EINVAL;
    + bit_error =
    + (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
    + bt->bitrate) * 1000) / bt->bitrate;
    + if (bit_error) {
    + bit_error =
    + (((priv->timer_freq / (priv->timer_freq / bt->bitrate)) -
    + bt->bitrate) * 1000000) / bt->bitrate;
    + printk(KERN_INFO "\nBitrate error %ld.%ld%%\n",
    + bit_error / 10000, bit_error % 1000);
    + } else
    + printk(KERN_INFO "\nBitrate error 0.0%%\n");
    +
    + return 0;
    +}
    +
    +static void omapl_pru_can_stop(struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + u16 int_mask = 0;
    +
    + pru_can_mask_ints(priv->dev, int_mask); /* mask all ints */
    + pru_can_start_abort_tx(priv->dev, PRU_CAN_STOP);
    + priv->can.state = CAN_STATE_STOPPED;
    +}
    +
    +/*
    + * This is to just set the can state to ERROR_ACTIVE
    + * ip link set canX up type can bitrate 125000
    + */
    +static void omapl_pru_can_start(struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + u16 int_mask = 0xFFFF;
    +
    + if (priv->can.state != CAN_STATE_STOPPED)
    + omapl_pru_can_stop(ndev);
    +
    + pru_can_mask_ints(priv->dev, int_mask); /* unmask all ints */
    +
    + pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
    + pru_can_get_global_status(priv->dev, &priv->can_rx_hndl);
    +
    + if (PRU_CAN_GSR_BIT_EPM & priv->can_tx_hndl.u32globalstatus)
    + priv->can.state = CAN_STATE_ERROR_PASSIVE;
    + else if (PRU_CAN_GSR_BIT_BFM & priv->can_tx_hndl.u32globalstatus)
    + priv->can.state = CAN_STATE_BUS_OFF;
    + else
    + priv->can.state = CAN_STATE_ERROR_ACTIVE;
    +}
    +
    +static int omapl_pru_can_set_mode(struct net_device *ndev, enum can_mode mode)
    +{
    + int ret = 0;
    +
    + switch (mode) {
    + case CAN_MODE_START:
    + omapl_pru_can_start(ndev);
    + if (netif_queue_stopped(ndev))
    + netif_wake_queue(ndev);
    + break;
    + case CAN_MODE_STOP:
    + omapl_pru_can_stop(ndev);
    + if (!netif_queue_stopped(ndev))
    + netif_stop_queue(ndev);
    + break;
    + default:
    + ret = -EOPNOTSUPP;
    + break;
    + }
    + return ret;
    +}
    +
    +static netdev_tx_t omapl_pru_can_start_xmit(struct sk_buff *skb,
    + struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + struct can_frame *cf = (struct can_frame *)skb->data;
    + int count;
    + u8 *data = cf->data;
    + u8 dlc = cf->can_dlc;
    + u8 *ptr8data = NULL;
    +
    + netif_stop_queue(ndev);
    + if (cf->can_id & CAN_EFF_FLAG) /* Extended frame format */
    + *((u32 *) &priv->can_tx_hndl.strcanmailbox) =
    + (cf->can_id & CAN_EFF_MASK) | PRU_CANMID_IDE;
    + else /* Standard frame format */
    + *((u32 *) &priv->can_tx_hndl.strcanmailbox) =
    + (cf->can_id & CAN_SFF_MASK) << 18;
    +
    + if (cf->can_id & CAN_RTR_FLAG) /* Remote transmission request */
    + *((u32 *) &priv->can_tx_hndl.strcanmailbox) |= CAN_RTR_FLAG;
    +
    + ptr8data = &priv->can_tx_hndl.strcanmailbox.u8data7 + (dlc - 1);
    + for (count = 0; count < (u8) dlc; count++) {
    + *ptr8data-- = *data++;
    + }
    + *((u32 *) &priv->can_tx_hndl.strcanmailbox.u16datalength) = (u32) dlc;
    +/*
    + * search for the next available mbx
    + * if the next mbx is busy, then try the next + 1
    + * do this until the head is reached.
    + * if still unable to tx, stop accepting any packets
    + * if able to tx and the head is reached, then reset next to tail, i.e mbx0
    + * if head is not reached, then just point to the next mbx
    + */
    + for (; priv->tx_next <= priv->tx_head; priv->tx_next++) {
    + priv->can_tx_hndl.ecanmailboxnumber =
    + (can_mailbox_number) priv->tx_next;
    + if (-1 == pru_can_write_data_to_mailbox(priv->dev,
    + &priv->can_tx_hndl)) {
    + if (priv->tx_next == priv->tx_head) {
    + priv->tx_next = priv->tx_tail;
    + if (!netif_queue_stopped(ndev))
    + netif_stop_queue(ndev); /* IF stalled */
    + dev_err(priv->dev,
    + "%s: no tx mbx available", __func__);
    + return NETDEV_TX_BUSY;
    + } else
    + continue;
    + } else {
    + /* set transmit request */
    + pru_can_tx(priv->dev, priv->tx_next, CAN_TX_PRU_1);
    + pru_can_tx_mode_set(priv->dev, false, ecanreceive);
    + pru_can_tx_mode_set(priv->dev, true, ecantransmit);
    + pru_can_start_abort_tx(priv->dev, PRU_CAN_START);
    + priv->tx_next++;
    + can_put_echo_skb(skb, ndev, 0);
    + break;
    + }
    + }
    + if (priv->tx_next > priv->tx_head) {
    + priv->tx_next = priv->tx_tail;
    + }
    + return NETDEV_TX_OK;
    +}
    +
    +static int omapl_pru_can_rx(struct net_device *ndev, u32 mbxno)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + struct net_device_stats *stats = &ndev->stats;
    + struct can_frame *cf;
    + struct sk_buff *skb;
    + u32 pru_can_mbx_data;
    + u8 *data = NULL;
    + u8 *ptr8data = NULL;
    + int count = 0;
    +
    + skb = alloc_can_skb(ndev, &cf);
    + if (!skb) {
    + if (printk_ratelimit())
    + dev_err(priv->dev,
    + "alloc_can_skb() failed\n");
    + return -ENOMEM;
    + }
    + data = cf->data;
    + /* get payload */
    + priv->can_rx_hndl.ecanmailboxnumber = (can_mailbox_number) mbxno;
    + if (pru_can_get_data_from_mailbox(priv->dev, &priv->can_rx_hndl)) {
    + __can_err("failed to get data from mailbox\n");
    + return -EAGAIN;
    + }
    + /* give ownweship to pru */
    + pru_can_tx(priv->dev, mbxno, CAN_RX_PRU_0);
    +
    + /* get data length code */
    + cf->can_dlc =
    + get_can_dlc(*
    + ((u32 *) &priv->can_rx_hndl.strcanmailbox.
    + u16datalength) & 0xF);
    + if (cf->can_dlc <= 4) {
    + ptr8data =
    + &priv->can_rx_hndl.strcanmailbox.u8data3 + (4 -
    + cf->can_dlc);
    + for (count = 0; count < cf->can_dlc; count++) {
    + *data++ = *ptr8data++;
    + }
    + } else {
    + ptr8data = &priv->can_rx_hndl.strcanmailbox.u8data3;
    + for (count = 0; count < 4; count++) {
    + *data++ = *ptr8data++;
    + }
    + ptr8data =
    + &priv->can_rx_hndl.strcanmailbox.u8data4 - (cf->can_dlc -
    + 5);
    + for (count = 0; count < cf->can_dlc - 4; count++) {
    + *data++ = *ptr8data++;
    + }
    + }
    +
    + pru_can_mbx_data = *((u32 *) &priv->can_rx_hndl.strcanmailbox);
    + /* get id extended or std */
    + if (pru_can_mbx_data & PRU_CANMID_IDE)
    + cf->can_id = (pru_can_mbx_data & CAN_EFF_MASK) | CAN_EFF_FLAG;
    + else
    + cf->can_id = (pru_can_mbx_data >> 18) & CAN_SFF_MASK;
    +
    + if (pru_can_mbx_data & CAN_RTR_FLAG)
    + cf->can_id |= CAN_RTR_FLAG;
    +
    + netif_rx_ni(skb);
    + stats->rx_packets++;
    + stats->rx_bytes += cf->can_dlc;
    + return 0;
    +}
    +
    +static int omapl_pru_can_err(struct net_device *ndev, int int_status,
    + int err_status)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + struct net_device_stats *stats = &ndev->stats;
    + struct can_frame *cf;
    + struct sk_buff *skb;
    + int tx_err_cnt, rx_err_cnt;
    +
    + /* propogate the error condition to the can stack */
    + skb = alloc_can_err_skb(ndev, &cf);
    + if (!skb) {
    + if (printk_ratelimit())
    + dev_err(priv->dev,
    + "alloc_can_err_skb() failed\n");
    + return -ENOMEM;
    + }
    +
    + if (err_status & PRU_CAN_GSR_BIT_EPM) { /* error passive int */
    + priv->can.state = CAN_STATE_ERROR_PASSIVE;
    + ++priv->can.can_stats.error_passive;
    + cf->can_id |= CAN_ERR_CRTL;
    + tx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_TX_PRU_1);
    + rx_err_cnt = pru_can_get_error_cnt(priv->dev, CAN_RX_PRU_0);
    + if (tx_err_cnt > 127)
    + cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
    + if (rx_err_cnt > 127)
    + cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
    +
    + dev_dbg(priv->ndev->dev.parent, "Error passive interrupt\n");
    + }
    +
    + if (err_status & PRU_CAN_GSR_BIT_BFM) {
    + priv->can.state = CAN_STATE_BUS_OFF;
    + cf->can_id |= CAN_ERR_BUSOFF;
    + /*
    + * Disable all interrupts in bus-off to avoid int hog
    + * this should be handled by the pru
    + */
    + pru_can_mask_ints(priv->dev, 0xFFFF);
    + can_bus_off(ndev);
    + dev_dbg(priv->ndev->dev.parent, "Bus off mode\n");
    + }
    +
    + netif_rx(skb);
    + stats->rx_packets++;
    + stats->rx_bytes += cf->can_dlc;
    + return 0;
    +}
    +
    +void omapl_pru_can_rx_wQ(struct work_struct *work)
    +{
    + struct omapl_pru_can_priv *priv = container_of(work,
    + struct omapl_pru_can_priv, rx_work);
    + struct net_device *ndev = priv->ndev;
    + u32 bit_set, mbxno = 0;
    +
    + if (-1 == pru_can_get_intr_status(priv->dev, &priv->can_rx_hndl))
    + return;
    +
    + if (PRU_CAN_ISR_BIT_RRI & priv->can_rx_hndl.u32interruptstatus) {
    + mbxno = RTR_MBX_NO;
    + omapl_pru_can_rx(ndev, mbxno);
    + } else {
    + /* Extract the mboxno from the status */
    + for (bit_set = 0; ((priv->can_rx_hndl.u32interruptstatus & 0xFF)
    + >> bit_set != 0); bit_set++)
    + ;
    + if (0 == bit_set) {
    + dev_err(priv->dev,
    + "%s: invalid mailbox number: %X\n", __func__,
    + priv->can_rx_hndl.u32interruptstatus);
    + } else {
    + mbxno = bit_set - 1;
    + if (PRU_CAN_ISR_BIT_ESI & priv->can_rx_hndl.
    + u32interruptstatus) {
    + pru_can_get_global_status(priv->dev,
    + &priv->can_rx_hndl);
    + omapl_pru_can_err(ndev,
    + priv->can_rx_hndl.u32interruptstatus,
    + priv->can_rx_hndl.u32globalstatus);
    + } else {
    + omapl_pru_can_rx(ndev, mbxno);
    + }
    + }
    + }
    +}
    +
    +irqreturn_t omapl_tx_can_intr(int irq, void *dev_id)
    +{
    + struct net_device *ndev = dev_id;
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + struct net_device_stats *stats = &ndev->stats;
    + u32 bit_set, mbxno;
    +
    + pru_can_get_intr_status(priv->dev, &priv->can_tx_hndl);
    + if ((PRU_CAN_ISR_BIT_CCI & priv->can_tx_hndl.u32interruptstatus)
    + || (PRU_CAN_ISR_BIT_SRDI & priv->can_tx_hndl.u32interruptstatus)) {
    + __can_debug("tx_int_status = 0x%X\n",
    + priv->can_tx_hndl.u32interruptstatus);
    + can_free_echo_skb(ndev, 0);
    + } else {
    + for (bit_set = 0; ((priv->can_tx_hndl.u32interruptstatus & 0xFF)
    + >> bit_set != 0); bit_set++)
    + ;
    + if (0 == bit_set) {
    + __can_err("%s: invalid mailbox number\n", __func__);
    + can_free_echo_skb(ndev, 0);
    + } else {
    + mbxno = bit_set - 1; /* mail box numbering starts from 0 */
    + if (PRU_CAN_ISR_BIT_ESI & priv->can_tx_hndl.
    + u32interruptstatus) {
    + /* read gsr and ack pru */
    + pru_can_get_global_status(priv->dev, &priv->can_tx_hndl);
    + omapl_pru_can_err(ndev,
    + priv->can_tx_hndl.
    + u32interruptstatus,
    + priv->can_tx_hndl.
    + u32globalstatus);
    + } else {
    + stats->tx_packets++;
    + /* stats->tx_bytes += dlc; */
    + /*can_get_echo_skb(ndev, 0);*/
    + }
    + }
    + }
    + if (netif_queue_stopped(ndev))
    + netif_wake_queue(ndev);
    +
    + can_get_echo_skb(ndev, 0);
    + pru_can_tx_mode_set(priv->dev, true, ecanreceive);
    + return IRQ_HANDLED;
    +}
    +
    +irqreturn_t omapl_rx_can_intr(int irq, void *dev_id)
    +{
    +
    + struct net_device *ndev = dev_id;
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + u32 intc_status = 0;
    +
    + intc_status = pru_can_get_intc_status(priv->dev);
    + if (intc_status & 4)
    + return omapl_tx_can_intr(irq, dev_id);
    + if (intc_status & 2) {
    + if (!work_pending(&priv->rx_work))
    + queue_work(priv->pru_can_wQ, &priv->rx_work);
    + }
    +
    + return IRQ_HANDLED;
    +}
    +
    +static int omapl_pru_can_open(struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    + int err;
    +
    + /* register interrupt handler */
    + err = request_irq(priv->trx_irq, &omapl_rx_can_intr, IRQF_SHARED,
    + "pru_can_irq", ndev);
    + if (err) {
    + dev_err(priv->dev, "error requesting rx interrupt\n");
    + goto exit_trx_irq;
    + }
    + /* common open */
    + err = open_candev(ndev);
    + if (err) {
    + dev_err(priv->dev, "open_candev() failed %d\n", err);
    + goto exit_open;
    + }
    +
    + pru_can_emu_init(priv->dev, priv->can.clock.freq);
    + priv->tx_tail = MB_MIN;
    + priv->tx_head = MB_MAX;
    +
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX0, 0);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX1, 1);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX2, 2);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX3, 3);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX4, 4);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX5, 5);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX6, 6);
    + pru_can_rx_id_map(priv->dev, CONFIG_DA8XX_PRU_CANID_MBX7, 7);
    +
    + omapl_pru_can_start(ndev);
    + netif_start_queue(ndev);
    + return 0;
    +
    +exit_open:
    + free_irq(priv->trx_irq, ndev);
    +exit_trx_irq:
    + return err;
    +}
    +
    +static int omapl_pru_can_close(struct net_device *ndev)
    +{
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    +
    + if (!netif_queue_stopped(ndev))
    + netif_stop_queue(ndev);
    +
    + close_candev(ndev);
    +
    + free_irq(priv->trx_irq, ndev);
    + return 0;
    +}
    +
    +static const struct net_device_ops omapl_pru_can_netdev_ops = {
    + .ndo_open = omapl_pru_can_open,
    + .ndo_stop = omapl_pru_can_close,
    + .ndo_start_xmit = omapl_pru_can_start_xmit,
    +};
    +
    +static int __devinit omapl_pru_can_probe(struct platform_device *pdev)
    +{
    + struct net_device *ndev = NULL;
    + const struct da8xx_pru_can_data *pdata;
    + struct omapl_pru_can_priv *priv = NULL;
    + struct device *dev = &pdev->dev;
    + u32 err;
    +
    + pdata = dev->platform_data;
    + if (!pdata) {
    + dev_err(&pdev->dev, "platform data not found\n");
    + return -EINVAL;
    + }
    +
    + ndev = alloc_candev(sizeof(struct omapl_pru_can_priv), MB_MAX + 1);
    + if (!ndev) {
    + dev_err(&pdev->dev, "alloc_candev failed\n");
    + err = -ENOMEM;
    + goto probe_exit;
    + }
    + priv = netdev_priv(ndev);
    +
    + priv->trx_irq = platform_get_irq(to_platform_device(dev->parent), 0);
    + if (!priv->trx_irq) {
    + dev_err(&pdev->dev, "unable to get pru interrupt resources!\n");
    + err = -ENODEV;
    + goto probe_exit;
    + }
    +
    + priv->ndev = ndev;
    + priv->dev = dev; /* priv->dev = pdev->dev */
    +
    + priv->can.bittiming_const = NULL;
    + priv->can.do_set_bittiming = omapl_pru_can_set_bittiming;
    + priv->can.do_set_mode = omapl_pru_can_set_mode;
    + priv->can.do_get_state = omapl_pru_can_get_state;
    + priv->can_tx_hndl.u8prunumber = CAN_TX_PRU_1;
    + priv->can_rx_hndl.u8prunumber = CAN_RX_PRU_0;
    +
    + /* we support local echo, no arp */
    + ndev->flags |= (IFF_ECHO | IFF_NOARP);
    +
    + /* pdev->dev->device_private->driver_data = ndev */
    + platform_set_drvdata(pdev, ndev);
    + SET_NETDEV_DEV(ndev, &pdev->dev);
    + ndev->netdev_ops = &omapl_pru_can_netdev_ops;
    +
    + priv->can.clock.freq = pruss_get_clk_freq(priv->dev);
    +
    + priv->clk_timer = clk_get(&pdev->dev, "pll1_sysclk2");
    + if (IS_ERR(priv->clk_timer)) {
    + dev_err(&pdev->dev, "no timer clock available\n");
    + err = PTR_ERR(priv->clk_timer);
    + priv->clk_timer = NULL;
    + goto probe_exit_candev;
    + }
    + priv->timer_freq = clk_get_rate(priv->clk_timer);
    +
    + err = register_candev(ndev);
    + if (err) {
    + dev_err(&pdev->dev, "register_candev() failed\n");
    + err = -ENODEV;
    + goto probe_exit_clk;
    + }
    +
    + err = request_firmware(&priv->fw_tx, "PRU_CAN_Emulation_Tx.bin",
    + &pdev->dev);
    + if (err) {
    + dev_err(&pdev->dev, "can't load firmware\n");
    + err = -ENODEV;
    + goto probe_exit_clk;
    + }
    +
    + dev_info(&pdev->dev, "fw_tx size %d. downloading...\n",
    + priv->fw_tx->size);
    +
    + err = request_firmware(&priv->fw_rx, "PRU_CAN_Emulation_Rx.bin",
    + &pdev->dev);
    + if (err) {
    + dev_err(&pdev->dev, "can't load firmware\n");
    + err = -ENODEV;
    + goto probe_release_fw;
    + }
    + dev_info(&pdev->dev, "fw_rx size %d. downloading...\n",
    + priv->fw_rx->size);
    +
    + /* init the pru */
    + pru_can_emu_init(priv->dev, priv->can.clock.freq);
    + udelay(200);
    +
    + pruss_enable(priv->dev, CAN_RX_PRU_0);
    + pruss_enable(priv->dev, CAN_TX_PRU_1);
    +
    + /* download firmware into pru */
    + err = pruss_load(priv->dev, CAN_RX_PRU_0,
    + (u32 *)priv->fw_rx->data, (priv->fw_rx->size / 4));
    + if (err) {
    + dev_err(&pdev->dev, "firmware download error\n");
    + err = -ENODEV;
    + goto probe_release_fw_1;
    + }
    + err = pruss_load(priv->dev, CAN_TX_PRU_1,
    + (u32 *)priv->fw_tx->data, (priv->fw_tx->size / 4));
    + if (err) {
    + dev_err(&pdev->dev, "firmware download error\n");
    + err = -ENODEV;
    + goto probe_release_fw_1;
    + }
    +
    + if (pru_can_calc_timing(priv->dev, DFLT_PRU_FREQ,
    + DFLT_PRU_BITRATE) != 0)
    + return -EINVAL;
    +
    + pruss_run(priv->dev, CAN_RX_PRU_0);
    + pruss_run(priv->dev, CAN_TX_PRU_1);
    +
    + /*Create The Work Queue */
    + priv->pru_can_wQ = create_freezeable_workqueue("omapl_pru_wQ");
    + if (priv->pru_can_wQ == NULL) {
    + dev_err(&pdev->dev, "failed to create work queue\n");
    + err = -ENODEV;
    + goto probe_release_fw_1;
    + }
    +
    + INIT_WORK(&priv->rx_work, omapl_pru_can_rx_wQ);
    + dev_info(&pdev->dev,
    + "%s device registered (trx_irq = %d, clk = %d)\n",
    + DRV_NAME, priv->trx_irq, priv->can.clock.freq);
    +
    + return 0;
    +
    +probe_release_fw_1:
    + release_firmware(priv->fw_rx);
    +probe_release_fw:
    + release_firmware(priv->fw_tx);
    +probe_exit_clk:
    + clk_put(priv->clk_timer);
    +probe_exit_candev:
    + if (NULL != ndev)
    + free_candev(ndev);
    +probe_exit:
    + return err;
    +}
    +
    +static int __devexit omapl_pru_can_remove(struct platform_device *pdev)
    +{
    + struct net_device *ndev = platform_get_drvdata(pdev);
    + struct omapl_pru_can_priv *priv = netdev_priv(ndev);
    +
    + omapl_pru_can_stop(ndev);
    +
    + pru_can_emu_exit(priv->dev);
    + release_firmware(priv->fw_tx);
    + release_firmware(priv->fw_rx);
    + clk_put(priv->clk_timer);
    + flush_workqueue(priv->pru_can_wQ);
    + destroy_workqueue(priv->pru_can_wQ);
    + unregister_candev(ndev);
    + free_candev(ndev);
    + platform_set_drvdata(pdev, NULL);
    + return 0;
    +}
    +
    +#ifdef CONFIG_PM
    +static int omapl_pru_can_suspend(struct platform_device *pdev,
    + pm_message_t mesg)
    +{
    + dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
    + return 0;
    +}
    +
    +static int omapl_pru_can_resume(struct platform_device *pdev)
    +{
    + dev_info(&pdev->dev, "%s not yet implemented\n", __func__);
    + return 0;
    +}
    +#else
    +#define omapl_pru_can_suspend NULL
    +#define omapl_pru_can_resume NULL
    +#endif /* CONFIG_PM */
    +
    +static struct platform_driver omapl_pru_can_driver = {
    + .probe = omapl_pru_can_probe,
    + .remove = __devexit_p(omapl_pru_can_remove),
    + .suspend = omapl_pru_can_suspend,
    + .resume = omapl_pru_can_resume,
    + .driver = {
    + .name = DRV_NAME,
    + .owner = THIS_MODULE,
    + },
    +};
    +
    +static int __init omapl_pru_can_init(void)
    +{
    + __can_debug(KERN_INFO DRV_DESC "\n");
    + return platform_driver_register(&omapl_pru_can_driver);
    +}
    +
    +module_init(omapl_pru_can_init);
    +
    +static void __exit omapl_pru_can_exit(void)
    +{
    + __can_debug(KERN_INFO DRV_DESC " unloaded\n");
    + platform_driver_unregister(&omapl_pru_can_driver);
    +}
    +
    +module_exit(omapl_pru_can_exit);
    +
    +MODULE_AUTHOR("Subhasish Ghosh <subhasish@mistralsolutions.com>");
    +MODULE_LICENSE("GPL");
    +MODULE_DESCRIPTION("omapl pru CAN netdevice driver");
    diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.c b/drivers/net/can/da8xx_pruss/pruss_can_api.c
    new file mode 100644
    index 0000000..2f7438a
    --- /dev/null
    +++ b/drivers/net/can/da8xx_pruss/pruss_can_api.c
    @@ -0,0 +1,1227 @@
    +/*
    + * Copyright (C) 2010 Texas Instruments Incorporated
    + * Author: Wilfred Felix
    + *
    + * 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 version 2.
    + *
    + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
    + * whether express or implied; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * General Public License for more details.
    + */
    +
    +#include "pruss_can_api.h"
    +
    +static can_emu_drv_inst gstr_can_inst[ecanmaxinst];
    +
    +/*
    + * pru_can_set_brp() Updates the BRP register of PRU0
    + * and PRU1 of OMAP L138. This API will be called by the
    + * Application to updtae the BRP register of PRU0 and PRU1
    + *
    + * param u16bitrateprescaler The can bus bitrate
    + * prescaler value be set
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_set_brp(struct device *dev, u16 u16bitrateprescaler)
    +{
    +
    + u32 u32offset;
    +
    + if (u16bitrateprescaler > 255) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER);
    + pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
    +
    + u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER);
    + pruss_writel(dev, u32offset, (u32 *) &u16bitrateprescaler, 1);
    +
    + return 0;
    +
    +}
    +
    +/*
    + * pru_can_set_bit_timing() Updates the timing register
    + * of PRU0 and PRU1 of OMAP L138. This API will be called by
    + * the Application to updtae the timing register of PRU0 and PRU1
    + *
    + * param pstrbittiming Pointer to structure holding
    + * the bit timing values for can bus.
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_set_bit_timing(struct device *dev,
    + can_bit_timing_consts *pstrbittiming)
    +{
    +
    + u32 u32offset;
    + u32 u32serregister;
    +
    + u32serregister = 0;
    +
    + if (pstrbittiming == NULL) {
    + return -1;
    + }
    +
    + if ((pstrbittiming->u8syncjumpwidth > PRU_CAN_MAX_SJW) ||
    + (pstrbittiming->u8phseg1 > PRU_CAN_MAX_PHSEG1) ||
    + (pstrbittiming->u8phseg2 > PRU_CAN_MAX_PHSEG2)) {
    + return -1;
    + }
    +
    + u32serregister = u32serregister |
    + ((pstrbittiming->u8syncjumpwidth << 7) |
    + (pstrbittiming->u8phseg1 << 3) |
    + (pstrbittiming->u8phseg2));
    +
    + u32offset = (PRU_CAN_TX_TIMING_REGISTER);
    + pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
    +
    + u32offset = (PRU_CAN_RX_TIMING_REGISTER);
    + pruss_writel(dev, u32offset, (u32 *) &u32serregister, 1);
    +
    + return 0;
    +}
    +
    +
    +/*
    + * pru_can_calc_timing()
    + * Updates the timing values of PRU0 and PRU1 of OMAP L138.
    + * This API will be called by the
    + * Application to updtae the timing values of PRU0 and PRU1
    + *
    + * return SUCCESS or FAILURE
    + */
    +
    +s16 pru_can_calc_timing(struct device *dev, u32 pru_freq, u32 bit_rate)
    +{
    + u16 u16phaseseg1;
    + u16 u16phaseseg2;
    + u32 u32offset;
    + u32 u32timing_value;
    + u32 u32setup_value;
    + u32timing_value = TIMER_CLK_FREQ / bit_rate;
    + u32offset = (PRU_CAN_TIMING_VAL_TX);
    + pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
    + pruss_readl(dev, u32offset, (u32 *) &u32timing_value, 4);
    + u32setup_value =
    + (GPIO_SETUP_DELAY * (pru_freq / 1000000) / 1000) /
    + DELAY_LOOP_LENGTH;
    + u32offset = (PRU_CAN_TIMING_VAL_TX_SJW);
    + pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
    + u16phaseseg1 = (u16) (u32timing_value / 2);
    + u16phaseseg2 = u32timing_value - u16phaseseg1;
    + u16phaseseg1 -= TIMER_SETUP_DELAY;
    + u16phaseseg2 -= TIMER_SETUP_DELAY;
    + u32setup_value = (u16phaseseg1 << 16) | u16phaseseg2;
    + u32offset = (PRU_CAN_TIMING_VAL_RX);
    + pruss_writel(dev, u32offset, (u32 *) &u32setup_value, 4);
    + u32offset = (PRU_CAN_TIMING_VAL_RX + 4);
    + pruss_writel(dev, u32offset, (u32 *) &u32timing_value, 4);
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_write_data_to_mailbox()
    + * Updates the transmit mailboxes of PRU1 of OMAP L138.
    + * This API will be called by the Application to update
    + * the transmit mailboxes of PRU1
    + *
    + * param pu16canframedata Can mailbox data buffer
    + *
    + * param u8mailboxnum Mailbox to be updated
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_write_data_to_mailbox(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl)
    +{
    + s16 s16subrtnretval;
    + u32 u32offset;
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + switch ((u8) pstremuapphndl->ecanmailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_TX_MAILBOX0);
    + break;
    + case 1:
    + u32offset = (PRU_CAN_TX_MAILBOX1);
    + break;
    + case 2:
    + u32offset = (PRU_CAN_TX_MAILBOX2);
    + break;
    + case 3:
    + u32offset = (PRU_CAN_TX_MAILBOX3);
    + break;
    + case 4:
    + u32offset = (PRU_CAN_TX_MAILBOX4);
    + break;
    + case 5:
    + u32offset = (PRU_CAN_TX_MAILBOX5);
    + break;
    + case 6:
    + u32offset = (PRU_CAN_TX_MAILBOX6);
    + break;
    + case 7:
    + u32offset = (PRU_CAN_TX_MAILBOX7);
    + break;
    + default:
    + return -1;
    + }
    +
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &(pstremuapphndl->strcanmailbox), 4);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + return 0;
    +}
    +
    +/*
    + * pru_can_get_data_from_mailbox()
    + * Receive data from the receive mailboxes of PRU0 of OMAP L138.
    + * This API will be called by the Application to get data from
    + * the receive mailboxes of PRU0
    + *
    + * param pu16canframedata Can mailbox data buffer
    + *
    + * param u8mailboxnum Mailbox to be updated
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_get_data_from_mailbox(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl)
    +{
    + s16 s16subrtnretval;
    + u32 u32offset;
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + switch ((u8) pstremuapphndl->ecanmailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_RX_MAILBOX0);
    + break;
    + case 1:
    + u32offset = (PRU_CAN_RX_MAILBOX1);
    + break;
    + case 2:
    + u32offset = (PRU_CAN_RX_MAILBOX2);
    + break;
    + case 3:
    + u32offset = (PRU_CAN_RX_MAILBOX3);
    + break;
    + case 4:
    + u32offset = (PRU_CAN_RX_MAILBOX4);
    + break;
    + case 5:
    + u32offset = (PRU_CAN_RX_MAILBOX5);
    + break;
    + case 6:
    + u32offset = (PRU_CAN_RX_MAILBOX6);
    + break;
    + case 7:
    + u32offset = (PRU_CAN_RX_MAILBOX7);
    + break;
    + case 8:
    + u32offset = (PRU_CAN_RX_MAILBOX8);
    + break;
    + default:
    + return -1;
    + }
    +
    + s16subrtnretval =
    + pruss_readl(dev, u32offset,
    + (u32 *) &(pstremuapphndl->strcanmailbox),
    + 4);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + return 0;
    +}
    +
    +/*
    + * pru_can_receive_id_map()
    + * Receive mailboxes ID Mapping of PRU0 of OMAP L138.
    + * This API will be called by the Application
    + * to map the IDs to receive mailboxes of PRU0
    + *
    + * param u32nodeid Can node ID
    + *
    + * param ecanmailboxno Mailbox to be mapped
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_rx_id_map(struct device *dev, u32 u32nodeid,
    + can_mailbox_number ecanmailboxno)
    +{
    +
    + pruss_writel(dev, (PRU_CAN_ID_MAP +
    + (((u8) ecanmailboxno) * 4)), (u32 *) &u32nodeid, 1);
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_get_intr_status()
    + * Gets the interrupts status register value.
    + * This API will be called by the Application
    + * to get the interrupts status register value
    + *
    + * param u8prunumber PRU number for which IntStatusReg
    + * has to be read
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_get_intr_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl)
    +{
    + u32 u32offset;
    + s16 s16subrtnretval = -1;
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
    + u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER);
    + } else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
    + u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER);
    + } else {
    + return -1;
    + }
    +
    + s16subrtnretval = pruss_readl(dev, u32offset,
    + (u32 *) &pstremuapphndl->u32interruptstatus, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_get_global_status() Gets the globalstatus
    + * register value. This API will be called by the Application
    + * to get the global status register value
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_get_global_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl)
    +{
    + u32 u32offset;
    + int s16subrtnretval = -1;
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
    + u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
    + } else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
    + u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
    + } else {
    + return -1;
    + }
    +
    + s16subrtnretval = pruss_readl(dev, u32offset,
    + (u32 *) &pstremuapphndl->u32globalstatus, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_get_mailbox_status() Gets the mailbox status
    + * register value. This API will be called by the Application
    + * to get the mailbox status register value
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_get_mailbox_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl)
    +{
    + u32 u32offset;
    + s16 s16subrtnretval = -1;
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_1) {
    + switch (pstremuapphndl->ecanmailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER);
    + break;
    + case 1:
    + u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER);
    + break;
    + case 2:
    + u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER);
    + break;
    + case 3:
    + u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER);
    + break;
    + case 4:
    + u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER);
    + break;
    + case 5:
    + u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER);
    + break;
    + case 6:
    + u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER);
    + break;
    + case 7:
    + u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER);
    + break;
    + default:
    + return -1;
    + }
    + }
    +
    + else if (pstremuapphndl->u8prunumber == DA8XX_PRUCORE_0) {
    + switch (pstremuapphndl->ecanmailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER);
    + break;
    + case 1:
    + u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER);
    + break;
    + case 2:
    + u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER);
    + break;
    + case 3:
    + u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER);
    + break;
    + case 4:
    + u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER);
    + break;
    + case 5:
    + u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER);
    + break;
    + case 6:
    + u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER);
    + break;
    + case 7:
    + u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER);
    + break;
    + case 8:
    + u32offset = (PRU_CAN_RX_MAILBOX8_STATUS_REGISTER);
    + break;
    + default:
    + return -1;
    + }
    + }
    +
    + else {
    + return -1;
    + }
    +
    + s16subrtnretval = pruss_readl(dev, u32offset,
    + (u32 *) &pstremuapphndl->u32mailboxstatus, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + return 0;
    +}
    +
    +s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
    + can_transfer_direction ecan_trx)
    +{
    + u32 u32offset;
    + u32 u32value;
    +
    + if (ecan_trx == ecantransmit) {
    + u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
    + pruss_readl(dev, u32offset, &u32value, 1);
    + if (btransfer_flag == true) {
    + u32value &= 0x1F;
    + u32value |= 0x80;
    + } else {
    + u32value &= 0x7F;
    + }
    + pruss_writel(dev, u32offset, &u32value, 1);
    + u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
    + pruss_writel(dev, u32offset, &u32value, 1);
    + } else if (ecan_trx == ecanreceive) {
    + u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER);
    + pruss_readl(dev, u32offset, &u32value, 1);
    + if (btransfer_flag == true) {
    + u32value &= 0x1F;
    + u32value |= 0x40;
    + } else {
    + u32value &= 0xBF;
    + }
    + pruss_writel(dev, u32offset, &u32value, 1);
    + u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER);
    + pruss_writel(dev, u32offset, &u32value, 1);
    + } else
    + return -1;
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_config_mode_set() Sets the timing value
    + * for data transfer. This API will be called by the Application
    + * to set timing valus for data transfer
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_config_mode_set(struct device *dev, bool bconfigmodeflag)
    +{
    +
    + u32 u32bitrateprescaler;
    + u32 u32canbittiming;
    +
    + pruss_readl(dev, (PRU_CAN_TX_CLOCK_BRP_REGISTER),
    + (u32 *) &u32bitrateprescaler, 1);
    + pruss_readl(dev, (PRU_CAN_TX_TIMING_REGISTER),
    + (u32 *) &u32canbittiming, 1);
    +
    + if (bconfigmodeflag == 1) {
    + pru_can_calc_timing(dev, u32canbittiming, u32bitrateprescaler);
    + }
    +
    + else {
    + pru_can_calc_timing(dev, 0, 0);
    + }
    +
    + return 0;
    +}
    +
    +/*
    + * pru_can_emu_init() Initializes the Can
    + * Emulation Parameters. This API will be called by the Application
    + * to Initialize the Can Emulation Parameters
    + *
    + * param u32pruclock PRU Clock value
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_emu_init(struct device *dev, u32 u32pruclock)
    +{
    + u32 u32offset;
    + u32 u32value;
    + s16 s16subrtnretval = -1;
    + u8 u8loop;
    +
    + for (u8loop = 0; u8loop < (u8) ecanmaxinst; u8loop++) {
    + gstr_can_inst[u8loop].bcaninststate = (bool) 0;
    + gstr_can_inst[u8loop].ecantransferdirection =
    + (can_transfer_direction) 0;
    + gstr_can_inst[u8loop].u32apphandlerptr = 0;
    + }
    +
    + u32offset = (PRU_CAN_TX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_GLOBAL_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000040;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000040;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_INTERRUPT_MASK_REGISTER & 0xFFFF);
    + u32value = 0x00004000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval =
    + pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000001;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_TIMING_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_CLOCK_BRP_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_TX_ERROR_COUNTER_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_POLARITY0 & 0xFFFF);
    + u32value = 0xFFFFFFFF;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32offset = (PRUSS_INTC_POLARITY1 & 0xFFFF);
    + u32value = 0xFFFFFFFF;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32offset = (PRUSS_INTC_TYPE0 & 0xFFFF);
    + u32value = 0x1C000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32offset = (PRUSS_INTC_TYPE1 & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_HSTINTENIDXCLR & 0xFFFF);
    + u32value = 0x0;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_GLBLEN & 0xFFFF);
    + u32value = 0x1;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + /* tx intr map arm->pru */
    + u32offset = (PRUSS_INTC_HSTINTENIDXSET & 0xFFFF);
    + u32value = 0x0;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_HOSTMAP0 & 0xFFFF);
    + u32value = 0x03020100;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_HOSTMAP1 & 0xFFFF);
    + u32value = 0x07060504;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_HOSTMAP2 & 0xFFFF);
    + u32value = 0x0000908;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_CHANMAP0 & 0xFFFF);
    + u32value = 0;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_CHANMAP8 & 0xFFFF);
    + u32value = 0x00020200;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + u32value = 32;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + u32value = 19;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
    + u32value = 19;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + u32value = 18;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
    + u32value = 18;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + u32value = 34;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
    + u32value = 34;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
    + u32value = 32;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRUSS_INTC_HOSTINTEN & 0xFFFF);
    + u32value = 0x5;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    +/* PRU0 - Rx Internal Registers Initializations */
    +
    + u32offset = (PRU_CAN_RX_GLOBAL_CONTROL_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_GLOBAL_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000040;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_INTERRUPT_MASK_REGISTER & 0xFFFF);
    + u32value = 0x00004000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x0000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_ERROR_COUNTER_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_TIMING_REGISTER & 0xFFFF);
    + u32value = 0x0000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + u32offset = (PRU_CAN_RX_CLOCK_BRP_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset, (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + return 0;
    +}
    +
    +
    +/*
    + * pru_can_emu_open() Opens the can emu for
    + * application to use. This API will be called by the Application
    + * to Open the can emu for application to use.
    + *
    + * param pstremuapphndl Pointer to application handler
    + * structure
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_emu_open(struct device *dev, can_emu_app_hndl *pstremuapphndl)
    +{
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    +
    + if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate == 1) {
    + return -1;
    + }
    +
    + gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
    + bcaninststate = (bool)1;
    + gstr_can_inst[(u8) pstremuapphndl->
    + ecaninstance].ecantransferdirection =
    + (can_transfer_direction)(u8)pstremuapphndl->ecantransferdirection;
    + gstr_can_inst[(u8) pstremuapphndl->ecaninstance].
    + u32apphandlerptr = (u32) pstremuapphndl;
    +
    + return 0;
    +}
    +
    +
    +/*
    + * brief pru_can_emu_close() Closes the can emu for other
    + * applications to use. This API will be called by the Application to Close
    + * the can emu for other applications to use
    + *
    + * param pstremuapphndl Pointer to application handler structure
    + *
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_emu_close(struct device *dev, can_emu_app_hndl *pstremuapphndl)
    +{
    +
    + if (pstremuapphndl == NULL) {
    + return -1;
    + }
    + if (gstr_can_inst[pstremuapphndl->ecaninstance].bcaninststate == 0) {
    + return -1;
    + }
    + if ((u32) pstremuapphndl != gstr_can_inst[(u8) pstremuapphndl->
    + ecaninstance].u32apphandlerptr){
    + return -1;
    + }
    + gstr_can_inst[(u8) pstremuapphndl->ecaninstance].bcaninststate
    + = (bool) 0;
    + gstr_can_inst[(u8) pstremuapphndl->
    + ecaninstance].ecantransferdirection = (can_transfer_direction) 0;
    + gstr_can_inst[(u8) pstremuapphndl->ecaninstance].u32apphandlerptr = 0;
    +
    + return 0;
    +}
    +
    +/*
    + * brief pru_can_emu_exit() Diables all the PRUs
    + * This API will be called by the Application to disable all PRUs
    + * param None
    + * return SUCCESS or FAILURE
    + */
    +s16 pru_can_emu_exit(struct device *dev)
    +{
    + s16 s16subrtnretval;
    +
    + s16subrtnretval = pruss_disable(dev, CAN_RX_PRU_0);
    + if (s16subrtnretval == -1)
    + return -1;
    + s16subrtnretval = pruss_disable(dev, CAN_TX_PRU_1);
    + if (s16subrtnretval == -1)
    + return -1;
    +
    + return 0;
    +}
    +
    +s16 pru_can_emu_sreset(struct device *dev)
    +{
    + return 0;
    +}
    +
    +s16 pru_can_tx(struct device *dev, u8 u8mailboxnumber, u8 u8prunumber)
    +{
    + u32 u32offset = 0;
    + u32 u32value = 0;
    + s16 s16subrtnretval = -1;
    +
    + if (DA8XX_PRUCORE_1 == u8prunumber) {
    + switch (u8mailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_TX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 1:
    + u32offset = (PRU_CAN_TX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 2:
    + u32offset = (PRU_CAN_TX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 3:
    + u32offset = (PRU_CAN_TX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 4:
    + u32offset = (PRU_CAN_TX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 5:
    + u32offset = (PRU_CAN_TX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 6:
    + u32offset = (PRU_CAN_TX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 7:
    + u32offset = (PRU_CAN_TX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000080;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + default:
    + return -1;
    + }
    + } else {
    +
    + u32offset = (PRU_CAN_RX_INTERRUPT_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_readl(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + u32value = u32value & ~(1 << u8mailboxnumber);
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    +
    + switch (u8mailboxnumber) {
    + case 0:
    + u32offset = (PRU_CAN_RX_MAILBOX0_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 1:
    + u32offset = (PRU_CAN_RX_MAILBOX1_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 2:
    + u32offset = (PRU_CAN_RX_MAILBOX2_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 3:
    + u32offset = (PRU_CAN_RX_MAILBOX3_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 4:
    + u32offset = (PRU_CAN_RX_MAILBOX4_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 5:
    + u32offset = (PRU_CAN_RX_MAILBOX5_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 6:
    + u32offset = (PRU_CAN_RX_MAILBOX6_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + case 7:
    + u32offset = (PRU_CAN_RX_MAILBOX7_STATUS_REGISTER & 0xFFFF);
    + u32value = 0x00000000;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + break;
    + default:
    + return -1;
    + }
    + }
    + return 0;
    +}
    +
    +s16 pru_can_start_abort_tx(struct device *dev, bool bcantransmitabortflag)
    +{
    + u32 u32offset;
    + u32 u32value;
    + s16 s16subrtnretval;
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + u32value = 32;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    +
    + u32offset = (PRUSS_INTC_ENIDXSET & 0xFFFF);
    + u32value = 32;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    +
    + u32offset = (PRUSS_INTC_STATIDXSET & 0xFFFF);
    + u32value = 32;
    + s16subrtnretval = pruss_writel(dev, u32offset,
    + (u32 *) &u32value, 1);
    + if (s16subrtnretval == -1) {
    + return -1;
    + }
    + return 0;
    +}
    +
    +s16 pru_can_mask_ints(struct device *dev, u32 int_mask)
    +{
    + return 0;
    +}
    +
    +int pru_can_get_error_cnt(struct device *dev, u8 u8prunumber)
    +{
    + return 0;
    +}
    +
    +int pru_can_get_intc_status(struct device *dev)
    +{
    + u32 u32offset = 0;
    + u32 u32getvalue = 0;
    + u32 u32clrvalue = 0;
    +
    + u32offset = (PRUSS_INTC_STATCLRINT1 & 0xFFFF);
    + pruss_readl(dev, u32offset, (u32 *) &u32getvalue, 1);
    +
    + if (u32getvalue & 4)
    + u32clrvalue = 34; /* CLR Event 34 */
    +
    + if (u32getvalue & 2)
    + u32clrvalue = 33; /* CLR Event 33 */
    +
    + if (u32clrvalue) {
    + u32offset = (PRUSS_INTC_STATIDXCLR & 0xFFFF);
    + pruss_writel(dev, u32offset, &u32clrvalue, 1);
    + } else
    + return -1;
    +
    + return u32getvalue;
    +}
    diff --git a/drivers/net/can/da8xx_pruss/pruss_can_api.h b/drivers/net/can/da8xx_pruss/pruss_can_api.h
    new file mode 100644
    index 0000000..7550456
    --- /dev/null
    +++ b/drivers/net/can/da8xx_pruss/pruss_can_api.h
    @@ -0,0 +1,290 @@
    +/*
    + * Copyright (C) 2010 Texas Instruments Incorporated
    + * Author: Ganeshan N
    + *
    + * 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 version 2.
    + *
    + * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
    + * whether express or implied; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    + * General Public License for more details.
    + */
    +
    +#ifndef _PRU_CAN_API_H_
    +#define _PRU_CAN_API_H_
    +
    +#include <linux/types.h>
    +#include <linux/mfd/pruss/da8xx_pru.h>
    +
    +
    +#define CAN_BIT_TIMINGS (0x273)
    +
    +/* Timer Clock is sourced from DDR freq (PLL1 SYS CLK 2) */
    +#define TIMER_CLK_FREQ 132000000
    +
    +#define TIMER_SETUP_DELAY 14
    +#define GPIO_SETUP_DELAY 150
    +
    +#define CAN_RX_PRU_0 PRUSS_NUM0
    +#define CAN_TX_PRU_1 PRUSS_NUM1
    +
    +/* Number of Instruction in the Delay loop */
    +#define DELAY_LOOP_LENGTH 2
    +
    +#define PRU1_BASE_ADDR 0x2000
    +
    +#define PRU_CAN_TX_GLOBAL_CONTROL_REGISTER (PRU1_BASE_ADDR)
    +#define PRU_CAN_TX_GLOBAL_STATUS_REGISTER (PRU1_BASE_ADDR + 0x04)
    +#define PRU_CAN_TX_INTERRUPT_MASK_REGISTER (PRU1_BASE_ADDR + 0x08)
    +#define PRU_CAN_TX_INTERRUPT_STATUS_REGISTER (PRU1_BASE_ADDR + 0x0C)
    +#define PRU_CAN_TX_MAILBOX0_STATUS_REGISTER (PRU1_BASE_ADDR + 0x10)
    +#define PRU_CAN_TX_MAILBOX1_STATUS_REGISTER (PRU1_BASE_ADDR + 0x14)
    +#define PRU_CAN_TX_MAILBOX2_STATUS_REGISTER (PRU1_BASE_ADDR + 0x18)
    +#define PRU_CAN_TX_MAILBOX3_STATUS_REGISTER (PRU1_BASE_ADDR + 0x1C)
    +#define PRU_CAN_TX_MAILBOX4_STATUS_REGISTER (PRU1_BASE_ADDR + 0x20)
    +#define PRU_CAN_TX_MAILBOX5_STATUS_REGISTER (PRU1_BASE_ADDR + 0x24)
    +#define PRU_CAN_TX_MAILBOX6_STATUS_REGISTER (PRU1_BASE_ADDR + 0x28)
    +#define PRU_CAN_TX_MAILBOX7_STATUS_REGISTER (PRU1_BASE_ADDR + 0x2C)
    +#define PRU_CAN_TX_ERROR_COUNTER_REGISTER (PRU1_BASE_ADDR + 0x30)
    +#define PRU_CAN_TX_TIMING_REGISTER (PRU1_BASE_ADDR + 0x34)
    +#define PRU_CAN_TX_CLOCK_BRP_REGISTER (PRU1_BASE_ADDR + 0x38)
    +
    +#define PRU_CAN_TX_MAILBOX0 (PRU1_BASE_ADDR + 0x40)
    +#define PRU_CAN_TX_MAILBOX1 (PRU1_BASE_ADDR + 0x50)
    +#define PRU_CAN_TX_MAILBOX2 (PRU1_BASE_ADDR + 0x60)
    +#define PRU_CAN_TX_MAILBOX3 (PRU1_BASE_ADDR + 0x70)
    +#define PRU_CAN_TX_MAILBOX4 (PRU1_BASE_ADDR + 0x80)
    +#define PRU_CAN_TX_MAILBOX5 (PRU1_BASE_ADDR + 0x90)
    +#define PRU_CAN_TX_MAILBOX6 (PRU1_BASE_ADDR + 0xA0)
    +#define PRU_CAN_TX_MAILBOX7 (PRU1_BASE_ADDR + 0xB0)
    +
    +#define PRU_CAN_TIMING_VAL_TX (PRU1_BASE_ADDR + 0xC0)
    +#define PRU_CAN_TIMING_VAL_TX_SJW (PRU1_BASE_ADDR + 0xC4)
    +#define PRU_CAN_TRANSMIT_FRAME (PRU1_BASE_ADDR + 0xE0)
    +
    +#define PRU0_BASE_ADDR 0
    +
    +#define PRU_CAN_RX_GLOBAL_CONTROL_REGISTER (PRU0_BASE_ADDR)
    +#define PRU_CAN_RX_GLOBAL_STATUS_REGISTER (PRU0_BASE_ADDR + 0x04)
    +#define PRU_CAN_RX_INTERRUPT_MASK_REGISTER (PRU0_BASE_ADDR + 0x08)
    +#define PRU_CAN_RX_INTERRUPT_STATUS_REGISTER (PRU0_BASE_ADDR + 0x0C)
    +#define PRU_CAN_RX_MAILBOX0_STATUS_REGISTER (PRU0_BASE_ADDR + 0x10)
    +#define PRU_CAN_RX_MAILBOX1_STATUS_REGISTER (PRU0_BASE_ADDR + 0x14)
    +#define PRU_CAN_RX_MAILBOX2_STATUS_REGISTER (PRU0_BASE_ADDR + 0x18)
    +#define PRU_CAN_RX_MAILBOX3_STATUS_REGISTER (PRU0_BASE_ADDR + 0x1C)
    +#define PRU_CAN_RX_MAILBOX4_STATUS_REGISTER (PRU0_BASE_ADDR + 0x20)
    +#define PRU_CAN_RX_MAILBOX5_STATUS_REGISTER (PRU0_BASE_ADDR + 0x24)
    +#define PRU_CAN_RX_MAILBOX6_STATUS_REGISTER (PRU0_BASE_ADDR + 0x28)
    +#define PRU_CAN_RX_MAILBOX7_STATUS_REGISTER (PRU0_BASE_ADDR + 0x2C)
    +#define PRU_CAN_RX_MAILBOX8_STATUS_REGISTER (PRU0_BASE_ADDR + 0x30)
    +#define PRU_CAN_RX_ERROR_COUNTER_REGISTER (PRU0_BASE_ADDR + 0x34)
    +#define PRU_CAN_RX_TIMING_REGISTER (PRU0_BASE_ADDR + 0x38)
    +#define PRU_CAN_RX_CLOCK_BRP_REGISTER (PRU0_BASE_ADDR + 0x3C)
    +
    +#define PRU_CAN_RX_MAILBOX0 (PRU0_BASE_ADDR + 0x40)
    +#define PRU_CAN_RX_MAILBOX1 (PRU0_BASE_ADDR + 0x50)
    +#define PRU_CAN_RX_MAILBOX2 (PRU0_BASE_ADDR + 0x60)
    +#define PRU_CAN_RX_MAILBOX3 (PRU0_BASE_ADDR + 0x70)
    +#define PRU_CAN_RX_MAILBOX4 (PRU0_BASE_ADDR + 0x80)
    +#define PRU_CAN_RX_MAILBOX5 (PRU0_BASE_ADDR + 0x90)
    +#define PRU_CAN_RX_MAILBOX6 (PRU0_BASE_ADDR + 0xA0)
    +#define PRU_CAN_RX_MAILBOX7 (PRU0_BASE_ADDR + 0xB0)
    +#define PRU_CAN_RX_MAILBOX8 (PRU0_BASE_ADDR + 0xC0)
    +
    +#define PRU_CAN_TIMING_VAL_RX (PRU0_BASE_ADDR + 0xD0)
    +#define PRU_CAN_RECEIVE_FRAME (PRU0_BASE_ADDR + 0xD4)
    +#define PRU_CAN_ID_MAP (PRU0_BASE_ADDR + 0xF0)
    +
    +#define PRU_CAN_ERROR_ACTIVE 128
    +
    +#define CAN_ACK_FAILED 0xE
    +#define CAN_ARBTR_FAIL 0xD
    +#define CAN_BIT_ERROR 0xC
    +#define CAN_TRANSMISSION_SUCCESS 0xA
    +
    +#define STD_DATA_FRAME 0x1
    +#define EXTD_DATA_FRAME 0x2
    +#define STD_REMOTE_FRAME 0x3
    +#define EXTD_REMOTE_FRAME 0x4
    +
    +#define PRU_CAN_MAX_SJW 8
    +#define PRU_CAN_MAX_PHSEG1 25
    +#define PRU_CAN_MAX_PHSEG2 25
    +
    +#define DA8XX_PRUCANCORE_0_REGS 0x7000
    +#define DA8XX_PRUCANCORE_1_REGS 0x7800
    +#define PRU0_PROG_RAM_START_OFFSET 0x8000
    +#define PRU1_PROG_RAM_START_OFFSET 0xC000
    +#define PRU_CAN_INIT_MAX_TIMEOUT 0xFF
    +
    +typedef enum {
    + ecaninst0 = 0,
    + ecaninst1,
    + ecanmaxinst
    +} can_instance_enum;
    +
    +typedef enum {
    + ecanmailbox0 = 0,
    + ecanmailbox1,
    + ecanmailbox2,
    + ecanmailbox3,
    + ecanmailbox4,
    + ecanmailbox5,
    + ecanmailbox6,
    + ecanmailbox7
    +} can_mailbox_number;
    +
    +typedef enum {
    + ecandirectioninit = 0,
    + ecantransmit,
    + ecanreceive
    +} can_transfer_direction;
    +
    +typedef struct {
    + u16 u16extendedidentifier;
    + u16 u16baseidentifier;
    + u8 u8data7;
    + u8 u8data6;
    + u8 u8data5;
    + u8 u8data4;
    + u8 u8data3;
    + u8 u8data2;
    + u8 u8data1;
    + u8 u8data0;
    + u16 u16datalength;
    + u16 u16crc;
    +} can_mail_box_structure;
    +
    +typedef struct {
    + can_transfer_direction ecantransferdirection;
    +} can_mailbox_config;
    +
    +typedef struct {
    + can_instance_enum ecaninstance;
    + can_transfer_direction ecantransferdirection;
    + can_mail_box_structure strcanmailbox;
    + can_mailbox_number ecanmailboxnumber;
    + u8 u8prunumber;
    + u32 u32globalstatus;
    + u32 u32interruptstatus;
    + u32 u32mailboxstatus;
    +} can_emu_app_hndl;
    +
    +typedef struct {
    + bool bcaninststate;
    + can_transfer_direction ecantransferdirection;
    + u32 u32apphandlerptr;
    +} can_emu_drv_inst;
    +
    +typedef struct {
    + u8 u8syncjumpwidth;
    + u8 u8phseg1;
    + u8 u8phseg2;
    +} can_bit_timing_consts;
    +
    +/* Field Definition Macros */
    +
    +/* CONTROL */
    +
    +/*
    + * pru_can_set_brp() Updates the BRP register of PRU.
    + */
    +s16 pru_can_set_brp(struct device *dev, u16 u16prescaler);
    +
    +/*
    + * pru_can_set_bit_timing() Updates the timing register of PRU
    + */
    +s16 pru_can_set_bit_timing(struct device *dev,
    + can_bit_timing_consts *pstrbittiming);
    +
    +/*
    + * pru_can_calc_timing() Updates the timing values of PRU
    + */
    +s16 pru_can_calc_timing(struct device *dev,
    + u32 u32bittiming, u32 u32bitrateprescaler);
    +
    +/*
    + * pru_can_write_data_to_mailbox() Updates the transmit mailboxes of PRU1
    + */
    +s16 pru_can_write_data_to_mailbox(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_get_data_from_mailbox() Receive data from receive mailboxes
    + */
    +s16 pru_can_get_data_from_mailbox(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_rx_id_map() Receive mailboxes ID Mapping of PRU0
    + */
    +s16 pru_can_rx_id_map(struct device *dev,
    + u32 u32nodeid, can_mailbox_number ecanmailboxno);
    +
    +/*
    + *pru_can_get_intr_status() Get interrupts status register value
    + */
    +s16 pru_can_get_intr_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +
    +/*
    + * pru_can_get_global_status() Get the globalstatus register value
    + */
    +s16 pru_can_get_global_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_get_mailbox_status() Get mailbox status reg value
    + */
    +s16 pru_can_get_mailbox_status(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_configuration_mode_set() Sets timing val for data transfer
    + */
    +s16 pru_can_config_mode_set(struct device *dev,
    + bool bconfig_modeflag);
    +
    +/*
    + * pru_can_emu_init() Initializes Can Emulation Parameters
    + */
    +s16 pru_can_emu_init(struct device *dev,
    + u32 u32pruclock);
    +
    +/*
    + * pru_can_emu_open() Opens can emu for application to use
    + */
    +s16 pru_can_emu_open(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_emu_close() Closes can emu for applications to use
    + */
    +s16 pru_can_emu_close(struct device *dev,
    + can_emu_app_hndl *pstremuapphndl);
    +
    +/*
    + * pru_can_emu_exit() Diables all the PRUs
    + */
    +s16 pru_can_emu_exit(struct device *dev);
    +
    +s16 pru_can_tx_mode_set(struct device *dev, bool btransfer_flag,
    + can_transfer_direction ecan_trx);
    +
    +s16 pru_can_emu_sreset(struct device *dev);
    +
    +s16 pru_can_tx(struct device *dev,
    + u8 u8mailboxnumber, u8 u8prunumber);
    +
    +s16 pru_can_start_abort_tx(struct device *dev,
    + bool btxabort_flag);
    +
    +s16 pru_can_mask_ints(struct device *dev, u32 int_mask);
    +
    +s32 pru_can_get_error_cnt(struct device *dev, u8 u8prunumber);
    +
    +s32 pru_can_get_intc_status(struct device *dev);
    +#endif
    --
    1.7.2.3


    \
     
     \ /
      Last update: 2011-02-11 15:41    [W:0.169 / U:1.036 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site