Loading drivers/clk/bcm/clk-kona-setup.c +30 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) struct peri_clk_data *peri; struct bcm_clk_policy *policy; struct bcm_clk_gate *gate; struct bcm_clk_hyst *hyst; struct bcm_clk_div *div; struct bcm_clk_sel *sel; struct bcm_clk_trig *trig; Loading @@ -106,12 +107,25 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) } gate = &peri->gate; hyst = &peri->hyst; if (gate_exists(gate)) { if (gate->offset > limit) { pr_err("%s: bad gate offset for %s (%u > %u)\n", __func__, name, gate->offset, limit); return false; } if (hyst_exists(hyst)) { if (hyst->offset > limit) { pr_err("%s: bad hysteresis offset for %s " "(%u > %u)\n", __func__, name, hyst->offset, limit); return false; } } } else if (hyst_exists(hyst)) { pr_err("%s: hysteresis but no gate for %s\n", __func__, name); return false; } div = &peri->div; Loading Loading @@ -261,6 +275,17 @@ static bool gate_valid(struct bcm_clk_gate *gate, const char *field_name, return true; } static bool hyst_valid(struct bcm_clk_hyst *hyst, const char *clock_name) { if (!bit_posn_valid(hyst->en_bit, "hysteresis enable", clock_name)) return false; if (!bit_posn_valid(hyst->val_bit, "hysteresis value", clock_name)) return false; return true; } /* * A selector bitfield must be valid. Its parent_sel array must * also be reasonable for the field. Loading Loading @@ -379,6 +404,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk) struct peri_clk_data *peri; struct bcm_clk_policy *policy; struct bcm_clk_gate *gate; struct bcm_clk_hyst *hyst; struct bcm_clk_sel *sel; struct bcm_clk_div *div; struct bcm_clk_div *pre_div; Loading Loading @@ -406,6 +432,10 @@ peri_clk_data_valid(struct kona_clk *bcm_clk) if (gate_exists(gate) && !gate_valid(gate, "gate", name)) return false; hyst = &peri->hyst; if (hyst_exists(hyst) && !hyst_valid(hyst, name)) return false; sel = &peri->sel; if (selector_exists(sel)) { if (!sel_valid(sel, "selector", name)) Loading drivers/clk/bcm/clk-kona.c +33 −0 Original line number Diff line number Diff line Loading @@ -527,6 +527,35 @@ static int clk_gate(struct ccu_data *ccu, const char *name, return -EIO; } /* Hysteresis operations */ /* * If a clock gate requires a turn-off delay it will have * "hysteresis" register bits defined. The first, if set, enables * the delay; and if enabled, the second bit determines whether the * delay is "low" or "high" (1 means high). For now, if it's * defined for a clock, we set it. */ static bool hyst_init(struct ccu_data *ccu, struct bcm_clk_hyst *hyst) { u32 offset; u32 reg_val; u32 mask; if (!hyst_exists(hyst)) return true; offset = hyst->offset; mask = (u32)1 << hyst->en_bit; mask |= (u32)1 << hyst->val_bit; reg_val = __ccu_read(ccu, offset); reg_val |= mask; __ccu_write(ccu, offset, reg_val); return true; } /* Trigger operations */ /* Loading Loading @@ -1131,6 +1160,10 @@ static bool __peri_clk_init(struct kona_clk *bcm_clk) pr_err("%s: error initializing gate for %s\n", __func__, name); return false; } if (!hyst_init(ccu, &peri->hyst)) { pr_err("%s: error initializing hyst for %s\n", __func__, name); return false; } if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) { pr_err("%s: error initializing divider for %s\n", __func__, name); Loading drivers/clk/bcm/clk-kona.h +19 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ #define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) #define hyst_exists(hyst) ((hyst)->offset != 0) #define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) #define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) #define divider_has_fraction(div) (!divider_is_fixed(div) && \ Loading Loading @@ -205,6 +207,22 @@ struct bcm_clk_gate { .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ } /* Gate hysteresis for clocks */ struct bcm_clk_hyst { u32 offset; /* hyst register offset (normally CLKGATE) */ u32 en_bit; /* bit used to enable hysteresis */ u32 val_bit; /* if enabled: 0 = low delay; 1 = high delay */ }; /* Hysteresis initialization macro */ #define HYST(_offset, _en_bit, _val_bit) \ { \ .offset = (_offset), \ .en_bit = (_en_bit), \ .val_bit = (_val_bit), \ } /* * Each clock can have zero, one, or two dividers which change the * output rate of the clock. Each divider can be either fixed or Loading Loading @@ -372,6 +390,7 @@ struct bcm_clk_trig { struct peri_clk_data { struct bcm_clk_policy policy; struct bcm_clk_gate gate; struct bcm_clk_hyst hyst; struct bcm_clk_trig pre_trig; struct bcm_clk_div pre_div; struct bcm_clk_trig trig; Loading Loading
drivers/clk/bcm/clk-kona-setup.c +30 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) struct peri_clk_data *peri; struct bcm_clk_policy *policy; struct bcm_clk_gate *gate; struct bcm_clk_hyst *hyst; struct bcm_clk_div *div; struct bcm_clk_sel *sel; struct bcm_clk_trig *trig; Loading @@ -106,12 +107,25 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk) } gate = &peri->gate; hyst = &peri->hyst; if (gate_exists(gate)) { if (gate->offset > limit) { pr_err("%s: bad gate offset for %s (%u > %u)\n", __func__, name, gate->offset, limit); return false; } if (hyst_exists(hyst)) { if (hyst->offset > limit) { pr_err("%s: bad hysteresis offset for %s " "(%u > %u)\n", __func__, name, hyst->offset, limit); return false; } } } else if (hyst_exists(hyst)) { pr_err("%s: hysteresis but no gate for %s\n", __func__, name); return false; } div = &peri->div; Loading Loading @@ -261,6 +275,17 @@ static bool gate_valid(struct bcm_clk_gate *gate, const char *field_name, return true; } static bool hyst_valid(struct bcm_clk_hyst *hyst, const char *clock_name) { if (!bit_posn_valid(hyst->en_bit, "hysteresis enable", clock_name)) return false; if (!bit_posn_valid(hyst->val_bit, "hysteresis value", clock_name)) return false; return true; } /* * A selector bitfield must be valid. Its parent_sel array must * also be reasonable for the field. Loading Loading @@ -379,6 +404,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk) struct peri_clk_data *peri; struct bcm_clk_policy *policy; struct bcm_clk_gate *gate; struct bcm_clk_hyst *hyst; struct bcm_clk_sel *sel; struct bcm_clk_div *div; struct bcm_clk_div *pre_div; Loading Loading @@ -406,6 +432,10 @@ peri_clk_data_valid(struct kona_clk *bcm_clk) if (gate_exists(gate) && !gate_valid(gate, "gate", name)) return false; hyst = &peri->hyst; if (hyst_exists(hyst) && !hyst_valid(hyst, name)) return false; sel = &peri->sel; if (selector_exists(sel)) { if (!sel_valid(sel, "selector", name)) Loading
drivers/clk/bcm/clk-kona.c +33 −0 Original line number Diff line number Diff line Loading @@ -527,6 +527,35 @@ static int clk_gate(struct ccu_data *ccu, const char *name, return -EIO; } /* Hysteresis operations */ /* * If a clock gate requires a turn-off delay it will have * "hysteresis" register bits defined. The first, if set, enables * the delay; and if enabled, the second bit determines whether the * delay is "low" or "high" (1 means high). For now, if it's * defined for a clock, we set it. */ static bool hyst_init(struct ccu_data *ccu, struct bcm_clk_hyst *hyst) { u32 offset; u32 reg_val; u32 mask; if (!hyst_exists(hyst)) return true; offset = hyst->offset; mask = (u32)1 << hyst->en_bit; mask |= (u32)1 << hyst->val_bit; reg_val = __ccu_read(ccu, offset); reg_val |= mask; __ccu_write(ccu, offset, reg_val); return true; } /* Trigger operations */ /* Loading Loading @@ -1131,6 +1160,10 @@ static bool __peri_clk_init(struct kona_clk *bcm_clk) pr_err("%s: error initializing gate for %s\n", __func__, name); return false; } if (!hyst_init(ccu, &peri->hyst)) { pr_err("%s: error initializing hyst for %s\n", __func__, name); return false; } if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) { pr_err("%s: error initializing divider for %s\n", __func__, name); Loading
drivers/clk/bcm/clk-kona.h +19 −0 Original line number Diff line number Diff line Loading @@ -60,6 +60,8 @@ #define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) #define hyst_exists(hyst) ((hyst)->offset != 0) #define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) #define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) #define divider_has_fraction(div) (!divider_is_fixed(div) && \ Loading Loading @@ -205,6 +207,22 @@ struct bcm_clk_gate { .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ } /* Gate hysteresis for clocks */ struct bcm_clk_hyst { u32 offset; /* hyst register offset (normally CLKGATE) */ u32 en_bit; /* bit used to enable hysteresis */ u32 val_bit; /* if enabled: 0 = low delay; 1 = high delay */ }; /* Hysteresis initialization macro */ #define HYST(_offset, _en_bit, _val_bit) \ { \ .offset = (_offset), \ .en_bit = (_en_bit), \ .val_bit = (_val_bit), \ } /* * Each clock can have zero, one, or two dividers which change the * output rate of the clock. Each divider can be either fixed or Loading Loading @@ -372,6 +390,7 @@ struct bcm_clk_trig { struct peri_clk_data { struct bcm_clk_policy policy; struct bcm_clk_gate gate; struct bcm_clk_hyst hyst; struct bcm_clk_trig pre_trig; struct bcm_clk_div pre_div; struct bcm_clk_trig trig; Loading