Source
x
/*
* Reset driver for NXP LPC18xx/43xx Reset Generation Unit (RGU).
*
* Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
*
* 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.
*
*/
/* LPC18xx RGU registers */
/* Internal reset outputs */
struct lpc18xx_rgu_data {
struct reset_controller_dev rcdev;
struct notifier_block restart_nb;
struct clk *clk_delay;
struct clk *clk_reg;
void __iomem *base;
spinlock_t lock;
u32 delay_us;
};
static int lpc18xx_rgu_restart(struct notifier_block *nb, unsigned long mode,
void *cmd)
{
struct lpc18xx_rgu_data *rc = container_of(nb, struct lpc18xx_rgu_data,
restart_nb);
writel(BIT(LPC18XX_RGU_CORE_RST), rc->base + LPC18XX_RGU_CTRL0);
mdelay(2000);
pr_emerg("%s: unable to restart system\n", __func__);
return NOTIFY_DONE;
}
/*
* The LPC18xx RGU has mostly self-deasserting resets except for the
* two reset lines going to the internal Cortex-M0 cores.
*
* To prevent the M0 core resets from accidentally getting deasserted
* status register must be check and bits in control register set to
* preserve the state.
*/
static int lpc18xx_rgu_setclear_reset(struct reset_controller_dev *rcdev,
unsigned long id, bool set)
{
struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
u32 stat_offset = LPC18XX_RGU_ACTIVE_STATUS0;
u32 ctrl_offset = LPC18XX_RGU_CTRL0;
unsigned long flags;
u32 stat, rst_bit;
stat_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
ctrl_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
rst_bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
spin_lock_irqsave(&rc->lock, flags);
stat = ~readl(rc->base + stat_offset);
if (set)
writel(stat | rst_bit, rc->base + ctrl_offset);
else
writel(stat & ~rst_bit, rc->base + ctrl_offset);
spin_unlock_irqrestore(&rc->lock, flags);
return 0;
}