linux/drivers/clk/sunxi-ng/ccu_reset.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2016 Maxime Ripard
   4 * Maxime Ripard <maxime.ripard@free-electrons.com>
   5 */
   6
   7#include <linux/delay.h>
   8#include <linux/io.h>
   9#include <linux/reset-controller.h>
  10
  11#include "ccu_reset.h"
  12
  13static int ccu_reset_assert(struct reset_controller_dev *rcdev,
  14                            unsigned long id)
  15{
  16        struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  17        const struct ccu_reset_map *map = &ccu->reset_map[id];
  18        unsigned long flags;
  19        u32 reg;
  20
  21        spin_lock_irqsave(ccu->lock, flags);
  22
  23        reg = readl(ccu->base + map->reg);
  24        writel(reg & ~map->bit, ccu->base + map->reg);
  25
  26        spin_unlock_irqrestore(ccu->lock, flags);
  27
  28        return 0;
  29}
  30
  31static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
  32                              unsigned long id)
  33{
  34        struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  35        const struct ccu_reset_map *map = &ccu->reset_map[id];
  36        unsigned long flags;
  37        u32 reg;
  38
  39        spin_lock_irqsave(ccu->lock, flags);
  40
  41        reg = readl(ccu->base + map->reg);
  42        writel(reg | map->bit, ccu->base + map->reg);
  43
  44        spin_unlock_irqrestore(ccu->lock, flags);
  45
  46        return 0;
  47}
  48
  49static int ccu_reset_reset(struct reset_controller_dev *rcdev,
  50                           unsigned long id)
  51{
  52        ccu_reset_assert(rcdev, id);
  53        udelay(10);
  54        ccu_reset_deassert(rcdev, id);
  55
  56        return 0;
  57}
  58
  59static int ccu_reset_status(struct reset_controller_dev *rcdev,
  60                            unsigned long id)
  61{
  62        struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
  63        const struct ccu_reset_map *map = &ccu->reset_map[id];
  64
  65        /*
  66         * The reset control API expects 0 if reset is not asserted,
  67         * which is the opposite of what our hardware uses.
  68         */
  69        return !(map->bit & readl(ccu->base + map->reg));
  70}
  71
  72const struct reset_control_ops ccu_reset_ops = {
  73        .assert         = ccu_reset_assert,
  74        .deassert       = ccu_reset_deassert,
  75        .reset          = ccu_reset_reset,
  76        .status         = ccu_reset_status,
  77};
  78