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

physmap-bt1-rom.c (3021B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2020 BAIKAL ELECTRONICS, JSC
      4 *
      5 * Authors:
      6 *   Serge Semin <Sergey.Semin@baikalelectronics.ru>
      7 *
      8 * Baikal-T1 Physically Mapped Internal ROM driver
      9 */
     10#include <linux/bits.h>
     11#include <linux/device.h>
     12#include <linux/kernel.h>
     13#include <linux/mtd/map.h>
     14#include <linux/mtd/xip.h>
     15#include <linux/mux/consumer.h>
     16#include <linux/of.h>
     17#include <linux/of_device.h>
     18#include <linux/platform_device.h>
     19#include <linux/string.h>
     20#include <linux/types.h>
     21
     22#include "physmap-bt1-rom.h"
     23
     24/*
     25 * Baikal-T1 SoC ROMs are only accessible by the dword-aligned instructions.
     26 * We have to take this into account when implementing the data read-methods.
     27 * Note there is no need in bothering with endianness, since both Baikal-T1
     28 * CPU and MMIO are LE.
     29 */
     30static map_word __xipram bt1_rom_map_read(struct map_info *map,
     31					  unsigned long ofs)
     32{
     33	void __iomem *src = map->virt + ofs;
     34	unsigned int shift;
     35	map_word ret;
     36	u32 data;
     37
     38	/* Read data within offset dword. */
     39	shift = (uintptr_t)src & 0x3;
     40	data = readl_relaxed(src - shift);
     41	if (!shift) {
     42		ret.x[0] = data;
     43		return ret;
     44	}
     45	ret.x[0] = data >> (shift * BITS_PER_BYTE);
     46
     47	/* Read data from the next dword. */
     48	shift = 4 - shift;
     49	if (ofs + shift >= map->size)
     50		return ret;
     51
     52	data = readl_relaxed(src + shift);
     53	ret.x[0] |= data << (shift * BITS_PER_BYTE);
     54
     55	return ret;
     56}
     57
     58static void __xipram bt1_rom_map_copy_from(struct map_info *map,
     59					   void *to, unsigned long from,
     60					   ssize_t len)
     61{
     62	void __iomem *src = map->virt + from;
     63	unsigned int shift, chunk;
     64	u32 data;
     65
     66	if (len <= 0 || from >= map->size)
     67		return;
     68
     69	/* Make sure we don't go over the map limit. */
     70	len = min_t(ssize_t, map->size - from, len);
     71
     72	/*
     73	 * Since requested data size can be pretty big we have to implement
     74	 * the copy procedure as optimal as possible. That's why it's split
     75	 * up into the next three stages: unaligned head, aligned body,
     76	 * unaligned tail.
     77	 */
     78	shift = (uintptr_t)src & 0x3;
     79	if (shift) {
     80		chunk = min_t(ssize_t, 4 - shift, len);
     81		data = readl_relaxed(src - shift);
     82		memcpy(to, (char *)&data + shift, chunk);
     83		src += chunk;
     84		to += chunk;
     85		len -= chunk;
     86	}
     87
     88	while (len >= 4) {
     89		data = readl_relaxed(src);
     90		memcpy(to, &data, 4);
     91		src += 4;
     92		to += 4;
     93		len -= 4;
     94	}
     95
     96	if (len) {
     97		data = readl_relaxed(src);
     98		memcpy(to, &data, len);
     99	}
    100}
    101
    102int of_flash_probe_bt1_rom(struct platform_device *pdev,
    103			   struct device_node *np,
    104			   struct map_info *map)
    105{
    106	struct device *dev = &pdev->dev;
    107
    108	/* It's supposed to be read-only MTD. */
    109	if (!of_device_is_compatible(np, "mtd-rom")) {
    110		dev_info(dev, "No mtd-rom compatible string\n");
    111		return 0;
    112	}
    113
    114	/* Multiplatform guard. */
    115	if (!of_device_is_compatible(np, "baikal,bt1-int-rom"))
    116		return 0;
    117
    118	/* Sanity check the device parameters retrieved from DTB. */
    119	if (map->bankwidth != 4)
    120		dev_warn(dev, "Bank width is supposed to be 32 bits wide\n");
    121
    122	map->read = bt1_rom_map_read;
    123	map->copy_from = bt1_rom_map_copy_from;
    124
    125	return 0;
    126}