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