diff options
Diffstat (limited to 'drivers/mtd/nand/ndfc.c')
-rw-r--r-- | drivers/mtd/nand/ndfc.c | 65 |
1 files changed, 36 insertions, 29 deletions
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index bbe6d451290d..ea2dea8a9c88 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/of_platform.h> | 33 | #include <linux/of_platform.h> |
34 | #include <asm/io.h> | 34 | #include <asm/io.h> |
35 | 35 | ||
36 | #define NDFC_MAX_CS 4 | ||
36 | 37 | ||
37 | struct ndfc_controller { | 38 | struct ndfc_controller { |
38 | struct platform_device *ofdev; | 39 | struct platform_device *ofdev; |
@@ -41,17 +42,16 @@ struct ndfc_controller { | |||
41 | struct nand_chip chip; | 42 | struct nand_chip chip; |
42 | int chip_select; | 43 | int chip_select; |
43 | struct nand_hw_control ndfc_control; | 44 | struct nand_hw_control ndfc_control; |
44 | #ifdef CONFIG_MTD_PARTITIONS | ||
45 | struct mtd_partition *parts; | 45 | struct mtd_partition *parts; |
46 | #endif | ||
47 | }; | 46 | }; |
48 | 47 | ||
49 | static struct ndfc_controller ndfc_ctrl; | 48 | static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS]; |
50 | 49 | ||
51 | static void ndfc_select_chip(struct mtd_info *mtd, int chip) | 50 | static void ndfc_select_chip(struct mtd_info *mtd, int chip) |
52 | { | 51 | { |
53 | uint32_t ccr; | 52 | uint32_t ccr; |
54 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 53 | struct nand_chip *nchip = mtd->priv; |
54 | struct ndfc_controller *ndfc = nchip->priv; | ||
55 | 55 | ||
56 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); | 56 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); |
57 | if (chip >= 0) { | 57 | if (chip >= 0) { |
@@ -64,7 +64,8 @@ static void ndfc_select_chip(struct mtd_info *mtd, int chip) | |||
64 | 64 | ||
65 | static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 65 | static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
66 | { | 66 | { |
67 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 67 | struct nand_chip *chip = mtd->priv; |
68 | struct ndfc_controller *ndfc = chip->priv; | ||
68 | 69 | ||
69 | if (cmd == NAND_CMD_NONE) | 70 | if (cmd == NAND_CMD_NONE) |
70 | return; | 71 | return; |
@@ -77,7 +78,8 @@ static void ndfc_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
77 | 78 | ||
78 | static int ndfc_ready(struct mtd_info *mtd) | 79 | static int ndfc_ready(struct mtd_info *mtd) |
79 | { | 80 | { |
80 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 81 | struct nand_chip *chip = mtd->priv; |
82 | struct ndfc_controller *ndfc = chip->priv; | ||
81 | 83 | ||
82 | return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; | 84 | return in_be32(ndfc->ndfcbase + NDFC_STAT) & NDFC_STAT_IS_READY; |
83 | } | 85 | } |
@@ -85,7 +87,8 @@ static int ndfc_ready(struct mtd_info *mtd) | |||
85 | static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) | 87 | static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) |
86 | { | 88 | { |
87 | uint32_t ccr; | 89 | uint32_t ccr; |
88 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 90 | struct nand_chip *chip = mtd->priv; |
91 | struct ndfc_controller *ndfc = chip->priv; | ||
89 | 92 | ||
90 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); | 93 | ccr = in_be32(ndfc->ndfcbase + NDFC_CCR); |
91 | ccr |= NDFC_CCR_RESET_ECC; | 94 | ccr |= NDFC_CCR_RESET_ECC; |
@@ -96,7 +99,8 @@ static void ndfc_enable_hwecc(struct mtd_info *mtd, int mode) | |||
96 | static int ndfc_calculate_ecc(struct mtd_info *mtd, | 99 | static int ndfc_calculate_ecc(struct mtd_info *mtd, |
97 | const u_char *dat, u_char *ecc_code) | 100 | const u_char *dat, u_char *ecc_code) |
98 | { | 101 | { |
99 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 102 | struct nand_chip *chip = mtd->priv; |
103 | struct ndfc_controller *ndfc = chip->priv; | ||
100 | uint32_t ecc; | 104 | uint32_t ecc; |
101 | uint8_t *p = (uint8_t *)&ecc; | 105 | uint8_t *p = (uint8_t *)&ecc; |
102 | 106 | ||
@@ -119,7 +123,8 @@ static int ndfc_calculate_ecc(struct mtd_info *mtd, | |||
119 | */ | 123 | */ |
120 | static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | 124 | static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
121 | { | 125 | { |
122 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 126 | struct nand_chip *chip = mtd->priv; |
127 | struct ndfc_controller *ndfc = chip->priv; | ||
123 | uint32_t *p = (uint32_t *) buf; | 128 | uint32_t *p = (uint32_t *) buf; |
124 | 129 | ||
125 | for(;len > 0; len -= 4) | 130 | for(;len > 0; len -= 4) |
@@ -128,7 +133,8 @@ static void ndfc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | |||
128 | 133 | ||
129 | static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 134 | static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
130 | { | 135 | { |
131 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 136 | struct nand_chip *chip = mtd->priv; |
137 | struct ndfc_controller *ndfc = chip->priv; | ||
132 | uint32_t *p = (uint32_t *) buf; | 138 | uint32_t *p = (uint32_t *) buf; |
133 | 139 | ||
134 | for(;len > 0; len -= 4) | 140 | for(;len > 0; len -= 4) |
@@ -137,7 +143,8 @@ static void ndfc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
137 | 143 | ||
138 | static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | 144 | static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
139 | { | 145 | { |
140 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 146 | struct nand_chip *chip = mtd->priv; |
147 | struct ndfc_controller *ndfc = chip->priv; | ||
141 | uint32_t *p = (uint32_t *) buf; | 148 | uint32_t *p = (uint32_t *) buf; |
142 | 149 | ||
143 | for(;len > 0; len -= 4) | 150 | for(;len > 0; len -= 4) |
@@ -152,13 +159,11 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | |||
152 | static int ndfc_chip_init(struct ndfc_controller *ndfc, | 159 | static int ndfc_chip_init(struct ndfc_controller *ndfc, |
153 | struct device_node *node) | 160 | struct device_node *node) |
154 | { | 161 | { |
155 | #ifdef CONFIG_MTD_PARTITIONS | ||
156 | #ifdef CONFIG_MTD_CMDLINE_PARTS | 162 | #ifdef CONFIG_MTD_CMDLINE_PARTS |
157 | static const char *part_types[] = { "cmdlinepart", NULL }; | 163 | static const char *part_types[] = { "cmdlinepart", NULL }; |
158 | #else | 164 | #else |
159 | static const char *part_types[] = { NULL }; | 165 | static const char *part_types[] = { NULL }; |
160 | #endif | 166 | #endif |
161 | #endif | ||
162 | struct device_node *flash_np; | 167 | struct device_node *flash_np; |
163 | struct nand_chip *chip = &ndfc->chip; | 168 | struct nand_chip *chip = &ndfc->chip; |
164 | int ret; | 169 | int ret; |
@@ -179,6 +184,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
179 | chip->ecc.mode = NAND_ECC_HW; | 184 | chip->ecc.mode = NAND_ECC_HW; |
180 | chip->ecc.size = 256; | 185 | chip->ecc.size = 256; |
181 | chip->ecc.bytes = 3; | 186 | chip->ecc.bytes = 3; |
187 | chip->priv = ndfc; | ||
182 | 188 | ||
183 | ndfc->mtd.priv = chip; | 189 | ndfc->mtd.priv = chip; |
184 | ndfc->mtd.owner = THIS_MODULE; | 190 | ndfc->mtd.owner = THIS_MODULE; |
@@ -198,25 +204,18 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, | |||
198 | if (ret) | 204 | if (ret) |
199 | goto err; | 205 | goto err; |
200 | 206 | ||
201 | #ifdef CONFIG_MTD_PARTITIONS | ||
202 | ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); | 207 | ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0); |
203 | if (ret < 0) | 208 | if (ret < 0) |
204 | goto err; | 209 | goto err; |
205 | 210 | ||
206 | #ifdef CONFIG_MTD_OF_PARTS | ||
207 | if (ret == 0) { | 211 | if (ret == 0) { |
208 | ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, | 212 | ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np, |
209 | &ndfc->parts); | 213 | &ndfc->parts); |
210 | if (ret < 0) | 214 | if (ret < 0) |
211 | goto err; | 215 | goto err; |
212 | } | 216 | } |
213 | #endif | ||
214 | 217 | ||
215 | if (ret > 0) | 218 | ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret); |
216 | ret = add_mtd_partitions(&ndfc->mtd, ndfc->parts, ret); | ||
217 | else | ||
218 | #endif | ||
219 | ret = add_mtd_device(&ndfc->mtd); | ||
220 | 219 | ||
221 | err: | 220 | err: |
222 | of_node_put(flash_np); | 221 | of_node_put(flash_np); |
@@ -227,15 +226,10 @@ err: | |||
227 | 226 | ||
228 | static int __devinit ndfc_probe(struct platform_device *ofdev) | 227 | static int __devinit ndfc_probe(struct platform_device *ofdev) |
229 | { | 228 | { |
230 | struct ndfc_controller *ndfc = &ndfc_ctrl; | 229 | struct ndfc_controller *ndfc; |
231 | const __be32 *reg; | 230 | const __be32 *reg; |
232 | u32 ccr; | 231 | u32 ccr; |
233 | int err, len; | 232 | int err, len, cs; |
234 | |||
235 | spin_lock_init(&ndfc->ndfc_control.lock); | ||
236 | init_waitqueue_head(&ndfc->ndfc_control.wq); | ||
237 | ndfc->ofdev = ofdev; | ||
238 | dev_set_drvdata(&ofdev->dev, ndfc); | ||
239 | 233 | ||
240 | /* Read the reg property to get the chip select */ | 234 | /* Read the reg property to get the chip select */ |
241 | reg = of_get_property(ofdev->dev.of_node, "reg", &len); | 235 | reg = of_get_property(ofdev->dev.of_node, "reg", &len); |
@@ -243,7 +237,20 @@ static int __devinit ndfc_probe(struct platform_device *ofdev) | |||
243 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); | 237 | dev_err(&ofdev->dev, "unable read reg property (%d)\n", len); |
244 | return -ENOENT; | 238 | return -ENOENT; |
245 | } | 239 | } |
246 | ndfc->chip_select = be32_to_cpu(reg[0]); | 240 | |
241 | cs = be32_to_cpu(reg[0]); | ||
242 | if (cs >= NDFC_MAX_CS) { | ||
243 | dev_err(&ofdev->dev, "invalid CS number (%d)\n", cs); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | ndfc = &ndfc_ctrl[cs]; | ||
248 | ndfc->chip_select = cs; | ||
249 | |||
250 | spin_lock_init(&ndfc->ndfc_control.lock); | ||
251 | init_waitqueue_head(&ndfc->ndfc_control.wq); | ||
252 | ndfc->ofdev = ofdev; | ||
253 | dev_set_drvdata(&ofdev->dev, ndfc); | ||
247 | 254 | ||
248 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); | 255 | ndfc->ndfcbase = of_iomap(ofdev->dev.of_node, 0); |
249 | if (!ndfc->ndfcbase) { | 256 | if (!ndfc->ndfcbase) { |