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

Merge tag 'linux-can-next-for-4.21-20181128' of...

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



Marc Kleine-Budde says:

====================
This is a pull request for net-next/master consisting of 18 patches.

The first patch is by Colin Ian King and fixes the spelling in the ucan
driver.

The next three patches target the xilinx driver. YueHaibing's patch
fixes the return type of ndo_start_xmit function. Two patches by
Shubhrajyoti Datta add support for the CAN FD 2.0 controllers.

Flavio Suligoi's patch for the sja1000 driver add support for the ASEM
CAN raw hardware.

Wolfram Sang's and Kuninori Morimoto's patches switch the rcar driver to
use SPDX license identifiers.

The remaining 111 patches improve the flexcan driver. Pankaj Bansal's
patch enables the driver in Kconfig on all architectures with IOMEM
support. The next four patches by me fix indention, add missing
parentheses and comments. Aisheng Dong's patches add self wake support
and document it in the DT bindings. The remaining patches by Pankaj
Bansal first fix the loopback support and prepare the driver for the
CAN-FD support needed for the LX2160A SoC. The actual CAN-FD support
will be added in a later patch series.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e561bb29 6cbf7602
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -24,6 +24,14 @@ Optional properties:
              if this property is present then controller is assumed to be big
              endian.

- fsl,stop-mode: register bits of stop mode control, the format is
		 <&gpr req_gpr req_bit ack_gpr ack_bit>.
		 gpr is the phandle to general purpose register node.
		 req_gpr is the gpr register offset of CAN stop request.
		 req_bit is the bit offset of CAN stop request.
		 ack_gpr is the gpr register offset of CAN stop acknowledge.
		 ack_bit is the bit offset of CAN stop acknowledge.

