From patchwork Wed Dec 5 19:28:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dan Murphy X-Patchwork-Id: 152933 Delivered-To: patch@linaro.org Received: by 2002:a2e:299d:0:0:0:0:0 with SMTP id p29-v6csp9676989ljp; Wed, 5 Dec 2018 11:28:55 -0800 (PST) X-Google-Smtp-Source: AFSGD/X+Ov9nezhHs9our1L3q6i8bAYz1uPWuZE6wLMqw0Qy+pbqN9XOoP0EInvuzC1502O/SAC4 X-Received: by 2002:a65:60c2:: with SMTP id r2mr20629232pgv.393.1544038135340; Wed, 05 Dec 2018 11:28:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544038135; cv=none; d=google.com; s=arc-20160816; b=DMWdwSjpcR9+oteQMxhWdOJtJZkNYNxEO2vQb+uAWD+KEk6wdpEf07YwO/lQmhxUPg ZwuhRvfE3mGkH/suSv+QRjwNY7S56cOaJWsUaLFEUChWM0SXgxKYPD3QNCF6VYBWKsrg gthGKAls/6TtnYZoAgbjpEHpv0v/6fyc8X4T/D8c3vE4qR6DlF6oA7Qdf976j8S3iHgl 8qcxsWpvfF9lWWByPkEYcz4UwgPSVrHgG/fvKIm0Zvcy43NDgglHQ47uJYBKIrpBJddK RbpJdKWge6Yj3y7wyk0jsEoXDF0y15SdeNIPWtAulbVcnikneF3u5uKlpn4Vdx/t/UTw dc/g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=LSXMXuerpMpMfX7bfeBfOLcxQOrAlRzVxOBjj7vjDQo=; b=olyq+DG0l3C5lMp52bJ04XroOMYMJVnXio0lIVJt1f3zYLFL5y9TwpgrlpaSop4gZA vv0rlFZQ2r85j4YZ7fsOBq1HXKIcuuwTxlQZveYvcEJ6sdwItX38SHm7/XIW04FQyOHZ VeuoVIkOiCzvLm4EK9mlIvjaCwxZXbcO39c/LzVHIpKhiPIJULN+Zmm19a7S2yJdbs96 8ZNMmuWeV+FBLuFKDQXTSqLm45LF3+puit6QWHcBi6OfvKMhhznqY3vKkx8gYLDise0x S2G7PJz4DFnoiSfcxTsEykfACLiGda/g9GeBGqH+zlHtluW9YDUL0RhmQHJd9TGQgtPY QWkg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=uz3z+fcE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d32si21274525pla.136.2018.12.05.11.28.55; Wed, 05 Dec 2018 11:28:55 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@ti.com header.s=ti-com-17Q1 header.b=uz3z+fcE; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=NONE dis=NONE) header.from=ti.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728537AbeLET2s (ORCPT + 31 others); Wed, 5 Dec 2018 14:28:48 -0500 Received: from lelv0143.ext.ti.com ([198.47.23.248]:60200 "EHLO lelv0143.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727297AbeLET2n (ORCPT ); Wed, 5 Dec 2018 14:28:43 -0500 Received: from lelv0266.itg.ti.com ([10.180.67.225]) by lelv0143.ext.ti.com (8.15.2/8.15.2) with ESMTP id wB5JSYmR100814; Wed, 5 Dec 2018 13:28:34 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ti.com; s=ti-com-17Q1; t=1544038114; bh=LSXMXuerpMpMfX7bfeBfOLcxQOrAlRzVxOBjj7vjDQo=; h=From:To:CC:Subject:Date:In-Reply-To:References; b=uz3z+fcEArMRAAVqmc0GHzY5Yglw9vCxDiTy8DUG3DOeXHs+IFFYvLJkdwFZEiIan mFX3sY7B5CI7uvTZfqnT+5EynNz7aXnbB9tI5eAG3Wae+KDK051xXHnN6XCwNLgzO/ FnmXl9ep6AeZrHE8WreWMDJrnXeUnMzCqjTRNIXM= Received: from DLEE109.ent.ti.com (dlee109.ent.ti.com [157.170.170.41]) by lelv0266.itg.ti.com (8.15.2/8.15.2) with ESMTPS id wB5JSYJg027127 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=FAIL); Wed, 5 Dec 2018 13:28:34 -0600 Received: from DLEE108.ent.ti.com (157.170.170.38) by DLEE109.ent.ti.com (157.170.170.41) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1591.10; Wed, 5 Dec 2018 13:28:33 -0600 Received: from dflp32.itg.ti.com (10.64.6.15) by DLEE108.ent.ti.com (157.170.170.38) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_RSA_WITH_AES_256_CBC_SHA) id 15.1.1591.10 via Frontend Transport; Wed, 5 Dec 2018 13:28:33 -0600 Received: from legion.dal.desgin.ti.com (legion.dal.design.ti.com [128.247.22.53]) by dflp32.itg.ti.com (8.14.3/8.13.8) with ESMTP id wB5JSXND030402; Wed, 5 Dec 2018 13:28:33 -0600 Received: from localhost (a0272616local-lt.dhcp.ti.com [172.22.72.36]) by legion.dal.desgin.ti.com (8.11.7p1+Sun/8.11.7) with ESMTP id wB5JSXU29760; Wed, 5 Dec 2018 13:28:33 -0600 (CST) From: Dan Murphy To: , , CC: , , , Dan Murphy Subject: [[RFC] PATCH v2 2/4] can: m_can: Migrate the m_can code to use the framework Date: Wed, 5 Dec 2018 13:28:23 -0600 Message-ID: <20181205192825.11555-3-dmurphy@ti.com> X-Mailer: git-send-email 2.12.2 In-Reply-To: <20181205192825.11555-1-dmurphy@ti.com> References: <20181205192825.11555-1-dmurphy@ti.com> MIME-Version: 1.0 X-EXCLAIMER-MD-CONFIG: e1e8a2fd-e40a-4ac6-ac9b-f7e9cc9ee180 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Migrate the m_can code to use the m_can_platform framework code. Signed-off-by: Dan Murphy --- drivers/net/can/m_can/Kconfig | 12 + drivers/net/can/m_can/Makefile | 4 +- drivers/net/can/m_can/m_can.c | 479 ++++++++++++++++----------------- 3 files changed, 241 insertions(+), 254 deletions(-) -- 2.20.0.rc2.7.g965798d1f2 diff --git a/drivers/net/can/m_can/Kconfig b/drivers/net/can/m_can/Kconfig index 04f20dd39007..b1a9358b7660 100644 --- a/drivers/net/can/m_can/Kconfig +++ b/drivers/net/can/m_can/Kconfig @@ -1,5 +1,17 @@ config CAN_M_CAN + tristate "Bosch M_CAN support" + ---help--- + Say Y here if you want to support for Bosch M_CAN controller. + +config CAN_M_CAN_CORE + depends on CAN_M_CAN + tristate "Bosch M_CAN Core support" + ---help--- + Say Y here if you want to support for Bosch M_CAN controller. + +config CAN_M_CAN_PLATFORM depends on HAS_IOMEM + depends on CAN_M_CAN_CORE tristate "Bosch M_CAN devices" ---help--- Say Y here if you want to support for Bosch M_CAN controller. diff --git a/drivers/net/can/m_can/Makefile b/drivers/net/can/m_can/Makefile index 8bbd7f24f5be..04f36947ac3b 100644 --- a/drivers/net/can/m_can/Makefile +++ b/drivers/net/can/m_can/Makefile @@ -2,4 +2,6 @@ # Makefile for the Bosch M_CAN controller driver. # -obj-$(CONFIG_CAN_M_CAN) += m_can.o +obj-$(CONFIG_CAN_M_CAN_CORE) += m_can.o +obj-$(CONFIG_CAN_M_CAN_PLATFORM) += m_can_platform.o +obj-$(CONFIG_CAN_M_CAN_TCAN4X5X) += tcan4x5x.o diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 9b449400376b..71b8fa9c1e70 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -28,6 +28,8 @@ #include #include +#include "m_can_platform.h" + /* napi related */ #define M_CAN_NAPI_WEIGHT 64 @@ -86,28 +88,6 @@ enum m_can_reg { M_CAN_TXEFA = 0xf8, }; -/* m_can lec values */ -enum m_can_lec_type { - LEC_NO_ERROR = 0, - LEC_STUFF_ERROR, - LEC_FORM_ERROR, - LEC_ACK_ERROR, - LEC_BIT1_ERROR, - LEC_BIT0_ERROR, - LEC_CRC_ERROR, - LEC_UNUSED, -}; - -enum m_can_mram_cfg { - MRAM_SIDF = 0, - MRAM_XIDF, - MRAM_RXF0, - MRAM_RXF1, - MRAM_RXB, - MRAM_TXE, - MRAM_TXB, - MRAM_CFG_NUM, -}; /* Core Release Register (CREL) */ #define CREL_REL_SHIFT 28 @@ -347,68 +327,100 @@ enum m_can_mram_cfg { #define TX_EVENT_MM_SHIFT TX_BUF_MM_SHIFT #define TX_EVENT_MM_MASK (0xff << TX_EVENT_MM_SHIFT) -/* address offset and element number for each FIFO/Buffer in the Message RAM */ -struct mram_cfg { - u16 off; - u8 num; -}; +static inline u32 m_can_read(const struct m_can_classdev *priv, enum m_can_reg reg) +{ + u32 ret; -/* m_can private data structure */ -struct m_can_priv { - struct can_priv can; /* must be the first member */ - struct napi_struct napi; - struct net_device *dev; - struct device *device; - struct clk *hclk; - struct clk *cclk; - void __iomem *base; - u32 irqstatus; - int version; - - /* message ram configuration */ - void __iomem *mram_base; - struct mram_cfg mcfg[MRAM_CFG_NUM]; -}; + if (priv->m_can_write) + ret = priv->m_can_read(priv, priv->reg_offset + reg); + else + ret = readl(priv->base + reg); -static inline u32 m_can_read(const struct m_can_priv *priv, enum m_can_reg reg) -{ - return readl(priv->base + reg); + return ret; } -static inline void m_can_write(const struct m_can_priv *priv, +static inline int m_can_write(const struct m_can_classdev *priv, enum m_can_reg reg, u32 val) { - writel(val, priv->base + reg); + int ret = 0; + + if (priv->m_can_write) + ret = priv->m_can_write(priv, priv->reg_offset + reg, val); + else + writel(val, priv->base + reg); + + return ret; } -static inline u32 m_can_fifo_read(const struct m_can_priv *priv, +static inline u32 m_can_fifo_read(const struct m_can_classdev *priv, u32 fgi, unsigned int offset) { - return readl(priv->mram_base + priv->mcfg[MRAM_RXF0].off + - fgi * RXF0_ELEMENT_SIZE + offset); + u32 addr_offset = priv->mcfg[MRAM_RXF0].off + fgi * RXF0_ELEMENT_SIZE + offset; + u32 read_fifo_addr; /* need to take into account iomem cases */ + u32 ret = 0; + + if (priv->mram_start) + read_fifo_addr = priv->mram_start + addr_offset; + else + read_fifo_addr = priv->mram_base + addr_offset; + + if (priv->m_can_fifo_read) + ret = priv->m_can_read(priv, read_fifo_addr); + else + ret = readl(read_fifo_addr); + + return ret; } -static inline void m_can_fifo_write(const struct m_can_priv *priv, +static inline void m_can_fifo_write(const struct m_can_classdev *priv, u32 fpi, unsigned int offset, u32 val) { - writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off + - fpi * TXB_ELEMENT_SIZE + offset); + u32 addr_offset = priv->mcfg[MRAM_TXB].off + fpi * TXB_ELEMENT_SIZE + offset; + u32 write_fifo_addr; + u32 ret; + + if (priv->mram_start) + write_fifo_addr = priv->mram_start + addr_offset; + else + write_fifo_addr = priv->mram_base + addr_offset; + + if (priv->m_can_write) + ret = priv->m_can_write(priv, write_fifo_addr, val); + else + writel(val, write_fifo_addr); + + return ret; } -static inline u32 m_can_txe_fifo_read(const struct m_can_priv *priv, +static inline u32 m_can_txe_fifo_read(const struct m_can_classdev *priv, u32 fgi, - u32 offset) { - return readl(priv->mram_base + priv->mcfg[MRAM_TXE].off + - fgi * TXE_ELEMENT_SIZE + offset); + u32 offset) +{ + u32 addr_offset = priv->mcfg[MRAM_TXE].off + fgi * TXE_ELEMENT_SIZE + offset; + u32 read_fifo_addr; + u32 ret = 0; + +printk("%s: Here\n", __func__); + if (priv->mram_start) + read_fifo_addr = priv->mram_start + addr_offset; + else + read_fifo_addr = priv->mram_base + addr_offset; + + if (priv->m_can_fifo_read) + ret = priv->m_can_read(priv, read_fifo_addr); + else + ret = readl(read_fifo_addr); + + return ret; } -static inline bool m_can_tx_fifo_full(const struct m_can_priv *priv) +static inline bool m_can_tx_fifo_full(const struct m_can_classdev *priv) { +printk("%s: Here\n", __func__); return !!(m_can_read(priv, M_CAN_TXFQS) & TXFQS_TFQF); } -static inline void m_can_config_endisable(const struct m_can_priv *priv, - bool enable) +void m_can_config_endisable(const struct m_can_classdev *priv, bool enable) { u32 cccr = m_can_read(priv, M_CAN_CCCR); u32 timeout = 10; @@ -430,7 +442,7 @@ static inline void m_can_config_endisable(const struct m_can_priv *priv, while ((m_can_read(priv, M_CAN_CCCR) & (CCCR_INIT | CCCR_CCE)) != val) { if (timeout == 0) { - netdev_warn(priv->dev, "Failed to init module\n"); + netdev_warn(priv->net, "Failed to init module\n"); return; } timeout--; @@ -438,13 +450,13 @@ static inline void m_can_config_endisable(const struct m_can_priv *priv, } } -static inline void m_can_enable_all_interrupts(const struct m_can_priv *priv) +static inline void m_can_enable_all_interrupts(const struct m_can_classdev *priv) { /* Only interrupt line 0 is used in this driver */ m_can_write(priv, M_CAN_ILE, ILE_EINT0); } -static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv) +static inline void m_can_disable_all_interrupts(const struct m_can_classdev *priv) { m_can_write(priv, M_CAN_ILE, 0x0); } @@ -452,12 +464,12 @@ static inline void m_can_disable_all_interrupts(const struct m_can_priv *priv) static void m_can_read_fifo(struct net_device *dev, u32 rxfs) { struct net_device_stats *stats = &dev->stats; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct canfd_frame *cf; struct sk_buff *skb; u32 id, fgi, dlc; int i; - +printk("%s: Here\n", __func__); /* calculate the fifo get index for where to read data */ fgi = (rxfs & RXFS_FGI_MASK) >> RXFS_FGI_SHIFT; dlc = m_can_fifo_read(priv, fgi, M_CAN_FIFO_DLC); @@ -509,10 +521,10 @@ static void m_can_read_fifo(struct net_device *dev, u32 rxfs) static int m_can_do_rx_poll(struct net_device *dev, int quota) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); u32 pkts = 0; u32 rxfs; - +printk("%s: Here\n", __func__); rxfs = m_can_read(priv, M_CAN_RXF0S); if (!(rxfs & RXFS_FFL_MASK)) { netdev_dbg(dev, "no messages in fifo0\n"); @@ -541,7 +553,7 @@ static int m_can_handle_lost_msg(struct net_device *dev) struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; struct can_frame *frame; - +printk("%s: Here\n", __func__); netdev_err(dev, "msg lost in rxf0\n"); stats->rx_errors++; @@ -562,11 +574,11 @@ static int m_can_handle_lost_msg(struct net_device *dev) static int m_can_handle_lec_err(struct net_device *dev, enum m_can_lec_type lec_type) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; - +printk("%s: Here\n", __func__); priv->can.can_stats.bus_error++; stats->rx_errors++; @@ -619,7 +631,7 @@ static int m_can_handle_lec_err(struct net_device *dev, static int __m_can_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); unsigned int ecr; ecr = m_can_read(priv, M_CAN_ECR); @@ -629,28 +641,32 @@ static int __m_can_get_berr_counter(const struct net_device *dev, return 0; } -static int m_can_clk_start(struct m_can_priv *priv) +static int m_can_clk_start(struct m_can_classdev *priv) { int err; - err = pm_runtime_get_sync(priv->device); + if (priv->pm_clock_support == 0) + return 0; + + err = pm_runtime_get_sync(priv->dev); if (err < 0) { - pm_runtime_put_noidle(priv->device); + pm_runtime_put_noidle(priv->dev); return err; } return 0; } -static void m_can_clk_stop(struct m_can_priv *priv) +static void m_can_clk_stop(struct m_can_classdev *priv) { - pm_runtime_put_sync(priv->device); + if (priv->pm_clock_support) + pm_runtime_put_sync(priv->dev); } static int m_can_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); int err; err = m_can_clk_start(priv); @@ -667,7 +683,7 @@ static int m_can_get_berr_counter(const struct net_device *dev, static int m_can_handle_state_change(struct net_device *dev, enum can_state new_state) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf; struct sk_buff *skb; @@ -741,7 +757,7 @@ static int m_can_handle_state_change(struct net_device *dev, static int m_can_handle_state_errors(struct net_device *dev, u32 psr) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); int work_done = 0; if ((psr & PSR_EW) && @@ -794,7 +810,7 @@ static inline bool is_lec_err(u32 psr) static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, u32 psr) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); int work_done = 0; if (irqstatus & IR_RF0L) @@ -814,7 +830,7 @@ static int m_can_handle_bus_errors(struct net_device *dev, u32 irqstatus, static int m_can_poll(struct napi_struct *napi, int quota) { struct net_device *dev = napi->dev; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); int work_done = 0; u32 irqstatus, psr; @@ -849,7 +865,7 @@ static void m_can_echo_tx_event(struct net_device *dev) int i = 0; unsigned int msg_mark; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; /* read tx event fifo status */ @@ -882,7 +898,7 @@ static void m_can_echo_tx_event(struct net_device *dev) static irqreturn_t m_can_isr(int irq, void *dev_id) { struct net_device *dev = (struct net_device *)dev_id; - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; u32 ir; @@ -977,7 +993,7 @@ static const struct can_bittiming_const m_can_data_bittiming_const_31X = { static int m_can_set_bittiming(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *dbt = &priv->can.data_bittiming; u16 brp, sjw, tseg1, tseg2; @@ -1050,7 +1066,7 @@ static int m_can_set_bittiming(struct net_device *dev) */ static void m_can_chip_config(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); u32 cccr, test; m_can_config_endisable(priv, true); @@ -1150,17 +1166,17 @@ static void m_can_chip_config(struct net_device *dev) /* route all interrupts to INT0 */ m_can_write(priv, M_CAN_ILS, ILS_ALL_INT0); - +printk("%s: Bit timing\n", __func__); /* set bittiming params */ m_can_set_bittiming(dev); - +printk("%s: out\n", __func__); m_can_config_endisable(priv, false); } static void m_can_start(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); - + struct m_can_classdev *priv = netdev_priv(dev); +printk("%s: Hear\n", __func__); /* basic m_can configuration */ m_can_chip_config(dev); @@ -1171,6 +1187,7 @@ static void m_can_start(struct net_device *dev) static int m_can_set_mode(struct net_device *dev, enum can_mode mode) { +printk("%s: Hear\n", __func__); switch (mode) { case CAN_MODE_START: m_can_start(dev); @@ -1188,20 +1205,17 @@ static int m_can_set_mode(struct net_device *dev, enum can_mode mode) * else it returns the release and step coded as: * return value = 10 * + 1 * */ -static int m_can_check_core_release(void __iomem *m_can_base) +static int m_can_check_core_release(struct m_can_classdev *priv) { u32 crel_reg; u8 rel; u8 step; int res; - struct m_can_priv temp_priv = { - .base = m_can_base - }; /* Read Core Release Version and split into version number * Example: Version 3.2.1 => rel = 3; step = 2; substep = 1; */ - crel_reg = m_can_read(&temp_priv, M_CAN_CREL); + crel_reg = m_can_read(priv, M_CAN_CREL); rel = (u8)((crel_reg & CREL_REL_MASK) >> CREL_REL_SHIFT); step = (u8)((crel_reg & CREL_STEP_MASK) >> CREL_STEP_SHIFT); @@ -1219,86 +1233,84 @@ static int m_can_check_core_release(void __iomem *m_can_base) /* Selectable Non ISO support only in version 3.2.x * This function checks if the bit is writable. */ -static bool m_can_niso_supported(const struct m_can_priv *priv) +static bool m_can_niso_supported(const struct m_can_classdev *priv) { u32 cccr_reg, cccr_poll; - int niso_timeout; + int niso_timeout = 0; m_can_config_endisable(priv, true); cccr_reg = m_can_read(priv, M_CAN_CCCR); cccr_reg |= CCCR_NISO; m_can_write(priv, M_CAN_CCCR, cccr_reg); - - niso_timeout = readl_poll_timeout((priv->base + M_CAN_CCCR), cccr_poll, - (cccr_poll == cccr_reg), 0, 10); +printk("%s: Fix readl poll timeout\n", __func__); +/* niso_timeout = readl_poll_timeout((priv->base + M_CAN_CCCR), cccr_poll, + (cccr_poll == cccr_reg), 0, 10);*/ /* Clear NISO */ cccr_reg &= ~(CCCR_NISO); m_can_write(priv, M_CAN_CCCR, cccr_reg); m_can_config_endisable(priv, false); - +printk("%s: out\n", __func__); /* return false if time out (-ETIMEDOUT), else return true */ return !niso_timeout; } -static int m_can_dev_setup(struct platform_device *pdev, struct net_device *dev, - void __iomem *addr) +static int m_can_dev_setup(struct net_device *dev) { - struct m_can_priv *priv; + struct m_can_classdev *m_can_dev; int m_can_version; - m_can_version = m_can_check_core_release(addr); + m_can_dev = netdev_priv(dev); + + m_can_version = m_can_check_core_release(m_can_dev); /* return if unsupported version */ if (!m_can_version) { - dev_err(&pdev->dev, "Unsupported version number: %2d", + dev_err(m_can_dev->dev, "Unsupported version number: %2d", m_can_version); return -EINVAL; } - priv = netdev_priv(dev); - netif_napi_add(dev, &priv->napi, m_can_poll, M_CAN_NAPI_WEIGHT); + netif_napi_add(dev, &m_can_dev->napi, m_can_poll, M_CAN_NAPI_WEIGHT); /* Shared properties of all M_CAN versions */ - priv->version = m_can_version; - priv->dev = dev; - priv->base = addr; - priv->can.do_set_mode = m_can_set_mode; - priv->can.do_get_berr_counter = m_can_get_berr_counter; + m_can_dev->version = m_can_version; + m_can_dev->can.do_set_mode = m_can_set_mode; + m_can_dev->can.do_get_berr_counter = m_can_get_berr_counter; /* Set M_CAN supported operations */ - priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | + m_can_dev->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_FD; /* Set properties depending on M_CAN version */ - switch (priv->version) { + switch (m_can_dev->version) { case 30: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - priv->can.bittiming_const = &m_can_bittiming_const_30X; - priv->can.data_bittiming_const = + m_can_dev->can.bittiming_const = &m_can_bittiming_const_30X; + m_can_dev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; break; case 31: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - priv->can.bittiming_const = &m_can_bittiming_const_31X; - priv->can.data_bittiming_const = + m_can_dev->can.bittiming_const = &m_can_bittiming_const_31X; + m_can_dev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; break; case 32: - priv->can.bittiming_const = &m_can_bittiming_const_31X; - priv->can.data_bittiming_const = + m_can_dev->can.bittiming_const = &m_can_bittiming_const_31X; + m_can_dev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; - priv->can.ctrlmode_supported |= (m_can_niso_supported(priv) + m_can_dev->can.ctrlmode_supported |= (m_can_niso_supported(m_can_dev) ? CAN_CTRLMODE_FD_NON_ISO : 0); break; default: - dev_err(&pdev->dev, "Unsupported version number: %2d", - priv->version); + dev_err(m_can_dev->dev, "Unsupported version number: %2d", + m_can_dev->version); return -EINVAL; } @@ -1307,7 +1319,7 @@ static int m_can_dev_setup(struct platform_device *pdev, struct net_device *dev, static int m_can_open(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); int err; err = m_can_clk_start(priv); @@ -1347,7 +1359,7 @@ static int m_can_open(struct net_device *dev) static void m_can_stop(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); /* disable all interrupts */ m_can_disable_all_interrupts(priv); @@ -1358,7 +1370,7 @@ static void m_can_stop(struct net_device *dev) static int m_can_close(struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); netif_stop_queue(dev); napi_disable(&priv->napi); @@ -1373,7 +1385,7 @@ static int m_can_close(struct net_device *dev) static int m_can_next_echo_skb_occupied(struct net_device *dev, int putidx) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); /*get wrap around for loopback skb index */ unsigned int wrap = priv->can.echo_skb_max; int next_idx; @@ -1388,7 +1400,7 @@ static int m_can_next_echo_skb_occupied(struct net_device *dev, int putidx) static netdev_tx_t m_can_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct m_can_priv *priv = netdev_priv(dev); + struct m_can_classdev *priv = netdev_priv(dev); struct canfd_frame *cf = (struct canfd_frame *)skb->data; u32 id, cccr, fdflags; int i; @@ -1515,21 +1527,7 @@ static int register_m_can_dev(struct net_device *dev) return register_candev(dev); } -static void m_can_init_ram(struct m_can_priv *priv) -{ - int end, i, start; - - /* initialize the entire Message RAM in use to avoid possible - * ECC/parity checksum errors when reading an uninitialized buffer - */ - start = priv->mcfg[MRAM_SIDF].off; - end = priv->mcfg[MRAM_TXB].off + - priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; - for (i = start; i < end; i += 4) - writel(0x0, priv->mram_base + i); -} - -static void m_can_of_parse_mram(struct m_can_priv *priv, +static void m_can_of_parse_mram(struct m_can_classdev *priv, const u32 *mram_config_vals) { priv->mcfg[MRAM_SIDF].off = mram_config_vals[0]; @@ -1556,7 +1554,7 @@ static void m_can_of_parse_mram(struct m_can_priv *priv, priv->mcfg[MRAM_TXB].num = mram_config_vals[7] & (TXBC_NDTB_MASK >> TXBC_NDTB_SHIFT); - dev_dbg(priv->device, + dev_dbg(priv->dev, "mram_base %p sidf 0x%x %d xidf 0x%x %d rxf0 0x%x %d rxf1 0x%x %d rxb 0x%x %d txe 0x%x %d txb 0x%x %d\n", priv->mram_base, priv->mcfg[MRAM_SIDF].off, priv->mcfg[MRAM_SIDF].num, @@ -1566,63 +1564,57 @@ static void m_can_of_parse_mram(struct m_can_priv *priv, priv->mcfg[MRAM_RXB].off, priv->mcfg[MRAM_RXB].num, priv->mcfg[MRAM_TXE].off, priv->mcfg[MRAM_TXE].num, priv->mcfg[MRAM_TXB].off, priv->mcfg[MRAM_TXB].num); - - m_can_init_ram(priv); } -static int m_can_plat_probe(struct platform_device *pdev) +void m_can_init_ram(struct m_can_classdev *priv) { - struct net_device *dev; - struct m_can_priv *priv; - struct resource *res; - void __iomem *addr; - void __iomem *mram_addr; - struct clk *hclk, *cclk; - int irq, ret; - struct device_node *np; - u32 mram_config_vals[MRAM_CFG_LEN]; - u32 tx_fifo_size; - - np = pdev->dev.of_node; + int end, i, start; - hclk = devm_clk_get(&pdev->dev, "hclk"); - cclk = devm_clk_get(&pdev->dev, "cclk"); + /* initialize the entire Message RAM in use to avoid possible + * ECC/parity checksum errors when reading an uninitialized buffer + */ + start = priv->mcfg[MRAM_SIDF].off; + end = priv->mcfg[MRAM_TXB].off + + priv->mcfg[MRAM_TXB].num * TXB_ELEMENT_SIZE; - if (IS_ERR(hclk) || IS_ERR(cclk)) { - dev_err(&pdev->dev, "no clock found\n"); - ret = -ENODEV; - goto failed_ret; + for (i = start; i < end; i += 4) { + if (priv->mram_start) + m_can_write(priv, priv->mram_start + i, 0x0); + else + writel(0x0, priv->mram_base + i); } +} - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); - addr = devm_ioremap_resource(&pdev->dev, res); - irq = platform_get_irq_byname(pdev, "int0"); +int m_can_core_get_clocks(struct m_can_classdev *m_can_dev) +{ + int ret = 0; - if (IS_ERR(addr) || irq < 0) { - ret = -EINVAL; - goto failed_ret; - } + m_can_dev->hclk = devm_clk_get(m_can_dev->dev, "hclk"); + m_can_dev->cclk = devm_clk_get(m_can_dev->dev, "cclk"); - /* message ram could be shared */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram"); - if (!res) { + if (IS_ERR(m_can_dev->cclk)) { + dev_err(m_can_dev->dev, "no clock found\n"); ret = -ENODEV; - goto failed_ret; } - mram_addr = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!mram_addr) { - ret = -ENOMEM; - goto failed_ret; - } + return ret; +} + +struct m_can_classdev *m_can_core_allocate_dev(struct device *dev) +{ + struct m_can_classdev *class_dev = NULL; + u32 mram_config_vals[MRAM_CFG_LEN]; + struct net_device *net_dev; + u32 tx_fifo_size; + int ret; - /* get message ram configuration */ - ret = of_property_read_u32_array(np, "bosch,mram-cfg", - mram_config_vals, - sizeof(mram_config_vals) / 4); + ret = fwnode_property_read_u32_array(dev_fwnode(dev), + "bosch,mram-cfg", + mram_config_vals, + sizeof(mram_config_vals) / 4); if (ret) { - dev_err(&pdev->dev, "Could not get Message RAM configuration."); - goto failed_ret; + dev_err(dev, "Could not get Message RAM configuration."); + goto out; } /* Get TX FIFO size @@ -1631,69 +1623,76 @@ static int m_can_plat_probe(struct platform_device *pdev) tx_fifo_size = mram_config_vals[7]; /* allocate the m_can device */ - dev = alloc_candev(sizeof(*priv), tx_fifo_size); - if (!dev) { - ret = -ENOMEM; - goto failed_ret; + net_dev = alloc_candev(sizeof(*class_dev), tx_fifo_size); + if (!net_dev) { + dev_err(dev, "Failed to allocate CAN device"); + goto out; } - priv = netdev_priv(dev); - dev->irq = irq; - priv->device = &pdev->dev; - priv->hclk = hclk; - priv->cclk = cclk; - priv->can.clock.freq = clk_get_rate(cclk); - priv->mram_base = mram_addr; + class_dev = netdev_priv(net_dev); + if (!class_dev) { + dev_err(dev, "Failed to init netdev private"); + goto out; + } - platform_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); + class_dev->net = net_dev; + class_dev->dev = dev; + SET_NETDEV_DEV(net_dev, dev); - /* Enable clocks. Necessary to read Core Release in order to determine - * M_CAN version - */ - pm_runtime_enable(&pdev->dev); - ret = m_can_clk_start(priv); - if (ret) - goto pm_runtime_fail; + m_can_of_parse_mram(class_dev, mram_config_vals); +out: + return class_dev; +} + +int m_can_core_register(struct m_can_classdev *m_can_dev) +{ + int ret; - ret = m_can_dev_setup(pdev, dev, addr); + if (m_can_dev->pm_clock_support) { + pm_runtime_enable(m_can_dev->dev); + ret = m_can_clk_start(m_can_dev); + if (ret) + goto pm_runtime_fail; + } + + ret = m_can_dev_setup(m_can_dev->net); if (ret) goto clk_disable; - ret = register_m_can_dev(dev); + ret = register_m_can_dev(m_can_dev->net); if (ret) { - dev_err(&pdev->dev, "registering %s failed (err=%d)\n", - KBUILD_MODNAME, ret); + dev_err(m_can_dev->dev, "registering %s failed (err=%d)\n", + m_can_dev->net->name, ret); goto clk_disable; } - m_can_of_parse_mram(priv, mram_config_vals); + devm_can_led_init(m_can_dev->net); - devm_can_led_init(dev); + of_can_transceiver(m_can_dev->net); - of_can_transceiver(dev); + dev_info(m_can_dev->dev, "%s device registered (irq=%d, version=%d)\n", + KBUILD_MODNAME, m_can_dev->net->irq, m_can_dev->version); - dev_info(&pdev->dev, "%s device registered (irq=%d, version=%d)\n", - KBUILD_MODNAME, dev->irq, priv->version); + m_can_set_bittiming(m_can_dev->net); /* Probe finished * Stop clocks. They will be reactivated once the M_CAN device is opened */ clk_disable: - m_can_clk_stop(priv); + m_can_clk_stop(m_can_dev); pm_runtime_fail: if (ret) { - pm_runtime_disable(&pdev->dev); - free_candev(dev); + pm_runtime_disable(m_can_dev->dev); + free_candev(m_can_dev->net); } -failed_ret: + return ret; } -static __maybe_unused int m_can_suspend(struct device *dev) +int m_can_core_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *priv = netdev_priv(ndev); if (netif_running(ndev)) { netif_stop_queue(ndev); @@ -1709,10 +1708,10 @@ static __maybe_unused int m_can_suspend(struct device *dev) return 0; } -static __maybe_unused int m_can_resume(struct device *dev) +int m_can_core_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *priv = netdev_priv(ndev); pinctrl_pm_select_default_state(dev); @@ -1747,8 +1746,6 @@ static int m_can_plat_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); - free_candev(dev); return 0; @@ -1757,7 +1754,7 @@ static int m_can_plat_remove(struct platform_device *pdev) static int __maybe_unused m_can_runtime_suspend(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *priv = netdev_priv(ndev); clk_disable_unprepare(priv->cclk); clk_disable_unprepare(priv->hclk); @@ -1768,7 +1765,7 @@ static int __maybe_unused m_can_runtime_suspend(struct device *dev) static int __maybe_unused m_can_runtime_resume(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); - struct m_can_priv *priv = netdev_priv(ndev); + struct m_can_classdev *priv = netdev_priv(ndev); int err; err = clk_prepare_enable(priv->hclk); @@ -1782,30 +1779,6 @@ static int __maybe_unused m_can_runtime_resume(struct device *dev) return err; } -static const struct dev_pm_ops m_can_pmops = { - SET_RUNTIME_PM_OPS(m_can_runtime_suspend, - m_can_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(m_can_suspend, m_can_resume) -}; - -static const struct of_device_id m_can_of_table[] = { - { .compatible = "bosch,m_can", .data = NULL }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(of, m_can_of_table); - -static struct platform_driver m_can_plat_driver = { - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = m_can_of_table, - .pm = &m_can_pmops, - }, - .probe = m_can_plat_probe, - .remove = m_can_plat_remove, -}; - -module_platform_driver(m_can_plat_driver); - MODULE_AUTHOR("Dong Aisheng "); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("CAN bus driver for Bosch M_CAN controller");