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 get_device(&pdev
->dev
);
76 ecc
= platform_get_drvdata(pdev
);
77 clk_prepare_enable(ecc
->clk
);
83 * of_ingenic_ecc_get() - get the ECC controller from a DT node
84 * @of_node: the node that contains an ecc-engine property.
86 * Get the ecc-engine property from the given device tree
87 * node and pass it to ingenic_ecc_get to do the work.
89 * Return: a pointer to ingenic_ecc, errors are encoded into the pointer.
90 * PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet.
92 struct ingenic_ecc
*of_ingenic_ecc_get(struct device_node
*of_node
)
94 struct ingenic_ecc
*ecc
= NULL
;
95 struct device_node
*np
;
97 np
= of_parse_phandle(of_node
, "ecc-engine", 0);
100 * If the ecc-engine property is not found, check for the deprecated
101 * ingenic,bch-controller property
104 np
= of_parse_phandle(of_node
, "ingenic,bch-controller", 0);
107 ecc
= ingenic_ecc_get(np
);
114 * ingenic_ecc_release() - release the ECC controller device
117 void ingenic_ecc_release(struct ingenic_ecc
*ecc
)
119 clk_disable_unprepare(ecc
->clk
);
120 put_device(ecc
->dev
);
123 int ingenic_ecc_probe(struct platform_device
*pdev
)
125 struct device
*dev
= &pdev
->dev
;
126 struct ingenic_ecc
*ecc
;
127 struct resource
*res
;
129 ecc
= devm_kzalloc(dev
, sizeof(*ecc
), GFP_KERNEL
);
133 ecc
->ops
= device_get_match_data(dev
);
137 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
138 ecc
->base
= devm_ioremap_resource(dev
, res
);
139 if (IS_ERR(ecc
->base
))
140 return PTR_ERR(ecc
->base
);
142 ecc
->ops
->disable(ecc
);
144 ecc
->clk
= devm_clk_get(dev
, NULL
);
145 if (IS_ERR(ecc
->clk
)) {
146 dev_err(dev
, "failed to get clock: %ld\n", PTR_ERR(ecc
->clk
));
147 return PTR_ERR(ecc
->clk
);
150 mutex_init(&ecc
->lock
);
153 platform_set_drvdata(pdev
, ecc
);
157 EXPORT_SYMBOL(ingenic_ecc_probe
);