1709Swollman// SPDX-License-Identifier: GPL-2.0 27477Sache/* 3709Swollman * JZ47xx ECC common code 437Srgrimes * 537Srgrimes * Copyright (c) 2015 Imagination Technologies 637Srgrimes * Author: Alex Smith <alex.smith@imgtec.com> 737Srgrimes */ 837Srgrimes 937Srgrimes#include <linux/clk.h> 1037Srgrimes#include <linux/init.h> 1137Srgrimes#include <linux/module.h> 1237Srgrimes#include <linux/of.h> 1337Srgrimes#include <linux/of_platform.h> 1437Srgrimes#include <linux/platform_device.h> 1537Srgrimes 1637Srgrimes#include "ingenic_ecc.h" 1737Srgrimes 1837Srgrimes/** 1937Srgrimes * ingenic_ecc_calculate() - calculate ECC for a data buffer 2037Srgrimes * @ecc: ECC device. 213843Sdg * @params: ECC parameters. 223843Sdg * @buf: input buffer with raw data. 232164Sdg * @ecc_code: output buffer with ECC. 2437Srgrimes * 2537Srgrimes * Return: 0 on success, -ETIMEDOUT if timed out while waiting for ECC 2637Srgrimes * controller. 2737Srgrimes */ 2837Srgrimesint ingenic_ecc_calculate(struct ingenic_ecc *ecc, 2937Srgrimes struct ingenic_ecc_params *params, 3037Srgrimes const u8 *buf, u8 *ecc_code) 3137Srgrimes{ 3237Srgrimes return ecc->ops->calculate(ecc, params, buf, ecc_code); 3337Srgrimes} 3437Srgrimes 3537Srgrimes/** 3637Srgrimes * ingenic_ecc_correct() - detect and correct bit errors 3737Srgrimes * @ecc: ECC device. 3837Srgrimes * @params: ECC parameters. 3937Srgrimes * @buf: raw data read from the chip. 4037Srgrimes * @ecc_code: ECC read from the chip. 4137Srgrimes * 4237Srgrimes * Given the raw data and the ECC read from the NAND device, detects and 4337Srgrimes * corrects errors in the data. 4437Srgrimes * 4537Srgrimes * Return: the number of bit errors corrected, -EBADMSG if there are too many 4637Srgrimes * errors to correct or -ETIMEDOUT if we timed out waiting for the controller. 4737Srgrimes */ 4837Srgrimesint ingenic_ecc_correct(struct ingenic_ecc *ecc, 4937Srgrimes struct ingenic_ecc_params *params, 5037Srgrimes u8 *buf, u8 *ecc_code) 5137Srgrimes{ 5237Srgrimes return ecc->ops->correct(ecc, params, buf, ecc_code); 5337Srgrimes} 5437Srgrimes 552164Sdg/** 562164Sdg * ingenic_ecc_get() - get the ECC controller device 5737Srgrimes * @np: ECC device tree node. 5837Srgrimes * 5937Srgrimes * Gets the ECC controller device from the specified device tree node. The 6037Srgrimes * device must be released with ingenic_ecc_release() when it is no longer being 613036Sdg * used. 623036Sdg * 633036Sdg * Return: a pointer to ingenic_ecc, errors are encoded into the pointer. 641692Sphk * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. 6537Srgrimes */ 6637Srgrimesstatic struct ingenic_ecc *ingenic_ecc_get(struct device_node *np) 6737Srgrimes{ 68872Sache struct platform_device *pdev; 69872Sache struct ingenic_ecc *ecc; 70872Sache 71872Sache pdev = of_find_device_by_node(np); 724091Sache if (!pdev) 73872Sache return ERR_PTR(-EPROBE_DEFER); 747219Sjkh 757219Sjkh if (!platform_get_drvdata(pdev)) { 767219Sjkh put_device(&pdev->dev); 777219Sjkh return ERR_PTR(-EPROBE_DEFER); 787219Sjkh } 791675Sache 807219Sjkh ecc = platform_get_drvdata(pdev); 817293Sjkh clk_prepare_enable(ecc->clk); 821675Sache 831675Sache return ecc; 847259Sjkh} 857259Sjkh 867293Sjkh/** 8737Srgrimes * of_ingenic_ecc_get() - get the ECC controller from a DT node 8837Srgrimes * @of_node: the node that contains an ecc-engine property. 897460Sjkh * 907460Sjkh * Get the ecc-engine property from the given device tree 917460Sjkh * node and pass it to ingenic_ecc_get to do the work. 927460Sjkh * 937460Sjkh * Return: a pointer to ingenic_ecc, errors are encoded into the pointer. 947259Sjkh * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. 957259Sjkh */ 9637Srgrimesstruct ingenic_ecc *of_ingenic_ecc_get(struct device_node *of_node) 971001Sguido{ 987259Sjkh struct ingenic_ecc *ecc = NULL; 997259Sjkh struct device_node *np; 100857Sdg 1017259Sjkh np = of_parse_phandle(of_node, "ecc-engine", 0); 10237Srgrimes 10337Srgrimes /* 104958Sache * If the ecc-engine property is not found, check for the deprecated 105958Sache * ingenic,bch-controller property 1061186Srgrimes */ 1071186Srgrimes if (!np) 1081186Srgrimes np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); 1091186Srgrimes 1101308Srich if (np) { 1111186Srgrimes ecc = ingenic_ecc_get(np); 1121186Srgrimes of_node_put(np); 1131186Srgrimes } 1141186Srgrimes return ecc; 1151186Srgrimes} 1161186Srgrimes 1171186Srgrimes/** 1187238Sache * ingenic_ecc_release() - release the ECC controller device 1197219Sjkh * @ecc: ECC device. 1207238Sache */ 1217477Sachevoid ingenic_ecc_release(struct ingenic_ecc *ecc) 1227477Sache{ 1237238Sache clk_disable_unprepare(ecc->clk); 1247238Sache put_device(ecc->dev); 1257238Sache} 1267238Sache 1277238Sacheint ingenic_ecc_probe(struct platform_device *pdev) 1287294Sjkh{ 1297238Sache struct device *dev = &pdev->dev; 1307238Sache struct ingenic_ecc *ecc; 1317459Sjkh 1327238Sache ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); 1337238Sache if (!ecc) 1347219Sjkh return -ENOMEM; 1357459Sjkh 1367238Sache ecc->ops = device_get_match_data(dev); 1377219Sjkh if (!ecc->ops) 1387219Sjkh return -EINVAL; 1397238Sache 1407238Sache ecc->base = devm_platform_ioremap_resource(pdev, 0); 1417459Sjkh if (IS_ERR(ecc->base)) 1427238Sache return PTR_ERR(ecc->base); 1437238Sache 1447238Sache ecc->ops->disable(ecc); 1457477Sache 1467477Sache ecc->clk = devm_clk_get(dev, NULL); 1477477Sache if (IS_ERR(ecc->clk)) { 1487477Sache dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk)); 1497477Sache return PTR_ERR(ecc->clk); 1507477Sache } 1517477Sache 1527477Sache mutex_init(&ecc->lock); 1537477Sache 1547477Sache ecc->dev = dev; 1557477Sache platform_set_drvdata(pdev, ecc); 1567294Sjkh 1577459Sjkh return 0; 1587238Sache} 1597238SacheEXPORT_SYMBOL(ingenic_ecc_probe); 1607238Sache