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