0001
0002
0003
0004
0005
0006
0007 #include <linux/delay.h>
0008 #include <linux/io.h>
0009 #include <linux/reset-controller.h>
0010
0011 #include "ccu_reset.h"
0012
0013 static int ccu_reset_assert(struct reset_controller_dev *rcdev,
0014 unsigned long id)
0015 {
0016 struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
0017 const struct ccu_reset_map *map = &ccu->reset_map[id];
0018 unsigned long flags;
0019 u32 reg;
0020
0021 spin_lock_irqsave(ccu->lock, flags);
0022
0023 reg = readl(ccu->base + map->reg);
0024 writel(reg & ~map->bit, ccu->base + map->reg);
0025
0026 spin_unlock_irqrestore(ccu->lock, flags);
0027
0028 return 0;
0029 }
0030
0031 static int ccu_reset_deassert(struct reset_controller_dev *rcdev,
0032 unsigned long id)
0033 {
0034 struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
0035 const struct ccu_reset_map *map = &ccu->reset_map[id];
0036 unsigned long flags;
0037 u32 reg;
0038
0039 spin_lock_irqsave(ccu->lock, flags);
0040
0041 reg = readl(ccu->base + map->reg);
0042 writel(reg | map->bit, ccu->base + map->reg);
0043
0044 spin_unlock_irqrestore(ccu->lock, flags);
0045
0046 return 0;
0047 }
0048
0049 static int ccu_reset_reset(struct reset_controller_dev *rcdev,
0050 unsigned long id)
0051 {
0052 ccu_reset_assert(rcdev, id);
0053 udelay(10);
0054 ccu_reset_deassert(rcdev, id);
0055
0056 return 0;
0057 }
0058
0059 static int ccu_reset_status(struct reset_controller_dev *rcdev,
0060 unsigned long id)
0061 {
0062 struct ccu_reset *ccu = rcdev_to_ccu_reset(rcdev);
0063 const struct ccu_reset_map *map = &ccu->reset_map[id];
0064
0065
0066
0067
0068
0069 return !(map->bit & readl(ccu->base + map->reg));
0070 }
0071
0072 const struct reset_control_ops ccu_reset_ops = {
0073 .assert = ccu_reset_assert,
0074 .deassert = ccu_reset_deassert,
0075 .reset = ccu_reset_reset,
0076 .status = ccu_reset_status,
0077 };
0078 EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);