Commit 607cba15 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-next-for-4.4-20150921' of...

Merge tag 'linux-can-next-for-4.4-20150921' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2015-09-17

this is a pull request of 8 patches for net-next/master.

All 8 patches are by me and cleanup the flexcan driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 852bcafb 6fa7da24
...@@ -26,12 +26,8 @@ ...@@ -26,12 +26,8 @@
#include <linux/can/led.h> #include <linux/can/led.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
...@@ -63,10 +59,10 @@ ...@@ -63,10 +59,10 @@
#define FLEXCAN_MCR_LPRIO_EN BIT(13) #define FLEXCAN_MCR_LPRIO_EN BIT(13)
#define FLEXCAN_MCR_AEN BIT(12) #define FLEXCAN_MCR_AEN BIT(12)
#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f) #define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f)
#define FLEXCAN_MCR_IDAM_A (0 << 8) #define FLEXCAN_MCR_IDAM_A (0x0 << 8)
#define FLEXCAN_MCR_IDAM_B (1 << 8) #define FLEXCAN_MCR_IDAM_B (0x1 << 8)
#define FLEXCAN_MCR_IDAM_C (2 << 8) #define FLEXCAN_MCR_IDAM_C (0x2 << 8)
#define FLEXCAN_MCR_IDAM_D (3 << 8) #define FLEXCAN_MCR_IDAM_D (0x3 << 8)
/* FLEXCAN control register (CANCTRL) bits */ /* FLEXCAN control register (CANCTRL) bits */
#define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24) #define FLEXCAN_CTRL_PRESDIV(x) (((x) & 0xff) << 24)
...@@ -161,7 +157,7 @@ ...@@ -161,7 +157,7 @@
#define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24) #define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24)
#define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24) #define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24)
#define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24) #define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24)
#define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24) #define FLEXCAN_MB_CODE_RX_OVERRUN (0x6 << 24)
#define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24) #define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24)
#define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24) #define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24)
...@@ -175,12 +171,9 @@ ...@@ -175,12 +171,9 @@
#define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16) #define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16)
#define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff) #define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff)
#define FLEXCAN_MB_CODE_MASK (0xf0ffffff)
#define FLEXCAN_TIMEOUT_US (50) #define FLEXCAN_TIMEOUT_US (50)
/* /* FLEXCAN hardware feature flags
* FLEXCAN hardware feature flags
* *
* Below is some version info we got: * Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re- * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re-
...@@ -194,9 +187,9 @@ ...@@ -194,9 +187,9 @@
* *
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/ */
#define FLEXCAN_HAS_V10_FEATURES BIT(1) /* For core version >= 10 */ #define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */
#define FLEXCAN_HAS_BROKEN_ERR_STATE BIT(2) /* [TR]WRN_INT not connected */ #define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */
#define FLEXCAN_HAS_MECR_FEATURES BIT(3) /* Memory error detection */ #define FLEXCAN_QUIRK_DISABLE_MECR BIT(3) /* Disble Memory error detection */
/* Structure of the message buffer */ /* Structure of the message buffer */
struct flexcan_mb { struct flexcan_mb {
...@@ -228,7 +221,7 @@ struct flexcan_regs { ...@@ -228,7 +221,7 @@ struct flexcan_regs {
u32 rxfgmask; /* 0x48 */ u32 rxfgmask; /* 0x48 */
u32 rxfir; /* 0x4c */ u32 rxfir; /* 0x4c */
u32 _reserved3[12]; /* 0x50 */ u32 _reserved3[12]; /* 0x50 */
struct flexcan_mb cantxfg[64]; /* 0x80 */ struct flexcan_mb mb[64]; /* 0x80 */
/* FIFO-mode: /* FIFO-mode:
* MB * MB
* 0x080...0x08f 0 RX message buffer * 0x080...0x08f 0 RX message buffer
...@@ -251,14 +244,14 @@ struct flexcan_regs { ...@@ -251,14 +244,14 @@ struct flexcan_regs {
}; };
struct flexcan_devtype_data { struct flexcan_devtype_data {
u32 features; /* hardware controller features */ u32 quirks; /* quirks needed for different IP cores */
}; };
struct flexcan_priv { struct flexcan_priv {
struct can_priv can; struct can_priv can;
struct napi_struct napi; struct napi_struct napi;
void __iomem *base; struct flexcan_regs __iomem *regs;
u32 reg_esr; u32 reg_esr;
u32 reg_ctrl_default; u32 reg_ctrl_default;
...@@ -270,14 +263,17 @@ struct flexcan_priv { ...@@ -270,14 +263,17 @@ struct flexcan_priv {
}; };
static struct flexcan_devtype_data fsl_p1010_devtype_data = { static struct flexcan_devtype_data fsl_p1010_devtype_data = {
.features = FLEXCAN_HAS_BROKEN_ERR_STATE, .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE,
}; };
static struct flexcan_devtype_data fsl_imx28_devtype_data; static struct flexcan_devtype_data fsl_imx28_devtype_data;
static struct flexcan_devtype_data fsl_imx6q_devtype_data = { static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
.features = FLEXCAN_HAS_V10_FEATURES, .quirks = FLEXCAN_QUIRK_DISABLE_RXFG,
}; };
static struct flexcan_devtype_data fsl_vf610_devtype_data = { static struct flexcan_devtype_data fsl_vf610_devtype_data = {
.features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_MECR_FEATURES, .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_DISABLE_MECR,
}; };
static const struct can_bittiming_const flexcan_bittiming_const = { static const struct can_bittiming_const flexcan_bittiming_const = {
...@@ -292,11 +288,10 @@ static const struct can_bittiming_const flexcan_bittiming_const = { ...@@ -292,11 +288,10 @@ static const struct can_bittiming_const flexcan_bittiming_const = {
.brp_inc = 1, .brp_inc = 1,
}; };
/* /* Abstract off the read/write for arm versus ppc. This
* Abstract off the read/write for arm versus ppc. This
* assumes that PPC uses big-endian registers and everything * assumes that PPC uses big-endian registers and everything
* else uses little-endian registers, independent of CPU * else uses little-endian registers, independent of CPU
* endianess. * endianness.
*/ */
#if defined(CONFIG_PPC) #if defined(CONFIG_PPC)
static inline u32 flexcan_read(void __iomem *addr) static inline u32 flexcan_read(void __iomem *addr)
...@@ -345,7 +340,7 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, ...@@ -345,7 +340,7 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
static int flexcan_chip_enable(struct flexcan_priv *priv) static int flexcan_chip_enable(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg; u32 reg;
...@@ -364,7 +359,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv) ...@@ -364,7 +359,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv)
static int flexcan_chip_disable(struct flexcan_priv *priv) static int flexcan_chip_disable(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg; u32 reg;
...@@ -383,7 +378,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) ...@@ -383,7 +378,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv)
static int flexcan_chip_freeze(struct flexcan_priv *priv) static int flexcan_chip_freeze(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate; unsigned int timeout = 1000 * 1000 * 10 / priv->can.bittiming.bitrate;
u32 reg; u32 reg;
...@@ -402,7 +397,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv) ...@@ -402,7 +397,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv)
static int flexcan_chip_unfreeze(struct flexcan_priv *priv) static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
u32 reg; u32 reg;
...@@ -421,7 +416,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) ...@@ -421,7 +416,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv)
static int flexcan_chip_softreset(struct flexcan_priv *priv) static int flexcan_chip_softreset(struct flexcan_priv *priv)
{ {
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr); flexcan_write(FLEXCAN_MCR_SOFTRST, &regs->mcr);
...@@ -434,12 +429,11 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) ...@@ -434,12 +429,11 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv)
return 0; return 0;
} }
static int __flexcan_get_berr_counter(const struct net_device *dev, static int __flexcan_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec) struct can_berr_counter *bec)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg = flexcan_read(&regs->ecr); u32 reg = flexcan_read(&regs->ecr);
bec->txerr = (reg >> 0) & 0xff; bec->txerr = (reg >> 0) & 0xff;
...@@ -474,9 +468,10 @@ static int flexcan_get_berr_counter(const struct net_device *dev, ...@@ -474,9 +468,10 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
struct can_frame *cf = (struct can_frame *)skb->data; struct can_frame *cf = (struct can_frame *)skb->data;
u32 can_id; u32 can_id;
u32 data;
u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16); u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
if (can_dropped_invalid_skb(dev, skb)) if (can_dropped_invalid_skb(dev, skb))
...@@ -495,26 +490,26 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -495,26 +490,26 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
ctrl |= FLEXCAN_MB_CNT_RTR; ctrl |= FLEXCAN_MB_CNT_RTR;
if (cf->can_dlc > 0) { if (cf->can_dlc > 0) {
u32 data = be32_to_cpup((__be32 *)&cf->data[0]); data = be32_to_cpup((__be32 *)&cf->data[0]);
flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]); flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[0]);
} }
if (cf->can_dlc > 3) { if (cf->can_dlc > 3) {
u32 data = be32_to_cpup((__be32 *)&cf->data[4]); data = be32_to_cpup((__be32 *)&cf->data[4]);
flexcan_write(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); flexcan_write(data, &regs->mb[FLEXCAN_TX_BUF_ID].data[1]);
} }
can_put_echo_skb(skb, dev, 0); can_put_echo_skb(skb, dev, 0);
flexcan_write(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id); flexcan_write(can_id, &regs->mb[FLEXCAN_TX_BUF_ID].can_id);
flexcan_write(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); flexcan_write(ctrl, &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
/* Errata ERR005829 step8: /* Errata ERR005829 step8:
* Write twice INACTIVE(0x8) code to first MB. * Write twice INACTIVE(0x8) code to first MB.
*/ */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
&regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
&regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
...@@ -633,8 +628,8 @@ static void flexcan_read_fifo(const struct net_device *dev, ...@@ -633,8 +628,8 @@ static void flexcan_read_fifo(const struct net_device *dev,
struct can_frame *cf) struct can_frame *cf)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
struct flexcan_mb __iomem *mb = &regs->cantxfg[0]; struct flexcan_mb __iomem *mb = &regs->mb[0];
u32 reg_ctrl, reg_id; u32 reg_ctrl, reg_id;
reg_ctrl = flexcan_read(&mb->can_ctrl); reg_ctrl = flexcan_read(&mb->can_ctrl);
...@@ -683,12 +678,11 @@ static int flexcan_poll(struct napi_struct *napi, int quota) ...@@ -683,12 +678,11 @@ static int flexcan_poll(struct napi_struct *napi, int quota)
{ {
struct net_device *dev = napi->dev; struct net_device *dev = napi->dev;
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_iflag1, reg_esr; u32 reg_iflag1, reg_esr;
int work_done = 0; int work_done = 0;
/* /* The error bits are cleared on read,
* The error bits are cleared on read,
* use saved value from irq handler. * use saved value from irq handler.
*/ */
reg_esr = flexcan_read(&regs->esr) | priv->reg_esr; reg_esr = flexcan_read(&regs->esr) | priv->reg_esr;
...@@ -723,17 +717,17 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -723,17 +717,17 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
struct net_device *dev = dev_id; struct net_device *dev = dev_id;
struct net_device_stats *stats = &dev->stats; struct net_device_stats *stats = &dev->stats;
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_iflag1, reg_esr; u32 reg_iflag1, reg_esr;
reg_iflag1 = flexcan_read(&regs->iflag1); reg_iflag1 = flexcan_read(&regs->iflag1);
reg_esr = flexcan_read(&regs->esr); reg_esr = flexcan_read(&regs->esr);
/* ACK all bus error and state change IRQ sources */ /* ACK all bus error and state change IRQ sources */
if (reg_esr & FLEXCAN_ESR_ALL_INT) if (reg_esr & FLEXCAN_ESR_ALL_INT)
flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr); flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, &regs->esr);
/* /* schedule NAPI in case of:
* schedule NAPI in case of:
* - rx IRQ * - rx IRQ
* - state change IRQ * - state change IRQ
* - bus error IRQ and bus error reporting is activated * - bus error IRQ and bus error reporting is activated
...@@ -741,8 +735,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -741,8 +735,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) ||
(reg_esr & FLEXCAN_ESR_ERR_STATE) || (reg_esr & FLEXCAN_ESR_ERR_STATE) ||
flexcan_has_and_handle_berr(priv, reg_esr)) { flexcan_has_and_handle_berr(priv, reg_esr)) {
/* /* The error bits are cleared on read,
* The error bits are cleared on read,
* save them for later use. * save them for later use.
*/ */
priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
...@@ -765,9 +758,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -765,9 +758,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
stats->tx_bytes += can_get_echo_skb(dev, 0); stats->tx_bytes += can_get_echo_skb(dev, 0);
stats->tx_packets++; stats->tx_packets++;
can_led_event(dev, CAN_LED_EVENT_TX); can_led_event(dev, CAN_LED_EVENT_TX);
/* after sending a RTR frame mailbox is in RX mode */
/* after sending a RTR frame MB is in RX mode */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
&regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1); flexcan_write((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
netif_wake_queue(dev); netif_wake_queue(dev);
} }
...@@ -779,7 +773,7 @@ static void flexcan_set_bittiming(struct net_device *dev) ...@@ -779,7 +773,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
{ {
const struct flexcan_priv *priv = netdev_priv(dev); const struct flexcan_priv *priv = netdev_priv(dev);
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg; u32 reg;
reg = flexcan_read(&regs->ctrl); reg = flexcan_read(&regs->ctrl);
...@@ -813,8 +807,7 @@ static void flexcan_set_bittiming(struct net_device *dev) ...@@ -813,8 +807,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl)); flexcan_read(&regs->mcr), flexcan_read(&regs->ctrl));
} }
/* /* flexcan_chip_start
* flexcan_chip_start
* *
* this functions is entered with clocks enabled * this functions is entered with clocks enabled
* *
...@@ -822,7 +815,7 @@ static void flexcan_set_bittiming(struct net_device *dev) ...@@ -822,7 +815,7 @@ static void flexcan_set_bittiming(struct net_device *dev)
static int flexcan_chip_start(struct net_device *dev) static int flexcan_chip_start(struct net_device *dev)
{ {
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr; u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
int err, i; int err, i;
...@@ -838,29 +831,26 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -838,29 +831,26 @@ static int flexcan_chip_start(struct net_device *dev)
flexcan_set_bittiming(dev); flexcan_set_bittiming(dev);
/* /* MCR
* MCR
* *
* enable freeze * enable freeze
* enable fifo * enable fifo
* halt now * halt now
* only supervisor access * only supervisor access
* enable warning int * enable warning int
* choose format C
* disable local echo * disable local echo
* * choose format C
* set max mailbox number
*/ */
reg_mcr = flexcan_read(&regs->mcr); reg_mcr = flexcan_read(&regs->mcr);
reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS |
FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID);
netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
flexcan_write(reg_mcr, &regs->mcr); flexcan_write(reg_mcr, &regs->mcr);
/* /* CTRL
* CTRL
* *
* disable timer sync feature * disable timer sync feature
* *
...@@ -875,12 +865,12 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -875,12 +865,12 @@ static int flexcan_chip_start(struct net_device *dev)
reg_ctrl &= ~FLEXCAN_CTRL_TSYN; reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF | reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
FLEXCAN_CTRL_ERR_STATE; FLEXCAN_CTRL_ERR_STATE;
/*
* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK), /* enable the "error interrupt" (FLEXCAN_CTRL_ERR_MSK),
* on most Flexcan cores, too. Otherwise we don't get * on most Flexcan cores, too. Otherwise we don't get
* any error warning or passive interrupts. * any error warning or passive interrupts.
*/ */
if (priv->devtype_data->features & FLEXCAN_HAS_BROKEN_ERR_STATE || if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE ||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
else else
...@@ -888,41 +878,41 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -888,41 +878,41 @@ static int flexcan_chip_start(struct net_device *dev)
/* save for later use */ /* save for later use */
priv->reg_ctrl_default = reg_ctrl; priv->reg_ctrl_default = reg_ctrl;
/* leave interrupts disabled for now */
reg_ctrl &= ~FLEXCAN_CTRL_ERR_ALL;
netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
flexcan_write(reg_ctrl, &regs->ctrl); flexcan_write(reg_ctrl, &regs->ctrl);
/* clear and invalidate all mailboxes first */ /* clear and invalidate all mailboxes first */
for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) { for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->mb); i++) {
flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE,
&regs->cantxfg[i].can_ctrl); &regs->mb[i].can_ctrl);
} }
/* Errata ERR005829: mark first TX mailbox as INACTIVE */ /* Errata ERR005829: mark first TX mailbox as INACTIVE */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
&regs->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); &regs->mb[FLEXCAN_TX_BUF_RESERVED].can_ctrl);
/* mark TX mailbox as INACTIVE */ /* mark TX mailbox as INACTIVE */
flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE,
&regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); &regs->mb[FLEXCAN_TX_BUF_ID].can_ctrl);
/* acceptance mask/acceptance code (accept everything) */ /* acceptance mask/acceptance code (accept everything) */
flexcan_write(0x0, &regs->rxgmask); flexcan_write(0x0, &regs->rxgmask);
flexcan_write(0x0, &regs->rx14mask); flexcan_write(0x0, &regs->rx14mask);
flexcan_write(0x0, &regs->rx15mask); flexcan_write(0x0, &regs->rx15mask);
if (priv->devtype_data->features & FLEXCAN_HAS_V10_FEATURES) if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
flexcan_write(0x0, &regs->rxfgmask); flexcan_write(0x0, &regs->rxfgmask);
/* /* On Vybrid, disable memory error detection interrupts
* On Vybrid, disable memory error detection interrupts
* and freeze mode. * and freeze mode.
* This also works around errata e5295 which generates * This also works around errata e5295 which generates
* false positive memory errors and put the device in * false positive memory errors and put the device in
* freeze mode. * freeze mode.
*/ */
if (priv->devtype_data->features & FLEXCAN_HAS_MECR_FEATURES) { if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) {
/* /* Follow the protocol as described in "Detection
* Follow the protocol as described in "Detection
* and Correction of Memory Errors" to write to * and Correction of Memory Errors" to write to
* MECR register * MECR register
*/ */
...@@ -949,8 +939,11 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -949,8 +939,11 @@ static int flexcan_chip_start(struct net_device *dev)
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
/* enable FIFO interrupts */ /* enable interrupts atomically */
disable_irq(dev->irq);
flexcan_write(priv->reg_ctrl_default, &regs->ctrl);
flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1); flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
enable_irq(dev->irq);
/* print chip status */ /* print chip status */
netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__, netdev_dbg(dev, "%s: reading mcr=0x%08x ctrl=0x%08x\n", __func__,
...@@ -965,16 +958,14 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -965,16 +958,14 @@ static int flexcan_chip_start(struct net_device *dev)
return err; return err;
} }
/* /* flexcan_chip_stop
* flexcan_chip_stop
* *
* this functions is entered with clocks enabled * this functions is entered with clocks enabled
*
*/ */
static void flexcan_chip_stop(struct net_device *dev) static void flexcan_chip_stop(struct net_device *dev)
{ {
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
/* freeze + disable module */ /* freeze + disable module */
flexcan_chip_freeze(priv); flexcan_chip_freeze(priv);
...@@ -987,8 +978,6 @@ static void flexcan_chip_stop(struct net_device *dev) ...@@ -987,8 +978,6 @@ static void flexcan_chip_stop(struct net_device *dev)
flexcan_transceiver_disable(priv); flexcan_transceiver_disable(priv);
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
return;
} }
static int flexcan_open(struct net_device *dev) static int flexcan_open(struct net_device *dev)
...@@ -1085,7 +1074,7 @@ static const struct net_device_ops flexcan_netdev_ops = { ...@@ -1085,7 +1074,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
static int register_flexcandev(struct net_device *dev) static int register_flexcandev(struct net_device *dev)
{ {
struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->base; struct flexcan_regs __iomem *regs = priv->regs;
u32 reg, err; u32 reg, err;
err = clk_prepare_enable(priv->clk_ipg); err = clk_prepare_enable(priv->clk_ipg);
...@@ -1114,8 +1103,7 @@ static int register_flexcandev(struct net_device *dev) ...@@ -1114,8 +1103,7 @@ static int register_flexcandev(struct net_device *dev)
FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV; FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
flexcan_write(reg, &regs->mcr); flexcan_write(reg, &regs->mcr);
/* /* Currently we only support newer versions of this core
* Currently we only support newer versions of this core
* featuring a RX FIFO. Older cores found on some Coldfire * featuring a RX FIFO. Older cores found on some Coldfire
* derivates are not yet supported. * derivates are not yet supported.
*/ */
...@@ -1168,7 +1156,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1168,7 +1156,7 @@ static int flexcan_probe(struct platform_device *pdev)
struct regulator *reg_xceiver; struct regulator *reg_xceiver;
struct resource *mem; struct resource *mem;
struct clk *clk_ipg = NULL, *clk_per = NULL; struct clk *clk_ipg = NULL, *clk_per = NULL;
void __iomem *base; struct flexcan_regs __iomem *regs;
int err, irq; int err, irq;
u32 clock_freq = 0; u32 clock_freq = 0;
...@@ -1202,9 +1190,9 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1202,9 +1190,9 @@ static int flexcan_probe(struct platform_device *pdev)
if (irq <= 0) if (irq <= 0)
return -ENODEV; return -ENODEV;
base = devm_ioremap_resource(&pdev->dev, mem); regs = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(base)) if (IS_ERR(regs))
return PTR_ERR(base); return PTR_ERR(regs);
of_id = of_match_device(flexcan_of_match, &pdev->dev); of_id = of_match_device(flexcan_of_match, &pdev->dev);
if (of_id) { if (of_id) {
...@@ -1232,12 +1220,11 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1232,12 +1220,11 @@ static int flexcan_probe(struct platform_device *pdev)
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
CAN_CTRLMODE_BERR_REPORTING; CAN_CTRLMODE_BERR_REPORTING;
priv->base = base; priv->regs = regs;
priv->clk_ipg = clk_ipg; priv->clk_ipg = clk_ipg;
priv->clk_per = clk_per; priv->clk_per = clk_per;
priv->pdata = dev_get_platdata(&pdev->dev); priv->pdata = dev_get_platdata(&pdev->dev);
priv->devtype_data = devtype_data; priv->devtype_data = devtype_data;
priv->reg_xceiver = reg_xceiver; priv->reg_xceiver = reg_xceiver;
netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT); netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
...@@ -1254,7 +1241,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -1254,7 +1241,7 @@ static int flexcan_probe(struct platform_device *pdev)
devm_can_led_init(dev); devm_can_led_init(dev);
dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n", dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
priv->base, dev->irq); priv->regs, dev->irq);
return 0; return 0;
......
...@@ -14,9 +14,10 @@ ...@@ -14,9 +14,10 @@
#define _CAN_DEV_H #define _CAN_DEV_H
#include <linux/can.h> #include <linux/can.h>
#include <linux/can/netlink.h>
#include <linux/can/error.h> #include <linux/can/error.h>
#include <linux/can/led.h> #include <linux/can/led.h>
#include <linux/can/netlink.h>
#include <linux/netdevice.h>
/* /*
* CAN mode * CAN mode
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/netdevice.h>
enum can_led_event { enum can_led_event {
CAN_LED_EVENT_OPEN, CAN_LED_EVENT_OPEN,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment