aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTero Kristo <t-kristo@ti.com>2017-07-26 09:47:27 -0400
committerTero Kristo <t-kristo@ti.com>2018-03-08 04:42:04 -0500
commit4902c2025b8ade9c230d4bca25ec5f691e91cb1f (patch)
tree96ec1d931a1c4c67ea9a7e852d9db8b963e1be73
parentbe02637f6b741875aa0779c35f31591738aa2cd9 (diff)
clk: ti: add support for register read-modify-write low-level operation
Useful for changing few bits on a register, this makes sure for example that the operation is done atomically in case of syscon. Signed-off-by: Tero Kristo <t-kristo@ti.com>
-rw-r--r--drivers/clk/ti/clk.c24
-rw-r--r--include/linux/clk/ti.h2
2 files changed, 26 insertions, 0 deletions
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index f4d6802a8544..4efa2c9ea908 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -55,6 +55,29 @@ static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg)
55 writel_relaxed(val, io->mem + reg->offset); 55 writel_relaxed(val, io->mem + reg->offset);
56} 56}
57 57
58static void _clk_rmw(u32 val, u32 mask, void __iomem *ptr)
59{
60 u32 v;
61
62 v = readl_relaxed(ptr);
63 v &= ~mask;
64 v |= val;
65 writel_relaxed(v, ptr);
66}
67
68static void clk_memmap_rmw(u32 val, u32 mask, const struct clk_omap_reg *reg)
69{
70 struct clk_iomap *io = clk_memmaps[reg->index];
71
72 if (reg->ptr) {
73 _clk_rmw(val, mask, reg->ptr);
74 } else if (io->regmap) {
75 regmap_update_bits(io->regmap, reg->offset, mask, val);
76 } else {
77 _clk_rmw(val, mask, io->mem + reg->offset);
78 }
79}
80
58static u32 clk_memmap_readl(const struct clk_omap_reg *reg) 81static u32 clk_memmap_readl(const struct clk_omap_reg *reg)
59{ 82{
60 u32 val; 83 u32 val;
@@ -89,6 +112,7 @@ int ti_clk_setup_ll_ops(struct ti_clk_ll_ops *ops)
89 ti_clk_ll_ops = ops; 112 ti_clk_ll_ops = ops;
90 ops->clk_readl = clk_memmap_readl; 113 ops->clk_readl = clk_memmap_readl;
91 ops->clk_writel = clk_memmap_writel; 114 ops->clk_writel = clk_memmap_writel;
115 ops->clk_rmw = clk_memmap_rmw;
92 116
93 return 0; 117 return 0;
94} 118}
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index d18da839b810..9e8611470187 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -211,6 +211,7 @@ enum {
211 * struct ti_clk_ll_ops - low-level ops for clocks 211 * struct ti_clk_ll_ops - low-level ops for clocks
212 * @clk_readl: pointer to register read function 212 * @clk_readl: pointer to register read function
213 * @clk_writel: pointer to register write function 213 * @clk_writel: pointer to register write function
214 * @clk_rmw: pointer to register read-modify-write function
214 * @clkdm_clk_enable: pointer to clockdomain enable function 215 * @clkdm_clk_enable: pointer to clockdomain enable function
215 * @clkdm_clk_disable: pointer to clockdomain disable function 216 * @clkdm_clk_disable: pointer to clockdomain disable function
216 * @clkdm_lookup: pointer to clockdomain lookup function 217 * @clkdm_lookup: pointer to clockdomain lookup function
@@ -226,6 +227,7 @@ enum {
226struct ti_clk_ll_ops { 227struct ti_clk_ll_ops {
227 u32 (*clk_readl)(const struct clk_omap_reg *reg); 228 u32 (*clk_readl)(const struct clk_omap_reg *reg);
228 void (*clk_writel)(u32 val, const struct clk_omap_reg *reg); 229 void (*clk_writel)(u32 val, const struct clk_omap_reg *reg);
230 void (*clk_rmw)(u32 val, u32 mask, const struct clk_omap_reg *reg);
229 int (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk); 231 int (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
230 int (*clkdm_clk_disable)(struct clockdomain *clkdm, 232 int (*clkdm_clk_disable)(struct clockdomain *clkdm,
231 struct clk *clk); 233 struct clk *clk);