Commit 1b15a5f9 authored by Robert Jarzmik's avatar Robert Jarzmik Committed by David Woodhouse

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: default avatarRobert Jarzmik <robert.jarzmik@free.fr>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent a2b3d284
...@@ -80,14 +80,9 @@ static struct nand_ecclayout docg3_oobinfo = { ...@@ -80,14 +80,9 @@ static struct nand_ecclayout docg3_oobinfo = {
.oobavail = 8, .oobavail = 8,
}; };
/**
* struct docg3_bch - BCH engine
*/
static struct bch_control *docg3_bch;
static inline u8 doc_readb(struct docg3 *docg3, u16 reg) 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); trace_docg3_io(0, 8, reg, (int)val);
return val; return val;
...@@ -95,7 +90,7 @@ static inline u8 doc_readb(struct docg3 *docg3, u16 reg) ...@@ -95,7 +90,7 @@ static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
static inline u16 doc_readw(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); trace_docg3_io(0, 16, reg, (int)val);
return val; return val;
...@@ -103,13 +98,13 @@ static inline u16 doc_readw(struct docg3 *docg3, u16 reg) ...@@ -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) 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); trace_docg3_io(1, 8, reg, val);
} }
static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg) 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); 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) ...@@ -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++) for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
ecc[i] = bitrev8(hwecc[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); NULL, ecc, NULL, errorpos);
BUG_ON(numerrs == -EINVAL); BUG_ON(numerrs == -EINVAL);
if (numerrs < 0) if (numerrs < 0)
...@@ -1599,13 +1595,13 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = { ...@@ -1599,13 +1595,13 @@ static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
}; };
static int doc_register_sysfs(struct platform_device *pdev, static int doc_register_sysfs(struct platform_device *pdev,
struct mtd_info **floors) struct docg3_cascade *cascade)
{ {
int ret = 0, floor, i = 0; int ret = 0, floor, i = 0;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor]; for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS &&
floor++) cascade->floors[floor]; floor++)
for (i = 0; !ret && i < 4; i++) for (i = 0; !ret && i < 4; i++)
ret = device_create_file(dev, &doc_sys_attrs[floor][i]); ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
if (!ret) if (!ret)
...@@ -1619,12 +1615,12 @@ static int doc_register_sysfs(struct platform_device *pdev, ...@@ -1619,12 +1615,12 @@ static int doc_register_sysfs(struct platform_device *pdev,
} }
static void doc_unregister_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; struct device *dev = &pdev->dev;
int floor, i; int floor, i;
for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor]; for (floor = 0; floor < DOC_MAX_NBFLOORS && cascade->floors[floor];
floor++) floor++)
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
device_remove_file(dev, &doc_sys_attrs[floor][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) ...@@ -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 * @base: the io space where the device is probed
* @floor: the floor of the probed device * @floor: the floor of the probed device
* @dev: the 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. * 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) ...@@ -1841,7 +1838,7 @@ static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
* launched. * launched.
*/ */
static struct mtd_info * __init 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; int ret, bbt_nbpages;
u16 chip_id, chip_id_inv; u16 chip_id, chip_id_inv;
...@@ -1864,7 +1861,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev) ...@@ -1864,7 +1861,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev)
docg3->dev = dev; docg3->dev = dev;
docg3->device_id = floor; docg3->device_id = floor;
docg3->base = base; docg3->cascade = cascade;
doc_set_device_id(docg3, docg3->device_id); doc_set_device_id(docg3, docg3->device_id);
if (!floor) if (!floor)
doc_set_asic_mode(docg3, DOC_ASICMODE_RESET); doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
...@@ -1881,7 +1878,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev) ...@@ -1881,7 +1878,7 @@ doc_probe_device(void __iomem *base, int floor, struct device *dev)
switch (chip_id) { switch (chip_id) {
case DOC_CHIPID_G3: case DOC_CHIPID_G3:
doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n", doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n",
base, floor); docg3->cascade->base, floor);
break; break;
default: default:
doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id); 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) ...@@ -1926,10 +1923,12 @@ static void doc_release_device(struct mtd_info *mtd)
static int docg3_resume(struct platform_device *pdev) static int docg3_resume(struct platform_device *pdev)
{ {
int i; int i;
struct docg3_cascade *cascade;
struct mtd_info **docg3_floors, *mtd; struct mtd_info **docg3_floors, *mtd;
struct docg3 *docg3; struct docg3 *docg3;
docg3_floors = platform_get_drvdata(pdev); cascade = platform_get_drvdata(pdev);
docg3_floors = cascade->floors;
mtd = docg3_floors[0]; mtd = docg3_floors[0];
docg3 = mtd->priv; docg3 = mtd->priv;
...@@ -1951,11 +1950,13 @@ static int docg3_resume(struct platform_device *pdev) ...@@ -1951,11 +1950,13 @@ static int docg3_resume(struct platform_device *pdev)
static int docg3_suspend(struct platform_device *pdev, pm_message_t state) static int docg3_suspend(struct platform_device *pdev, pm_message_t state)
{ {
int floor, i; int floor, i;
struct docg3_cascade *cascade;
struct mtd_info **docg3_floors, *mtd; struct mtd_info **docg3_floors, *mtd;
struct docg3 *docg3; struct docg3 *docg3;
u8 ctrl, pwr_down; 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++) { for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) {
mtd = docg3_floors[floor]; mtd = docg3_floors[floor];
if (!mtd) if (!mtd)
...@@ -2005,7 +2006,7 @@ static int __init docg3_probe(struct platform_device *pdev) ...@@ -2005,7 +2006,7 @@ static int __init docg3_probe(struct platform_device *pdev)
struct resource *ress; struct resource *ress;
void __iomem *base; void __iomem *base;
int ret, floor, found = 0; int ret, floor, found = 0;
struct mtd_info **docg3_floors; struct docg3_cascade *cascade;
ret = -ENXIO; ret = -ENXIO;
ress = platform_get_resource(pdev, IORESOURCE_MEM, 0); ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -2016,17 +2017,18 @@ static int __init docg3_probe(struct platform_device *pdev) ...@@ -2016,17 +2017,18 @@ static int __init docg3_probe(struct platform_device *pdev)
base = ioremap(ress->start, DOC_IOSPACE_SIZE); base = ioremap(ress->start, DOC_IOSPACE_SIZE);
ret = -ENOMEM; ret = -ENOMEM;
docg3_floors = kzalloc(sizeof(*docg3_floors) * DOC_MAX_NBFLOORS, cascade = kzalloc(sizeof(*cascade) * DOC_MAX_NBFLOORS,
GFP_KERNEL); GFP_KERNEL);
if (!docg3_floors) if (!cascade)
goto nomem1; 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); DOC_ECC_BCH_PRIMPOLY);
if (!docg3_bch) if (!cascade->bch)
goto nomem2; goto nomem2;
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { 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)) { if (IS_ERR(mtd)) {
ret = PTR_ERR(mtd); ret = PTR_ERR(mtd);
goto err_probe; goto err_probe;
...@@ -2037,7 +2039,7 @@ static int __init docg3_probe(struct platform_device *pdev) ...@@ -2037,7 +2039,7 @@ static int __init docg3_probe(struct platform_device *pdev)
else else
continue; continue;
} }
docg3_floors[floor] = mtd; cascade->floors[floor] = mtd;
ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL, ret = mtd_device_parse_register(mtd, part_probes, NULL, NULL,
0); 0);
if (ret) if (ret)
...@@ -2045,26 +2047,26 @@ static int __init docg3_probe(struct platform_device *pdev) ...@@ -2045,26 +2047,26 @@ static int __init docg3_probe(struct platform_device *pdev)
found++; found++;
} }
ret = doc_register_sysfs(pdev, docg3_floors); ret = doc_register_sysfs(pdev, cascade);
if (ret) if (ret)
goto err_probe; goto err_probe;
if (!found) if (!found)
goto notfound; goto notfound;
platform_set_drvdata(pdev, docg3_floors); platform_set_drvdata(pdev, cascade);
doc_dbg_register(docg3_floors[0]->priv); doc_dbg_register(cascade->floors[0]->priv);
return 0; return 0;
notfound: notfound:
ret = -ENODEV; ret = -ENODEV;
dev_info(dev, "No supported DiskOnChip found\n"); dev_info(dev, "No supported DiskOnChip found\n");
err_probe: err_probe:
free_bch(docg3_bch); kfree(cascade->bch);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (docg3_floors[floor]) if (cascade->floors[floor])
doc_release_device(docg3_floors[floor]); doc_release_device(cascade->floors[floor]);
nomem2: nomem2:
kfree(docg3_floors); kfree(cascade);
nomem1: nomem1:
iounmap(base); iounmap(base);
noress: noress:
...@@ -2079,19 +2081,19 @@ static int __init docg3_probe(struct platform_device *pdev) ...@@ -2079,19 +2081,19 @@ static int __init docg3_probe(struct platform_device *pdev)
*/ */
static int __exit docg3_release(struct platform_device *pdev) static int __exit docg3_release(struct platform_device *pdev)
{ {
struct mtd_info **docg3_floors = platform_get_drvdata(pdev); struct docg3_cascade *cascade = platform_get_drvdata(pdev);
struct docg3 *docg3 = docg3_floors[0]->priv; struct docg3 *docg3 = cascade->floors[0]->priv;
void __iomem *base = docg3->base; void __iomem *base = cascade->base;
int floor; int floor;
doc_unregister_sysfs(pdev, docg3_floors); doc_unregister_sysfs(pdev, cascade);
doc_dbg_unregister(docg3); doc_dbg_unregister(docg3);
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
if (docg3_floors[floor]) if (cascade->floors[floor])
doc_release_device(docg3_floors[floor]); doc_release_device(cascade->floors[floor]);
kfree(docg3_floors); free_bch(docg3->cascade->bch);
free_bch(docg3_bch); kfree(cascade);
iounmap(base); iounmap(base);
return 0; return 0;
} }
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#ifndef _MTD_DOCG3_H #ifndef _MTD_DOCG3_H
#define _MTD_DOCG3_H #define _MTD_DOCG3_H
#include <linux/mtd/mtd.h>
/* /*
* Flash memory areas : * Flash memory areas :
* - 0x0000 .. 0x07ff : IPL * - 0x0000 .. 0x07ff : IPL
...@@ -266,10 +268,22 @@ ...@@ -266,10 +268,22 @@
*/ */
#define DOC_LAYOUT_DPS_KEY_LENGTH 8 #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 * struct docg3 - DiskOnChip driver private data
* @dev: the device currently under control * @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) * @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 * @if_cfg: if true, reads are on 16bits, else reads are on 8bits
...@@ -287,7 +301,7 @@ ...@@ -287,7 +301,7 @@
*/ */
struct docg3 { struct docg3 {
struct device *dev; struct device *dev;
void __iomem *base; struct docg3_cascade *cascade;
unsigned int device_id:4; unsigned int device_id:4;
unsigned int if_cfg:1; unsigned int if_cfg:1;
unsigned int reliable:2; unsigned int reliable:2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment