| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0 OR MIT | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | * MTK ECC controller driver. | 
|---|
| 3 | 4 | * Copyright (C) 2016  MediaTek Inc. | 
|---|
| 4 | 5 | * Authors:	Xiaolei Li		<xiaolei.li@mediatek.com> | 
|---|
| 5 | 6 | *		Jorge Ramirez-Ortiz	<jorge.ramirez-ortiz@linaro.org> | 
|---|
| 6 |  | - * | 
|---|
| 7 |  | - * This program is free software; you can redistribute it and/or modify | 
|---|
| 8 |  | - * it under the terms of the GNU General Public License version 2 as | 
|---|
| 9 |  | - * published by the Free Software Foundation. | 
|---|
| 10 |  | - * | 
|---|
| 11 |  | - * This program is distributed in the hope that it will be useful, | 
|---|
| 12 |  | - * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 13 |  | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
| 14 |  | - * GNU General Public License for more details. | 
|---|
| 15 | 7 | */ | 
|---|
| 16 | 8 |  | 
|---|
| 17 | 9 | #include <linux/platform_device.h> | 
|---|
| .. | .. | 
|---|
| 51 | 43 |  | 
|---|
| 52 | 44 | struct mtk_ecc_caps { | 
|---|
| 53 | 45 | u32 err_mask; | 
|---|
|  | 46 | +	u32 err_shift; | 
|---|
| 54 | 47 | const u8 *ecc_strength; | 
|---|
| 55 | 48 | const u32 *ecc_regs; | 
|---|
| 56 | 49 | u8 num_ecc_strength; | 
|---|
| .. | .. | 
|---|
| 84 | 77 | }; | 
|---|
| 85 | 78 |  | 
|---|
| 86 | 79 | static const u8 ecc_strength_mt7622[] = { | 
|---|
| 87 |  | -	4, 6, 8, 10, 12, 14, 16 | 
|---|
|  | 80 | +	4, 6, 8, 10, 12 | 
|---|
| 88 | 81 | }; | 
|---|
| 89 | 82 |  | 
|---|
| 90 | 83 | enum mtk_ecc_regs { | 
|---|
| .. | .. | 
|---|
| 229 | 222 | for (i = 0; i < sectors; i++) { | 
|---|
| 230 | 223 | offset = (i >> 2) << 2; | 
|---|
| 231 | 224 | err = readl(ecc->regs + ECC_DECENUM0 + offset); | 
|---|
| 232 |  | -		err = err >> ((i % 4) * 8); | 
|---|
|  | 225 | +		err = err >> ((i % 4) * ecc->caps->err_shift); | 
|---|
| 233 | 226 | err &= ecc->caps->err_mask; | 
|---|
| 234 | 227 | if (err == ecc->caps->err_mask) { | 
|---|
| 235 | 228 | /* uncorrectable errors */ | 
|---|
| .. | .. | 
|---|
| 267 | 260 | struct mtk_ecc *ecc; | 
|---|
| 268 | 261 |  | 
|---|
| 269 | 262 | pdev = of_find_device_by_node(np); | 
|---|
| 270 |  | -	if (!pdev || !platform_get_drvdata(pdev)) | 
|---|
|  | 263 | +	if (!pdev) | 
|---|
| 271 | 264 | return ERR_PTR(-EPROBE_DEFER); | 
|---|
| 272 | 265 |  | 
|---|
| 273 |  | -	get_device(&pdev->dev); | 
|---|
| 274 | 266 | ecc = platform_get_drvdata(pdev); | 
|---|
|  | 267 | +	if (!ecc) { | 
|---|
|  | 268 | +		put_device(&pdev->dev); | 
|---|
|  | 269 | +		return ERR_PTR(-EPROBE_DEFER); | 
|---|
|  | 270 | +	} | 
|---|
|  | 271 | + | 
|---|
| 275 | 272 | clk_prepare_enable(ecc->clk); | 
|---|
| 276 | 273 | mtk_ecc_hw_init(ecc); | 
|---|
| 277 | 274 |  | 
|---|
| .. | .. | 
|---|
| 453 | 450 |  | 
|---|
| 454 | 451 | static const struct mtk_ecc_caps mtk_ecc_caps_mt2701 = { | 
|---|
| 455 | 452 | .err_mask = 0x3f, | 
|---|
|  | 453 | +	.err_shift = 8, | 
|---|
| 456 | 454 | .ecc_strength = ecc_strength_mt2701, | 
|---|
| 457 | 455 | .ecc_regs = mt2701_ecc_regs, | 
|---|
| 458 | 456 | .num_ecc_strength = 20, | 
|---|
| .. | .. | 
|---|
| 463 | 461 |  | 
|---|
| 464 | 462 | static const struct mtk_ecc_caps mtk_ecc_caps_mt2712 = { | 
|---|
| 465 | 463 | .err_mask = 0x7f, | 
|---|
|  | 464 | +	.err_shift = 8, | 
|---|
| 466 | 465 | .ecc_strength = ecc_strength_mt2712, | 
|---|
| 467 | 466 | .ecc_regs = mt2712_ecc_regs, | 
|---|
| 468 | 467 | .num_ecc_strength = 23, | 
|---|
| .. | .. | 
|---|
| 472 | 471 | }; | 
|---|
| 473 | 472 |  | 
|---|
| 474 | 473 | static const struct mtk_ecc_caps mtk_ecc_caps_mt7622 = { | 
|---|
| 475 |  | -	.err_mask = 0x3f, | 
|---|
|  | 474 | +	.err_mask = 0x1f, | 
|---|
|  | 475 | +	.err_shift = 5, | 
|---|
| 476 | 476 | .ecc_strength = ecc_strength_mt7622, | 
|---|
| 477 | 477 | .ecc_regs = mt7622_ecc_regs, | 
|---|
| 478 |  | -	.num_ecc_strength = 7, | 
|---|
|  | 478 | +	.num_ecc_strength = 5, | 
|---|
| 479 | 479 | .ecc_mode_shift = 4, | 
|---|
| 480 | 480 | .parity_bits = 13, | 
|---|
| 481 | 481 | .pg_irq_sel = 0, | 
|---|
| .. | .. | 
|---|
| 531 | 531 | } | 
|---|
| 532 | 532 |  | 
|---|
| 533 | 533 | irq = platform_get_irq(pdev, 0); | 
|---|
| 534 |  | -	if (irq < 0) { | 
|---|
| 535 |  | -		dev_err(dev, "failed to get irq: %d\n", irq); | 
|---|
|  | 534 | +	if (irq < 0) | 
|---|
| 536 | 535 | return irq; | 
|---|
| 537 |  | -	} | 
|---|
| 538 | 536 |  | 
|---|
| 539 | 537 | ret = dma_set_mask(dev, DMA_BIT_MASK(32)); | 
|---|
| 540 | 538 | if (ret) { | 
|---|
| .. | .. | 
|---|
| 600 | 598 |  | 
|---|
| 601 | 599 | MODULE_AUTHOR("Xiaolei Li <xiaolei.li@mediatek.com>"); | 
|---|
| 602 | 600 | MODULE_DESCRIPTION("MTK Nand ECC Driver"); | 
|---|
| 603 |  | -MODULE_LICENSE("GPL"); | 
|---|
|  | 601 | +MODULE_LICENSE("Dual MIT/GPL"); | 
|---|