Example:

	can@1c000 {
+1 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ Required properties:
			  - "xlnx,zynq-can-1.0" for Zynq CAN controllers
			  - "xlnx,axi-can-1.00.a" for Axi CAN controllers
			  - "xlnx,canfd-1.0" for CAN FD controllers
			  - "xlnx,canfd-2.0" for CAN FD 2.0 controllers
- reg			: Physical base address and size of the controller
			  registers map.
- interrupts		: Property with a value describing the interrupt
+1 −1
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ config CAN_AT91

config CAN_FLEXCAN
	tristate "Support for Freescale FLEXCAN based chips"
	depends on ARM || PPC
	depends on OF && HAS_IOMEM
	---help---
	  Say Y here if you want to support for Freescale FlexCAN.

+288 −77
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>

#define DRV_NAME			"flexcan"

@@ -131,16 +133,15 @@
	(FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
#define FLEXCAN_ESR_ALL_INT \
	(FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | \
	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT)
	 FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT | \
	 FLEXCAN_ESR_WAK_INT)

/* FLEXCAN interrupt flag register (IFLAG) bits */
/* Errata ERR005829 step7: Reserve first valid MB */
#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8
#define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP	0
#define FLEXCAN_TX_MB				63
#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST	(FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1)
#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST	(FLEXCAN_TX_MB - 1)
#define FLEXCAN_IFLAG_MB(x)		BIT(x & 0x1f)
#define FLEXCAN_IFLAG_MB(x)		BIT((x) & 0x1f)
#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)
#define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)
#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE	BIT(5)
@@ -189,12 +190,13 @@
#define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP	BIT(5) /* Use timestamp based offloading */
#define FLEXCAN_QUIRK_BROKEN_PERR_STATE	BIT(6) /* No interrupt for error passive */
#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN	BIT(7) /* default to BE register access */
#define FLEXCAN_QUIRK_SETUP_STOP_MODE		BIT(8) /* Setup stop mode to support wakeup */

/* Structure of the message buffer */
struct flexcan_mb {
	u32 can_ctrl;
	u32 can_id;
	u32 data[2];
	u32 data[];
};

/* Structure of the hardware registers */
@@ -223,7 +225,7 @@ struct flexcan_regs {
	u32 rxfgmask;		/* 0x48 */
	u32 rxfir;		/* 0x4c */
	u32 _reserved3[12];	/* 0x50 */
	struct flexcan_mb mb[64];	/* 0x80 */
	u8 mb[2][512];		/* 0x80 */
	/* FIFO-mode:
	 *			MB
	 * 0x080...0x08f	0	RX message buffer
@@ -253,12 +255,24 @@ struct flexcan_devtype_data {
	u32 quirks;		/* quirks needed for different IP cores */
};

struct flexcan_stop_mode {
	struct regmap *gpr;
	u8 req_gpr;
	u8 req_bit;
	u8 ack_gpr;
	u8 ack_bit;
};

struct flexcan_priv {
	struct can_priv can;
	struct can_rx_offload offload;

	struct flexcan_regs __iomem *regs;
	struct flexcan_mb __iomem *tx_mb;
	struct flexcan_mb __iomem *tx_mb_reserved;
	u8 tx_mb_idx;
	u8 mb_count;
	u8 mb_size;
	u32 reg_ctrl_default;
	u32 reg_imask1_default;
	u32 reg_imask2_default;
@@ -267,6 +281,7 @@ struct flexcan_priv {
	struct clk *clk_per;
	const struct flexcan_devtype_data *devtype_data;
	struct regulator *reg_xceiver;
	struct flexcan_stop_mode stm;

	/* Read and Write APIs */
	u32 (*read)(void __iomem *addr);
@@ -290,7 +305,8 @@ static const struct flexcan_devtype_data fsl_imx28_devtype_data = {

static const struct flexcan_devtype_data fsl_imx6q_devtype_data = {
	.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE,
		FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE |
		FLEXCAN_QUIRK_SETUP_STOP_MODE,
};

static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
@@ -350,6 +366,68 @@ static inline void flexcan_write_le(u32 val, void __iomem *addr)
	iowrite32(val, addr);
}

static struct flexcan_mb __iomem *flexcan_get_mb(const struct flexcan_priv *priv,
						 u8 mb_index)
{
	u8 bank_size;
	bool bank;

	if (WARN_ON(mb_index >= priv->mb_count))
		return NULL;

	bank_size = sizeof(priv->regs->mb[0]) / priv->mb_size;

	bank = mb_index >= bank_size;
	if (bank)
		mb_index -= bank_size;

	return (struct flexcan_mb __iomem *)
		(&priv->regs->mb[bank][priv->mb_size * mb_index]);
}

static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	u32 reg_mcr;

	reg_mcr = priv->read(&regs->mcr);

	if (enable)
		reg_mcr |= FLEXCAN_MCR_WAK_MSK;
	else
		reg_mcr &= ~FLEXCAN_MCR_WAK_MSK;

	priv->write(reg_mcr, &regs->mcr);
}

static inline void flexcan_enter_stop_mode(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	u32 reg_mcr;

	reg_mcr = priv->read(&regs->mcr);
	reg_mcr |= FLEXCAN_MCR_SLF_WAK;
	priv->write(reg_mcr, &regs->mcr);

	/* enable stop request */
	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
			   1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
}

static inline void flexcan_exit_stop_mode(struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
	u32 reg_mcr;

	/* remove stop request */
	regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
			   1 << priv->stm.req_bit, 0);

	reg_mcr = priv->read(&regs->mcr);
	reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
	priv->write(reg_mcr, &regs->mcr);
}

static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
{
	struct flexcan_regs __iomem *regs = priv->regs;
@@ -512,11 +590,11 @@ static int flexcan_get_berr_counter(const struct net_device *dev,
static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	const struct flexcan_priv *priv = netdev_priv(dev);
	struct flexcan_regs __iomem *regs = priv->regs;
	struct can_frame *cf = (struct can_frame *)skb->data;
	u32 can_id;
	u32 data;
	u32 ctrl = FLEXCAN_MB_CODE_TX_DATA | (cf->can_dlc << 16);
	int i;

	if (can_dropped_invalid_skb(dev, skb))
		return NETDEV_TX_OK;
@@ -533,19 +611,15 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
	if (cf->can_id & CAN_RTR_FLAG)
		ctrl |= FLEXCAN_MB_CNT_RTR;

	if (cf->can_dlc > 0) {
		data = be32_to_cpup((__be32 *)&cf->data[0]);
		priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[0]);
	}
	if (cf->can_dlc > 4) {
		data = be32_to_cpup((__be32 *)&cf->data[4]);
		priv->write(data, &regs->mb[FLEXCAN_TX_MB].data[1]);
	for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
		data = be32_to_cpup((__be32 *)&cf->data[i]);
		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
	}

	can_put_echo_skb(skb, dev, 0);

	priv->write(can_id, &regs->mb[FLEXCAN_TX_MB].can_id);
	priv->write(ctrl, &regs->mb[FLEXCAN_TX_MB].can_ctrl);
	priv->write(can_id, &priv->tx_mb->can_id);
	priv->write(ctrl, &priv->tx_mb->can_ctrl);

	/* Errata ERR005829 step8:
	 * Write twice INACTIVE(0x8) code to first MB.
@@ -672,8 +746,11 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
{
	struct flexcan_priv *priv = rx_offload_to_priv(offload);
	struct flexcan_regs __iomem *regs = priv->regs;
	struct flexcan_mb __iomem *mb = &regs->mb[n];
	struct flexcan_mb __iomem *mb;
	u32 reg_ctrl, reg_id, reg_iflag1;
	int i;

	mb = flexcan_get_mb(priv, n);

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
		u32 code;
@@ -714,8 +791,10 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,
		cf->can_id |= CAN_RTR_FLAG;
	cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);

	*(__be32 *)(cf->data + 0) = cpu_to_be32(priv->read(&mb->data[0]));
	*(__be32 *)(cf->data + 4) = cpu_to_be32(priv->read(&mb->data[1]));
	for (i = 0; i < cf->can_dlc; i += sizeof(u32)) {
		__be32 data = cpu_to_be32(priv->read(&mb->data[i / sizeof(u32)]));
		*(__be32 *)(cf->data + i) = data;
	}

	/* mark as read */
	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
@@ -744,7 +823,7 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)
	u32 iflag1, iflag2;

	iflag2 = priv->read(&regs->iflag2) & priv->reg_imask2_default &
		~FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);
		~FLEXCAN_IFLAG_MB(priv->tx_mb_idx);
	iflag1 = priv->read(&regs->iflag1) & priv->reg_imask1_default;

	return (u64)iflag2 << 32 | iflag1;
