cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sbc_gxx.c (5692B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/* 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 Ltd
      6
      7
      8The SBC-MediaGX / SBC-GXx has up to 16 MiB of
      9Intel 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-0xdffff
     16
     17   Two IO address locations for paging
     18
     19   0x258
     20       bit 0-7: address bit 14-21
     21   0x259
     22       bit 0-1: address bit 22-23
     23       bit 7:   0 - reset/powered down
     24                1 - device enabled
     25
     26The single flash device is divided into 3 partition which appear as
     27separate MTD devices.
     28
     2925/04/2001 AJL (Arcom)  Modified signon strings and partition sizes
     30                        (to support bzImages up to 638KiB-ish)
     31*/
     32
     33// Includes
     34
     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// Defines
     45
     46// - Hardware specific
     47
     48#define WINDOW_START 0xdc000
     49
     50/* Number of bits in offset. */
     51#define WINDOW_SHIFT 14
     52#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 0x258
     57#define PAGE_IO_SIZE 2
     58
     59/* bit 7 of 0x259 must be 1 to enable device. */
     60#define DEVICE_ENABLE 0x8000
     61
     62// - Flash / Partition sizing
     63
     64#define MAX_SIZE_KiB             16384
     65#define BOOT_PARTITION_SIZE_KiB  768
     66#define DATA_PARTITION_SIZE_KiB  1280
     67#define APP_PARTITION_SIZE_KiB   6144
     68
     69// Globals
     70
     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 the
     76 * single flash device into. If the size if zero we use up to the end of the
     77 * 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 3
     90
     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 amount
    158			 of flash so the cfi probe routines find all
    159			 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_to
    165};
    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");