0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/of_platform.h>
0013 #include <linux/platform_device.h>
0014
0015 #include "ingenic_ecc.h"
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 int ingenic_ecc_calculate(struct ingenic_ecc *ecc,
0028 struct ingenic_ecc_params *params,
0029 const u8 *buf, u8 *ecc_code)
0030 {
0031 return ecc->ops->calculate(ecc, params, buf, ecc_code);
0032 }
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047 int ingenic_ecc_correct(struct ingenic_ecc *ecc,
0048 struct ingenic_ecc_params *params,
0049 u8 *buf, u8 *ecc_code)
0050 {
0051 return ecc->ops->correct(ecc, params, buf, ecc_code);
0052 }
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 static struct ingenic_ecc *ingenic_ecc_get(struct device_node *np)
0066 {
0067 struct platform_device *pdev;
0068 struct ingenic_ecc *ecc;
0069
0070 pdev = of_find_device_by_node(np);
0071 if (!pdev)
0072 return ERR_PTR(-EPROBE_DEFER);
0073
0074 if (!platform_get_drvdata(pdev)) {
0075 put_device(&pdev->dev);
0076 return ERR_PTR(-EPROBE_DEFER);
0077 }
0078
0079 ecc = platform_get_drvdata(pdev);
0080 clk_prepare_enable(ecc->clk);
0081
0082 return ecc;
0083 }
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *of_node)
0096 {
0097 struct ingenic_ecc *ecc = NULL;
0098 struct device_node *np;
0099
0100 np = of_parse_phandle(of_node, "ecc-engine", 0);
0101
0102
0103
0104
0105
0106 if (!np)
0107 np = of_parse_phandle(of_node, "ingenic,bch-controller", 0);
0108
0109 if (np) {
0110 ecc = ingenic_ecc_get(np);
0111 of_node_put(np);
0112 }
0113 return ecc;
0114 }
0115
0116
0117
0118
0119
0120 void ingenic_ecc_release(struct ingenic_ecc *ecc)
0121 {
0122 clk_disable_unprepare(ecc->clk);
0123 put_device(ecc->dev);
0124 }
0125
0126 int ingenic_ecc_probe(struct platform_device *pdev)
0127 {
0128 struct device *dev = &pdev->dev;
0129 struct ingenic_ecc *ecc;
0130
0131 ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL);
0132 if (!ecc)
0133 return -ENOMEM;
0134
0135 ecc->ops = device_get_match_data(dev);
0136 if (!ecc->ops)
0137 return -EINVAL;
0138
0139 ecc->base = devm_platform_ioremap_resource(pdev, 0);
0140 if (IS_ERR(ecc->base))
0141 return PTR_ERR(ecc->base);
0142
0143 ecc->ops->disable(ecc);
0144
0145 ecc->clk = devm_clk_get(dev, NULL);
0146 if (IS_ERR(ecc->clk)) {
0147 dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk));
0148 return PTR_ERR(ecc->clk);
0149 }
0150
0151 mutex_init(&ecc->lock);
0152
0153 ecc->dev = dev;
0154 platform_set_drvdata(pdev, ecc);
0155
0156 return 0;
0157 }
0158 EXPORT_SYMBOL(ingenic_ecc_probe);