@@ -794,8 +873,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
	reg_iflag2 = priv->read(&regs->iflag2);

	/* transmission complete interrupt */
	if (reg_iflag2 & FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB)) {
		u32 reg_ctrl = priv->read(&regs->mb[FLEXCAN_TX_MB].can_ctrl);
	if (reg_iflag2 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) {
		u32 reg_ctrl = priv->read(&priv->tx_mb->can_ctrl);

		handled = IRQ_HANDLED;
		stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload,
@@ -805,8 +884,8 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)

		/* after sending a RTR frame MB is in RX mode */
		priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
			    &regs->mb[FLEXCAN_TX_MB].can_ctrl);
		priv->write(FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB), &regs->iflag2);
			    &priv->tx_mb->can_ctrl);
		priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), &regs->iflag2);
		netif_wake_queue(dev);
	}

@@ -919,6 +998,7 @@ static int flexcan_chip_start(struct net_device *dev)
	struct flexcan_regs __iomem *regs = priv->regs;
	u32 reg_mcr, reg_ctrl, reg_ctrl2, reg_mecr;
	int err, i;
	struct flexcan_mb __iomem *mb;

	/* enable module */
	err = flexcan_chip_enable(priv);
@@ -935,11 +1015,9 @@ static int flexcan_chip_start(struct net_device *dev)
	/* MCR
	 *
	 * enable freeze
	 * enable fifo
	 * halt now
	 * only supervisor access
	 * enable warning int
	 * disable local echo
	 * enable individual RX masking
	 * choose format C
	 * set max mailbox number
@@ -947,14 +1025,37 @@ static int flexcan_chip_start(struct net_device *dev)
	reg_mcr = priv->read(&regs->mcr);
	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);
	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |
		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ |
		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_MB);
		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IRMQ | FLEXCAN_MCR_IDAM_C |
		FLEXCAN_MCR_MAXMB(priv->tx_mb_idx);

	/* MCR
	 *
	 * FIFO:
	 * - disable for timestamp mode
	 * - enable for FIFO mode
	 */
	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
		reg_mcr &= ~FLEXCAN_MCR_FEN;
	else
		reg_mcr |= FLEXCAN_MCR_FEN;

	/* MCR
	 *
	 * NOTE: In loopback mode, the CAN_MCR[SRXDIS] cannot be
	 *       asserted because this will impede the self reception
	 *       of a transmitted message. This is not documented in
	 *       earlier versions of flexcan block guide.
	 *
	 * Self Reception:
	 * - enable Self Reception for loopback mode
	 *   (by clearing "Self Reception Disable" bit)
	 * - disable for normal operation
	 */
	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
		reg_mcr &= ~FLEXCAN_MCR_SRX_DIS;
	else
		reg_mcr |= FLEXCAN_MCR_SRX_DIS;

	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);
	priv->write(reg_mcr, &regs->mcr);

