18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Handle mapping of the NOR flash on implementa A7 boards
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2002 SYSGO Real-Time Solutions GmbH
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/module.h>
98c2ecf20Sopenharmony_ci#include <linux/types.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <asm/io.h>
138c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
148c2ecf20Sopenharmony_ci#include <linux/mtd/map.h>
158c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h>
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define WINDOW_ADDR0 0x00000000      /* physical properties of flash */
188c2ecf20Sopenharmony_ci#define WINDOW_SIZE0 0x00800000
198c2ecf20Sopenharmony_ci#define WINDOW_ADDR1 0x10000000      /* physical properties of flash */
208c2ecf20Sopenharmony_ci#define WINDOW_SIZE1 0x00800000
218c2ecf20Sopenharmony_ci#define NUM_FLASHBANKS 2
228c2ecf20Sopenharmony_ci#define BUSWIDTH     4
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#define MSG_PREFIX "impA7:"   /* prefix for our printk()'s */
258c2ecf20Sopenharmony_ci#define MTDID      "impa7-%d"  /* for mtdparts= partitioning */
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic struct mtd_info *impa7_mtd[NUM_FLASHBANKS];
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic const char * const rom_probe_types[] = { "jedec_probe", NULL };
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistatic struct map_info impa7_map[NUM_FLASHBANKS] = {
328c2ecf20Sopenharmony_ci	{
338c2ecf20Sopenharmony_ci		.name = "impA7 NOR Flash Bank #0",
348c2ecf20Sopenharmony_ci		.size = WINDOW_SIZE0,
358c2ecf20Sopenharmony_ci		.bankwidth = BUSWIDTH,
368c2ecf20Sopenharmony_ci	},
378c2ecf20Sopenharmony_ci	{
388c2ecf20Sopenharmony_ci		.name = "impA7 NOR Flash Bank #1",
398c2ecf20Sopenharmony_ci		.size = WINDOW_SIZE1,
408c2ecf20Sopenharmony_ci		.bankwidth = BUSWIDTH,
418c2ecf20Sopenharmony_ci	},
428c2ecf20Sopenharmony_ci};
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/*
458c2ecf20Sopenharmony_ci * MTD partitioning stuff
468c2ecf20Sopenharmony_ci */
478c2ecf20Sopenharmony_cistatic const struct mtd_partition partitions[] =
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	{
508c2ecf20Sopenharmony_ci		.name = "FileSystem",
518c2ecf20Sopenharmony_ci		.size = 0x800000,
528c2ecf20Sopenharmony_ci		.offset = 0x00000000
538c2ecf20Sopenharmony_ci	},
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic int __init init_impa7(void)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	const char * const *type;
598c2ecf20Sopenharmony_ci	int i;
608c2ecf20Sopenharmony_ci	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
618c2ecf20Sopenharmony_ci	  { WINDOW_ADDR0, WINDOW_SIZE0 },
628c2ecf20Sopenharmony_ci	  { WINDOW_ADDR1, WINDOW_SIZE1 },
638c2ecf20Sopenharmony_ci        };
648c2ecf20Sopenharmony_ci	int devicesfound = 0;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	for(i=0; i<NUM_FLASHBANKS; i++)
678c2ecf20Sopenharmony_ci	{
688c2ecf20Sopenharmony_ci		printk(KERN_NOTICE MSG_PREFIX "probing 0x%08lx at 0x%08lx\n",
698c2ecf20Sopenharmony_ci		       pt[i].size, pt[i].addr);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci		impa7_map[i].phys = pt[i].addr;
728c2ecf20Sopenharmony_ci		impa7_map[i].virt = ioremap(pt[i].addr, pt[i].size);
738c2ecf20Sopenharmony_ci		if (!impa7_map[i].virt) {
748c2ecf20Sopenharmony_ci			printk(MSG_PREFIX "failed to ioremap\n");
758c2ecf20Sopenharmony_ci			return -EIO;
768c2ecf20Sopenharmony_ci		}
778c2ecf20Sopenharmony_ci		simple_map_init(&impa7_map[i]);
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci		impa7_mtd[i] = NULL;
808c2ecf20Sopenharmony_ci		type = rom_probe_types;
818c2ecf20Sopenharmony_ci		for(; !impa7_mtd[i] && *type; type++) {
828c2ecf20Sopenharmony_ci			impa7_mtd[i] = do_map_probe(*type, &impa7_map[i]);
838c2ecf20Sopenharmony_ci		}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		if (impa7_mtd[i]) {
868c2ecf20Sopenharmony_ci			impa7_mtd[i]->owner = THIS_MODULE;
878c2ecf20Sopenharmony_ci			devicesfound++;
888c2ecf20Sopenharmony_ci			mtd_device_register(impa7_mtd[i], partitions,
898c2ecf20Sopenharmony_ci					    ARRAY_SIZE(partitions));
908c2ecf20Sopenharmony_ci		} else {
918c2ecf20Sopenharmony_ci			iounmap((void __iomem *)impa7_map[i].virt);
928c2ecf20Sopenharmony_ci		}
938c2ecf20Sopenharmony_ci	}
948c2ecf20Sopenharmony_ci	return devicesfound == 0 ? -ENXIO : 0;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic void __exit cleanup_impa7(void)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	int i;
1008c2ecf20Sopenharmony_ci	for (i=0; i<NUM_FLASHBANKS; i++) {
1018c2ecf20Sopenharmony_ci		if (impa7_mtd[i]) {
1028c2ecf20Sopenharmony_ci			mtd_device_unregister(impa7_mtd[i]);
1038c2ecf20Sopenharmony_ci			map_destroy(impa7_mtd[i]);
1048c2ecf20Sopenharmony_ci			iounmap((void __iomem *)impa7_map[i].virt);
1058c2ecf20Sopenharmony_ci			impa7_map[i].virt = NULL;
1068c2ecf20Sopenharmony_ci		}
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cimodule_init(init_impa7);
1118c2ecf20Sopenharmony_cimodule_exit(cleanup_impa7);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1148c2ecf20Sopenharmony_ciMODULE_AUTHOR("Pavel Bartusek <pba@sysgo.de>");
1158c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("MTD map driver for implementa impA7");
116