1/*
2 * Flash memory access on Alchemy Pb1xxx boards
3 *
4 * (C) 2001 Pete Popov <ppopov@mvista.com>
5 *
6 * $Id: pb1xxx-flash.c,v 1.1.1.1 2008/10/15 03:26:35 james26_jang Exp $
7 */
8
9#include <linux/config.h>
10#include <linux/module.h>
11#include <linux/types.h>
12#include <linux/kernel.h>
13
14#include <linux/mtd/mtd.h>
15#include <linux/mtd/map.h>
16#include <linux/mtd/partitions.h>
17
18#include <asm/io.h>
19#include <asm/au1000.h>
20
21#ifdef 	DEBUG_RW
22#define	DBG(x...)	printk(x)
23#else
24#define	DBG(x...)
25#endif
26
27#ifdef CONFIG_MIPS_PB1000
28#define WINDOW_ADDR 0x1F800000
29#define WINDOW_SIZE 0x800000
30#endif
31
32__u8 physmap_read8(struct map_info *map, unsigned long ofs)
33{
34	__u8 ret;
35	ret = __raw_readb(map->map_priv_1 + ofs);
36	DBG("read8 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
37	return ret;
38}
39
40__u16 physmap_read16(struct map_info *map, unsigned long ofs)
41{
42	__u16 ret;
43	ret = __raw_readw(map->map_priv_1 + ofs);
44	DBG("read16 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
45	return ret;
46}
47
48__u32 physmap_read32(struct map_info *map, unsigned long ofs)
49{
50	__u32 ret;
51	ret = __raw_readl(map->map_priv_1 + ofs);
52	DBG("read32 from %x, %x\n", (unsigned)(map->map_priv_1 + ofs), ret);
53	return ret;
54}
55
56void physmap_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
57{
58	DBG("physmap_copy from %x to %x\n", (unsigned)from, (unsigned)to);
59	memcpy_fromio(to, map->map_priv_1 + from, len);
60}
61
62void physmap_write8(struct map_info *map, __u8 d, unsigned long adr)
63{
64	DBG("write8 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
65	__raw_writeb(d, map->map_priv_1 + adr);
66	mb();
67}
68
69void physmap_write16(struct map_info *map, __u16 d, unsigned long adr)
70{
71	DBG("write16 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
72	__raw_writew(d, map->map_priv_1 + adr);
73	mb();
74}
75
76void physmap_write32(struct map_info *map, __u32 d, unsigned long adr)
77{
78	DBG("write32 at %x, %x\n", (unsigned)(map->map_priv_1 + adr), d);
79	__raw_writel(d, map->map_priv_1 + adr);
80	mb();
81}
82
83void physmap_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
84{
85	DBG("physmap_copy_to %x from %x\n", (unsigned)to, (unsigned)from);
86	memcpy_toio(map->map_priv_1 + to, from, len);
87}
88
89
90
91static struct map_info pb1xxx_map = {
92	name:		"Pb1xxx flash",
93	read8: physmap_read8,
94	read16: physmap_read16,
95	read32: physmap_read32,
96	copy_from: physmap_copy_from,
97	write8: physmap_write8,
98	write16: physmap_write16,
99	write32: physmap_write32,
100	copy_to: physmap_copy_to,
101};
102
103
104#ifdef CONFIG_MIPS_PB1000
105
106static unsigned long flash_size = 0x00800000;
107static unsigned char flash_buswidth = 4;
108static struct mtd_partition pb1xxx_partitions[] = {
109        {
110                name: "yamon env",
111                size: 0x00020000,
112                offset: 0,
113                mask_flags: MTD_WRITEABLE
114        },{
115                name: "User FS",
116                size: 0x003e0000,
117                offset: 0x20000,
118        },{
119                name: "boot code",
120                size: 0x100000,
121                offset: 0x400000,
122                mask_flags: MTD_WRITEABLE
123        },{
124                name: "raw/kernel",
125                size: 0x300000,
126                offset: 0x500000
127        }
128};
129
130#elif defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
131
132static unsigned char flash_buswidth = 4;
133#if defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
134/* both 32MB banks will be used. Combine the first 32MB bank and the
135 * first 28MB of the second bank together into a single jffs/jffs2
136 * partition.
137 */
138static unsigned long flash_size = 0x04000000;
139#define WINDOW_ADDR 0x1C000000
140#define WINDOW_SIZE 0x4000000
141static struct mtd_partition pb1xxx_partitions[] = {
142        {
143                name: "User FS",
144                size:   0x3c00000,
145                offset: 0x0000000
146        },{
147                name: "yamon",
148                size: 0x0100000,
149                offset: 0x3c00000,
150                mask_flags: MTD_WRITEABLE
151        },{
152                name: "raw kernel",
153                size: 0x02c0000,
154                offset: 0x3d00000
155        }
156};
157#elif defined(CONFIG_MTD_PB1500_BOOT) && !defined(CONFIG_MTD_PB1500_USER)
158static unsigned long flash_size = 0x02000000;
159#define WINDOW_ADDR 0x1E000000
160#define WINDOW_SIZE 0x2000000
161static struct mtd_partition pb1xxx_partitions[] = {
162        {
163                name: "User FS",
164                size:   0x1c00000,
165                offset: 0x0000000
166        },{
167                name: "yamon",
168                size: 0x0100000,
169                offset: 0x1c00000,
170                mask_flags: MTD_WRITEABLE
171        },{
172                name: "raw kernel",
173                size: 0x02c0000,
174                offset: 0x1d00000
175        }
176};
177#elif !defined(CONFIG_MTD_PB1500_BOOT) && defined(CONFIG_MTD_PB1500_USER)
178static unsigned long flash_size = 0x02000000;
179#define WINDOW_ADDR 0x1C000000
180#define WINDOW_SIZE 0x2000000
181static struct mtd_partition pb1xxx_partitions[] = {
182        {
183                name: "User FS",
184                size:   0x1e00000,
185                offset: 0x0000000
186        },{
187                name: "raw kernel",
188                size: 0x0200000,
189                offset: 0x1e00000,
190        }
191};
192#else
193#error MTD_PB1500 define combo error /* should never happen */
194#endif
195#else
196#error Unsupported board
197#endif
198
199
200#define NB_OF(x)  (sizeof(x)/sizeof(x[0]))
201
202static struct mtd_partition *parsed_parts;
203static struct mtd_info *mymtd;
204
205int __init pb1xxx_mtd_init(void)
206{
207	struct mtd_partition *parts;
208	int nb_parts = 0;
209	char *part_type;
210
211	/* Default flash buswidth */
212	pb1xxx_map.buswidth = flash_buswidth;
213
214	/*
215	 * Static partition definition selection
216	 */
217	part_type = "static";
218	parts = pb1xxx_partitions;
219	nb_parts = NB_OF(pb1xxx_partitions);
220	pb1xxx_map.size = flash_size;
221
222	/*
223	 * Now let's probe for the actual flash.  Do it here since
224	 * specific machine settings might have been set above.
225	 */
226	printk(KERN_NOTICE "Pb1xxx flash: probing %d-bit flash bus\n",
227			pb1xxx_map.buswidth*8);
228	pb1xxx_map.map_priv_1 =
229		(unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
230	mymtd = do_map_probe("cfi_probe", &pb1xxx_map);
231	if (!mymtd) return -ENXIO;
232	mymtd->module = THIS_MODULE;
233
234	add_mtd_partitions(mymtd, parts, nb_parts);
235	return 0;
236}
237
238static void __exit pb1xxx_mtd_cleanup(void)
239{
240	if (mymtd) {
241		del_mtd_partitions(mymtd);
242		map_destroy(mymtd);
243		if (parsed_parts)
244			kfree(parsed_parts);
245	}
246}
247
248module_init(pb1xxx_mtd_init);
249module_exit(pb1xxx_mtd_cleanup);
250
251MODULE_AUTHOR("Pete Popov");
252MODULE_DESCRIPTION("Pb1xxx CFI map driver");
253MODULE_LICENSE("GPL");
254