cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ingenic_ecc.c (3961B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * JZ47xx ECC common code
      4 *
      5 * Copyright (c) 2015 Imagination Technologies
      6 * Author: Alex Smith <alex.smith@imgtec.com>
      7 */
      8
      9#include <linux/clk.h>
     10#include <linux/init.h>
     11#include <linux/module.h>
     12#include <linux/of_platform.h>
     13#include <linux/platform_device.h>
     14
     15#include "ingenic_ecc.h"
     16
     17/**
     18 * ingenic_ecc_calculate() - calculate ECC for a data buffer
     19 * @ecc: ECC device.
     20 * @params: ECC parameters.
     21 * @buf: input buffer with raw data.
     22 * @ecc_code: output buffer with ECC.
     23 *
     24 * Return: 0 on success, -ETIMEDOUT if timed out while waiting for ECC
     25 * controller.
     26 */
     27int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
     28			  struct ingenic_ecc_params *params,
     29			  const u8 *buf, u8 *ecc_code)
     30{
     31	return ecc->ops->calculate(ecc, params, buf, ecc_code);
     32}
     33
     34/**
     35 * ingenic_ecc_correct() - detect and correct bit errors
     36 * @ecc: ECC device.
     37 * @params: ECC parameters.
     38 * @buf: raw data read from the chip.
     39 * @ecc_code: ECC read from the chip.
     40 *
     41 * Given the raw data and the ECC read from the NAND device, detects and
     42 * corrects errors in the data.
     43 *
     44 * Return: the number of bit errors corrected, -EBADMSG if there are too many
     45 * errors to correct or -ETIMEDOUT if we timed out waiting for the controller.
     46 */
     47int ingenic_ecc_correct(struct ingenic_ecc *ecc,
     48			struct ingenic_ecc_params *params,
     49			u8 *buf, u8 *ecc_code)
     50{
     51	return ecc->ops->correct(ecc, params, buf, ecc_code);
     52}
     53
     54/**
     55 * ingenic_ecc_get() - get the ECC controller device
     56 * @np: ECC device tree node.
     57 *
     58 * Gets the ECC controller device from the specified device tree node. The
     59 * device must be released with ingenic_ecc_release() when it is no longer being
     60 * used.
     61 *
     62 * Return: a pointer to ingenic_ecc, errors are encoded into the pointer.
     63 * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
     64 */
     65static struct ingenic_ecc *ingenic_ecc_get(struct device_node *np)
     66{
     67	struct platform_device *pdev;
     68	struct ingenic_ecc *ecc;
     69
     70	pdev = of_find_device_by_node(np);
     71	if (!pdev)
     72		return ERR_PTR(-EPROBE_DEFER);
     73
     74	if (!platform_get_drvdata(pdev)) {
     75		put_device(&pdev->dev);
     76		return ERR_PTR(-EPROBE_DEFER);
     77	}
     78
     79	ecc = platform_get_drvdata(pdev);
     80	clk_prepare_enable(ecc->clk);
     81
     82	return ecc;
     83}
     84
     85/**
     86 * of_ingenic_ecc_get() - get the ECC controller from a DT node
     87 * @of_node: the node that contains an ecc-engine property.
     88 *
     89 * Get the ecc-engine property from the given device tree
     90 * node and pass it to ingenic_ecc_get to do the work.
     91 *
     92 * Return: a pointer to ingenic_ecc, errors are encoded into the pointer.
     93 * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
     94 */
     95struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *of_node)
     96{
     97	struct ingenic_ecc *ecc = NULL;
     98	struct device_node *np;
     99
    100	np = of_parse_phandle(of_node, "ecc-engine", 0);
    101
    102	/*
    103	 * If the ecc-engine property is not found, check for the deprecated
    104	 * ingenic,bch-controller property
    105	 */
    106	if (!np)
    107		np = of_parse_phandle(of_node, "ingenic,bch-controller", 0);
    108
    109	if (np) {
    110		ecc = ingenic_ecc_get(np);
    111		of_node_put(np);
    112	}
    113	return ecc;
    114}
    115
    116/**
    117 * ingenic_ecc_release() - release the ECC controller device
    118 * @ecc: ECC device.
    119 */
    120void ingenic_ecc_release(struct ingenic_ecc *ecc)
    121{
    122	clk_disable_unprepare(ecc->clk);
    123	put_device(ecc->dev);
    124}
    125
    126int ingenic_ecc_probe(struct platform_device *pdev)
    127{
    128	struct device *dev = &pdev->dev;
    129	struct ingenic_ecc *ecc;
    130
    131	ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
    132	if (!ecc)
    133		return -ENOMEM;
    134
    135	ecc->ops = device_get_match_data(dev);
    136	if (!ecc->ops)
    137		return -EINVAL;
    138
    139	ecc->base = devm_platform_ioremap_resource(pdev, 0);
    140	if (IS_ERR(ecc->base))
    141		return PTR_ERR(ecc->base);
    142
    143	ecc->ops->disable(ecc);
    144
    145	ecc->clk = devm_clk_get(dev, NULL);
    146	if (IS_ERR(ecc->clk)) {
    147		dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk));
    148		return PTR_ERR(ecc->clk);
    149	}
    150
    151	mutex_init(&ecc->lock);
    152
    153	ecc->dev = dev;
    154	platform_set_drvdata(pdev, ecc);
    155
    156	return 0;
    157}
    158EXPORT_SYMBOL(ingenic_ecc_probe);