@@ -10,6 +10,7 @@
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
@@ -26,18 +27,37 @@
static inline u32 clk_mux_readl(struct clk_mux *mux)
{
- if (mux->flags & CLK_MUX_BIG_ENDIAN)
+ int ret;
+ uint32_t val;
+
+ if (mux->flags & CLK_MUX_BIG_ENDIAN) {
return ioread32be(mux->reg);
+ } else if (mux->flags & CLK_MUX_REGMAP) {
+ ret = regmap_read(mux->regmap, mux->reg_off, &val);
+ if (ret < 0) {
+ pr_warn("%s: failed read %x, %d\n", __func__, mux->reg_off, ret);
+ return ret;
+ } else {
+ return val;
+ }
+ }
return readl(mux->reg);
}
static inline void clk_mux_writel(struct clk_mux *mux, u32 val)
{
- if (mux->flags & CLK_MUX_BIG_ENDIAN)
+ int ret;
+
+ if (mux->flags & CLK_MUX_BIG_ENDIAN) {
iowrite32be(val, mux->reg);
- else
+ } else if (mux->flags & CLK_MUX_REGMAP) {
+ ret = regmap_write(mux->regmap, mux->reg_off, val);
+ if (ret < 0)
+ pr_warn("%s: failed write %x, %d\n", __func__, mux->reg_off, ret);
+ } else {
writel(val, mux->reg);
+ }
}
int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
@@ -837,6 +837,8 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
* @mask: mask of mutliplexer bit field
* @flags: hardware-specific flags
* @lock: register lock
+ * @regmap: register controlling regmap
+ * @reg_off: register offset
*
* Clock with multiple selectable parents. Implements .get_parent, .set_parent
* and .recalc_rate
@@ -855,6 +857,7 @@ void clk_hw_unregister_divider(struct clk_hw *hw);
* CLK_MUX_BIG_ENDIAN - By default little endian register accesses are used for
* the mux register. Setting this flag makes the register accesses big
* endian.
+ * CLK_MUX_REGMAP - Indicate the accessing method is using regmap API.
*/
struct clk_mux {
struct clk_hw hw;
@@ -864,6 +867,8 @@ struct clk_mux {
u8 shift;
u8 flags;
spinlock_t *lock;
+ struct regmap *regmap;
+ u32 reg_off;
};
#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
@@ -874,6 +879,7 @@ struct clk_mux {
#define CLK_MUX_READ_ONLY BIT(3) /* mux can't be changed */
#define CLK_MUX_ROUND_CLOSEST BIT(4)
#define CLK_MUX_BIG_ENDIAN BIT(5)
+#define CLK_MUX_REGMAP BIT(6)
extern const struct clk_ops clk_mux_ops;
extern const struct clk_ops clk_mux_ro_ops;