@@ -999,14 +1100,16 @@ static int flexcan_chip_start(struct net_device *dev)

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
			mb = flexcan_get_mb(priv, i);
			priv->write(FLEXCAN_MB_CODE_RX_EMPTY,
				    &regs->mb[i].can_ctrl);
				    &mb->can_ctrl);
		}
	} else {
		/* clear and invalidate unused mailboxes first */
		for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= ARRAY_SIZE(regs->mb); i++) {
		for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) {
			mb = flexcan_get_mb(priv, i);
			priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
				    &regs->mb[i].can_ctrl);
				    &mb->can_ctrl);
		}
	}

@@ -1016,7 +1119,7 @@ static int flexcan_chip_start(struct net_device *dev)

	/* mark TX mailbox as INACTIVE */
	priv->write(FLEXCAN_MB_CODE_TX_INACTIVE,
		    &regs->mb[FLEXCAN_TX_MB].can_ctrl);
		    &priv->tx_mb->can_ctrl);

	/* acceptance mask/acceptance code (accept everything) */
	priv->write(0x0, &regs->rxgmask);
@@ -1027,7 +1130,7 @@ static int flexcan_chip_start(struct net_device *dev)
		priv->write(0x0, &regs->rxfgmask);

	/* clear acceptance filters */
	for (i = 0; i < ARRAY_SIZE(regs->mb); i++)
	for (i = 0; i < priv->mb_count; i++)
		priv->write(0, &regs->rximr[i]);

	/* On Vybrid, disable memory error detection interrupts
@@ -1128,10 +1231,49 @@ static int flexcan_open(struct net_device *dev)
	if (err)
		goto out_close;

	priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
	priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
			 (sizeof(priv->regs->mb[1]) / priv->mb_size);

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
		priv->tx_mb_reserved =
			flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP);
	else
		priv->tx_mb_reserved =
			flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_FIFO);
	priv->tx_mb_idx = priv->mb_count - 1;
	priv->tx_mb = flexcan_get_mb(priv, priv->tx_mb_idx);

	priv->reg_imask1_default = 0;
	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx);

	priv->offload.mailbox_read = flexcan_mailbox_read;

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
		u64 imask;

		priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST;
		priv->offload.mb_last = priv->mb_count - 2;

		imask = GENMASK_ULL(priv->offload.mb_last,
				    priv->offload.mb_first);
		priv->reg_imask1_default |= imask;
		priv->reg_imask2_default |= imask >> 32;

		err = can_rx_offload_add_timestamp(dev, &priv->offload);
	} else {
		priv->reg_imask1_default |= FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
			FLEXCAN_IFLAG_RX_FIFO_AVAILABLE;
		err = can_rx_offload_add_fifo(dev, &priv->offload,
					      FLEXCAN_NAPI_WEIGHT);
	}
	if (err)
		goto out_free_irq;

	/* start chip and queuing */
	err = flexcan_chip_start(dev);
	if (err)
		goto out_free_irq;
		goto out_offload_del;

	can_led_event(dev, CAN_LED_EVENT_OPEN);

