ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[firefly-linux-kernel-4.4.55.git] / drivers / clk / rockchip / softrst.c
1 /*
2  * Copyright (c) 2014 MundoReader S.L.
3  * Author: Heiko Stuebner <heiko@sntech.de>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15
16 #include <linux/slab.h>
17 #include <linux/io.h>
18 #include <linux/reset-controller.h>
19 #include <linux/spinlock.h>
20 #include "clk.h"
21
22 struct rockchip_softrst {
23         struct reset_controller_dev     rcdev;
24         void __iomem                    *reg_base;
25         int                             num_regs;
26         int                             num_per_reg;
27         u8                              flags;
28         spinlock_t                      lock;
29 };
30
31 static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
32                               unsigned long id)
33 {
34         struct rockchip_softrst *softrst = container_of(rcdev,
35                                                      struct rockchip_softrst,
36                                                      rcdev);
37         int bank = id / softrst->num_per_reg;
38         int offset = id % softrst->num_per_reg;
39
40         if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
41                 writel(BIT(offset) | (BIT(offset) << 16),
42                        softrst->reg_base + (bank * 4));
43         } else {
44                 unsigned long flags;
45                 u32 reg;
46
47                 spin_lock_irqsave(&softrst->lock, flags);
48
49                 reg = readl(softrst->reg_base + (bank * 4));
50                 writel(reg | BIT(offset), softrst->reg_base + (bank * 4));
51
52                 spin_unlock_irqrestore(&softrst->lock, flags);
53         }
54
55         return 0;
56 }
57
58 static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
59                                 unsigned long id)
60 {
61         struct rockchip_softrst *softrst = container_of(rcdev,
62                                                      struct rockchip_softrst,
63                                                      rcdev);
64         int bank = id / softrst->num_per_reg;
65         int offset = id % softrst->num_per_reg;
66
67         if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
68                 writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
69         } else {
70                 unsigned long flags;
71                 u32 reg;
72
73                 spin_lock_irqsave(&softrst->lock, flags);
74
75                 reg = readl(softrst->reg_base + (bank * 4));
76                 writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4));
77
78                 spin_unlock_irqrestore(&softrst->lock, flags);
79         }
80
81         return 0;
82 }
83
84 static struct reset_control_ops rockchip_softrst_ops = {
85         .assert         = rockchip_softrst_assert,
86         .deassert       = rockchip_softrst_deassert,
87 };
88
89 void __init rockchip_register_softrst(struct device_node *np,
90                                       unsigned int num_regs,
91                                       void __iomem *base, u8 flags)
92 {
93         struct rockchip_softrst *softrst;
94         int ret;
95
96         softrst = kzalloc(sizeof(*softrst), GFP_KERNEL);
97         if (!softrst)
98                 return;
99
100         spin_lock_init(&softrst->lock);
101
102         softrst->reg_base = base;
103         softrst->flags = flags;
104         softrst->num_regs = num_regs;
105         softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
106                                                                       : 32;
107
108         softrst->rcdev.owner = THIS_MODULE;
109         softrst->rcdev.nr_resets =  num_regs * softrst->num_per_reg;
110         softrst->rcdev.ops = &rockchip_softrst_ops;
111         softrst->rcdev.of_node = np;
112         ret = reset_controller_register(&softrst->rcdev);
113         if (ret) {
114                 pr_err("%s: could not register reset controller, %d\n",
115                        __func__, ret);
116                 kfree(softrst);
117         }
118 };