brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · 77c22ce Raw
119 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2012, 2013, NVIDIA CORPORATION.  All rights reserved.4 */5 6#include <linux/io.h>7#include <linux/clk-provider.h>8#include <linux/of.h>9#include <linux/of_address.h>10#include <linux/delay.h>11#include <linux/export.h>12#include <linux/clk/tegra.h>13 14#include "clk.h"15#include "clk-id.h"16 17#define OSC_CTRL			0x5018#define OSC_CTRL_OSC_FREQ_SHIFT		2819#define OSC_CTRL_PLL_REF_DIV_SHIFT	2620#define OSC_CTRL_MASK			(0x3f2 |	\21					(0xf << OSC_CTRL_OSC_FREQ_SHIFT))22 23static u32 osc_ctrl_ctx;24 25int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks,26			      unsigned long *input_freqs, unsigned int num,27			      unsigned int clk_m_div, unsigned long *osc_freq,28			      unsigned long *pll_ref_freq)29{30	struct clk *clk, *osc;31	struct clk **dt_clk;32	u32 val, pll_ref_div;33	unsigned osc_idx;34 35	val = readl_relaxed(clk_base + OSC_CTRL);36	osc_ctrl_ctx = val & OSC_CTRL_MASK;37	osc_idx = val >> OSC_CTRL_OSC_FREQ_SHIFT;38 39	if (osc_idx < num)40		*osc_freq = input_freqs[osc_idx];41	else42		*osc_freq = 0;43 44	if (!*osc_freq) {45		WARN_ON(1);46		return -EINVAL;47	}48 49	dt_clk = tegra_lookup_dt_id(tegra_clk_osc, clks);50	if (!dt_clk)51		return 0;52 53	osc = clk_register_fixed_rate(NULL, "osc", NULL, 0, *osc_freq);54	*dt_clk = osc;55 56	/* osc_div2 */57	dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div2, clks);58	if (dt_clk) {59		clk = clk_register_fixed_factor(NULL, "osc_div2", "osc",60						0, 1, 2);61		*dt_clk = clk;62	}63 64	/* osc_div4 */65	dt_clk = tegra_lookup_dt_id(tegra_clk_osc_div4, clks);66	if (dt_clk) {67		clk = clk_register_fixed_factor(NULL, "osc_div4", "osc",68						0, 1, 4);69		*dt_clk = clk;70	}71 72	dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, clks);73	if (!dt_clk)74		return 0;75 76	clk = clk_register_fixed_factor(NULL, "clk_m", "osc",77					0, 1, clk_m_div);78	*dt_clk = clk;79 80	/* pll_ref */81	val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;82	pll_ref_div = 1 << val;83	dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, clks);84	if (!dt_clk)85		return 0;86 87	clk = clk_register_fixed_factor(NULL, "pll_ref", "osc",88					0, 1, pll_ref_div);89	*dt_clk = clk;90 91	if (pll_ref_freq)92		*pll_ref_freq = *osc_freq / pll_ref_div;93 94	return 0;95}96 97void __init tegra_fixed_clk_init(struct tegra_clk *tegra_clks)98{99	struct clk *clk;100	struct clk **dt_clk;101 102	/* clk_32k */103	dt_clk = tegra_lookup_dt_id(tegra_clk_clk_32k, tegra_clks);104	if (dt_clk) {105		clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, 0, 32768);106		*dt_clk = clk;107	}108}109 110void tegra_clk_osc_resume(void __iomem *clk_base)111{112	u32 val;113 114	val = readl_relaxed(clk_base + OSC_CTRL) & ~OSC_CTRL_MASK;115	val |= osc_ctrl_ctx;116	writel_relaxed(val, clk_base + OSC_CTRL);117	fence_udelay(2, clk_base);118}119