Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ARTPEC-6 clock initialization
0004  *
0005  * Copyright 2015-2016 Axis Communications AB.
0006  */
0007 
0008 #include <linux/clk-provider.h>
0009 #include <linux/device.h>
0010 #include <linux/io.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/slab.h>
0015 #include <dt-bindings/clock/axis,artpec6-clkctrl.h>
0016 
0017 #define NUM_I2S_CLOCKS 2
0018 
0019 struct artpec6_clkctrl_drvdata {
0020     struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS];
0021     void __iomem *syscon_base;
0022     struct clk_onecell_data clk_data;
0023     spinlock_t i2scfg_lock;
0024 };
0025 
0026 static struct artpec6_clkctrl_drvdata *clkdata;
0027 
0028 static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = {
0029     "i2s0",
0030     "i2s1",
0031 };
0032 
0033 static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = {
0034     ARTPEC6_CLK_I2S0_CLK,
0035     ARTPEC6_CLK_I2S1_CLK,
0036 };
0037 
0038 static void of_artpec6_clkctrl_setup(struct device_node *np)
0039 {
0040     int i;
0041     const char *sys_refclk_name;
0042     u32 pll_mode, pll_m, pll_n;
0043     struct clk **clks;
0044 
0045     /* Mandatory parent clock. */
0046     i = of_property_match_string(np, "clock-names", "sys_refclk");
0047     if (i < 0)
0048         return;
0049 
0050     sys_refclk_name = of_clk_get_parent_name(np, i);
0051 
0052     clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL);
0053     if (!clkdata)
0054         return;
0055 
0056     clks = clkdata->clk_table;
0057 
0058     for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i)
0059         clks[i] = ERR_PTR(-EPROBE_DEFER);
0060 
0061     clkdata->syscon_base = of_iomap(np, 0);
0062     BUG_ON(clkdata->syscon_base == NULL);
0063 
0064     /* Read PLL1 factors configured by boot strap pins. */
0065     pll_mode = (readl(clkdata->syscon_base) >> 6) & 3;
0066     switch (pll_mode) {
0067     case 0:     /* DDR3-2133 mode */
0068         pll_m = 4;
0069         pll_n = 85;
0070         break;
0071     case 1:     /* DDR3-1866 mode */
0072         pll_m = 6;
0073         pll_n = 112;
0074         break;
0075     case 2:     /* DDR3-1600 mode */
0076         pll_m = 4;
0077         pll_n = 64;
0078         break;
0079     case 3:     /* DDR3-1333 mode */
0080         pll_m = 8;
0081         pll_n = 106;
0082         break;
0083     }
0084 
0085     clks[ARTPEC6_CLK_CPU] =
0086         clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n,
0087                       pll_m);
0088     clks[ARTPEC6_CLK_CPU_PERIPH] =
0089         clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2);
0090 
0091     /* EPROBE_DEFER on the apb_clock is not handled in amba devices. */
0092     clks[ARTPEC6_CLK_UART_PCLK] =
0093         clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8);
0094     clks[ARTPEC6_CLK_UART_REFCLK] =
0095         clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0,
0096                     50000000);
0097 
0098     clks[ARTPEC6_CLK_SPI_PCLK] =
0099         clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8);
0100     clks[ARTPEC6_CLK_SPI_SSPCLK] =
0101         clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0,
0102                     50000000);
0103 
0104     clks[ARTPEC6_CLK_DBG_PCLK] =
0105         clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8);
0106 
0107     clkdata->clk_data.clks = clkdata->clk_table;
0108     clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS;
0109 
0110     of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data);
0111 }
0112 
0113 CLK_OF_DECLARE_DRIVER(artpec6_clkctrl, "axis,artpec6-clkctrl",
0114               of_artpec6_clkctrl_setup);
0115 
0116 static int artpec6_clkctrl_probe(struct platform_device *pdev)
0117 {
0118     int propidx;
0119     struct device_node *np = pdev->dev.of_node;
0120     struct device *dev = &pdev->dev;
0121     struct clk **clks = clkdata->clk_table;
0122     const char *sys_refclk_name;
0123     const char *i2s_refclk_name = NULL;
0124     const char *frac_clk_name[2] = { NULL, NULL };
0125     const char *i2s_mux_parents[2];
0126     u32 muxreg;
0127     int i;
0128     int err = 0;
0129 
0130     /* Mandatory parent clock. */
0131     propidx = of_property_match_string(np, "clock-names", "sys_refclk");
0132     if (propidx < 0)
0133         return -EINVAL;
0134 
0135     sys_refclk_name = of_clk_get_parent_name(np, propidx);
0136 
0137     /* Find clock names of optional parent clocks. */
0138     propidx = of_property_match_string(np, "clock-names", "i2s_refclk");
0139     if (propidx >= 0)
0140         i2s_refclk_name = of_clk_get_parent_name(np, propidx);
0141 
0142     propidx = of_property_match_string(np, "clock-names", "frac_clk0");
0143     if (propidx >= 0)
0144         frac_clk_name[0] = of_clk_get_parent_name(np, propidx);
0145     propidx = of_property_match_string(np, "clock-names", "frac_clk1");
0146     if (propidx >= 0)
0147         frac_clk_name[1] = of_clk_get_parent_name(np, propidx);
0148 
0149     spin_lock_init(&clkdata->i2scfg_lock);
0150 
0151     clks[ARTPEC6_CLK_NAND_CLKA] =
0152         clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8);
0153     clks[ARTPEC6_CLK_NAND_CLKB] =
0154         clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0,
0155                     100000000);
0156     clks[ARTPEC6_CLK_ETH_ACLK] =
0157         clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4);
0158     clks[ARTPEC6_CLK_DMA_ACLK] =
0159         clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4);
0160     clks[ARTPEC6_CLK_PTP_REF] =
0161         clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0,
0162                     100000000);
0163     clks[ARTPEC6_CLK_SD_PCLK] =
0164         clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0,
0165                     100000000);
0166     clks[ARTPEC6_CLK_SD_IMCLK] =
0167         clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0,
0168                     100000000);
0169     clks[ARTPEC6_CLK_I2S_HST] =
0170         clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8);
0171 
0172     for (i = 0; i < NUM_I2S_CLOCKS; ++i) {
0173         if (i2s_refclk_name && frac_clk_name[i]) {
0174             i2s_mux_parents[0] = frac_clk_name[i];
0175             i2s_mux_parents[1] = i2s_refclk_name;
0176 
0177             clks[i2s_clk_indexes[i]] =
0178                 clk_register_mux(dev, i2s_clk_names[i],
0179                          i2s_mux_parents, 2,
0180                          CLK_SET_RATE_NO_REPARENT |
0181                          CLK_SET_RATE_PARENT,
0182                          clkdata->syscon_base + 0x14, i, 1,
0183                          0, &clkdata->i2scfg_lock);
0184         } else if (frac_clk_name[i]) {
0185             /* Lock the mux for internal clock reference. */
0186             muxreg = readl(clkdata->syscon_base + 0x14);
0187             muxreg &= ~BIT(i);
0188             writel(muxreg, clkdata->syscon_base + 0x14);
0189             clks[i2s_clk_indexes[i]] =
0190                 clk_register_fixed_factor(dev, i2s_clk_names[i],
0191                               frac_clk_name[i], 0, 1,
0192                               1);
0193         } else if (i2s_refclk_name) {
0194             /* Lock the mux for external clock reference. */
0195             muxreg = readl(clkdata->syscon_base + 0x14);
0196             muxreg |= BIT(i);
0197             writel(muxreg, clkdata->syscon_base + 0x14);
0198             clks[i2s_clk_indexes[i]] =
0199                 clk_register_fixed_factor(dev, i2s_clk_names[i],
0200                               i2s_refclk_name, 0, 1, 1);
0201         }
0202     }
0203 
0204     clks[ARTPEC6_CLK_I2C] =
0205         clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000);
0206 
0207     clks[ARTPEC6_CLK_SYS_TIMER] =
0208         clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0,
0209                     100000000);
0210     clks[ARTPEC6_CLK_FRACDIV_IN] =
0211         clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0,
0212                     600000000);
0213 
0214     for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) {
0215         if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) {
0216             dev_err(dev,
0217                 "Failed to register clock at index %d err=%ld\n",
0218                 i, PTR_ERR(clks[i]));
0219             err = PTR_ERR(clks[i]);
0220         }
0221     }
0222 
0223     return err;
0224 }
0225 
0226 static const struct of_device_id artpec_clkctrl_of_match[] = {
0227     { .compatible = "axis,artpec6-clkctrl" },
0228     {}
0229 };
0230 
0231 static struct platform_driver artpec6_clkctrl_driver = {
0232     .probe = artpec6_clkctrl_probe,
0233     .driver = {
0234            .name = "artpec6_clkctrl",
0235            .of_match_table = artpec_clkctrl_of_match,
0236     },
0237 };
0238 
0239 builtin_platform_driver(artpec6_clkctrl_driver);