1/*
2 * $Id: walnut.c,v 1.1.1.1 2007/08/03 18:52:44 Exp $
3 *
4 * Mapping for Walnut flash
5 * (used ebony.c as a "framework")
6 *
7 * Heikki Lindholm <holindho@infradead.org>
8 *
9 *
10 * This program is free software; you can redistribute  it and/or modify it
11 * under  the terms of  the GNU General  Public License as published by the
12 * Free Software Foundation;  either version 2 of the  License, or (at your
13 * option) any later version.
14 */
15
16#include <linux/module.h>
17#include <linux/types.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/mtd/mtd.h>
21#include <linux/mtd/map.h>
22#include <linux/mtd/partitions.h>
23#include <asm/io.h>
24#include <asm/ibm4xx.h>
25#include <platforms/4xx/walnut.h>
26
27/* these should be in platforms/4xx/walnut.h ? */
28#define WALNUT_FLASH_ONBD_N(x)		(x & 0x02)
29#define WALNUT_FLASH_SRAM_SEL(x)	(x & 0x01)
30#define WALNUT_FLASH_LOW		0xFFF00000
31#define WALNUT_FLASH_HIGH		0xFFF80000
32#define WALNUT_FLASH_SIZE		0x80000
33
34static struct mtd_info *flash;
35
36static struct map_info walnut_map = {
37	.name =		"Walnut flash",
38	.size =		WALNUT_FLASH_SIZE,
39	.bankwidth =	1,
40};
41
42/* Actually, OpenBIOS is the last 128 KiB of the flash - better
43 * partitioning could be made */
44static struct mtd_partition walnut_partitions[] = {
45	{
46		.name =   "OpenBIOS",
47		.offset = 0x0,
48		.size =   WALNUT_FLASH_SIZE,
49		/*.mask_flags = MTD_WRITEABLE, */ /* force read-only */
50	}
51};
52
53int __init init_walnut(void)
54{
55	u8 fpga_brds1;
56	void *fpga_brds1_adr;
57	void *fpga_status_adr;
58	unsigned long flash_base;
59
60	/* this should already be mapped (platform/4xx/walnut.c) */
61	fpga_status_adr = ioremap(WALNUT_FPGA_BASE, 8);
62	if (!fpga_status_adr)
63		return -ENOMEM;
64
65	fpga_brds1_adr = fpga_status_adr+5;
66	fpga_brds1 = readb(fpga_brds1_adr);
67	/* iounmap(fpga_status_adr); */
68
69	if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
70		printk("The on-board flash is disabled (U79 sw 5)!");
71		iounmap(fpga_status_adr);
72		return -EIO;
73	}
74	if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
75		flash_base = WALNUT_FLASH_LOW;
76	else
77		flash_base = WALNUT_FLASH_HIGH;
78
79	walnut_map.phys = flash_base;
80	walnut_map.virt =
81		(void __iomem *)ioremap(flash_base, walnut_map.size);
82
83	if (!walnut_map.virt) {
84		printk("Failed to ioremap flash.\n");
85		iounmap(fpga_status_adr);
86		return -EIO;
87	}
88
89	simple_map_init(&walnut_map);
90
91	flash = do_map_probe("jedec_probe", &walnut_map);
92	if (flash) {
93		flash->owner = THIS_MODULE;
94		add_mtd_partitions(flash, walnut_partitions,
95					ARRAY_SIZE(walnut_partitions));
96	} else {
97		printk("map probe failed for flash\n");
98		iounmap(fpga_status_adr);
99		return -ENXIO;
100	}
101
102	iounmap(fpga_status_adr);
103	return 0;
104}
105
106static void __exit cleanup_walnut(void)
107{
108	if (flash) {
109		del_mtd_partitions(flash);
110		map_destroy(flash);
111	}
112
113	if (walnut_map.virt) {
114		iounmap((void *)walnut_map.virt);
115		walnut_map.virt = 0;
116	}
117}
118
119module_init(init_walnut);
120module_exit(cleanup_walnut);
121
122MODULE_LICENSE("GPL");
123MODULE_AUTHOR("Heikki Lindholm <holindho@infradead.org>");
124MODULE_DESCRIPTION("MTD map and partitions for IBM 405GP Walnut boards");
125