brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · c7624d7 Raw
161 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2014 Linaro Ltd.4 *5 * Author: Linus Walleij <linus.walleij@linaro.org>6 */7#include <linux/init.h>8#include <linux/mfd/syscon.h>9#include <linux/reboot.h>10#include <linux/regmap.h>11#include <linux/of.h>12 13#define INTEGRATOR_HDR_CTRL_OFFSET	0x0C14#define INTEGRATOR_HDR_LOCK_OFFSET	0x1415#define INTEGRATOR_CM_CTRL_RESET	(1 << 3)16 17#define VERSATILE_SYS_LOCK_OFFSET	0x2018#define VERSATILE_SYS_RESETCTL_OFFSET	0x4019 20/* Magic unlocking token used on all Versatile boards */21#define VERSATILE_LOCK_VAL		0xA05F22 23/*24 * We detect the different syscon types from the compatible strings.25 */26enum versatile_reboot {27	INTEGRATOR_REBOOT_CM,28	VERSATILE_REBOOT_CM,29	REALVIEW_REBOOT_EB,30	REALVIEW_REBOOT_PB1176,31	REALVIEW_REBOOT_PB11MP,32	REALVIEW_REBOOT_PBA8,33	REALVIEW_REBOOT_PBX,34};35 36/* Pointer to the system controller */37static struct regmap *syscon_regmap;38static enum versatile_reboot versatile_reboot_type;39 40static const struct of_device_id versatile_reboot_of_match[] = {41	{42		.compatible = "arm,core-module-integrator",43		.data = (void *)INTEGRATOR_REBOOT_CM44	},45	{46		.compatible = "arm,core-module-versatile",47		.data = (void *)VERSATILE_REBOOT_CM,48	},49	{50		.compatible = "arm,realview-eb-syscon",51		.data = (void *)REALVIEW_REBOOT_EB,52	},53	{54		.compatible = "arm,realview-pb1176-syscon",55		.data = (void *)REALVIEW_REBOOT_PB1176,56	},57	{58		.compatible = "arm,realview-pb11mp-syscon",59		.data = (void *)REALVIEW_REBOOT_PB11MP,60	},61	{62		.compatible = "arm,realview-pba8-syscon",63		.data = (void *)REALVIEW_REBOOT_PBA8,64	},65	{66		.compatible = "arm,realview-pbx-syscon",67		.data = (void *)REALVIEW_REBOOT_PBX,68	},69	{},70};71 72static int versatile_reboot(struct notifier_block *this, unsigned long mode,73			    void *cmd)74{75	/* Unlock the reset register */76	/* Then hit reset on the different machines */77	switch (versatile_reboot_type) {78	case INTEGRATOR_REBOOT_CM:79		regmap_write(syscon_regmap, INTEGRATOR_HDR_LOCK_OFFSET,80			     VERSATILE_LOCK_VAL);81		regmap_update_bits(syscon_regmap,82				   INTEGRATOR_HDR_CTRL_OFFSET,83				   INTEGRATOR_CM_CTRL_RESET,84				   INTEGRATOR_CM_CTRL_RESET);85		break;86	case VERSATILE_REBOOT_CM:87		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,88			     VERSATILE_LOCK_VAL);89		regmap_update_bits(syscon_regmap,90				   VERSATILE_SYS_RESETCTL_OFFSET,91				   0x0107,92				   0x0105);93		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,94			     0);95		break;96	case REALVIEW_REBOOT_EB:97		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,98			     VERSATILE_LOCK_VAL);99		regmap_write(syscon_regmap,100			     VERSATILE_SYS_RESETCTL_OFFSET, 0x0008);101		break;102	case REALVIEW_REBOOT_PB1176:103		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,104			     VERSATILE_LOCK_VAL);105		regmap_write(syscon_regmap,106			     VERSATILE_SYS_RESETCTL_OFFSET, 0x0100);107		break;108	case REALVIEW_REBOOT_PB11MP:109	case REALVIEW_REBOOT_PBA8:110		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,111			     VERSATILE_LOCK_VAL);112		regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET,113			     0x0000);114		regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET,115			     0x0004);116		break;117	case REALVIEW_REBOOT_PBX:118		regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET,119			     VERSATILE_LOCK_VAL);120		regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET,121			     0x00f0);122		regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET,123			     0x00f4);124		break;125	}126	dsb();127 128	return NOTIFY_DONE;129}130 131static struct notifier_block versatile_reboot_nb = {132	.notifier_call = versatile_reboot,133	.priority = 192,134};135 136static int __init versatile_reboot_probe(void)137{138	const struct of_device_id *reboot_id;139	struct device_node *np;140	int err;141 142	np = of_find_matching_node_and_match(NULL, versatile_reboot_of_match,143						 &reboot_id);144	if (!np)145		return -ENODEV;146	versatile_reboot_type = (enum versatile_reboot)reboot_id->data;147 148	syscon_regmap = syscon_node_to_regmap(np);149	of_node_put(np);150	if (IS_ERR(syscon_regmap))151		return PTR_ERR(syscon_regmap);152 153	err = register_restart_handler(&versatile_reboot_nb);154	if (err)155		return err;156 157	pr_info("versatile reboot driver registered\n");158	return 0;159}160device_initcall(versatile_reboot_probe);161