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

rtc-gamecube.c (10442B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Nintendo GameCube, Wii and Wii U RTC driver
      4 *
      5 * This driver is for the MX23L4005, more specifically its real-time clock and
      6 * SRAM storage.  The value returned by the RTC counter must be added with the
      7 * offset stored in a bias register in SRAM (on the GameCube and Wii) or in
      8 * /config/rtc.xml (on the Wii U).  The latter being very impractical to access
      9 * from Linux, this driver assumes the bootloader has read it and stored it in
     10 * SRAM like for the other two consoles.
     11 *
     12 * This device sits on a bus named EXI (which is similar to SPI), channel 0,
     13 * device 1.  This driver assumes no other user of the EXI bus, which is
     14 * currently the case but would have to be reworked to add support for other
     15 * GameCube hardware exposed on this bus.
     16 *
     17 * References:
     18 * - https://wiiubrew.org/wiki/Hardware/RTC
     19 * - https://wiibrew.org/wiki/MX23L4005
     20 *
     21 * Copyright (C) 2018 rw-r-r-0644
     22 * Copyright (C) 2021 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
     23 *
     24 * Based on rtc-gcn.c
     25 * Copyright (C) 2004-2009 The GameCube Linux Team
     26 * Copyright (C) 2005,2008,2009 Albert Herranz
     27 * Based on gamecube_time.c from Torben Nielsen.
     28 */
     29
     30#include <linux/init.h>
     31#include <linux/module.h>
     32#include <linux/of.h>
     33#include <linux/of_address.h>
     34#include <linux/platform_device.h>
     35#include <linux/regmap.h>
     36#include <linux/rtc.h>
     37#include <linux/time.h>
     38
     39/* EXI registers */
     40#define EXICSR	0
     41#define EXICR	12
     42#define EXIDATA	16
     43
     44/* EXI register values */
     45#define EXICSR_DEV		0x380
     46	#define EXICSR_DEV1	0x100
     47#define EXICSR_CLK		0x070
     48	#define EXICSR_CLK_1MHZ	0x000
     49	#define EXICSR_CLK_2MHZ	0x010
     50	#define EXICSR_CLK_4MHZ	0x020
     51	#define EXICSR_CLK_8MHZ	0x030
     52	#define EXICSR_CLK_16MHZ 0x040
     53	#define EXICSR_CLK_32MHZ 0x050
     54#define EXICSR_INT		0x008
     55	#define EXICSR_INTSET	0x008
     56
     57#define EXICR_TSTART		0x001
     58#define EXICR_TRSMODE		0x002
     59	#define EXICR_TRSMODE_IMM 0x000
     60#define EXICR_TRSTYPE		0x00C
     61	#define EXICR_TRSTYPE_R	0x000
     62	#define EXICR_TRSTYPE_W	0x004
     63#define EXICR_TLEN		0x030
     64	#define EXICR_TLEN32	0x030
     65
     66/* EXI registers values to access the RTC */
     67#define RTC_EXICSR	(EXICSR_DEV1 | EXICSR_CLK_8MHZ | EXICSR_INTSET)
     68#define RTC_EXICR_W	(EXICR_TSTART | EXICR_TRSMODE_IMM | EXICR_TRSTYPE_W | EXICR_TLEN32)
     69#define RTC_EXICR_R	(EXICR_TSTART | EXICR_TRSMODE_IMM | EXICR_TRSTYPE_R | EXICR_TLEN32)
     70#define RTC_EXIDATA_W	0x80000000
     71
     72/* RTC registers */
     73#define RTC_COUNTER	0x200000
     74#define RTC_SRAM	0x200001
     75#define RTC_SRAM_BIAS	0x200004
     76#define RTC_SNAPSHOT	0x204000
     77#define RTC_ONTMR	0x210000
     78#define RTC_OFFTMR	0x210001
     79#define RTC_TEST0	0x210004
     80#define RTC_TEST1	0x210005
     81#define RTC_TEST2	0x210006
     82#define RTC_TEST3	0x210007
     83#define RTC_CONTROL0	0x21000c
     84#define RTC_CONTROL1	0x21000d
     85
     86/* RTC flags */
     87#define RTC_CONTROL0_UNSTABLE_POWER	0x00000800
     88#define RTC_CONTROL0_LOW_BATTERY	0x00000200
     89
     90struct priv {
     91	struct regmap *regmap;
     92	void __iomem *iob;
     93	u32 rtc_bias;
     94};
     95
     96static int exi_read(void *context, u32 reg, u32 *data)
     97{
     98	struct priv *d = (struct priv *)context;
     99	void __iomem *iob = d->iob;
    100
    101	/* The spin loops here loop about 15~16 times each, so there is no need
    102	 * to use a more expensive sleep method.
    103	 */
    104
    105	/* Write register offset */
    106	iowrite32be(RTC_EXICSR, iob + EXICSR);
    107	iowrite32be(reg << 8, iob + EXIDATA);
    108	iowrite32be(RTC_EXICR_W, iob + EXICR);
    109	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
    110		cpu_relax();
    111
    112	/* Read data */
    113	iowrite32be(RTC_EXICSR, iob + EXICSR);
    114	iowrite32be(RTC_EXICR_R, iob + EXICR);
    115	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
    116		cpu_relax();
    117	*data = ioread32be(iob + EXIDATA);
    118
    119	/* Clear channel parameters */
    120	iowrite32be(0, iob + EXICSR);
    121
    122	return 0;
    123}
    124
    125static int exi_write(void *context, u32 reg, u32 data)
    126{
    127	struct priv *d = (struct priv *)context;
    128	void __iomem *iob = d->iob;
    129
    130	/* The spin loops here loop about 15~16 times each, so there is no need
    131	 * to use a more expensive sleep method.
    132	 */
    133
    134	/* Write register offset */
    135	iowrite32be(RTC_EXICSR, iob + EXICSR);
    136	iowrite32be(RTC_EXIDATA_W | (reg << 8), iob + EXIDATA);
    137	iowrite32be(RTC_EXICR_W, iob + EXICR);
    138	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
    139		cpu_relax();
    140
    141	/* Write data */
    142	iowrite32be(RTC_EXICSR, iob + EXICSR);
    143	iowrite32be(data, iob + EXIDATA);
    144	iowrite32be(RTC_EXICR_W, iob + EXICR);
    145	while (!(ioread32be(iob + EXICSR) & EXICSR_INTSET))
    146		cpu_relax();
    147
    148	/* Clear channel parameters */
    149	iowrite32be(0, iob + EXICSR);
    150
    151	return 0;
    152}
    153
    154static const struct regmap_bus exi_bus = {
    155	/* TODO: is that true?  Not that it matters here, but still. */
    156	.fast_io = true,
    157	.reg_read = exi_read,
    158	.reg_write = exi_write,
    159};
    160
    161static int gamecube_rtc_read_time(struct device *dev, struct rtc_time *t)
    162{
    163	struct priv *d = dev_get_drvdata(dev);
    164	int ret;
    165	u32 counter;
    166	time64_t timestamp;
    167
    168	ret = regmap_read(d->regmap, RTC_COUNTER, &counter);
    169	if (ret)
    170		return ret;
    171
    172	/* Add the counter and the bias to obtain the timestamp */
    173	timestamp = (time64_t)d->rtc_bias + counter;
    174	rtc_time64_to_tm(timestamp, t);
    175
    176	return 0;
    177}
    178
    179static int gamecube_rtc_set_time(struct device *dev, struct rtc_time *t)
    180{
    181	struct priv *d = dev_get_drvdata(dev);
    182	time64_t timestamp;
    183
    184	/* Subtract the timestamp and the bias to obtain the counter value */
    185	timestamp = rtc_tm_to_time64(t);
    186	return regmap_write(d->regmap, RTC_COUNTER, timestamp - d->rtc_bias);
    187}
    188
    189static int gamecube_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
    190{
    191	struct priv *d = dev_get_drvdata(dev);
    192	int value;
    193	int control0;
    194	int ret;
    195
    196	switch (cmd) {
    197	case RTC_VL_READ:
    198		ret = regmap_read(d->regmap, RTC_CONTROL0, &control0);
    199		if (ret)
    200			return ret;
    201
    202		value = 0;
    203		if (control0 & RTC_CONTROL0_UNSTABLE_POWER)
    204			value |= RTC_VL_DATA_INVALID;
    205		if (control0 & RTC_CONTROL0_LOW_BATTERY)
    206			value |= RTC_VL_BACKUP_LOW;
    207		return put_user(value, (unsigned int __user *)arg);
    208
    209	default:
    210		return -ENOIOCTLCMD;
    211	}
    212}
    213
    214static const struct rtc_class_ops gamecube_rtc_ops = {
    215	.read_time	= gamecube_rtc_read_time,
    216	.set_time	= gamecube_rtc_set_time,
    217	.ioctl		= gamecube_rtc_ioctl,
    218};
    219
    220static int gamecube_rtc_read_offset_from_sram(struct priv *d)
    221{
    222	struct device_node *np;
    223	int ret;
    224	struct resource res;
    225	void __iomem *hw_srnprot;
    226	u32 old;
    227
    228	np = of_find_compatible_node(NULL, NULL, "nintendo,latte-srnprot");
    229	if (!np)
    230		np = of_find_compatible_node(NULL, NULL,
    231					     "nintendo,hollywood-srnprot");
    232	if (!np) {
    233		pr_info("HW_SRNPROT not found, assuming a GameCube\n");
    234		return regmap_read(d->regmap, RTC_SRAM_BIAS, &d->rtc_bias);
    235	}
    236
    237	ret = of_address_to_resource(np, 0, &res);
    238	of_node_put(np);
    239	if (ret) {
    240		pr_err("no io memory range found\n");
    241		return -1;
    242	}
    243
    244	hw_srnprot = ioremap(res.start, resource_size(&res));
    245	old = ioread32be(hw_srnprot);
    246
    247	/* TODO: figure out why we use this magic constant.  I obtained it by
    248	 * reading the leftover value after boot, after IOSU already ran.
    249	 *
    250	 * On my Wii U, setting this register to 1 prevents the console from
    251	 * rebooting properly, so wiiubrew.org must be missing something.
    252	 *
    253	 * See https://wiiubrew.org/wiki/Hardware/Latte_registers
    254	 */
    255	if (old != 0x7bf)
    256		iowrite32be(0x7bf, hw_srnprot);
    257
    258	/* Get the offset from RTC SRAM.
    259	 *
    260	 * Its default location on the GameCube and on the Wii is in the SRAM,
    261	 * while on the Wii U the bootloader needs to fill it with the contents
    262	 * of /config/rtc.xml on the SLC (the eMMC).  We don’t do that from
    263	 * Linux since it requires implementing a proprietary filesystem and do
    264	 * file decryption, instead we require the bootloader to fill the same
    265	 * SRAM address as on previous consoles.
    266	 */
    267	ret = regmap_read(d->regmap, RTC_SRAM_BIAS, &d->rtc_bias);
    268	if (ret) {
    269		pr_err("failed to get the RTC bias\n");
    270		iounmap(hw_srnprot);
    271		return -1;
    272	}
    273
    274	/* Reset SRAM access to how it was before, our job here is done. */
    275	if (old != 0x7bf)
    276		iowrite32be(old, hw_srnprot);
    277	iounmap(hw_srnprot);
    278
    279	return 0;
    280}
    281
    282static const struct regmap_range rtc_rd_ranges[] = {
    283	regmap_reg_range(0x200000, 0x200010),
    284	regmap_reg_range(0x204000, 0x204000),
    285	regmap_reg_range(0x210000, 0x210001),
    286	regmap_reg_range(0x210004, 0x210007),
    287	regmap_reg_range(0x21000c, 0x21000d),
    288};
    289
    290static const struct regmap_access_table rtc_rd_regs = {
    291	.yes_ranges =	rtc_rd_ranges,
    292	.n_yes_ranges =	ARRAY_SIZE(rtc_rd_ranges),
    293};
    294
    295static const struct regmap_range rtc_wr_ranges[] = {
    296	regmap_reg_range(0x200000, 0x200010),
    297	regmap_reg_range(0x204000, 0x204000),
    298	regmap_reg_range(0x210000, 0x210001),
    299	regmap_reg_range(0x21000d, 0x21000d),
    300};
    301
    302static const struct regmap_access_table rtc_wr_regs = {
    303	.yes_ranges =	rtc_wr_ranges,
    304	.n_yes_ranges =	ARRAY_SIZE(rtc_wr_ranges),
    305};
    306
    307static const struct regmap_config gamecube_rtc_regmap_config = {
    308	.reg_bits = 24,
    309	.val_bits = 32,
    310	.rd_table = &rtc_rd_regs,
    311	.wr_table = &rtc_wr_regs,
    312	.max_register = 0x21000d,
    313	.name = "gamecube-rtc",
    314};
    315
    316static int gamecube_rtc_probe(struct platform_device *pdev)
    317{
    318	struct device *dev = &pdev->dev;
    319	struct rtc_device *rtc;
    320	struct priv *d;
    321	int ret;
    322
    323	d = devm_kzalloc(dev, sizeof(struct priv), GFP_KERNEL);
    324	if (!d)
    325		return -ENOMEM;
    326
    327	d->iob = devm_platform_ioremap_resource(pdev, 0);
    328	if (IS_ERR(d->iob))
    329		return PTR_ERR(d->iob);
    330
    331	d->regmap = devm_regmap_init(dev, &exi_bus, d,
    332				     &gamecube_rtc_regmap_config);
    333	if (IS_ERR(d->regmap))
    334		return PTR_ERR(d->regmap);
    335
    336	ret = gamecube_rtc_read_offset_from_sram(d);
    337	if (ret)
    338		return ret;
    339	dev_dbg(dev, "SRAM bias: 0x%x", d->rtc_bias);
    340
    341	dev_set_drvdata(dev, d);
    342
    343	rtc = devm_rtc_allocate_device(dev);
    344	if (IS_ERR(rtc))
    345		return PTR_ERR(rtc);
    346
    347	/* We can represent further than that, but it depends on the stored
    348	 * bias and we can’t modify it persistently on all supported consoles,
    349	 * so here we pretend to be limited to 2106.
    350	 */
    351	rtc->range_min = 0;
    352	rtc->range_max = U32_MAX;
    353	rtc->ops = &gamecube_rtc_ops;
    354
    355	devm_rtc_register_device(rtc);
    356
    357	return 0;
    358}
    359
    360static const struct of_device_id gamecube_rtc_of_match[] = {
    361	{.compatible = "nintendo,latte-exi" },
    362	{.compatible = "nintendo,hollywood-exi" },
    363	{.compatible = "nintendo,flipper-exi" },
    364	{ }
    365};
    366MODULE_DEVICE_TABLE(of, gamecube_rtc_of_match);
    367
    368static struct platform_driver gamecube_rtc_driver = {
    369	.probe		= gamecube_rtc_probe,
    370	.driver		= {
    371		.name	= "rtc-gamecube",
    372		.of_match_table	= gamecube_rtc_of_match,
    373	},
    374};
    375module_platform_driver(gamecube_rtc_driver);
    376
    377MODULE_AUTHOR("Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>");
    378MODULE_DESCRIPTION("Nintendo GameCube, Wii and Wii U RTC driver");
    379MODULE_LICENSE("GPL");