mtd: docg3 refactor cascade floors structure
Group floors into a common cascade structure. This will provide a common structure to store common data to all cascaded docg3 chips, like IO addressing, locking protection. Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
a2b3d284ed
commit
1b15a5f93b
2 changed files with 61 additions and 45 deletions
|
@ -80,14 +80,9 @@ static struct nand_ecclayout docg3_oobinfo = {
|
|||
.oobavail = 8,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct docg3_bch - BCH engine
|
||||
*/
|
||||
static struct bch_control *docg3_bch;
|
||||
|
||||
static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
|
||||
{
|
||||
u8 val = readb(docg3->base + reg);
|
||||
u8 val = readb(docg3->cascade->base + reg);
|
||||
|
||||
trace_docg3_io(0, 8, reg, (int)val);
|
||||
return val;
|
||||
|
@ -95,7 +90,7 @@ static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
|
|||
|
||||
static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
|
||||
{
|
||||
u16 val = readw(docg3->base + reg);
|
||||
u16 val = readw(docg3->cascade->base + reg);
|
||||
|
||||
trace_docg3_io(0, 16, reg, (int)val);
|
||||
return val;
|
||||
|
@ -103,13 +98,13 @@ static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
|
|||
|
||||
static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
|
||||
{
|
||||
writeb(val, docg3->base + reg);
|
||||
writeb(val, docg3->cascade->base + reg);
|
||||
trace_docg3_io(1, 8, reg, val);
|
||||
}
|
||||
|
||||
static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
|
||||
{
|
||||
writew(val, docg3->base + reg);
|
||||
writew(val, docg3->cascade->base + reg);
|
||||
trace_docg3_io(1, 16, reg, val);
|
||||
}
|
||||
|
||||
|
@ -643,7 +638,8 @@ static int doc_ecc_bch_fix_data(struct docg3 *docg3, void *buf, u8 *hwecc)
|
|||
|
||||
for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
|
||||
ecc[i] = bitrev8(hwecc[i]);
|
||||
numerrs = decode_bch(docg3_bch, NULL, DOC_ECC_BCH_COVERED_BYTES,
|
||||
numerrs = decode_bch(docg3->cascade->bch, NULL,
|
||||
DOC_ECC_BCH_COVERED_BYTES,
|
||||
NULL, ecc, NULL, errorpos);
|
||||
BUG_ON(numerrs == -EINVAL);
|
||||
if (numerrs < 0)
|
||||
|
@ -1599,13 +1595,13 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
|
|||
};
|
||||
|
||||
static int doc_register_sysfs(struct platform_device *pdev,
|
||||
struct mtd_info **floors)
|
||||
struct docg3_cascade *cascade)
|
||||
{
|
||||
int ret = 0, floor, i = 0;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
|
||||
floor++)
|
||||
for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS &&
|
||||
cascade->floors[floor]; floor++)
|
||||
for (i = 0; !ret && i < 4; i++)
|
||||
ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
|
||||
if (!ret)
|
||||
|
@ -1619,12 +1615,12 @@ static int doc_register_sysfs(struct platform_device *pdev,
|
|||
}
|
||||
|
||||
static void doc_unregister_sysfs(struct platform_device *pdev,
|
||||
struct mtd_info **floors)
|
||||
struct docg3_cascade *cascade)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
int floor, i;
|
||||
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS && cascade->floors[floor];
|
||||
floor++)
|
||||
for (i = 0; i < 4; i++)
|
||||
device_remove_file(dev, &doc_sys_attrs[floor][i]);
|
||||
|
@ -1833,6 +1829,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
|
|||
* @base: the io space where the device is probed
|
||||
* @floor: the floor of the probed device
|
||||
* @dev: the device
|
||||
* @cascade: the cascade of chips this devices will belong to
|
||||
*
|
||||
* Checks whether a device at the specified IO range, and floor is available.
|
||||
*
|
||||
|
@ -1841,7 +1838,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
|
|||
* launched.
|
||||
*/
|
||||
static struct mtd_info * __init
|
||||
doc_probe_device(void __iomem *base, int floor, struct device *dev)
|
||||
doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev)
|
||||
{
|
||||
int ret, bbt_nbpages;
|
||||
u16 chip_id, chip_id_inv;
|
||||
|
@ -1864,7 +1861,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev)
|
|||
|
||||
docg3->dev = dev;
|
||||
docg3->device_id = floor;
|
||||
docg3->base = base;
|
||||
docg3->cascade = cascade;
|
||||
doc_set_device_id(docg3, docg3->device_id);
|
||||
if (!floor)
|
||||
doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
|
||||
|
@ -1881,7 +1878,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev)
|
|||
switch (chip_id) {
|
||||
case DOC_CHIPID_G3:
|
||||
doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n",
|
||||
base, floor);
|
||||
docg3->cascade->base, floor);
|
||||
break;
|
||||
default:
|
||||
doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
|
||||
|
@ -1926,10 +1923,12 @@ static void doc_release_device(struct mtd_info *mtd)
|
|||
static int docg3_resume(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
struct docg3_cascade *cascade;
|
||||
struct mtd_info **docg3_floors, *mtd;
|
||||
struct docg3 *docg3;
|
||||
|
||||
docg3_floors = platform_get_drvdata(pdev);
|
||||
cascade = platform_get_drvdata(pdev);
|
||||
docg3_floors = cascade->floors;
|
||||
mtd = docg3_floors[0];
|
||||
docg3 = mtd->priv;
|
||||
|
||||
|
@ -1951,11 +1950,13 @@ static int docg3_resume(struct platform_device *pdev)
|
|||
static int docg3_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
int floor, i;
|
||||
struct docg3_cascade *cascade;
|
||||
struct mtd_info **docg3_floors, *mtd;
|
||||
struct docg3 *docg3;
|
||||
u8 ctrl, pwr_down;
|
||||
|
||||
docg3_floors = platform_get_drvdata(pdev);
|
||||
cascade = platform_get_drvdata(pdev);
|
||||
docg3_floors = cascade->floors;
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
|
||||
mtd = docg3_floors[floor];
|
||||
if (!mtd)
|
||||
|
@ -2005,7 +2006,7 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|||
struct resource *ress;
|
||||
void __iomem *base;
|
||||
int ret, floor, found = 0;
|
||||
struct mtd_info **docg3_floors;
|
||||
struct docg3_cascade *cascade;
|
||||
|
||||
ret = -ENXIO;
|
||||
ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
@ -2016,17 +2017,18 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|||
base = ioremap(ress->start, DOC_IOSPACE_SIZE);
|
||||
|
||||
ret = -ENOMEM;
|
||||
docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS,
|
||||
GFP_KERNEL);
|
||||
if (!docg3_floors)
|
||||
cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS,
|
||||
GFP_KERNEL);
|
||||
if (!cascade)
|
||||
goto nomem1;
|
||||
docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
|
||||
cascade->base = base;
|
||||
cascade->bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
|
||||
DOC_ECC_BCH_PRIMPOLY);
|
||||
if (!docg3_bch)
|
||||
if (!cascade->bch)
|
||||
goto nomem2;
|
||||
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
|
||||
mtd = doc_probe_device(base, floor, dev);
|
||||
mtd = doc_probe_device(cascade, floor, dev);
|
||||
if (IS_ERR(mtd)) {
|
||||
ret = PTR_ERR(mtd);
|
||||
goto err_probe;
|
||||
|
@ -2037,7 +2039,7 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|||
else
|
||||
continue;
|
||||
}
|
||||
docg3_floors[floor] = mtd;
|
||||
cascade->floors[floor] = mtd;
|
||||
ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL,
|
||||
0);
|
||||
if (ret)
|
||||
|
@ -2045,26 +2047,26 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|||
found++;
|
||||
}
|
||||
|
||||
ret = doc_register_sysfs(pdev, docg3_floors);
|
||||
ret = doc_register_sysfs(pdev, cascade);
|
||||
if (ret)
|
||||
goto err_probe;
|
||||
if (!found)
|
||||
goto notfound;
|
||||
|
||||
platform_set_drvdata(pdev, docg3_floors);
|
||||
doc_dbg_register(docg3_floors[0]->priv);
|
||||
platform_set_drvdata(pdev, cascade);
|
||||
doc_dbg_register(cascade->floors[0]->priv);
|
||||
return 0;
|
||||
|
||||
notfound:
|
||||
ret = -ENODEV;
|
||||
dev_info(dev, "No supported DiskOnChip found\n");
|
||||
err_probe:
|
||||
free_bch(docg3_bch);
|
||||
kfree(cascade->bch);
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
|
||||
if (docg3_floors[floor])
|
||||
doc_release_device(docg3_floors[floor]);
|
||||
if (cascade->floors[floor])
|
||||
doc_release_device(cascade->floors[floor]);
|
||||
nomem2:
|
||||
kfree(docg3_floors);
|
||||
kfree(cascade);
|
||||
nomem1:
|
||||
iounmap(base);
|
||||
noress:
|
||||
|
@ -2079,19 +2081,19 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|||
*/
|
||||
static int __exit docg3_release(struct platform_device *pdev)
|
||||
{
|
||||
struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
|
||||
struct docg3 *docg3 = docg3_floors[0]->priv;
|
||||
void __iomem *base = docg3->base;
|
||||
struct docg3_cascade *cascade = platform_get_drvdata(pdev);
|
||||
struct docg3 *docg3 = cascade->floors[0]->priv;
|
||||
void __iomem *base = cascade->base;
|
||||
int floor;
|
||||
|
||||
doc_unregister_sysfs(pdev, docg3_floors);
|
||||
doc_unregister_sysfs(pdev, cascade);
|
||||
doc_dbg_unregister(docg3);
|
||||
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
|
||||
if (docg3_floors[floor])
|
||||
doc_release_device(docg3_floors[floor]);
|
||||
if (cascade->floors[floor])
|
||||
doc_release_device(cascade->floors[floor]);
|
||||
|
||||
kfree(docg3_floors);
|
||||
free_bch(docg3_bch);
|
||||
free_bch(docg3->cascade->bch);
|
||||
kfree(cascade);
|
||||
iounmap(base);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#ifndef _MTD_DOCG3_H
|
||||
#define _MTD_DOCG3_H
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
/*
|
||||
* Flash memory areas :
|
||||
* - 0x0000 .. 0x07ff : IPL
|
||||
|
@ -266,10 +268,22 @@
|
|||
*/
|
||||
#define DOC_LAYOUT_DPS_KEY_LENGTH 8
|
||||
|
||||
/**
|
||||
* struct docg3_cascade - Cascade of 1 to 4 docg3 chips
|
||||
* @floors: floors (ie. one physical docg3 chip is one floor)
|
||||
* @base: IO space to access all chips in the cascade
|
||||
* @bch: the BCH correcting control structure
|
||||
*/
|
||||
struct docg3_cascade {
|
||||
struct mtd_info *floors[DOC_MAX_NBFLOORS];
|
||||
void __iomem *base;
|
||||
struct bch_control *bch;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct docg3 - DiskOnChip driver private data
|
||||
* @dev: the device currently under control
|
||||
* @base: mapped IO space
|
||||
* @cascade: the cascade this device belongs to
|
||||
* @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
|
||||
* @if_cfg: if true, reads are on 16bits, else reads are on 8bits
|
||||
|
||||
|
@ -287,7 +301,7 @@
|
|||
*/
|
||||
struct docg3 {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
struct docg3_cascade *cascade;
|
||||
unsigned int device_id:4;
|
||||
unsigned int if_cfg:1;
|
||||
unsigned int reliable:2;
|
||||
|
|
Loading…
Reference in a new issue