@@ -1140,6 +1282,8 @@ static int flexcan_open(struct net_device *dev)

	return 0;

 out_offload_del:
	can_rx_offload_del(&priv->offload);
 out_free_irq:
	free_irq(dev->irq, dev);
 out_close:
@@ -1160,6 +1304,7 @@ static int flexcan_close(struct net_device *dev)
	can_rx_offload_disable(&priv->offload);
	flexcan_chip_stop(dev);

	can_rx_offload_del(&priv->offload);
	free_irq(dev->irq, dev);
	clk_disable_unprepare(priv->clk_per);
	clk_disable_unprepare(priv->clk_ipg);
@@ -1260,6 +1405,59 @@ static void unregister_flexcandev(struct net_device *dev)
	unregister_candev(dev);
}

static int flexcan_setup_stop_mode(struct platform_device *pdev)
{
	struct net_device *dev = platform_get_drvdata(pdev);
	struct device_node *np = pdev->dev.of_node;
	struct device_node *gpr_np;
	struct flexcan_priv *priv;
	phandle phandle;
	u32 out_val[5];
	int ret;

	if (!np)
		return -EINVAL;

	/* stop mode property format is:
	 * <&gpr req_gpr req_bit ack_gpr ack_bit>.
	 */
	ret = of_property_read_u32_array(np, "fsl,stop-mode", out_val,
					 ARRAY_SIZE(out_val));
	if (ret) {
		dev_dbg(&pdev->dev, "no stop-mode property\n");
		return ret;
	}
	phandle = *out_val;

	gpr_np = of_find_node_by_phandle(phandle);
	if (!gpr_np) {
		dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
		return PTR_ERR(gpr_np);
	}

	priv = netdev_priv(dev);
	priv->stm.gpr = syscon_node_to_regmap(gpr_np);
	of_node_put(gpr_np);
	if (IS_ERR(priv->stm.gpr)) {
		dev_dbg(&pdev->dev, "could not find gpr regmap\n");
		return PTR_ERR(priv->stm.gpr);
	}

	priv->stm.req_gpr = out_val[1];
	priv->stm.req_bit = out_val[2];
	priv->stm.ack_gpr = out_val[3];
	priv->stm.ack_bit = out_val[4];

	dev_dbg(&pdev->dev,
		"gpr %s req_gpr=0x02%x req_bit=%u ack_gpr=0x02%x ack_bit=%u\n",
		gpr_np->full_name, priv->stm.req_gpr, priv->stm.req_bit,
		priv->stm.ack_gpr, priv->stm.ack_bit);

	device_set_wakeup_capable(&pdev->dev, true);

	return 0;
}

