379 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Nintendo GameCube, Wii and Wii U RTC driver4 *5 * This driver is for the MX23L4005, more specifically its real-time clock and6 * SRAM storage. The value returned by the RTC counter must be added with the7 * offset stored in a bias register in SRAM (on the GameCube and Wii) or in8 * /config/rtc.xml (on the Wii U). The latter being very impractical to access9 * from Linux, this driver assumes the bootloader has read it and stored it in10 * 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 is14 * currently the case but would have to be reworked to add support for other15 * GameCube hardware exposed on this bus.16 *17 * References:18 * - https://wiiubrew.org/wiki/Hardware/RTC19 * - https://wiibrew.org/wiki/MX23L400520 *21 * Copyright (C) 2018 rw-r-r-064422 * Copyright (C) 2021 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>23 *24 * Based on rtc-gcn.c25 * Copyright (C) 2004-2009 The GameCube Linux Team26 * Copyright (C) 2005,2008,2009 Albert Herranz27 * 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 041#define EXICR 1242#define EXIDATA 1643 44/* EXI register values */45#define EXICSR_DEV 0x38046 #define EXICSR_DEV1 0x10047#define EXICSR_CLK 0x07048 #define EXICSR_CLK_1MHZ 0x00049 #define EXICSR_CLK_2MHZ 0x01050 #define EXICSR_CLK_4MHZ 0x02051 #define EXICSR_CLK_8MHZ 0x03052 #define EXICSR_CLK_16MHZ 0x04053 #define EXICSR_CLK_32MHZ 0x05054#define EXICSR_INT 0x00855 #define EXICSR_INTSET 0x00856 57#define EXICR_TSTART 0x00158#define EXICR_TRSMODE 0x00259 #define EXICR_TRSMODE_IMM 0x00060#define EXICR_TRSTYPE 0x00C61 #define EXICR_TRSTYPE_R 0x00062 #define EXICR_TRSTYPE_W 0x00463#define EXICR_TLEN 0x03064 #define EXICR_TLEN32 0x03065 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 0x8000000071 72/* RTC registers */73#define RTC_COUNTER 0x20000074#define RTC_SRAM 0x20000175#define RTC_SRAM_BIAS 0x20000476#define RTC_SNAPSHOT 0x20400077#define RTC_ONTMR 0x21000078#define RTC_OFFTMR 0x21000179#define RTC_TEST0 0x21000480#define RTC_TEST1 0x21000581#define RTC_TEST2 0x21000682#define RTC_TEST3 0x21000783#define RTC_CONTROL0 0x21000c84#define RTC_CONTROL1 0x21000d85 86/* RTC flags */87#define RTC_CONTROL0_UNSTABLE_POWER 0x0000080088#define RTC_CONTROL0_LOW_BATTERY 0x0000020089 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 need102 * 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 need131 * 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 by248 * reading the leftover value after boot, after IOSU already ran.249 *250 * On my Wii U, setting this register to 1 prevents the console from251 * rebooting properly, so wiiubrew.org must be missing something.252 *253 * See https://wiiubrew.org/wiki/Hardware/Latte_registers254 */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 contents262 * of /config/rtc.xml on the SLC (the eMMC). We don’t do that from263 * Linux since it requires implementing a proprietary filesystem and do264 * file decryption, instead we require the bootloader to fill the same265 * SRAM address as on previous consoles.266 */267 ret = regmap_read(d->regmap, RTC_SRAM_BIAS, &d->rtc_bias);268 269 /* Reset SRAM access to how it was before, our job here is done. */270 if (old != 0x7bf)271 iowrite32be(old, hw_srnprot);272 273 iounmap(hw_srnprot);274 275 if (ret)276 pr_err("failed to get the RTC bias\n");277 278 return ret;279}280 281static const struct regmap_range rtc_rd_ranges[] = {282 regmap_reg_range(0x200000, 0x200010),283 regmap_reg_range(0x204000, 0x204000),284 regmap_reg_range(0x210000, 0x210001),285 regmap_reg_range(0x210004, 0x210007),286 regmap_reg_range(0x21000c, 0x21000d),287};288 289static const struct regmap_access_table rtc_rd_regs = {290 .yes_ranges = rtc_rd_ranges,291 .n_yes_ranges = ARRAY_SIZE(rtc_rd_ranges),292};293 294static const struct regmap_range rtc_wr_ranges[] = {295 regmap_reg_range(0x200000, 0x200010),296 regmap_reg_range(0x204000, 0x204000),297 regmap_reg_range(0x210000, 0x210001),298 regmap_reg_range(0x21000d, 0x21000d),299};300 301static const struct regmap_access_table rtc_wr_regs = {302 .yes_ranges = rtc_wr_ranges,303 .n_yes_ranges = ARRAY_SIZE(rtc_wr_ranges),304};305 306static const struct regmap_config gamecube_rtc_regmap_config = {307 .reg_bits = 24,308 .val_bits = 32,309 .rd_table = &rtc_rd_regs,310 .wr_table = &rtc_wr_regs,311 .max_register = 0x21000d,312 .name = "gamecube-rtc",313};314 315static int gamecube_rtc_probe(struct platform_device *pdev)316{317 struct device *dev = &pdev->dev;318 struct rtc_device *rtc;319 struct priv *d;320 int ret;321 322 d = devm_kzalloc(dev, sizeof(struct priv), GFP_KERNEL);323 if (!d)324 return -ENOMEM;325 326 d->iob = devm_platform_ioremap_resource(pdev, 0);327 if (IS_ERR(d->iob))328 return PTR_ERR(d->iob);329 330 d->regmap = devm_regmap_init(dev, &exi_bus, d,331 &gamecube_rtc_regmap_config);332 if (IS_ERR(d->regmap))333 return PTR_ERR(d->regmap);334 335 ret = gamecube_rtc_read_offset_from_sram(d);336 if (ret)337 return ret;338 dev_dbg(dev, "SRAM bias: 0x%x", d->rtc_bias);339 340 dev_set_drvdata(dev, d);341 342 rtc = devm_rtc_allocate_device(dev);343 if (IS_ERR(rtc))344 return PTR_ERR(rtc);345 346 /* We can represent further than that, but it depends on the stored347 * bias and we can’t modify it persistently on all supported consoles,348 * so here we pretend to be limited to 2106.349 */350 rtc->range_min = 0;351 rtc->range_max = U32_MAX;352 rtc->ops = &gamecube_rtc_ops;353 354 devm_rtc_register_device(rtc);355 356 return 0;357}358 359static const struct of_device_id gamecube_rtc_of_match[] = {360 {.compatible = "nintendo,latte-exi" },361 {.compatible = "nintendo,hollywood-exi" },362 {.compatible = "nintendo,flipper-exi" },363 { }364};365MODULE_DEVICE_TABLE(of, gamecube_rtc_of_match);366 367static struct platform_driver gamecube_rtc_driver = {368 .probe = gamecube_rtc_probe,369 .driver = {370 .name = "rtc-gamecube",371 .of_match_table = gamecube_rtc_of_match,372 },373};374module_platform_driver(gamecube_rtc_driver);375 376MODULE_AUTHOR("Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>");377MODULE_DESCRIPTION("Nintendo GameCube, Wii and Wii U RTC driver");378MODULE_LICENSE("GPL");379