Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Stephen Boyd:
"Here's more than a handful of clk driver fixes for changes that came
in during the merge window:

- Fix the AT91 sama5d2 programmable clk prescaler formula

- A bunch of Amlogic meson clk driver fixes for the VPU clks

- A DMI quirk for Intel's Bay Trail SoC's driver to properly mark pmc
clks as critical only when really needed

- Stop overwriting CLK_SET_RATE_PARENT flag in mediatek's clk gate
implementation

- Use the right structure to test for a frequency table in i.MX's
PLL_1416x driver"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
clk: imx: Fix PLL_1416X not rounding rates
clk: mediatek: fix clk-gate flag setting
platform/x86: pmc_atom: Drop __initconst on dmi table
clk: x86: Add system specific quirk to mark clocks as critical
clk: meson: vid-pll-div: remove warning and return 0 on invalid config
clk: meson: pll: fix rounding and setting a rate that matches precisely
clk: meson-g12a: fix VPU clock parents
clk: meson: g12a: fix VPU clock muxes mask
clk: meson-gxbb: round the vdec dividers to closest
clk: at91: fix programmable clock for sama5d2

+99 -27
+43 -14
drivers/clk/at91/clk-programmable.c
··· 20 20 #define PROG_ID_MAX 7 21 21 22 22 #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) 23 - #define PROG_PRES_MASK 0x7 24 - #define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) 23 + #define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & layout->pres_mask) 25 24 #define PROG_MAX_RM9200_CSS 3 26 25 27 26 struct clk_programmable { ··· 36 37 unsigned long parent_rate) 37 38 { 38 39 struct clk_programmable *prog = to_clk_programmable(hw); 40 + const struct clk_programmable_layout *layout = prog->layout; 39 41 unsigned int pckr; 42 + unsigned long rate; 40 43 41 44 regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); 42 45 43 - return parent_rate >> PROG_PRES(prog->layout, pckr); 46 + if (layout->is_pres_direct) 47 + rate = parent_rate / (PROG_PRES(layout, pckr) + 1); 48 + else 49 + rate = parent_rate >> PROG_PRES(layout, pckr); 50 + 51 + return rate; 44 52 } 45 53 46 54 static int clk_programmable_determine_rate(struct clk_hw *hw, 47 55 struct clk_rate_request *req) 48 56 { 57 + struct clk_programmable *prog = to_clk_programmable(hw); 58 + const struct clk_programmable_layout *layout = prog->layout; 49 59 struct clk_hw *parent; 50 60 long best_rate = -EINVAL; 51 61 unsigned long parent_rate; 52 - unsigned long tmp_rate; 62 + unsigned long tmp_rate = 0; 53 63 int shift; 54 64 int i; 55 65 ··· 68 60 continue; 69 61 70 62 parent_rate = clk_hw_get_rate(parent); 71 - for (shift = 0; shift < PROG_PRES_MASK; shift++) { 72 - tmp_rate = parent_rate >> shift; 73 - if (tmp_rate <= req->rate) 74 - break; 63 + if (layout->is_pres_direct) { 64 + for (shift = 0; shift <= layout->pres_mask; shift++) { 65 + tmp_rate = parent_rate / (shift + 1); 66 + if (tmp_rate <= req->rate) 67 + break; 68 + } 69 + } else { 70 + for (shift = 0; shift < layout->pres_mask; shift++) { 71 + tmp_rate = parent_rate >> shift; 72 + if (tmp_rate <= req->rate) 73 + break; 74 + } 75 75 } 76 76 77 77 if (tmp_rate > req->rate) ··· 153 137 if (!div) 154 138 return -EINVAL; 155 139 156 - shift = fls(div) - 1; 140 + if (layout->is_pres_direct) { 141 + shift = div - 1; 157 142 158 - if (div != (1 << shift)) 159 - return -EINVAL; 143 + if (shift > layout->pres_mask) 144 + return -EINVAL; 145 + } else { 146 + shift = fls(div) - 1; 160 147 161 - if (shift >= PROG_PRES_MASK) 162 - return -EINVAL; 148 + if (div != (1 << shift)) 149 + return -EINVAL; 150 + 151 + if (shift >= layout->pres_mask) 152 + return -EINVAL; 153 + } 163 154 164 155 regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), 165 - PROG_PRES_MASK << layout->pres_shift, 156 + layout->pres_mask << layout->pres_shift, 166 157 shift << layout->pres_shift); 167 158 168 159 return 0; ··· 225 202 } 226 203 227 204 const struct clk_programmable_layout at91rm9200_programmable_layout = { 205 + .pres_mask = 0x7, 228 206 .pres_shift = 2, 229 207 .css_mask = 0x3, 230 208 .have_slck_mck = 0, 209 + .is_pres_direct = 0, 231 210 }; 232 211 233 212 const struct clk_programmable_layout at91sam9g45_programmable_layout = { 213 + .pres_mask = 0x7, 234 214 .pres_shift = 2, 235 215 .css_mask = 0x3, 236 216 .have_slck_mck = 1, 217 + .is_pres_direct = 0, 237 218 }; 238 219 239 220 const struct clk_programmable_layout at91sam9x5_programmable_layout = { 221 + .pres_mask = 0x7, 240 222 .pres_shift = 4, 241 223 .css_mask = 0x7, 242 224 .have_slck_mck = 0, 225 + .is_pres_direct = 0, 243 226 };
+2
drivers/clk/at91/pmc.h
··· 71 71 }; 72 72 73 73 struct clk_programmable_layout { 74 + u8 pres_mask; 74 75 u8 pres_shift; 75 76 u8 css_mask; 76 77 u8 have_slck_mck; 78 + u8 is_pres_direct; 77 79 }; 78 80 79 81 extern const struct clk_programmable_layout at91rm9200_programmable_layout;
+9 -1
drivers/clk/at91/sama5d2.c
··· 125 125 .pll = true }, 126 126 }; 127 127 128 + static const struct clk_programmable_layout sama5d2_programmable_layout = { 129 + .pres_mask = 0xff, 130 + .pres_shift = 4, 131 + .css_mask = 0x7, 132 + .have_slck_mck = 0, 133 + .is_pres_direct = 1, 134 + }; 135 + 128 136 static void __init sama5d2_pmc_setup(struct device_node *np) 129 137 { 130 138 struct clk_range range = CLK_RANGE(0, 0); ··· 257 249 258 250 hw = at91_clk_register_programmable(regmap, name, 259 251 parent_names, 6, i, 260 - &at91sam9x5_programmable_layout); 252 + &sama5d2_programmable_layout); 261 253 if (IS_ERR(hw)) 262 254 goto err_free; 263 255 }
+1 -1
drivers/clk/imx/clk-pll14xx.c
··· 362 362 363 363 switch (pll_clk->type) { 364 364 case PLL_1416X: 365 - if (!pll->rate_table) 365 + if (!pll_clk->rate_table) 366 366 init.ops = &clk_pll1416x_min_ops; 367 367 else 368 368 init.ops = &clk_pll1416x_ops;
+1 -2
drivers/clk/mediatek/clk-gate.c
··· 169 169 return ERR_PTR(-ENOMEM); 170 170 171 171 init.name = name; 172 - init.flags = CLK_SET_RATE_PARENT; 172 + init.flags = flags | CLK_SET_RATE_PARENT; 173 173 init.parent_names = parent_name ? &parent_name : NULL; 174 174 init.num_parents = parent_name ? 1 : 0; 175 175 init.ops = ops; 176 - init.flags = flags; 177 176 178 177 cg->regmap = regmap; 179 178 cg->set_ofs = set_ofs;
+1 -1
drivers/clk/meson/clk-pll.c
··· 120 120 return true; 121 121 } else { 122 122 /* Round down */ 123 - if (now < rate && best < now) 123 + if (now <= rate && best < now) 124 124 return true; 125 125 } 126 126
+3 -3
drivers/clk/meson/g12a.c
··· 960 960 /* VPU Clock */ 961 961 962 962 static const char * const g12a_vpu_parent_names[] = { 963 - "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", 963 + "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7", 964 964 "mpll1", "vid_pll", "hifi_pll", "gp0_pll", 965 965 }; 966 966 967 967 static struct clk_regmap g12a_vpu_0_sel = { 968 968 .data = &(struct clk_regmap_mux_data){ 969 969 .offset = HHI_VPU_CLK_CNTL, 970 - .mask = 0x3, 970 + .mask = 0x7, 971 971 .shift = 9, 972 972 }, 973 973 .hw.init = &(struct clk_init_data){ ··· 1011 1011 static struct clk_regmap g12a_vpu_1_sel = { 1012 1012 .data = &(struct clk_regmap_mux_data){ 1013 1013 .offset = HHI_VPU_CLK_CNTL, 1014 - .mask = 0x3, 1014 + .mask = 0x7, 1015 1015 .shift = 25, 1016 1016 }, 1017 1017 .hw.init = &(struct clk_init_data){
+2
drivers/clk/meson/gxbb.c
··· 2216 2216 .offset = HHI_VDEC_CLK_CNTL, 2217 2217 .shift = 0, 2218 2218 .width = 7, 2219 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 2219 2220 }, 2220 2221 .hw.init = &(struct clk_init_data){ 2221 2222 .name = "vdec_1_div", ··· 2262 2261 .offset = HHI_VDEC2_CLK_CNTL, 2263 2262 .shift = 16, 2264 2263 .width = 7, 2264 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 2265 2265 }, 2266 2266 .hw.init = &(struct clk_init_data){ 2267 2267 .name = "vdec_hevc_div",
+2 -2
drivers/clk/meson/vid-pll-div.c
··· 82 82 div = _get_table_val(meson_parm_read(clk->map, &pll_div->val), 83 83 meson_parm_read(clk->map, &pll_div->sel)); 84 84 if (!div || !div->divider) { 85 - pr_info("%s: Invalid config value for vid_pll_div\n", __func__); 86 - return parent_rate; 85 + pr_debug("%s: Invalid config value for vid_pll_div\n", __func__); 86 + return 0; 87 87 } 88 88 89 89 return DIV_ROUND_UP_ULL(parent_rate * div->multiplier, div->divider);
+11 -3
drivers/clk/x86/clk-pmc-atom.c
··· 165 165 }; 166 166 167 167 static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, 168 - void __iomem *base, 168 + const struct pmc_clk_data *pmc_data, 169 169 const char **parent_names, 170 170 int num_parents) 171 171 { ··· 184 184 init.num_parents = num_parents; 185 185 186 186 pclk->hw.init = &init; 187 - pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; 187 + pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; 188 188 spin_lock_init(&pclk->lock); 189 + 190 + /* 191 + * On some systems, the pmc_plt_clocks already enabled by the 192 + * firmware are being marked as critical to avoid them being 193 + * gated by the clock framework. 194 + */ 195 + if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw)) 196 + init.flags |= CLK_IS_CRITICAL; 189 197 190 198 ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); 191 199 if (ret) { ··· 340 332 return PTR_ERR(parent_names); 341 333 342 334 for (i = 0; i < PMC_CLK_NUM; i++) { 343 - data->clks[i] = plt_clk_register(pdev, i, pmc_data->base, 335 + data->clks[i] = plt_clk_register(pdev, i, pmc_data, 344 336 parent_names, data->nparents); 345 337 if (IS_ERR(data->clks[i])) { 346 338 err = PTR_ERR(data->clks[i]);
+21
drivers/platform/x86/pmc_atom.c
··· 17 17 18 18 #include <linux/debugfs.h> 19 19 #include <linux/device.h> 20 + #include <linux/dmi.h> 20 21 #include <linux/init.h> 21 22 #include <linux/io.h> 22 23 #include <linux/platform_data/x86/clk-pmc-atom.h> ··· 392 391 } 393 392 #endif /* CONFIG_DEBUG_FS */ 394 393 394 + /* 395 + * Some systems need one or more of their pmc_plt_clks to be 396 + * marked as critical. 397 + */ 398 + static const struct dmi_system_id critclk_systems[] = { 399 + { 400 + .ident = "MPL CEC1x", 401 + .matches = { 402 + DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"), 403 + DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"), 404 + }, 405 + }, 406 + { /*sentinel*/ } 407 + }; 408 + 395 409 static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap, 396 410 const struct pmc_data *pmc_data) 397 411 { 398 412 struct platform_device *clkdev; 399 413 struct pmc_clk_data *clk_data; 414 + const struct dmi_system_id *d = dmi_first_match(critclk_systems); 400 415 401 416 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); 402 417 if (!clk_data) ··· 420 403 421 404 clk_data->base = pmc_regmap; /* offset is added by client */ 422 405 clk_data->clks = pmc_data->clks; 406 + if (d) { 407 + clk_data->critical = true; 408 + pr_info("%s critclks quirk enabled\n", d->ident); 409 + } 423 410 424 411 clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom", 425 412 PLATFORM_DEVID_NONE,
+3
include/linux/platform_data/x86/clk-pmc-atom.h
··· 35 35 * 36 36 * @base: PMC clock register base offset 37 37 * @clks: pointer to set of registered clocks, typically 0..5 38 + * @critical: flag to indicate if firmware enabled pmc_plt_clks 39 + * should be marked as critial or not 38 40 */ 39 41 struct pmc_clk_data { 40 42 void __iomem *base; 41 43 const struct pmc_clk *clks; 44 + bool critical; 42 45 }; 43 46 44 47 #endif /* __PLATFORM_DATA_X86_CLK_PMC_ATOM_H */