Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+92 −105
Original line number Original line Diff line number Diff line
@@ -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 @@
#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 @@
#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 @@
#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 @@
 *
 *
 * 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 {
	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 {
};
};


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 {
};
};


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 = {
	.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,


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)


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)


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)


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)


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)
	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,
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)
		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,
			      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)
{
{
	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)
	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)
	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)
		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)
{
{
	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)
		   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)
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)


	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)
	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)


	/* 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)


	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)
	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)


	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 = {
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)
		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)
	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)
	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)
	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)
	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;


+2 −1
Original line number Original line Diff line number Diff line
@@ -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
+1 −0
Original line number Original line Diff line number Diff line
@@ -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,