| .. | .. |
|---|
| 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"); |
|---|