brintos

brintos / linux-shallow public Read only

0
0
Text · 5.6 KiB · 9d48a26 Raw
225 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* sbc_gxx.c -- MTD map driver for Arcom Control Systems SBC-MediaGX,3                SBC-GXm and SBC-GX1 series boards.4 5   Copyright (C) 2001 Arcom Control System Ltd6 7 8The SBC-MediaGX / SBC-GXx has up to 16 MiB of9Intel StrataFlash (28F320/28F640) in x8 mode.10 11This driver uses the CFI probe and Intel Extended Command Set drivers.12 13The flash is accessed as follows:14 15   16 KiB memory window at 0xdc000-0xdffff16 17   Two IO address locations for paging18 19   0x25820       bit 0-7: address bit 14-2121   0x25922       bit 0-1: address bit 22-2323       bit 7:   0 - reset/powered down24                1 - device enabled25 26The single flash device is divided into 3 partition which appear as27separate MTD devices.28 2925/04/2001 AJL (Arcom)  Modified signon strings and partition sizes30                        (to support bzImages up to 638KiB-ish)31*/32 33// Includes34 35#include <linux/module.h>36#include <linux/ioport.h>37#include <linux/init.h>38#include <asm/io.h>39 40#include <linux/mtd/mtd.h>41#include <linux/mtd/map.h>42#include <linux/mtd/partitions.h>43 44// Defines45 46// - Hardware specific47 48#define WINDOW_START 0xdc00049 50/* Number of bits in offset. */51#define WINDOW_SHIFT 1452#define WINDOW_LENGTH (1 << WINDOW_SHIFT)53 54/* The bits for the offset into the window. */55#define WINDOW_MASK (WINDOW_LENGTH-1)56#define PAGE_IO 0x25857#define PAGE_IO_SIZE 258 59/* bit 7 of 0x259 must be 1 to enable device. */60#define DEVICE_ENABLE 0x800061 62// - Flash / Partition sizing63 64#define MAX_SIZE_KiB             1638465#define BOOT_PARTITION_SIZE_KiB  76866#define DATA_PARTITION_SIZE_KiB  128067#define APP_PARTITION_SIZE_KiB   614468 69// Globals70 71static volatile int page_in_window = -1; // Current page in window.72static void __iomem *iomapadr;73static DEFINE_SPINLOCK(sbc_gxx_spin);74 75/* partition_info gives details on the logical partitions that the split the76 * single flash device into. If the size if zero we use up to the end of the77 * device. */78static const struct mtd_partition partition_info[] = {79    { .name = "SBC-GXx flash boot partition",80      .offset = 0,81      .size =   BOOT_PARTITION_SIZE_KiB*1024 },82    { .name = "SBC-GXx flash data partition",83      .offset = BOOT_PARTITION_SIZE_KiB*1024,84      .size = (DATA_PARTITION_SIZE_KiB)*1024 },85    { .name = "SBC-GXx flash application partition",86      .offset = (BOOT_PARTITION_SIZE_KiB+DATA_PARTITION_SIZE_KiB)*1024 }87};88 89#define NUM_PARTITIONS 390 91static inline void sbc_gxx_page(struct map_info *map, unsigned long ofs)92{93	unsigned long page = ofs >> WINDOW_SHIFT;94 95	if( page!=page_in_window ) {96		outw( page | DEVICE_ENABLE, PAGE_IO );97		page_in_window = page;98	}99}100 101 102static map_word sbc_gxx_read8(struct map_info *map, unsigned long ofs)103{104	map_word ret;105	spin_lock(&sbc_gxx_spin);106	sbc_gxx_page(map, ofs);107	ret.x[0] = readb(iomapadr + (ofs & WINDOW_MASK));108	spin_unlock(&sbc_gxx_spin);109	return ret;110}111 112static void sbc_gxx_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)113{114	while(len) {115		unsigned long thislen = len;116		if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))117			thislen = WINDOW_LENGTH-(from & WINDOW_MASK);118 119		spin_lock(&sbc_gxx_spin);120		sbc_gxx_page(map, from);121		memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);122		spin_unlock(&sbc_gxx_spin);123		to += thislen;124		from += thislen;125		len -= thislen;126	}127}128 129static void sbc_gxx_write8(struct map_info *map, map_word d, unsigned long adr)130{131	spin_lock(&sbc_gxx_spin);132	sbc_gxx_page(map, adr);133	writeb(d.x[0], iomapadr + (adr & WINDOW_MASK));134	spin_unlock(&sbc_gxx_spin);135}136 137static void sbc_gxx_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)138{139	while(len) {140		unsigned long thislen = len;141		if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))142			thislen = WINDOW_LENGTH-(to & WINDOW_MASK);143 144		spin_lock(&sbc_gxx_spin);145		sbc_gxx_page(map, to);146		memcpy_toio(iomapadr + (to & WINDOW_MASK), from, thislen);147		spin_unlock(&sbc_gxx_spin);148		to += thislen;149		from += thislen;150		len -= thislen;151	}152}153 154static struct map_info sbc_gxx_map = {155	.name = "SBC-GXx flash",156	.phys = NO_XIP,157	.size = MAX_SIZE_KiB*1024, /* this must be set to a maximum possible amount158			 of flash so the cfi probe routines find all159			 the chips */160	.bankwidth = 1,161	.read = sbc_gxx_read8,162	.copy_from = sbc_gxx_copy_from,163	.write = sbc_gxx_write8,164	.copy_to = sbc_gxx_copy_to165};166 167/* MTD device for all of the flash. */168static struct mtd_info *all_mtd;169 170static void cleanup_sbc_gxx(void)171{172	if( all_mtd ) {173		mtd_device_unregister(all_mtd);174		map_destroy( all_mtd );175	}176 177	iounmap(iomapadr);178	release_region(PAGE_IO,PAGE_IO_SIZE);179}180 181static int __init init_sbc_gxx(void)182{183  	iomapadr = ioremap(WINDOW_START, WINDOW_LENGTH);184	if (!iomapadr) {185		printk( KERN_ERR"%s: failed to ioremap memory region\n",186			sbc_gxx_map.name );187		return -EIO;188	}189 190	if (!request_region( PAGE_IO, PAGE_IO_SIZE, "SBC-GXx flash")) {191		printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n",192			sbc_gxx_map.name,193			PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 );194		iounmap(iomapadr);195		return -EAGAIN;196	}197 198 199	printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n",200		sbc_gxx_map.name,201		PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1,202		WINDOW_START, WINDOW_START+WINDOW_LENGTH-1 );203 204	/* Probe for chip. */205	all_mtd = do_map_probe( "cfi_probe", &sbc_gxx_map );206	if( !all_mtd ) {207		cleanup_sbc_gxx();208		return -ENXIO;209	}210 211	all_mtd->owner = THIS_MODULE;212 213	/* Create MTD devices for each partition. */214	mtd_device_register(all_mtd, partition_info, NUM_PARTITIONS);215 216	return 0;217}218 219module_init(init_sbc_gxx);220module_exit(cleanup_sbc_gxx);221 222MODULE_LICENSE("GPL");223MODULE_AUTHOR("Arcom Control Systems Ltd.");224MODULE_DESCRIPTION("MTD map driver for SBC-GXm and SBC-GX1 series boards");225