]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/board-omap3evm-flash.c
NAND support for OMAP3 EVM
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / board-omap3evm-flash.c
1 /*
2  * board-omap3evm-flash.c
3  *
4  * Copyright (c) 2008 Texas Instruments,
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/platform_device.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/partitions.h>
15 #include <linux/mtd/nand.h>
16 #include <linux/mtd/onenand_regs.h>
17 #include <linux/types.h>
18 #include <linux/io.h>
19
20 #include <asm/mach/flash.h>
21 #include <mach/onenand.h>
22 #include <mach/board.h>
23 #include <mach/gpmc.h>
24 #include <mach/nand.h>
25
26 static int omap3evm_onenand_setup(void __iomem *, int freq);
27
28 static struct mtd_partition omap3evm_onenand_partitions[] = {
29         {
30                 .name           = "xloader-onenand",
31                 .offset         = 0,
32                 .size           = 4*(64*2048),
33                 .mask_flags     = MTD_WRITEABLE
34         },
35         {
36                 .name           = "uboot-onenand",
37                 .offset         = MTDPART_OFS_APPEND,
38                 .size           =  15*(64*2048),
39                 .mask_flags     = MTD_WRITEABLE
40         },
41         {
42                 .name           = "params-onenand",
43                 .offset         = MTDPART_OFS_APPEND,
44                 .size           = 1*(64*2048),
45         },
46         {
47                 .name           = "linux-onenand",
48                 .offset         = MTDPART_OFS_APPEND,
49                 .size           = 40*(64*2048),
50         },
51         {
52                 .name           = "jffs2-onenand",
53                 .offset         = MTDPART_OFS_APPEND,
54                 .size           = MTDPART_SIZ_FULL,
55         },
56 };
57
58 static struct omap_onenand_platform_data omap3evm_onenand_data = {
59         .parts = omap3evm_onenand_partitions,
60         .nr_parts = ARRAY_SIZE(omap3evm_onenand_partitions),
61         .onenand_setup = omap3evm_onenand_setup,
62         .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
63 };
64
65 static struct platform_device omap3evm_onenand_device = {
66         .name           = "omap2-onenand",
67         .id             = -1,
68         .dev = {
69                 .platform_data = &omap3evm_onenand_data,
70         },
71 };
72
73 static struct mtd_partition omap3evm_nand_partitions[] = {
74         /* All the partition sizes are listed in terms of NAND block size */
75         {
76                 .name           = "xloader-nand",
77                 .offset         = 0,
78                 .size           = 4*(128 * 1024),
79                 .mask_flags     = MTD_WRITEABLE
80         },
81         {
82                 .name           = "uboot-nand",
83                 .offset         = MTDPART_OFS_APPEND,
84                 .size           = 14*(128 * 1024),
85                 .mask_flags     = MTD_WRITEABLE
86         },
87         {
88                 .name           = "params-nand",
89
90                 .offset         = MTDPART_OFS_APPEND,
91                 .size           = 2*(128 * 1024)
92         },
93         {
94                 .name           = "linux-nand",
95                 .offset         = MTDPART_OFS_APPEND,
96                 .size           = 40*(128 * 1024)
97         },
98         {
99                 .name           = "jffs2-nand",
100                 .size           = MTDPART_SIZ_FULL,
101                 .offset         = MTDPART_OFS_APPEND,
102         },
103 };
104
105 static struct omap_nand_platform_data omap3evm_nand_data = {
106         .parts          = omap3evm_nand_partitions,
107         .nr_parts       = ARRAY_SIZE(omap3evm_nand_partitions),
108         .nand_setup     = NULL,
109         .dma_channel    = -1,           /* disable DMA in OMAP NAND driver */
110         .dev_ready      = NULL,
111 };
112
113 static struct resource omap3evm_nand_resource = {
114         .flags          = IORESOURCE_MEM,
115 };
116
117 static struct platform_device omap3evm_nand_device = {
118         .name           = "omap2-nand",
119         .id             = 0,
120         .dev            = {
121                 .platform_data  = &omap3evm_nand_data,
122         },
123         .num_resources  = 1,
124         .resource       = &omap3evm_nand_resource,
125 };
126
127 /*
128  *      omap3evm_onenand_setup - Set the onenand sync mode
129  *      @onenand_base:  The onenand base address in GPMC memory map
130  *
131  */
132
133 static int omap3evm_onenand_setup(void __iomem *onenand_base, int freq)
134 {
135         /* nothing is required to be setup for onenand as of now */
136         return 0;
137 }
138
139 void __init omap3evm_flash_init(void)
140 {
141         u8              cs = 0;
142         u8              onenandcs = GPMC_CS_NUM + 1, nandcs = GPMC_CS_NUM + 1;
143         u32             gpmc_base_add = OMAP34XX_GPMC_VIRT;
144
145         while (cs < GPMC_CS_NUM) {
146                 u32 ret = 0;
147                 ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
148
149                 /*
150                 * xloader/Uboot would have programmed the NAND/oneNAND
151                 * base address for us This is a ugly hack. The proper
152                 * way of doing this is to pass the setup of u-boot up
153                 * to kernel using kernel params - something on the
154                 * lines of machineID. Check if NAND/oneNAND is configured
155                 */
156                 if ((ret & 0xC00) == 0x800) {
157                         /* Found it!! */
158                         if (nandcs > GPMC_CS_NUM)
159                                 nandcs = cs;
160                 } else {
161                         ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
162                         if ((ret & 0x3F) == (ONENAND_MAP >> 24))
163                                 onenandcs = cs;
164                 }
165                 cs++;
166         }
167         if ((nandcs > GPMC_CS_NUM) && (onenandcs > GPMC_CS_NUM)) {
168                 printk(KERN_INFO "NAND/OneNAND: Unable to find configuration "
169                                 " in GPMC\n ");
170                 return;
171         }
172
173         if (nandcs < GPMC_CS_NUM) {
174                 omap3evm_nand_data.cs   = nandcs;
175                 omap3evm_nand_data.gpmc_cs_baseaddr = (void *)(gpmc_base_add +
176                                         GPMC_CS0_BASE + nandcs*GPMC_CS_SIZE);
177                 omap3evm_nand_data.gpmc_baseaddr   = (void *) (gpmc_base_add);
178
179                 if (platform_device_register(&omap3evm_nand_device) < 0) {
180                         printk(KERN_ERR "Unable to register NAND device\n");
181                 }
182         }
183
184         if (onenandcs < GPMC_CS_NUM) {
185                 omap3evm_onenand_data.cs = onenandcs;
186                 if (platform_device_register(&omap3evm_onenand_device) < 0)
187                         printk(KERN_ERR "Unable to register OneNAND device\n");
188         }
189 }
190