 2a153f1c55
			
		
	
	
	2a153f1c55
	
	
	
		
			
			Add a helper for reseting different devices on the SoC. Signed-off-by: John Crispin <blogic@openwrt.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5804/ Patchwork: https://patchwork.linux-mips.org/patch/5797/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
		
			
				
	
	
		
			106 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
	
		
			2.2 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This program is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of the GNU General Public License version 2 as published
 | |
|  * by the Free Software Foundation.
 | |
|  *
 | |
|  * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
 | |
|  * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
 | |
|  * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
 | |
|  */
 | |
| 
 | |
| #include <linux/pm.h>
 | |
| #include <linux/io.h>
 | |
| #include <linux/of.h>
 | |
| #include <linux/reset-controller.h>
 | |
| 
 | |
| #include <asm/reboot.h>
 | |
| 
 | |
| #include <asm/mach-ralink/ralink_regs.h>
 | |
| 
 | |
| /* Reset Control */
 | |
| #define SYSC_REG_RESET_CTRL     0x034
 | |
| #define RSTCTL_RESET_SYSTEM     BIT(0)
 | |
| 
 | |
| static int ralink_assert_device(struct reset_controller_dev *rcdev,
 | |
| 				unsigned long id)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	if (id < 8)
 | |
| 		return -1;
 | |
| 
 | |
| 	val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
 | |
| 	val |= BIT(id);
 | |
| 	rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ralink_deassert_device(struct reset_controller_dev *rcdev,
 | |
| 				  unsigned long id)
 | |
| {
 | |
| 	u32 val;
 | |
| 
 | |
| 	if (id < 8)
 | |
| 		return -1;
 | |
| 
 | |
| 	val = rt_sysc_r32(SYSC_REG_RESET_CTRL);
 | |
| 	val &= ~BIT(id);
 | |
| 	rt_sysc_w32(val, SYSC_REG_RESET_CTRL);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int ralink_reset_device(struct reset_controller_dev *rcdev,
 | |
| 			       unsigned long id)
 | |
| {
 | |
| 	ralink_assert_device(rcdev, id);
 | |
| 	return ralink_deassert_device(rcdev, id);
 | |
| }
 | |
| 
 | |
| static struct reset_control_ops reset_ops = {
 | |
| 	.reset = ralink_reset_device,
 | |
| 	.assert = ralink_assert_device,
 | |
| 	.deassert = ralink_deassert_device,
 | |
| };
 | |
| 
 | |
| static struct reset_controller_dev reset_dev = {
 | |
| 	.ops			= &reset_ops,
 | |
| 	.owner			= THIS_MODULE,
 | |
| 	.nr_resets		= 32,
 | |
| 	.of_reset_n_cells	= 1,
 | |
| };
 | |
| 
 | |
| void ralink_rst_init(void)
 | |
| {
 | |
| 	reset_dev.of_node = of_find_compatible_node(NULL, NULL,
 | |
| 						"ralink,rt2880-reset");
 | |
| 	if (!reset_dev.of_node)
 | |
| 		pr_err("Failed to find reset controller node");
 | |
| 	else
 | |
| 		reset_controller_register(&reset_dev);
 | |
| }
 | |
| 
 | |
| static void ralink_restart(char *command)
 | |
| {
 | |
| 	local_irq_disable();
 | |
| 	rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
 | |
| 	unreachable();
 | |
| }
 | |
| 
 | |
| static void ralink_halt(void)
 | |
| {
 | |
| 	local_irq_disable();
 | |
| 	unreachable();
 | |
| }
 | |
| 
 | |
| static int __init mips_reboot_setup(void)
 | |
| {
 | |
| 	_machine_restart = ralink_restart;
 | |
| 	_machine_halt = ralink_halt;
 | |
| 	pm_power_off = ralink_halt;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| arch_initcall(mips_reboot_setup);
 |