1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
diff -Nurd linux-2.6.24-base/arch/arm/mach-hipox/hipox.c linux-2.6.24/arch/arm/mach-hipox/hipox.c
--- linux-2.6.24-base/arch/arm/mach-hipox/hipox.c 2009-04-16 13:21:06.000000000 +0000
+++ linux-2.6.24/arch/arm/mach-hipox/hipox.c 2009-04-17 07:04:33.000000000 +0000
@@ -155,7 +155,7 @@
{ CORE_MODULE_BASE, __phys_to_pfn(CORE_MODULE_BASE_PA), SZ_4K, MT_DEVICE },
{ APB_BRIDGE_A_BASE, __phys_to_pfn(APB_BRIDGE_A_BASE_PA), SZ_16M, MT_DEVICE },
{ STATIC_CONTROL_BASE, __phys_to_pfn(STATIC_CONTROL_BASE_PA), SZ_4K, MT_DEVICE },
- { STATIC_CS0_BASE, __phys_to_pfn(STATIC_CS0_BASE_PA), SZ_4K, MT_DEVICE },
+ { STATIC_CS0_BASE, __phys_to_pfn(STATIC_CS0_BASE_PA), SZ_4M, MT_DEVICE },
{ STATIC_CS1_BASE, __phys_to_pfn(STATIC_CS1_BASE_PA), SZ_4K, MT_DEVICE },
{ STATIC_CS2_BASE, __phys_to_pfn(STATIC_CS2_BASE_PA), SZ_4K, MT_DEVICE },
{ APB_BRIDGE_B_BASE, __phys_to_pfn(APB_BRIDGE_B_BASE_PA), SZ_16M, MT_DEVICE },
diff -Nurd linux-2.6.24-base/drivers/mtd/maps/physmap.c linux-2.6.24/drivers/mtd/maps/physmap.c
--- linux-2.6.24-base/drivers/mtd/maps/physmap.c 2008-01-24 22:58:37.000000000 +0000
+++ linux-2.6.24/drivers/mtd/maps/physmap.c 2009-04-17 07:04:33.000000000 +0000
@@ -22,6 +22,12 @@
#include <linux/mtd/physmap.h>
#include <asm/io.h>
+#if defined (CONFIG_ARCH_HIPOX)
+#include <asm/arch/hardware.h>
+/* timing for NOR flash */
+#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f0d /* fast ASIC settings, 70ns */
+#endif /* CONFIG_ARCH_HIPOX */
+
struct physmap_flash_info {
struct mtd_info *mtd;
struct map_info map;
@@ -88,6 +94,11 @@
if (physmap_data == NULL)
return -ENODEV;
+#if defined (CONFIG_ARCH_HIPOX)
+/* init timing for static memory controller */
+ writel(STATIC_BUS_FLASH_CONFIG, STATIC_CONTROL_BANK0);
+#endif /* CONFIG_ARCH_HIPOX */
+
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
(unsigned long long)(dev->resource->end - dev->resource->start + 1),
(unsigned long long)dev->resource->start);
@@ -207,6 +218,10 @@
#endif
#ifdef PHYSMAP_COMPAT
+static void physmap_flash_release(struct device *dev)
+{
+}
+
static struct physmap_flash_data physmap_flash_data = {
.width = CONFIG_MTD_PHYSMAP_BANKWIDTH,
};
@@ -222,6 +237,7 @@
.id = 0,
.dev = {
.platform_data = &physmap_flash_data,
+ .release = physmap_flash_release, /* needed for module build */
},
.num_resources = 1,
.resource = &physmap_flash_resource,
diff -Nurd linux-2.6.24-base/drivers/mtd/nand/Kconfig linux-2.6.24/drivers/mtd/nand/Kconfig
--- linux-2.6.24-base/drivers/mtd/nand/Kconfig 2008-01-24 22:58:37.000000000 +0000
+++ linux-2.6.24/drivers/mtd/nand/Kconfig 2009-04-17 07:04:33.000000000 +0000
@@ -283,6 +283,11 @@
tristate "Support for NAND Flash on CM-X270 modules"
depends on MTD_NAND && MACH_ARMCORE
+config MTD_NAND_HIPOX
+ tristate "NAND Flash device on OXE810 based HydraIP board"
+ depends on MTD_NAND && ARCH_HIPOX
+ help
+ Support for NAND flash on OXE180 based HydraIP platform.
config MTD_NAND_NANDSIM
tristate "Support for NAND Flash Simulator"
diff -Nurd linux-2.6.24-base/drivers/mtd/nand/Makefile linux-2.6.24/drivers/mtd/nand/Makefile
--- linux-2.6.24-base/drivers/mtd/nand/Makefile 2008-01-24 22:58:37.000000000 +0000
+++ linux-2.6.24/drivers/mtd/nand/Makefile 2009-04-17 07:04:33.000000000 +0000
@@ -29,5 +29,6 @@
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
obj-$(CONFIG_MTD_ALAUDA) += alauda.o
+obj-$(CONFIG_MTD_NAND_HIPOX) += hipox_nand.o
nand-objs := nand_base.o nand_bbt.o
diff -Nurd linux-2.6.24-base/drivers/mtd/nand/hipox_nand.c linux-2.6.24/drivers/mtd/nand/hipox_nand.c
--- linux-2.6.24-base/drivers/mtd/nand/hipox_nand.c 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.24/drivers/mtd/nand/hipox_nand.c 2009-04-17 07:26:17.000000000 +0000
@@ -0,0 +1,230 @@
+/*
+ * drivers/mtd/nand/hipox_nand.c
+ *
+ * Copyright (C) 2009 DResearch Digital Media Systems GmbH
+ *
+ * $Id:$
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Overview:
+ * This is a device driver for the NAND flash device found on the
+ * OXE810 based HydraIP board.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/sizes.h>
+#include <asm/mach-types.h>
+
+// the testboards ran down to a value of 4
+//#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f3f /* slow settings, 345 ns */
+//#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f0d /* fast settings, 70 ns */
+//#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f09 /* ultra fast settings, 50 ns */
+#define STATIC_BUS_FLASH_CONFIG 0x4f1f3f04 /* warp settings, 27 ns */
+
+/*
+ * MTD structure for HydraIP board
+ */
+static struct mtd_info *hipox_nand_mtd = NULL;
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "cmdlinepart", NULL };
+
+#define NUM_PARTITIONS 2
+
+/*
+ * Define static partitions for flash device
+ */
+static struct mtd_partition partition_info[NUM_PARTITIONS] = {
+ {
+ .name = "boot",
+ .offset = 0x00000000,
+ .size = 0x02000000,
+ }, {
+ .name = "system",
+ .offset = 0x02000000,
+ .size = 0x0e000000,
+ },
+};
+#endif
+
+
+/*
+ * hardware specific access to control-lines
+ */
+static void hipox_nand_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+ struct nand_chip *this = mtd->priv;
+
+ if (ctrl & NAND_CTRL_CHANGE) {
+ unsigned long IO_ADDR_W = (unsigned long) this->IO_ADDR_W;
+
+ IO_ADDR_W = CONFIG_SYS_NAND_BASE;
+
+ if (ctrl & NAND_NCE)
+ writel(0x20000000, GPIO_A_OUTPUT_CLEAR); /* assert CS-NAND */
+ else
+ writel(0x20000000, GPIO_A_OUTPUT_SET); /* deassert CS-NAND */
+
+ if (ctrl & NAND_CLE)
+ IO_ADDR_W = CONFIG_SYS_NAND_COMMAND_LATCH;
+ if (ctrl & NAND_ALE)
+ IO_ADDR_W = CONFIG_SYS_NAND_ADDRESS_LATCH;
+
+ this->IO_ADDR_W = (void *)IO_ADDR_W;
+ }
+
+ if (cmd != NAND_CMD_NONE)
+ writeb(cmd, this->IO_ADDR_W);
+}
+
+static void hipox_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+ struct nand_chip *chip = mtd->priv;
+ volatile uint8_t *io = chip->IO_ADDR_R;
+
+ if((((int)buf) & 1) || (len & 1))
+ {
+ while(len-- > 0)
+ *buf++ = *io;
+
+ return;
+ }
+
+ // now it's aligned, group to 16 bit access
+ {
+ uint16_t *ptr16 = (uint16_t *)buf;
+ len >>= 1;
+
+ while(len-- > 0)
+ *ptr16++ = *io | (*io << 8);
+ }
+}
+
+/*
+ * Main initialization routine
+ */
+static int __init hipox_nand_init(void)
+{
+ struct nand_chip *this;
+ const char *part_type = NULL;
+ int mtd_parts_nb = 0;
+ struct mtd_partition *mtd_parts = NULL;
+
+ if (!machine_is_hipox())
+ return -ENXIO;
+
+ /* Allocate memory for MTD device structure and private data */
+ hipox_nand_mtd = kmalloc(sizeof(struct mtd_info)+sizeof(struct nand_chip), GFP_KERNEL);
+
+ if (!hipox_nand_mtd) {
+ printk("Unable to allocate HIPOX_NAND MTD device structure.\n");
+ return -ENOMEM;
+ }
+
+ /* Get pointer to private data */
+ this = (struct nand_chip *)&hipox_nand_mtd[1];
+
+ if (!this) {
+ printk("Unable to allocate HIPOX_NAND MTD NAND device structure.\n");
+ kfree(hipox_nand_mtd);
+ return -ENOMEM;
+ }
+
+ writel(STATIC_BUS_FLASH_CONFIG, STATIC_CONTROL_BANK0);
+
+ /* Initialize structures */
+ memset(hipox_nand_mtd, 0, sizeof(struct mtd_info));
+ memset(this, 0, sizeof(struct nand_chip));
+
+ // assert CS-NAND
+ writel(0x20000000, GPIO_A_OUTPUT_SET);
+ writel(0x20000000, GPIO_A_OUTPUT_ENABLE_SET);
+
+ // deselect alternate function
+ writel(readl(SYS_CTRL_GPIO_PRIMSEL_CTRL_0) & ~0x20000000,
+ SYS_CTRL_GPIO_PRIMSEL_CTRL_0);
+ writel(readl(SYS_CTRL_GPIO_SECSEL_CTRL_0) & ~0x20000000,
+ SYS_CTRL_GPIO_SECSEL_CTRL_0);
+ writel(readl(SYS_CTRL_GPIO_TERTSEL_CTRL_0) & ~0x20000000,
+ SYS_CTRL_GPIO_TERTSEL_CTRL_0);
+
+ writel(0x20000000, GPIO_A_OUTPUT_CLEAR);
+
+ // reset NAND unit
+ writeb(0xff, CONFIG_SYS_NAND_COMMAND_LATCH); // reset command
+ udelay(500);
+
+ // deassert CS-NAND
+ writel(0x20000000, GPIO_A_OUTPUT_SET);
+
+ /* Link the private data with the MTD structure */
+ hipox_nand_mtd->priv = this;
+ hipox_nand_mtd->owner = THIS_MODULE;
+
+ /* insert callbacks */
+ this->IO_ADDR_R = (void *)CONFIG_SYS_NAND_BASE;
+ this->IO_ADDR_W = (void *)CONFIG_SYS_NAND_BASE;
+ this->cmd_ctrl = hipox_nand_hwcontrol;
+ this->read_buf = hipox_read_buf;
+ this->chip_delay = 25; // 23 still worked on our EvalBoard
+ this->ecc.mode = NAND_ECC_SOFT;
+ printk("Searching for NAND flash...\n");
+
+ /* Scan to find existence of the device */
+ if (nand_scan(hipox_nand_mtd, 1)) {
+ kfree(hipox_nand_mtd);
+ return -ENXIO;
+ }
+#ifdef CONFIG_MTD_PARTITIONS
+ hipox_nand_mtd->name = "hipox-nand";
+ mtd_parts_nb = parse_mtd_partitions(hipox_nand_mtd, part_probes, &mtd_parts, 0);
+ if (mtd_parts_nb > 0)
+ part_type = "command line";
+ else
+ mtd_parts_nb = 0;
+#endif
+ if (mtd_parts_nb == 0) {
+ mtd_parts = partition_info;
+ mtd_parts_nb = NUM_PARTITIONS;
+ part_type = "static";
+ }
+
+ /* Register the partitions */
+ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
+ add_mtd_partitions(hipox_nand_mtd, mtd_parts, mtd_parts_nb);
+
+ /* Return happy */
+ return 0;
+}
+
+module_init(hipox_nand_init);
+
+/*
+ * Clean up routine
+ */
+static void __exit hipox_nand_cleanup(void)
+{
+ /* Unregister the device */
+ //del_mtd_device(hipox_nand_mtd);
+ nand_release(hipox_nand_mtd);
+
+ /* Free the MTD device structure */
+ kfree(hipox_nand_mtd);
+}
+
+module_exit(hipox_nand_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Rene Grosser <rgrosser@dresearch.de>, Steffen Sledz <sledz@dresearch.de>");
+MODULE_DESCRIPTION("MTD map driver for OXE810 based HydraIP device");
diff -Nurd linux-2.6.24-base/include/asm-arm/arch-hipox/hardware.h linux-2.6.24/include/asm-arm/arch-hipox/hardware.h
--- linux-2.6.24-base/include/asm-arm/arch-hipox/hardware.h 2009-04-16 13:21:35.000000000 +0000
+++ linux-2.6.24/include/asm-arm/arch-hipox/hardware.h 2009-04-17 07:25:53.000000000 +0000
@@ -134,6 +134,11 @@
#define COPRO_REGS_BASE (APB_BRIDGE_B_BASE + 0xB00000)
#define DMA_SG_BASE (APB_BRIDGE_B_BASE + 0xC00000)
+/* NAND access */
+#define CONFIG_SYS_NAND_BASE STATIC_CS0_BASE
+#define CONFIG_SYS_NAND_ADDRESS_LATCH (CONFIG_SYS_NAND_BASE + 0x8000)
+#define CONFIG_SYS_NAND_COMMAND_LATCH (CONFIG_SYS_NAND_BASE + 0x4000)
+
/* Interrupt Controller registers */
#define RPS_IC_BASE RPS_BASE
#define RPS_IRQ_STATUS (RPS_IC_BASE)
|