root/drivers/power/reset/brcmstb-reboot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. brcmstb_restart_handler
  2. brcmstb_reboot_probe
  3. brcmstb_reboot_init

   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 
  34 static struct regmap *regmap;
  35 static u32 rst_src_en;
  36 static u32 sw_mstr_rst;
  37 
  38 struct reset_reg_mask {
  39         u32 rst_src_en_mask;
  40         u32 sw_mstr_rst_mask;
  41 };
  42 
  43 static const struct reset_reg_mask *reset_masks;
  44 
  45 static 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 
  81 static struct notifier_block brcmstb_restart_nb = {
  82         .notifier_call = brcmstb_restart_handler,
  83         .priority = 128,
  84 };
  85 
  86 static const struct reset_reg_mask reset_bits_40nm = {
  87         .rst_src_en_mask = BIT(0),
  88         .sw_mstr_rst_mask = BIT(0),
  89 };
  90 
  91 static const struct reset_reg_mask reset_bits_65nm = {
  92         .rst_src_en_mask = BIT(3),
  93         .sw_mstr_rst_mask = BIT(31),
  94 };
  95 
  96 static 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 
 102 static 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 
 143 static 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 
 151 static int __init brcmstb_reboot_init(void)
 152 {
 153         return platform_driver_probe(&brcmstb_reboot_driver,
 154                                         brcmstb_reboot_probe);
 155 }
 156 subsys_initcall(brcmstb_reboot_init);

/* [<][>][^][v][top][bottom][index][help] */