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