615 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Zynq clock controller4 *5 * Copyright (C) 2012 - 2013 Xilinx6 *7 * Sören Brinkmann <soren.brinkmann@xilinx.com>8 */9 10#include <linux/clk/zynq.h>11#include <linux/clk.h>12#include <linux/clk-provider.h>13#include <linux/of.h>14#include <linux/of_address.h>15#include <linux/slab.h>16#include <linux/string.h>17#include <linux/io.h>18 19static void __iomem *zynq_clkc_base;20 21#define SLCR_ARMPLL_CTRL (zynq_clkc_base + 0x00)22#define SLCR_DDRPLL_CTRL (zynq_clkc_base + 0x04)23#define SLCR_IOPLL_CTRL (zynq_clkc_base + 0x08)24#define SLCR_PLL_STATUS (zynq_clkc_base + 0x0c)25#define SLCR_ARM_CLK_CTRL (zynq_clkc_base + 0x20)26#define SLCR_DDR_CLK_CTRL (zynq_clkc_base + 0x24)27#define SLCR_DCI_CLK_CTRL (zynq_clkc_base + 0x28)28#define SLCR_APER_CLK_CTRL (zynq_clkc_base + 0x2c)29#define SLCR_GEM0_CLK_CTRL (zynq_clkc_base + 0x40)30#define SLCR_GEM1_CLK_CTRL (zynq_clkc_base + 0x44)31#define SLCR_SMC_CLK_CTRL (zynq_clkc_base + 0x48)32#define SLCR_LQSPI_CLK_CTRL (zynq_clkc_base + 0x4c)33#define SLCR_SDIO_CLK_CTRL (zynq_clkc_base + 0x50)34#define SLCR_UART_CLK_CTRL (zynq_clkc_base + 0x54)35#define SLCR_SPI_CLK_CTRL (zynq_clkc_base + 0x58)36#define SLCR_CAN_CLK_CTRL (zynq_clkc_base + 0x5c)37#define SLCR_CAN_MIOCLK_CTRL (zynq_clkc_base + 0x60)38#define SLCR_DBG_CLK_CTRL (zynq_clkc_base + 0x64)39#define SLCR_PCAP_CLK_CTRL (zynq_clkc_base + 0x68)40#define SLCR_FPGA0_CLK_CTRL (zynq_clkc_base + 0x70)41#define SLCR_621_TRUE (zynq_clkc_base + 0xc4)42#define SLCR_SWDT_CLK_SEL (zynq_clkc_base + 0x204)43 44#define NUM_MIO_PINS 5445#define CLK_NAME_LEN 1646 47#define DBG_CLK_CTRL_CLKACT_TRC BIT(0)48#define DBG_CLK_CTRL_CPU_1XCLKACT BIT(1)49 50enum zynq_clk {51 armpll, ddrpll, iopll,52 cpu_6or4x, cpu_3or2x, cpu_2x, cpu_1x,53 ddr2x, ddr3x, dci,54 lqspi, smc, pcap, gem0, gem1, fclk0, fclk1, fclk2, fclk3, can0, can1,55 sdio0, sdio1, uart0, uart1, spi0, spi1, dma,56 usb0_aper, usb1_aper, gem0_aper, gem1_aper,57 sdio0_aper, sdio1_aper, spi0_aper, spi1_aper, can0_aper, can1_aper,58 i2c0_aper, i2c1_aper, uart0_aper, uart1_aper, gpio_aper, lqspi_aper,59 smc_aper, swdt, dbg_trc, dbg_apb, clk_max};60 61static struct clk *ps_clk;62static struct clk *clks[clk_max];63static struct clk_onecell_data clk_data;64 65static DEFINE_SPINLOCK(armpll_lock);66static DEFINE_SPINLOCK(ddrpll_lock);67static DEFINE_SPINLOCK(iopll_lock);68static DEFINE_SPINLOCK(armclk_lock);69static DEFINE_SPINLOCK(swdtclk_lock);70static DEFINE_SPINLOCK(ddrclk_lock);71static DEFINE_SPINLOCK(dciclk_lock);72static DEFINE_SPINLOCK(gem0clk_lock);73static DEFINE_SPINLOCK(gem1clk_lock);74static DEFINE_SPINLOCK(canclk_lock);75static DEFINE_SPINLOCK(canmioclk_lock);76static DEFINE_SPINLOCK(dbgclk_lock);77static DEFINE_SPINLOCK(aperclk_lock);78 79static const char *const armpll_parents[] __initconst = {"armpll_int",80 "ps_clk"};81static const char *const ddrpll_parents[] __initconst = {"ddrpll_int",82 "ps_clk"};83static const char *const iopll_parents[] __initconst = {"iopll_int",84 "ps_clk"};85static const char *gem0_mux_parents[] __initdata = {"gem0_div1", "dummy_name"};86static const char *gem1_mux_parents[] __initdata = {"gem1_div1", "dummy_name"};87static const char *const can0_mio_mux2_parents[] __initconst = {"can0_gate",88 "can0_mio_mux"};89static const char *const can1_mio_mux2_parents[] __initconst = {"can1_gate",90 "can1_mio_mux"};91static const char *dbg_emio_mux_parents[] __initdata = {"dbg_div",92 "dummy_name"};93 94static const char *const dbgtrc_emio_input_names[] __initconst = {95 "trace_emio_clk"};96static const char *const gem0_emio_input_names[] __initconst = {97 "gem0_emio_clk"};98static const char *const gem1_emio_input_names[] __initconst = {99 "gem1_emio_clk"};100static const char *const swdt_ext_clk_input_names[] __initconst = {101 "swdt_ext_clk"};102 103static void __init zynq_clk_register_fclk(enum zynq_clk fclk,104 const char *clk_name, void __iomem *fclk_ctrl_reg,105 const char **parents, int enable)106{107 u32 enable_reg;108 char *mux_name;109 char *div0_name;110 char *div1_name;111 spinlock_t *fclk_lock;112 spinlock_t *fclk_gate_lock;113 void __iomem *fclk_gate_reg = fclk_ctrl_reg + 8;114 115 fclk_lock = kmalloc(sizeof(*fclk_lock), GFP_KERNEL);116 if (!fclk_lock)117 goto err;118 fclk_gate_lock = kmalloc(sizeof(*fclk_gate_lock), GFP_KERNEL);119 if (!fclk_gate_lock)120 goto err_fclk_gate_lock;121 spin_lock_init(fclk_lock);122 spin_lock_init(fclk_gate_lock);123 124 mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name);125 if (!mux_name)126 goto err_mux_name;127 div0_name = kasprintf(GFP_KERNEL, "%s_div0", clk_name);128 if (!div0_name)129 goto err_div0_name;130 div1_name = kasprintf(GFP_KERNEL, "%s_div1", clk_name);131 if (!div1_name)132 goto err_div1_name;133 134 clk_register_mux(NULL, mux_name, parents, 4,135 CLK_SET_RATE_NO_REPARENT, fclk_ctrl_reg, 4, 2, 0,136 fclk_lock);137 138 clk_register_divider(NULL, div0_name, mux_name,139 0, fclk_ctrl_reg, 8, 6, CLK_DIVIDER_ONE_BASED |140 CLK_DIVIDER_ALLOW_ZERO, fclk_lock);141 142 clk_register_divider(NULL, div1_name, div0_name,143 CLK_SET_RATE_PARENT, fclk_ctrl_reg, 20, 6,144 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,145 fclk_lock);146 147 clks[fclk] = clk_register_gate(NULL, clk_name,148 div1_name, CLK_SET_RATE_PARENT, fclk_gate_reg,149 0, CLK_GATE_SET_TO_DISABLE, fclk_gate_lock);150 enable_reg = readl(fclk_gate_reg) & 1;151 if (enable && !enable_reg) {152 if (clk_prepare_enable(clks[fclk]))153 pr_warn("%s: FCLK%u enable failed\n", __func__,154 fclk - fclk0);155 }156 kfree(mux_name);157 kfree(div0_name);158 kfree(div1_name);159 160 return;161 162err_div1_name:163 kfree(div0_name);164err_div0_name:165 kfree(mux_name);166err_mux_name:167 kfree(fclk_gate_lock);168err_fclk_gate_lock:169 kfree(fclk_lock);170err:171 clks[fclk] = ERR_PTR(-ENOMEM);172}173 174static void __init zynq_clk_register_periph_clk(enum zynq_clk clk0,175 enum zynq_clk clk1, const char *clk_name0,176 const char *clk_name1, void __iomem *clk_ctrl,177 const char **parents, unsigned int two_gates)178{179 char *mux_name;180 char *div_name;181 spinlock_t *lock;182 183 lock = kmalloc(sizeof(*lock), GFP_KERNEL);184 if (!lock)185 goto err;186 spin_lock_init(lock);187 188 mux_name = kasprintf(GFP_KERNEL, "%s_mux", clk_name0);189 div_name = kasprintf(GFP_KERNEL, "%s_div", clk_name0);190 191 clk_register_mux(NULL, mux_name, parents, 4,192 CLK_SET_RATE_NO_REPARENT, clk_ctrl, 4, 2, 0, lock);193 194 clk_register_divider(NULL, div_name, mux_name, 0, clk_ctrl, 8, 6,195 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, lock);196 197 clks[clk0] = clk_register_gate(NULL, clk_name0, div_name,198 CLK_SET_RATE_PARENT, clk_ctrl, 0, 0, lock);199 if (two_gates)200 clks[clk1] = clk_register_gate(NULL, clk_name1, div_name,201 CLK_SET_RATE_PARENT, clk_ctrl, 1, 0, lock);202 203 kfree(mux_name);204 kfree(div_name);205 206 return;207 208err:209 clks[clk0] = ERR_PTR(-ENOMEM);210 if (two_gates)211 clks[clk1] = ERR_PTR(-ENOMEM);212}213 214static void __init zynq_clk_setup(struct device_node *np)215{216 int i;217 u32 tmp;218 int ret;219 char clk_name[CLK_NAME_LEN];220 unsigned int fclk_enable = 0;221 const char *clk_output_name[clk_max];222 const char *cpu_parents[4];223 const char *periph_parents[4];224 const char *swdt_ext_clk_mux_parents[2];225 const char *can_mio_mux_parents[NUM_MIO_PINS];226 const char *dummy_nm = "dummy_name";227 228 pr_info("Zynq clock init\n");229 230 /* get clock output names from DT */231 for (i = 0; i < clk_max; i++) {232 if (of_property_read_string_index(np, "clock-output-names",233 i, &clk_output_name[i])) {234 pr_err("%s: clock output name not in DT\n", __func__);235 BUG();236 }237 }238 cpu_parents[0] = clk_output_name[armpll];239 cpu_parents[1] = clk_output_name[armpll];240 cpu_parents[2] = clk_output_name[ddrpll];241 cpu_parents[3] = clk_output_name[iopll];242 periph_parents[0] = clk_output_name[iopll];243 periph_parents[1] = clk_output_name[iopll];244 periph_parents[2] = clk_output_name[armpll];245 periph_parents[3] = clk_output_name[ddrpll];246 247 of_property_read_u32(np, "fclk-enable", &fclk_enable);248 249 /* ps_clk */250 ret = of_property_read_u32(np, "ps-clk-frequency", &tmp);251 if (ret) {252 pr_warn("ps_clk frequency not specified, using 33 MHz.\n");253 tmp = 33333333;254 }255 ps_clk = clk_register_fixed_rate(NULL, "ps_clk", NULL, 0, tmp);256 257 /* PLLs */258 clk_register_zynq_pll("armpll_int", "ps_clk", SLCR_ARMPLL_CTRL,259 SLCR_PLL_STATUS, 0, &armpll_lock);260 clks[armpll] = clk_register_mux(NULL, clk_output_name[armpll],261 armpll_parents, 2, CLK_SET_RATE_NO_REPARENT,262 SLCR_ARMPLL_CTRL, 4, 1, 0, &armpll_lock);263 264 clk_register_zynq_pll("ddrpll_int", "ps_clk", SLCR_DDRPLL_CTRL,265 SLCR_PLL_STATUS, 1, &ddrpll_lock);266 clks[ddrpll] = clk_register_mux(NULL, clk_output_name[ddrpll],267 ddrpll_parents, 2, CLK_SET_RATE_NO_REPARENT,268 SLCR_DDRPLL_CTRL, 4, 1, 0, &ddrpll_lock);269 270 clk_register_zynq_pll("iopll_int", "ps_clk", SLCR_IOPLL_CTRL,271 SLCR_PLL_STATUS, 2, &iopll_lock);272 clks[iopll] = clk_register_mux(NULL, clk_output_name[iopll],273 iopll_parents, 2, CLK_SET_RATE_NO_REPARENT,274 SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock);275 276 /* CPU clocks */277 tmp = readl(SLCR_621_TRUE) & 1;278 clk_register_mux(NULL, "cpu_mux", cpu_parents, 4,279 CLK_SET_RATE_NO_REPARENT, SLCR_ARM_CLK_CTRL, 4, 2, 0,280 &armclk_lock);281 clk_register_divider(NULL, "cpu_div", "cpu_mux", 0,282 SLCR_ARM_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |283 CLK_DIVIDER_ALLOW_ZERO, &armclk_lock);284 285 clks[cpu_6or4x] = clk_register_gate(NULL, clk_output_name[cpu_6or4x],286 "cpu_div", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,287 SLCR_ARM_CLK_CTRL, 24, 0, &armclk_lock);288 289 clk_register_fixed_factor(NULL, "cpu_3or2x_div", "cpu_div", 0,290 1, 2);291 clks[cpu_3or2x] = clk_register_gate(NULL, clk_output_name[cpu_3or2x],292 "cpu_3or2x_div", CLK_IGNORE_UNUSED,293 SLCR_ARM_CLK_CTRL, 25, 0, &armclk_lock);294 295 clk_register_fixed_factor(NULL, "cpu_2x_div", "cpu_div", 0, 1,296 2 + tmp);297 clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x],298 "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL,299 26, 0, &armclk_lock);300 clk_prepare_enable(clks[cpu_2x]);301 302 clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1,303 4 + 2 * tmp);304 clks[cpu_1x] = clk_register_gate(NULL, clk_output_name[cpu_1x],305 "cpu_1x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, 27,306 0, &armclk_lock);307 308 /* Timers */309 swdt_ext_clk_mux_parents[0] = clk_output_name[cpu_1x];310 for (i = 0; i < ARRAY_SIZE(swdt_ext_clk_input_names); i++) {311 int idx = of_property_match_string(np, "clock-names",312 swdt_ext_clk_input_names[i]);313 if (idx >= 0)314 swdt_ext_clk_mux_parents[i + 1] =315 of_clk_get_parent_name(np, idx);316 else317 swdt_ext_clk_mux_parents[i + 1] = dummy_nm;318 }319 clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt],320 swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT |321 CLK_SET_RATE_NO_REPARENT, SLCR_SWDT_CLK_SEL, 0, 1, 0,322 &swdtclk_lock);323 324 /* DDR clocks */325 clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0,326 SLCR_DDR_CLK_CTRL, 26, 6, CLK_DIVIDER_ONE_BASED |327 CLK_DIVIDER_ALLOW_ZERO, &ddrclk_lock);328 clks[ddr2x] = clk_register_gate(NULL, clk_output_name[ddr2x],329 "ddr2x_div", 0, SLCR_DDR_CLK_CTRL, 1, 0, &ddrclk_lock);330 clk_prepare_enable(clks[ddr2x]);331 clk_register_divider(NULL, "ddr3x_div", "ddrpll", 0,332 SLCR_DDR_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED |333 CLK_DIVIDER_ALLOW_ZERO, &ddrclk_lock);334 clks[ddr3x] = clk_register_gate(NULL, clk_output_name[ddr3x],335 "ddr3x_div", 0, SLCR_DDR_CLK_CTRL, 0, 0, &ddrclk_lock);336 clk_prepare_enable(clks[ddr3x]);337 338 clk_register_divider(NULL, "dci_div0", "ddrpll", 0,339 SLCR_DCI_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |340 CLK_DIVIDER_ALLOW_ZERO, &dciclk_lock);341 clk_register_divider(NULL, "dci_div1", "dci_div0",342 CLK_SET_RATE_PARENT, SLCR_DCI_CLK_CTRL, 20, 6,343 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,344 &dciclk_lock);345 clks[dci] = clk_register_gate(NULL, clk_output_name[dci], "dci_div1",346 CLK_SET_RATE_PARENT, SLCR_DCI_CLK_CTRL, 0, 0,347 &dciclk_lock);348 clk_prepare_enable(clks[dci]);349 350 /* Peripheral clocks */351 for (i = fclk0; i <= fclk3; i++) {352 int enable = !!(fclk_enable & BIT(i - fclk0));353 354 zynq_clk_register_fclk(i, clk_output_name[i],355 SLCR_FPGA0_CLK_CTRL + 0x10 * (i - fclk0),356 periph_parents, enable);357 }358 359 zynq_clk_register_periph_clk(lqspi, clk_max, clk_output_name[lqspi], NULL,360 SLCR_LQSPI_CLK_CTRL, periph_parents, 0);361 362 zynq_clk_register_periph_clk(smc, clk_max, clk_output_name[smc], NULL,363 SLCR_SMC_CLK_CTRL, periph_parents, 0);364 365 zynq_clk_register_periph_clk(pcap, clk_max, clk_output_name[pcap], NULL,366 SLCR_PCAP_CLK_CTRL, periph_parents, 0);367 368 zynq_clk_register_periph_clk(sdio0, sdio1, clk_output_name[sdio0],369 clk_output_name[sdio1], SLCR_SDIO_CLK_CTRL,370 periph_parents, 1);371 372 zynq_clk_register_periph_clk(uart0, uart1, clk_output_name[uart0],373 clk_output_name[uart1], SLCR_UART_CLK_CTRL,374 periph_parents, 1);375 376 zynq_clk_register_periph_clk(spi0, spi1, clk_output_name[spi0],377 clk_output_name[spi1], SLCR_SPI_CLK_CTRL,378 periph_parents, 1);379 380 for (i = 0; i < ARRAY_SIZE(gem0_emio_input_names); i++) {381 int idx = of_property_match_string(np, "clock-names",382 gem0_emio_input_names[i]);383 if (idx >= 0)384 gem0_mux_parents[i + 1] = of_clk_get_parent_name(np,385 idx);386 }387 clk_register_mux(NULL, "gem0_mux", periph_parents, 4,388 CLK_SET_RATE_NO_REPARENT, SLCR_GEM0_CLK_CTRL, 4, 2, 0,389 &gem0clk_lock);390 clk_register_divider(NULL, "gem0_div0", "gem0_mux", 0,391 SLCR_GEM0_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |392 CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock);393 clk_register_divider(NULL, "gem0_div1", "gem0_div0",394 CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6,395 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,396 &gem0clk_lock);397 clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2,398 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,399 SLCR_GEM0_CLK_CTRL, 6, 1, 0,400 &gem0clk_lock);401 clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0],402 "gem0_emio_mux", CLK_SET_RATE_PARENT,403 SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock);404 405 for (i = 0; i < ARRAY_SIZE(gem1_emio_input_names); i++) {406 int idx = of_property_match_string(np, "clock-names",407 gem1_emio_input_names[i]);408 if (idx >= 0)409 gem1_mux_parents[i + 1] = of_clk_get_parent_name(np,410 idx);411 }412 clk_register_mux(NULL, "gem1_mux", periph_parents, 4,413 CLK_SET_RATE_NO_REPARENT, SLCR_GEM1_CLK_CTRL, 4, 2, 0,414 &gem1clk_lock);415 clk_register_divider(NULL, "gem1_div0", "gem1_mux", 0,416 SLCR_GEM1_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |417 CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock);418 clk_register_divider(NULL, "gem1_div1", "gem1_div0",419 CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6,420 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,421 &gem1clk_lock);422 clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2,423 CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,424 SLCR_GEM1_CLK_CTRL, 6, 1, 0,425 &gem1clk_lock);426 clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1],427 "gem1_emio_mux", CLK_SET_RATE_PARENT,428 SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock);429 430 for (i = 0; i < NUM_MIO_PINS; i++) {431 int idx;432 433 snprintf(clk_name, CLK_NAME_LEN, "mio_clk_%2.2d", i);434 idx = of_property_match_string(np, "clock-names", clk_name);435 if (idx >= 0)436 can_mio_mux_parents[i] = of_clk_get_parent_name(np,437 idx);438 else439 can_mio_mux_parents[i] = dummy_nm;440 }441 clk_register_mux(NULL, "can_mux", periph_parents, 4,442 CLK_SET_RATE_NO_REPARENT, SLCR_CAN_CLK_CTRL, 4, 2, 0,443 &canclk_lock);444 clk_register_divider(NULL, "can_div0", "can_mux", 0,445 SLCR_CAN_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |446 CLK_DIVIDER_ALLOW_ZERO, &canclk_lock);447 clk_register_divider(NULL, "can_div1", "can_div0",448 CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 20, 6,449 CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,450 &canclk_lock);451 clk_register_gate(NULL, "can0_gate", "can_div1",452 CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 0, 0,453 &canclk_lock);454 clk_register_gate(NULL, "can1_gate", "can_div1",455 CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 1, 0,456 &canclk_lock);457 clk_register_mux(NULL, "can0_mio_mux",458 can_mio_mux_parents, 54, CLK_SET_RATE_PARENT |459 CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 0, 6, 0,460 &canmioclk_lock);461 clk_register_mux(NULL, "can1_mio_mux",462 can_mio_mux_parents, 54, CLK_SET_RATE_PARENT |463 CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 16, 6,464 0, &canmioclk_lock);465 clks[can0] = clk_register_mux(NULL, clk_output_name[can0],466 can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT |467 CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 6, 1, 0,468 &canmioclk_lock);469 clks[can1] = clk_register_mux(NULL, clk_output_name[can1],470 can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT |471 CLK_SET_RATE_NO_REPARENT, SLCR_CAN_MIOCLK_CTRL, 22, 1,472 0, &canmioclk_lock);473 474 for (i = 0; i < ARRAY_SIZE(dbgtrc_emio_input_names); i++) {475 int idx = of_property_match_string(np, "clock-names",476 dbgtrc_emio_input_names[i]);477 if (idx >= 0)478 dbg_emio_mux_parents[i + 1] = of_clk_get_parent_name(np,479 idx);480 }481 clk_register_mux(NULL, "dbg_mux", periph_parents, 4,482 CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 4, 2, 0,483 &dbgclk_lock);484 clk_register_divider(NULL, "dbg_div", "dbg_mux", 0,485 SLCR_DBG_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED |486 CLK_DIVIDER_ALLOW_ZERO, &dbgclk_lock);487 clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2,488 CLK_SET_RATE_NO_REPARENT, SLCR_DBG_CLK_CTRL, 6, 1, 0,489 &dbgclk_lock);490 clks[dbg_trc] = clk_register_gate(NULL, clk_output_name[dbg_trc],491 "dbg_emio_mux", CLK_SET_RATE_PARENT, SLCR_DBG_CLK_CTRL,492 0, 0, &dbgclk_lock);493 clks[dbg_apb] = clk_register_gate(NULL, clk_output_name[dbg_apb],494 clk_output_name[cpu_1x], 0, SLCR_DBG_CLK_CTRL, 1, 0,495 &dbgclk_lock);496 497 /* leave debug clocks in the state the bootloader set them up to */498 tmp = readl(SLCR_DBG_CLK_CTRL);499 if (tmp & DBG_CLK_CTRL_CLKACT_TRC)500 if (clk_prepare_enable(clks[dbg_trc]))501 pr_warn("%s: trace clk enable failed\n", __func__);502 if (tmp & DBG_CLK_CTRL_CPU_1XCLKACT)503 if (clk_prepare_enable(clks[dbg_apb]))504 pr_warn("%s: debug APB clk enable failed\n", __func__);505 506 /* One gated clock for all APER clocks. */507 clks[dma] = clk_register_gate(NULL, clk_output_name[dma],508 clk_output_name[cpu_2x], 0, SLCR_APER_CLK_CTRL, 0, 0,509 &aperclk_lock);510 clks[usb0_aper] = clk_register_gate(NULL, clk_output_name[usb0_aper],511 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 2, 0,512 &aperclk_lock);513 clks[usb1_aper] = clk_register_gate(NULL, clk_output_name[usb1_aper],514 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 3, 0,515 &aperclk_lock);516 clks[gem0_aper] = clk_register_gate(NULL, clk_output_name[gem0_aper],517 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 6, 0,518 &aperclk_lock);519 clks[gem1_aper] = clk_register_gate(NULL, clk_output_name[gem1_aper],520 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 7, 0,521 &aperclk_lock);522 clks[sdio0_aper] = clk_register_gate(NULL, clk_output_name[sdio0_aper],523 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 10, 0,524 &aperclk_lock);525 clks[sdio1_aper] = clk_register_gate(NULL, clk_output_name[sdio1_aper],526 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 11, 0,527 &aperclk_lock);528 clks[spi0_aper] = clk_register_gate(NULL, clk_output_name[spi0_aper],529 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 14, 0,530 &aperclk_lock);531 clks[spi1_aper] = clk_register_gate(NULL, clk_output_name[spi1_aper],532 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 15, 0,533 &aperclk_lock);534 clks[can0_aper] = clk_register_gate(NULL, clk_output_name[can0_aper],535 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 16, 0,536 &aperclk_lock);537 clks[can1_aper] = clk_register_gate(NULL, clk_output_name[can1_aper],538 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 17, 0,539 &aperclk_lock);540 clks[i2c0_aper] = clk_register_gate(NULL, clk_output_name[i2c0_aper],541 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 18, 0,542 &aperclk_lock);543 clks[i2c1_aper] = clk_register_gate(NULL, clk_output_name[i2c1_aper],544 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 19, 0,545 &aperclk_lock);546 clks[uart0_aper] = clk_register_gate(NULL, clk_output_name[uart0_aper],547 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 20, 0,548 &aperclk_lock);549 clks[uart1_aper] = clk_register_gate(NULL, clk_output_name[uart1_aper],550 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 21, 0,551 &aperclk_lock);552 clks[gpio_aper] = clk_register_gate(NULL, clk_output_name[gpio_aper],553 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 22, 0,554 &aperclk_lock);555 clks[lqspi_aper] = clk_register_gate(NULL, clk_output_name[lqspi_aper],556 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 23, 0,557 &aperclk_lock);558 clks[smc_aper] = clk_register_gate(NULL, clk_output_name[smc_aper],559 clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 24, 0,560 &aperclk_lock);561 562 for (i = 0; i < ARRAY_SIZE(clks); i++) {563 if (IS_ERR(clks[i])) {564 pr_err("Zynq clk %d: register failed with %ld\n",565 i, PTR_ERR(clks[i]));566 BUG();567 }568 }569 570 clk_data.clks = clks;571 clk_data.clk_num = ARRAY_SIZE(clks);572 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);573}574 575CLK_OF_DECLARE(zynq_clkc, "xlnx,ps7-clkc", zynq_clk_setup);576 577void __init zynq_clock_init(void)578{579 struct device_node *np;580 struct device_node *slcr;581 struct resource res;582 583 np = of_find_compatible_node(NULL, NULL, "xlnx,ps7-clkc");584 if (!np) {585 pr_err("%s: clkc node not found\n", __func__);586 goto np_err;587 }588 589 if (of_address_to_resource(np, 0, &res)) {590 pr_err("%pOFn: failed to get resource\n", np);591 goto np_err;592 }593 594 slcr = of_get_parent(np);595 596 if (slcr->data) {597 zynq_clkc_base = (__force void __iomem *)slcr->data + res.start;598 } else {599 pr_err("%pOFn: Unable to get I/O memory\n", np);600 of_node_put(slcr);601 goto np_err;602 }603 604 pr_info("%s: clkc starts at %p\n", __func__, zynq_clkc_base);605 606 of_node_put(slcr);607 of_node_put(np);608 609 return;610 611np_err:612 of_node_put(np);613 BUG();614}615