cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

brcmstb-reboot.c (3781B)


      1/*
      2 * Copyright (C) 2013 Broadcom Corporation
      3 *
      4 * This program is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU General Public License as
      6 * published by the Free Software Foundation version 2.
      7 *
      8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
      9 * kind, whether express or implied; without even the implied warranty
     10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 * GNU General Public License for more details.
     12 */
     13
     14#include <linux/bitops.h>
     15#include <linux/device.h>
     16#include <linux/errno.h>
     17#include <linux/init.h>
     18#include <linux/io.h>
     19#include <linux/jiffies.h>
     20#include <linux/notifier.h>
     21#include <linux/of_address.h>
     22#include <linux/of_irq.h>
     23#include <linux/of_platform.h>
     24#include <linux/platform_device.h>
     25#include <linux/printk.h>
     26#include <linux/reboot.h>
     27#include <linux/regmap.h>
     28#include <linux/smp.h>
     29#include <linux/mfd/syscon.h>
     30
     31#define RESET_SOURCE_ENABLE_REG 1
     32#define SW_MASTER_RESET_REG 2
     33
     34static struct regmap *regmap;
     35static u32 rst_src_en;
     36static u32 sw_mstr_rst;
     37
     38struct reset_reg_mask {
     39	u32 rst_src_en_mask;
     40	u32 sw_mstr_rst_mask;
     41};
     42
     43static const struct reset_reg_mask *reset_masks;
     44
     45static int brcmstb_restart_handler(struct notifier_block *this,
     46				   unsigned long mode, void *cmd)
     47{
     48	int rc;
     49	u32 tmp;
     50
     51	rc = regmap_write(regmap, rst_src_en, reset_masks->rst_src_en_mask);
     52	if (rc) {
     53		pr_err("failed to write rst_src_en (%d)\n", rc);
     54		return NOTIFY_DONE;
     55	}
     56
     57	rc = regmap_read(regmap, rst_src_en, &tmp);
     58	if (rc) {
     59		pr_err("failed to read rst_src_en (%d)\n", rc);
     60		return NOTIFY_DONE;
     61	}
     62
     63	rc = regmap_write(regmap, sw_mstr_rst, reset_masks->sw_mstr_rst_mask);
     64	if (rc) {
     65		pr_err("failed to write sw_mstr_rst (%d)\n", rc);
     66		return NOTIFY_DONE;
     67	}
     68
     69	rc = regmap_read(regmap, sw_mstr_rst, &tmp);
     70	if (rc) {
     71		pr_err("failed to read sw_mstr_rst (%d)\n", rc);
     72		return NOTIFY_DONE;
     73	}
     74
     75	while (1)
     76		;
     77
     78	return NOTIFY_DONE;
     79}
     80
     81static struct notifier_block brcmstb_restart_nb = {
     82	.notifier_call = brcmstb_restart_handler,
     83	.priority = 128,
     84};
     85
     86static const struct reset_reg_mask reset_bits_40nm = {
     87	.rst_src_en_mask = BIT(0),
     88	.sw_mstr_rst_mask = BIT(0),
     89};
     90
     91static const struct reset_reg_mask reset_bits_65nm = {
     92	.rst_src_en_mask = BIT(3),
     93	.sw_mstr_rst_mask = BIT(31),
     94};
     95
     96static const struct of_device_id of_match[] = {
     97	{ .compatible = "brcm,brcmstb-reboot", .data = &reset_bits_40nm },
     98	{ .compatible = "brcm,bcm7038-reboot", .data = &reset_bits_65nm },
     99	{},
    100};
    101
    102static int brcmstb_reboot_probe(struct platform_device *pdev)
    103{
    104	int rc;
    105	struct device_node *np = pdev->dev.of_node;
    106	const struct of_device_id *of_id;
    107
    108	of_id = of_match_node(of_match, np);
    109	if (!of_id) {
    110		pr_err("failed to look up compatible string\n");
    111		return -EINVAL;
    112	}
    113	reset_masks = of_id->data;
    114
    115	regmap = syscon_regmap_lookup_by_phandle(np, "syscon");
    116	if (IS_ERR(regmap)) {
    117		pr_err("failed to get syscon phandle\n");
    118		return -EINVAL;
    119	}
    120
    121	rc = of_property_read_u32_index(np, "syscon", RESET_SOURCE_ENABLE_REG,
    122					&rst_src_en);
    123	if (rc) {
    124		pr_err("can't get rst_src_en offset (%d)\n", rc);
    125		return -EINVAL;
    126	}
    127
    128	rc = of_property_read_u32_index(np, "syscon", SW_MASTER_RESET_REG,
    129					&sw_mstr_rst);
    130	if (rc) {
    131		pr_err("can't get sw_mstr_rst offset (%d)\n", rc);
    132		return -EINVAL;
    133	}
    134
    135	rc = register_restart_handler(&brcmstb_restart_nb);
    136	if (rc)
    137		dev_err(&pdev->dev,
    138			"cannot register restart handler (err=%d)\n", rc);
    139
    140	return rc;
    141}
    142
    143static struct platform_driver brcmstb_reboot_driver = {
    144	.probe = brcmstb_reboot_probe,
    145	.driver = {
    146		.name = "brcmstb-reboot",
    147		.of_match_table = of_match,
    148	},
    149};
    150
    151static int __init brcmstb_reboot_init(void)
    152{
    153	return platform_driver_probe(&brcmstb_reboot_driver,
    154					brcmstb_reboot_probe);
    155}
    156subsys_initcall(brcmstb_reboot_init);