1ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/*
2ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Nomadik clock implementation
3ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Copyright (C) 2013 ST-Ericsson AB
4ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * License terms: GNU General Public License (GPL) version 2
5ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Author: Linus Walleij <linus.walleij@linaro.org>
6ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */
7ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
8ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
9ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
10ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/bitops.h>
114a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clk.h>
124a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clkdev.h>
134a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/err.h>
144a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/io.h>
154a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij#include <linux/clk-provider.h>
166e2b07a172b6ed98c7cdc301333b2d9f86c11880Linus Walleij#include <linux/of.h>
17ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/of_address.h>
18ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/debugfs.h>
19ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/seq_file.h>
20ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/spinlock.h>
21ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#include <linux/reboot.h>
224a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij
234a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij/*
244a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij * The Nomadik clock tree is described in the STN8815A12 DB V4.2
254a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij * reference manual for the chip, page 94 ff.
26ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
27ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */
28ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
29ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_CR			0x00U
30eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T0_ENSEL		BIT(15)
31eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T1_ENSEL		BIT(17)
32eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T2_ENSEL		BIT(19)
33eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T3_ENSEL		BIT(21)
34eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T4_ENSEL		BIT(23)
35eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T5_ENSEL		BIT(25)
36eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T6_ENSEL		BIT(27)
37eb6b036dde364c528807f53ee8c8e5c9b0e46c34Linus Walleij#define SRC_CR_T7_ENSEL		BIT(29)
38ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR		0x0CU
39ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_XTALTIMEN	BIT(20)
40ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_SXTALDIS	BIT(19)
41ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALSTAT	BIT(2)
42ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALEN	BIT(1)
43ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_XTALCR_MXTALOVER	BIT(0)
44ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR		0x10U
45ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLLTIMEN	BIT(29)
46ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL2EN	BIT(28)
47ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1STAT	BIT(2)
48ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1EN	BIT(1)
49ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLCR_PLL1OVER	BIT(0)
50ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PLLFR		0x14U
51ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKEN0		0x24U
52ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKDIS0		0x28U
53ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKENSR0		0x2CU
54ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKSR0		0x30U
55ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKEN1		0x34U
56ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKDIS1		0x38U
57ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKENSR1		0x3CU
58ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define SRC_PCKSR1		0x40U
59ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
60ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* Lock protecting the SRC_CR register */
61ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic DEFINE_SPINLOCK(src_lock);
62ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/* Base address of the SRC */
63ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __iomem *src_base;
64ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
65ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarthstatic int nomadik_clk_reboot_handler(struct notifier_block *this,
66ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth				unsigned long code,
67ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth				void *unused)
68ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth{
69ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	u32 val;
70ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
71ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	/* The main chrystal need to be enabled for reboot to work */
72ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val = readl(src_base + SRC_XTALCR);
73ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val &= ~SRC_XTALCR_MXTALOVER;
74ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_XTALCR_MXTALEN;
75ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	pr_crit("force-enabling MXTALO\n");
76ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	writel(val, src_base + SRC_XTALCR);
77ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	return NOTIFY_OK;
78ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth}
79ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
80ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarthstatic struct notifier_block nomadik_clk_reboot_notifier = {
81ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	.notifier_call = nomadik_clk_reboot_handler,
82ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth};
83ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
84ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarthstatic const struct of_device_id nomadik_src_match[] __initconst = {
85ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	{ .compatible = "stericsson,nomadik-src" },
86ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	{ /* sentinel */ }
87ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth};
88ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
8954bf93c49a9a7a395df3a6442c5b6bf428c945cbSebastian Hesselbarthstatic void __init nomadik_src_init(void)
90ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth{
91ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	struct device_node *np;
92ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	u32 val;
93ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
94ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	np = of_find_matching_node(NULL, nomadik_src_match);
95ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	if (!np) {
96ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		pr_crit("no matching node for SRC, aborting clock init\n");
97ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		return;
98ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	}
99ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	src_base = of_iomap(np, 0);
100ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	if (!src_base) {
101ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		pr_err("%s: must have src parent node with REGS (%s)\n",
102ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		       __func__, np->name);
103ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		return;
104ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	}
105ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
106ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	/* Set all timers to use the 2.4 MHz TIMCLK */
107ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val = readl(src_base + SRC_CR);
108ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T0_ENSEL;
109ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T1_ENSEL;
110ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T2_ENSEL;
111ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T3_ENSEL;
112ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T4_ENSEL;
113ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T5_ENSEL;
114ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T6_ENSEL;
115ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val |= SRC_CR_T7_ENSEL;
116ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	writel(val, src_base + SRC_CR);
117ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
118ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	val = readl(src_base + SRC_XTALCR);
119ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	pr_info("SXTALO is %s\n",
120ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		(val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
121ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	pr_info("MXTAL is %s\n",
122ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		(val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
123ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	if (of_property_read_bool(np, "disable-sxtalo")) {
124ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		/* The machine uses an external oscillator circuit */
125ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		val |= SRC_XTALCR_SXTALDIS;
126ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		pr_info("disabling SXTALO\n");
127ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	}
128ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	if (of_property_read_bool(np, "disable-mxtalo")) {
129ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		/* Disable this too: also run by external oscillator */
130ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		val |= SRC_XTALCR_MXTALOVER;
131ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		val &= ~SRC_XTALCR_MXTALEN;
132ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth		pr_info("disabling MXTALO\n");
133ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	}
134ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	writel(val, src_base + SRC_XTALCR);
135ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth	register_reboot_notifier(&nomadik_clk_reboot_notifier);
136ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth}
137ea25a900f593cd34347ec884b3acac09ffe07667Sebastian Hesselbarth
138ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/**
139ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * struct clk_pll1 - Nomadik PLL1 clock
140ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @hw: corresponding clock hardware entry
141ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @id: PLL instance: 1 or 2
142ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */
143ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstruct clk_pll {
144ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_hw hw;
145ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	int id;
146ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
147ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
148ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/**
149ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * struct clk_src - Nomadik src clock
150ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @hw: corresponding clock hardware entry
151ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @id: the clock ID
152ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @group1: true if the clock is in group1, else it is in group0
153ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * @clkbit: bit 0...31 corresponding to the clock in each clock register
154ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij */
155ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstruct clk_src {
156ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_hw hw;
157ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	int id;
158ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	bool group1;
159ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 clkbit;
160ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
161ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
162ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define to_pll(_hw) container_of(_hw, struct clk_pll, hw)
163ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#define to_src(_hw) container_of(_hw, struct clk_src, hw)
164ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
165ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int pll_clk_enable(struct clk_hw *hw)
166ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
167ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_pll *pll = to_pll(hw);
168ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 val;
169ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
170ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	spin_lock(&src_lock);
171ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	val = readl(src_base + SRC_PLLCR);
172ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (pll->id == 1) {
173ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		if (val & SRC_PLLCR_PLL1OVER) {
174ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			val |= SRC_PLLCR_PLL1EN;
175ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			writel(val, src_base + SRC_PLLCR);
176ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		}
177ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	} else if (pll->id == 2) {
178ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		val |= SRC_PLLCR_PLL2EN;
179ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		writel(val, src_base + SRC_PLLCR);
180ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
181ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	spin_unlock(&src_lock);
182ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 0;
183ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
184ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
185ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void pll_clk_disable(struct clk_hw *hw)
186ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
187ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_pll *pll = to_pll(hw);
188ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 val;
189ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
190ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	spin_lock(&src_lock);
191ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	val = readl(src_base + SRC_PLLCR);
192ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (pll->id == 1) {
193ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		if (val & SRC_PLLCR_PLL1OVER) {
194ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			val &= ~SRC_PLLCR_PLL1EN;
195ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			writel(val, src_base + SRC_PLLCR);
196ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		}
197ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	} else if (pll->id == 2) {
198ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		val &= ~SRC_PLLCR_PLL2EN;
199ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		writel(val, src_base + SRC_PLLCR);
200ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
201ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	spin_unlock(&src_lock);
202ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
203ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
204ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int pll_clk_is_enabled(struct clk_hw *hw)
205ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
206ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_pll *pll = to_pll(hw);
207ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 val;
208ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
209ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	val = readl(src_base + SRC_PLLCR);
210ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (pll->id == 1) {
211ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		if (val & SRC_PLLCR_PLL1OVER)
212ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			return !!(val & SRC_PLLCR_PLL1EN);
213ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	} else if (pll->id == 2) {
214ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return !!(val & SRC_PLLCR_PLL2EN);
215ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
216ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 1;
217ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
218ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
219ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
220ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij					  unsigned long parent_rate)
221ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
222ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_pll *pll = to_pll(hw);
223ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 val;
224ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
225ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	val = readl(src_base + SRC_PLLFR);
226ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
227ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (pll->id == 1) {
228ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u8 mul;
229ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u8 div;
230ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
231ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		mul = (val >> 8) & 0x3FU;
232ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		mul += 2;
233ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		div = val & 0x07U;
234ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return (parent_rate * mul) >> div;
235ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
236ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
237ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (pll->id == 2) {
238ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u8 mul;
239ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
240ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		mul = (val >> 24) & 0x3FU;
241ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		mul += 2;
242ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return (parent_rate * mul);
243ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
244ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
245ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	/* Unknown PLL */
246ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 0;
247ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
248ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
249ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
250ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct clk_ops pll_clk_ops = {
251ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.enable = pll_clk_enable,
252ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.disable = pll_clk_disable,
253ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.is_enabled = pll_clk_is_enabled,
254ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.recalc_rate = pll_clk_recalc_rate,
255ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
256ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
257ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic struct clk * __init
258ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijpll_clk_register(struct device *dev, const char *name,
259ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		 const char *parent_name, u32 id)
260ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
261ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk *clk;
262ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_pll *pll;
263ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_init_data init;
264ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
265ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (id != 1 && id != 2) {
266ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__);
267ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return ERR_PTR(-EINVAL);
268ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
269ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
270ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
271ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (!pll) {
272ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		pr_err("%s: could not allocate PLL clk\n", __func__);
273ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return ERR_PTR(-ENOMEM);
274ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
275ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
276ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.name = name;
277ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.ops = &pll_clk_ops;
278ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.parent_names = (parent_name ? &parent_name : NULL);
279ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.num_parents = (parent_name ? 1 : 0);
280ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	pll->hw.init = &init;
281ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	pll->id = id;
282ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
283ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	pr_debug("register PLL1 clock \"%s\"\n", name);
284ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
285ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	clk = clk_register(dev, &pll->hw);
286ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (IS_ERR(clk))
287ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		kfree(pll);
288ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
289ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return clk;
290ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
291ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
292ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij/*
293ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * The Nomadik SRC clocks are gated, but not in the sense that
294ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * you read-modify-write a register. Instead there are separate
295ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * clock enable and clock disable registers. Writing a '1' bit in
296ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * the enable register for a certain clock ungates that clock without
297ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * affecting the other clocks. The disable register works the opposite
298ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij * way.
2994a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij */
3004a31bd28e86ac50eb620f6b5b36464c45b5fa38fLinus Walleij
301ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int src_clk_enable(struct clk_hw *hw)
302ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
303ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_src *sclk = to_src(hw);
304ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0;
305ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
306ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
307ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	writel(sclk->clkbit, src_base + enreg);
308ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	/* spin until enabled */
309ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	while (!(readl(src_base + sreg) & sclk->clkbit))
310ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		cpu_relax();
311ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 0;
312ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
313ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
314ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void src_clk_disable(struct clk_hw *hw)
315ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
316ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_src *sclk = to_src(hw);
317ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0;
318ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
319ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
320ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	writel(sclk->clkbit, src_base + disreg);
321ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	/* spin until disabled */
322ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	while (readl(src_base + sreg) & sclk->clkbit)
323ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		cpu_relax();
324ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
325ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
326ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int src_clk_is_enabled(struct clk_hw *hw)
327ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
328ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_src *sclk = to_src(hw);
329ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
330ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 val = readl(src_base + sreg);
331ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
332ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return !!(val & sclk->clkbit);
333ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
334ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
335ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic unsigned long
336ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijsrc_clk_recalc_rate(struct clk_hw *hw,
337ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		    unsigned long parent_rate)
338ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
339ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return parent_rate;
340ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
341ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
342ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct clk_ops src_clk_ops = {
343ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.enable = src_clk_enable,
344ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.disable = src_clk_disable,
345ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.is_enabled = src_clk_is_enabled,
346ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.recalc_rate = src_clk_recalc_rate,
347ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
348ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
349ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic struct clk * __init
350ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijsrc_clk_register(struct device *dev, const char *name,
351ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		 const char *parent_name, u8 id)
352ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
353ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk *clk;
354ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_src *sclk;
355ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk_init_data init;
356ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
357ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
358ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (!sclk) {
359ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		pr_err("could not allocate SRC clock %s\n",
360ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			name);
361ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return ERR_PTR(-ENOMEM);
362ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
363ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.name = name;
364ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.ops = &src_clk_ops;
365ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	/* Do not force-disable the static SDRAM controller */
366ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (id == 2)
367ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		init.flags = CLK_IGNORE_UNUSED;
368ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	else
369ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		init.flags = 0;
370ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.parent_names = (parent_name ? &parent_name : NULL);
371ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	init.num_parents = (parent_name ? 1 : 0);
372ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	sclk->hw.init = &init;
373ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	sclk->id = id;
374ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	sclk->group1 = (id > 31);
375ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	sclk->clkbit = BIT(id & 0x1f);
376ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
377ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
378ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		 name, id, sclk->group1, sclk->clkbit);
379ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
380ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	clk = clk_register(dev, &sclk->hw);
381ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (IS_ERR(clk))
382ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		kfree(sclk);
383ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
384ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return clk;
385ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
386ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
387ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#ifdef CONFIG_DEBUG_FS
388ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
389ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic u32 src_pcksr0_boot;
390ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic u32 src_pcksr1_boot;
391ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
392ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const char * const src_clk_names[] = {
393ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKDMA0  ",
394ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKSMC   ",
395ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKSDRAM ",
396ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKDMA1  ",
397ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKCLCD  ",
398ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKIRDA  ",
399ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKSSP   ",
400ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKUART0 ",
401ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKSDI   ",
402ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKI2C0  ",
403ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKI2C1  ",
404ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKUART1 ",
405ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLMSP0   ",
406ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKUSB   ",
407ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKDIF   ",
408ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKSAA   ",
409ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKSVA   ",
410ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKHSI   ",
411ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKXTI   ",
412ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKUART2 ",
413ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKMSP1  ",
414ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKMSP2  ",
415ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKOWM   ",
416ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKHPI   ",
417ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKSKE   ",
418ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKHSEM  ",
419ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLK3D    ",
420ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKHASH  ",
421ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKCRYP  ",
422ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKMSHC  ",
423ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKUSBM  ",
424ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HCLKRNG   ",
425ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
426ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
427ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
428ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
429ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"CLDCLK    ",
430ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"IRDACLK   ",
431ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"SSPICLK   ",
432ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"UART0CLK  ",
433ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"SDICLK    ",
434ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"I2C0CLK   ",
435ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"I2C1CLK   ",
436ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"UART1CLK  ",
437ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"MSPCLK0   ",
438ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"USBCLK    ",
439ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"DIFCLK    ",
440ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"IPI2CCLK  ",
441ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"IPBMCCLK  ",
442ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HSICLKRX  ",
443ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"HSICLKTX  ",
444ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"UART2CLK  ",
445ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"MSPCLK1   ",
446ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"MSPCLK2   ",
447ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"OWMCLK    ",
448ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
449ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"SKECLK    ",
450ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RESERVED  ",
451ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"3DCLK     ",
452ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"PCLKMSP3  ",
453ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"MSPCLK3   ",
454ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"MSHCCLK   ",
455ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"USBMCLK   ",
456ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	"RNGCCLK   ",
457ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
458ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
459ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int nomadik_src_clk_show(struct seq_file *s, void *what)
460ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
461ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	int i;
462ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 src_pcksr0 = readl(src_base + SRC_PCKSR0);
463ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 src_pcksr1 = readl(src_base + SRC_PCKSR1);
464ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
465ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
466ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
467ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	seq_printf(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
468ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
469ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
470ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
471ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1;
472ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		u32 mask = BIT(i & 0x1f);
473ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
474ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		seq_printf(s, "%s  %s     %s     %s\n",
475ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   src_clk_names[i],
476ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   (pcksrb & mask) ? "on " : "off",
477ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   (pcksr & mask) ? "on " : "off",
478ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   (pckreq & mask) ? "on " : "off");
479ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
480ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 0;
481ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
482ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
483ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int nomadik_src_clk_open(struct inode *inode, struct file *file)
484ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
485ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return single_open(file, nomadik_src_clk_show, NULL);
486ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
487ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
488ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic const struct file_operations nomadik_src_clk_debugfs_ops = {
489ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.open           = nomadik_src_clk_open,
490ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.read           = seq_read,
491ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij        .llseek         = seq_lseek,
492ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	.release        = single_release,
493ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij};
494ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
495ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic int __init nomadik_src_clk_init_debugfs(void)
496ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
497ec6deea1a147a10baf1672dc66025a13bc259680Linus Walleij	/* Vital for multiplatform */
498ec6deea1a147a10baf1672dc66025a13bc259680Linus Walleij	if (!src_base)
499ec6deea1a147a10baf1672dc66025a13bc259680Linus Walleij		return -ENODEV;
500ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
501ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
502ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
503ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			    NULL, NULL, &nomadik_src_clk_debugfs_ops);
504ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	return 0;
505ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
506ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
507ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijmodule_init(nomadik_src_clk_init_debugfs);
508ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
509ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij#endif
510ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
511ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_pll_setup(struct device_node *np)
512ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
513ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk *clk = ERR_PTR(-EINVAL);
514ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *clk_name = np->name;
515ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *parent_name;
516ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 pll_id;
517ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
51874227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	if (!src_base)
51974227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth		nomadik_src_init();
52074227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth
521ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (of_property_read_u32(np, "pll-id", &pll_id)) {
522ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		pr_err("%s: PLL \"%s\" missing pll-id property\n",
523ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			__func__, clk_name);
524ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return;
525ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
526ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	parent_name = of_clk_get_parent_name(np, 0);
527ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	clk = pll_clk_register(NULL, clk_name, parent_name, pll_id);
528ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (!IS_ERR(clk))
529ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		of_clk_add_provider(np, of_clk_src_simple_get, clk);
530ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
53174227e65f9742f559f6e243ba2c9a983e1f1221dSebastian HesselbarthCLK_OF_DECLARE(nomadik_pll_clk,
53274227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	"st,nomadik-pll-clock", of_nomadik_pll_setup);
533ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
534ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_hclk_setup(struct device_node *np)
535ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
536ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk *clk = ERR_PTR(-EINVAL);
537ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *clk_name = np->name;
538ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *parent_name;
539ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
54074227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	if (!src_base)
54174227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth		nomadik_src_init();
54274227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth
543ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	parent_name = of_clk_get_parent_name(np, 0);
544ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	/*
545ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	 * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
546ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	 */
547ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	clk = clk_register_divider(NULL, clk_name, parent_name,
548ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   0, src_base + SRC_CR,
549ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   13, 2,
550ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
551ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			   &src_lock);
552ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (!IS_ERR(clk))
553ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		of_clk_add_provider(np, of_clk_src_simple_get, clk);
554ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
55574227e65f9742f559f6e243ba2c9a983e1f1221dSebastian HesselbarthCLK_OF_DECLARE(nomadik_hclk_clk,
55674227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	"st,nomadik-hclk-clock", of_nomadik_hclk_setup);
557ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
558ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleijstatic void __init of_nomadik_src_clk_setup(struct device_node *np)
559ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij{
560ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	struct clk *clk = ERR_PTR(-EINVAL);
561ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *clk_name = np->name;
562ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	const char *parent_name;
563ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	u32 clk_id;
564ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij
56574227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	if (!src_base)
56674227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth		nomadik_src_init();
56774227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth
568ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (of_property_read_u32(np, "clock-id", &clk_id)) {
569ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
570ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij			__func__, clk_name);
571ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		return;
572ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	}
573ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	parent_name = of_clk_get_parent_name(np, 0);
574ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	clk = src_clk_register(NULL, clk_name, parent_name, clk_id);
575ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij	if (!IS_ERR(clk))
576ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij		of_clk_add_provider(np, of_clk_src_simple_get, clk);
577ef6eb322ce574ba73658a677e83e5da3cfab301bLinus Walleij}
57874227e65f9742f559f6e243ba2c9a983e1f1221dSebastian HesselbarthCLK_OF_DECLARE(nomadik_src_clk,
57974227e65f9742f559f6e243ba2c9a983e1f1221dSebastian Hesselbarth	"st,nomadik-src-clock", of_nomadik_src_clk_setup);
580