Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * TI Divider Clock
0004  *
0005  * Copyright (C) 2013 Texas Instruments, Inc.
0006  *
0007  * Tero Kristo <t-kristo@ti.com>
0008  */
0009 
0010 #include <linux/clk-provider.h>
0011 #include <linux/slab.h>
0012 #include <linux/err.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/clk/ti.h>
0016 #include "clock.h"
0017 
0018 #undef pr_fmt
0019 #define pr_fmt(fmt) "%s: " fmt, __func__
0020 
0021 static unsigned int _get_table_div(const struct clk_div_table *table,
0022                    unsigned int val)
0023 {
0024     const struct clk_div_table *clkt;
0025 
0026     for (clkt = table; clkt->div; clkt++)
0027         if (clkt->val == val)
0028             return clkt->div;
0029     return 0;
0030 }
0031 
0032 static void _setup_mask(struct clk_omap_divider *divider)
0033 {
0034     u16 mask;
0035     u32 max_val;
0036     const struct clk_div_table *clkt;
0037 
0038     if (divider->table) {
0039         max_val = 0;
0040 
0041         for (clkt = divider->table; clkt->div; clkt++)
0042             if (clkt->val > max_val)
0043                 max_val = clkt->val;
0044     } else {
0045         max_val = divider->max;
0046 
0047         if (!(divider->flags & CLK_DIVIDER_ONE_BASED) &&
0048             !(divider->flags & CLK_DIVIDER_POWER_OF_TWO))
0049             max_val--;
0050     }
0051 
0052     if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0053         mask = fls(max_val) - 1;
0054     else
0055         mask = max_val;
0056 
0057     divider->mask = (1 << fls(mask)) - 1;
0058 }
0059 
0060 static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
0061 {
0062     if (divider->flags & CLK_DIVIDER_ONE_BASED)
0063         return val;
0064     if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0065         return 1 << val;
0066     if (divider->table)
0067         return _get_table_div(divider->table, val);
0068     return val + 1;
0069 }
0070 
0071 static unsigned int _get_table_val(const struct clk_div_table *table,
0072                    unsigned int div)
0073 {
0074     const struct clk_div_table *clkt;
0075 
0076     for (clkt = table; clkt->div; clkt++)
0077         if (clkt->div == div)
0078             return clkt->val;
0079     return 0;
0080 }
0081 
0082 static unsigned int _get_val(struct clk_omap_divider *divider, u8 div)
0083 {
0084     if (divider->flags & CLK_DIVIDER_ONE_BASED)
0085         return div;
0086     if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0087         return __ffs(div);
0088     if (divider->table)
0089         return  _get_table_val(divider->table, div);
0090     return div - 1;
0091 }
0092 
0093 static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
0094                         unsigned long parent_rate)
0095 {
0096     struct clk_omap_divider *divider = to_clk_omap_divider(hw);
0097     unsigned int div, val;
0098 
0099     val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
0100     val &= divider->mask;
0101 
0102     div = _get_div(divider, val);
0103     if (!div) {
0104         WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
0105              "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
0106              clk_hw_get_name(hw));
0107         return parent_rate;
0108     }
0109 
0110     return DIV_ROUND_UP(parent_rate, div);
0111 }
0112 
0113 /*
0114  * The reverse of DIV_ROUND_UP: The maximum number which
0115  * divided by m is r
0116  */
0117 #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
0118 
0119 static bool _is_valid_table_div(const struct clk_div_table *table,
0120                 unsigned int div)
0121 {
0122     const struct clk_div_table *clkt;
0123 
0124     for (clkt = table; clkt->div; clkt++)
0125         if (clkt->div == div)
0126             return true;
0127     return false;
0128 }
0129 
0130 static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div)
0131 {
0132     if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
0133         return is_power_of_2(div);
0134     if (divider->table)
0135         return _is_valid_table_div(divider->table, div);
0136     return true;
0137 }
0138 
0139 static int _div_round_up(const struct clk_div_table *table,
0140              unsigned long parent_rate, unsigned long rate)
0141 {
0142     const struct clk_div_table *clkt;
0143     int up = INT_MAX;
0144     int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
0145 
0146     for (clkt = table; clkt->div; clkt++) {
0147         if (clkt->div == div)
0148             return clkt->div;
0149         else if (clkt->div < div)
0150             continue;
0151 
0152         if ((clkt->div - div) < (up - div))
0153             up = clkt->div;
0154     }
0155 
0156     return up;
0157 }
0158 
0159 static int _div_round(const struct clk_div_table *table,
0160               unsigned long parent_rate, unsigned long rate)
0161 {
0162     if (!table)
0163         return DIV_ROUND_UP(parent_rate, rate);
0164 
0165     return _div_round_up(table, parent_rate, rate);
0166 }
0167 
0168 static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
0169                   unsigned long *best_parent_rate)
0170 {
0171     struct clk_omap_divider *divider = to_clk_omap_divider(hw);
0172     int i, bestdiv = 0;
0173     unsigned long parent_rate, best = 0, now, maxdiv;
0174     unsigned long parent_rate_saved = *best_parent_rate;
0175 
0176     if (!rate)
0177         rate = 1;
0178 
0179     maxdiv = divider->max;
0180 
0181     if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
0182         parent_rate = *best_parent_rate;
0183         bestdiv = _div_round(divider->table, parent_rate, rate);
0184         bestdiv = bestdiv == 0 ? 1 : bestdiv;
0185         bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
0186         return bestdiv;
0187     }
0188 
0189     /*
0190      * The maximum divider we can use without overflowing
0191      * unsigned long in rate * i below
0192      */
0193     maxdiv = min(ULONG_MAX / rate, maxdiv);
0194 
0195     for (i = 1; i <= maxdiv; i++) {
0196         if (!_is_valid_div(divider, i))
0197             continue;
0198         if (rate * i == parent_rate_saved) {
0199             /*
0200              * It's the most ideal case if the requested rate can be
0201              * divided from parent clock without needing to change
0202              * parent rate, so return the divider immediately.
0203              */
0204             *best_parent_rate = parent_rate_saved;
0205             return i;
0206         }
0207         parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
0208                 MULT_ROUND_UP(rate, i));
0209         now = DIV_ROUND_UP(parent_rate, i);
0210         if (now <= rate && now > best) {
0211             bestdiv = i;
0212             best = now;
0213             *best_parent_rate = parent_rate;
0214         }
0215     }
0216 
0217     if (!bestdiv) {
0218         bestdiv = divider->max;
0219         *best_parent_rate =
0220             clk_hw_round_rate(clk_hw_get_parent(hw), 1);
0221     }
0222 
0223     return bestdiv;
0224 }
0225 
0226 static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
0227                       unsigned long *prate)
0228 {
0229     int div;
0230     div = ti_clk_divider_bestdiv(hw, rate, prate);
0231 
0232     return DIV_ROUND_UP(*prate, div);
0233 }
0234 
0235 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
0236                    unsigned long parent_rate)
0237 {
0238     struct clk_omap_divider *divider;
0239     unsigned int div, value;
0240     u32 val;
0241 
0242     if (!hw || !rate)
0243         return -EINVAL;
0244 
0245     divider = to_clk_omap_divider(hw);
0246 
0247     div = DIV_ROUND_UP(parent_rate, rate);
0248 
0249     if (div > divider->max)
0250         div = divider->max;
0251     if (div < divider->min)
0252         div = divider->min;
0253 
0254     value = _get_val(divider, div);
0255 
0256     val = ti_clk_ll_ops->clk_readl(&divider->reg);
0257     val &= ~(divider->mask << divider->shift);
0258     val |= value << divider->shift;
0259     ti_clk_ll_ops->clk_writel(val, &divider->reg);
0260 
0261     ti_clk_latch(&divider->reg, divider->latch);
0262 
0263     return 0;
0264 }
0265 
0266 /**
0267  * clk_divider_save_context - Save the divider value
0268  * @hw: pointer  struct clk_hw
0269  *
0270  * Save the divider value
0271  */
0272 static int clk_divider_save_context(struct clk_hw *hw)
0273 {
0274     struct clk_omap_divider *divider = to_clk_omap_divider(hw);
0275     u32 val;
0276 
0277     val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
0278     divider->context = val & divider->mask;
0279 
0280     return 0;
0281 }
0282 
0283 /**
0284  * clk_divider_restore_context - restore the saved the divider value
0285  * @hw: pointer  struct clk_hw
0286  *
0287  * Restore the saved the divider value
0288  */
0289 static void clk_divider_restore_context(struct clk_hw *hw)
0290 {
0291     struct clk_omap_divider *divider = to_clk_omap_divider(hw);
0292     u32 val;
0293 
0294     val = ti_clk_ll_ops->clk_readl(&divider->reg);
0295     val &= ~(divider->mask << divider->shift);
0296     val |= divider->context << divider->shift;
0297     ti_clk_ll_ops->clk_writel(val, &divider->reg);
0298 }
0299 
0300 const struct clk_ops ti_clk_divider_ops = {
0301     .recalc_rate = ti_clk_divider_recalc_rate,
0302     .round_rate = ti_clk_divider_round_rate,
0303     .set_rate = ti_clk_divider_set_rate,
0304     .save_context = clk_divider_save_context,
0305     .restore_context = clk_divider_restore_context,
0306 };
0307 
0308 static struct clk *_register_divider(struct device_node *node,
0309                      u32 flags,
0310                      struct clk_omap_divider *div)
0311 {
0312     struct clk *clk;
0313     struct clk_init_data init;
0314     const char *parent_name;
0315     const char *name;
0316 
0317     parent_name = of_clk_get_parent_name(node, 0);
0318 
0319     name = ti_dt_clk_name(node);
0320     init.name = name;
0321     init.ops = &ti_clk_divider_ops;
0322     init.flags = flags;
0323     init.parent_names = (parent_name ? &parent_name : NULL);
0324     init.num_parents = (parent_name ? 1 : 0);
0325 
0326     div->hw.init = &init;
0327 
0328     /* register the clock */
0329     clk = ti_clk_register(NULL, &div->hw, name);
0330 
0331     if (IS_ERR(clk))
0332         kfree(div);
0333 
0334     return clk;
0335 }
0336 
0337 int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
0338                   u8 flags, struct clk_omap_divider *divider)
0339 {
0340     int valid_div = 0;
0341     int i;
0342     struct clk_div_table *tmp;
0343     u16 min_div = 0;
0344 
0345     if (!div_table) {
0346         divider->min = 1;
0347         divider->max = max_div;
0348         _setup_mask(divider);
0349         return 0;
0350     }
0351 
0352     i = 0;
0353 
0354     while (!num_dividers || i < num_dividers) {
0355         if (div_table[i] == -1)
0356             break;
0357         if (div_table[i])
0358             valid_div++;
0359         i++;
0360     }
0361 
0362     num_dividers = i;
0363 
0364     tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
0365     if (!tmp)
0366         return -ENOMEM;
0367 
0368     valid_div = 0;
0369 
0370     for (i = 0; i < num_dividers; i++)
0371         if (div_table[i] > 0) {
0372             tmp[valid_div].div = div_table[i];
0373             tmp[valid_div].val = i;
0374             valid_div++;
0375             if (div_table[i] > max_div)
0376                 max_div = div_table[i];
0377             if (!min_div || div_table[i] < min_div)
0378                 min_div = div_table[i];
0379         }
0380 
0381     divider->min = min_div;
0382     divider->max = max_div;
0383     divider->table = tmp;
0384     _setup_mask(divider);
0385 
0386     return 0;
0387 }
0388 
0389 static int __init ti_clk_get_div_table(struct device_node *node,
0390                        struct clk_omap_divider *div)
0391 {
0392     struct clk_div_table *table;
0393     const __be32 *divspec;
0394     u32 val;
0395     u32 num_div;
0396     u32 valid_div;
0397     int i;
0398 
0399     divspec = of_get_property(node, "ti,dividers", &num_div);
0400 
0401     if (!divspec)
0402         return 0;
0403 
0404     num_div /= 4;
0405 
0406     valid_div = 0;
0407 
0408     /* Determine required size for divider table */
0409     for (i = 0; i < num_div; i++) {
0410         of_property_read_u32_index(node, "ti,dividers", i, &val);
0411         if (val)
0412             valid_div++;
0413     }
0414 
0415     if (!valid_div) {
0416         pr_err("no valid dividers for %pOFn table\n", node);
0417         return -EINVAL;
0418     }
0419 
0420     table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
0421     if (!table)
0422         return -ENOMEM;
0423 
0424     valid_div = 0;
0425 
0426     for (i = 0; i < num_div; i++) {
0427         of_property_read_u32_index(node, "ti,dividers", i, &val);
0428         if (val) {
0429             table[valid_div].div = val;
0430             table[valid_div].val = i;
0431             valid_div++;
0432         }
0433     }
0434 
0435     div->table = table;
0436 
0437     return 0;
0438 }
0439 
0440 static int _populate_divider_min_max(struct device_node *node,
0441                      struct clk_omap_divider *divider)
0442 {
0443     u32 min_div = 0;
0444     u32 max_div = 0;
0445     u32 val;
0446     const struct clk_div_table *clkt;
0447 
0448     if (!divider->table) {
0449         /* Clk divider table not provided, determine min/max divs */
0450         if (of_property_read_u32(node, "ti,min-div", &min_div))
0451             min_div = 1;
0452 
0453         if (of_property_read_u32(node, "ti,max-div", &max_div)) {
0454             pr_err("no max-div for %pOFn!\n", node);
0455             return -EINVAL;
0456         }
0457     } else {
0458 
0459         for (clkt = divider->table; clkt->div; clkt++) {
0460             val = clkt->div;
0461             if (val > max_div)
0462                 max_div = val;
0463             if (!min_div || val < min_div)
0464                 min_div = val;
0465         }
0466     }
0467 
0468     divider->min = min_div;
0469     divider->max = max_div;
0470     _setup_mask(divider);
0471 
0472     return 0;
0473 }
0474 
0475 static int __init ti_clk_divider_populate(struct device_node *node,
0476                       struct clk_omap_divider *div,
0477                       u32 *flags)
0478 {
0479     u32 val;
0480     int ret;
0481 
0482     ret = ti_clk_get_reg_addr(node, 0, &div->reg);
0483     if (ret)
0484         return ret;
0485 
0486     if (!of_property_read_u32(node, "ti,bit-shift", &val))
0487         div->shift = val;
0488     else
0489         div->shift = 0;
0490 
0491     if (!of_property_read_u32(node, "ti,latch-bit", &val))
0492         div->latch = val;
0493     else
0494         div->latch = -EINVAL;
0495 
0496     *flags = 0;
0497     div->flags = 0;
0498 
0499     if (of_property_read_bool(node, "ti,index-starts-at-one"))
0500         div->flags |= CLK_DIVIDER_ONE_BASED;
0501 
0502     if (of_property_read_bool(node, "ti,index-power-of-two"))
0503         div->flags |= CLK_DIVIDER_POWER_OF_TWO;
0504 
0505     if (of_property_read_bool(node, "ti,set-rate-parent"))
0506         *flags |= CLK_SET_RATE_PARENT;
0507 
0508     ret = ti_clk_get_div_table(node, div);
0509     if (ret)
0510         return ret;
0511 
0512     return _populate_divider_min_max(node, div);
0513 }
0514 
0515 /**
0516  * of_ti_divider_clk_setup - Setup function for simple div rate clock
0517  * @node: device node for this clock
0518  *
0519  * Sets up a basic divider clock.
0520  */
0521 static void __init of_ti_divider_clk_setup(struct device_node *node)
0522 {
0523     struct clk *clk;
0524     u32 flags = 0;
0525     struct clk_omap_divider *div;
0526 
0527     div = kzalloc(sizeof(*div), GFP_KERNEL);
0528     if (!div)
0529         return;
0530 
0531     if (ti_clk_divider_populate(node, div, &flags))
0532         goto cleanup;
0533 
0534     clk = _register_divider(node, flags, div);
0535     if (!IS_ERR(clk)) {
0536         of_clk_add_provider(node, of_clk_src_simple_get, clk);
0537         of_ti_clk_autoidle_setup(node);
0538         return;
0539     }
0540 
0541 cleanup:
0542     kfree(div->table);
0543     kfree(div);
0544 }
0545 CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
0546 
0547 static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
0548 {
0549     struct clk_omap_divider *div;
0550     u32 tmp;
0551 
0552     div = kzalloc(sizeof(*div), GFP_KERNEL);
0553     if (!div)
0554         return;
0555 
0556     if (ti_clk_divider_populate(node, div, &tmp))
0557         goto cleanup;
0558 
0559     if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
0560         return;
0561 
0562 cleanup:
0563     kfree(div->table);
0564     kfree(div);
0565 }
0566 CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
0567            of_ti_composite_divider_clk_setup);