cregit-Linux how code gets into the kernel

Release 4.7 drivers/power/reset/arm-versatile-reboot.c

/*
 * Copyright (C) 2014 Linaro Ltd.
 *
 * Author: Linus Walleij <linus.walleij@linaro.org>
 *
 * 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.
 *
 */
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
#include <linux/of.h>


#define INTEGRATOR_HDR_CTRL_OFFSET	0x0C

#define INTEGRATOR_HDR_LOCK_OFFSET	0x14

#define INTEGRATOR_CM_CTRL_RESET	(1 << 3)


#define VERSATILE_SYS_LOCK_OFFSET	0x20

#define VERSATILE_SYS_RESETCTL_OFFSET	0x40

/* Magic unlocking token used on all Versatile boards */

#define VERSATILE_LOCK_VAL		0xA05F

/*
 * We detect the different syscon types from the compatible strings.
 */

enum versatile_reboot {
	
INTEGRATOR_REBOOT_CM,
	
VERSATILE_REBOOT_CM,
	
REALVIEW_REBOOT_EB,
	
REALVIEW_REBOOT_PB1176,
	
REALVIEW_REBOOT_PB11MP,
	
REALVIEW_REBOOT_PBA8,
	
REALVIEW_REBOOT_PBX,
};

/* Pointer to the system controller */

static struct regmap *syscon_regmap;

static enum versatile_reboot versatile_reboot_type;


static const struct of_device_id versatile_reboot_of_match[] = {
	{
		.compatible = "arm,core-module-integrator",
		.data = (void *)INTEGRATOR_REBOOT_CM
	},
	{
		.compatible = "arm,core-module-versatile",
		.data = (void *)VERSATILE_REBOOT_CM,
        },
	{
		.compatible = "arm,realview-eb-syscon",
		.data = (void *)REALVIEW_REBOOT_EB,
        },
	{
		.compatible = "arm,realview-pb1176-syscon",
		.data = (void *)REALVIEW_REBOOT_PB1176,
        },
	{
		.compatible = "arm,realview-pb11mp-syscon",
		.data = (void *)REALVIEW_REBOOT_PB11MP,
        },
	{
		.compatible = "arm,realview-pba8-syscon",
		.data = (void *)REALVIEW_REBOOT_PBA8,
        },
	{
		.compatible = "arm,realview-pbx-syscon",
		.data = (void *)REALVIEW_REBOOT_PBX,
        },
	{},
};


static int versatile_reboot(struct notifier_block *this, unsigned long mode, void *cmd) { /* Unlock the reset register */ /* Then hit reset on the different machines */ switch (versatile_reboot_type) { case INTEGRATOR_REBOOT_CM: regmap_write(syscon_regmap, INTEGRATOR_HDR_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_update_bits(syscon_regmap, INTEGRATOR_HDR_CTRL_OFFSET, INTEGRATOR_CM_CTRL_RESET, INTEGRATOR_CM_CTRL_RESET); break; case VERSATILE_REBOOT_CM: regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_update_bits(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0107, 0x0105); regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, 0); break; case REALVIEW_REBOOT_EB: regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0008); break; case REALVIEW_REBOOT_PB1176: regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0100); break; case REALVIEW_REBOOT_PB11MP: case REALVIEW_REBOOT_PBA8: regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0000); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x0004); break; case REALVIEW_REBOOT_PBX: regmap_write(syscon_regmap, VERSATILE_SYS_LOCK_OFFSET, VERSATILE_LOCK_VAL); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x00f0); regmap_write(syscon_regmap, VERSATILE_SYS_RESETCTL_OFFSET, 0x00f4); break; } dsb(); return NOTIFY_DONE; }

Contributors

PersonTokensPropCommitsCommitProp
linus walleijlinus walleij18793.97%375.00%
guenter roeckguenter roeck126.03%125.00%
Total199100.00%4100.00%

static struct notifier_block versatile_reboot_nb = { .notifier_call = versatile_reboot, .priority = 192, };
static int __init versatile_reboot_probe(void) { const struct of_device_id *reboot_id; struct device_node *np; int err; np = of_find_matching_node_and_match(NULL, versatile_reboot_of_match, &reboot_id); if (!np) return -ENODEV; versatile_reboot_type = (enum versatile_reboot)reboot_id->data; syscon_regmap = syscon_node_to_regmap(np); if (IS_ERR(syscon_regmap)) return PTR_ERR(syscon_regmap); err = register_restart_handler(&versatile_reboot_nb); if (err) return err; pr_info("versatile reboot driver registered\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
linus walleijlinus walleij8183.51%150.00%
guenter roeckguenter roeck1616.49%150.00%
Total97100.00%2100.00%

device_initcall(versatile_reboot_probe);

Overall Contributors

PersonTokensPropCommitsCommitProp
linus walleijlinus walleij46891.23%375.00%
guenter roeckguenter roeck458.77%125.00%
Total513100.00%4100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}