1 /* 2 * ARTPEC-6 clock initialization 3 * 4 * Copyright 2015-2016 Axis Comunications AB. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/clk-provider.h> 12 #include <linux/device.h> 13 #include <linux/io.h> 14 #include <linux/of.h> 15 #include <linux/of_address.h> 16 #include <linux/platform_device.h> 17 #include <linux/slab.h> 18 #include <dt-bindings/clock/axis,artpec6-clkctrl.h> 19 20 #define NUM_I2S_CLOCKS 2 21 22 struct artpec6_clkctrl_drvdata { 23 struct clk *clk_table[ARTPEC6_CLK_NUMCLOCKS]; 24 void __iomem *syscon_base; 25 struct clk_onecell_data clk_data; 26 spinlock_t i2scfg_lock; 27 }; 28 29 static struct artpec6_clkctrl_drvdata *clkdata; 30 31 static const char *const i2s_clk_names[NUM_I2S_CLOCKS] = { 32 "i2s0", 33 "i2s1", 34 }; 35 36 static const int i2s_clk_indexes[NUM_I2S_CLOCKS] = { 37 ARTPEC6_CLK_I2S0_CLK, 38 ARTPEC6_CLK_I2S1_CLK, 39 }; 40 41 static void of_artpec6_clkctrl_setup(struct device_node *np) 42 { 43 int i; 44 const char *sys_refclk_name; 45 u32 pll_mode, pll_m, pll_n; 46 struct clk **clks; 47 48 /* Mandatory parent clock. */ 49 i = of_property_match_string(np, "clock-names", "sys_refclk"); 50 if (i < 0) 51 return; 52 53 sys_refclk_name = of_clk_get_parent_name(np, i); 54 55 clkdata = kzalloc(sizeof(*clkdata), GFP_KERNEL); 56 if (!clkdata) 57 return; 58 59 clks = clkdata->clk_table; 60 61 for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) 62 clks[i] = ERR_PTR(-EPROBE_DEFER); 63 64 clkdata->syscon_base = of_iomap(np, 0); 65 BUG_ON(clkdata->syscon_base == NULL); 66 67 /* Read PLL1 factors configured by boot strap pins. */ 68 pll_mode = (readl(clkdata->syscon_base) >> 6) & 3; 69 switch (pll_mode) { 70 case 0: /* DDR3-2133 mode */ 71 pll_m = 4; 72 pll_n = 85; 73 break; 74 case 1: /* DDR3-1866 mode */ 75 pll_m = 6; 76 pll_n = 112; 77 break; 78 case 2: /* DDR3-1600 mode */ 79 pll_m = 4; 80 pll_n = 64; 81 break; 82 case 3: /* DDR3-1333 mode */ 83 pll_m = 8; 84 pll_n = 106; 85 break; 86 } 87 88 clks[ARTPEC6_CLK_CPU] = 89 clk_register_fixed_factor(NULL, "cpu", sys_refclk_name, 0, pll_n, 90 pll_m); 91 clks[ARTPEC6_CLK_CPU_PERIPH] = 92 clk_register_fixed_factor(NULL, "cpu_periph", "cpu", 0, 1, 2); 93 94 /* EPROBE_DEFER on the apb_clock is not handled in amba devices. */ 95 clks[ARTPEC6_CLK_UART_PCLK] = 96 clk_register_fixed_factor(NULL, "uart_pclk", "cpu", 0, 1, 8); 97 clks[ARTPEC6_CLK_UART_REFCLK] = 98 clk_register_fixed_rate(NULL, "uart_ref", sys_refclk_name, 0, 99 50000000); 100 101 clks[ARTPEC6_CLK_SPI_PCLK] = 102 clk_register_fixed_factor(NULL, "spi_pclk", "cpu", 0, 1, 8); 103 clks[ARTPEC6_CLK_SPI_SSPCLK] = 104 clk_register_fixed_rate(NULL, "spi_sspclk", sys_refclk_name, 0, 105 50000000); 106 107 clks[ARTPEC6_CLK_DBG_PCLK] = 108 clk_register_fixed_factor(NULL, "dbg_pclk", "cpu", 0, 1, 8); 109 110 clkdata->clk_data.clks = clkdata->clk_table; 111 clkdata->clk_data.clk_num = ARTPEC6_CLK_NUMCLOCKS; 112 113 of_clk_add_provider(np, of_clk_src_onecell_get, &clkdata->clk_data); 114 } 115 116 CLK_OF_DECLARE(artpec6_clkctrl, "axis,artpec6-clkctrl", 117 of_artpec6_clkctrl_setup); 118 119 static int artpec6_clkctrl_probe(struct platform_device *pdev) 120 { 121 int propidx; 122 struct device_node *np = pdev->dev.of_node; 123 struct device *dev = &pdev->dev; 124 struct clk **clks = clkdata->clk_table; 125 const char *sys_refclk_name; 126 const char *i2s_refclk_name = NULL; 127 const char *frac_clk_name[2] = { NULL, NULL }; 128 const char *i2s_mux_parents[2]; 129 u32 muxreg; 130 int i; 131 int err = 0; 132 133 /* Mandatory parent clock. */ 134 propidx = of_property_match_string(np, "clock-names", "sys_refclk"); 135 if (propidx < 0) 136 return -EINVAL; 137 138 sys_refclk_name = of_clk_get_parent_name(np, propidx); 139 140 /* Find clock names of optional parent clocks. */ 141 propidx = of_property_match_string(np, "clock-names", "i2s_refclk"); 142 if (propidx >= 0) 143 i2s_refclk_name = of_clk_get_parent_name(np, propidx); 144 145 propidx = of_property_match_string(np, "clock-names", "frac_clk0"); 146 if (propidx >= 0) 147 frac_clk_name[0] = of_clk_get_parent_name(np, propidx); 148 propidx = of_property_match_string(np, "clock-names", "frac_clk1"); 149 if (propidx >= 0) 150 frac_clk_name[1] = of_clk_get_parent_name(np, propidx); 151 152 spin_lock_init(&clkdata->i2scfg_lock); 153 154 clks[ARTPEC6_CLK_NAND_CLKA] = 155 clk_register_fixed_factor(dev, "nand_clka", "cpu", 0, 1, 8); 156 clks[ARTPEC6_CLK_NAND_CLKB] = 157 clk_register_fixed_rate(dev, "nand_clkb", sys_refclk_name, 0, 158 100000000); 159 clks[ARTPEC6_CLK_ETH_ACLK] = 160 clk_register_fixed_factor(dev, "eth_aclk", "cpu", 0, 1, 4); 161 clks[ARTPEC6_CLK_DMA_ACLK] = 162 clk_register_fixed_factor(dev, "dma_aclk", "cpu", 0, 1, 4); 163 clks[ARTPEC6_CLK_PTP_REF] = 164 clk_register_fixed_rate(dev, "ptp_ref", sys_refclk_name, 0, 165 100000000); 166 clks[ARTPEC6_CLK_SD_PCLK] = 167 clk_register_fixed_rate(dev, "sd_pclk", sys_refclk_name, 0, 168 100000000); 169 clks[ARTPEC6_CLK_SD_IMCLK] = 170 clk_register_fixed_rate(dev, "sd_imclk", sys_refclk_name, 0, 171 100000000); 172 clks[ARTPEC6_CLK_I2S_HST] = 173 clk_register_fixed_factor(dev, "i2s_hst", "cpu", 0, 1, 8); 174 175 for (i = 0; i < NUM_I2S_CLOCKS; ++i) { 176 if (i2s_refclk_name && frac_clk_name[i]) { 177 i2s_mux_parents[0] = frac_clk_name[i]; 178 i2s_mux_parents[1] = i2s_refclk_name; 179 180 clks[i2s_clk_indexes[i]] = 181 clk_register_mux(dev, i2s_clk_names[i], 182 i2s_mux_parents, 2, 183 CLK_SET_RATE_NO_REPARENT | 184 CLK_SET_RATE_PARENT, 185 clkdata->syscon_base + 0x14, i, 1, 186 0, &clkdata->i2scfg_lock); 187 } else if (frac_clk_name[i]) { 188 /* Lock the mux for internal clock reference. */ 189 muxreg = readl(clkdata->syscon_base + 0x14); 190 muxreg &= ~BIT(i); 191 writel(muxreg, clkdata->syscon_base + 0x14); 192 clks[i2s_clk_indexes[i]] = 193 clk_register_fixed_factor(dev, i2s_clk_names[i], 194 frac_clk_name[i], 0, 1, 195 1); 196 } else if (i2s_refclk_name) { 197 /* Lock the mux for external clock reference. */ 198 muxreg = readl(clkdata->syscon_base + 0x14); 199 muxreg |= BIT(i); 200 writel(muxreg, clkdata->syscon_base + 0x14); 201 clks[i2s_clk_indexes[i]] = 202 clk_register_fixed_factor(dev, i2s_clk_names[i], 203 i2s_refclk_name, 0, 1, 1); 204 } 205 } 206 207 clks[ARTPEC6_CLK_I2C] = 208 clk_register_fixed_rate(dev, "i2c", sys_refclk_name, 0, 100000000); 209 210 clks[ARTPEC6_CLK_SYS_TIMER] = 211 clk_register_fixed_rate(dev, "timer", sys_refclk_name, 0, 212 100000000); 213 clks[ARTPEC6_CLK_FRACDIV_IN] = 214 clk_register_fixed_rate(dev, "fracdiv_in", sys_refclk_name, 0, 215 600000000); 216 217 for (i = 0; i < ARTPEC6_CLK_NUMCLOCKS; ++i) { 218 if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER) { 219 dev_err(dev, 220 "Failed to register clock at index %d err=%ld\n", 221 i, PTR_ERR(clks[i])); 222 err = PTR_ERR(clks[i]); 223 } 224 } 225 226 return err; 227 } 228 229 static const struct of_device_id artpec_clkctrl_of_match[] = { 230 { .compatible = "axis,artpec6-clkctrl" }, 231 {} 232 }; 233 234 static struct platform_driver artpec6_clkctrl_driver = { 235 .probe = artpec6_clkctrl_probe, 236 .driver = { 237 .name = "artpec6_clkctrl", 238 .of_match_table = artpec_clkctrl_of_match, 239 }, 240 }; 241 242 builtin_platform_driver(artpec6_clkctrl_driver); 243