static void __init cpg_mstp_clocks_init(struct device_node *np) { struct mstp_clock_group *group; const char *idxname; struct clk **clks; unsigned int i; group = kzalloc(sizeof(*group), GFP_KERNEL); clks = kmalloc_array(MSTP_MAX_CLOCKS, sizeof(*clks), GFP_KERNEL); if (group == NULL || clks == NULL) { kfree(group); kfree(clks); return; } spin_lock_init(&group->lock); group->data.clks = clks; group->smstpcr = of_iomap(np, 0); group->mstpsr = of_iomap(np, 1); if (group->smstpcr == NULL) { pr_err("%s: failed to remap SMSTPCR\n", __func__); kfree(group); kfree(clks); return; } if (of_device_is_compatible(np, "renesas,r7s72100-mstp-clocks")) group->width_8bit = true; for (i = 0; i < MSTP_MAX_CLOCKS; ++i) clks[i] = ERR_PTR(-ENOENT); if (of_find_property(np, "clock-indices", &i)) idxname = "clock-indices"; else idxname = "renesas,clock-indices"; for (i = 0; i < MSTP_MAX_CLOCKS; ++i) { const char *parent_name; const char *name; u32 clkidx; int ret; /* Skip clocks with no name. */ ret = of_property_read_string_index(np, "clock-output-names", i, &name); if (ret < 0 || strlen(name) == 0) continue; parent_name = of_clk_get_parent_name(np, i); ret = of_property_read_u32_index(np, idxname, i, &clkidx); if (parent_name == NULL || ret < 0) break; if (clkidx >= MSTP_MAX_CLOCKS) { pr_err("%s: invalid clock %pOFn %s index %u\n", __func__, np, name, clkidx); continue; } clks[clkidx] = cpg_mstp_clock_register(name, parent_name, clkidx, group); if (!IS_ERR(clks[clkidx])) { group->data.clk_num = max(group->data.clk_num, clkidx + 1); /* * Register a clkdev to let board code retrieve the * clock by name and register aliases for non-DT * devices. * * FIXME: Remove this when all devices that require a * clock will be instantiated from DT. */ clk_register_clkdev(clks[clkidx], name, NULL); } else { pr_err("%s: failed to register %pOFn %s clock (%ld)\n", __func__, np, name, PTR_ERR(clks[clkidx])); } } of_clk_add_provider(np, of_clk_src_onecell_get, &group->data); }
/** * of_ti_dpll_setup - Setup function for OMAP DPLL clocks * @node: device node containing the DPLL info * @ops: ops for the DPLL * @ddt: DPLL data template to use * @init_flags: flags for controlling init types * * Initializes a DPLL clock from device tree data. */ static void __init of_ti_dpll_setup(struct device_node *node, const struct clk_ops *ops, const struct dpll_data *ddt, u8 init_flags) { struct clk_hw_omap *clk_hw = NULL; struct clk_init_data *init = NULL; const char **parent_names = NULL; struct dpll_data *dd = NULL; int i; u8 dpll_mode = 0; dd = kzalloc(sizeof(*dd), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); init = kzalloc(sizeof(*init), GFP_KERNEL); if (!dd || !clk_hw || !init) goto cleanup; memcpy(dd, ddt, sizeof(*dd)); clk_hw->dpll_data = dd; clk_hw->ops = &clkhwops_omap3_dpll; clk_hw->hw.init = init; clk_hw->flags = MEMMAP_ADDRESSING; init->name = node->name; init->ops = ops; init->num_parents = of_clk_get_parent_count(node); if (init->num_parents < 1) { pr_err("%s must have parent(s)\n", node->name); goto cleanup; } parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL); if (!parent_names) goto cleanup; for (i = 0; i < init->num_parents; i++) parent_names[i] = of_clk_get_parent_name(node, i); init->parent_names = parent_names; dd->control_reg = ti_clk_get_reg_addr(node, 0); dd->idlest_reg = ti_clk_get_reg_addr(node, 1); dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg) goto cleanup; if (init_flags & DPLL_HAS_AUTOIDLE) { dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); if (!dd->autoidle_reg) goto cleanup; } if (of_property_read_bool(node, "ti,low-power-stop")) dpll_mode |= 1 << DPLL_LOW_POWER_STOP; if (of_property_read_bool(node, "ti,low-power-bypass")) dpll_mode |= 1 << DPLL_LOW_POWER_BYPASS; if (of_property_read_bool(node, "ti,lock")) dpll_mode |= 1 << DPLL_LOCKED; if (dpll_mode) dd->modes = dpll_mode; ti_clk_register_dpll(&clk_hw->hw, node); return; cleanup: kfree(dd); kfree(parent_names); kfree(init); kfree(clk_hw); }
static void __init sama5d4_pmc_setup(struct device_node *np) { struct clk_range range = CLK_RANGE(0, 0); const char *slck_name, *mainxtal_name; struct pmc_data *sama5d4_pmc; const char *parent_names[5]; struct regmap *regmap; struct clk *hw; int i; bool bypass; i = of_property_match_string(np, "clock-names", "slow_clk"); if (i < 0) return; slck_name = of_clk_get_parent_name(np, i); i = of_property_match_string(np, "clock-names", "main_xtal"); if (i < 0) return; mainxtal_name = of_clk_get_parent_name(np, i); regmap = syscon_node_to_regmap(np); if (IS_ERR(regmap)) return; sama5d4_pmc = pmc_data_allocate(PMC_MCK2 + 1, nck(sama5d4_systemck), nck(sama5d4_periph32ck), 0); if (!sama5d4_pmc) return; hw = at91_clk_register_main_rc_osc(regmap, "main_rc_osc", 12000000, 100000000); if (IS_ERR(hw)) goto err_free; bypass = of_property_read_bool(np, "atmel,osc-bypass"); hw = at91_clk_register_main_osc(regmap, "main_osc", mainxtal_name, bypass); if (IS_ERR(hw)) goto err_free; parent_names[0] = "main_rc_osc"; parent_names[1] = "main_osc"; hw = at91_clk_register_sam9x5_main(regmap, "mainck", parent_names, 2); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_pll(regmap, "pllack", "mainck", 0, &sama5d3_pll_layout, &plla_characteristics); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_plldiv(regmap, "plladivck", "pllack"); if (IS_ERR(hw)) goto err_free; hw = at91_clk_register_utmi(regmap, NULL, "utmick", "mainck"); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->chws[PMC_UTMI] = hw; parent_names[0] = slck_name; parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; hw = at91_clk_register_master(regmap, "masterck", 4, parent_names, &at91sam9x5_master_layout, &mck_characteristics); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->chws[PMC_MCK] = hw; hw = at91_clk_register_h32mx(regmap, "h32mxck", "masterck"); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->chws[PMC_MCK2] = hw; parent_names[0] = "plladivck"; parent_names[1] = "utmick"; hw = at91sam9x5_clk_register_usb(regmap, "usbck", parent_names, 2); if (IS_ERR(hw)) goto err_free; parent_names[0] = "plladivck"; parent_names[1] = "utmick"; hw = at91sam9x5_clk_register_smd(regmap, "smdclk", parent_names, 2); if (IS_ERR(hw)) goto err_free; parent_names[0] = slck_name; parent_names[1] = "mainck"; parent_names[2] = "plladivck"; parent_names[3] = "utmick"; parent_names[4] = "mck"; for (i = 0; i < 3; i++) { char *name; name = xasprintf("prog%d", i); hw = at91_clk_register_programmable(regmap, name, parent_names, 5, i, &at91sam9x5_programmable_layout); if (IS_ERR(hw)) goto err_free; } for (i = 0; i < ARRAY_SIZE(sama5d4_systemck); i++) { hw = at91_clk_register_system(regmap, sama5d4_systemck[i].n, sama5d4_systemck[i].p, sama5d4_systemck[i].id); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->shws[sama5d4_systemck[i].id] = hw; } for (i = 0; i < ARRAY_SIZE(sama5d4_periphck); i++) { hw = at91_clk_register_sam9x5_peripheral(regmap, sama5d4_periphck[i].n, "masterck", sama5d4_periphck[i].id, &range); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->phws[sama5d4_periphck[i].id] = hw; } for (i = 0; i < ARRAY_SIZE(sama5d4_periph32ck); i++) { hw = at91_clk_register_sam9x5_peripheral(regmap, sama5d4_periph32ck[i].n, "h32mxck", sama5d4_periph32ck[i].id, &range); if (IS_ERR(hw)) goto err_free; sama5d4_pmc->phws[sama5d4_periph32ck[i].id] = hw; } of_clk_add_provider(np, of_clk_hw_pmc_get, sama5d4_pmc); return; err_free: pmc_data_free(sama5d4_pmc); }
static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct clk_onecell_data *clk_data; const char *clk_parent; const char *clk_name; struct resource *r; void __iomem *reg; int gate_id; int ngates; int i; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); reg = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(reg)) return PTR_ERR(reg); clk_parent = of_clk_get_parent_name(np, 0); if (!clk_parent) return -EINVAL; ngates = of_property_count_strings(np, "clock-output-names"); if (ngates < 0) return ngates; if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE) return -EINVAL; clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data), GFP_KERNEL); if (!clk_data) return -ENOMEM; clk_data->clks = devm_kzalloc(&pdev->dev, SUN6I_APB0_GATES_MAX_SIZE * sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) return -ENOMEM; for (i = 0; i < ngates; i++) { of_property_read_string_index(np, "clock-output-names", i, &clk_name); gate_id = i; of_property_read_u32_index(np, "clock-indices", i, &gate_id); WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE); if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE) continue; clk_data->clks[gate_id] = clk_register_gate(&pdev->dev, clk_name, clk_parent, 0, reg, gate_id, 0, NULL); WARN_ON(IS_ERR(clk_data->clks[gate_id])); } clk_data->clk_num = ngates; return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data); }
void __init of_dra7_apll_setup(struct device_node *node) { const struct clk_ops *ops; struct clk *clk; const char *clk_name = node->name; int num_parents; const char **parent_names = NULL; u8 apll_flags = 0; struct dpll_data *ad; u32 idlest_mask = 0x1; u32 autoidle_mask = 0x3; int i; ops = &apll_ck_ops; ad = kzalloc(sizeof(*ad), GFP_KERNEL); if (!ad) { pr_err("%s: could not allocate dpll_data\n", __func__); return; } of_property_read_string(node, "clock-output-names", &clk_name); num_parents = of_clk_get_parent_count(node); if (num_parents < 1) { pr_err("%s: omap dpll %s must have parent(s)\n", __func__, node->name); goto cleanup; } parent_names = kzalloc(sizeof(char *) * num_parents, GFP_KERNEL); for (i = 0; i < num_parents; i++) parent_names[i] = of_clk_get_parent_name(node, i); ad->clk_ref = of_clk_get(node, 0); ad->clk_bypass = of_clk_get(node, 1); if (IS_ERR(ad->clk_ref)) { pr_err("%s: ti,clk-ref for %s not found\n", __func__, clk_name); goto cleanup; } if (IS_ERR(ad->clk_bypass)) { pr_err("%s: ti,clk-bypass for %s not found\n", __func__, clk_name); goto cleanup; } i = of_property_match_string(node, "reg-names", "control"); if (i >= 0) ad->control_reg = of_iomap(node, i); i = of_property_match_string(node, "reg-names", "idlest"); if (i >= 0) ad->idlest_reg = of_iomap(node, i); ad->idlest_mask = idlest_mask; ad->enable_mask = autoidle_mask; clk = omap_clk_register_apll(NULL, clk_name, parent_names, num_parents, apll_flags, ad, NULL, ops); if (!IS_ERR(clk)) of_clk_add_provider(node, of_clk_src_simple_get, clk); return; cleanup: kfree(parent_names); kfree(ad); return; }
static void __init cpg_div6_clock_init(struct device_node *np) { struct clk_init_data init; struct div6_clock *clock; const char *parent_name; const char *name; struct clk *clk; int ret; clock = kzalloc(sizeof(*clock), GFP_KERNEL); if (!clock) { pr_err("%s: failed to allocate %s DIV6 clock\n", __func__, np->name); return; } /* Remap the clock register and read the divisor. Disabling the * clock overwrites the divisor, so we need to cache its value for the * enable operation. */ clock->reg = of_iomap(np, 0); if (clock->reg == NULL) { pr_err("%s: failed to map %s DIV6 clock register\n", __func__, np->name); goto error; } clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1; /* Parse the DT properties. */ ret = of_property_read_string(np, "clock-output-names", &name); if (ret < 0) { pr_err("%s: failed to get %s DIV6 clock output name\n", __func__, np->name); goto error; } parent_name = of_clk_get_parent_name(np, 0); if (parent_name == NULL) { pr_err("%s: failed to get %s DIV6 clock parent name\n", __func__, np->name); goto error; } /* Register the clock. */ init.name = name; init.ops = &cpg_div6_clock_ops; init.flags = CLK_IS_BASIC; init.parent_names = &parent_name; init.num_parents = 1; clock->hw.init = &init; clk = clk_register(NULL, &clock->hw); if (IS_ERR(clk)) { pr_err("%s: failed to register %s DIV6 clock (%ld)\n", __func__, np->name, PTR_ERR(clk)); goto error; } of_clk_add_provider(np, of_clk_src_simple_get, clk); return; error: if (clock->reg) iounmap(clock->reg); kfree(clock); }
/** * zynqmp_clk_setup - Setup the clock framework and register clocks * @np: Device node * * Return: Error code on failure */ static void __init zynqmp_clk_setup(struct device_node *np) { int i; u32 tmp; struct clk *clk; char *clk_name; int idx; idx = of_property_match_string(np, "clock-names", "pss_ref_clk"); if (idx < 0) { pr_err("pss_ref_clk not provided\n"); return; } input_clks[0] = of_clk_get_parent_name(np, idx); idx = of_property_match_string(np, "clock-names", "video_clk"); if (idx < 0) { pr_err("video_clk not provided\n"); return; } input_clks[1] = of_clk_get_parent_name(np, idx); idx = of_property_match_string(np, "clock-names", "pss_alt_ref_clk"); if (idx < 0) { pr_err("pss_alt_ref_clk not provided\n"); return; } input_clks[2] = of_clk_get_parent_name(np, idx); idx = of_property_match_string(np, "clock-names", "aux_ref_clk"); if (idx < 0) { pr_err("aux_ref_clk not provided\n"); return; } input_clks[3] = of_clk_get_parent_name(np, idx); idx = of_property_match_string(np, "clock-names", "gt_crx_ref_clk"); if (idx < 0) { pr_err("aux_ref_clk not provided\n"); return; } input_clks[4] = of_clk_get_parent_name(np, idx); /* get clock output names from DT */ for (i = 0; i < clk_max; i++) { if (of_property_read_string_index(np, "clock-output-names", i, &clk_output_name[i])) { pr_err("%s: clock output name not in DT\n", __func__); BUG(); } } /* APU clocks */ acpu_parents[0] = clk_output_name[apll]; acpu_parents[1] = dummy_nm; acpu_parents[2] = clk_output_name[dpll]; acpu_parents[3] = clk_output_name[vpll]; /* PLL clocks */ zynqmp_clk_register_pll_clk(apll, clk_output_name[apll], CLK_IGNORE_UNUSED, (resource_size_t *)CRF_APB_APLL_CTRL, (resource_size_t *)CRF_APB_PLL_STATUS, 0); zynqmp_clk_register_pll_clk(dpll, clk_output_name[dpll], 0, (resource_size_t *)CRF_APB_DPLL_CTRL, (resource_size_t *)CRF_APB_PLL_STATUS, 1); zynqmp_clk_register_pll_clk(vpll, clk_output_name[vpll], CLK_IGNORE_UNUSED, (resource_size_t *)CRF_APB_VPLL_CTRL, (resource_size_t *)CRF_APB_PLL_STATUS, 2); zynqmp_clk_register_pll_clk(iopll, clk_output_name[iopll], 0, (resource_size_t *)CRL_APB_IOPLL_CTRL, (resource_size_t *)CRL_APB_PLL_STATUS, 0); zynqmp_clk_register_pll_clk(rpll, clk_output_name[rpll], 0, (resource_size_t *)CRL_APB_RPLL_CTRL, (resource_size_t *)CRL_APB_PLL_STATUS, 1); /* Domain crossing PLL clock dividers */ clks[apll_to_lpd] = zynqmp_clk_register_divider(NULL, "apll_to_lpd", clk_output_name[apll], 0, (resource_size_t *)CRF_APB_APLL_TO_LPD_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[dpll_to_lpd] = zynqmp_clk_register_divider(NULL, "dpll_to_lpd", clk_output_name[dpll], 0, (resource_size_t *)CRF_APB_DPLL_TO_LPD_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[vpll_to_lpd] = zynqmp_clk_register_divider(NULL, "vpll_to_lpd", clk_output_name[vpll], 0, (resource_size_t *)CRF_APB_VPLL_TO_LPD_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[iopll_to_fpd] = zynqmp_clk_register_divider(NULL, "iopll_to_fpd", clk_output_name[iopll], 0, (resource_size_t *)CRL_APB_IOPLL_TO_FPD_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[rpll_to_fpd] = zynqmp_clk_register_divider(NULL, "rpll_to_fpd", clk_output_name[rpll], 0, (resource_size_t *)CRL_APB_RPLL_TO_FPD_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_mux(NULL, "acpu_mux", acpu_parents, 4, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRF_APB_ACPU_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "acpu_div0", "acpu_mux", 0, (resource_size_t *)CRF_APB_ACPU_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[acpu] = zynqmp_clk_register_gate(NULL, clk_output_name[acpu], "acpu_div0", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, (resource_size_t *)CRF_APB_ACPU_CTRL, 24, 0); clk_prepare_enable(clks[acpu]); clk = clk_register_fixed_factor(NULL, "acpu_half_div", "acpu_div0", 0, 1, 2); clks[acpu_half] = zynqmp_clk_register_gate(NULL, clk_output_name[acpu_half], "acpu_half_div", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, (resource_size_t *)CRF_APB_ACPU_CTRL, 25, 0); /* Timers */ /* The first parent clock source will be changed in the future. * Currently, using the acpu clock as the parent based on the * assumption that it comes from APB. */ wdt_ext_clk_mux_parents[0] = clk_output_name[acpu]; for (i = 0; i < ARRAY_SIZE(swdt_ext_clk_input_names); i++) { int idx = of_property_match_string(np, "clock-names", swdt_ext_clk_input_names[i]); if (idx >= 0) wdt_ext_clk_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); else wdt_ext_clk_mux_parents[i + 1] = dummy_nm; } clks[wdt] = zynqmp_clk_register_mux(NULL, clk_output_name[wdt], wdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_WDT_CLK_SEL, 0, 1, 0); /* DDR clocks */ ddr_parents[0] = clk_output_name[dpll]; ddr_parents[1] = clk_output_name[vpll]; clk = zynqmp_clk_register_mux(NULL, "ddr_mux", ddr_parents, 2, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRF_APB_DDR_CTRL, 0, 3, 0); clks[ddr_ref] = zynqmp_clk_register_divider(NULL, clk_output_name[ddr_ref], "ddr_mux", 0, (resource_size_t *)CRF_APB_DDR_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk_prepare_enable(clks[ddr_ref]); /* Peripheral clock parents */ zynqmp_clk_get_parents(clk_output_name, periph_parents[dbg_trace], iopll_to_fpd, dpll, apll); zynqmp_clk_get_parents(clk_output_name, periph_parents[dbg_fpd], iopll_to_fpd, dpll, apll); zynqmp_clk_get_parents(clk_output_name, periph_parents[dbg_lpd], rpll, iopll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[dbg_tstmp], iopll_to_fpd, dpll, apll); zynqmp_clk_get_parents(clk_output_name, periph_parents[dp_video_ref], vpll, dpll, rpll_to_fpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[dp_audio_ref], vpll, dpll, rpll_to_fpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[dp_stc_ref], vpll, dpll, rpll_to_fpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gpu_ref], iopll_to_fpd, vpll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[sata_ref], iopll_to_fpd, apll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[pcie_ref], iopll_to_fpd, rpll_to_fpd, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[gdma_ref], apll, vpll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[dpdma_ref], apll, vpll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[topsw_main], apll, vpll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[topsw_lsbus], apll, iopll_to_fpd, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[gtgref0_ref], iopll_to_fpd, apll, dpll); zynqmp_clk_get_parents(clk_output_name, periph_parents[usb3_dual_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[usb0_bus_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[usb1_bus_ref], iopll, apll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gem0_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gem1_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gem2_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gem3_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[qspi_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[sdio0_ref], iopll, rpll, vpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[sdio1_ref], iopll, rpll, vpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[uart0_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[uart1_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[spi0_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[spi1_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[can0_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[can1_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[cpu_r5], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[iou_switch], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[csu_pll], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[pcap], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[lpd_switch], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[lpd_lsbus], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[nand_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[adma_ref], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[gem_tsu_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[ams_ref], rpll, iopll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[i2c0_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[i2c1_ref], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[pl0], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[pl1], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[pl2], iopll, rpll, dpll_to_lpd); zynqmp_clk_get_parents(clk_output_name, periph_parents[pl3], iopll, rpll, dpll_to_lpd); /* PL clocks */ zynqmp_clk_register_pl_clk(pl0, clk_output_name[pl0], (resource_size_t *)CRL_APB_PL0_REF_CTRL, periph_parents[pl0]); zynqmp_clk_register_pl_clk(pl1, clk_output_name[pl1], (resource_size_t *)CRL_APB_PL1_REF_CTRL, periph_parents[pl1]); zynqmp_clk_register_pl_clk(pl2, clk_output_name[pl2], (resource_size_t *)CRL_APB_PL2_REF_CTRL, periph_parents[pl2]); zynqmp_clk_register_pl_clk(pl3, clk_output_name[pl3], (resource_size_t *)CRL_APB_PL3_REF_CTRL, periph_parents[pl3]); /* Peripheral clock */ zynqmp_clk_register_periph_clk(dbg_trace, clk_output_name[dbg_trace], CRF_APB_DBG_TRACE_CTRL, periph_parents[dbg_trace], 1, 0, 24); zynqmp_clk_get_parents(clk_output_name, periph_parents[dbg_fpd], iopll_to_fpd, dpll, apll); zynqmp_clk_register_periph_clk(dbg_fpd, clk_output_name[dbg_fpd], CRF_APB_DBG_FPD_CTRL, periph_parents[dbg_fpd], 1, 0, 24); zynqmp_clk_register_periph_clk(dbg_lpd, clk_output_name[dbg_lpd], CRL_APB_DBG_LPD_CTRL, periph_parents[dbg_lpd], 1, 0, 24); zynqmp_clk_register_periph_clk(dbg_tstmp, clk_output_name[dbg_tstmp], CRF_APB_DBG_TSTMP_CTRL, periph_parents[dbg_tstmp], 0, 0, 0); zynqmp_clk_register_periph_clk(dp_video_ref, clk_output_name[dp_video_ref], CRF_APB_DP_VIDEO_REF_CTRL, periph_parents[dp_video_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(dp_audio_ref, clk_output_name[dp_audio_ref], CRF_APB_DP_AUDIO_REF_CTRL, periph_parents[dp_audio_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(dp_stc_ref, clk_output_name[dp_stc_ref], CRF_APB_DP_STC_REF_CTRL, periph_parents[dp_stc_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(gpu_ref, clk_output_name[gpu_ref], CRF_APB_GPU_REF_CTRL, periph_parents[gpu_ref], 1, 0, 24); clks[gpu_pp0_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gpu_pp0_ref], "gpu_ref_div0", CLK_SET_RATE_PARENT, (resource_size_t *)CRF_APB_GPU_REF_CTRL, 25, 0); clks[gpu_pp1_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gpu_pp1_ref], "gpu_ref_div0", CLK_SET_RATE_PARENT, (resource_size_t *)CRF_APB_GPU_REF_CTRL, 26, 0); zynqmp_clk_register_periph_clk(sata_ref, clk_output_name[sata_ref], CRF_APB_SATA_REF_CTRL, periph_parents[sata_ref], 1, 0, 24); zynqmp_clk_register_periph_clk(pcie_ref, clk_output_name[pcie_ref], CRF_APB_PCIE_REF_CTRL, periph_parents[pcie_ref], 1, 0, 24); zynqmp_clk_register_periph_clk(gdma_ref, clk_output_name[gdma_ref], CRF_APB_GDMA_REF_CTRL, periph_parents[gdma_ref], 1, 0, 24); zynqmp_clk_register_periph_clk(dpdma_ref, clk_output_name[dpdma_ref], CRF_APB_DPDMA_REF_CTRL, periph_parents[dpdma_ref], 1, 0, 24); zynqmp_clk_register_periph_clk(topsw_main, clk_output_name[topsw_main], CRF_APB_TOPSW_MAIN_CTRL, periph_parents[topsw_main], CLK_IGNORE_UNUSED, 0, 24); zynqmp_clk_register_periph_clk(topsw_lsbus, clk_output_name[topsw_lsbus], CRF_APB_TOPSW_LSBUS_CTRL, periph_parents[topsw_lsbus], CLK_IGNORE_UNUSED, 0, 24); zynqmp_clk_register_periph_clk(gtgref0_ref, clk_output_name[gtgref0_ref], CRF_APB_GTGREF0_REF_CTRL, periph_parents[gtgref0_ref], 1, 0, 24); zynqmp_clk_register_periph_clk(usb3_dual_ref, clk_output_name[usb3_dual_ref], CRL_APB_USB3_DUAL_REF_CTRL, periph_parents[usb3_dual_ref], 1, 1, 25); zynqmp_clk_register_periph_clk(usb0_bus_ref, clk_output_name[usb0_bus_ref], CRL_APB_USB0_BUS_REF_CTRL, periph_parents[usb0_bus_ref], 1, 1, 25); clks[usb0] = zynqmp_clk_register_mux(NULL, clk_output_name[usb0], usb0_mio_mux_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_USB0_BUS_REF_CTRL, 2, 1, 0); zynqmp_clk_register_periph_clk(usb1_bus_ref, clk_output_name[usb1_bus_ref], CRL_APB_USB1_BUS_REF_CTRL, periph_parents[usb1_bus_ref], 1, 1, 25); clks[usb1] = zynqmp_clk_register_mux(NULL, clk_output_name[usb1], usb1_mio_mux_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_USB1_BUS_REF_CTRL, 2, 1, 0); /* Ethernet clocks */ for (i = 0; i < ARRAY_SIZE(gem0_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem0_emio_input_names[i]); if (idx >= 0) gem0_tx_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = zynqmp_clk_register_mux(NULL, "gem0_ref_mux", periph_parents[gem0_ref], 4, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_GEM0_REF_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "gem0_ref_div0", "gem0_ref_mux", 0, (resource_size_t *)CRL_APB_GEM0_REF_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_divider(NULL, "gem0_ref_div1", "gem0_ref_div0", 0, (resource_size_t *)CRL_APB_GEM0_REF_CTRL, 16, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_mux(NULL, "gem0_tx_mux", gem0_tx_mux_parents, 2, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_GEM_CLK_CTRL, 1, 1, 0); clks[gem0_rx] = zynqmp_clk_register_gate(NULL, clk_output_name[gem0_rx], "gem0_tx_mux", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM0_REF_CTRL, 26, 0); clks[gem0_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gem0_ref], "gem0_ref_div1", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM0_REF_CTRL, 25, 0); for (i = 0; i < ARRAY_SIZE(gem1_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem1_emio_input_names[i]); if (idx >= 0) gem1_tx_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = zynqmp_clk_register_mux(NULL, "gem1_ref_mux", periph_parents[gem1_ref], 4, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_GEM1_REF_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "gem1_ref_div0", "gem1_ref_mux", 0, (resource_size_t *)CRL_APB_GEM1_REF_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_divider(NULL, "gem1_ref_div1", "gem1_ref_div0", 0, (resource_size_t *)CRL_APB_GEM1_REF_CTRL, 16, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_mux(NULL, "gem1_tx_mux", gem1_tx_mux_parents, 2, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_GEM_CLK_CTRL, 6, 1, 0); clks[gem1_rx] = zynqmp_clk_register_gate(NULL, clk_output_name[gem1_rx], "gem1_tx_mux", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM1_REF_CTRL, 26, 0); clks[gem1_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gem1_ref], "gem1_ref_div1", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM1_REF_CTRL, 25, 0); for (i = 0; i < ARRAY_SIZE(gem2_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem2_emio_input_names[i]); if (idx >= 0) gem2_tx_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = zynqmp_clk_register_mux(NULL, "gem2_ref_mux", periph_parents[gem2_ref], 4, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_GEM2_REF_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "gem2_ref_div0", "gem2_ref_mux", 0, (resource_size_t *)CRL_APB_GEM2_REF_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_divider(NULL, "gem2_ref_div1", "gem2_ref_div0", 0, (resource_size_t *)CRL_APB_GEM2_REF_CTRL, 16, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_mux(NULL, "gem2_tx_mux", gem2_tx_mux_parents, 2, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_GEM_CLK_CTRL, 11, 1, 0); clks[gem2_rx] = zynqmp_clk_register_gate(NULL, clk_output_name[gem2_rx], "gem2_tx_mux", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM2_REF_CTRL, 26, 0); clks[gem2_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gem2_ref], "gem2_ref_div1", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM2_REF_CTRL, 25, 0); for (i = 0; i < ARRAY_SIZE(gem3_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem3_emio_input_names[i]); if (idx >= 0) gem3_tx_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = zynqmp_clk_register_mux(NULL, "gem3_ref_mux", periph_parents[gem3_ref], 4, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_GEM3_REF_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "gem3_ref_div0", "gem3_ref_mux", 0, (resource_size_t *)CRL_APB_GEM3_REF_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_divider(NULL, "gem3_ref_div1", "gem3_ref_div0", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM3_REF_CTRL, 16, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clk = zynqmp_clk_register_mux(NULL, "gem3_tx_mux", gem3_tx_mux_parents, 2, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_GEM_CLK_CTRL, 16, 1, 0); clks[gem3_rx] = zynqmp_clk_register_gate(NULL, clk_output_name[gem3_rx], "gem3_tx_mux", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM3_REF_CTRL, 26, 0); clks[gem3_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[gem3_ref], "gem3_ref_div1", CLK_SET_RATE_PARENT, (resource_size_t *)CRL_APB_GEM3_REF_CTRL, 25, 0); gem_tsu_mux_parents[0] = clk_output_name[gem_tsu_ref]; gem_tsu_mux_parents[1] = clk_output_name[gem_tsu_ref]; gem_tsu_mux_parents[2] = "mio_clk_26"; gem_tsu_mux_parents[3] = "mio_clk_50_or_51"; zynqmp_clk_register_periph_clk(gem_tsu_ref, clk_output_name[gem_tsu_ref], CRL_APB_GEM_TSU_REF_CTRL, periph_parents[gem_tsu_ref], 1, 1, 24); clks[gem_tsu] = zynqmp_clk_register_mux(NULL, clk_output_name[gem_tsu], gem_tsu_mux_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_GEM_CLK_CTRL, 20, 2, 0); zynqmp_clk_register_periph_clk(qspi_ref, clk_output_name[qspi_ref], CRL_APB_QSPI_REF_CTRL, periph_parents[qspi_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(sdio0_ref, clk_output_name[sdio0_ref], CRL_APB_SDIO0_REF_CTRL, periph_parents[sdio0_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(sdio1_ref, clk_output_name[sdio1_ref], CRL_APB_SDIO1_REF_CTRL, periph_parents[sdio1_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(uart0_ref, clk_output_name[uart0_ref], CRL_APB_UART0_REF_CTRL, periph_parents[uart0_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(uart1_ref, clk_output_name[uart1_ref], CRL_APB_UART1_REF_CTRL, periph_parents[uart1_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(spi0_ref, clk_output_name[spi0_ref], CRL_APB_SPI0_REF_CTRL, periph_parents[spi0_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(spi1_ref, clk_output_name[spi1_ref], CRL_APB_SPI1_REF_CTRL, periph_parents[spi1_ref], 1, 1, 24); tmp = strlen("mio_clk_00x"); clk_name = kmalloc(tmp, GFP_KERNEL); for (i = 0; i < NUM_MIO_PINS; i++) { int idx; snprintf(clk_name, tmp, "mio_clk_%2.2d", i); idx = of_property_match_string(np, "clock-names", clk_name); if (idx >= 0) can_mio_mux_parents[i] = of_clk_get_parent_name(np, idx); else can_mio_mux_parents[i] = dummy_nm; } kfree(clk_name); zynqmp_clk_register_periph_clk(can0_ref, clk_output_name[can0_ref], CRL_APB_CAN0_REF_CTRL, periph_parents[can0_ref], 1, 1, 24); clk = zynqmp_clk_register_mux(NULL, "can0_mio_mux", can_mio_mux_parents, NUM_MIO_PINS, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_CAN_MIO_CTRL, 0, 7, 0); clks[can0] = zynqmp_clk_register_mux(NULL, clk_output_name[can0], can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_CAN_MIO_CTRL, 7, 1, 0); zynqmp_clk_register_periph_clk(can1_ref, clk_output_name[can1_ref], CRL_APB_CAN1_REF_CTRL, periph_parents[can1_ref], 1, 1, 24); clk = zynqmp_clk_register_mux(NULL, "can1_mio_mux", can_mio_mux_parents, NUM_MIO_PINS, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_CAN_MIO_CTRL, 15, 7, 0); clks[can1] = zynqmp_clk_register_mux(NULL, clk_output_name[can1], can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)IOU_SLCR_CAN_MIO_CTRL, 22, 1, 0); zynqmp_clk_register_periph_clk(cpu_r5, clk_output_name[cpu_r5], CRL_APB_CPU_R5_CTRL, periph_parents[cpu_r5], CLK_IGNORE_UNUSED, 0, 24); clk = zynqmp_clk_register_gate(NULL, "cpu_r5_core_gate", "cpu_r5_div0", CLK_IGNORE_UNUSED, (resource_size_t *)CRL_APB_CPU_R5_CTRL, 25, 0); zynqmp_clk_register_periph_clk(iou_switch, clk_output_name[iou_switch], CRL_APB_IOU_SWITCH_CTRL, periph_parents[iou_switch], CLK_IGNORE_UNUSED, 0, 24); zynqmp_clk_register_periph_clk(csu_pll, clk_output_name[csu_pll], CRL_APB_CSU_PLL_CTRL, periph_parents[csu_pll], 1, 0, 24); zynqmp_clk_register_periph_clk(pcap, clk_output_name[pcap], CRL_APB_PCAP_CTRL, periph_parents[pcap], 1, 0, 24); zynqmp_clk_register_periph_clk(lpd_switch, clk_output_name[lpd_switch], CRL_APB_LPD_SWITCH_CTRL, periph_parents[lpd_switch], CLK_IGNORE_UNUSED, 0, 24); zynqmp_clk_register_periph_clk(lpd_lsbus, clk_output_name[lpd_lsbus], CRL_APB_LPD_LSBUS_CTRL, periph_parents[lpd_lsbus], CLK_IGNORE_UNUSED, 0, 24); zynqmp_clk_register_periph_clk(nand_ref, clk_output_name[nand_ref], CRL_APB_NAND_REF_CTRL, periph_parents[nand_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(adma_ref, clk_output_name[adma_ref], CRL_APB_ADMA_REF_CTRL, periph_parents[adma_ref], 1, 0, 24); dll_ref_parents[0] = clk_output_name[iopll]; dll_ref_parents[1] = clk_output_name[rpll]; clks[dll_ref] = zynqmp_clk_register_mux(NULL, clk_output_name[dll_ref], dll_ref_parents, 2, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_DLL_REF_CTRL, 0, 3, 0); zynqmp_clk_register_periph_clk(ams_ref, clk_output_name[ams_ref], CRL_APB_AMS_REF_CTRL, periph_parents[ams_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(i2c0_ref, clk_output_name[i2c0_ref], CRL_APB_I2C0_REF_CTRL, periph_parents[i2c0_ref], 1, 1, 24); zynqmp_clk_register_periph_clk(i2c1_ref, clk_output_name[i2c1_ref], CRL_APB_I2C1_REF_CTRL, periph_parents[i2c1_ref], 1, 1, 24); timestamp_ref_parents[0] = clk_output_name[rpll]; timestamp_ref_parents[1] = dummy_nm; timestamp_ref_parents[2] = clk_output_name[iopll]; timestamp_ref_parents[3] = clk_output_name[dpll_to_lpd]; timestamp_ref_parents[4] = input_clks[0]; timestamp_ref_parents[5] = input_clks[0]; timestamp_ref_parents[6] = input_clks[0]; timestamp_ref_parents[7] = input_clks[0]; clk = zynqmp_clk_register_mux(NULL, "timestamp_ref_mux", timestamp_ref_parents, 8, CLK_SET_RATE_NO_REPARENT, (resource_size_t *)CRL_APB_TIMESTAMP_REF_CTRL, 0, 3, 0); clk = zynqmp_clk_register_divider(NULL, "timestamp_ref_div0", "timestamp_ref_mux", 0, (resource_size_t *)CRL_APB_TIMESTAMP_REF_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO); clks[timestamp_ref] = zynqmp_clk_register_gate(NULL, clk_output_name[timestamp_ref], "timestamp_ref_div0", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, (resource_size_t *)CRL_APB_TIMESTAMP_REF_CTRL, 24, 0); for (i = 0; i < ARRAY_SIZE(clks); i++) { if (IS_ERR(clks[i])) { pr_err("Zynq Ultrascale+ MPSoC clk %d: register failed with %ld\n", i, PTR_ERR(clks[i])); BUG(); } } clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); }
static void __init zynq_clk_setup(struct device_node *np) { int i; u32 tmp; int ret; struct clk *clk; char *clk_name; const char *clk_output_name[clk_max]; const char *cpu_parents[4]; const char *periph_parents[4]; const char *swdt_ext_clk_mux_parents[2]; const char *can_mio_mux_parents[NUM_MIO_PINS]; pr_info("Zynq clock init\n"); /* get clock output names from DT */ for (i = 0; i < clk_max; i++) { if (of_property_read_string_index(np, "clock-output-names", i, &clk_output_name[i])) { pr_err("%s: clock output name not in DT\n", __func__); BUG(); } } cpu_parents[0] = clk_output_name[armpll]; cpu_parents[1] = clk_output_name[armpll]; cpu_parents[2] = clk_output_name[ddrpll]; cpu_parents[3] = clk_output_name[iopll]; periph_parents[0] = clk_output_name[iopll]; periph_parents[1] = clk_output_name[iopll]; periph_parents[2] = clk_output_name[armpll]; periph_parents[3] = clk_output_name[ddrpll]; /* ps_clk */ ret = of_property_read_u32(np, "ps-clk-frequency", &tmp); if (ret) { pr_warn("ps_clk frequency not specified, using 33 MHz.\n"); tmp = 33333333; } ps_clk = clk_register_fixed_rate(NULL, "ps_clk", NULL, CLK_IS_ROOT, tmp); /* PLLs */ clk = clk_register_zynq_pll("armpll_int", "ps_clk", SLCR_ARMPLL_CTRL, SLCR_PLL_STATUS, 0, &armpll_lock); clks[armpll] = clk_register_mux(NULL, clk_output_name[armpll], armpll_parents, 2, 0, SLCR_ARMPLL_CTRL, 4, 1, 0, &armpll_lock); clk = clk_register_zynq_pll("ddrpll_int", "ps_clk", SLCR_DDRPLL_CTRL, SLCR_PLL_STATUS, 1, &ddrpll_lock); clks[ddrpll] = clk_register_mux(NULL, clk_output_name[ddrpll], ddrpll_parents, 2, 0, SLCR_DDRPLL_CTRL, 4, 1, 0, &ddrpll_lock); clk = clk_register_zynq_pll("iopll_int", "ps_clk", SLCR_IOPLL_CTRL, SLCR_PLL_STATUS, 2, &iopll_lock); clks[iopll] = clk_register_mux(NULL, clk_output_name[iopll], iopll_parents, 2, 0, SLCR_IOPLL_CTRL, 4, 1, 0, &iopll_lock); /* CPU clocks */ tmp = readl(SLCR_621_TRUE) & 1; clk = clk_register_mux(NULL, "cpu_mux", cpu_parents, 4, 0, SLCR_ARM_CLK_CTRL, 4, 2, 0, &armclk_lock); clk = clk_register_divider(NULL, "cpu_div", "cpu_mux", 0, SLCR_ARM_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &armclk_lock); clks[cpu_6or4x] = clk_register_gate(NULL, clk_output_name[cpu_6or4x], "cpu_div", CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, 24, 0, &armclk_lock); clk = clk_register_fixed_factor(NULL, "cpu_3or2x_div", "cpu_div", 0, 1, 2); clks[cpu_3or2x] = clk_register_gate(NULL, clk_output_name[cpu_3or2x], "cpu_3or2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, 25, 0, &armclk_lock); clk = clk_register_fixed_factor(NULL, "cpu_2x_div", "cpu_div", 0, 1, 2 + tmp); clks[cpu_2x] = clk_register_gate(NULL, clk_output_name[cpu_2x], "cpu_2x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, 26, 0, &armclk_lock); clk = clk_register_fixed_factor(NULL, "cpu_1x_div", "cpu_div", 0, 1, 4 + 2 * tmp); clks[cpu_1x] = clk_register_gate(NULL, clk_output_name[cpu_1x], "cpu_1x_div", CLK_IGNORE_UNUSED, SLCR_ARM_CLK_CTRL, 27, 0, &armclk_lock); /* Timers */ swdt_ext_clk_mux_parents[0] = clk_output_name[cpu_1x]; for (i = 0; i < ARRAY_SIZE(swdt_ext_clk_input_names); i++) { int idx = of_property_match_string(np, "clock-names", swdt_ext_clk_input_names[i]); if (idx >= 0) swdt_ext_clk_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); else swdt_ext_clk_mux_parents[i + 1] = dummy_nm; } clks[swdt] = clk_register_mux(NULL, clk_output_name[swdt], swdt_ext_clk_mux_parents, 2, CLK_SET_RATE_PARENT, SLCR_SWDT_CLK_SEL, 0, 1, 0, &swdtclk_lock); /* DDR clocks */ clk = clk_register_divider(NULL, "ddr2x_div", "ddrpll", 0, SLCR_DDR_CLK_CTRL, 26, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &ddrclk_lock); clks[ddr2x] = clk_register_gate(NULL, clk_output_name[ddr2x], "ddr2x_div", 0, SLCR_DDR_CLK_CTRL, 1, 0, &ddrclk_lock); clk_prepare_enable(clks[ddr2x]); clk = clk_register_divider(NULL, "ddr3x_div", "ddrpll", 0, SLCR_DDR_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &ddrclk_lock); clks[ddr3x] = clk_register_gate(NULL, clk_output_name[ddr3x], "ddr3x_div", 0, SLCR_DDR_CLK_CTRL, 0, 0, &ddrclk_lock); clk_prepare_enable(clks[ddr3x]); clk = clk_register_divider(NULL, "dci_div0", "ddrpll", 0, SLCR_DCI_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &dciclk_lock); clk = clk_register_divider(NULL, "dci_div1", "dci_div0", CLK_SET_RATE_PARENT, SLCR_DCI_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &dciclk_lock); clks[dci] = clk_register_gate(NULL, clk_output_name[dci], "dci_div1", CLK_SET_RATE_PARENT, SLCR_DCI_CLK_CTRL, 0, 0, &dciclk_lock); clk_prepare_enable(clks[dci]); /* Peripheral clocks */ for (i = fclk0; i <= fclk3; i++) zynq_clk_register_fclk(i, clk_output_name[i], SLCR_FPGA0_CLK_CTRL + 0x10 * (i - fclk0), periph_parents); zynq_clk_register_periph_clk(lqspi, 0, clk_output_name[lqspi], NULL, SLCR_LQSPI_CLK_CTRL, periph_parents, 0); zynq_clk_register_periph_clk(smc, 0, clk_output_name[smc], NULL, SLCR_SMC_CLK_CTRL, periph_parents, 0); zynq_clk_register_periph_clk(pcap, 0, clk_output_name[pcap], NULL, SLCR_PCAP_CLK_CTRL, periph_parents, 0); zynq_clk_register_periph_clk(sdio0, sdio1, clk_output_name[sdio0], clk_output_name[sdio1], SLCR_SDIO_CLK_CTRL, periph_parents, 1); zynq_clk_register_periph_clk(uart0, uart1, clk_output_name[uart0], clk_output_name[uart1], SLCR_UART_CLK_CTRL, periph_parents, 1); zynq_clk_register_periph_clk(spi0, spi1, clk_output_name[spi0], clk_output_name[spi1], SLCR_SPI_CLK_CTRL, periph_parents, 1); for (i = 0; i < ARRAY_SIZE(gem0_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem0_emio_input_names[i]); if (idx >= 0) gem0_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = clk_register_mux(NULL, "gem0_mux", periph_parents, 4, 0, SLCR_GEM0_CLK_CTRL, 4, 2, 0, &gem0clk_lock); clk = clk_register_divider(NULL, "gem0_div0", "gem0_mux", 0, SLCR_GEM0_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock); clk = clk_register_divider(NULL, "gem0_div1", "gem0_div0", CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem0clk_lock); clk = clk_register_mux(NULL, "gem0_emio_mux", gem0_mux_parents, 2, CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 6, 1, 0, &gem0clk_lock); clks[gem0] = clk_register_gate(NULL, clk_output_name[gem0], "gem0_emio_mux", CLK_SET_RATE_PARENT, SLCR_GEM0_CLK_CTRL, 0, 0, &gem0clk_lock); for (i = 0; i < ARRAY_SIZE(gem1_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", gem1_emio_input_names[i]); if (idx >= 0) gem1_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = clk_register_mux(NULL, "gem1_mux", periph_parents, 4, 0, SLCR_GEM1_CLK_CTRL, 4, 2, 0, &gem1clk_lock); clk = clk_register_divider(NULL, "gem1_div0", "gem1_mux", 0, SLCR_GEM1_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock); clk = clk_register_divider(NULL, "gem1_div1", "gem1_div0", CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &gem1clk_lock); clk = clk_register_mux(NULL, "gem1_emio_mux", gem1_mux_parents, 2, CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 6, 1, 0, &gem1clk_lock); clks[gem1] = clk_register_gate(NULL, clk_output_name[gem1], "gem1_emio_mux", CLK_SET_RATE_PARENT, SLCR_GEM1_CLK_CTRL, 0, 0, &gem1clk_lock); tmp = strlen("mio_clk_00x"); clk_name = kmalloc(tmp, GFP_KERNEL); for (i = 0; i < NUM_MIO_PINS; i++) { int idx; snprintf(clk_name, tmp, "mio_clk_%2.2d", i); idx = of_property_match_string(np, "clock-names", clk_name); if (idx >= 0) can_mio_mux_parents[i] = of_clk_get_parent_name(np, idx); else can_mio_mux_parents[i] = dummy_nm; } kfree(clk_name); clk = clk_register_mux(NULL, "can_mux", periph_parents, 4, 0, SLCR_CAN_CLK_CTRL, 4, 2, 0, &canclk_lock); clk = clk_register_divider(NULL, "can_div0", "can_mux", 0, SLCR_CAN_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &canclk_lock); clk = clk_register_divider(NULL, "can_div1", "can_div0", CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 20, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &canclk_lock); clk = clk_register_gate(NULL, "can0_gate", "can_div1", CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 0, 0, &canclk_lock); clk = clk_register_gate(NULL, "can1_gate", "can_div1", CLK_SET_RATE_PARENT, SLCR_CAN_CLK_CTRL, 1, 0, &canclk_lock); clk = clk_register_mux(NULL, "can0_mio_mux", can_mio_mux_parents, 54, CLK_SET_RATE_PARENT, SLCR_CAN_MIOCLK_CTRL, 0, 6, 0, &canmioclk_lock); clk = clk_register_mux(NULL, "can1_mio_mux", can_mio_mux_parents, 54, CLK_SET_RATE_PARENT, SLCR_CAN_MIOCLK_CTRL, 16, 6, 0, &canmioclk_lock); clks[can0] = clk_register_mux(NULL, clk_output_name[can0], can0_mio_mux2_parents, 2, CLK_SET_RATE_PARENT, SLCR_CAN_MIOCLK_CTRL, 6, 1, 0, &canmioclk_lock); clks[can1] = clk_register_mux(NULL, clk_output_name[can1], can1_mio_mux2_parents, 2, CLK_SET_RATE_PARENT, SLCR_CAN_MIOCLK_CTRL, 22, 1, 0, &canmioclk_lock); for (i = 0; i < ARRAY_SIZE(dbgtrc_emio_input_names); i++) { int idx = of_property_match_string(np, "clock-names", dbgtrc_emio_input_names[i]); if (idx >= 0) dbg_emio_mux_parents[i + 1] = of_clk_get_parent_name(np, idx); } clk = clk_register_mux(NULL, "dbg_mux", periph_parents, 4, 0, SLCR_DBG_CLK_CTRL, 4, 2, 0, &dbgclk_lock); clk = clk_register_divider(NULL, "dbg_div", "dbg_mux", 0, SLCR_DBG_CLK_CTRL, 8, 6, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, &dbgclk_lock); clk = clk_register_mux(NULL, "dbg_emio_mux", dbg_emio_mux_parents, 2, 0, SLCR_DBG_CLK_CTRL, 6, 1, 0, &dbgclk_lock); clks[dbg_trc] = clk_register_gate(NULL, clk_output_name[dbg_trc], "dbg_emio_mux", CLK_SET_RATE_PARENT, SLCR_DBG_CLK_CTRL, 0, 0, &dbgclk_lock); clks[dbg_apb] = clk_register_gate(NULL, clk_output_name[dbg_apb], clk_output_name[cpu_1x], 0, SLCR_DBG_CLK_CTRL, 1, 0, &dbgclk_lock); /* One gated clock for all APER clocks. */ clks[dma] = clk_register_gate(NULL, clk_output_name[dma], clk_output_name[cpu_2x], 0, SLCR_APER_CLK_CTRL, 0, 0, &aperclk_lock); clks[usb0_aper] = clk_register_gate(NULL, clk_output_name[usb0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 2, 0, &aperclk_lock); clks[usb1_aper] = clk_register_gate(NULL, clk_output_name[usb1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 3, 0, &aperclk_lock); clks[gem0_aper] = clk_register_gate(NULL, clk_output_name[gem0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 6, 0, &aperclk_lock); clks[gem1_aper] = clk_register_gate(NULL, clk_output_name[gem1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 7, 0, &aperclk_lock); clks[sdio0_aper] = clk_register_gate(NULL, clk_output_name[sdio0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 10, 0, &aperclk_lock); clks[sdio1_aper] = clk_register_gate(NULL, clk_output_name[sdio1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 11, 0, &aperclk_lock); clks[spi0_aper] = clk_register_gate(NULL, clk_output_name[spi0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 14, 0, &aperclk_lock); clks[spi1_aper] = clk_register_gate(NULL, clk_output_name[spi1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 15, 0, &aperclk_lock); clks[can0_aper] = clk_register_gate(NULL, clk_output_name[can0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 16, 0, &aperclk_lock); clks[can1_aper] = clk_register_gate(NULL, clk_output_name[can1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 17, 0, &aperclk_lock); clks[i2c0_aper] = clk_register_gate(NULL, clk_output_name[i2c0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 18, 0, &aperclk_lock); clks[i2c1_aper] = clk_register_gate(NULL, clk_output_name[i2c1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 19, 0, &aperclk_lock); clks[uart0_aper] = clk_register_gate(NULL, clk_output_name[uart0_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 20, 0, &aperclk_lock); clks[uart1_aper] = clk_register_gate(NULL, clk_output_name[uart1_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 21, 0, &aperclk_lock); clks[gpio_aper] = clk_register_gate(NULL, clk_output_name[gpio_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 22, 0, &aperclk_lock); clks[lqspi_aper] = clk_register_gate(NULL, clk_output_name[lqspi_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 23, 0, &aperclk_lock); clks[smc_aper] = clk_register_gate(NULL, clk_output_name[smc_aper], clk_output_name[cpu_1x], 0, SLCR_APER_CLK_CTRL, 24, 0, &aperclk_lock); for (i = 0; i < ARRAY_SIZE(clks); i++) { if (IS_ERR(clks[i])) { pr_err("Zynq clk %d: register failed with %ld\n", i, PTR_ERR(clks[i])); BUG(); } } clk_data.clks = clks; clk_data.clk_num = ARRAY_SIZE(clks); of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); }
/** * of_ti_dpll_setup - Setup function for OMAP DPLL clocks * @node: device node containing the DPLL info * @ops: ops for the DPLL * @ddt: DPLL data template to use * * Initializes a DPLL clock from device tree data. */ static void __init of_ti_dpll_setup(struct device_node *node, const struct clk_ops *ops, const struct dpll_data *ddt) { struct clk_hw_omap *clk_hw = NULL; struct clk_init_data *init = NULL; const char **parent_names = NULL; struct dpll_data *dd = NULL; int i; u8 dpll_mode = 0; dd = kzalloc(sizeof(*dd), GFP_KERNEL); clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL); init = kzalloc(sizeof(*init), GFP_KERNEL); if (!dd || !clk_hw || !init) goto cleanup; memcpy(dd, ddt, sizeof(*dd)); clk_hw->dpll_data = dd; clk_hw->ops = &clkhwops_omap3_dpll; clk_hw->hw.init = init; clk_hw->flags = MEMMAP_ADDRESSING; init->name = node->name; init->ops = ops; init->num_parents = of_clk_get_parent_count(node); if (init->num_parents < 1) { pr_err("%s must have parent(s)\n", node->name); goto cleanup; } parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL); if (!parent_names) goto cleanup; for (i = 0; i < init->num_parents; i++) parent_names[i] = of_clk_get_parent_name(node, i); init->parent_names = parent_names; dd->control_reg = ti_clk_get_reg_addr(node, 0); /* * Special case for OMAP2 DPLL, register order is different due to * missing idlest_reg, also clkhwops is different. Detected from * missing idlest_mask. */ if (!dd->idlest_mask) { dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1); #ifdef CONFIG_ARCH_OMAP2 clk_hw->ops = &clkhwops_omap2xxx_dpll; omap2xxx_clkt_dpllcore_init(&clk_hw->hw); #endif } else { dd->idlest_reg = ti_clk_get_reg_addr(node, 1); if (IS_ERR(dd->idlest_reg)) goto cleanup; dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2); } if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg)) goto cleanup; if (dd->autoidle_mask) { dd->autoidle_reg = ti_clk_get_reg_addr(node, 3); if (IS_ERR(dd->autoidle_reg)) goto cleanup; } if (of_property_read_bool(node, "ti,low-power-stop")) dpll_mode |= 1 << DPLL_LOW_POWER_STOP; if (of_property_read_bool(node, "ti,low-power-bypass")) dpll_mode |= 1 << DPLL_LOW_POWER_BYPASS; if (of_property_read_bool(node, "ti,lock")) dpll_mode |= 1 << DPLL_LOCKED; if (dpll_mode) dd->modes = dpll_mode; _register_dpll(&clk_hw->hw, node); return; cleanup: kfree(dd); kfree(parent_names); kfree(init); kfree(clk_hw); }
static void __init zynq_periph_clk_setup(struct device_node *np) { struct zynq_periph_clk *periph; const char *parent_names[3]; struct clk_init_data init; int clk_num = 0, err; const char *name; struct clk *clk; u32 reg; int i; err = of_property_read_u32(np, "reg", ®); if (WARN_ON(err)) return; periph = kzalloc(sizeof(*periph), GFP_KERNEL); if (WARN_ON(!periph)) return; periph->clk_ctrl = slcr_base + reg; spin_lock_init(&periph->clkact_lock); init.name = np->name; init.ops = &zynq_periph_clk_ops; for (i = 0; i < ARRAY_SIZE(parent_names); i++) parent_names[i] = of_clk_get_parent_name(np, i); init.parent_names = parent_names; init.num_parents = ARRAY_SIZE(parent_names); periph->hw.init = &init; clk = clk_register(NULL, &periph->hw); if (WARN_ON(IS_ERR(clk))) return; err = of_clk_add_provider(np, of_clk_src_simple_get, clk); if (WARN_ON(err)) return; err = of_property_read_string_index(np, "clock-output-names", 0, &name); if (WARN_ON(err)) return; periph->gates[0] = clk_register_gate(NULL, name, np->name, 0, periph->clk_ctrl, 0, 0, &periph->clkact_lock); if (WARN_ON(IS_ERR(periph->gates[0]))) return; clk_num++; /* some periph clks have 2 downstream gates */ err = of_property_read_string_index(np, "clock-output-names", 1, &name); if (err != -ENODATA) { periph->gates[1] = clk_register_gate(NULL, name, np->name, 0, periph->clk_ctrl, 1, 0, &periph->clkact_lock); if (WARN_ON(IS_ERR(periph->gates[1]))) return; clk_num++; } periph->onecell_data.clks = periph->gates; periph->onecell_data.clk_num = clk_num; err = of_clk_add_provider(np, of_clk_src_onecell_get, &periph->onecell_data); if (WARN_ON(err)) return; }