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