162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* netsc520.c -- MTD map driver for AMD NetSc520 Demonstration Board
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2001 Mark Langsdorf (mark.langsdorf@amd.com)
562306a36Sopenharmony_ci *	based on sc520cdp.c by Sysgo Real-Time Solutions GmbH
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * The NetSc520 is a demonstration board for the Elan Sc520 processor available
862306a36Sopenharmony_ci * from AMD.  It has a single back of 16 megs of 32-bit Flash ROM and another
962306a36Sopenharmony_ci * 16 megs of SDRAM.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/types.h>
1462306a36Sopenharmony_ci#include <linux/kernel.h>
1562306a36Sopenharmony_ci#include <linux/init.h>
1662306a36Sopenharmony_ci#include <asm/io.h>
1762306a36Sopenharmony_ci#include <linux/mtd/mtd.h>
1862306a36Sopenharmony_ci#include <linux/mtd/map.h>
1962306a36Sopenharmony_ci#include <linux/mtd/partitions.h>
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci/*
2362306a36Sopenharmony_ci** The single, 16 megabyte flash bank is divided into four virtual
2462306a36Sopenharmony_ci** partitions.  The first partition is 768 KiB and is intended to
2562306a36Sopenharmony_ci** store the kernel image loaded by the bootstrap loader.  The second
2662306a36Sopenharmony_ci** partition is 256 KiB and holds the BIOS image.  The third
2762306a36Sopenharmony_ci** partition is 14.5 MiB and is intended for the flash file system
2862306a36Sopenharmony_ci** image.  The last partition is 512 KiB and contains another copy
2962306a36Sopenharmony_ci** of the BIOS image and the reset vector.
3062306a36Sopenharmony_ci**
3162306a36Sopenharmony_ci** Only the third partition should be mounted.  The first partition
3262306a36Sopenharmony_ci** should not be mounted, but it can erased and written to using the
3362306a36Sopenharmony_ci** MTD character routines.  The second and fourth partitions should
3462306a36Sopenharmony_ci** not be touched - it is possible to corrupt the BIOS image by
3562306a36Sopenharmony_ci** mounting these partitions, and potentially the board will not be
3662306a36Sopenharmony_ci** recoverable afterwards.
3762306a36Sopenharmony_ci*/
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/* partition_info gives details on the logical partitions that the split the
4062306a36Sopenharmony_ci * single flash device into. If the size if zero we use up to the end of the
4162306a36Sopenharmony_ci * device. */
4262306a36Sopenharmony_cistatic const struct mtd_partition partition_info[] = {
4362306a36Sopenharmony_ci    {
4462306a36Sopenharmony_ci	    .name = "NetSc520 boot kernel",
4562306a36Sopenharmony_ci	    .offset = 0,
4662306a36Sopenharmony_ci	    .size = 0xc0000
4762306a36Sopenharmony_ci    },
4862306a36Sopenharmony_ci    {
4962306a36Sopenharmony_ci	    .name = "NetSc520 Low BIOS",
5062306a36Sopenharmony_ci	    .offset = 0xc0000,
5162306a36Sopenharmony_ci	    .size = 0x40000
5262306a36Sopenharmony_ci    },
5362306a36Sopenharmony_ci    {
5462306a36Sopenharmony_ci	    .name = "NetSc520 file system",
5562306a36Sopenharmony_ci	    .offset = 0x100000,
5662306a36Sopenharmony_ci	    .size = 0xe80000
5762306a36Sopenharmony_ci    },
5862306a36Sopenharmony_ci    {
5962306a36Sopenharmony_ci	    .name = "NetSc520 High BIOS",
6062306a36Sopenharmony_ci	    .offset = 0xf80000,
6162306a36Sopenharmony_ci	    .size = 0x80000
6262306a36Sopenharmony_ci    },
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci#define NUM_PARTITIONS ARRAY_SIZE(partition_info)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci#define WINDOW_SIZE	0x00100000
6762306a36Sopenharmony_ci#define WINDOW_ADDR	0x00200000
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic struct map_info netsc520_map = {
7062306a36Sopenharmony_ci	.name = "netsc520 Flash Bank",
7162306a36Sopenharmony_ci	.size = WINDOW_SIZE,
7262306a36Sopenharmony_ci	.bankwidth = 4,
7362306a36Sopenharmony_ci	.phys = WINDOW_ADDR,
7462306a36Sopenharmony_ci};
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#define NUM_FLASH_BANKS	ARRAY_SIZE(netsc520_map)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic struct mtd_info *mymtd;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic int __init init_netsc520(void)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	printk(KERN_NOTICE "NetSc520 flash device: 0x%Lx at 0x%Lx\n",
8362306a36Sopenharmony_ci			(unsigned long long)netsc520_map.size,
8462306a36Sopenharmony_ci			(unsigned long long)netsc520_map.phys);
8562306a36Sopenharmony_ci	netsc520_map.virt = ioremap(netsc520_map.phys, netsc520_map.size);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (!netsc520_map.virt) {
8862306a36Sopenharmony_ci		printk("Failed to ioremap\n");
8962306a36Sopenharmony_ci		return -EIO;
9062306a36Sopenharmony_ci	}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	simple_map_init(&netsc520_map);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	mymtd = do_map_probe("cfi_probe", &netsc520_map);
9562306a36Sopenharmony_ci	if(!mymtd)
9662306a36Sopenharmony_ci		mymtd = do_map_probe("map_ram", &netsc520_map);
9762306a36Sopenharmony_ci	if(!mymtd)
9862306a36Sopenharmony_ci		mymtd = do_map_probe("map_rom", &netsc520_map);
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (!mymtd) {
10162306a36Sopenharmony_ci		iounmap(netsc520_map.virt);
10262306a36Sopenharmony_ci		return -ENXIO;
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	mymtd->owner = THIS_MODULE;
10662306a36Sopenharmony_ci	mtd_device_register(mymtd, partition_info, NUM_PARTITIONS);
10762306a36Sopenharmony_ci	return 0;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic void __exit cleanup_netsc520(void)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	if (mymtd) {
11362306a36Sopenharmony_ci		mtd_device_unregister(mymtd);
11462306a36Sopenharmony_ci		map_destroy(mymtd);
11562306a36Sopenharmony_ci	}
11662306a36Sopenharmony_ci	if (netsc520_map.virt) {
11762306a36Sopenharmony_ci		iounmap(netsc520_map.virt);
11862306a36Sopenharmony_ci		netsc520_map.virt = NULL;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_cimodule_init(init_netsc520);
12362306a36Sopenharmony_cimodule_exit(cleanup_netsc520);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ciMODULE_LICENSE("GPL");
12662306a36Sopenharmony_ciMODULE_AUTHOR("Mark Langsdorf <mark.langsdorf@amd.com>");
12762306a36Sopenharmony_ciMODULE_DESCRIPTION("MTD map driver for AMD NetSc520 Demonstration Board");
128