Skip to content

Commit b3e79e7

Browse files
fancermiquelraynal
authored andcommitted
mtd: physmap: Add Baikal-T1 physically mapped ROM support
Baikal-T1 Boot Controller provides an access to a RO storages, which are physically mapped into the SoC MMIO space. In particularly there are Internal ROM embedded into the SoC with a pre-installed firmware, externally attached SPI flash (also accessed in the read-only mode) and a memory region, which mirrors one of them in accordance with the currently enabled system boot mode (also called Boot ROM). This commit adds the Internal ROM support to the physmap driver of the MTD kernel subsystem. The driver will create the Internal ROM MTD as long as it is defined in the system dts file. The physically mapped SPI flash region will be used to implement the SPI-mem interface. The mirroring memory region won't be accessible directly since it's redundant due to both bootable regions being exposed anyway. Note we had to create a dedicated code for the ROMs since read from the corresponding memory regions must be done via the dword-aligned addresses. Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru> Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru> Cc: Lee Jones <lee.jones@linaro.org> Cc: linux-mips@vger.kernel.org Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20200920111445.21816-1-Sergey.Semin@baikalelectronics.ru
1 parent 6aec345 commit b3e79e7

5 files changed

Lines changed: 160 additions & 0 deletions

File tree

drivers/mtd/maps/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ config MTD_PHYSMAP_OF
7575
physically into the CPU's memory. The mapping description here is
7676
taken from OF device tree.
7777

78+
config MTD_PHYSMAP_BT1_ROM
79+
bool "Baikal-T1 Boot ROMs OF-based physical memory map handling"
80+
depends on MTD_PHYSMAP_OF
81+
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
82+
select MTD_COMPLEX_MAPPINGS
83+
select MULTIPLEXER
84+
select MUX_MMIO
85+
help
86+
This provides some extra DT physmap parsing for the Baikal-T1
87+
platforms, some detection and setting up ROMs-specific accessors.
88+
7889
config MTD_PHYSMAP_VERSATILE
7990
bool "ARM Versatile OF-based physical memory map handling"
8091
depends on MTD_PHYSMAP_OF

drivers/mtd/maps/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
1818
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
1919
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
2020
physmap-objs-y += physmap-core.o
21+
physmap-objs-$(CONFIG_MTD_PHYSMAP_BT1_ROM) += physmap-bt1-rom.o
2122
physmap-objs-$(CONFIG_MTD_PHYSMAP_VERSATILE) += physmap-versatile.o
2223
physmap-objs-$(CONFIG_MTD_PHYSMAP_GEMINI) += physmap-gemini.o
2324
physmap-objs-$(CONFIG_MTD_PHYSMAP_IXP4XX) += physmap-ixp4xx.o

drivers/mtd/maps/physmap-bt1-rom.c

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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+
*/
30+
static 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 long shift;
35+
map_word ret;
36+
u32 data;
37+
38+
/* Read data within offset dword. */
39+
shift = (unsigned long)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+
58+
static 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+
ssize_t 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 = (ssize_t)src & 0x3;
79+
if (shift) {
80+
chunk = min_t(ssize_t, 4 - shift, len);
81+
data = readl_relaxed(src - shift);
82+
memcpy(to, &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+
102+
int 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+
}

drivers/mtd/maps/physmap-bt1-rom.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
#include <linux/mtd/map.h>
3+
#include <linux/of.h>
4+
5+
#ifdef CONFIG_MTD_PHYSMAP_BT1_ROM
6+
int of_flash_probe_bt1_rom(struct platform_device *pdev,
7+
struct device_node *np,
8+
struct map_info *map);
9+
#else
10+
static inline
11+
int of_flash_probe_bt1_rom(struct platform_device *pdev,
12+
struct device_node *np,
13+
struct map_info *map)
14+
{
15+
return 0;
16+
}
17+
#endif

drivers/mtd/maps/physmap-core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <linux/pm_runtime.h>
4242
#include <linux/gpio/consumer.h>
4343

44+
#include "physmap-bt1-rom.h"
4445
#include "physmap-gemini.h"
4546
#include "physmap-ixp4xx.h"
4647
#include "physmap-versatile.h"
@@ -371,6 +372,10 @@ static int physmap_flash_of_init(struct platform_device *dev)
371372
info->maps[i].bankwidth = bankwidth;
372373
info->maps[i].device_node = dp;
373374

375+
err = of_flash_probe_bt1_rom(dev, dp, &info->maps[i]);
376+
if (err)
377+
return err;
378+
374379
err = of_flash_probe_gemini(dev, dp, &info->maps[i]);
375380
if (err)
376381
return err;

0 commit comments

Comments
 (0)