diff options
author | Tero Kristo <t-kristo@ti.com> | 2017-07-26 09:47:27 -0400 |
---|---|---|
committer | Tero Kristo <t-kristo@ti.com> | 2018-03-08 04:42:04 -0500 |
commit | 4902c2025b8ade9c230d4bca25ec5f691e91cb1f (patch) | |
tree | 96ec1d931a1c4c67ea9a7e852d9db8b963e1be73 | |
parent | be02637f6b741875aa0779c35f31591738aa2cd9 (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.c | 24 | ||||
-rw-r--r-- | include/linux/clk/ti.h | 2 |
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 | ||
58 | static 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 | |||
68 | static 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 | |||
58 | static u32 clk_memmap_readl(const struct clk_omap_reg *reg) | 81 | static 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 { | |||
226 | struct ti_clk_ll_ops { | 227 | struct 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); |