1 // SPDX-License-Identifier: GPL-2.0
3 * JZ47xx ECC common code
5 * Copyright (c) 2015 Imagination Technologies
6 * Author: Alex Smith <alex.smith@imgtec.com>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/of_platform.h>
13 #include <linux/platform_device.h>
15 #include "ingenic_ecc.h"
18 * ingenic_ecc_calculate() - calculate ECC for a data buffer
20 * @params: ECC parameters.
21 * @buf: input buffer with raw data.
22 * @ecc_code: output buffer with ECC.
24 * Return: 0 on success, -ETIMEDOUT if timed out while waiting for ECC
27 int ingenic_ecc_calculate(struct ingenic_ecc
*ecc
,
28 struct ingenic_ecc_params
*params
,
29 const u8
*buf
, u8
*ecc_code
)
31 return ecc
->ops
->calculate(ecc
, params
, buf
, ecc_code
);
35 * ingenic_ecc_correct() - detect and correct bit errors
37 * @params: ECC parameters.
38 * @buf: raw data read from the chip.
39 * @ecc_code: ECC read from the chip.
41 * Given the raw data and the ECC read from the NAND device, detects and
42 * corrects errors in the data.
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.
47 int ingenic_ecc_correct(struct ingenic_ecc
*ecc
,
48 struct ingenic_ecc_params
*params
,
49 u8
*buf
, u8
*ecc_code
)
51 return ecc
->ops
->correct(ecc
, params
, buf
, ecc_code
);
55 * ingenic_ecc_get() - get the ECC controller device
56 * @np: ECC device tree node.
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
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.
65 static struct ingenic_ecc
*ingenic_ecc_get(struct device_node
*np
)
67 struct platform_device
*pdev
;
68 struct ingenic_ecc
*ecc
;
70 pdev
= of_find_device_by_node(np
);
71 if (!pdev
|| !platform_get_drvdata(pdev
))
72 return ERR_PTR(-EPROBE_DEFER
);
74 ecc
= platform_get_drvdata(pdev
);
75 clk_prepare_enable(ecc
->clk
);
81 * of_ingenic_ecc_get() - get the ECC controller from a DT node
82 * @of_node: the node that contains an ecc-engine property.
84 * Get the ecc-engine property from the given device tree
85 * node and pass it to ingenic_ecc_get to do the work.
87 * Return: a pointer to ingenic_ecc, errors are encoded into the pointer.
88 * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
90 struct ingenic_ecc
*of_ingenic_ecc_get(struct device_node
*of_node
)
92 struct ingenic_ecc
*ecc
= NULL
;
93 struct device_node
*np
;
95 np
= of_parse_phandle(of_node
, "ecc-engine", 0);
98 * If the ecc-engine property is not found, check for the deprecated
99 * ingenic,bch-controller property
102 np
= of_parse_phandle(of_node
, "ingenic,bch-controller", 0);
105 ecc
= ingenic_ecc_get(np
);
112 * ingenic_ecc_release() - release the ECC controller device
115 void ingenic_ecc_release(struct ingenic_ecc
*ecc
)
117 clk_disable_unprepare(ecc
->clk
);
118 put_device(ecc
->dev
);
121 int ingenic_ecc_probe(struct platform_device
*pdev
)
123 struct device
*dev
= &pdev
->dev
;
124 struct ingenic_ecc
*ecc
;
126 ecc
= devm_kzalloc(dev
, sizeof(*ecc
), GFP_KERNEL
);
130 ecc
->ops
= device_get_match_data(dev
);
134 ecc
->base
= devm_platform_ioremap_resource(pdev
, 0);
135 if (IS_ERR(ecc
->base
))
136 return PTR_ERR(ecc
->base
);
138 ecc
->ops
->disable(ecc
);
140 ecc
->clk
= devm_clk_get(dev
, NULL
);
141 if (IS_ERR(ecc
->clk
)) {
142 dev_err(dev
, "failed to get clock: %ld\n", PTR_ERR(ecc
->clk
));
143 return PTR_ERR(ecc
->clk
);
146 mutex_init(&ecc
->lock
);
149 platform_set_drvdata(pdev
, ecc
);
153 EXPORT_SYMBOL(ingenic_ecc_probe
);