diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 8777eab86b01..4f967084137e 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -184,6 +184,12 @@ static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw) {"APSS_SLEEP_VOTE", 0x4}, }; + static struct clk_register_data data2[] = { + {"MEM_ENABLE", 0x0}, + {"MEM_ENABLE_ACK", 0x0}, + {"MEM_ENABLE_ACK_MASK", 0x0}, + }; + size = ARRAY_SIZE(data); for (i = 0; i < size; i++) { @@ -204,6 +210,18 @@ static void clk_branch2_list_registers(struct seq_file *f, struct clk_hw *hw) } } } + + if (br->mem_enable_reg && br->mem_ack_reg) { + regmap_read(br->clkr.regmap, br->mem_enable_reg + + data2[0].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data2[0].name, val); + + regmap_read(br->clkr.regmap, br->mem_ack_reg + + data2[1].offset, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", data2[1].name, val); + clock_debug_output(f, "%20s: 0x%.8x\n", data2[2].name, + br->mem_enable_ack_bit); + } } static int clk_branch2_set_flags(struct clk_hw *hw, unsigned long flags) @@ -260,6 +278,39 @@ static int clk_branch2_init(struct clk_hw *hw) return 0; } +static int clk_branch2_mem_enable(struct clk_hw *hw) +{ + struct clk_branch *br = to_clk_branch(hw); + u32 val; + int count = 200; + + regmap_update_bits(br->clkr.regmap, br->mem_enable_reg, + br->mem_enable_ack_bit, br->mem_enable_ack_bit); + + regmap_read(br->clkr.regmap, br->mem_ack_reg, &val); + + pr_debug("%s Val 0x%x\n", __func__, val); + while (count-- > 0) { + if (val & br->mem_enable_ack_bit) { + pr_debug("%s Val 0x%x\n", __func__, val); + return clk_branch2_enable(hw); + } + udelay(1); + regmap_read(br->clkr.regmap, br->mem_ack_reg, &val); + } + + return -EBUSY; +} + +static void clk_branch2_mem_disable(struct clk_hw *hw) +{ + struct clk_branch *br = to_clk_branch(hw); + + regmap_update_bits(br->clkr.regmap, br->mem_enable_reg, + br->mem_enable_ack_bit, 0); + return clk_branch2_disable(hw); +} + const struct clk_ops clk_branch2_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, @@ -290,6 +341,15 @@ const struct clk_ops clk_branch2_force_off_ops = { }; EXPORT_SYMBOL(clk_branch2_force_off_ops); +const struct clk_ops clk_branch2_mem_ops = { + .enable = clk_branch2_mem_enable, + .disable = clk_branch2_mem_disable, + .is_enabled = clk_is_enabled_regmap, + .init = clk_branch2_init, + .debug_init = clk_branch_debug_init, +}; +EXPORT_SYMBOL(clk_branch2_mem_ops); + static unsigned long clk_branch2_hw_ctl_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index eeabc1573bec..2657c0ab7486 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -23,8 +23,11 @@ struct clk_branch { u32 hwcg_reg; u32 halt_reg; + u32 mem_enable_reg; + u32 mem_ack_reg; u8 hwcg_bit; u8 halt_bit; + u8 mem_enable_ack_bit; u8 halt_check; #define BRANCH_VOTED BIT(7) /* Delay on disable */ #define BRANCH_HALT 0 /* pol: 1 = halt */ @@ -43,6 +46,7 @@ extern const struct clk_ops clk_branch2_hw_ctl_ops; extern const struct clk_ops clk_branch_simple_ops; extern const struct clk_ops clk_branch2_aon_ops; extern const struct clk_ops clk_branch2_force_off_ops; +extern const struct clk_ops clk_branch2_mem_ops; #define to_clk_branch(_hw) \ container_of(to_clk_regmap(_hw), struct clk_branch, clkr) diff --git a/drivers/clk/qcom/clk-opp.h b/drivers/clk/qcom/clk-opp.h index aba1ee18bff5..eaf25b853073 100644 --- a/drivers/clk/qcom/clk-opp.h +++ b/drivers/clk/qcom/clk-opp.h @@ -7,7 +7,7 @@ void clk_hw_populate_clock_opp_table(struct device_node *np, struct clk_hw *hw); -#define MAX_LEN_OPP_HANDLE 50 +#define MAX_LEN_OPP_HANDLE 100 #define LEN_OPP_HANDLE 16 #endif