Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2015 Altera Corporation. All rights reserved
0004  */
0005 #include <linux/slab.h>
0006 #include <linux/clk-provider.h>
0007 #include <linux/io.h>
0008 #include <linux/mfd/syscon.h>
0009 #include <linux/of.h>
0010 #include <linux/regmap.h>
0011 
0012 #include "clk.h"
0013 
0014 #define streq(a, b) (strcmp((a), (b)) == 0)
0015 
0016 #define to_socfpga_gate_clk(p) container_of(p, struct socfpga_gate_clk, hw.hw)
0017 
0018 /* SDMMC Group for System Manager defines */
0019 #define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x28
0020 
0021 static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
0022     unsigned long parent_rate)
0023 {
0024     struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
0025     u32 div = 1, val;
0026 
0027     if (socfpgaclk->fixed_div)
0028         div = socfpgaclk->fixed_div;
0029     else if (socfpgaclk->div_reg) {
0030         val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift;
0031         val &= GENMASK(socfpgaclk->width - 1, 0);
0032         div = (1 << val);
0033     }
0034 
0035     return parent_rate / div;
0036 }
0037 
0038 static int socfpga_clk_prepare(struct clk_hw *hwclk)
0039 {
0040     struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
0041     int i;
0042     u32 hs_timing;
0043     u32 clk_phase[2];
0044 
0045     if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
0046         for (i = 0; i < ARRAY_SIZE(clk_phase); i++) {
0047             switch (socfpgaclk->clk_phase[i]) {
0048             case 0:
0049                 clk_phase[i] = 0;
0050                 break;
0051             case 45:
0052                 clk_phase[i] = 1;
0053                 break;
0054             case 90:
0055                 clk_phase[i] = 2;
0056                 break;
0057             case 135:
0058                 clk_phase[i] = 3;
0059                 break;
0060             case 180:
0061                 clk_phase[i] = 4;
0062                 break;
0063             case 225:
0064                 clk_phase[i] = 5;
0065                 break;
0066             case 270:
0067                 clk_phase[i] = 6;
0068                 break;
0069             case 315:
0070                 clk_phase[i] = 7;
0071                 break;
0072             default:
0073                 clk_phase[i] = 0;
0074                 break;
0075             }
0076         }
0077 
0078         hs_timing = SYSMGR_SDMMC_CTRL_SET_AS10(clk_phase[0], clk_phase[1]);
0079         if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
0080             regmap_write(socfpgaclk->sys_mgr_base_addr,
0081                      SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);
0082         else
0083             pr_err("%s: cannot set clk_phase because sys_mgr_base_addr is not available!\n",
0084                     __func__);
0085     }
0086     return 0;
0087 }
0088 
0089 static struct clk_ops gateclk_ops = {
0090     .prepare = socfpga_clk_prepare,
0091     .recalc_rate = socfpga_gate_clk_recalc_rate,
0092 };
0093 
0094 static void __init __socfpga_gate_init(struct device_node *node,
0095     const struct clk_ops *ops)
0096 {
0097     u32 clk_gate[2];
0098     u32 div_reg[3];
0099     u32 clk_phase[2];
0100     u32 fixed_div;
0101     struct clk_hw *hw_clk;
0102     struct socfpga_gate_clk *socfpga_clk;
0103     const char *clk_name = node->name;
0104     const char *parent_name[SOCFPGA_MAX_PARENTS];
0105     struct clk_init_data init;
0106     int rc;
0107 
0108     socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
0109     if (WARN_ON(!socfpga_clk))
0110         return;
0111 
0112     rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
0113     if (rc)
0114         clk_gate[0] = 0;
0115 
0116     if (clk_gate[0]) {
0117         socfpga_clk->hw.reg = clk_mgr_a10_base_addr + clk_gate[0];
0118         socfpga_clk->hw.bit_idx = clk_gate[1];
0119 
0120         gateclk_ops.enable = clk_gate_ops.enable;
0121         gateclk_ops.disable = clk_gate_ops.disable;
0122     }
0123 
0124     rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
0125     if (rc)
0126         socfpga_clk->fixed_div = 0;
0127     else
0128         socfpga_clk->fixed_div = fixed_div;
0129 
0130     rc = of_property_read_u32_array(node, "div-reg", div_reg, 3);
0131     if (!rc) {
0132         socfpga_clk->div_reg = clk_mgr_a10_base_addr + div_reg[0];
0133         socfpga_clk->shift = div_reg[1];
0134         socfpga_clk->width = div_reg[2];
0135     } else {
0136         socfpga_clk->div_reg = NULL;
0137     }
0138 
0139     rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
0140     if (!rc) {
0141         socfpga_clk->clk_phase[0] = clk_phase[0];
0142         socfpga_clk->clk_phase[1] = clk_phase[1];
0143 
0144         socfpga_clk->sys_mgr_base_addr =
0145             syscon_regmap_lookup_by_compatible("altr,sys-mgr");
0146         if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
0147             pr_err("%s: failed to find altr,sys-mgr regmap!\n",
0148                     __func__);
0149             kfree(socfpga_clk);
0150             return;
0151         }
0152     }
0153 
0154     of_property_read_string(node, "clock-output-names", &clk_name);
0155 
0156     init.name = clk_name;
0157     init.ops = ops;
0158     init.flags = 0;
0159 
0160     init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
0161     init.parent_names = parent_name;
0162     socfpga_clk->hw.hw.init = &init;
0163     hw_clk = &socfpga_clk->hw.hw;
0164 
0165     if (clk_hw_register(NULL, hw_clk)) {
0166         kfree(socfpga_clk);
0167         return;
0168     }
0169     rc = of_clk_add_provider(node, of_clk_src_simple_get, hw_clk);
0170     if (WARN_ON(rc))
0171         return;
0172 }
0173 
0174 void __init socfpga_a10_gate_init(struct device_node *node)
0175 {
0176     __socfpga_gate_init(node, &gateclk_ops);
0177 }