162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci * flexcan.c - FLEXCAN CAN controller driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (c) 2005-2006 Varma Electronics Oy
562306a36Sopenharmony_ci * Copyright (c) 2009 Sascha Hauer, Pengutronix
662306a36Sopenharmony_ci * Copyright (c) 2010-2017 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
762306a36Sopenharmony_ci * Copyright (c) 2014 David Jander, Protonic Holland
862306a36Sopenharmony_ci * Copyright (C) 2022 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci */
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#ifndef _FLEXCAN_H
1562306a36Sopenharmony_ci#define _FLEXCAN_H
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <linux/can/rx-offload.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* FLEXCAN hardware feature flags
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * Below is some version info we got:
2262306a36Sopenharmony_ci *    SOC   Version   IP-Version  Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece-   FD Mode     MB
2362306a36Sopenharmony_ci *                                Filter? connected?  Passive detection  ption in MB Supported?
2462306a36Sopenharmony_ci * MCF5441X FlexCAN2  ?               no       yes        no       no        no           no     16
2562306a36Sopenharmony_ci *    MX25  FlexCAN2  03.00.00.00     no        no        no       no        no           no     64
2662306a36Sopenharmony_ci *    MX28  FlexCAN2  03.00.04.00    yes       yes        no       no        no           no     64
2762306a36Sopenharmony_ci *    MX35  FlexCAN2  03.00.00.00     no        no        no       no        no           no     64
2862306a36Sopenharmony_ci *    MX53  FlexCAN2  03.00.00.00    yes        no        no       no        no           no     64
2962306a36Sopenharmony_ci *    MX6s  FlexCAN3  10.00.12.00    yes       yes        no       no       yes           no     64
3062306a36Sopenharmony_ci *    MX8QM FlexCAN3  03.00.23.00    yes       yes        no       no       yes          yes     64
3162306a36Sopenharmony_ci *    MX8MP FlexCAN3  03.00.17.01    yes       yes        no      yes       yes          yes     64
3262306a36Sopenharmony_ci *    VF610 FlexCAN3  ?               no       yes        no      yes       yes?          no     64
3362306a36Sopenharmony_ci *  LS1021A FlexCAN2  03.00.04.00     no       yes        no       no       yes           no     64
3462306a36Sopenharmony_ci *  LX2160A FlexCAN3  03.00.23.00     no       yes        no      yes       yes          yes     64
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* [TR]WRN_INT not connected */
4062306a36Sopenharmony_ci#define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1)
4162306a36Sopenharmony_ci /* Disable RX FIFO Global mask */
4262306a36Sopenharmony_ci#define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2)
4362306a36Sopenharmony_ci/* Enable EACEN and RRS bit in ctrl2 */
4462306a36Sopenharmony_ci#define FLEXCAN_QUIRK_ENABLE_EACEN_RRS  BIT(3)
4562306a36Sopenharmony_ci/* Disable non-correctable errors interrupt and freeze mode */
4662306a36Sopenharmony_ci#define FLEXCAN_QUIRK_DISABLE_MECR BIT(4)
4762306a36Sopenharmony_ci/* Use mailboxes (not FIFO) for RX path */
4862306a36Sopenharmony_ci#define FLEXCAN_QUIRK_USE_RX_MAILBOX BIT(5)
4962306a36Sopenharmony_ci/* No interrupt for error passive */
5062306a36Sopenharmony_ci#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6)
5162306a36Sopenharmony_ci/* default to BE register access */
5262306a36Sopenharmony_ci#define FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN BIT(7)
5362306a36Sopenharmony_ci/* Setup stop mode with GPR to support wakeup */
5462306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR BIT(8)
5562306a36Sopenharmony_ci/* Support CAN-FD mode */
5662306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SUPPORT_FD BIT(9)
5762306a36Sopenharmony_ci/* support memory detection and correction */
5862306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10)
5962306a36Sopenharmony_ci/* Setup stop mode with SCU firmware to support wakeup */
6062306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW BIT(11)
6162306a36Sopenharmony_ci/* Setup 3 separate interrupts, main, boff and err */
6262306a36Sopenharmony_ci#define FLEXCAN_QUIRK_NR_IRQ_3 BIT(12)
6362306a36Sopenharmony_ci/* Setup 16 mailboxes */
6462306a36Sopenharmony_ci#define FLEXCAN_QUIRK_NR_MB_16 BIT(13)
6562306a36Sopenharmony_ci/* Device supports RX via mailboxes */
6662306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX BIT(14)
6762306a36Sopenharmony_ci/* Device supports RTR reception via mailboxes */
6862306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR BIT(15)
6962306a36Sopenharmony_ci/* Device supports RX via FIFO */
7062306a36Sopenharmony_ci#define FLEXCAN_QUIRK_SUPPORT_RX_FIFO BIT(16)
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct flexcan_devtype_data {
7362306a36Sopenharmony_ci	u32 quirks;		/* quirks needed for different IP cores */
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistruct flexcan_stop_mode {
7762306a36Sopenharmony_ci	struct regmap *gpr;
7862306a36Sopenharmony_ci	u8 req_gpr;
7962306a36Sopenharmony_ci	u8 req_bit;
8062306a36Sopenharmony_ci};
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistruct flexcan_priv {
8362306a36Sopenharmony_ci	struct can_priv can;
8462306a36Sopenharmony_ci	struct can_rx_offload offload;
8562306a36Sopenharmony_ci	struct device *dev;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	struct flexcan_regs __iomem *regs;
8862306a36Sopenharmony_ci	struct flexcan_mb __iomem *tx_mb;
8962306a36Sopenharmony_ci	struct flexcan_mb __iomem *tx_mb_reserved;
9062306a36Sopenharmony_ci	u8 tx_mb_idx;
9162306a36Sopenharmony_ci	u8 mb_count;
9262306a36Sopenharmony_ci	u8 mb_size;
9362306a36Sopenharmony_ci	u8 clk_src;	/* clock source of CAN Protocol Engine */
9462306a36Sopenharmony_ci	u8 scu_idx;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	u64 rx_mask;
9762306a36Sopenharmony_ci	u64 tx_mask;
9862306a36Sopenharmony_ci	u32 reg_ctrl_default;
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	struct clk *clk_ipg;
10162306a36Sopenharmony_ci	struct clk *clk_per;
10262306a36Sopenharmony_ci	struct flexcan_devtype_data devtype_data;
10362306a36Sopenharmony_ci	struct regulator *reg_xceiver;
10462306a36Sopenharmony_ci	struct flexcan_stop_mode stm;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	int irq_boff;
10762306a36Sopenharmony_ci	int irq_err;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	/* IPC handle when setup stop mode by System Controller firmware(scfw) */
11062306a36Sopenharmony_ci	struct imx_sc_ipc *sc_ipc_handle;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	/* Read and Write APIs */
11362306a36Sopenharmony_ci	u32 (*read)(void __iomem *addr);
11462306a36Sopenharmony_ci	void (*write)(u32 val, void __iomem *addr);
11562306a36Sopenharmony_ci};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ciextern const struct ethtool_ops flexcan_ethtool_ops;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic inline bool
12062306a36Sopenharmony_ciflexcan_supports_rx_mailbox(const struct flexcan_priv *priv)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	const u32 quirks = priv->devtype_data.quirks;
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return quirks & FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline bool
12862306a36Sopenharmony_ciflexcan_supports_rx_mailbox_rtr(const struct flexcan_priv *priv)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	const u32 quirks = priv->devtype_data.quirks;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	return (quirks & (FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
13362306a36Sopenharmony_ci			  FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR)) ==
13462306a36Sopenharmony_ci		(FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX |
13562306a36Sopenharmony_ci		 FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR);
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistatic inline bool
13962306a36Sopenharmony_ciflexcan_supports_rx_fifo(const struct flexcan_priv *priv)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	const u32 quirks = priv->devtype_data.quirks;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	return quirks & FLEXCAN_QUIRK_SUPPORT_RX_FIFO;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic inline bool
14762306a36Sopenharmony_ciflexcan_active_rx_rtr(const struct flexcan_priv *priv)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	const u32 quirks = priv->devtype_data.quirks;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (quirks & FLEXCAN_QUIRK_USE_RX_MAILBOX) {
15262306a36Sopenharmony_ci		if (quirks & FLEXCAN_QUIRK_SUPPORT_RX_MAILBOX_RTR)
15362306a36Sopenharmony_ci			return true;
15462306a36Sopenharmony_ci	} else {
15562306a36Sopenharmony_ci		/*  RX-FIFO is always RTR capable */
15662306a36Sopenharmony_ci		return true;
15762306a36Sopenharmony_ci	}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	return false;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci#endif /* _FLEXCAN_H */
164