79 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (C) 2016 Maxime Ripard4 * 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};78EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);79