root/drivers/reset/reset-lpc18xx.c

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

DEFINITIONS

This source file includes following definitions.
  1. lpc18xx_rgu_restart
  2. lpc18xx_rgu_setclear_reset
  3. lpc18xx_rgu_assert
  4. lpc18xx_rgu_deassert
  5. lpc18xx_rgu_reset
  6. lpc18xx_rgu_status
  7. lpc18xx_rgu_probe

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Reset driver for NXP LPC18xx/43xx Reset Generation Unit (RGU).
   4  *
   5  * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
   6  */
   7 
   8 #include <linux/clk.h>
   9 #include <linux/delay.h>
  10 #include <linux/err.h>
  11 #include <linux/io.h>
  12 #include <linux/init.h>
  13 #include <linux/of.h>
  14 #include <linux/platform_device.h>
  15 #include <linux/reboot.h>
  16 #include <linux/reset-controller.h>
  17 #include <linux/spinlock.h>
  18 
  19 /* LPC18xx RGU registers */
  20 #define LPC18XX_RGU_CTRL0               0x100
  21 #define LPC18XX_RGU_CTRL1               0x104
  22 #define LPC18XX_RGU_ACTIVE_STATUS0      0x150
  23 #define LPC18XX_RGU_ACTIVE_STATUS1      0x154
  24 
  25 #define LPC18XX_RGU_RESETS_PER_REG      32
  26 
  27 /* Internal reset outputs */
  28 #define LPC18XX_RGU_CORE_RST    0
  29 #define LPC43XX_RGU_M0SUB_RST   12
  30 #define LPC43XX_RGU_M0APP_RST   56
  31 
  32 struct lpc18xx_rgu_data {
  33         struct reset_controller_dev rcdev;
  34         struct notifier_block restart_nb;
  35         struct clk *clk_delay;
  36         struct clk *clk_reg;
  37         void __iomem *base;
  38         spinlock_t lock;
  39         u32 delay_us;
  40 };
  41 
  42 #define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
  43 
  44 static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
  45                                void *cmd)
  46 {
  47         struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
  48                                                    restart_nb);
  49 
  50         writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
  51         mdelay(2000);
  52 
  53         pr_emerg("%s: unable to restart system\n", __func__);
  54 
  55         return NOTIFY_DONE;
  56 }
  57 
  58 /*
  59  * The LPC18xx RGU has mostly self-deasserting resets except for the
  60  * two reset lines going to the internal Cortex-M0 cores.
  61  *
  62  * To prevent the M0 core resets from accidentally getting deasserted
  63  * status register must be check and bits in control register set to
  64  * preserve the state.
  65  */
  66 static int lpc18xx_rgu_setclear_reset(struct reset_controller_dev *rcdev,
  67                                       unsigned long id, bool set)
  68 {
  69         struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
  70         u32 stat_offset = LPC18XX_RGU_ACTIVE_STATUS0;
  71         u32 ctrl_offset = LPC18XX_RGU_CTRL0;
  72         unsigned long flags;
  73         u32 stat, rst_bit;
  74 
  75         stat_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
  76         ctrl_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
  77         rst_bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
  78 
  79         spin_lock_irqsave(&rc->lock, flags);
  80         stat = ~readl(rc->base + stat_offset);
  81         if (set)
  82                 writel(stat | rst_bit, rc->base + ctrl_offset);
  83         else
  84                 writel(stat & ~rst_bit, rc->base + ctrl_offset);
  85         spin_unlock_irqrestore(&rc->lock, flags);
  86 
  87         return 0;
  88 }
  89 
  90 static int lpc18xx_rgu_assert(struct reset_controller_dev *rcdev,
  91                               unsigned long id)
  92 {
  93         return lpc18xx_rgu_setclear_reset(rcdev, id, true);
  94 }
  95 
  96 static int lpc18xx_rgu_deassert(struct reset_controller_dev *rcdev,
  97                                 unsigned long id)
  98 {
  99         return lpc18xx_rgu_setclear_reset(rcdev, id, false);
 100 }
 101 
 102 /* Only M0 cores require explicit reset deassert */
 103 static int lpc18xx_rgu_reset(struct reset_controller_dev *rcdev,
 104                              unsigned long id)
 105 {
 106         struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
 107 
 108         lpc18xx_rgu_assert(rcdev, id);
 109         udelay(rc->delay_us);
 110 
 111         switch (id) {
 112         case LPC43XX_RGU_M0SUB_RST:
 113         case LPC43XX_RGU_M0APP_RST:
 114                 lpc18xx_rgu_setclear_reset(rcdev, id, false);
 115         }
 116 
 117         return 0;
 118 }
 119 
 120 static int lpc18xx_rgu_status(struct reset_controller_dev *rcdev,
 121                               unsigned long id)
 122 {
 123         struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
 124         u32 bit, offset = LPC18XX_RGU_ACTIVE_STATUS0;
 125 
 126         offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
 127         bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
 128 
 129         return !(readl(rc->base + offset) & bit);
 130 }
 131 
 132 static const struct reset_control_ops lpc18xx_rgu_ops = {
 133         .reset          = lpc18xx_rgu_reset,
 134         .assert         = lpc18xx_rgu_assert,
 135         .deassert       = lpc18xx_rgu_deassert,
 136         .status         = lpc18xx_rgu_status,
 137 };
 138 
 139 static int lpc18xx_rgu_probe(struct platform_device *pdev)
 140 {
 141         struct lpc18xx_rgu_data *rc;
 142         struct resource *res;
 143         u32 fcclk, firc;
 144         int ret;
 145 
 146         rc = devm_kzalloc(&pdev->dev, sizeof(*rc), GFP_KERNEL);
 147         if (!rc)
 148                 return -ENOMEM;
 149 
 150         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 151         rc->base = devm_ioremap_resource(&pdev->dev, res);
 152         if (IS_ERR(rc->base))
 153                 return PTR_ERR(rc->base);
 154 
 155         rc->clk_reg = devm_clk_get(&pdev->dev, "reg");
 156         if (IS_ERR(rc->clk_reg)) {
 157                 dev_err(&pdev->dev, "reg clock not found\n");
 158                 return PTR_ERR(rc->clk_reg);
 159         }
 160 
 161         rc->clk_delay = devm_clk_get(&pdev->dev, "delay");
 162         if (IS_ERR(rc->clk_delay)) {
 163                 dev_err(&pdev->dev, "delay clock not found\n");
 164                 return PTR_ERR(rc->clk_delay);
 165         }
 166 
 167         ret = clk_prepare_enable(rc->clk_reg);
 168         if (ret) {
 169                 dev_err(&pdev->dev, "unable to enable reg clock\n");
 170                 return ret;
 171         }
 172 
 173         ret = clk_prepare_enable(rc->clk_delay);
 174         if (ret) {
 175                 dev_err(&pdev->dev, "unable to enable delay clock\n");
 176                 goto dis_clk_reg;
 177         }
 178 
 179         fcclk = clk_get_rate(rc->clk_reg) / USEC_PER_SEC;
 180         firc = clk_get_rate(rc->clk_delay) / USEC_PER_SEC;
 181         if (fcclk == 0 || firc == 0)
 182                 rc->delay_us = 2;
 183         else
 184                 rc->delay_us = DIV_ROUND_UP(fcclk, firc * firc);
 185 
 186         spin_lock_init(&rc->lock);
 187 
 188         rc->rcdev.owner = THIS_MODULE;
 189         rc->rcdev.nr_resets = 64;
 190         rc->rcdev.ops = &lpc18xx_rgu_ops;
 191         rc->rcdev.of_node = pdev->dev.of_node;
 192 
 193         platform_set_drvdata(pdev, rc);
 194 
 195         ret = reset_controller_register(&rc->rcdev);
 196         if (ret) {
 197                 dev_err(&pdev->dev, "unable to register device\n");
 198                 goto dis_clks;
 199         }
 200 
 201         rc->restart_nb.priority = 192,
 202         rc->restart_nb.notifier_call = lpc18xx_rgu_restart,
 203         ret = register_restart_handler(&rc->restart_nb);
 204         if (ret)
 205                 dev_warn(&pdev->dev, "failed to register restart handler\n");
 206 
 207         return 0;
 208 
 209 dis_clks:
 210         clk_disable_unprepare(rc->clk_delay);
 211 dis_clk_reg:
 212         clk_disable_unprepare(rc->clk_reg);
 213 
 214         return ret;
 215 }
 216 
 217 static const struct of_device_id lpc18xx_rgu_match[] = {
 218         { .compatible = "nxp,lpc1850-rgu" },
 219         { }
 220 };
 221 
 222 static struct platform_driver lpc18xx_rgu_driver = {
 223         .probe  = lpc18xx_rgu_probe,
 224         .driver = {
 225                 .name                   = "lpc18xx-reset",
 226                 .of_match_table         = lpc18xx_rgu_match,
 227                 .suppress_bind_attrs    = true,
 228         },
 229 };
 230 builtin_platform_driver(lpc18xx_rgu_driver);

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