-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mtd: rawnand: ingenic: Separate top-level and SoC specific code
The ingenic-nand driver uses an API provided by the jz4780-bch driver. This makes it difficult to support other SoCs in the jz4780-bch driver. To work around this, we separate the API functions from the SoC-specific code, so that these API functions are SoC-agnostic. Signed-off-by: Paul Cercueil <paul@crapouillou.net> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
- Loading branch information
Paul Cercueil
authored and
Miquel Raynal
committed
Apr 8, 2019
1 parent
d74fd06
commit 15de8c6
Showing
7 changed files
with
310 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740_nand.o | ||
obj-$(CONFIG_MTD_NAND_JZ4780) += ingenic_nand.o jz4780_bch.o | ||
obj-$(CONFIG_MTD_NAND_JZ4780) += ingenic_nand.o | ||
|
||
obj-$(CONFIG_MTD_NAND_INGENIC_ECC) += ingenic_ecc.o | ||
obj-$(CONFIG_MTD_NAND_JZ4780_BCH) += jz4780_bch.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* JZ47xx ECC common code | ||
* | ||
* Copyright (c) 2015 Imagination Technologies | ||
* Author: Alex Smith <alex.smith@imgtec.com> | ||
*/ | ||
|
||
#include <linux/clk.h> | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/of_platform.h> | ||
#include <linux/platform_device.h> | ||
|
||
#include "ingenic_ecc.h" | ||
|
||
/** | ||
* ingenic_ecc_calculate() - calculate ECC for a data buffer | ||
* @ecc: ECC device. | ||
* @params: ECC parameters. | ||
* @buf: input buffer with raw data. | ||
* @ecc_code: output buffer with ECC. | ||
* | ||
* Return: 0 on success, -ETIMEDOUT if timed out while waiting for ECC | ||
* controller. | ||
*/ | ||
int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
const u8 *buf, u8 *ecc_code) | ||
{ | ||
return ecc->ops->calculate(ecc, params, buf, ecc_code); | ||
} | ||
EXPORT_SYMBOL(ingenic_ecc_calculate); | ||
|
||
/** | ||
* ingenic_ecc_correct() - detect and correct bit errors | ||
* @ecc: ECC device. | ||
* @params: ECC parameters. | ||
* @buf: raw data read from the chip. | ||
* @ecc_code: ECC read from the chip. | ||
* | ||
* Given the raw data and the ECC read from the NAND device, detects and | ||
* corrects errors in the data. | ||
* | ||
* Return: the number of bit errors corrected, -EBADMSG if there are too many | ||
* errors to correct or -ETIMEDOUT if we timed out waiting for the controller. | ||
*/ | ||
int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
u8 *buf, u8 *ecc_code) | ||
{ | ||
return ecc->ops->correct(ecc, params, buf, ecc_code); | ||
} | ||
EXPORT_SYMBOL(ingenic_ecc_correct); | ||
|
||
/** | ||
* ingenic_ecc_get() - get the ECC controller device | ||
* @np: ECC device tree node. | ||
* | ||
* Gets the ECC controller device from the specified device tree node. The | ||
* device must be released with ingenic_ecc_release() when it is no longer being | ||
* used. | ||
* | ||
* Return: a pointer to ingenic_ecc, errors are encoded into the pointer. | ||
* PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
*/ | ||
static struct ingenic_ecc *ingenic_ecc_get(struct device_node *np) | ||
{ | ||
struct platform_device *pdev; | ||
struct ingenic_ecc *ecc; | ||
|
||
pdev = of_find_device_by_node(np); | ||
if (!pdev || !platform_get_drvdata(pdev)) | ||
return ERR_PTR(-EPROBE_DEFER); | ||
|
||
get_device(&pdev->dev); | ||
|
||
ecc = platform_get_drvdata(pdev); | ||
clk_prepare_enable(ecc->clk); | ||
|
||
return ecc; | ||
} | ||
|
||
/** | ||
* of_ingenic_ecc_get() - get the ECC controller from a DT node | ||
* @of_node: the node that contains a bch-controller property. | ||
* | ||
* Get the bch-controller property from the given device tree | ||
* node and pass it to ingenic_ecc_get to do the work. | ||
* | ||
* Return: a pointer to ingenic_ecc, errors are encoded into the pointer. | ||
* PTR_ERR(-EPROBE_DEFER) if the device hasn't been initialised yet. | ||
*/ | ||
struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *of_node) | ||
{ | ||
struct ingenic_ecc *ecc = NULL; | ||
struct device_node *np; | ||
|
||
np = of_parse_phandle(of_node, "ingenic,bch-controller", 0); | ||
|
||
if (np) { | ||
ecc = ingenic_ecc_get(np); | ||
of_node_put(np); | ||
} | ||
return ecc; | ||
} | ||
EXPORT_SYMBOL(of_ingenic_ecc_get); | ||
|
||
/** | ||
* ingenic_ecc_release() - release the ECC controller device | ||
* @ecc: ECC device. | ||
*/ | ||
void ingenic_ecc_release(struct ingenic_ecc *ecc) | ||
{ | ||
clk_disable_unprepare(ecc->clk); | ||
put_device(ecc->dev); | ||
} | ||
EXPORT_SYMBOL(ingenic_ecc_release); | ||
|
||
int ingenic_ecc_probe(struct platform_device *pdev) | ||
{ | ||
struct device *dev = &pdev->dev; | ||
struct ingenic_ecc *ecc; | ||
struct resource *res; | ||
|
||
ecc = devm_kzalloc(dev, sizeof(*ecc), GFP_KERNEL); | ||
if (!ecc) | ||
return -ENOMEM; | ||
|
||
ecc->ops = device_get_match_data(dev); | ||
if (!ecc->ops) | ||
return -EINVAL; | ||
|
||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
ecc->base = devm_ioremap_resource(dev, res); | ||
if (IS_ERR(ecc->base)) | ||
return PTR_ERR(ecc->base); | ||
|
||
ecc->ops->disable(ecc); | ||
|
||
ecc->clk = devm_clk_get(dev, NULL); | ||
if (IS_ERR(ecc->clk)) { | ||
dev_err(dev, "failed to get clock: %ld\n", PTR_ERR(ecc->clk)); | ||
return PTR_ERR(ecc->clk); | ||
} | ||
|
||
mutex_init(&ecc->lock); | ||
|
||
ecc->dev = dev; | ||
platform_set_drvdata(pdev, ecc); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL(ingenic_ecc_probe); | ||
|
||
MODULE_LICENSE("GPL v2"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ | ||
#define __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ | ||
|
||
#include <linux/compiler_types.h> | ||
#include <linux/err.h> | ||
#include <linux/mutex.h> | ||
#include <linux/types.h> | ||
#include <uapi/asm-generic/errno-base.h> | ||
|
||
struct clk; | ||
struct device; | ||
struct ingenic_ecc; | ||
struct platform_device; | ||
|
||
/** | ||
* struct ingenic_ecc_params - ECC parameters | ||
* @size: data bytes per ECC step. | ||
* @bytes: ECC bytes per step. | ||
* @strength: number of correctable bits per ECC step. | ||
*/ | ||
struct ingenic_ecc_params { | ||
int size; | ||
int bytes; | ||
int strength; | ||
}; | ||
|
||
#if IS_ENABLED(CONFIG_MTD_NAND_INGENIC_ECC) | ||
int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
const u8 *buf, u8 *ecc_code); | ||
int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, u8 *buf, | ||
u8 *ecc_code); | ||
|
||
void ingenic_ecc_release(struct ingenic_ecc *ecc); | ||
struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np); | ||
#else /* CONFIG_MTD_NAND_INGENIC_ECC */ | ||
int ingenic_ecc_calculate(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
const u8 *buf, u8 *ecc_code) | ||
{ | ||
return -ENODEV; | ||
} | ||
|
||
int ingenic_ecc_correct(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, u8 *buf, | ||
u8 *ecc_code) | ||
{ | ||
return -ENODEV; | ||
} | ||
|
||
void ingenic_ecc_release(struct ingenic_ecc *ecc) | ||
{ | ||
} | ||
|
||
struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np) | ||
{ | ||
return ERR_PTR(-ENODEV); | ||
} | ||
#endif /* CONFIG_MTD_NAND_INGENIC_ECC */ | ||
|
||
struct ingenic_ecc_ops { | ||
void (*disable)(struct ingenic_ecc *ecc); | ||
int (*calculate)(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
const u8 *buf, u8 *ecc_code); | ||
int (*correct)(struct ingenic_ecc *ecc, | ||
struct ingenic_ecc_params *params, | ||
u8 *buf, u8 *ecc_code); | ||
}; | ||
|
||
struct ingenic_ecc { | ||
struct device *dev; | ||
const struct ingenic_ecc_ops *ops; | ||
void __iomem *base; | ||
struct clk *clk; | ||
struct mutex lock; | ||
}; | ||
|
||
int ingenic_ecc_probe(struct platform_device *pdev); | ||
|
||
#endif /* __DRIVERS_MTD_NAND_INGENIC_ECC_INTERNAL_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.