Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * r8a7778 Core CPG Clocks
0004  *
0005  * Copyright (C) 2014  Ulrich Hecht
0006  */
0007 
0008 #include <linux/clk-provider.h>
0009 #include <linux/clk/renesas.h>
0010 #include <linux/of_address.h>
0011 #include <linux/slab.h>
0012 #include <linux/soc/renesas/rcar-rst.h>
0013 
0014 /* PLL multipliers per bits 11, 12, and 18 of MODEMR */
0015 static const struct {
0016     unsigned long plla_mult;
0017     unsigned long pllb_mult;
0018 } r8a7778_rates[] __initconst = {
0019     [0] = { 21, 21 },
0020     [1] = { 24, 24 },
0021     [2] = { 28, 28 },
0022     [3] = { 32, 32 },
0023     [5] = { 24, 21 },
0024     [6] = { 28, 21 },
0025     [7] = { 32, 24 },
0026 };
0027 
0028 /* Clock dividers per bits 1 and 2 of MODEMR */
0029 static const struct {
0030     const char *name;
0031     unsigned int div[4];
0032 } r8a7778_divs[6] __initconst = {
0033     { "b",   { 12, 12, 16, 18 } },
0034     { "out", { 12, 12, 16, 18 } },
0035     { "p",   { 16, 12, 16, 12 } },
0036     { "s",   { 4,  3,  4,  3  } },
0037     { "s1",  { 8,  6,  8,  6  } },
0038 };
0039 
0040 static u32 cpg_mode_rates __initdata;
0041 static u32 cpg_mode_divs __initdata;
0042 
0043 static struct clk * __init
0044 r8a7778_cpg_register_clock(struct device_node *np, const char *name)
0045 {
0046     if (!strcmp(name, "plla")) {
0047         return clk_register_fixed_factor(NULL, "plla",
0048             of_clk_get_parent_name(np, 0), 0,
0049             r8a7778_rates[cpg_mode_rates].plla_mult, 1);
0050     } else if (!strcmp(name, "pllb")) {
0051         return clk_register_fixed_factor(NULL, "pllb",
0052             of_clk_get_parent_name(np, 0), 0,
0053             r8a7778_rates[cpg_mode_rates].pllb_mult, 1);
0054     } else {
0055         unsigned int i;
0056 
0057         for (i = 0; i < ARRAY_SIZE(r8a7778_divs); i++) {
0058             if (!strcmp(name, r8a7778_divs[i].name)) {
0059                 return clk_register_fixed_factor(NULL,
0060                     r8a7778_divs[i].name,
0061                     "plla", 0, 1,
0062                     r8a7778_divs[i].div[cpg_mode_divs]);
0063             }
0064         }
0065     }
0066 
0067     return ERR_PTR(-EINVAL);
0068 }
0069 
0070 
0071 static void __init r8a7778_cpg_clocks_init(struct device_node *np)
0072 {
0073     struct clk_onecell_data *data;
0074     struct clk **clks;
0075     unsigned int i;
0076     int num_clks;
0077     u32 mode;
0078 
0079     if (rcar_rst_read_mode_pins(&mode))
0080         return;
0081 
0082     BUG_ON(!(mode & BIT(19)));
0083 
0084     cpg_mode_rates = (!!(mode & BIT(18)) << 2) |
0085              (!!(mode & BIT(12)) << 1) |
0086              (!!(mode & BIT(11)));
0087     cpg_mode_divs = (!!(mode & BIT(2)) << 1) |
0088             (!!(mode & BIT(1)));
0089 
0090     num_clks = of_property_count_strings(np, "clock-output-names");
0091     if (num_clks < 0) {
0092         pr_err("%s: failed to count clocks\n", __func__);
0093         return;
0094     }
0095 
0096     data = kzalloc(sizeof(*data), GFP_KERNEL);
0097     clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
0098     if (data == NULL || clks == NULL) {
0099         /* We're leaking memory on purpose, there's no point in cleaning
0100          * up as the system won't boot anyway.
0101          */
0102         return;
0103     }
0104 
0105     data->clks = clks;
0106     data->clk_num = num_clks;
0107 
0108     for (i = 0; i < num_clks; ++i) {
0109         const char *name;
0110         struct clk *clk;
0111 
0112         of_property_read_string_index(np, "clock-output-names", i,
0113                           &name);
0114 
0115         clk = r8a7778_cpg_register_clock(np, name);
0116         if (IS_ERR(clk))
0117             pr_err("%s: failed to register %pOFn %s clock (%ld)\n",
0118                    __func__, np, name, PTR_ERR(clk));
0119         else
0120             data->clks[i] = clk;
0121     }
0122 
0123     of_clk_add_provider(np, of_clk_src_onecell_get, data);
0124 
0125     cpg_mstp_add_clk_domain(np);
0126 }
0127 
0128 CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
0129            r8a7778_cpg_clocks_init);