From patchwork Wed Oct 16 10:59:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Richter X-Patchwork-Id: 21069 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f69.google.com (mail-oa0-f69.google.com [209.85.219.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id B9BAA25B8B for ; Wed, 16 Oct 2013 11:00:16 +0000 (UTC) Received: by mail-oa0-f69.google.com with SMTP id n12sf1549826oag.8 for ; Wed, 16 Oct 2013 04:00:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=mime-version:x-gm-message-state:delivered-to:sender:from:to:cc :subject:date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=r/3X2rpEZtLxsG67aRBOlfsC7b46BOQh+bVVz/vkkJc=; b=W34dUVZJk7vk/p33USpT1NQwWREVj5RgrF7v7tnCpPrM21Mzry1CQoM8vbGhqpsSXU LHWMAzlfbpefT8kZJL6sHpU1BfDWwV+LTnWSgU2HSUV9aSWSQ8rcdlaOTRlIrwrlOj8f 69pXgfILTXMCJiiS66NFYYuFCUIOiIT3c5MOufsmyzpbJa1zd14z26kIFRRPcYHphKxZ jzxqXuVBwWyj3dEo42/0X/B5JwPJhCaccEsnVX1FNFduBZ1nTzDfluA/HhAKciXrI5O0 Cz+ViJ3CXy0EsWwhfLw9bWwH5fob4aQBZ7ToZz7Z7Yzw5nKdbeKfZAPsjlcl2HdoUIy/ gFWA== X-Received: by 10.42.93.207 with SMTP id y15mr660020icm.20.1381921216194; Wed, 16 Oct 2013 04:00:16 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.16.200 with SMTP id i8ls502054qed.65.gmail; Wed, 16 Oct 2013 04:00:16 -0700 (PDT) X-Received: by 10.52.98.66 with SMTP id eg2mr1547249vdb.24.1381921216058; Wed, 16 Oct 2013 04:00:16 -0700 (PDT) Received: from mail-vb0-x22e.google.com (mail-vb0-x22e.google.com [2607:f8b0:400c:c02::22e]) by mx.google.com with ESMTPS id rl1si24514220vcb.149.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Oct 2013 04:00:16 -0700 (PDT) Received-SPF: neutral (google.com: 2607:f8b0:400c:c02::22e is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=2607:f8b0:400c:c02::22e; Received: by mail-vb0-f46.google.com with SMTP id 10so212072vbe.33 for ; Wed, 16 Oct 2013 04:00:16 -0700 (PDT) X-Gm-Message-State: ALoCoQmzMl20cgHWe5FKO2S7kJp+PNYb+K61OPwZd+TIkBD85Q5OJL/OLwzpzCC2iWiV76t/n7Bz X-Received: by 10.58.38.200 with SMTP id i8mr1813342vek.6.1381921215965; Wed, 16 Oct 2013 04:00:15 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp29656vcz; Wed, 16 Oct 2013 04:00:15 -0700 (PDT) X-Received: by 10.204.103.199 with SMTP id l7mr1900474bko.11.1381921214696; Wed, 16 Oct 2013 04:00:14 -0700 (PDT) Received: from mail-bk0-x229.google.com (mail-bk0-x229.google.com [2a00:1450:4008:c01::229]) by mx.google.com with ESMTPS id ke1si11702252bkb.65.1969.12.31.16.00.00 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Oct 2013 04:00:14 -0700 (PDT) Received-SPF: pass (google.com: domain of rric.net@gmail.com designates 2a00:1450:4008:c01::229 as permitted sender) client-ip=2a00:1450:4008:c01::229; Received: by mail-bk0-f41.google.com with SMTP id na10so209308bkb.0 for ; Wed, 16 Oct 2013 04:00:13 -0700 (PDT) X-Received: by 10.205.86.199 with SMTP id at7mr1920232bkc.9.1381921213838; Wed, 16 Oct 2013 04:00:13 -0700 (PDT) Received: from rric.localhost (f053084124.adsl.alicedsl.de. [78.53.84.124]) by mx.google.com with ESMTPSA id kk2sm46597269bkb.10.1969.12.31.16.00.00 (version=TLSv1.2 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 16 Oct 2013 04:00:13 -0700 (PDT) Sender: Robert Richter From: Robert Richter To: linux-edac@vger.kernel.org Cc: Rob Herring , linux-kernel@vger.kernel.org, Robert Richter , Robert Richter Subject: [PATCH 3/5] edac, highbank: Add Calxeda ECX-2000 support Date: Wed, 16 Oct 2013 12:59:36 +0200 Message-Id: <1381921178-28511-4-git-send-email-rric@kernel.org> X-Mailer: git-send-email 1.8.4.rc3 In-Reply-To: <1381921178-28511-1-git-send-email-rric@kernel.org> References: <1381921178-28511-1-git-send-email-rric@kernel.org> X-Original-Sender: rric.net@gmail.com X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 2607:f8b0:400c:c02::22e is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@gmail.com Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , From: Robert Richter Implement edac support for Calxeda ECX-2000. The ECX-2000 memory controller is similar to Highbank but has different register bases for error and interrupt registers. There is an own device tree name "calxeda,ecx-2000-ddr-ctrl" for identification and initialization of the ECX-2000 and its base addresses. Signed-off-by: Robert Richter Signed-off-by: Robert Richter --- drivers/edac/highbank_mc_edac.c | 105 ++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 35 deletions(-) diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c index 7a78307..79cb872 100644 --- a/drivers/edac/highbank_mc_edac.c +++ b/drivers/edac/highbank_mc_edac.c @@ -26,31 +26,40 @@ #include "edac_module.h" /* DDR Ctrlr Error Registers */ -#define HB_DDR_ECC_OPT 0x128 -#define HB_DDR_ECC_U_ERR_ADDR 0x130 -#define HB_DDR_ECC_U_ERR_STAT 0x134 -#define HB_DDR_ECC_U_ERR_DATAL 0x138 -#define HB_DDR_ECC_U_ERR_DATAH 0x13c -#define HB_DDR_ECC_C_ERR_ADDR 0x140 -#define HB_DDR_ECC_C_ERR_STAT 0x144 -#define HB_DDR_ECC_C_ERR_DATAL 0x148 -#define HB_DDR_ECC_C_ERR_DATAH 0x14c -#define HB_DDR_ECC_INT_STATUS 0x180 -#define HB_DDR_ECC_INT_ACK 0x184 -#define HB_DDR_ECC_U_ERR_ID 0x424 -#define HB_DDR_ECC_C_ERR_ID 0x428 -#define HB_DDR_ECC_INT_STAT_CE 0x8 -#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10 -#define HB_DDR_ECC_INT_STAT_UE 0x20 -#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40 +#define HB_DDR_ECC_ERR_BASE 0x128 +#define MW_DDR_ECC_ERR_BASE 0x1b4 + +#define HB_DDR_ECC_OPT 0x00 +#define HB_DDR_ECC_U_ERR_ADDR 0x08 +#define HB_DDR_ECC_U_ERR_STAT 0x0c +#define HB_DDR_ECC_U_ERR_DATAL 0x10 +#define HB_DDR_ECC_U_ERR_DATAH 0x14 +#define HB_DDR_ECC_C_ERR_ADDR 0x18 +#define HB_DDR_ECC_C_ERR_STAT 0x1c +#define HB_DDR_ECC_C_ERR_DATAL 0x20 +#define HB_DDR_ECC_C_ERR_DATAH 0x24 #define HB_DDR_ECC_OPT_MODE_MASK 0x3 #define HB_DDR_ECC_OPT_FWC 0x100 #define HB_DDR_ECC_OPT_XOR_SHIFT 16 +/* DDR Ctrlr Interrupt Registers */ + +#define HB_DDR_ECC_INT_BASE 0x180 +#define MW_DDR_ECC_INT_BASE 0x218 + +#define HB_DDR_ECC_INT_STATUS 0x00 +#define HB_DDR_ECC_INT_ACK 0x04 + +#define HB_DDR_ECC_INT_STAT_CE 0x8 +#define HB_DDR_ECC_INT_STAT_DOUBLE_CE 0x10 +#define HB_DDR_ECC_INT_STAT_UE 0x20 +#define HB_DDR_ECC_INT_STAT_DOUBLE_UE 0x40 + struct hb_mc_drvdata { - void __iomem *mc_vbase; + void __iomem *mc_err_base; + void __iomem *mc_int_base; }; static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) @@ -60,10 +69,10 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) u32 status, err_addr; /* Read the interrupt status register */ - status = readl(drvdata->mc_vbase + HB_DDR_ECC_INT_STATUS); + status = readl(drvdata->mc_int_base + HB_DDR_ECC_INT_STATUS); if (status & HB_DDR_ECC_INT_STAT_UE) { - err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_U_ERR_ADDR); + err_addr = readl(drvdata->mc_err_base + HB_DDR_ECC_U_ERR_ADDR); edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & ~PAGE_MASK, 0, @@ -71,9 +80,9 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) mci->ctl_name, ""); } if (status & HB_DDR_ECC_INT_STAT_CE) { - u32 syndrome = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_STAT); + u32 syndrome = readl(drvdata->mc_err_base + HB_DDR_ECC_C_ERR_STAT); syndrome = (syndrome >> 8) & 0xff; - err_addr = readl(drvdata->mc_vbase + HB_DDR_ECC_C_ERR_ADDR); + err_addr = readl(drvdata->mc_err_base + HB_DDR_ECC_C_ERR_ADDR); edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, err_addr >> PAGE_SHIFT, err_addr & ~PAGE_MASK, syndrome, @@ -82,7 +91,7 @@ static irqreturn_t highbank_mc_err_handler(int irq, void *dev_id) } /* clear the error, clears the interrupt */ - writel(status, drvdata->mc_vbase + HB_DDR_ECC_INT_ACK); + writel(status, drvdata->mc_int_base + HB_DDR_ECC_INT_ACK); return IRQ_HANDLED; } @@ -104,10 +113,10 @@ static ssize_t highbank_mc_err_inject_write(struct file *file, buf[buf_size] = 0; if (!kstrtou8(buf, 16, &synd)) { - reg = readl(pdata->mc_vbase + HB_DDR_ECC_OPT); + reg = readl(pdata->mc_err_base + HB_DDR_ECC_OPT); reg &= HB_DDR_ECC_OPT_MODE_MASK; reg |= (synd << HB_DDR_ECC_OPT_XOR_SHIFT) | HB_DDR_ECC_OPT_FWC; - writel(reg, pdata->mc_vbase + HB_DDR_ECC_OPT); + writel(reg, pdata->mc_err_base + HB_DDR_ECC_OPT); } return count; @@ -131,17 +140,46 @@ static void highbank_mc_create_debugfs_nodes(struct mem_ctl_info *mci) {} #endif +struct hb_mc_settings { + int err_offset; + int int_offset; +}; + +static struct hb_mc_settings hb_settings = { + .err_offset = HB_DDR_ECC_ERR_BASE, + .int_offset = HB_DDR_ECC_INT_BASE, +}; + +static struct hb_mc_settings mw_settings = { + .err_offset = MW_DDR_ECC_ERR_BASE, + .int_offset = MW_DDR_ECC_INT_BASE, +}; + +static struct of_device_id hb_ddr_ctrl_of_match[] = { + { .compatible = "calxeda,hb-ddr-ctrl", .data = &hb_settings }, + { .compatible = "calxeda,ecx-2000-ddr-ctrl", .data = &mw_settings }, + {}, +}; +MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match); + static int highbank_mc_probe(struct platform_device *pdev) { + const struct of_device_id *id; + const struct hb_mc_settings *settings; struct edac_mc_layer layers[2]; struct mem_ctl_info *mci; struct hb_mc_drvdata *drvdata; struct dimm_info *dimm; struct resource *r; + void __iomem *base; u32 control; int irq; int res = 0; + id = of_match_device(hb_ddr_ctrl_of_match, &pdev->dev); + if (!id) + return -ENODEV; + layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; layers[0].size = 1; layers[0].is_virt_csrow = true; @@ -174,15 +212,18 @@ static int highbank_mc_probe(struct platform_device *pdev) goto err; } - drvdata->mc_vbase = devm_ioremap(&pdev->dev, - r->start, resource_size(r)); - if (!drvdata->mc_vbase) { + base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); + if (!base) { dev_err(&pdev->dev, "Unable to map regs\n"); res = -ENOMEM; goto err; } - control = readl(drvdata->mc_vbase + HB_DDR_ECC_OPT) & 0x3; + settings = id->data; + drvdata->mc_err_base = base + settings->err_offset; + drvdata->mc_int_base = base + settings->int_offset; + + control = readl(drvdata->mc_err_base + HB_DDR_ECC_OPT) & 0x3; if (!control || (control == 0x2)) { dev_err(&pdev->dev, "No ECC present, or ECC disabled\n"); res = -ENODEV; @@ -238,12 +279,6 @@ static int highbank_mc_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id hb_ddr_ctrl_of_match[] = { - { .compatible = "calxeda,hb-ddr-ctrl", }, - {}, -}; -MODULE_DEVICE_TABLE(of, hb_ddr_ctrl_of_match); - static struct platform_driver highbank_mc_edac_driver = { .probe = highbank_mc_probe, .remove = highbank_mc_remove,