162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/powerpc/platforms/embedded6xx/wii.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Nintendo Wii board-specific support
662306a36Sopenharmony_ci * Copyright (C) 2008-2009 The GameCube Linux Team
762306a36Sopenharmony_ci * Copyright (C) 2008,2009 Albert Herranz
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#define DRV_MODULE_NAME "wii"
1062306a36Sopenharmony_ci#define pr_fmt(fmt) DRV_MODULE_NAME ": " fmt
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/init.h>
1462306a36Sopenharmony_ci#include <linux/irq.h>
1562306a36Sopenharmony_ci#include <linux/seq_file.h>
1662306a36Sopenharmony_ci#include <linux/of_address.h>
1762306a36Sopenharmony_ci#include <linux/of_platform.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <asm/io.h>
2062306a36Sopenharmony_ci#include <asm/machdep.h>
2162306a36Sopenharmony_ci#include <asm/time.h>
2262306a36Sopenharmony_ci#include <asm/udbg.h>
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#include "flipper-pic.h"
2562306a36Sopenharmony_ci#include "hlwd-pic.h"
2662306a36Sopenharmony_ci#include "usbgecko_udbg.h"
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/* control block */
2962306a36Sopenharmony_ci#define HW_CTRL_COMPATIBLE	"nintendo,hollywood-control"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define HW_CTRL_RESETS		0x94
3262306a36Sopenharmony_ci#define HW_CTRL_RESETS_SYS	(1<<0)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* gpio */
3562306a36Sopenharmony_ci#define HW_GPIO_COMPATIBLE	"nintendo,hollywood-gpio"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define HW_GPIO_BASE(idx)	(idx * 0x20)
3862306a36Sopenharmony_ci#define HW_GPIO_OUT(idx)	(HW_GPIO_BASE(idx) + 0)
3962306a36Sopenharmony_ci#define HW_GPIO_DIR(idx)	(HW_GPIO_BASE(idx) + 4)
4062306a36Sopenharmony_ci#define HW_GPIO_OWNER		(HW_GPIO_BASE(1) + 0x1c)
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci#define HW_GPIO_SHUTDOWN	(1<<1)
4362306a36Sopenharmony_ci#define HW_GPIO_SLOT_LED	(1<<5)
4462306a36Sopenharmony_ci#define HW_GPIO_SENSOR_BAR	(1<<8)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cistatic void __iomem *hw_ctrl;
4862306a36Sopenharmony_cistatic void __iomem *hw_gpio;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic void __noreturn wii_spin(void)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	local_irq_disable();
5362306a36Sopenharmony_ci	for (;;)
5462306a36Sopenharmony_ci		cpu_relax();
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic void __iomem *__init wii_ioremap_hw_regs(char *name, char *compatible)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	void __iomem *hw_regs = NULL;
6062306a36Sopenharmony_ci	struct device_node *np;
6162306a36Sopenharmony_ci	struct resource res;
6262306a36Sopenharmony_ci	int error = -ENODEV;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, compatible);
6562306a36Sopenharmony_ci	if (!np) {
6662306a36Sopenharmony_ci		pr_err("no compatible node found for %s\n", compatible);
6762306a36Sopenharmony_ci		goto out;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci	error = of_address_to_resource(np, 0, &res);
7062306a36Sopenharmony_ci	if (error) {
7162306a36Sopenharmony_ci		pr_err("no valid reg found for %pOFn\n", np);
7262306a36Sopenharmony_ci		goto out_put;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	hw_regs = ioremap(res.start, resource_size(&res));
7662306a36Sopenharmony_ci	if (hw_regs) {
7762306a36Sopenharmony_ci		pr_info("%s at 0x%pa mapped to 0x%p\n", name,
7862306a36Sopenharmony_ci			&res.start, hw_regs);
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciout_put:
8262306a36Sopenharmony_ci	of_node_put(np);
8362306a36Sopenharmony_ciout:
8462306a36Sopenharmony_ci	return hw_regs;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cistatic void __init wii_setup_arch(void)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	hw_ctrl = wii_ioremap_hw_regs("hw_ctrl", HW_CTRL_COMPATIBLE);
9062306a36Sopenharmony_ci	hw_gpio = wii_ioremap_hw_regs("hw_gpio", HW_GPIO_COMPATIBLE);
9162306a36Sopenharmony_ci	if (hw_gpio) {
9262306a36Sopenharmony_ci		/* turn off the front blue led and IR light */
9362306a36Sopenharmony_ci		clrbits32(hw_gpio + HW_GPIO_OUT(0),
9462306a36Sopenharmony_ci			  HW_GPIO_SLOT_LED | HW_GPIO_SENSOR_BAR);
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic void __noreturn wii_restart(char *cmd)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	local_irq_disable();
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (hw_ctrl) {
10362306a36Sopenharmony_ci		/* clear the system reset pin to cause a reset */
10462306a36Sopenharmony_ci		clrbits32(hw_ctrl + HW_CTRL_RESETS, HW_CTRL_RESETS_SYS);
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci	wii_spin();
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic void wii_power_off(void)
11062306a36Sopenharmony_ci{
11162306a36Sopenharmony_ci	local_irq_disable();
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (hw_gpio) {
11462306a36Sopenharmony_ci		/*
11562306a36Sopenharmony_ci		 * set the owner of the shutdown pin to ARM, because it is
11662306a36Sopenharmony_ci		 * accessed through the registers for the ARM, below
11762306a36Sopenharmony_ci		 */
11862306a36Sopenharmony_ci		clrbits32(hw_gpio + HW_GPIO_OWNER, HW_GPIO_SHUTDOWN);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		/* make sure that the poweroff GPIO is configured as output */
12162306a36Sopenharmony_ci		setbits32(hw_gpio + HW_GPIO_DIR(1), HW_GPIO_SHUTDOWN);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci		/* drive the poweroff GPIO high */
12462306a36Sopenharmony_ci		setbits32(hw_gpio + HW_GPIO_OUT(1), HW_GPIO_SHUTDOWN);
12562306a36Sopenharmony_ci	}
12662306a36Sopenharmony_ci	wii_spin();
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic void __noreturn wii_halt(void)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	if (ppc_md.restart)
13262306a36Sopenharmony_ci		ppc_md.restart(NULL);
13362306a36Sopenharmony_ci	wii_spin();
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic void __init wii_pic_probe(void)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	flipper_pic_probe();
13962306a36Sopenharmony_ci	hlwd_pic_probe();
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic int __init wii_probe(void)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	pm_power_off = wii_power_off;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	ug_udbg_init();
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	return 1;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_cistatic void wii_shutdown(void)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	hlwd_quiesce();
15462306a36Sopenharmony_ci	flipper_quiesce();
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistatic const struct of_device_id wii_of_bus[] = {
15862306a36Sopenharmony_ci	{ .compatible = "nintendo,hollywood", },
15962306a36Sopenharmony_ci	{ },
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic int __init wii_device_probe(void)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	of_platform_populate(NULL, wii_of_bus, NULL, NULL);
16562306a36Sopenharmony_ci	return 0;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_cimachine_device_initcall(wii, wii_device_probe);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_cidefine_machine(wii) {
17062306a36Sopenharmony_ci	.name			= "wii",
17162306a36Sopenharmony_ci	.compatible		= "nintendo,wii",
17262306a36Sopenharmony_ci	.probe			= wii_probe,
17362306a36Sopenharmony_ci	.setup_arch		= wii_setup_arch,
17462306a36Sopenharmony_ci	.restart		= wii_restart,
17562306a36Sopenharmony_ci	.halt			= wii_halt,
17662306a36Sopenharmony_ci	.init_IRQ		= wii_pic_probe,
17762306a36Sopenharmony_ci	.get_irq		= flipper_pic_get_irq,
17862306a36Sopenharmony_ci	.progress		= udbg_progress,
17962306a36Sopenharmony_ci	.machine_shutdown	= wii_shutdown,
18062306a36Sopenharmony_ci};
181