brintos

brintos / linux-shallow public Read only

0
0
Text · 8.4 KiB · 29723c9 Raw
337 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/4 *5 * Texas Instruments DDR3 ECC error correction and detection driver6 *7 * This program is free software; you can redistribute it and/or modify it8 * under the terms and conditions of the GNU General Public License,9 * version 2, as published by the Free Software Foundation.10 *11 * This program is distributed in the hope it will be useful, but WITHOUT12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for14 * more details.15 *16 * You should have received a copy of the GNU General Public License along with17 * this program.  If not, see <http://www.gnu.org/licenses/>.18 */19 20#include <linux/init.h>21#include <linux/edac.h>22#include <linux/io.h>23#include <linux/interrupt.h>24#include <linux/of_address.h>25#include <linux/of_device.h>26#include <linux/module.h>27 28#include "edac_module.h"29 30/* EMIF controller registers */31#define EMIF_SDRAM_CONFIG		0x00832#define EMIF_IRQ_STATUS			0x0ac33#define EMIF_IRQ_ENABLE_SET		0x0b434#define EMIF_ECC_CTRL			0x11035#define EMIF_1B_ECC_ERR_CNT		0x13036#define EMIF_1B_ECC_ERR_THRSH		0x13437#define EMIF_1B_ECC_ERR_ADDR_LOG	0x13c38#define EMIF_2B_ECC_ERR_ADDR_LOG	0x14039 40/* Bit definitions for EMIF_SDRAM_CONFIG */41#define SDRAM_TYPE_SHIFT		2942#define SDRAM_TYPE_MASK			GENMASK(31, 29)43#define SDRAM_TYPE_DDR3			(3 << SDRAM_TYPE_SHIFT)44#define SDRAM_TYPE_DDR2			(2 << SDRAM_TYPE_SHIFT)45#define SDRAM_NARROW_MODE_MASK		GENMASK(15, 14)46#define SDRAM_K2_NARROW_MODE_SHIFT	1247#define SDRAM_K2_NARROW_MODE_MASK	GENMASK(13, 12)48#define SDRAM_ROWSIZE_SHIFT		749#define SDRAM_ROWSIZE_MASK		GENMASK(9, 7)50#define SDRAM_IBANK_SHIFT		451#define SDRAM_IBANK_MASK		GENMASK(6, 4)52#define SDRAM_K2_IBANK_SHIFT		553#define SDRAM_K2_IBANK_MASK		GENMASK(6, 5)54#define SDRAM_K2_EBANK_SHIFT		355#define SDRAM_K2_EBANK_MASK		BIT(SDRAM_K2_EBANK_SHIFT)56#define SDRAM_PAGESIZE_SHIFT		057#define SDRAM_PAGESIZE_MASK		GENMASK(2, 0)58#define SDRAM_K2_PAGESIZE_SHIFT		059#define SDRAM_K2_PAGESIZE_MASK		GENMASK(1, 0)60 61#define EMIF_1B_ECC_ERR_THRSH_SHIFT	2462 63/* IRQ bit definitions */64#define EMIF_1B_ECC_ERR			BIT(5)65#define EMIF_2B_ECC_ERR			BIT(4)66#define EMIF_WR_ECC_ERR			BIT(3)67#define EMIF_SYS_ERR			BIT(0)68/* Bit 31 enables ECC and 28 enables RMW */69#define ECC_ENABLED			(BIT(31) | BIT(28))70 71#define EDAC_MOD_NAME			"ti-emif-edac"72 73enum {74	EMIF_TYPE_DRA7,75	EMIF_TYPE_K276};77 78struct ti_edac {79	void __iomem *reg;80};81 82static u32 ti_edac_readl(struct ti_edac *edac, u16 offset)83{84	return readl_relaxed(edac->reg + offset);85}86 87static void ti_edac_writel(struct ti_edac *edac, u32 val, u16 offset)88{89	writel_relaxed(val, edac->reg + offset);90}91 92static irqreturn_t ti_edac_isr(int irq, void *data)93{94	struct mem_ctl_info *mci = data;95	struct ti_edac *edac = mci->pvt_info;96	u32 irq_status;97	u32 err_addr;98	int err_count;99 100	irq_status = ti_edac_readl(edac, EMIF_IRQ_STATUS);101 102	if (irq_status & EMIF_1B_ECC_ERR) {103		err_addr = ti_edac_readl(edac, EMIF_1B_ECC_ERR_ADDR_LOG);104		err_count = ti_edac_readl(edac, EMIF_1B_ECC_ERR_CNT);105		ti_edac_writel(edac, err_count, EMIF_1B_ECC_ERR_CNT);106		edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, err_count,107				     err_addr >> PAGE_SHIFT,108				     err_addr & ~PAGE_MASK, -1, 0, 0, 0,109				     mci->ctl_name, "1B");110	}111 112	if (irq_status & EMIF_2B_ECC_ERR) {113		err_addr = ti_edac_readl(edac, EMIF_2B_ECC_ERR_ADDR_LOG);114		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,115				     err_addr >> PAGE_SHIFT,116				     err_addr & ~PAGE_MASK, -1, 0, 0, 0,117				     mci->ctl_name, "2B");118	}119 120	if (irq_status & EMIF_WR_ECC_ERR)121		edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1,122				     0, 0, -1, 0, 0, 0,123				     mci->ctl_name, "WR");124 125	ti_edac_writel(edac, irq_status, EMIF_IRQ_STATUS);126 127	return IRQ_HANDLED;128}129 130static void ti_edac_setup_dimm(struct mem_ctl_info *mci, u32 type)131{132	struct dimm_info *dimm;133	struct ti_edac *edac = mci->pvt_info;134	int bits;135	u32 val;136	u32 memsize;137 138	dimm = edac_get_dimm(mci, 0, 0, 0);139 140	val = ti_edac_readl(edac, EMIF_SDRAM_CONFIG);141 142	if (type == EMIF_TYPE_DRA7) {143		bits = ((val & SDRAM_PAGESIZE_MASK) >> SDRAM_PAGESIZE_SHIFT) + 8;144		bits += ((val & SDRAM_ROWSIZE_MASK) >> SDRAM_ROWSIZE_SHIFT) + 9;145		bits += (val & SDRAM_IBANK_MASK) >> SDRAM_IBANK_SHIFT;146 147		if (val & SDRAM_NARROW_MODE_MASK) {148			bits++;149			dimm->dtype = DEV_X16;150		} else {151			bits += 2;152			dimm->dtype = DEV_X32;153		}154	} else {155		bits = 16;156		bits += ((val & SDRAM_K2_PAGESIZE_MASK) >>157			SDRAM_K2_PAGESIZE_SHIFT) + 8;158		bits += (val & SDRAM_K2_IBANK_MASK) >> SDRAM_K2_IBANK_SHIFT;159		bits += (val & SDRAM_K2_EBANK_MASK) >> SDRAM_K2_EBANK_SHIFT;160 161		val = (val & SDRAM_K2_NARROW_MODE_MASK) >>162			SDRAM_K2_NARROW_MODE_SHIFT;163		switch (val) {164		case 0:165			bits += 3;166			dimm->dtype = DEV_X64;167			break;168		case 1:169			bits += 2;170			dimm->dtype = DEV_X32;171			break;172		case 2:173			bits++;174			dimm->dtype = DEV_X16;175			break;176		}177	}178 179	memsize = 1 << bits;180 181	dimm->nr_pages = memsize >> PAGE_SHIFT;182	dimm->grain = 4;183	if ((val & SDRAM_TYPE_MASK) == SDRAM_TYPE_DDR2)184		dimm->mtype = MEM_DDR2;185	else186		dimm->mtype = MEM_DDR3;187 188	val = ti_edac_readl(edac, EMIF_ECC_CTRL);189	if (val & ECC_ENABLED)190		dimm->edac_mode = EDAC_SECDED;191	else192		dimm->edac_mode = EDAC_NONE;193}194 195static const struct of_device_id ti_edac_of_match[] = {196	{ .compatible = "ti,emif-keystone", .data = (void *)EMIF_TYPE_K2 },197	{ .compatible = "ti,emif-dra7xx", .data = (void *)EMIF_TYPE_DRA7 },198	{},199};200MODULE_DEVICE_TABLE(of, ti_edac_of_match);201 202static int _emif_get_id(struct device_node *node)203{204	struct device_node *np;205	const __be32 *addrp;206	u32 addr, my_addr;207	int my_id = 0;208 209	addrp = of_get_address(node, 0, NULL, NULL);210	my_addr = (u32)of_translate_address(node, addrp);211 212	for_each_matching_node(np, ti_edac_of_match) {213		if (np == node)214			continue;215 216		addrp = of_get_address(np, 0, NULL, NULL);217		addr = (u32)of_translate_address(np, addrp);218 219		edac_printk(KERN_INFO, EDAC_MOD_NAME,220			    "addr=%x, my_addr=%x\n",221			    addr, my_addr);222 223		if (addr < my_addr)224			my_id++;225	}226 227	return my_id;228}229 230static int ti_edac_probe(struct platform_device *pdev)231{232	int error_irq = 0, ret = -ENODEV;233	struct device *dev = &pdev->dev;234	struct resource *res;235	void __iomem *reg;236	struct mem_ctl_info *mci;237	struct edac_mc_layer layers[1];238	const struct of_device_id *id;239	struct ti_edac *edac;240	int emif_id;241 242	id = of_match_device(ti_edac_of_match, &pdev->dev);243	if (!id)244		return -ENODEV;245 246	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);247	reg = devm_ioremap_resource(dev, res);248	if (IS_ERR(reg))249		return PTR_ERR(reg);250 251	layers[0].type = EDAC_MC_LAYER_ALL_MEM;252	layers[0].size = 1;253 254	/* Allocate ID number for our EMIF controller */255	emif_id = _emif_get_id(pdev->dev.of_node);256	if (emif_id < 0)257		return -EINVAL;258 259	mci = edac_mc_alloc(emif_id, 1, layers, sizeof(*edac));260	if (!mci)261		return -ENOMEM;262 263	mci->pdev = &pdev->dev;264	edac = mci->pvt_info;265	edac->reg = reg;266	platform_set_drvdata(pdev, mci);267 268	mci->mtype_cap = MEM_FLAG_DDR3 | MEM_FLAG_DDR2;269	mci->edac_ctl_cap = EDAC_FLAG_SECDED | EDAC_FLAG_NONE;270	mci->mod_name = EDAC_MOD_NAME;271	mci->ctl_name = id->compatible;272	mci->dev_name = dev_name(&pdev->dev);273 274	/* Setup memory layout */275	ti_edac_setup_dimm(mci, (u32)(id->data));276 277	/* add EMIF ECC error handler */278	error_irq = platform_get_irq(pdev, 0);279	if (error_irq < 0) {280		ret = error_irq;281		goto err;282	}283 284	ret = devm_request_irq(dev, error_irq, ti_edac_isr, 0,285			       "emif-edac-irq", mci);286	if (ret) {287		edac_printk(KERN_ERR, EDAC_MOD_NAME,288			    "request_irq fail for EMIF EDAC irq\n");289		goto err;290	}291 292	ret = edac_mc_add_mc(mci);293	if (ret) {294		edac_printk(KERN_ERR, EDAC_MOD_NAME,295			    "Failed to register mci: %d.\n", ret);296		goto err;297	}298 299	/* Generate an interrupt with each 1b error */300	ti_edac_writel(edac, 1 << EMIF_1B_ECC_ERR_THRSH_SHIFT,301		       EMIF_1B_ECC_ERR_THRSH);302 303	/* Enable interrupts */304	ti_edac_writel(edac,305		       EMIF_1B_ECC_ERR | EMIF_2B_ECC_ERR | EMIF_WR_ECC_ERR,306		       EMIF_IRQ_ENABLE_SET);307 308	return 0;309 310err:311	edac_mc_free(mci);312	return ret;313}314 315static void ti_edac_remove(struct platform_device *pdev)316{317	struct mem_ctl_info *mci = platform_get_drvdata(pdev);318 319	edac_mc_del_mc(&pdev->dev);320	edac_mc_free(mci);321}322 323static struct platform_driver ti_edac_driver = {324	.probe = ti_edac_probe,325	.remove_new = ti_edac_remove,326	.driver = {327		   .name = EDAC_MOD_NAME,328		   .of_match_table = ti_edac_of_match,329	},330};331 332module_platform_driver(ti_edac_driver);333 334MODULE_AUTHOR("Texas Instruments Inc.");335MODULE_DESCRIPTION("EDAC Driver for Texas Instruments DDR3 MC");336MODULE_LICENSE("GPL v2");337