static const struct of_device_id flexcan_of_match[] = {
	{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
	{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
@@ -1371,35 +1569,6 @@ static int flexcan_probe(struct platform_device *pdev)
	priv->devtype_data = devtype_data;
	priv->reg_xceiver = reg_xceiver;

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP];
	else
		priv->tx_mb_reserved = &regs->mb[FLEXCAN_TX_MB_RESERVED_OFF_FIFO];

	priv->reg_imask1_default = 0;
	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);

	priv->offload.mailbox_read = flexcan_mailbox_read;

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
		u64 imask;

		priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST;
		priv->offload.mb_last = FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST;

		imask = GENMASK_ULL(priv->offload.mb_last, priv->offload.mb_first);
		priv->reg_imask1_default |= imask;
		priv->reg_imask2_default |= imask >> 32;

		err = can_rx_offload_add_timestamp(dev, &priv->offload);
	} else {
		priv->reg_imask1_default |= FLEXCAN_IFLAG_RX_FIFO_OVERFLOW |
			FLEXCAN_IFLAG_RX_FIFO_AVAILABLE;
		err = can_rx_offload_add_fifo(dev, &priv->offload, FLEXCAN_NAPI_WEIGHT);
	}
	if (err)
		goto failed_offload;

	err = register_flexcandev(dev);
	if (err) {
		dev_err(&pdev->dev, "registering netdev failed\n");
@@ -1408,12 +1577,17 @@ static int flexcan_probe(struct platform_device *pdev)

	devm_can_led_init(dev);

	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE) {
		err = flexcan_setup_stop_mode(pdev);
		if (err)
			dev_dbg(&pdev->dev, "failed to setup stop-mode\n");
	}

	dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
		 priv->regs, dev->irq);

	return 0;

 failed_offload:
 failed_register:
	free_candev(dev);
	return err;
@@ -1422,10 +1596,8 @@ static int flexcan_probe(struct platform_device *pdev)
static int flexcan_remove(struct platform_device *pdev)
{
	struct net_device *dev = platform_get_drvdata(pdev);
	struct flexcan_priv *priv = netdev_priv(dev);

	unregister_flexcandev(dev);
	can_rx_offload_del(&priv->offload);
	free_candev(dev);

	return 0;
@@ -1438,9 +1610,17 @@ static int __maybe_unused flexcan_suspend(struct device *device)
	int err;

	if (netif_running(dev)) {
		/* if wakeup is enabled, enter stop mode
		 * else enter disabled mode.
		 */
		if (device_may_wakeup(device)) {
			enable_irq_wake(dev->irq);
			flexcan_enter_stop_mode(priv);
		} else {
			err = flexcan_chip_disable(priv);
			if (err)
				return err;
		}
		netif_stop_queue(dev);
		netif_device_detach(dev);
	}
@@ -1459,14 +1639,45 @@ static int __maybe_unused flexcan_resume(struct device *device)
	if (netif_running(dev)) {
		netif_device_attach(dev);
		netif_start_queue(dev);
		if (device_may_wakeup(device)) {
			disable_irq_wake(dev->irq);
		} else {
			err = flexcan_chip_enable(priv);
			if (err)
				return err;
		}
	}
	return 0;
}

static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume);
static int __maybe_unused flexcan_noirq_suspend(struct device *device)
{
	struct net_device *dev = dev_get_drvdata(device);
	struct flexcan_priv *priv = netdev_priv(dev);

	if (netif_running(dev) && device_may_wakeup(device))
		flexcan_enable_wakeup_irq(priv, true);

	return 0;
}

static int __maybe_unused flexcan_noirq_resume(struct device *device)
{
	struct net_device *dev = dev_get_drvdata(device);
	struct flexcan_priv *priv = netdev_priv(dev);

	if (netif_running(dev) && device_may_wakeup(device)) {
		flexcan_enable_wakeup_irq(priv, false);
		flexcan_exit_stop_mode(priv);
	}

	return 0;
}

static const struct dev_pm_ops flexcan_pm_ops = {
	SET_SYSTEM_SLEEP_PM_OPS(flexcan_suspend, flexcan_resume)
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(flexcan_noirq_suspend, flexcan_noirq_resume)
};

static struct platform_driver flexcan_driver = {
	.driver = {
+1 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0
config CAN_RCAR
	tristate "Renesas R-Car CAN controller"
	depends on ARCH_RENESAS || ARM
Loading