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