18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* Renesas R-Car CAN FD device driver 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2015 Renesas Electronics Corp. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/* The R-Car CAN FD controller can operate in either one of the below two modes 88c2ecf20Sopenharmony_ci * - CAN FD only mode 98c2ecf20Sopenharmony_ci * - Classical CAN (CAN 2.0) only mode 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This driver puts the controller in CAN FD only mode by default. In this 128c2ecf20Sopenharmony_ci * mode, the controller acts as a CAN FD node that can also interoperate with 138c2ecf20Sopenharmony_ci * CAN 2.0 nodes. 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * To switch the controller to Classical CAN (CAN 2.0) only mode, add 168c2ecf20Sopenharmony_ci * "renesas,no-can-fd" optional property to the device tree node. A h/w reset is 178c2ecf20Sopenharmony_ci * also required to switch modes. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * Note: The h/w manual register naming convention is clumsy and not acceptable 208c2ecf20Sopenharmony_ci * to use as it is in the driver. However, those names are added as comments 218c2ecf20Sopenharmony_ci * wherever it is modified to a readable name. 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include <linux/module.h> 258c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 268c2ecf20Sopenharmony_ci#include <linux/kernel.h> 278c2ecf20Sopenharmony_ci#include <linux/types.h> 288c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 298c2ecf20Sopenharmony_ci#include <linux/errno.h> 308c2ecf20Sopenharmony_ci#include <linux/netdevice.h> 318c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 328c2ecf20Sopenharmony_ci#include <linux/can/led.h> 338c2ecf20Sopenharmony_ci#include <linux/can/dev.h> 348c2ecf20Sopenharmony_ci#include <linux/clk.h> 358c2ecf20Sopenharmony_ci#include <linux/of.h> 368c2ecf20Sopenharmony_ci#include <linux/of_device.h> 378c2ecf20Sopenharmony_ci#include <linux/bitmap.h> 388c2ecf20Sopenharmony_ci#include <linux/bitops.h> 398c2ecf20Sopenharmony_ci#include <linux/iopoll.h> 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define RCANFD_DRV_NAME "rcar_canfd" 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* Global register bits */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* RSCFDnCFDGRMCFG */ 468c2ecf20Sopenharmony_ci#define RCANFD_GRMCFG_RCMC BIT(0) 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci/* RSCFDnCFDGCFG / RSCFDnGCFG */ 498c2ecf20Sopenharmony_ci#define RCANFD_GCFG_EEFE BIT(6) 508c2ecf20Sopenharmony_ci#define RCANFD_GCFG_CMPOC BIT(5) /* CAN FD only */ 518c2ecf20Sopenharmony_ci#define RCANFD_GCFG_DCS BIT(4) 528c2ecf20Sopenharmony_ci#define RCANFD_GCFG_DCE BIT(1) 538c2ecf20Sopenharmony_ci#define RCANFD_GCFG_TPRI BIT(0) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* RSCFDnCFDGCTR / RSCFDnGCTR */ 568c2ecf20Sopenharmony_ci#define RCANFD_GCTR_TSRST BIT(16) 578c2ecf20Sopenharmony_ci#define RCANFD_GCTR_CFMPOFIE BIT(11) /* CAN FD only */ 588c2ecf20Sopenharmony_ci#define RCANFD_GCTR_THLEIE BIT(10) 598c2ecf20Sopenharmony_ci#define RCANFD_GCTR_MEIE BIT(9) 608c2ecf20Sopenharmony_ci#define RCANFD_GCTR_DEIE BIT(8) 618c2ecf20Sopenharmony_ci#define RCANFD_GCTR_GSLPR BIT(2) 628c2ecf20Sopenharmony_ci#define RCANFD_GCTR_GMDC_MASK (0x3) 638c2ecf20Sopenharmony_ci#define RCANFD_GCTR_GMDC_GOPM (0x0) 648c2ecf20Sopenharmony_ci#define RCANFD_GCTR_GMDC_GRESET (0x1) 658c2ecf20Sopenharmony_ci#define RCANFD_GCTR_GMDC_GTEST (0x2) 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* RSCFDnCFDGSTS / RSCFDnGSTS */ 688c2ecf20Sopenharmony_ci#define RCANFD_GSTS_GRAMINIT BIT(3) 698c2ecf20Sopenharmony_ci#define RCANFD_GSTS_GSLPSTS BIT(2) 708c2ecf20Sopenharmony_ci#define RCANFD_GSTS_GHLTSTS BIT(1) 718c2ecf20Sopenharmony_ci#define RCANFD_GSTS_GRSTSTS BIT(0) 728c2ecf20Sopenharmony_ci/* Non-operational status */ 738c2ecf20Sopenharmony_ci#define RCANFD_GSTS_GNOPM (BIT(0) | BIT(1) | BIT(2) | BIT(3)) 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci/* RSCFDnCFDGERFL / RSCFDnGERFL */ 768c2ecf20Sopenharmony_ci#define RCANFD_GERFL_EEF1 BIT(17) 778c2ecf20Sopenharmony_ci#define RCANFD_GERFL_EEF0 BIT(16) 788c2ecf20Sopenharmony_ci#define RCANFD_GERFL_CMPOF BIT(3) /* CAN FD only */ 798c2ecf20Sopenharmony_ci#define RCANFD_GERFL_THLES BIT(2) 808c2ecf20Sopenharmony_ci#define RCANFD_GERFL_MES BIT(1) 818c2ecf20Sopenharmony_ci#define RCANFD_GERFL_DEF BIT(0) 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define RCANFD_GERFL_ERR(gpriv, x) ((x) & (RCANFD_GERFL_EEF1 |\ 848c2ecf20Sopenharmony_ci RCANFD_GERFL_EEF0 | RCANFD_GERFL_MES |\ 858c2ecf20Sopenharmony_ci (gpriv->fdmode ?\ 868c2ecf20Sopenharmony_ci RCANFD_GERFL_CMPOF : 0))) 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* AFL Rx rules registers */ 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */ 918c2ecf20Sopenharmony_ci#define RCANFD_GAFLCFG_SETRNC(n, x) (((x) & 0xff) << (24 - n * 8)) 928c2ecf20Sopenharmony_ci#define RCANFD_GAFLCFG_GETRNC(n, x) (((x) >> (24 - n * 8)) & 0xff) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ 958c2ecf20Sopenharmony_ci#define RCANFD_GAFLECTR_AFLDAE BIT(8) 968c2ecf20Sopenharmony_ci#define RCANFD_GAFLECTR_AFLPN(x) ((x) & 0x1f) 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ 998c2ecf20Sopenharmony_ci#define RCANFD_GAFLID_GAFLLB BIT(29) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLP1_j / RSCFDnGAFLP1_j */ 1028c2ecf20Sopenharmony_ci#define RCANFD_GAFLP1_GAFLFDP(x) (1 << (x)) 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* Channel register bits */ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* RSCFDnCmCFG - Classical CAN only */ 1078c2ecf20Sopenharmony_ci#define RCANFD_CFG_SJW(x) (((x) & 0x3) << 24) 1088c2ecf20Sopenharmony_ci#define RCANFD_CFG_TSEG2(x) (((x) & 0x7) << 20) 1098c2ecf20Sopenharmony_ci#define RCANFD_CFG_TSEG1(x) (((x) & 0xf) << 16) 1108c2ecf20Sopenharmony_ci#define RCANFD_CFG_BRP(x) (((x) & 0x3ff) << 0) 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* RSCFDnCFDCmNCFG - CAN FD only */ 1138c2ecf20Sopenharmony_ci#define RCANFD_NCFG_NTSEG2(x) (((x) & 0x1f) << 24) 1148c2ecf20Sopenharmony_ci#define RCANFD_NCFG_NTSEG1(x) (((x) & 0x7f) << 16) 1158c2ecf20Sopenharmony_ci#define RCANFD_NCFG_NSJW(x) (((x) & 0x1f) << 11) 1168c2ecf20Sopenharmony_ci#define RCANFD_NCFG_NBRP(x) (((x) & 0x3ff) << 0) 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* RSCFDnCFDCmCTR / RSCFDnCmCTR */ 1198c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CTME BIT(24) 1208c2ecf20Sopenharmony_ci#define RCANFD_CCTR_ERRD BIT(23) 1218c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BOM_MASK (0x3 << 21) 1228c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BOM_ISO (0x0 << 21) 1238c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BOM_BENTRY (0x1 << 21) 1248c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BOM_BEND (0x2 << 21) 1258c2ecf20Sopenharmony_ci#define RCANFD_CCTR_TDCVFIE BIT(19) 1268c2ecf20Sopenharmony_ci#define RCANFD_CCTR_SOCOIE BIT(18) 1278c2ecf20Sopenharmony_ci#define RCANFD_CCTR_EOCOIE BIT(17) 1288c2ecf20Sopenharmony_ci#define RCANFD_CCTR_TAIE BIT(16) 1298c2ecf20Sopenharmony_ci#define RCANFD_CCTR_ALIE BIT(15) 1308c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BLIE BIT(14) 1318c2ecf20Sopenharmony_ci#define RCANFD_CCTR_OLIE BIT(13) 1328c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BORIE BIT(12) 1338c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BOEIE BIT(11) 1348c2ecf20Sopenharmony_ci#define RCANFD_CCTR_EPIE BIT(10) 1358c2ecf20Sopenharmony_ci#define RCANFD_CCTR_EWIE BIT(9) 1368c2ecf20Sopenharmony_ci#define RCANFD_CCTR_BEIE BIT(8) 1378c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CSLPR BIT(2) 1388c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CHMDC_MASK (0x3) 1398c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CHDMC_COPM (0x0) 1408c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CHDMC_CRESET (0x1) 1418c2ecf20Sopenharmony_ci#define RCANFD_CCTR_CHDMC_CHLT (0x2) 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci/* RSCFDnCFDCmSTS / RSCFDnCmSTS */ 1448c2ecf20Sopenharmony_ci#define RCANFD_CSTS_COMSTS BIT(7) 1458c2ecf20Sopenharmony_ci#define RCANFD_CSTS_RECSTS BIT(6) 1468c2ecf20Sopenharmony_ci#define RCANFD_CSTS_TRMSTS BIT(5) 1478c2ecf20Sopenharmony_ci#define RCANFD_CSTS_BOSTS BIT(4) 1488c2ecf20Sopenharmony_ci#define RCANFD_CSTS_EPSTS BIT(3) 1498c2ecf20Sopenharmony_ci#define RCANFD_CSTS_SLPSTS BIT(2) 1508c2ecf20Sopenharmony_ci#define RCANFD_CSTS_HLTSTS BIT(1) 1518c2ecf20Sopenharmony_ci#define RCANFD_CSTS_CRSTSTS BIT(0) 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci#define RCANFD_CSTS_TECCNT(x) (((x) >> 24) & 0xff) 1548c2ecf20Sopenharmony_ci#define RCANFD_CSTS_RECCNT(x) (((x) >> 16) & 0xff) 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/* RSCFDnCFDCmERFL / RSCFDnCmERFL */ 1578c2ecf20Sopenharmony_ci#define RCANFD_CERFL_ADERR BIT(14) 1588c2ecf20Sopenharmony_ci#define RCANFD_CERFL_B0ERR BIT(13) 1598c2ecf20Sopenharmony_ci#define RCANFD_CERFL_B1ERR BIT(12) 1608c2ecf20Sopenharmony_ci#define RCANFD_CERFL_CERR BIT(11) 1618c2ecf20Sopenharmony_ci#define RCANFD_CERFL_AERR BIT(10) 1628c2ecf20Sopenharmony_ci#define RCANFD_CERFL_FERR BIT(9) 1638c2ecf20Sopenharmony_ci#define RCANFD_CERFL_SERR BIT(8) 1648c2ecf20Sopenharmony_ci#define RCANFD_CERFL_ALF BIT(7) 1658c2ecf20Sopenharmony_ci#define RCANFD_CERFL_BLF BIT(6) 1668c2ecf20Sopenharmony_ci#define RCANFD_CERFL_OVLF BIT(5) 1678c2ecf20Sopenharmony_ci#define RCANFD_CERFL_BORF BIT(4) 1688c2ecf20Sopenharmony_ci#define RCANFD_CERFL_BOEF BIT(3) 1698c2ecf20Sopenharmony_ci#define RCANFD_CERFL_EPF BIT(2) 1708c2ecf20Sopenharmony_ci#define RCANFD_CERFL_EWF BIT(1) 1718c2ecf20Sopenharmony_ci#define RCANFD_CERFL_BEF BIT(0) 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci#define RCANFD_CERFL_ERR(x) ((x) & (0x7fff)) /* above bits 14:0 */ 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* RSCFDnCFDCmDCFG */ 1768c2ecf20Sopenharmony_ci#define RCANFD_DCFG_DSJW(x) (((x) & 0x7) << 24) 1778c2ecf20Sopenharmony_ci#define RCANFD_DCFG_DTSEG2(x) (((x) & 0x7) << 20) 1788c2ecf20Sopenharmony_ci#define RCANFD_DCFG_DTSEG1(x) (((x) & 0xf) << 16) 1798c2ecf20Sopenharmony_ci#define RCANFD_DCFG_DBRP(x) (((x) & 0xff) << 0) 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci/* RSCFDnCFDCmFDCFG */ 1828c2ecf20Sopenharmony_ci#define RCANFD_FDCFG_TDCE BIT(9) 1838c2ecf20Sopenharmony_ci#define RCANFD_FDCFG_TDCOC BIT(8) 1848c2ecf20Sopenharmony_ci#define RCANFD_FDCFG_TDCO(x) (((x) & 0x7f) >> 16) 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* RSCFDnCFDRFCCx */ 1878c2ecf20Sopenharmony_ci#define RCANFD_RFCC_RFIM BIT(12) 1888c2ecf20Sopenharmony_ci#define RCANFD_RFCC_RFDC(x) (((x) & 0x7) << 8) 1898c2ecf20Sopenharmony_ci#define RCANFD_RFCC_RFPLS(x) (((x) & 0x7) << 4) 1908c2ecf20Sopenharmony_ci#define RCANFD_RFCC_RFIE BIT(1) 1918c2ecf20Sopenharmony_ci#define RCANFD_RFCC_RFE BIT(0) 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci/* RSCFDnCFDRFSTSx */ 1948c2ecf20Sopenharmony_ci#define RCANFD_RFSTS_RFIF BIT(3) 1958c2ecf20Sopenharmony_ci#define RCANFD_RFSTS_RFMLT BIT(2) 1968c2ecf20Sopenharmony_ci#define RCANFD_RFSTS_RFFLL BIT(1) 1978c2ecf20Sopenharmony_ci#define RCANFD_RFSTS_RFEMP BIT(0) 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci/* RSCFDnCFDRFIDx */ 2008c2ecf20Sopenharmony_ci#define RCANFD_RFID_RFIDE BIT(31) 2018c2ecf20Sopenharmony_ci#define RCANFD_RFID_RFRTR BIT(30) 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci/* RSCFDnCFDRFPTRx */ 2048c2ecf20Sopenharmony_ci#define RCANFD_RFPTR_RFDLC(x) (((x) >> 28) & 0xf) 2058c2ecf20Sopenharmony_ci#define RCANFD_RFPTR_RFPTR(x) (((x) >> 16) & 0xfff) 2068c2ecf20Sopenharmony_ci#define RCANFD_RFPTR_RFTS(x) (((x) >> 0) & 0xffff) 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci/* RSCFDnCFDRFFDSTSx */ 2098c2ecf20Sopenharmony_ci#define RCANFD_RFFDSTS_RFFDF BIT(2) 2108c2ecf20Sopenharmony_ci#define RCANFD_RFFDSTS_RFBRS BIT(1) 2118c2ecf20Sopenharmony_ci#define RCANFD_RFFDSTS_RFESI BIT(0) 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/* Common FIFO bits */ 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci/* RSCFDnCFDCFCCk */ 2168c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFTML(x) (((x) & 0xf) << 20) 2178c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFM(x) (((x) & 0x3) << 16) 2188c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFIM BIT(12) 2198c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFDC(x) (((x) & 0x7) << 8) 2208c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFPLS(x) (((x) & 0x7) << 4) 2218c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFTXIE BIT(2) 2228c2ecf20Sopenharmony_ci#define RCANFD_CFCC_CFE BIT(0) 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* RSCFDnCFDCFSTSk */ 2258c2ecf20Sopenharmony_ci#define RCANFD_CFSTS_CFMC(x) (((x) >> 8) & 0xff) 2268c2ecf20Sopenharmony_ci#define RCANFD_CFSTS_CFTXIF BIT(4) 2278c2ecf20Sopenharmony_ci#define RCANFD_CFSTS_CFMLT BIT(2) 2288c2ecf20Sopenharmony_ci#define RCANFD_CFSTS_CFFLL BIT(1) 2298c2ecf20Sopenharmony_ci#define RCANFD_CFSTS_CFEMP BIT(0) 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci/* RSCFDnCFDCFIDk */ 2328c2ecf20Sopenharmony_ci#define RCANFD_CFID_CFIDE BIT(31) 2338c2ecf20Sopenharmony_ci#define RCANFD_CFID_CFRTR BIT(30) 2348c2ecf20Sopenharmony_ci#define RCANFD_CFID_CFID_MASK(x) ((x) & 0x1fffffff) 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci/* RSCFDnCFDCFPTRk */ 2378c2ecf20Sopenharmony_ci#define RCANFD_CFPTR_CFDLC(x) (((x) & 0xf) << 28) 2388c2ecf20Sopenharmony_ci#define RCANFD_CFPTR_CFPTR(x) (((x) & 0xfff) << 16) 2398c2ecf20Sopenharmony_ci#define RCANFD_CFPTR_CFTS(x) (((x) & 0xff) << 0) 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/* RSCFDnCFDCFFDCSTSk */ 2428c2ecf20Sopenharmony_ci#define RCANFD_CFFDCSTS_CFFDF BIT(2) 2438c2ecf20Sopenharmony_ci#define RCANFD_CFFDCSTS_CFBRS BIT(1) 2448c2ecf20Sopenharmony_ci#define RCANFD_CFFDCSTS_CFESI BIT(0) 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/* This controller supports either Classical CAN only mode or CAN FD only mode. 2478c2ecf20Sopenharmony_ci * These modes are supported in two separate set of register maps & names. 2488c2ecf20Sopenharmony_ci * However, some of the register offsets are common for both modes. Those 2498c2ecf20Sopenharmony_ci * offsets are listed below as Common registers. 2508c2ecf20Sopenharmony_ci * 2518c2ecf20Sopenharmony_ci * The CAN FD only mode specific registers & Classical CAN only mode specific 2528c2ecf20Sopenharmony_ci * registers are listed separately. Their register names starts with 2538c2ecf20Sopenharmony_ci * RCANFD_F_xxx & RCANFD_C_xxx respectively. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* Common registers */ 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci/* RSCFDnCFDCmNCFG / RSCFDnCmCFG */ 2598c2ecf20Sopenharmony_ci#define RCANFD_CCFG(m) (0x0000 + (0x10 * (m))) 2608c2ecf20Sopenharmony_ci/* RSCFDnCFDCmCTR / RSCFDnCmCTR */ 2618c2ecf20Sopenharmony_ci#define RCANFD_CCTR(m) (0x0004 + (0x10 * (m))) 2628c2ecf20Sopenharmony_ci/* RSCFDnCFDCmSTS / RSCFDnCmSTS */ 2638c2ecf20Sopenharmony_ci#define RCANFD_CSTS(m) (0x0008 + (0x10 * (m))) 2648c2ecf20Sopenharmony_ci/* RSCFDnCFDCmERFL / RSCFDnCmERFL */ 2658c2ecf20Sopenharmony_ci#define RCANFD_CERFL(m) (0x000C + (0x10 * (m))) 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci/* RSCFDnCFDGCFG / RSCFDnGCFG */ 2688c2ecf20Sopenharmony_ci#define RCANFD_GCFG (0x0084) 2698c2ecf20Sopenharmony_ci/* RSCFDnCFDGCTR / RSCFDnGCTR */ 2708c2ecf20Sopenharmony_ci#define RCANFD_GCTR (0x0088) 2718c2ecf20Sopenharmony_ci/* RSCFDnCFDGCTS / RSCFDnGCTS */ 2728c2ecf20Sopenharmony_ci#define RCANFD_GSTS (0x008c) 2738c2ecf20Sopenharmony_ci/* RSCFDnCFDGERFL / RSCFDnGERFL */ 2748c2ecf20Sopenharmony_ci#define RCANFD_GERFL (0x0090) 2758c2ecf20Sopenharmony_ci/* RSCFDnCFDGTSC / RSCFDnGTSC */ 2768c2ecf20Sopenharmony_ci#define RCANFD_GTSC (0x0094) 2778c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLECTR / RSCFDnGAFLECTR */ 2788c2ecf20Sopenharmony_ci#define RCANFD_GAFLECTR (0x0098) 2798c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLCFG0 / RSCFDnGAFLCFG0 */ 2808c2ecf20Sopenharmony_ci#define RCANFD_GAFLCFG0 (0x009c) 2818c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLCFG1 / RSCFDnGAFLCFG1 */ 2828c2ecf20Sopenharmony_ci#define RCANFD_GAFLCFG1 (0x00a0) 2838c2ecf20Sopenharmony_ci/* RSCFDnCFDRMNB / RSCFDnRMNB */ 2848c2ecf20Sopenharmony_ci#define RCANFD_RMNB (0x00a4) 2858c2ecf20Sopenharmony_ci/* RSCFDnCFDRMND / RSCFDnRMND */ 2868c2ecf20Sopenharmony_ci#define RCANFD_RMND(y) (0x00a8 + (0x04 * (y))) 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci/* RSCFDnCFDRFCCx / RSCFDnRFCCx */ 2898c2ecf20Sopenharmony_ci#define RCANFD_RFCC(x) (0x00b8 + (0x04 * (x))) 2908c2ecf20Sopenharmony_ci/* RSCFDnCFDRFSTSx / RSCFDnRFSTSx */ 2918c2ecf20Sopenharmony_ci#define RCANFD_RFSTS(x) (0x00d8 + (0x04 * (x))) 2928c2ecf20Sopenharmony_ci/* RSCFDnCFDRFPCTRx / RSCFDnRFPCTRx */ 2938c2ecf20Sopenharmony_ci#define RCANFD_RFPCTR(x) (0x00f8 + (0x04 * (x))) 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci/* Common FIFO Control registers */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* RSCFDnCFDCFCCx / RSCFDnCFCCx */ 2988c2ecf20Sopenharmony_ci#define RCANFD_CFCC(ch, idx) (0x0118 + (0x0c * (ch)) + \ 2998c2ecf20Sopenharmony_ci (0x04 * (idx))) 3008c2ecf20Sopenharmony_ci/* RSCFDnCFDCFSTSx / RSCFDnCFSTSx */ 3018c2ecf20Sopenharmony_ci#define RCANFD_CFSTS(ch, idx) (0x0178 + (0x0c * (ch)) + \ 3028c2ecf20Sopenharmony_ci (0x04 * (idx))) 3038c2ecf20Sopenharmony_ci/* RSCFDnCFDCFPCTRx / RSCFDnCFPCTRx */ 3048c2ecf20Sopenharmony_ci#define RCANFD_CFPCTR(ch, idx) (0x01d8 + (0x0c * (ch)) + \ 3058c2ecf20Sopenharmony_ci (0x04 * (idx))) 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci/* RSCFDnCFDFESTS / RSCFDnFESTS */ 3088c2ecf20Sopenharmony_ci#define RCANFD_FESTS (0x0238) 3098c2ecf20Sopenharmony_ci/* RSCFDnCFDFFSTS / RSCFDnFFSTS */ 3108c2ecf20Sopenharmony_ci#define RCANFD_FFSTS (0x023c) 3118c2ecf20Sopenharmony_ci/* RSCFDnCFDFMSTS / RSCFDnFMSTS */ 3128c2ecf20Sopenharmony_ci#define RCANFD_FMSTS (0x0240) 3138c2ecf20Sopenharmony_ci/* RSCFDnCFDRFISTS / RSCFDnRFISTS */ 3148c2ecf20Sopenharmony_ci#define RCANFD_RFISTS (0x0244) 3158c2ecf20Sopenharmony_ci/* RSCFDnCFDCFRISTS / RSCFDnCFRISTS */ 3168c2ecf20Sopenharmony_ci#define RCANFD_CFRISTS (0x0248) 3178c2ecf20Sopenharmony_ci/* RSCFDnCFDCFTISTS / RSCFDnCFTISTS */ 3188c2ecf20Sopenharmony_ci#define RCANFD_CFTISTS (0x024c) 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci/* RSCFDnCFDTMCp / RSCFDnTMCp */ 3218c2ecf20Sopenharmony_ci#define RCANFD_TMC(p) (0x0250 + (0x01 * (p))) 3228c2ecf20Sopenharmony_ci/* RSCFDnCFDTMSTSp / RSCFDnTMSTSp */ 3238c2ecf20Sopenharmony_ci#define RCANFD_TMSTS(p) (0x02d0 + (0x01 * (p))) 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci/* RSCFDnCFDTMTRSTSp / RSCFDnTMTRSTSp */ 3268c2ecf20Sopenharmony_ci#define RCANFD_TMTRSTS(y) (0x0350 + (0x04 * (y))) 3278c2ecf20Sopenharmony_ci/* RSCFDnCFDTMTARSTSp / RSCFDnTMTARSTSp */ 3288c2ecf20Sopenharmony_ci#define RCANFD_TMTARSTS(y) (0x0360 + (0x04 * (y))) 3298c2ecf20Sopenharmony_ci/* RSCFDnCFDTMTCSTSp / RSCFDnTMTCSTSp */ 3308c2ecf20Sopenharmony_ci#define RCANFD_TMTCSTS(y) (0x0370 + (0x04 * (y))) 3318c2ecf20Sopenharmony_ci/* RSCFDnCFDTMTASTSp / RSCFDnTMTASTSp */ 3328c2ecf20Sopenharmony_ci#define RCANFD_TMTASTS(y) (0x0380 + (0x04 * (y))) 3338c2ecf20Sopenharmony_ci/* RSCFDnCFDTMIECy / RSCFDnTMIECy */ 3348c2ecf20Sopenharmony_ci#define RCANFD_TMIEC(y) (0x0390 + (0x04 * (y))) 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci/* RSCFDnCFDTXQCCm / RSCFDnTXQCCm */ 3378c2ecf20Sopenharmony_ci#define RCANFD_TXQCC(m) (0x03a0 + (0x04 * (m))) 3388c2ecf20Sopenharmony_ci/* RSCFDnCFDTXQSTSm / RSCFDnTXQSTSm */ 3398c2ecf20Sopenharmony_ci#define RCANFD_TXQSTS(m) (0x03c0 + (0x04 * (m))) 3408c2ecf20Sopenharmony_ci/* RSCFDnCFDTXQPCTRm / RSCFDnTXQPCTRm */ 3418c2ecf20Sopenharmony_ci#define RCANFD_TXQPCTR(m) (0x03e0 + (0x04 * (m))) 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci/* RSCFDnCFDTHLCCm / RSCFDnTHLCCm */ 3448c2ecf20Sopenharmony_ci#define RCANFD_THLCC(m) (0x0400 + (0x04 * (m))) 3458c2ecf20Sopenharmony_ci/* RSCFDnCFDTHLSTSm / RSCFDnTHLSTSm */ 3468c2ecf20Sopenharmony_ci#define RCANFD_THLSTS(m) (0x0420 + (0x04 * (m))) 3478c2ecf20Sopenharmony_ci/* RSCFDnCFDTHLPCTRm / RSCFDnTHLPCTRm */ 3488c2ecf20Sopenharmony_ci#define RCANFD_THLPCTR(m) (0x0440 + (0x04 * (m))) 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci/* RSCFDnCFDGTINTSTS0 / RSCFDnGTINTSTS0 */ 3518c2ecf20Sopenharmony_ci#define RCANFD_GTINTSTS0 (0x0460) 3528c2ecf20Sopenharmony_ci/* RSCFDnCFDGTINTSTS1 / RSCFDnGTINTSTS1 */ 3538c2ecf20Sopenharmony_ci#define RCANFD_GTINTSTS1 (0x0464) 3548c2ecf20Sopenharmony_ci/* RSCFDnCFDGTSTCFG / RSCFDnGTSTCFG */ 3558c2ecf20Sopenharmony_ci#define RCANFD_GTSTCFG (0x0468) 3568c2ecf20Sopenharmony_ci/* RSCFDnCFDGTSTCTR / RSCFDnGTSTCTR */ 3578c2ecf20Sopenharmony_ci#define RCANFD_GTSTCTR (0x046c) 3588c2ecf20Sopenharmony_ci/* RSCFDnCFDGLOCKK / RSCFDnGLOCKK */ 3598c2ecf20Sopenharmony_ci#define RCANFD_GLOCKK (0x047c) 3608c2ecf20Sopenharmony_ci/* RSCFDnCFDGRMCFG */ 3618c2ecf20Sopenharmony_ci#define RCANFD_GRMCFG (0x04fc) 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLIDj / RSCFDnGAFLIDj */ 3648c2ecf20Sopenharmony_ci#define RCANFD_GAFLID(offset, j) ((offset) + (0x10 * (j))) 3658c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLMj / RSCFDnGAFLMj */ 3668c2ecf20Sopenharmony_ci#define RCANFD_GAFLM(offset, j) ((offset) + 0x04 + (0x10 * (j))) 3678c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLP0j / RSCFDnGAFLP0j */ 3688c2ecf20Sopenharmony_ci#define RCANFD_GAFLP0(offset, j) ((offset) + 0x08 + (0x10 * (j))) 3698c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLP1j / RSCFDnGAFLP1j */ 3708c2ecf20Sopenharmony_ci#define RCANFD_GAFLP1(offset, j) ((offset) + 0x0c + (0x10 * (j))) 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci/* Classical CAN only mode register map */ 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci/* RSCFDnGAFLXXXj offset */ 3758c2ecf20Sopenharmony_ci#define RCANFD_C_GAFL_OFFSET (0x0500) 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci/* RSCFDnRMXXXq -> RCANFD_C_RMXXX(q) */ 3788c2ecf20Sopenharmony_ci#define RCANFD_C_RMID(q) (0x0600 + (0x10 * (q))) 3798c2ecf20Sopenharmony_ci#define RCANFD_C_RMPTR(q) (0x0604 + (0x10 * (q))) 3808c2ecf20Sopenharmony_ci#define RCANFD_C_RMDF0(q) (0x0608 + (0x10 * (q))) 3818c2ecf20Sopenharmony_ci#define RCANFD_C_RMDF1(q) (0x060c + (0x10 * (q))) 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci/* RSCFDnRFXXx -> RCANFD_C_RFXX(x) */ 3848c2ecf20Sopenharmony_ci#define RCANFD_C_RFOFFSET (0x0e00) 3858c2ecf20Sopenharmony_ci#define RCANFD_C_RFID(x) (RCANFD_C_RFOFFSET + (0x10 * (x))) 3868c2ecf20Sopenharmony_ci#define RCANFD_C_RFPTR(x) (RCANFD_C_RFOFFSET + 0x04 + \ 3878c2ecf20Sopenharmony_ci (0x10 * (x))) 3888c2ecf20Sopenharmony_ci#define RCANFD_C_RFDF(x, df) (RCANFD_C_RFOFFSET + 0x08 + \ 3898c2ecf20Sopenharmony_ci (0x10 * (x)) + (0x04 * (df))) 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci/* RSCFDnCFXXk -> RCANFD_C_CFXX(ch, k) */ 3928c2ecf20Sopenharmony_ci#define RCANFD_C_CFOFFSET (0x0e80) 3938c2ecf20Sopenharmony_ci#define RCANFD_C_CFID(ch, idx) (RCANFD_C_CFOFFSET + (0x30 * (ch)) + \ 3948c2ecf20Sopenharmony_ci (0x10 * (idx))) 3958c2ecf20Sopenharmony_ci#define RCANFD_C_CFPTR(ch, idx) (RCANFD_C_CFOFFSET + 0x04 + \ 3968c2ecf20Sopenharmony_ci (0x30 * (ch)) + (0x10 * (idx))) 3978c2ecf20Sopenharmony_ci#define RCANFD_C_CFDF(ch, idx, df) (RCANFD_C_CFOFFSET + 0x08 + \ 3988c2ecf20Sopenharmony_ci (0x30 * (ch)) + (0x10 * (idx)) + \ 3998c2ecf20Sopenharmony_ci (0x04 * (df))) 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci/* RSCFDnTMXXp -> RCANFD_C_TMXX(p) */ 4028c2ecf20Sopenharmony_ci#define RCANFD_C_TMID(p) (0x1000 + (0x10 * (p))) 4038c2ecf20Sopenharmony_ci#define RCANFD_C_TMPTR(p) (0x1004 + (0x10 * (p))) 4048c2ecf20Sopenharmony_ci#define RCANFD_C_TMDF0(p) (0x1008 + (0x10 * (p))) 4058c2ecf20Sopenharmony_ci#define RCANFD_C_TMDF1(p) (0x100c + (0x10 * (p))) 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci/* RSCFDnTHLACCm */ 4088c2ecf20Sopenharmony_ci#define RCANFD_C_THLACC(m) (0x1800 + (0x04 * (m))) 4098c2ecf20Sopenharmony_ci/* RSCFDnRPGACCr */ 4108c2ecf20Sopenharmony_ci#define RCANFD_C_RPGACC(r) (0x1900 + (0x04 * (r))) 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci/* CAN FD mode specific register map */ 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci/* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */ 4158c2ecf20Sopenharmony_ci#define RCANFD_F_DCFG(m) (0x0500 + (0x20 * (m))) 4168c2ecf20Sopenharmony_ci#define RCANFD_F_CFDCFG(m) (0x0504 + (0x20 * (m))) 4178c2ecf20Sopenharmony_ci#define RCANFD_F_CFDCTR(m) (0x0508 + (0x20 * (m))) 4188c2ecf20Sopenharmony_ci#define RCANFD_F_CFDSTS(m) (0x050c + (0x20 * (m))) 4198c2ecf20Sopenharmony_ci#define RCANFD_F_CFDCRC(m) (0x0510 + (0x20 * (m))) 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci/* RSCFDnCFDGAFLXXXj offset */ 4228c2ecf20Sopenharmony_ci#define RCANFD_F_GAFL_OFFSET (0x1000) 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/* RSCFDnCFDRMXXXq -> RCANFD_F_RMXXX(q) */ 4258c2ecf20Sopenharmony_ci#define RCANFD_F_RMID(q) (0x2000 + (0x20 * (q))) 4268c2ecf20Sopenharmony_ci#define RCANFD_F_RMPTR(q) (0x2004 + (0x20 * (q))) 4278c2ecf20Sopenharmony_ci#define RCANFD_F_RMFDSTS(q) (0x2008 + (0x20 * (q))) 4288c2ecf20Sopenharmony_ci#define RCANFD_F_RMDF(q, b) (0x200c + (0x04 * (b)) + (0x20 * (q))) 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci/* RSCFDnCFDRFXXx -> RCANFD_F_RFXX(x) */ 4318c2ecf20Sopenharmony_ci#define RCANFD_F_RFOFFSET (0x3000) 4328c2ecf20Sopenharmony_ci#define RCANFD_F_RFID(x) (RCANFD_F_RFOFFSET + (0x80 * (x))) 4338c2ecf20Sopenharmony_ci#define RCANFD_F_RFPTR(x) (RCANFD_F_RFOFFSET + 0x04 + \ 4348c2ecf20Sopenharmony_ci (0x80 * (x))) 4358c2ecf20Sopenharmony_ci#define RCANFD_F_RFFDSTS(x) (RCANFD_F_RFOFFSET + 0x08 + \ 4368c2ecf20Sopenharmony_ci (0x80 * (x))) 4378c2ecf20Sopenharmony_ci#define RCANFD_F_RFDF(x, df) (RCANFD_F_RFOFFSET + 0x0c + \ 4388c2ecf20Sopenharmony_ci (0x80 * (x)) + (0x04 * (df))) 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci/* RSCFDnCFDCFXXk -> RCANFD_F_CFXX(ch, k) */ 4418c2ecf20Sopenharmony_ci#define RCANFD_F_CFOFFSET (0x3400) 4428c2ecf20Sopenharmony_ci#define RCANFD_F_CFID(ch, idx) (RCANFD_F_CFOFFSET + (0x180 * (ch)) + \ 4438c2ecf20Sopenharmony_ci (0x80 * (idx))) 4448c2ecf20Sopenharmony_ci#define RCANFD_F_CFPTR(ch, idx) (RCANFD_F_CFOFFSET + 0x04 + \ 4458c2ecf20Sopenharmony_ci (0x180 * (ch)) + (0x80 * (idx))) 4468c2ecf20Sopenharmony_ci#define RCANFD_F_CFFDCSTS(ch, idx) (RCANFD_F_CFOFFSET + 0x08 + \ 4478c2ecf20Sopenharmony_ci (0x180 * (ch)) + (0x80 * (idx))) 4488c2ecf20Sopenharmony_ci#define RCANFD_F_CFDF(ch, idx, df) (RCANFD_F_CFOFFSET + 0x0c + \ 4498c2ecf20Sopenharmony_ci (0x180 * (ch)) + (0x80 * (idx)) + \ 4508c2ecf20Sopenharmony_ci (0x04 * (df))) 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci/* RSCFDnCFDTMXXp -> RCANFD_F_TMXX(p) */ 4538c2ecf20Sopenharmony_ci#define RCANFD_F_TMID(p) (0x4000 + (0x20 * (p))) 4548c2ecf20Sopenharmony_ci#define RCANFD_F_TMPTR(p) (0x4004 + (0x20 * (p))) 4558c2ecf20Sopenharmony_ci#define RCANFD_F_TMFDCTR(p) (0x4008 + (0x20 * (p))) 4568c2ecf20Sopenharmony_ci#define RCANFD_F_TMDF(p, b) (0x400c + (0x20 * (p)) + (0x04 * (b))) 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci/* RSCFDnCFDTHLACCm */ 4598c2ecf20Sopenharmony_ci#define RCANFD_F_THLACC(m) (0x6000 + (0x04 * (m))) 4608c2ecf20Sopenharmony_ci/* RSCFDnCFDRPGACCr */ 4618c2ecf20Sopenharmony_ci#define RCANFD_F_RPGACC(r) (0x6400 + (0x04 * (r))) 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci/* Constants */ 4648c2ecf20Sopenharmony_ci#define RCANFD_FIFO_DEPTH 8 /* Tx FIFO depth */ 4658c2ecf20Sopenharmony_ci#define RCANFD_NAPI_WEIGHT 8 /* Rx poll quota */ 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci#define RCANFD_NUM_CHANNELS 2 /* Two channels max */ 4688c2ecf20Sopenharmony_ci#define RCANFD_CHANNELS_MASK BIT((RCANFD_NUM_CHANNELS) - 1) 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci#define RCANFD_GAFL_PAGENUM(entry) ((entry) / 16) 4718c2ecf20Sopenharmony_ci#define RCANFD_CHANNEL_NUMRULES 1 /* only one rule per channel */ 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* Rx FIFO is a global resource of the controller. There are 8 such FIFOs 4748c2ecf20Sopenharmony_ci * available. Each channel gets a dedicated Rx FIFO (i.e.) the channel 4758c2ecf20Sopenharmony_ci * number is added to RFFIFO index. 4768c2ecf20Sopenharmony_ci */ 4778c2ecf20Sopenharmony_ci#define RCANFD_RFFIFO_IDX 0 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci/* Tx/Rx or Common FIFO is a per channel resource. Each channel has 3 Common 4808c2ecf20Sopenharmony_ci * FIFOs dedicated to them. Use the first (index 0) FIFO out of the 3 for Tx. 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci#define RCANFD_CFFIFO_IDX 0 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci/* fCAN clock select register settings */ 4858c2ecf20Sopenharmony_cienum rcar_canfd_fcanclk { 4868c2ecf20Sopenharmony_ci RCANFD_CANFDCLK = 0, /* CANFD clock */ 4878c2ecf20Sopenharmony_ci RCANFD_EXTCLK, /* Externally input clock */ 4888c2ecf20Sopenharmony_ci}; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistruct rcar_canfd_global; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci/* Channel priv data */ 4938c2ecf20Sopenharmony_cistruct rcar_canfd_channel { 4948c2ecf20Sopenharmony_ci struct can_priv can; /* Must be the first member */ 4958c2ecf20Sopenharmony_ci struct net_device *ndev; 4968c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv; /* Controller reference */ 4978c2ecf20Sopenharmony_ci void __iomem *base; /* Register base address */ 4988c2ecf20Sopenharmony_ci struct napi_struct napi; 4998c2ecf20Sopenharmony_ci u8 tx_len[RCANFD_FIFO_DEPTH]; /* For net stats */ 5008c2ecf20Sopenharmony_ci u32 tx_head; /* Incremented on xmit */ 5018c2ecf20Sopenharmony_ci u32 tx_tail; /* Incremented on xmit done */ 5028c2ecf20Sopenharmony_ci u32 channel; /* Channel number */ 5038c2ecf20Sopenharmony_ci spinlock_t tx_lock; /* To protect tx path */ 5048c2ecf20Sopenharmony_ci}; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci/* Global priv data */ 5078c2ecf20Sopenharmony_cistruct rcar_canfd_global { 5088c2ecf20Sopenharmony_ci struct rcar_canfd_channel *ch[RCANFD_NUM_CHANNELS]; 5098c2ecf20Sopenharmony_ci void __iomem *base; /* Register base address */ 5108c2ecf20Sopenharmony_ci struct platform_device *pdev; /* Respective platform device */ 5118c2ecf20Sopenharmony_ci struct clk *clkp; /* Peripheral clock */ 5128c2ecf20Sopenharmony_ci struct clk *can_clk; /* fCAN clock */ 5138c2ecf20Sopenharmony_ci enum rcar_canfd_fcanclk fcan; /* CANFD or Ext clock */ 5148c2ecf20Sopenharmony_ci unsigned long channels_mask; /* Enabled channels mask */ 5158c2ecf20Sopenharmony_ci bool fdmode; /* CAN FD or Classical CAN only mode */ 5168c2ecf20Sopenharmony_ci}; 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci/* CAN FD mode nominal rate constants */ 5198c2ecf20Sopenharmony_cistatic const struct can_bittiming_const rcar_canfd_nom_bittiming_const = { 5208c2ecf20Sopenharmony_ci .name = RCANFD_DRV_NAME, 5218c2ecf20Sopenharmony_ci .tseg1_min = 2, 5228c2ecf20Sopenharmony_ci .tseg1_max = 128, 5238c2ecf20Sopenharmony_ci .tseg2_min = 2, 5248c2ecf20Sopenharmony_ci .tseg2_max = 32, 5258c2ecf20Sopenharmony_ci .sjw_max = 32, 5268c2ecf20Sopenharmony_ci .brp_min = 1, 5278c2ecf20Sopenharmony_ci .brp_max = 1024, 5288c2ecf20Sopenharmony_ci .brp_inc = 1, 5298c2ecf20Sopenharmony_ci}; 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci/* CAN FD mode data rate constants */ 5328c2ecf20Sopenharmony_cistatic const struct can_bittiming_const rcar_canfd_data_bittiming_const = { 5338c2ecf20Sopenharmony_ci .name = RCANFD_DRV_NAME, 5348c2ecf20Sopenharmony_ci .tseg1_min = 2, 5358c2ecf20Sopenharmony_ci .tseg1_max = 16, 5368c2ecf20Sopenharmony_ci .tseg2_min = 2, 5378c2ecf20Sopenharmony_ci .tseg2_max = 8, 5388c2ecf20Sopenharmony_ci .sjw_max = 8, 5398c2ecf20Sopenharmony_ci .brp_min = 1, 5408c2ecf20Sopenharmony_ci .brp_max = 256, 5418c2ecf20Sopenharmony_ci .brp_inc = 1, 5428c2ecf20Sopenharmony_ci}; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci/* Classical CAN mode bitrate constants */ 5458c2ecf20Sopenharmony_cistatic const struct can_bittiming_const rcar_canfd_bittiming_const = { 5468c2ecf20Sopenharmony_ci .name = RCANFD_DRV_NAME, 5478c2ecf20Sopenharmony_ci .tseg1_min = 4, 5488c2ecf20Sopenharmony_ci .tseg1_max = 16, 5498c2ecf20Sopenharmony_ci .tseg2_min = 2, 5508c2ecf20Sopenharmony_ci .tseg2_max = 8, 5518c2ecf20Sopenharmony_ci .sjw_max = 4, 5528c2ecf20Sopenharmony_ci .brp_min = 1, 5538c2ecf20Sopenharmony_ci .brp_max = 1024, 5548c2ecf20Sopenharmony_ci .brp_inc = 1, 5558c2ecf20Sopenharmony_ci}; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci/* Helper functions */ 5588c2ecf20Sopenharmony_cistatic inline void rcar_canfd_update(u32 mask, u32 val, u32 __iomem *reg) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci u32 data = readl(reg); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci data &= ~mask; 5638c2ecf20Sopenharmony_ci data |= (val & mask); 5648c2ecf20Sopenharmony_ci writel(data, reg); 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_cistatic inline u32 rcar_canfd_read(void __iomem *base, u32 offset) 5688c2ecf20Sopenharmony_ci{ 5698c2ecf20Sopenharmony_ci return readl(base + (offset)); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic inline void rcar_canfd_write(void __iomem *base, u32 offset, u32 val) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci writel(val, base + (offset)); 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_cistatic void rcar_canfd_set_bit(void __iomem *base, u32 reg, u32 val) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci rcar_canfd_update(val, val, base + (reg)); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic void rcar_canfd_clear_bit(void __iomem *base, u32 reg, u32 val) 5838c2ecf20Sopenharmony_ci{ 5848c2ecf20Sopenharmony_ci rcar_canfd_update(val, 0, base + (reg)); 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_cistatic void rcar_canfd_update_bit(void __iomem *base, u32 reg, 5888c2ecf20Sopenharmony_ci u32 mask, u32 val) 5898c2ecf20Sopenharmony_ci{ 5908c2ecf20Sopenharmony_ci rcar_canfd_update(mask, val, base + (reg)); 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic void rcar_canfd_get_data(struct rcar_canfd_channel *priv, 5948c2ecf20Sopenharmony_ci struct canfd_frame *cf, u32 off) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci u32 i, lwords; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci lwords = DIV_ROUND_UP(cf->len, sizeof(u32)); 5998c2ecf20Sopenharmony_ci for (i = 0; i < lwords; i++) 6008c2ecf20Sopenharmony_ci *((u32 *)cf->data + i) = 6018c2ecf20Sopenharmony_ci rcar_canfd_read(priv->base, off + (i * sizeof(u32))); 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic void rcar_canfd_put_data(struct rcar_canfd_channel *priv, 6058c2ecf20Sopenharmony_ci struct canfd_frame *cf, u32 off) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci u32 i, lwords; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci lwords = DIV_ROUND_UP(cf->len, sizeof(u32)); 6108c2ecf20Sopenharmony_ci for (i = 0; i < lwords; i++) 6118c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, off + (i * sizeof(u32)), 6128c2ecf20Sopenharmony_ci *((u32 *)cf->data + i)); 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_cistatic void rcar_canfd_tx_failure_cleanup(struct net_device *ndev) 6168c2ecf20Sopenharmony_ci{ 6178c2ecf20Sopenharmony_ci u32 i; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci for (i = 0; i < RCANFD_FIFO_DEPTH; i++) 6208c2ecf20Sopenharmony_ci can_free_echo_skb(ndev, i); 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_cistatic int rcar_canfd_reset_controller(struct rcar_canfd_global *gpriv) 6248c2ecf20Sopenharmony_ci{ 6258c2ecf20Sopenharmony_ci u32 sts, ch; 6268c2ecf20Sopenharmony_ci int err; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* Check RAMINIT flag as CAN RAM initialization takes place 6298c2ecf20Sopenharmony_ci * after the MCU reset 6308c2ecf20Sopenharmony_ci */ 6318c2ecf20Sopenharmony_ci err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, 6328c2ecf20Sopenharmony_ci !(sts & RCANFD_GSTS_GRAMINIT), 2, 500000); 6338c2ecf20Sopenharmony_ci if (err) { 6348c2ecf20Sopenharmony_ci dev_dbg(&gpriv->pdev->dev, "global raminit failed\n"); 6358c2ecf20Sopenharmony_ci return err; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* Transition to Global Reset mode */ 6398c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR); 6408c2ecf20Sopenharmony_ci rcar_canfd_update_bit(gpriv->base, RCANFD_GCTR, 6418c2ecf20Sopenharmony_ci RCANFD_GCTR_GMDC_MASK, RCANFD_GCTR_GMDC_GRESET); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* Ensure Global reset mode */ 6448c2ecf20Sopenharmony_ci err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, 6458c2ecf20Sopenharmony_ci (sts & RCANFD_GSTS_GRSTSTS), 2, 500000); 6468c2ecf20Sopenharmony_ci if (err) { 6478c2ecf20Sopenharmony_ci dev_dbg(&gpriv->pdev->dev, "global reset failed\n"); 6488c2ecf20Sopenharmony_ci return err; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci /* Reset Global error flags */ 6528c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0x0); 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci /* Set the controller into appropriate mode */ 6558c2ecf20Sopenharmony_ci if (gpriv->fdmode) 6568c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GRMCFG, 6578c2ecf20Sopenharmony_ci RCANFD_GRMCFG_RCMC); 6588c2ecf20Sopenharmony_ci else 6598c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(gpriv->base, RCANFD_GRMCFG, 6608c2ecf20Sopenharmony_ci RCANFD_GRMCFG_RCMC); 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci /* Transition all Channels to reset mode */ 6638c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 6648c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(gpriv->base, 6658c2ecf20Sopenharmony_ci RCANFD_CCTR(ch), RCANFD_CCTR_CSLPR); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch), 6688c2ecf20Sopenharmony_ci RCANFD_CCTR_CHMDC_MASK, 6698c2ecf20Sopenharmony_ci RCANFD_CCTR_CHDMC_CRESET); 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* Ensure Channel reset mode */ 6728c2ecf20Sopenharmony_ci err = readl_poll_timeout((gpriv->base + RCANFD_CSTS(ch)), sts, 6738c2ecf20Sopenharmony_ci (sts & RCANFD_CSTS_CRSTSTS), 6748c2ecf20Sopenharmony_ci 2, 500000); 6758c2ecf20Sopenharmony_ci if (err) { 6768c2ecf20Sopenharmony_ci dev_dbg(&gpriv->pdev->dev, 6778c2ecf20Sopenharmony_ci "channel %u reset failed\n", ch); 6788c2ecf20Sopenharmony_ci return err; 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci return 0; 6828c2ecf20Sopenharmony_ci} 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_cistatic void rcar_canfd_configure_controller(struct rcar_canfd_global *gpriv) 6858c2ecf20Sopenharmony_ci{ 6868c2ecf20Sopenharmony_ci u32 cfg, ch; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci /* Global configuration settings */ 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* ECC Error flag Enable */ 6918c2ecf20Sopenharmony_ci cfg = RCANFD_GCFG_EEFE; 6928c2ecf20Sopenharmony_ci 6938c2ecf20Sopenharmony_ci if (gpriv->fdmode) 6948c2ecf20Sopenharmony_ci /* Truncate payload to configured message size RFPLS */ 6958c2ecf20Sopenharmony_ci cfg |= RCANFD_GCFG_CMPOC; 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* Set External Clock if selected */ 6988c2ecf20Sopenharmony_ci if (gpriv->fcan != RCANFD_CANFDCLK) 6998c2ecf20Sopenharmony_ci cfg |= RCANFD_GCFG_DCS; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GCFG, cfg); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* Channel configuration settings */ 7048c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 7058c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_CCTR(ch), 7068c2ecf20Sopenharmony_ci RCANFD_CCTR_ERRD); 7078c2ecf20Sopenharmony_ci rcar_canfd_update_bit(gpriv->base, RCANFD_CCTR(ch), 7088c2ecf20Sopenharmony_ci RCANFD_CCTR_BOM_MASK, 7098c2ecf20Sopenharmony_ci RCANFD_CCTR_BOM_BENTRY); 7108c2ecf20Sopenharmony_ci } 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic void rcar_canfd_configure_afl_rules(struct rcar_canfd_global *gpriv, 7148c2ecf20Sopenharmony_ci u32 ch) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci u32 cfg; 7178c2ecf20Sopenharmony_ci int offset, start, page, num_rules = RCANFD_CHANNEL_NUMRULES; 7188c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci if (ch == 0) { 7218c2ecf20Sopenharmony_ci start = 0; /* Channel 0 always starts from 0th rule */ 7228c2ecf20Sopenharmony_ci } else { 7238c2ecf20Sopenharmony_ci /* Get number of Channel 0 rules and adjust */ 7248c2ecf20Sopenharmony_ci cfg = rcar_canfd_read(gpriv->base, RCANFD_GAFLCFG0); 7258c2ecf20Sopenharmony_ci start = RCANFD_GAFLCFG_GETRNC(0, cfg); 7268c2ecf20Sopenharmony_ci } 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci /* Enable write access to entry */ 7298c2ecf20Sopenharmony_ci page = RCANFD_GAFL_PAGENUM(start); 7308c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLECTR, 7318c2ecf20Sopenharmony_ci (RCANFD_GAFLECTR_AFLPN(page) | 7328c2ecf20Sopenharmony_ci RCANFD_GAFLECTR_AFLDAE)); 7338c2ecf20Sopenharmony_ci 7348c2ecf20Sopenharmony_ci /* Write number of rules for channel */ 7358c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GAFLCFG0, 7368c2ecf20Sopenharmony_ci RCANFD_GAFLCFG_SETRNC(ch, num_rules)); 7378c2ecf20Sopenharmony_ci if (gpriv->fdmode) 7388c2ecf20Sopenharmony_ci offset = RCANFD_F_GAFL_OFFSET; 7398c2ecf20Sopenharmony_ci else 7408c2ecf20Sopenharmony_ci offset = RCANFD_C_GAFL_OFFSET; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci /* Accept all IDs */ 7438c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GAFLID(offset, start), 0); 7448c2ecf20Sopenharmony_ci /* IDE or RTR is not considered for matching */ 7458c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GAFLM(offset, start), 0); 7468c2ecf20Sopenharmony_ci /* Any data length accepted */ 7478c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GAFLP0(offset, start), 0); 7488c2ecf20Sopenharmony_ci /* Place the msg in corresponding Rx FIFO entry */ 7498c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GAFLP1(offset, start), 7508c2ecf20Sopenharmony_ci RCANFD_GAFLP1_GAFLFDP(ridx)); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* Disable write access to page */ 7538c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(gpriv->base, 7548c2ecf20Sopenharmony_ci RCANFD_GAFLECTR, RCANFD_GAFLECTR_AFLDAE); 7558c2ecf20Sopenharmony_ci} 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_cistatic void rcar_canfd_configure_rx(struct rcar_canfd_global *gpriv, u32 ch) 7588c2ecf20Sopenharmony_ci{ 7598c2ecf20Sopenharmony_ci /* Rx FIFO is used for reception */ 7608c2ecf20Sopenharmony_ci u32 cfg; 7618c2ecf20Sopenharmony_ci u16 rfdc, rfpls; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci /* Select Rx FIFO based on channel */ 7648c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci rfdc = 2; /* b010 - 8 messages Rx FIFO depth */ 7678c2ecf20Sopenharmony_ci if (gpriv->fdmode) 7688c2ecf20Sopenharmony_ci rfpls = 7; /* b111 - Max 64 bytes payload */ 7698c2ecf20Sopenharmony_ci else 7708c2ecf20Sopenharmony_ci rfpls = 0; /* b000 - Max 8 bytes payload */ 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci cfg = (RCANFD_RFCC_RFIM | RCANFD_RFCC_RFDC(rfdc) | 7738c2ecf20Sopenharmony_ci RCANFD_RFCC_RFPLS(rfpls) | RCANFD_RFCC_RFIE); 7748c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_RFCC(ridx), cfg); 7758c2ecf20Sopenharmony_ci} 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_cistatic void rcar_canfd_configure_tx(struct rcar_canfd_global *gpriv, u32 ch) 7788c2ecf20Sopenharmony_ci{ 7798c2ecf20Sopenharmony_ci /* Tx/Rx(Common) FIFO configured in Tx mode is 7808c2ecf20Sopenharmony_ci * used for transmission 7818c2ecf20Sopenharmony_ci * 7828c2ecf20Sopenharmony_ci * Each channel has 3 Common FIFO dedicated to them. 7838c2ecf20Sopenharmony_ci * Use the 1st (index 0) out of 3 7848c2ecf20Sopenharmony_ci */ 7858c2ecf20Sopenharmony_ci u32 cfg; 7868c2ecf20Sopenharmony_ci u16 cftml, cfm, cfdc, cfpls; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci cftml = 0; /* 0th buffer */ 7898c2ecf20Sopenharmony_ci cfm = 1; /* b01 - Transmit mode */ 7908c2ecf20Sopenharmony_ci cfdc = 2; /* b010 - 8 messages Tx FIFO depth */ 7918c2ecf20Sopenharmony_ci if (gpriv->fdmode) 7928c2ecf20Sopenharmony_ci cfpls = 7; /* b111 - Max 64 bytes payload */ 7938c2ecf20Sopenharmony_ci else 7948c2ecf20Sopenharmony_ci cfpls = 0; /* b000 - Max 8 bytes payload */ 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci cfg = (RCANFD_CFCC_CFTML(cftml) | RCANFD_CFCC_CFM(cfm) | 7978c2ecf20Sopenharmony_ci RCANFD_CFCC_CFIM | RCANFD_CFCC_CFDC(cfdc) | 7988c2ecf20Sopenharmony_ci RCANFD_CFCC_CFPLS(cfpls) | RCANFD_CFCC_CFTXIE); 7998c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), cfg); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci if (gpriv->fdmode) 8028c2ecf20Sopenharmony_ci /* Clear FD mode specific control/status register */ 8038c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, 8048c2ecf20Sopenharmony_ci RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), 0); 8058c2ecf20Sopenharmony_ci} 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_cistatic void rcar_canfd_enable_global_interrupts(struct rcar_canfd_global *gpriv) 8088c2ecf20Sopenharmony_ci{ 8098c2ecf20Sopenharmony_ci u32 ctr; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci /* Clear any stray error interrupt flags */ 8128c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci /* Global interrupts setup */ 8158c2ecf20Sopenharmony_ci ctr = RCANFD_GCTR_MEIE; 8168c2ecf20Sopenharmony_ci if (gpriv->fdmode) 8178c2ecf20Sopenharmony_ci ctr |= RCANFD_GCTR_CFMPOFIE; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, ctr); 8208c2ecf20Sopenharmony_ci} 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_cistatic void rcar_canfd_disable_global_interrupts(struct rcar_canfd_global 8238c2ecf20Sopenharmony_ci *gpriv) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci /* Disable all interrupts */ 8268c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GCTR, 0); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* Clear any stray error interrupt flags */ 8298c2ecf20Sopenharmony_ci rcar_canfd_write(gpriv->base, RCANFD_GERFL, 0); 8308c2ecf20Sopenharmony_ci} 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_cistatic void rcar_canfd_enable_channel_interrupts(struct rcar_canfd_channel 8338c2ecf20Sopenharmony_ci *priv) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci u32 ctr, ch = priv->channel; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci /* Clear any stray error flags */ 8388c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 0); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* Channel interrupts setup */ 8418c2ecf20Sopenharmony_ci ctr = (RCANFD_CCTR_TAIE | 8428c2ecf20Sopenharmony_ci RCANFD_CCTR_ALIE | RCANFD_CCTR_BLIE | 8438c2ecf20Sopenharmony_ci RCANFD_CCTR_OLIE | RCANFD_CCTR_BORIE | 8448c2ecf20Sopenharmony_ci RCANFD_CCTR_BOEIE | RCANFD_CCTR_EPIE | 8458c2ecf20Sopenharmony_ci RCANFD_CCTR_EWIE | RCANFD_CCTR_BEIE); 8468c2ecf20Sopenharmony_ci rcar_canfd_set_bit(priv->base, RCANFD_CCTR(ch), ctr); 8478c2ecf20Sopenharmony_ci} 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_cistatic void rcar_canfd_disable_channel_interrupts(struct rcar_canfd_channel 8508c2ecf20Sopenharmony_ci *priv) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci u32 ctr, ch = priv->channel; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci ctr = (RCANFD_CCTR_TAIE | 8558c2ecf20Sopenharmony_ci RCANFD_CCTR_ALIE | RCANFD_CCTR_BLIE | 8568c2ecf20Sopenharmony_ci RCANFD_CCTR_OLIE | RCANFD_CCTR_BORIE | 8578c2ecf20Sopenharmony_ci RCANFD_CCTR_BOEIE | RCANFD_CCTR_EPIE | 8588c2ecf20Sopenharmony_ci RCANFD_CCTR_EWIE | RCANFD_CCTR_BEIE); 8598c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(priv->base, RCANFD_CCTR(ch), ctr); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* Clear any stray error flags */ 8628c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 0); 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_cistatic void rcar_canfd_global_error(struct net_device *ndev) 8668c2ecf20Sopenharmony_ci{ 8678c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 8688c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = priv->gpriv; 8698c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 8708c2ecf20Sopenharmony_ci u32 ch = priv->channel; 8718c2ecf20Sopenharmony_ci u32 gerfl, sts; 8728c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); 8758c2ecf20Sopenharmony_ci if ((gerfl & RCANFD_GERFL_EEF0) && (ch == 0)) { 8768c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Ch0: ECC Error flag\n"); 8778c2ecf20Sopenharmony_ci stats->tx_dropped++; 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci if ((gerfl & RCANFD_GERFL_EEF1) && (ch == 1)) { 8808c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Ch1: ECC Error flag\n"); 8818c2ecf20Sopenharmony_ci stats->tx_dropped++; 8828c2ecf20Sopenharmony_ci } 8838c2ecf20Sopenharmony_ci if (gerfl & RCANFD_GERFL_MES) { 8848c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, 8858c2ecf20Sopenharmony_ci RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); 8868c2ecf20Sopenharmony_ci if (sts & RCANFD_CFSTS_CFMLT) { 8878c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Tx Message Lost flag\n"); 8888c2ecf20Sopenharmony_ci stats->tx_dropped++; 8898c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 8908c2ecf20Sopenharmony_ci RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX), 8918c2ecf20Sopenharmony_ci sts & ~RCANFD_CFSTS_CFMLT); 8928c2ecf20Sopenharmony_ci } 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); 8958c2ecf20Sopenharmony_ci if (sts & RCANFD_RFSTS_RFMLT) { 8968c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Rx Message Lost flag\n"); 8978c2ecf20Sopenharmony_ci stats->rx_dropped++; 8988c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_RFSTS(ridx), 8998c2ecf20Sopenharmony_ci sts & ~RCANFD_RFSTS_RFMLT); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci if (gpriv->fdmode && gerfl & RCANFD_GERFL_CMPOF) { 9038c2ecf20Sopenharmony_ci /* Message Lost flag will be set for respective channel 9048c2ecf20Sopenharmony_ci * when this condition happens with counters and flags 9058c2ecf20Sopenharmony_ci * already updated. 9068c2ecf20Sopenharmony_ci */ 9078c2ecf20Sopenharmony_ci netdev_dbg(ndev, "global payload overflow interrupt\n"); 9088c2ecf20Sopenharmony_ci } 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci /* Clear all global error interrupts. Only affected channels bits 9118c2ecf20Sopenharmony_ci * get cleared 9128c2ecf20Sopenharmony_ci */ 9138c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_GERFL, 0); 9148c2ecf20Sopenharmony_ci} 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_cistatic void rcar_canfd_error(struct net_device *ndev, u32 cerfl, 9178c2ecf20Sopenharmony_ci u16 txerr, u16 rxerr) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 9208c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 9218c2ecf20Sopenharmony_ci struct can_frame *cf; 9228c2ecf20Sopenharmony_ci struct sk_buff *skb; 9238c2ecf20Sopenharmony_ci u32 ch = priv->channel; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci netdev_dbg(ndev, "ch erfl %x txerr %u rxerr %u\n", cerfl, txerr, rxerr); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci /* Propagate the error condition to the CAN stack */ 9288c2ecf20Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 9298c2ecf20Sopenharmony_ci if (!skb) { 9308c2ecf20Sopenharmony_ci stats->rx_dropped++; 9318c2ecf20Sopenharmony_ci return; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci /* Channel error interrupts */ 9358c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_BEF) { 9368c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Bus error\n"); 9378c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT; 9388c2ecf20Sopenharmony_ci cf->data[2] = CAN_ERR_PROT_UNSPEC; 9398c2ecf20Sopenharmony_ci priv->can.can_stats.bus_error++; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_ADERR) { 9428c2ecf20Sopenharmony_ci netdev_dbg(ndev, "ACK Delimiter Error\n"); 9438c2ecf20Sopenharmony_ci stats->tx_errors++; 9448c2ecf20Sopenharmony_ci cf->data[3] |= CAN_ERR_PROT_LOC_ACK_DEL; 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_B0ERR) { 9478c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Bit Error (dominant)\n"); 9488c2ecf20Sopenharmony_ci stats->tx_errors++; 9498c2ecf20Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_BIT0; 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_B1ERR) { 9528c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Bit Error (recessive)\n"); 9538c2ecf20Sopenharmony_ci stats->tx_errors++; 9548c2ecf20Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_BIT1; 9558c2ecf20Sopenharmony_ci } 9568c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_CERR) { 9578c2ecf20Sopenharmony_ci netdev_dbg(ndev, "CRC Error\n"); 9588c2ecf20Sopenharmony_ci stats->rx_errors++; 9598c2ecf20Sopenharmony_ci cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_AERR) { 9628c2ecf20Sopenharmony_ci netdev_dbg(ndev, "ACK Error\n"); 9638c2ecf20Sopenharmony_ci stats->tx_errors++; 9648c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_ACK; 9658c2ecf20Sopenharmony_ci cf->data[3] |= CAN_ERR_PROT_LOC_ACK; 9668c2ecf20Sopenharmony_ci } 9678c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_FERR) { 9688c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Form Error\n"); 9698c2ecf20Sopenharmony_ci stats->rx_errors++; 9708c2ecf20Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_FORM; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_SERR) { 9738c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Stuff Error\n"); 9748c2ecf20Sopenharmony_ci stats->rx_errors++; 9758c2ecf20Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_STUFF; 9768c2ecf20Sopenharmony_ci } 9778c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_ALF) { 9788c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Arbitration lost Error\n"); 9798c2ecf20Sopenharmony_ci priv->can.can_stats.arbitration_lost++; 9808c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_LOSTARB; 9818c2ecf20Sopenharmony_ci cf->data[0] |= CAN_ERR_LOSTARB_UNSPEC; 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_BLF) { 9848c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Bus Lock Error\n"); 9858c2ecf20Sopenharmony_ci stats->rx_errors++; 9868c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_BUSERROR; 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_EWF) { 9898c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Error warning interrupt\n"); 9908c2ecf20Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_WARNING; 9918c2ecf20Sopenharmony_ci priv->can.can_stats.error_warning++; 9928c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_CRTL; 9938c2ecf20Sopenharmony_ci cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_WARNING : 9948c2ecf20Sopenharmony_ci CAN_ERR_CRTL_RX_WARNING; 9958c2ecf20Sopenharmony_ci cf->data[6] = txerr; 9968c2ecf20Sopenharmony_ci cf->data[7] = rxerr; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_EPF) { 9998c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Error passive interrupt\n"); 10008c2ecf20Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_PASSIVE; 10018c2ecf20Sopenharmony_ci priv->can.can_stats.error_passive++; 10028c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_CRTL; 10038c2ecf20Sopenharmony_ci cf->data[1] = txerr > rxerr ? CAN_ERR_CRTL_TX_PASSIVE : 10048c2ecf20Sopenharmony_ci CAN_ERR_CRTL_RX_PASSIVE; 10058c2ecf20Sopenharmony_ci cf->data[6] = txerr; 10068c2ecf20Sopenharmony_ci cf->data[7] = rxerr; 10078c2ecf20Sopenharmony_ci } 10088c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_BOEF) { 10098c2ecf20Sopenharmony_ci netdev_dbg(ndev, "Bus-off entry interrupt\n"); 10108c2ecf20Sopenharmony_ci rcar_canfd_tx_failure_cleanup(ndev); 10118c2ecf20Sopenharmony_ci priv->can.state = CAN_STATE_BUS_OFF; 10128c2ecf20Sopenharmony_ci priv->can.can_stats.bus_off++; 10138c2ecf20Sopenharmony_ci can_bus_off(ndev); 10148c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_BUSOFF; 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci if (cerfl & RCANFD_CERFL_OVLF) { 10178c2ecf20Sopenharmony_ci netdev_dbg(ndev, 10188c2ecf20Sopenharmony_ci "Overload Frame Transmission error interrupt\n"); 10198c2ecf20Sopenharmony_ci stats->tx_errors++; 10208c2ecf20Sopenharmony_ci cf->can_id |= CAN_ERR_PROT; 10218c2ecf20Sopenharmony_ci cf->data[2] |= CAN_ERR_PROT_OVERLOAD; 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci /* Clear channel error interrupts that are handled */ 10258c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CERFL(ch), 10268c2ecf20Sopenharmony_ci RCANFD_CERFL_ERR(~cerfl)); 10278c2ecf20Sopenharmony_ci stats->rx_packets++; 10288c2ecf20Sopenharmony_ci stats->rx_bytes += cf->can_dlc; 10298c2ecf20Sopenharmony_ci netif_rx(skb); 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_cistatic void rcar_canfd_tx_done(struct net_device *ndev) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 10358c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 10368c2ecf20Sopenharmony_ci u32 sts; 10378c2ecf20Sopenharmony_ci unsigned long flags; 10388c2ecf20Sopenharmony_ci u32 ch = priv->channel; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci do { 10418c2ecf20Sopenharmony_ci u8 unsent, sent; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci sent = priv->tx_tail % RCANFD_FIFO_DEPTH; 10448c2ecf20Sopenharmony_ci stats->tx_packets++; 10458c2ecf20Sopenharmony_ci stats->tx_bytes += priv->tx_len[sent]; 10468c2ecf20Sopenharmony_ci priv->tx_len[sent] = 0; 10478c2ecf20Sopenharmony_ci can_get_echo_skb(ndev, sent); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->tx_lock, flags); 10508c2ecf20Sopenharmony_ci priv->tx_tail++; 10518c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, 10528c2ecf20Sopenharmony_ci RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); 10538c2ecf20Sopenharmony_ci unsent = RCANFD_CFSTS_CFMC(sts); 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci /* Wake producer only when there is room */ 10568c2ecf20Sopenharmony_ci if (unsent != RCANFD_FIFO_DEPTH) 10578c2ecf20Sopenharmony_ci netif_wake_queue(ndev); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (priv->tx_head - priv->tx_tail <= unsent) { 10608c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->tx_lock, flags); 10618c2ecf20Sopenharmony_ci break; 10628c2ecf20Sopenharmony_ci } 10638c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->tx_lock, flags); 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci } while (1); 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci /* Clear interrupt */ 10688c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX), 10698c2ecf20Sopenharmony_ci sts & ~RCANFD_CFSTS_CFTXIF); 10708c2ecf20Sopenharmony_ci can_led_event(ndev, CAN_LED_EVENT_TX); 10718c2ecf20Sopenharmony_ci} 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_cistatic irqreturn_t rcar_canfd_global_interrupt(int irq, void *dev_id) 10748c2ecf20Sopenharmony_ci{ 10758c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = dev_id; 10768c2ecf20Sopenharmony_ci struct net_device *ndev; 10778c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv; 10788c2ecf20Sopenharmony_ci u32 sts, cc, gerfl; 10798c2ecf20Sopenharmony_ci u32 ch, ridx; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci /* Global error interrupts still indicate a condition specific 10828c2ecf20Sopenharmony_ci * to a channel. RxFIFO interrupt is a global interrupt. 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 10858c2ecf20Sopenharmony_ci priv = gpriv->ch[ch]; 10868c2ecf20Sopenharmony_ci ndev = priv->ndev; 10878c2ecf20Sopenharmony_ci ridx = ch + RCANFD_RFFIFO_IDX; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci /* Global error interrupts */ 10908c2ecf20Sopenharmony_ci gerfl = rcar_canfd_read(priv->base, RCANFD_GERFL); 10918c2ecf20Sopenharmony_ci if (unlikely(RCANFD_GERFL_ERR(gpriv, gerfl))) 10928c2ecf20Sopenharmony_ci rcar_canfd_global_error(ndev); 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci /* Handle Rx interrupts */ 10958c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); 10968c2ecf20Sopenharmony_ci cc = rcar_canfd_read(priv->base, RCANFD_RFCC(ridx)); 10978c2ecf20Sopenharmony_ci if (likely(sts & RCANFD_RFSTS_RFIF && 10988c2ecf20Sopenharmony_ci cc & RCANFD_RFCC_RFIE)) { 10998c2ecf20Sopenharmony_ci if (napi_schedule_prep(&priv->napi)) { 11008c2ecf20Sopenharmony_ci /* Disable Rx FIFO interrupts */ 11018c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(priv->base, 11028c2ecf20Sopenharmony_ci RCANFD_RFCC(ridx), 11038c2ecf20Sopenharmony_ci RCANFD_RFCC_RFIE); 11048c2ecf20Sopenharmony_ci __napi_schedule(&priv->napi); 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci return IRQ_HANDLED; 11098c2ecf20Sopenharmony_ci} 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_cistatic void rcar_canfd_state_change(struct net_device *ndev, 11128c2ecf20Sopenharmony_ci u16 txerr, u16 rxerr) 11138c2ecf20Sopenharmony_ci{ 11148c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 11158c2ecf20Sopenharmony_ci struct net_device_stats *stats = &ndev->stats; 11168c2ecf20Sopenharmony_ci enum can_state rx_state, tx_state, state = priv->can.state; 11178c2ecf20Sopenharmony_ci struct can_frame *cf; 11188c2ecf20Sopenharmony_ci struct sk_buff *skb; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* Handle transition from error to normal states */ 11218c2ecf20Sopenharmony_ci if (txerr < 96 && rxerr < 96) 11228c2ecf20Sopenharmony_ci state = CAN_STATE_ERROR_ACTIVE; 11238c2ecf20Sopenharmony_ci else if (txerr < 128 && rxerr < 128) 11248c2ecf20Sopenharmony_ci state = CAN_STATE_ERROR_WARNING; 11258c2ecf20Sopenharmony_ci 11268c2ecf20Sopenharmony_ci if (state != priv->can.state) { 11278c2ecf20Sopenharmony_ci netdev_dbg(ndev, "state: new %d, old %d: txerr %u, rxerr %u\n", 11288c2ecf20Sopenharmony_ci state, priv->can.state, txerr, rxerr); 11298c2ecf20Sopenharmony_ci skb = alloc_can_err_skb(ndev, &cf); 11308c2ecf20Sopenharmony_ci if (!skb) { 11318c2ecf20Sopenharmony_ci stats->rx_dropped++; 11328c2ecf20Sopenharmony_ci return; 11338c2ecf20Sopenharmony_ci } 11348c2ecf20Sopenharmony_ci tx_state = txerr >= rxerr ? state : 0; 11358c2ecf20Sopenharmony_ci rx_state = txerr <= rxerr ? state : 0; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci can_change_state(ndev, cf, tx_state, rx_state); 11388c2ecf20Sopenharmony_ci stats->rx_packets++; 11398c2ecf20Sopenharmony_ci stats->rx_bytes += cf->can_dlc; 11408c2ecf20Sopenharmony_ci netif_rx(skb); 11418c2ecf20Sopenharmony_ci } 11428c2ecf20Sopenharmony_ci} 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_cistatic irqreturn_t rcar_canfd_channel_interrupt(int irq, void *dev_id) 11458c2ecf20Sopenharmony_ci{ 11468c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = dev_id; 11478c2ecf20Sopenharmony_ci struct net_device *ndev; 11488c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv; 11498c2ecf20Sopenharmony_ci u32 sts, ch, cerfl; 11508c2ecf20Sopenharmony_ci u16 txerr, rxerr; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* Common FIFO is a per channel resource */ 11538c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 11548c2ecf20Sopenharmony_ci priv = gpriv->ch[ch]; 11558c2ecf20Sopenharmony_ci ndev = priv->ndev; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci /* Channel error interrupts */ 11588c2ecf20Sopenharmony_ci cerfl = rcar_canfd_read(priv->base, RCANFD_CERFL(ch)); 11598c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, RCANFD_CSTS(ch)); 11608c2ecf20Sopenharmony_ci txerr = RCANFD_CSTS_TECCNT(sts); 11618c2ecf20Sopenharmony_ci rxerr = RCANFD_CSTS_RECCNT(sts); 11628c2ecf20Sopenharmony_ci if (unlikely(RCANFD_CERFL_ERR(cerfl))) 11638c2ecf20Sopenharmony_ci rcar_canfd_error(ndev, cerfl, txerr, rxerr); 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci /* Handle state change to lower states */ 11668c2ecf20Sopenharmony_ci if (unlikely((priv->can.state != CAN_STATE_ERROR_ACTIVE) && 11678c2ecf20Sopenharmony_ci (priv->can.state != CAN_STATE_BUS_OFF))) 11688c2ecf20Sopenharmony_ci rcar_canfd_state_change(ndev, txerr, rxerr); 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci /* Handle Tx interrupts */ 11718c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, 11728c2ecf20Sopenharmony_ci RCANFD_CFSTS(ch, RCANFD_CFFIFO_IDX)); 11738c2ecf20Sopenharmony_ci if (likely(sts & RCANFD_CFSTS_CFTXIF)) 11748c2ecf20Sopenharmony_ci rcar_canfd_tx_done(ndev); 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci return IRQ_HANDLED; 11778c2ecf20Sopenharmony_ci} 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cistatic void rcar_canfd_set_bittiming(struct net_device *dev) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(dev); 11828c2ecf20Sopenharmony_ci const struct can_bittiming *bt = &priv->can.bittiming; 11838c2ecf20Sopenharmony_ci const struct can_bittiming *dbt = &priv->can.data_bittiming; 11848c2ecf20Sopenharmony_ci u16 brp, sjw, tseg1, tseg2; 11858c2ecf20Sopenharmony_ci u32 cfg; 11868c2ecf20Sopenharmony_ci u32 ch = priv->channel; 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci /* Nominal bit timing settings */ 11898c2ecf20Sopenharmony_ci brp = bt->brp - 1; 11908c2ecf20Sopenharmony_ci sjw = bt->sjw - 1; 11918c2ecf20Sopenharmony_ci tseg1 = bt->prop_seg + bt->phase_seg1 - 1; 11928c2ecf20Sopenharmony_ci tseg2 = bt->phase_seg2 - 1; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { 11958c2ecf20Sopenharmony_ci /* CAN FD only mode */ 11968c2ecf20Sopenharmony_ci cfg = (RCANFD_NCFG_NTSEG1(tseg1) | RCANFD_NCFG_NBRP(brp) | 11978c2ecf20Sopenharmony_ci RCANFD_NCFG_NSJW(sjw) | RCANFD_NCFG_NTSEG2(tseg2)); 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg); 12008c2ecf20Sopenharmony_ci netdev_dbg(priv->ndev, "nrate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", 12018c2ecf20Sopenharmony_ci brp, sjw, tseg1, tseg2); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci /* Data bit timing settings */ 12048c2ecf20Sopenharmony_ci brp = dbt->brp - 1; 12058c2ecf20Sopenharmony_ci sjw = dbt->sjw - 1; 12068c2ecf20Sopenharmony_ci tseg1 = dbt->prop_seg + dbt->phase_seg1 - 1; 12078c2ecf20Sopenharmony_ci tseg2 = dbt->phase_seg2 - 1; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci cfg = (RCANFD_DCFG_DTSEG1(tseg1) | RCANFD_DCFG_DBRP(brp) | 12108c2ecf20Sopenharmony_ci RCANFD_DCFG_DSJW(sjw) | RCANFD_DCFG_DTSEG2(tseg2)); 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_F_DCFG(ch), cfg); 12138c2ecf20Sopenharmony_ci netdev_dbg(priv->ndev, "drate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", 12148c2ecf20Sopenharmony_ci brp, sjw, tseg1, tseg2); 12158c2ecf20Sopenharmony_ci } else { 12168c2ecf20Sopenharmony_ci /* Classical CAN only mode */ 12178c2ecf20Sopenharmony_ci cfg = (RCANFD_CFG_TSEG1(tseg1) | RCANFD_CFG_BRP(brp) | 12188c2ecf20Sopenharmony_ci RCANFD_CFG_SJW(sjw) | RCANFD_CFG_TSEG2(tseg2)); 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_CCFG(ch), cfg); 12218c2ecf20Sopenharmony_ci netdev_dbg(priv->ndev, 12228c2ecf20Sopenharmony_ci "rate: brp %u, sjw %u, tseg1 %u, tseg2 %u\n", 12238c2ecf20Sopenharmony_ci brp, sjw, tseg1, tseg2); 12248c2ecf20Sopenharmony_ci } 12258c2ecf20Sopenharmony_ci} 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_cistatic int rcar_canfd_start(struct net_device *ndev) 12288c2ecf20Sopenharmony_ci{ 12298c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 12308c2ecf20Sopenharmony_ci int err = -EOPNOTSUPP; 12318c2ecf20Sopenharmony_ci u32 sts, ch = priv->channel; 12328c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci rcar_canfd_set_bittiming(ndev); 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci rcar_canfd_enable_channel_interrupts(priv); 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci /* Set channel to Operational mode */ 12398c2ecf20Sopenharmony_ci rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch), 12408c2ecf20Sopenharmony_ci RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_COPM); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* Verify channel mode change */ 12438c2ecf20Sopenharmony_ci err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts, 12448c2ecf20Sopenharmony_ci (sts & RCANFD_CSTS_COMSTS), 2, 500000); 12458c2ecf20Sopenharmony_ci if (err) { 12468c2ecf20Sopenharmony_ci netdev_err(ndev, "channel %u communication state failed\n", ch); 12478c2ecf20Sopenharmony_ci goto fail_mode_change; 12488c2ecf20Sopenharmony_ci } 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_ci /* Enable Common & Rx FIFO */ 12518c2ecf20Sopenharmony_ci rcar_canfd_set_bit(priv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), 12528c2ecf20Sopenharmony_ci RCANFD_CFCC_CFE); 12538c2ecf20Sopenharmony_ci rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), RCANFD_RFCC_RFE); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ci priv->can.state = CAN_STATE_ERROR_ACTIVE; 12568c2ecf20Sopenharmony_ci return 0; 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_cifail_mode_change: 12598c2ecf20Sopenharmony_ci rcar_canfd_disable_channel_interrupts(priv); 12608c2ecf20Sopenharmony_ci return err; 12618c2ecf20Sopenharmony_ci} 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_cistatic int rcar_canfd_open(struct net_device *ndev) 12648c2ecf20Sopenharmony_ci{ 12658c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 12668c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = priv->gpriv; 12678c2ecf20Sopenharmony_ci int err; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci /* Peripheral clock is already enabled in probe */ 12708c2ecf20Sopenharmony_ci err = clk_prepare_enable(gpriv->can_clk); 12718c2ecf20Sopenharmony_ci if (err) { 12728c2ecf20Sopenharmony_ci netdev_err(ndev, "failed to enable CAN clock, error %d\n", err); 12738c2ecf20Sopenharmony_ci goto out_clock; 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci err = open_candev(ndev); 12778c2ecf20Sopenharmony_ci if (err) { 12788c2ecf20Sopenharmony_ci netdev_err(ndev, "open_candev() failed, error %d\n", err); 12798c2ecf20Sopenharmony_ci goto out_can_clock; 12808c2ecf20Sopenharmony_ci } 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_ci napi_enable(&priv->napi); 12838c2ecf20Sopenharmony_ci err = rcar_canfd_start(ndev); 12848c2ecf20Sopenharmony_ci if (err) 12858c2ecf20Sopenharmony_ci goto out_close; 12868c2ecf20Sopenharmony_ci netif_start_queue(ndev); 12878c2ecf20Sopenharmony_ci can_led_event(ndev, CAN_LED_EVENT_OPEN); 12888c2ecf20Sopenharmony_ci return 0; 12898c2ecf20Sopenharmony_ciout_close: 12908c2ecf20Sopenharmony_ci napi_disable(&priv->napi); 12918c2ecf20Sopenharmony_ci close_candev(ndev); 12928c2ecf20Sopenharmony_ciout_can_clock: 12938c2ecf20Sopenharmony_ci clk_disable_unprepare(gpriv->can_clk); 12948c2ecf20Sopenharmony_ciout_clock: 12958c2ecf20Sopenharmony_ci return err; 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic void rcar_canfd_stop(struct net_device *ndev) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 13018c2ecf20Sopenharmony_ci int err; 13028c2ecf20Sopenharmony_ci u32 sts, ch = priv->channel; 13038c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci /* Transition to channel reset mode */ 13068c2ecf20Sopenharmony_ci rcar_canfd_update_bit(priv->base, RCANFD_CCTR(ch), 13078c2ecf20Sopenharmony_ci RCANFD_CCTR_CHMDC_MASK, RCANFD_CCTR_CHDMC_CRESET); 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci /* Check Channel reset mode */ 13108c2ecf20Sopenharmony_ci err = readl_poll_timeout((priv->base + RCANFD_CSTS(ch)), sts, 13118c2ecf20Sopenharmony_ci (sts & RCANFD_CSTS_CRSTSTS), 2, 500000); 13128c2ecf20Sopenharmony_ci if (err) 13138c2ecf20Sopenharmony_ci netdev_err(ndev, "channel %u reset failed\n", ch); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci rcar_canfd_disable_channel_interrupts(priv); 13168c2ecf20Sopenharmony_ci 13178c2ecf20Sopenharmony_ci /* Disable Common & Rx FIFO */ 13188c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(priv->base, RCANFD_CFCC(ch, RCANFD_CFFIFO_IDX), 13198c2ecf20Sopenharmony_ci RCANFD_CFCC_CFE); 13208c2ecf20Sopenharmony_ci rcar_canfd_clear_bit(priv->base, RCANFD_RFCC(ridx), RCANFD_RFCC_RFE); 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci /* Set the state as STOPPED */ 13238c2ecf20Sopenharmony_ci priv->can.state = CAN_STATE_STOPPED; 13248c2ecf20Sopenharmony_ci} 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_cistatic int rcar_canfd_close(struct net_device *ndev) 13278c2ecf20Sopenharmony_ci{ 13288c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 13298c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = priv->gpriv; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci netif_stop_queue(ndev); 13328c2ecf20Sopenharmony_ci rcar_canfd_stop(ndev); 13338c2ecf20Sopenharmony_ci napi_disable(&priv->napi); 13348c2ecf20Sopenharmony_ci clk_disable_unprepare(gpriv->can_clk); 13358c2ecf20Sopenharmony_ci close_candev(ndev); 13368c2ecf20Sopenharmony_ci can_led_event(ndev, CAN_LED_EVENT_STOP); 13378c2ecf20Sopenharmony_ci return 0; 13388c2ecf20Sopenharmony_ci} 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_cistatic netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb, 13418c2ecf20Sopenharmony_ci struct net_device *ndev) 13428c2ecf20Sopenharmony_ci{ 13438c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(ndev); 13448c2ecf20Sopenharmony_ci struct canfd_frame *cf = (struct canfd_frame *)skb->data; 13458c2ecf20Sopenharmony_ci u32 sts = 0, id, dlc; 13468c2ecf20Sopenharmony_ci unsigned long flags; 13478c2ecf20Sopenharmony_ci u32 ch = priv->channel; 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci if (can_dropped_invalid_skb(ndev, skb)) 13508c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 13518c2ecf20Sopenharmony_ci 13528c2ecf20Sopenharmony_ci if (cf->can_id & CAN_EFF_FLAG) { 13538c2ecf20Sopenharmony_ci id = cf->can_id & CAN_EFF_MASK; 13548c2ecf20Sopenharmony_ci id |= RCANFD_CFID_CFIDE; 13558c2ecf20Sopenharmony_ci } else { 13568c2ecf20Sopenharmony_ci id = cf->can_id & CAN_SFF_MASK; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci if (cf->can_id & CAN_RTR_FLAG) 13608c2ecf20Sopenharmony_ci id |= RCANFD_CFID_CFRTR; 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci dlc = RCANFD_CFPTR_CFDLC(can_len2dlc(cf->len)); 13638c2ecf20Sopenharmony_ci 13648c2ecf20Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { 13658c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 13668c2ecf20Sopenharmony_ci RCANFD_F_CFID(ch, RCANFD_CFFIFO_IDX), id); 13678c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 13688c2ecf20Sopenharmony_ci RCANFD_F_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc); 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci if (can_is_canfd_skb(skb)) { 13718c2ecf20Sopenharmony_ci /* CAN FD frame format */ 13728c2ecf20Sopenharmony_ci sts |= RCANFD_CFFDCSTS_CFFDF; 13738c2ecf20Sopenharmony_ci if (cf->flags & CANFD_BRS) 13748c2ecf20Sopenharmony_ci sts |= RCANFD_CFFDCSTS_CFBRS; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci if (priv->can.state == CAN_STATE_ERROR_PASSIVE) 13778c2ecf20Sopenharmony_ci sts |= RCANFD_CFFDCSTS_CFESI; 13788c2ecf20Sopenharmony_ci } 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 13818c2ecf20Sopenharmony_ci RCANFD_F_CFFDCSTS(ch, RCANFD_CFFIFO_IDX), sts); 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_ci rcar_canfd_put_data(priv, cf, 13848c2ecf20Sopenharmony_ci RCANFD_F_CFDF(ch, RCANFD_CFFIFO_IDX, 0)); 13858c2ecf20Sopenharmony_ci } else { 13868c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 13878c2ecf20Sopenharmony_ci RCANFD_C_CFID(ch, RCANFD_CFFIFO_IDX), id); 13888c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 13898c2ecf20Sopenharmony_ci RCANFD_C_CFPTR(ch, RCANFD_CFFIFO_IDX), dlc); 13908c2ecf20Sopenharmony_ci rcar_canfd_put_data(priv, cf, 13918c2ecf20Sopenharmony_ci RCANFD_C_CFDF(ch, RCANFD_CFFIFO_IDX, 0)); 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len; 13958c2ecf20Sopenharmony_ci can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci spin_lock_irqsave(&priv->tx_lock, flags); 13988c2ecf20Sopenharmony_ci priv->tx_head++; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci /* Stop the queue if we've filled all FIFO entries */ 14018c2ecf20Sopenharmony_ci if (priv->tx_head - priv->tx_tail >= RCANFD_FIFO_DEPTH) 14028c2ecf20Sopenharmony_ci netif_stop_queue(ndev); 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci /* Start Tx: Write 0xff to CFPC to increment the CPU-side 14058c2ecf20Sopenharmony_ci * pointer for the Common FIFO 14068c2ecf20Sopenharmony_ci */ 14078c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, 14088c2ecf20Sopenharmony_ci RCANFD_CFPCTR(ch, RCANFD_CFFIFO_IDX), 0xff); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&priv->tx_lock, flags); 14118c2ecf20Sopenharmony_ci return NETDEV_TX_OK; 14128c2ecf20Sopenharmony_ci} 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_cistatic void rcar_canfd_rx_pkt(struct rcar_canfd_channel *priv) 14158c2ecf20Sopenharmony_ci{ 14168c2ecf20Sopenharmony_ci struct net_device_stats *stats = &priv->ndev->stats; 14178c2ecf20Sopenharmony_ci struct canfd_frame *cf; 14188c2ecf20Sopenharmony_ci struct sk_buff *skb; 14198c2ecf20Sopenharmony_ci u32 sts = 0, id, dlc; 14208c2ecf20Sopenharmony_ci u32 ch = priv->channel; 14218c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { 14248c2ecf20Sopenharmony_ci id = rcar_canfd_read(priv->base, RCANFD_F_RFID(ridx)); 14258c2ecf20Sopenharmony_ci dlc = rcar_canfd_read(priv->base, RCANFD_F_RFPTR(ridx)); 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, RCANFD_F_RFFDSTS(ridx)); 14288c2ecf20Sopenharmony_ci if (sts & RCANFD_RFFDSTS_RFFDF) 14298c2ecf20Sopenharmony_ci skb = alloc_canfd_skb(priv->ndev, &cf); 14308c2ecf20Sopenharmony_ci else 14318c2ecf20Sopenharmony_ci skb = alloc_can_skb(priv->ndev, 14328c2ecf20Sopenharmony_ci (struct can_frame **)&cf); 14338c2ecf20Sopenharmony_ci } else { 14348c2ecf20Sopenharmony_ci id = rcar_canfd_read(priv->base, RCANFD_C_RFID(ridx)); 14358c2ecf20Sopenharmony_ci dlc = rcar_canfd_read(priv->base, RCANFD_C_RFPTR(ridx)); 14368c2ecf20Sopenharmony_ci skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cf); 14378c2ecf20Sopenharmony_ci } 14388c2ecf20Sopenharmony_ci 14398c2ecf20Sopenharmony_ci if (!skb) { 14408c2ecf20Sopenharmony_ci stats->rx_dropped++; 14418c2ecf20Sopenharmony_ci return; 14428c2ecf20Sopenharmony_ci } 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci if (id & RCANFD_RFID_RFIDE) 14458c2ecf20Sopenharmony_ci cf->can_id = (id & CAN_EFF_MASK) | CAN_EFF_FLAG; 14468c2ecf20Sopenharmony_ci else 14478c2ecf20Sopenharmony_ci cf->can_id = id & CAN_SFF_MASK; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci if (priv->can.ctrlmode & CAN_CTRLMODE_FD) { 14508c2ecf20Sopenharmony_ci if (sts & RCANFD_RFFDSTS_RFFDF) 14518c2ecf20Sopenharmony_ci cf->len = can_dlc2len(RCANFD_RFPTR_RFDLC(dlc)); 14528c2ecf20Sopenharmony_ci else 14538c2ecf20Sopenharmony_ci cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(dlc)); 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci if (sts & RCANFD_RFFDSTS_RFESI) { 14568c2ecf20Sopenharmony_ci cf->flags |= CANFD_ESI; 14578c2ecf20Sopenharmony_ci netdev_dbg(priv->ndev, "ESI Error\n"); 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci if (!(sts & RCANFD_RFFDSTS_RFFDF) && (id & RCANFD_RFID_RFRTR)) { 14618c2ecf20Sopenharmony_ci cf->can_id |= CAN_RTR_FLAG; 14628c2ecf20Sopenharmony_ci } else { 14638c2ecf20Sopenharmony_ci if (sts & RCANFD_RFFDSTS_RFBRS) 14648c2ecf20Sopenharmony_ci cf->flags |= CANFD_BRS; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci rcar_canfd_get_data(priv, cf, RCANFD_F_RFDF(ridx, 0)); 14678c2ecf20Sopenharmony_ci } 14688c2ecf20Sopenharmony_ci } else { 14698c2ecf20Sopenharmony_ci cf->len = get_can_dlc(RCANFD_RFPTR_RFDLC(dlc)); 14708c2ecf20Sopenharmony_ci if (id & RCANFD_RFID_RFRTR) 14718c2ecf20Sopenharmony_ci cf->can_id |= CAN_RTR_FLAG; 14728c2ecf20Sopenharmony_ci else 14738c2ecf20Sopenharmony_ci rcar_canfd_get_data(priv, cf, RCANFD_C_RFDF(ridx, 0)); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci /* Write 0xff to RFPC to increment the CPU-side 14778c2ecf20Sopenharmony_ci * pointer of the Rx FIFO 14788c2ecf20Sopenharmony_ci */ 14798c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_RFPCTR(ridx), 0xff); 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci can_led_event(priv->ndev, CAN_LED_EVENT_RX); 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci stats->rx_bytes += cf->len; 14848c2ecf20Sopenharmony_ci stats->rx_packets++; 14858c2ecf20Sopenharmony_ci netif_receive_skb(skb); 14868c2ecf20Sopenharmony_ci} 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_cistatic int rcar_canfd_rx_poll(struct napi_struct *napi, int quota) 14898c2ecf20Sopenharmony_ci{ 14908c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = 14918c2ecf20Sopenharmony_ci container_of(napi, struct rcar_canfd_channel, napi); 14928c2ecf20Sopenharmony_ci int num_pkts; 14938c2ecf20Sopenharmony_ci u32 sts; 14948c2ecf20Sopenharmony_ci u32 ch = priv->channel; 14958c2ecf20Sopenharmony_ci u32 ridx = ch + RCANFD_RFFIFO_IDX; 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci for (num_pkts = 0; num_pkts < quota; num_pkts++) { 14988c2ecf20Sopenharmony_ci sts = rcar_canfd_read(priv->base, RCANFD_RFSTS(ridx)); 14998c2ecf20Sopenharmony_ci /* Check FIFO empty condition */ 15008c2ecf20Sopenharmony_ci if (sts & RCANFD_RFSTS_RFEMP) 15018c2ecf20Sopenharmony_ci break; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci rcar_canfd_rx_pkt(priv); 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci /* Clear interrupt bit */ 15068c2ecf20Sopenharmony_ci if (sts & RCANFD_RFSTS_RFIF) 15078c2ecf20Sopenharmony_ci rcar_canfd_write(priv->base, RCANFD_RFSTS(ridx), 15088c2ecf20Sopenharmony_ci sts & ~RCANFD_RFSTS_RFIF); 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci /* All packets processed */ 15128c2ecf20Sopenharmony_ci if (num_pkts < quota) { 15138c2ecf20Sopenharmony_ci if (napi_complete_done(napi, num_pkts)) { 15148c2ecf20Sopenharmony_ci /* Enable Rx FIFO interrupts */ 15158c2ecf20Sopenharmony_ci rcar_canfd_set_bit(priv->base, RCANFD_RFCC(ridx), 15168c2ecf20Sopenharmony_ci RCANFD_RFCC_RFIE); 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci } 15198c2ecf20Sopenharmony_ci return num_pkts; 15208c2ecf20Sopenharmony_ci} 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_cistatic int rcar_canfd_do_set_mode(struct net_device *ndev, enum can_mode mode) 15238c2ecf20Sopenharmony_ci{ 15248c2ecf20Sopenharmony_ci int err; 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci switch (mode) { 15278c2ecf20Sopenharmony_ci case CAN_MODE_START: 15288c2ecf20Sopenharmony_ci err = rcar_canfd_start(ndev); 15298c2ecf20Sopenharmony_ci if (err) 15308c2ecf20Sopenharmony_ci return err; 15318c2ecf20Sopenharmony_ci netif_wake_queue(ndev); 15328c2ecf20Sopenharmony_ci return 0; 15338c2ecf20Sopenharmony_ci default: 15348c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 15358c2ecf20Sopenharmony_ci } 15368c2ecf20Sopenharmony_ci} 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_cistatic int rcar_canfd_get_berr_counter(const struct net_device *dev, 15398c2ecf20Sopenharmony_ci struct can_berr_counter *bec) 15408c2ecf20Sopenharmony_ci{ 15418c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = netdev_priv(dev); 15428c2ecf20Sopenharmony_ci u32 val, ch = priv->channel; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci /* Peripheral clock is already enabled in probe */ 15458c2ecf20Sopenharmony_ci val = rcar_canfd_read(priv->base, RCANFD_CSTS(ch)); 15468c2ecf20Sopenharmony_ci bec->txerr = RCANFD_CSTS_TECCNT(val); 15478c2ecf20Sopenharmony_ci bec->rxerr = RCANFD_CSTS_RECCNT(val); 15488c2ecf20Sopenharmony_ci return 0; 15498c2ecf20Sopenharmony_ci} 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_cistatic const struct net_device_ops rcar_canfd_netdev_ops = { 15528c2ecf20Sopenharmony_ci .ndo_open = rcar_canfd_open, 15538c2ecf20Sopenharmony_ci .ndo_stop = rcar_canfd_close, 15548c2ecf20Sopenharmony_ci .ndo_start_xmit = rcar_canfd_start_xmit, 15558c2ecf20Sopenharmony_ci .ndo_change_mtu = can_change_mtu, 15568c2ecf20Sopenharmony_ci}; 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_cistatic int rcar_canfd_channel_probe(struct rcar_canfd_global *gpriv, u32 ch, 15598c2ecf20Sopenharmony_ci u32 fcan_freq) 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci struct platform_device *pdev = gpriv->pdev; 15628c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv; 15638c2ecf20Sopenharmony_ci struct net_device *ndev; 15648c2ecf20Sopenharmony_ci int err = -ENODEV; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci ndev = alloc_candev(sizeof(*priv), RCANFD_FIFO_DEPTH); 15678c2ecf20Sopenharmony_ci if (!ndev) { 15688c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "alloc_candev() failed\n"); 15698c2ecf20Sopenharmony_ci err = -ENOMEM; 15708c2ecf20Sopenharmony_ci goto fail; 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci priv = netdev_priv(ndev); 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci ndev->netdev_ops = &rcar_canfd_netdev_ops; 15758c2ecf20Sopenharmony_ci ndev->flags |= IFF_ECHO; 15768c2ecf20Sopenharmony_ci priv->ndev = ndev; 15778c2ecf20Sopenharmony_ci priv->base = gpriv->base; 15788c2ecf20Sopenharmony_ci priv->channel = ch; 15798c2ecf20Sopenharmony_ci priv->can.clock.freq = fcan_freq; 15808c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "can_clk rate is %u\n", priv->can.clock.freq); 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci if (gpriv->fdmode) { 15838c2ecf20Sopenharmony_ci priv->can.bittiming_const = &rcar_canfd_nom_bittiming_const; 15848c2ecf20Sopenharmony_ci priv->can.data_bittiming_const = 15858c2ecf20Sopenharmony_ci &rcar_canfd_data_bittiming_const; 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci /* Controller starts in CAN FD only mode */ 15888c2ecf20Sopenharmony_ci can_set_static_ctrlmode(ndev, CAN_CTRLMODE_FD); 15898c2ecf20Sopenharmony_ci priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; 15908c2ecf20Sopenharmony_ci } else { 15918c2ecf20Sopenharmony_ci /* Controller starts in Classical CAN only mode */ 15928c2ecf20Sopenharmony_ci priv->can.bittiming_const = &rcar_canfd_bittiming_const; 15938c2ecf20Sopenharmony_ci priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING; 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci priv->can.do_set_mode = rcar_canfd_do_set_mode; 15978c2ecf20Sopenharmony_ci priv->can.do_get_berr_counter = rcar_canfd_get_berr_counter; 15988c2ecf20Sopenharmony_ci priv->gpriv = gpriv; 15998c2ecf20Sopenharmony_ci SET_NETDEV_DEV(ndev, &pdev->dev); 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_ci netif_napi_add(ndev, &priv->napi, rcar_canfd_rx_poll, 16028c2ecf20Sopenharmony_ci RCANFD_NAPI_WEIGHT); 16038c2ecf20Sopenharmony_ci spin_lock_init(&priv->tx_lock); 16048c2ecf20Sopenharmony_ci devm_can_led_init(ndev); 16058c2ecf20Sopenharmony_ci gpriv->ch[priv->channel] = priv; 16068c2ecf20Sopenharmony_ci err = register_candev(ndev); 16078c2ecf20Sopenharmony_ci if (err) { 16088c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 16098c2ecf20Sopenharmony_ci "register_candev() failed, error %d\n", err); 16108c2ecf20Sopenharmony_ci goto fail_candev; 16118c2ecf20Sopenharmony_ci } 16128c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "device registered (channel %u)\n", priv->channel); 16138c2ecf20Sopenharmony_ci return 0; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_cifail_candev: 16168c2ecf20Sopenharmony_ci netif_napi_del(&priv->napi); 16178c2ecf20Sopenharmony_ci free_candev(ndev); 16188c2ecf20Sopenharmony_cifail: 16198c2ecf20Sopenharmony_ci return err; 16208c2ecf20Sopenharmony_ci} 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_cistatic void rcar_canfd_channel_remove(struct rcar_canfd_global *gpriv, u32 ch) 16238c2ecf20Sopenharmony_ci{ 16248c2ecf20Sopenharmony_ci struct rcar_canfd_channel *priv = gpriv->ch[ch]; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci if (priv) { 16278c2ecf20Sopenharmony_ci unregister_candev(priv->ndev); 16288c2ecf20Sopenharmony_ci netif_napi_del(&priv->napi); 16298c2ecf20Sopenharmony_ci free_candev(priv->ndev); 16308c2ecf20Sopenharmony_ci } 16318c2ecf20Sopenharmony_ci} 16328c2ecf20Sopenharmony_ci 16338c2ecf20Sopenharmony_cistatic int rcar_canfd_probe(struct platform_device *pdev) 16348c2ecf20Sopenharmony_ci{ 16358c2ecf20Sopenharmony_ci void __iomem *addr; 16368c2ecf20Sopenharmony_ci u32 sts, ch, fcan_freq; 16378c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv; 16388c2ecf20Sopenharmony_ci struct device_node *of_child; 16398c2ecf20Sopenharmony_ci unsigned long channels_mask = 0; 16408c2ecf20Sopenharmony_ci int err, ch_irq, g_irq; 16418c2ecf20Sopenharmony_ci bool fdmode = true; /* CAN FD only mode - default */ 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci if (of_property_read_bool(pdev->dev.of_node, "renesas,no-can-fd")) 16448c2ecf20Sopenharmony_ci fdmode = false; /* Classical CAN only mode */ 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci of_child = of_get_child_by_name(pdev->dev.of_node, "channel0"); 16478c2ecf20Sopenharmony_ci if (of_child && of_device_is_available(of_child)) 16488c2ecf20Sopenharmony_ci channels_mask |= BIT(0); /* Channel 0 */ 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci of_child = of_get_child_by_name(pdev->dev.of_node, "channel1"); 16518c2ecf20Sopenharmony_ci if (of_child && of_device_is_available(of_child)) 16528c2ecf20Sopenharmony_ci channels_mask |= BIT(1); /* Channel 1 */ 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci ch_irq = platform_get_irq(pdev, 0); 16558c2ecf20Sopenharmony_ci if (ch_irq < 0) { 16568c2ecf20Sopenharmony_ci err = ch_irq; 16578c2ecf20Sopenharmony_ci goto fail_dev; 16588c2ecf20Sopenharmony_ci } 16598c2ecf20Sopenharmony_ci 16608c2ecf20Sopenharmony_ci g_irq = platform_get_irq(pdev, 1); 16618c2ecf20Sopenharmony_ci if (g_irq < 0) { 16628c2ecf20Sopenharmony_ci err = g_irq; 16638c2ecf20Sopenharmony_ci goto fail_dev; 16648c2ecf20Sopenharmony_ci } 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci /* Global controller context */ 16678c2ecf20Sopenharmony_ci gpriv = devm_kzalloc(&pdev->dev, sizeof(*gpriv), GFP_KERNEL); 16688c2ecf20Sopenharmony_ci if (!gpriv) { 16698c2ecf20Sopenharmony_ci err = -ENOMEM; 16708c2ecf20Sopenharmony_ci goto fail_dev; 16718c2ecf20Sopenharmony_ci } 16728c2ecf20Sopenharmony_ci gpriv->pdev = pdev; 16738c2ecf20Sopenharmony_ci gpriv->channels_mask = channels_mask; 16748c2ecf20Sopenharmony_ci gpriv->fdmode = fdmode; 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci /* Peripheral clock */ 16778c2ecf20Sopenharmony_ci gpriv->clkp = devm_clk_get(&pdev->dev, "fck"); 16788c2ecf20Sopenharmony_ci if (IS_ERR(gpriv->clkp)) { 16798c2ecf20Sopenharmony_ci err = PTR_ERR(gpriv->clkp); 16808c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "cannot get peripheral clock, error %d\n", 16818c2ecf20Sopenharmony_ci err); 16828c2ecf20Sopenharmony_ci goto fail_dev; 16838c2ecf20Sopenharmony_ci } 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci /* fCAN clock: Pick External clock. If not available fallback to 16868c2ecf20Sopenharmony_ci * CANFD clock 16878c2ecf20Sopenharmony_ci */ 16888c2ecf20Sopenharmony_ci gpriv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); 16898c2ecf20Sopenharmony_ci if (IS_ERR(gpriv->can_clk) || (clk_get_rate(gpriv->can_clk) == 0)) { 16908c2ecf20Sopenharmony_ci gpriv->can_clk = devm_clk_get(&pdev->dev, "canfd"); 16918c2ecf20Sopenharmony_ci if (IS_ERR(gpriv->can_clk)) { 16928c2ecf20Sopenharmony_ci err = PTR_ERR(gpriv->can_clk); 16938c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 16948c2ecf20Sopenharmony_ci "cannot get canfd clock, error %d\n", err); 16958c2ecf20Sopenharmony_ci goto fail_dev; 16968c2ecf20Sopenharmony_ci } 16978c2ecf20Sopenharmony_ci gpriv->fcan = RCANFD_CANFDCLK; 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci } else { 17008c2ecf20Sopenharmony_ci gpriv->fcan = RCANFD_EXTCLK; 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci fcan_freq = clk_get_rate(gpriv->can_clk); 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci if (gpriv->fcan == RCANFD_CANFDCLK) 17058c2ecf20Sopenharmony_ci /* CANFD clock is further divided by (1/2) within the IP */ 17068c2ecf20Sopenharmony_ci fcan_freq /= 2; 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci addr = devm_platform_ioremap_resource(pdev, 0); 17098c2ecf20Sopenharmony_ci if (IS_ERR(addr)) { 17108c2ecf20Sopenharmony_ci err = PTR_ERR(addr); 17118c2ecf20Sopenharmony_ci goto fail_dev; 17128c2ecf20Sopenharmony_ci } 17138c2ecf20Sopenharmony_ci gpriv->base = addr; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci /* Request IRQ that's common for both channels */ 17168c2ecf20Sopenharmony_ci err = devm_request_irq(&pdev->dev, ch_irq, 17178c2ecf20Sopenharmony_ci rcar_canfd_channel_interrupt, 0, 17188c2ecf20Sopenharmony_ci "canfd.chn", gpriv); 17198c2ecf20Sopenharmony_ci if (err) { 17208c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", 17218c2ecf20Sopenharmony_ci ch_irq, err); 17228c2ecf20Sopenharmony_ci goto fail_dev; 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci err = devm_request_irq(&pdev->dev, g_irq, 17258c2ecf20Sopenharmony_ci rcar_canfd_global_interrupt, 0, 17268c2ecf20Sopenharmony_ci "canfd.gbl", gpriv); 17278c2ecf20Sopenharmony_ci if (err) { 17288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "devm_request_irq(%d) failed, error %d\n", 17298c2ecf20Sopenharmony_ci g_irq, err); 17308c2ecf20Sopenharmony_ci goto fail_dev; 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci /* Enable peripheral clock for register access */ 17348c2ecf20Sopenharmony_ci err = clk_prepare_enable(gpriv->clkp); 17358c2ecf20Sopenharmony_ci if (err) { 17368c2ecf20Sopenharmony_ci dev_err(&pdev->dev, 17378c2ecf20Sopenharmony_ci "failed to enable peripheral clock, error %d\n", err); 17388c2ecf20Sopenharmony_ci goto fail_dev; 17398c2ecf20Sopenharmony_ci } 17408c2ecf20Sopenharmony_ci 17418c2ecf20Sopenharmony_ci err = rcar_canfd_reset_controller(gpriv); 17428c2ecf20Sopenharmony_ci if (err) { 17438c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "reset controller failed\n"); 17448c2ecf20Sopenharmony_ci goto fail_clk; 17458c2ecf20Sopenharmony_ci } 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci /* Controller in Global reset & Channel reset mode */ 17488c2ecf20Sopenharmony_ci rcar_canfd_configure_controller(gpriv); 17498c2ecf20Sopenharmony_ci 17508c2ecf20Sopenharmony_ci /* Configure per channel attributes */ 17518c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 17528c2ecf20Sopenharmony_ci /* Configure Channel's Rx fifo */ 17538c2ecf20Sopenharmony_ci rcar_canfd_configure_rx(gpriv, ch); 17548c2ecf20Sopenharmony_ci 17558c2ecf20Sopenharmony_ci /* Configure Channel's Tx (Common) fifo */ 17568c2ecf20Sopenharmony_ci rcar_canfd_configure_tx(gpriv, ch); 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci /* Configure receive rules */ 17598c2ecf20Sopenharmony_ci rcar_canfd_configure_afl_rules(gpriv, ch); 17608c2ecf20Sopenharmony_ci } 17618c2ecf20Sopenharmony_ci 17628c2ecf20Sopenharmony_ci /* Configure common interrupts */ 17638c2ecf20Sopenharmony_ci rcar_canfd_enable_global_interrupts(gpriv); 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci /* Start Global operation mode */ 17668c2ecf20Sopenharmony_ci rcar_canfd_update_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GMDC_MASK, 17678c2ecf20Sopenharmony_ci RCANFD_GCTR_GMDC_GOPM); 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci /* Verify mode change */ 17708c2ecf20Sopenharmony_ci err = readl_poll_timeout((gpriv->base + RCANFD_GSTS), sts, 17718c2ecf20Sopenharmony_ci !(sts & RCANFD_GSTS_GNOPM), 2, 500000); 17728c2ecf20Sopenharmony_ci if (err) { 17738c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "global operational mode failed\n"); 17748c2ecf20Sopenharmony_ci goto fail_mode; 17758c2ecf20Sopenharmony_ci } 17768c2ecf20Sopenharmony_ci 17778c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 17788c2ecf20Sopenharmony_ci err = rcar_canfd_channel_probe(gpriv, ch, fcan_freq); 17798c2ecf20Sopenharmony_ci if (err) 17808c2ecf20Sopenharmony_ci goto fail_channel; 17818c2ecf20Sopenharmony_ci } 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, gpriv); 17848c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "global operational state (clk %d, fdmode %d)\n", 17858c2ecf20Sopenharmony_ci gpriv->fcan, gpriv->fdmode); 17868c2ecf20Sopenharmony_ci return 0; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_cifail_channel: 17898c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) 17908c2ecf20Sopenharmony_ci rcar_canfd_channel_remove(gpriv, ch); 17918c2ecf20Sopenharmony_cifail_mode: 17928c2ecf20Sopenharmony_ci rcar_canfd_disable_global_interrupts(gpriv); 17938c2ecf20Sopenharmony_cifail_clk: 17948c2ecf20Sopenharmony_ci clk_disable_unprepare(gpriv->clkp); 17958c2ecf20Sopenharmony_cifail_dev: 17968c2ecf20Sopenharmony_ci return err; 17978c2ecf20Sopenharmony_ci} 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_cistatic int rcar_canfd_remove(struct platform_device *pdev) 18008c2ecf20Sopenharmony_ci{ 18018c2ecf20Sopenharmony_ci struct rcar_canfd_global *gpriv = platform_get_drvdata(pdev); 18028c2ecf20Sopenharmony_ci u32 ch; 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci rcar_canfd_reset_controller(gpriv); 18058c2ecf20Sopenharmony_ci rcar_canfd_disable_global_interrupts(gpriv); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci for_each_set_bit(ch, &gpriv->channels_mask, RCANFD_NUM_CHANNELS) { 18088c2ecf20Sopenharmony_ci rcar_canfd_disable_channel_interrupts(gpriv->ch[ch]); 18098c2ecf20Sopenharmony_ci rcar_canfd_channel_remove(gpriv, ch); 18108c2ecf20Sopenharmony_ci } 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci /* Enter global sleep mode */ 18138c2ecf20Sopenharmony_ci rcar_canfd_set_bit(gpriv->base, RCANFD_GCTR, RCANFD_GCTR_GSLPR); 18148c2ecf20Sopenharmony_ci clk_disable_unprepare(gpriv->clkp); 18158c2ecf20Sopenharmony_ci return 0; 18168c2ecf20Sopenharmony_ci} 18178c2ecf20Sopenharmony_ci 18188c2ecf20Sopenharmony_cistatic int __maybe_unused rcar_canfd_suspend(struct device *dev) 18198c2ecf20Sopenharmony_ci{ 18208c2ecf20Sopenharmony_ci return 0; 18218c2ecf20Sopenharmony_ci} 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_cistatic int __maybe_unused rcar_canfd_resume(struct device *dev) 18248c2ecf20Sopenharmony_ci{ 18258c2ecf20Sopenharmony_ci return 0; 18268c2ecf20Sopenharmony_ci} 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(rcar_canfd_pm_ops, rcar_canfd_suspend, 18298c2ecf20Sopenharmony_ci rcar_canfd_resume); 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_cistatic const struct of_device_id rcar_canfd_of_table[] = { 18328c2ecf20Sopenharmony_ci { .compatible = "renesas,rcar-gen3-canfd" }, 18338c2ecf20Sopenharmony_ci { } 18348c2ecf20Sopenharmony_ci}; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rcar_canfd_of_table); 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_cistatic struct platform_driver rcar_canfd_driver = { 18398c2ecf20Sopenharmony_ci .driver = { 18408c2ecf20Sopenharmony_ci .name = RCANFD_DRV_NAME, 18418c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rcar_canfd_of_table), 18428c2ecf20Sopenharmony_ci .pm = &rcar_canfd_pm_ops, 18438c2ecf20Sopenharmony_ci }, 18448c2ecf20Sopenharmony_ci .probe = rcar_canfd_probe, 18458c2ecf20Sopenharmony_ci .remove = rcar_canfd_remove, 18468c2ecf20Sopenharmony_ci}; 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_cimodule_platform_driver(rcar_canfd_driver); 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ciMODULE_AUTHOR("Ramesh Shanmugasundaram <ramesh.shanmugasundaram@bp.renesas.com>"); 18518c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 18528c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("CAN FD driver for Renesas R-Car SoC"); 18538c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:" RCANFD_DRV_NAME); 1854