ccu_reset.c (1858B)
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}; 78EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);