From patchwork Wed Jul 30 02:17:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Qiang X-Patchwork-Id: 374646 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7A4DB14017A for ; Wed, 30 Jul 2014 12:22:39 +1000 (EST) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id 3F98D1A040E for ; Wed, 30 Jul 2014 12:22:39 +1000 (EST) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1lp0144.outbound.protection.outlook.com [207.46.163.144]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 257C31A01B6 for ; Wed, 30 Jul 2014 12:22:02 +1000 (EST) Received: from BY2PR03MB348.namprd03.prod.outlook.com (10.141.139.22) by BY2PR03MB442.namprd03.prod.outlook.com (10.141.141.145) with Microsoft SMTP Server (TLS) id 15.0.995.14; Wed, 30 Jul 2014 02:21:55 +0000 Received: from CH1PR03CA003.namprd03.prod.outlook.com (10.255.156.148) by BY2PR03MB348.namprd03.prod.outlook.com (10.141.139.22) with Microsoft SMTP Server (TLS) id 15.0.990.7; Wed, 30 Jul 2014 02:21:53 +0000 Received: from BL2FFO11FD054.protection.gbl (10.255.156.132) by CH1PR03CA003.outlook.office365.com (10.255.156.148) with Microsoft SMTP Server (TLS) id 15.0.995.14 via Frontend Transport; Wed, 30 Jul 2014 02:21:52 +0000 Received: from tx30smr01.am.freescale.net (192.88.168.50) by BL2FFO11FD054.mail.protection.outlook.com (10.173.161.182) with Microsoft SMTP Server (TLS) id 15.0.990.10 via Frontend Transport; Wed, 30 Jul 2014 02:21:53 +0000 Received: from titan.ap.freescale.net ([10.192.208.233]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id s6U2LkCp024481; Tue, 29 Jul 2014 19:21:47 -0700 From: Zhao Qiang To: , , , , Subject: [PATCH v7] flexcan: add err_irq handler for flexcan Date: Wed, 30 Jul 2014 10:17:44 +0800 Message-ID: <1406686664-32716-1-git-send-email-B45475@freescale.com> X-Mailer: git-send-email 1.8.5 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:192.88.168.50; CTRY:US; IPV:CAL; IPV:NLI; EFV:NLI; SFV:NSPM; SFS:(6009001)(199002)(189002)(50466002)(80022001)(106466001)(50986999)(93916002)(68736004)(92726001)(95666004)(105606002)(31966008)(92566001)(88136002)(2201001)(83072002)(50226001)(85306003)(19580405001)(81542001)(89996001)(48376002)(19580395003)(83322001)(21056001)(74502001)(44976005)(47776003)(26826002)(97736001)(104016003)(74662001)(99396002)(102836001)(87936001)(87286001)(229853001)(84676001)(81342001)(104166001)(4396001)(62966002)(77156001)(64706001)(20776003)(107046002)(6806004)(85852003)(76482001)(36756003)(46102001)(77982001)(79102001)(42262001); DIR:OUT; SFP:; SCL:1; SRVR:BY2PR03MB348; H:tx30smr01.am.freescale.net; FPR:; MLV:ovrnspm; PTR:InfoDomainNonexistent; MX:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: BCL:0;PCL:0;RULEID: X-Forefront-PRVS: 0288CD37D9 Received-SPF: Fail (: domain of freescale.com does not designate 192.88.168.50 as permitted sender) receiver=; client-ip=192.88.168.50; helo=tx30smr01.am.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.168.50) smtp.mailfrom=qiang.zhao@freescale.com; X-Microsoft-Antispam: BCL:0;PCL:0;RULEID: X-OriginatorOrg: freescale.com Cc: Zhao Qiang X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" when flexcan is not physically linked, command 'cantest' will trigger an err_irq, add err_irq handler for it. Signed-off-by: Zhao Qiang --- Changes for v2: - use a space instead of tab - use flexcan_poll_state instead of print Changes for v3: - return IRQ_HANDLED if err is triggered - stop transmitted packets when there is an err_interrupt Changes for v4: - call flexcan_irq Changes for v5: - move err_int_handling code from flexcan_irq to flexcan_err_irq - call flexcan_err_irq from flexcan_irq Changes for v6: - move RX_IRQ handling back to flexcan_irq Changes for v7: - seperate err_irq_handling code from rx_irq_handling code and move it to err_irq_handler. drivers/net/can/flexcan.c | 73 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 16 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index f425ec2..12385f8 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -208,6 +208,7 @@ struct flexcan_priv { void __iomem *base; u32 reg_esr; u32 reg_ctrl_default; + int err_irq; struct clk *clk_ipg; struct clk *clk_per; @@ -690,6 +691,38 @@ static int flexcan_poll(struct napi_struct *napi, int quota) return work_done; } +static irqreturn_t flexcan_err_irq(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct flexcan_priv *priv = netdev_priv(dev); + struct flexcan_regs __iomem *regs = priv->base; + u32 reg_ctrl, reg_esr; + irqreturn_t ret = IRQ_NONE; + + reg_esr = flexcan_read(®s->esr); + reg_ctrl = flexcan_read(®s->ctrl); + + if (reg_esr & FLEXCAN_ESR_ALL_INT) { + flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); + ret = IRQ_HANDLED; + } + + if (reg_esr & FLEXCAN_ESR_ERR_INT) + flexcan_write(reg_ctrl & ~FLEXCAN_CTRL_ERR_MSK, ®s->ctrl); + + if ((reg_esr & FLEXCAN_ESR_ERR_STATE) || + flexcan_has_and_handle_berr(priv, reg_esr)) { + /* The error bits are cleared on read, + * save them for later use. + */ + priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; + flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, + ®s->ctrl); + napi_schedule(&priv->napi); + } + return ret; +} + static irqreturn_t flexcan_irq(int irq, void *dev_id) { struct net_device *dev = dev_id; @@ -698,11 +731,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) struct flexcan_regs __iomem *regs = priv->base; u32 reg_iflag1, reg_esr; - reg_iflag1 = flexcan_read(®s->iflag1); reg_esr = flexcan_read(®s->esr); - /* ACK all bus error and state change IRQ sources */ - if (reg_esr & FLEXCAN_ESR_ALL_INT) - flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); + reg_iflag1 = flexcan_read(®s->iflag1); + + flexcan_err_irq(irq, dev); /* * schedule NAPI in case of: @@ -710,18 +742,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) * - state change IRQ * - bus error IRQ and bus error reporting is activated */ - if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) || - (reg_esr & FLEXCAN_ESR_ERR_STATE) || - flexcan_has_and_handle_berr(priv, reg_esr)) { - /* - * The error bits are cleared on read, - * save them for later use. - */ - priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS; + if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) { flexcan_write(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->imask1); - flexcan_write(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL, - ®s->ctrl); napi_schedule(&priv->napi); } @@ -944,10 +967,17 @@ static int flexcan_open(struct net_device *dev) if (err) goto out_close; + if (priv->err_irq) { + err = request_irq(priv->err_irq, flexcan_err_irq, IRQF_SHARED, + dev->name, dev); + if (err) + goto out_free_irq; + } + /* start chip and queuing */ err = flexcan_chip_start(dev); if (err) - goto out_free_irq; + goto out_free_err_irq; can_led_event(dev, CAN_LED_EVENT_OPEN); @@ -956,6 +986,9 @@ static int flexcan_open(struct net_device *dev) return 0; + out_free_err_irq: + if (priv->err_irq) + free_irq(priv->err_irq, dev); out_free_irq: free_irq(dev->irq, dev); out_close: @@ -977,6 +1010,9 @@ static int flexcan_close(struct net_device *dev) flexcan_chip_stop(dev); free_irq(dev->irq, dev); + if (priv->err_irq) + free_irq(priv->err_irq, dev); + clk_disable_unprepare(priv->clk_per); clk_disable_unprepare(priv->clk_ipg); @@ -1099,7 +1135,7 @@ static int flexcan_probe(struct platform_device *pdev) struct resource *mem; struct clk *clk_ipg = NULL, *clk_per = NULL; void __iomem *base; - int err, irq; + int err, irq, err_irq; u32 clock_freq = 0; if (pdev->dev.of_node) @@ -1126,6 +1162,10 @@ static int flexcan_probe(struct platform_device *pdev) if (irq <= 0) return -ENODEV; + err_irq = platform_get_irq(pdev, 1); + if (err_irq <= 0) + err_irq = 0; + base = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(base)) return PTR_ERR(base); @@ -1149,6 +1189,7 @@ static int flexcan_probe(struct platform_device *pdev) dev->flags |= IFF_ECHO; priv = netdev_priv(dev); + priv->err_irq = err_irq; priv->can.clock.freq = clock_freq; priv->can.bittiming_const = &flexcan_bittiming_const; priv->can.do_set_mode = flexcan_set_mode;