aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-27 15:44:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-27 15:44:34 -0400
commit78c10e556ed904d5bfbd71e9cadd8ce8f25d6982 (patch)
treef73c802d60e81ff9e9fd2465eab096834d0227cd /drivers
parentd2c3ac7e7e39ec6d37e4114ae7444948561e59af (diff)
parent9ff897c4e8d5bd05ad7009f84a395596d4953858 (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: - Improvements to the tlb_dump code - KVM fixes - Add support for appended DTB - Minor improvements to the R12000 support - Minor improvements to the R12000 support - Various platform improvments for BCM47xx - The usual pile of minor cleanups - A number of BPF fixes and improvments - Some improvments to the support for R3000 and DECstations - Some improvments to the ATH79 platform support - A major patchset for the JZ4740 SOC adding support for the CI20 platform - Add support for the Pistachio SOC - Minor BMIPS/BCM63xx platform support improvments. - Avoid "SYNC 0" as memory barrier when unlocking spinlocks - Add support for the XWR-1750 board. - Paul's __cpuinit/__cpuinitdata cleanups. - New Malta CPU board support large memory so enable ZONE_DMA32. * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (131 commits) MIPS: spinlock: Adjust arch_spin_lock back-off time MIPS: asmmacro: Ensure 64-bit FP registers are used with MSA MIPS: BCM47xx: Simplify handling SPROM revisions MIPS: Cobalt Don't use module_init in non-modular MTD registration. MIPS: BCM47xx: Move NVRAM driver to the drivers/firmware/ MIPS: use for_each_sg() MIPS: BCM47xx: Don't select BCMA_HOST_PCI MIPS: BCM47xx: Add helper variable for storing NVRAM length MIPS: IRQ/IP27: Move IRQ allocation API to platform code. MIPS: Replace smp_mb with release barrier function in unlocks. MIPS: i8259: DT support MIPS: Malta: Basic DT plumbing MIPS: include errno.h for ENODEV in mips-cm.h MIPS: Define GCR_GIC_STATUS register fields MIPS: BPF: Introduce BPF ASM helpers MIPS: BPF: Use BPF register names to describe the ABI MIPS: BPF: Move register definition to the BPF header MIPS: net: BPF: Replace RSIZE with SZREG MIPS: BPF: Free up some callee-saved registers MIPS: Xtalk: Update xwidget.h with known Xtalk device numbers ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/Makefile3
-rw-r--r--drivers/clk/ingenic/Makefile3
-rw-r--r--drivers/clk/ingenic/cgu.c711
-rw-r--r--drivers/clk/ingenic/cgu.h223
-rw-r--r--drivers/clk/ingenic/jz4740-cgu.c303
-rw-r--r--drivers/clk/ingenic/jz4780-cgu.c733
-rw-r--r--drivers/cpufreq/ls1x-cpufreq.c4
-rw-r--r--drivers/firmware/Kconfig1
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/broadcom/Kconfig11
-rw-r--r--drivers/firmware/broadcom/Makefile1
-rw-r--r--drivers/firmware/broadcom/bcm47xx_nvram.c248
-rw-r--r--drivers/irqchip/Kconfig12
-rw-r--r--drivers/irqchip/Makefile2
-rw-r--r--drivers/irqchip/irq-ingenic.c177
-rw-r--r--drivers/irqchip/irq-mips-cpu.c172
-rw-r--r--drivers/phy/Kconfig7
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-pistachio-usb.c206
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/rtc-ls1x.c2
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c266
-rw-r--r--drivers/tty/serial/8250/Kconfig9
-rw-r--r--drivers/tty/serial/8250/Makefile3
-rw-r--r--drivers/tty/sysrq.c1
-rw-r--r--drivers/usb/host/Kconfig4
26 files changed, 3098 insertions, 8 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 5b6af6a9319f..8732e4c5bf3c 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -24,7 +24,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
24obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o 24obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
25obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o 25obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
26obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o 26obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
27obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o 27obj-$(CONFIG_MACH_LOONGSON32) += clk-ls1x.o
28obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o 28obj-$(CONFIG_COMMON_CLK_MAX_GEN) += clk-max-gen.o
29obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o 29obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
30obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o 30obj-$(CONFIG_COMMON_CLK_MAX77802) += clk-max77802.o
@@ -51,6 +51,7 @@ obj-$(CONFIG_ARCH_HI3xxx) += hisilicon/
51obj-$(CONFIG_ARCH_HIP04) += hisilicon/ 51obj-$(CONFIG_ARCH_HIP04) += hisilicon/
52obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/ 52obj-$(CONFIG_ARCH_HIX5HD2) += hisilicon/
53obj-$(CONFIG_ARCH_MXC) += imx/ 53obj-$(CONFIG_ARCH_MXC) += imx/
54obj-$(CONFIG_MACH_INGENIC) += ingenic/
54obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/ 55obj-$(CONFIG_COMMON_CLK_KEYSTONE) += keystone/
55ifeq ($(CONFIG_COMMON_CLK), y) 56ifeq ($(CONFIG_COMMON_CLK), y)
56obj-$(CONFIG_ARCH_MMP) += mmp/ 57obj-$(CONFIG_ARCH_MMP) += mmp/
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
new file mode 100644
index 000000000000..cd47b0664c2b
--- /dev/null
+++ b/drivers/clk/ingenic/Makefile
@@ -0,0 +1,3 @@
1obj-y += cgu.o
2obj-$(CONFIG_MACH_JZ4740) += jz4740-cgu.o
3obj-$(CONFIG_MACH_JZ4780) += jz4780-cgu.o
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
new file mode 100644
index 000000000000..b936cdd1a13c
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.c
@@ -0,0 +1,711 @@
1/*
2 * Ingenic SoC CGU driver
3 *
4 * Copyright (c) 2013-2015 Imagination Technologies
5 * Author: Paul Burton <paul.burton@imgtec.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/bitops.h>
19#include <linux/clk-provider.h>
20#include <linux/clkdev.h>
21#include <linux/delay.h>
22#include <linux/math64.h>
23#include <linux/of.h>
24#include <linux/of_address.h>
25#include <linux/slab.h>
26#include <linux/spinlock.h>
27#include "cgu.h"
28
29#define MHZ (1000 * 1000)
30
31/**
32 * ingenic_cgu_gate_get() - get the value of clock gate register bit
33 * @cgu: reference to the CGU whose registers should be read
34 * @info: info struct describing the gate bit
35 *
36 * Retrieves the state of the clock gate bit described by info. The
37 * caller must hold cgu->lock.
38 *
39 * Return: true if the gate bit is set, else false.
40 */
41static inline bool
42ingenic_cgu_gate_get(struct ingenic_cgu *cgu,
43 const struct ingenic_cgu_gate_info *info)
44{
45 return readl(cgu->base + info->reg) & BIT(info->bit);
46}
47
48/**
49 * ingenic_cgu_gate_set() - set the value of clock gate register bit
50 * @cgu: reference to the CGU whose registers should be modified
51 * @info: info struct describing the gate bit
52 * @val: non-zero to gate a clock, otherwise zero
53 *
54 * Sets the given gate bit in order to gate or ungate a clock.
55 *
56 * The caller must hold cgu->lock.
57 */
58static inline void
59ingenic_cgu_gate_set(struct ingenic_cgu *cgu,
60 const struct ingenic_cgu_gate_info *info, bool val)
61{
62 u32 clkgr = readl(cgu->base + info->reg);
63
64 if (val)
65 clkgr |= BIT(info->bit);
66 else
67 clkgr &= ~BIT(info->bit);
68
69 writel(clkgr, cgu->base + info->reg);
70}
71
72/*
73 * PLL operations
74 */
75
76static unsigned long
77ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
78{
79 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
80 struct ingenic_cgu *cgu = ingenic_clk->cgu;
81 const struct ingenic_cgu_clk_info *clk_info;
82 const struct ingenic_cgu_pll_info *pll_info;
83 unsigned m, n, od_enc, od;
84 bool bypass, enable;
85 unsigned long flags;
86 u32 ctl;
87
88 clk_info = &cgu->clock_info[ingenic_clk->idx];
89 BUG_ON(clk_info->type != CGU_CLK_PLL);
90 pll_info = &clk_info->pll;
91
92 spin_lock_irqsave(&cgu->lock, flags);
93 ctl = readl(cgu->base + pll_info->reg);
94 spin_unlock_irqrestore(&cgu->lock, flags);
95
96 m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0);
97 m += pll_info->m_offset;
98 n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0);
99 n += pll_info->n_offset;
100 od_enc = ctl >> pll_info->od_shift;
101 od_enc &= GENMASK(pll_info->od_bits - 1, 0);
102 bypass = !!(ctl & BIT(pll_info->bypass_bit));
103 enable = !!(ctl & BIT(pll_info->enable_bit));
104
105 if (bypass)
106 return parent_rate;
107
108 if (!enable)
109 return 0;
110
111 for (od = 0; od < pll_info->od_max; od++) {
112 if (pll_info->od_encoding[od] == od_enc)
113 break;
114 }
115 BUG_ON(od == pll_info->od_max);
116 od++;
117
118 return div_u64((u64)parent_rate * m, n * od);
119}
120
121static unsigned long
122ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info,
123 unsigned long rate, unsigned long parent_rate,
124 unsigned *pm, unsigned *pn, unsigned *pod)
125{
126 const struct ingenic_cgu_pll_info *pll_info;
127 unsigned m, n, od;
128
129 pll_info = &clk_info->pll;
130 od = 1;
131
132 /*
133 * The frequency after the input divider must be between 10 and 50 MHz.
134 * The highest divider yields the best resolution.
135 */
136 n = parent_rate / (10 * MHZ);
137 n = min_t(unsigned, n, 1 << clk_info->pll.n_bits);
138 n = max_t(unsigned, n, pll_info->n_offset);
139
140 m = (rate / MHZ) * od * n / (parent_rate / MHZ);
141 m = min_t(unsigned, m, 1 << clk_info->pll.m_bits);
142 m = max_t(unsigned, m, pll_info->m_offset);
143
144 if (pm)
145 *pm = m;
146 if (pn)
147 *pn = n;
148 if (pod)
149 *pod = od;
150
151 return div_u64((u64)parent_rate * m, n * od);
152}
153
154static long
155ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate,
156 unsigned long *prate)
157{
158 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
159 struct ingenic_cgu *cgu = ingenic_clk->cgu;
160 const struct ingenic_cgu_clk_info *clk_info;
161
162 clk_info = &cgu->clock_info[ingenic_clk->idx];
163 BUG_ON(clk_info->type != CGU_CLK_PLL);
164
165 return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL);
166}
167
168static int
169ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
170 unsigned long parent_rate)
171{
172 const unsigned timeout = 100;
173 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
174 struct ingenic_cgu *cgu = ingenic_clk->cgu;
175 const struct ingenic_cgu_clk_info *clk_info;
176 const struct ingenic_cgu_pll_info *pll_info;
177 unsigned long rate, flags;
178 unsigned m, n, od, i;
179 u32 ctl;
180
181 clk_info = &cgu->clock_info[ingenic_clk->idx];
182 BUG_ON(clk_info->type != CGU_CLK_PLL);
183 pll_info = &clk_info->pll;
184
185 rate = ingenic_pll_calc(clk_info, req_rate, parent_rate,
186 &m, &n, &od);
187 if (rate != req_rate)
188 pr_info("ingenic-cgu: request '%s' rate %luHz, actual %luHz\n",
189 clk_info->name, req_rate, rate);
190
191 spin_lock_irqsave(&cgu->lock, flags);
192 ctl = readl(cgu->base + pll_info->reg);
193
194 ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift);
195 ctl |= (m - pll_info->m_offset) << pll_info->m_shift;
196
197 ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
198 ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
199
200 ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
201 ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
202
203 ctl &= ~BIT(pll_info->bypass_bit);
204 ctl |= BIT(pll_info->enable_bit);
205
206 writel(ctl, cgu->base + pll_info->reg);
207
208 /* wait for the PLL to stabilise */
209 for (i = 0; i < timeout; i++) {
210 ctl = readl(cgu->base + pll_info->reg);
211 if (ctl & BIT(pll_info->stable_bit))
212 break;
213 mdelay(1);
214 }
215
216 spin_unlock_irqrestore(&cgu->lock, flags);
217
218 if (i == timeout)
219 return -EBUSY;
220
221 return 0;
222}
223
224static const struct clk_ops ingenic_pll_ops = {
225 .recalc_rate = ingenic_pll_recalc_rate,
226 .round_rate = ingenic_pll_round_rate,
227 .set_rate = ingenic_pll_set_rate,
228};
229
230/*
231 * Operations for all non-PLL clocks
232 */
233
234static u8 ingenic_clk_get_parent(struct clk_hw *hw)
235{
236 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
237 struct ingenic_cgu *cgu = ingenic_clk->cgu;
238 const struct ingenic_cgu_clk_info *clk_info;
239 u32 reg;
240 u8 i, hw_idx, idx = 0;
241
242 clk_info = &cgu->clock_info[ingenic_clk->idx];
243
244 if (clk_info->type & CGU_CLK_MUX) {
245 reg = readl(cgu->base + clk_info->mux.reg);
246 hw_idx = (reg >> clk_info->mux.shift) &
247 GENMASK(clk_info->mux.bits - 1, 0);
248
249 /*
250 * Convert the hardware index to the parent index by skipping
251 * over any -1's in the parents array.
252 */
253 for (i = 0; i < hw_idx; i++) {
254 if (clk_info->parents[i] != -1)
255 idx++;
256 }
257 }
258
259 return idx;
260}
261
262static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx)
263{
264 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
265 struct ingenic_cgu *cgu = ingenic_clk->cgu;
266 const struct ingenic_cgu_clk_info *clk_info;
267 unsigned long flags;
268 u8 curr_idx, hw_idx, num_poss;
269 u32 reg, mask;
270
271 clk_info = &cgu->clock_info[ingenic_clk->idx];
272
273 if (clk_info->type & CGU_CLK_MUX) {
274 /*
275 * Convert the parent index to the hardware index by adding
276 * 1 for any -1 in the parents array preceding the given
277 * index. That is, we want the index of idx'th entry in
278 * clk_info->parents which does not equal -1.
279 */
280 hw_idx = curr_idx = 0;
281 num_poss = 1 << clk_info->mux.bits;
282 for (; hw_idx < num_poss; hw_idx++) {
283 if (clk_info->parents[hw_idx] == -1)
284 continue;
285 if (curr_idx == idx)
286 break;
287 curr_idx++;
288 }
289
290 /* idx should always be a valid parent */
291 BUG_ON(curr_idx != idx);
292
293 mask = GENMASK(clk_info->mux.bits - 1, 0);
294 mask <<= clk_info->mux.shift;
295
296 spin_lock_irqsave(&cgu->lock, flags);
297
298 /* write the register */
299 reg = readl(cgu->base + clk_info->mux.reg);
300 reg &= ~mask;
301 reg |= hw_idx << clk_info->mux.shift;
302 writel(reg, cgu->base + clk_info->mux.reg);
303
304 spin_unlock_irqrestore(&cgu->lock, flags);
305 return 0;
306 }
307
308 return idx ? -EINVAL : 0;
309}
310
311static unsigned long
312ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
313{
314 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
315 struct ingenic_cgu *cgu = ingenic_clk->cgu;
316 const struct ingenic_cgu_clk_info *clk_info;
317 unsigned long rate = parent_rate;
318 u32 div_reg, div;
319
320 clk_info = &cgu->clock_info[ingenic_clk->idx];
321
322 if (clk_info->type & CGU_CLK_DIV) {
323 div_reg = readl(cgu->base + clk_info->div.reg);
324 div = (div_reg >> clk_info->div.shift) &
325 GENMASK(clk_info->div.bits - 1, 0);
326 div += 1;
327
328 rate /= div;
329 }
330
331 return rate;
332}
333
334static unsigned
335ingenic_clk_calc_div(const struct ingenic_cgu_clk_info *clk_info,
336 unsigned long parent_rate, unsigned long req_rate)
337{
338 unsigned div;
339
340 /* calculate the divide */
341 div = DIV_ROUND_UP(parent_rate, req_rate);
342
343 /* and impose hardware constraints */
344 div = min_t(unsigned, div, 1 << clk_info->div.bits);
345 div = max_t(unsigned, div, 1);
346
347 return div;
348}
349
350static long
351ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
352 unsigned long *parent_rate)
353{
354 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
355 struct ingenic_cgu *cgu = ingenic_clk->cgu;
356 const struct ingenic_cgu_clk_info *clk_info;
357 long rate = *parent_rate;
358
359 clk_info = &cgu->clock_info[ingenic_clk->idx];
360
361 if (clk_info->type & CGU_CLK_DIV)
362 rate /= ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
363 else if (clk_info->type & CGU_CLK_FIXDIV)
364 rate /= clk_info->fixdiv.div;
365
366 return rate;
367}
368
369static int
370ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
371 unsigned long parent_rate)
372{
373 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
374 struct ingenic_cgu *cgu = ingenic_clk->cgu;
375 const struct ingenic_cgu_clk_info *clk_info;
376 const unsigned timeout = 100;
377 unsigned long rate, flags;
378 unsigned div, i;
379 u32 reg, mask;
380 int ret = 0;
381
382 clk_info = &cgu->clock_info[ingenic_clk->idx];
383
384 if (clk_info->type & CGU_CLK_DIV) {
385 div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
386 rate = parent_rate / div;
387
388 if (rate != req_rate)
389 return -EINVAL;
390
391 spin_lock_irqsave(&cgu->lock, flags);
392 reg = readl(cgu->base + clk_info->div.reg);
393
394 /* update the divide */
395 mask = GENMASK(clk_info->div.bits - 1, 0);
396 reg &= ~(mask << clk_info->div.shift);
397 reg |= (div - 1) << clk_info->div.shift;
398
399 /* clear the stop bit */
400 if (clk_info->div.stop_bit != -1)
401 reg &= ~BIT(clk_info->div.stop_bit);
402
403 /* set the change enable bit */
404 if (clk_info->div.ce_bit != -1)
405 reg |= BIT(clk_info->div.ce_bit);
406
407 /* update the hardware */
408 writel(reg, cgu->base + clk_info->div.reg);
409
410 /* wait for the change to take effect */
411 if (clk_info->div.busy_bit != -1) {
412 for (i = 0; i < timeout; i++) {
413 reg = readl(cgu->base + clk_info->div.reg);
414 if (!(reg & BIT(clk_info->div.busy_bit)))
415 break;
416 mdelay(1);
417 }
418 if (i == timeout)
419 ret = -EBUSY;
420 }
421
422 spin_unlock_irqrestore(&cgu->lock, flags);
423 return ret;
424 }
425
426 return -EINVAL;
427}
428
429static int ingenic_clk_enable(struct clk_hw *hw)
430{
431 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
432 struct ingenic_cgu *cgu = ingenic_clk->cgu;
433 const struct ingenic_cgu_clk_info *clk_info;
434 unsigned long flags;
435
436 clk_info = &cgu->clock_info[ingenic_clk->idx];
437
438 if (clk_info->type & CGU_CLK_GATE) {
439 /* ungate the clock */
440 spin_lock_irqsave(&cgu->lock, flags);
441 ingenic_cgu_gate_set(cgu, &clk_info->gate, false);
442 spin_unlock_irqrestore(&cgu->lock, flags);
443 }
444
445 return 0;
446}
447
448static void ingenic_clk_disable(struct clk_hw *hw)
449{
450 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
451 struct ingenic_cgu *cgu = ingenic_clk->cgu;
452 const struct ingenic_cgu_clk_info *clk_info;
453 unsigned long flags;
454
455 clk_info = &cgu->clock_info[ingenic_clk->idx];
456
457 if (clk_info->type & CGU_CLK_GATE) {
458 /* gate the clock */
459 spin_lock_irqsave(&cgu->lock, flags);
460 ingenic_cgu_gate_set(cgu, &clk_info->gate, true);
461 spin_unlock_irqrestore(&cgu->lock, flags);
462 }
463}
464
465static int ingenic_clk_is_enabled(struct clk_hw *hw)
466{
467 struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
468 struct ingenic_cgu *cgu = ingenic_clk->cgu;
469 const struct ingenic_cgu_clk_info *clk_info;
470 unsigned long flags;
471 int enabled = 1;
472
473 clk_info = &cgu->clock_info[ingenic_clk->idx];
474
475 if (clk_info->type & CGU_CLK_GATE) {
476 spin_lock_irqsave(&cgu->lock, flags);
477 enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate);
478 spin_unlock_irqrestore(&cgu->lock, flags);
479 }
480
481 return enabled;
482}
483
484static const struct clk_ops ingenic_clk_ops = {
485 .get_parent = ingenic_clk_get_parent,
486 .set_parent = ingenic_clk_set_parent,
487
488 .recalc_rate = ingenic_clk_recalc_rate,
489 .round_rate = ingenic_clk_round_rate,
490 .set_rate = ingenic_clk_set_rate,
491
492 .enable = ingenic_clk_enable,
493 .disable = ingenic_clk_disable,
494 .is_enabled = ingenic_clk_is_enabled,
495};
496
497/*
498 * Setup functions.
499 */
500
501static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx)
502{
503 const struct ingenic_cgu_clk_info *clk_info = &cgu->clock_info[idx];
504 struct clk_init_data clk_init;
505 struct ingenic_clk *ingenic_clk = NULL;
506 struct clk *clk, *parent;
507 const char *parent_names[4];
508 unsigned caps, i, num_possible;
509 int err = -EINVAL;
510
511 BUILD_BUG_ON(ARRAY_SIZE(clk_info->parents) > ARRAY_SIZE(parent_names));
512
513 if (clk_info->type == CGU_CLK_EXT) {
514 clk = of_clk_get_by_name(cgu->np, clk_info->name);
515 if (IS_ERR(clk)) {
516 pr_err("%s: no external clock '%s' provided\n",
517 __func__, clk_info->name);
518 err = -ENODEV;
519 goto out;
520 }
521 err = clk_register_clkdev(clk, clk_info->name, NULL);
522 if (err) {
523 clk_put(clk);
524 goto out;
525 }
526 cgu->clocks.clks[idx] = clk;
527 return 0;
528 }
529
530 if (!clk_info->type) {
531 pr_err("%s: no clock type specified for '%s'\n", __func__,
532 clk_info->name);
533 goto out;
534 }
535
536 ingenic_clk = kzalloc(sizeof(*ingenic_clk), GFP_KERNEL);
537 if (!ingenic_clk) {
538 err = -ENOMEM;
539 goto out;
540 }
541
542 ingenic_clk->hw.init = &clk_init;
543 ingenic_clk->cgu = cgu;
544 ingenic_clk->idx = idx;
545
546 clk_init.name = clk_info->name;
547 clk_init.flags = 0;
548 clk_init.parent_names = parent_names;
549
550 caps = clk_info->type;
551
552 if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) {
553 clk_init.num_parents = 0;
554
555 if (caps & CGU_CLK_MUX)
556 num_possible = 1 << clk_info->mux.bits;
557 else
558 num_possible = ARRAY_SIZE(clk_info->parents);
559
560 for (i = 0; i < num_possible; i++) {
561 if (clk_info->parents[i] == -1)
562 continue;
563
564 parent = cgu->clocks.clks[clk_info->parents[i]];
565 parent_names[clk_init.num_parents] =
566 __clk_get_name(parent);
567 clk_init.num_parents++;
568 }
569
570 BUG_ON(!clk_init.num_parents);
571 BUG_ON(clk_init.num_parents > ARRAY_SIZE(parent_names));
572 } else {
573 BUG_ON(clk_info->parents[0] == -1);
574 clk_init.num_parents = 1;
575 parent = cgu->clocks.clks[clk_info->parents[0]];
576 parent_names[0] = __clk_get_name(parent);
577 }
578
579 if (caps & CGU_CLK_CUSTOM) {
580 clk_init.ops = clk_info->custom.clk_ops;
581
582 caps &= ~CGU_CLK_CUSTOM;
583
584 if (caps) {
585 pr_err("%s: custom clock may not be combined with type 0x%x\n",
586 __func__, caps);
587 goto out;
588 }
589 } else if (caps & CGU_CLK_PLL) {
590 clk_init.ops = &ingenic_pll_ops;
591
592 caps &= ~CGU_CLK_PLL;
593
594 if (caps) {
595 pr_err("%s: PLL may not be combined with type 0x%x\n",
596 __func__, caps);
597 goto out;
598 }
599 } else {
600 clk_init.ops = &ingenic_clk_ops;
601 }
602
603 /* nothing to do for gates or fixed dividers */
604 caps &= ~(CGU_CLK_GATE | CGU_CLK_FIXDIV);
605
606 if (caps & CGU_CLK_MUX) {
607 if (!(caps & CGU_CLK_MUX_GLITCHFREE))
608 clk_init.flags |= CLK_SET_PARENT_GATE;
609
610 caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE);
611 }
612
613 if (caps & CGU_CLK_DIV) {
614 caps &= ~CGU_CLK_DIV;
615 } else {
616 /* pass rate changes to the parent clock */
617 clk_init.flags |= CLK_SET_RATE_PARENT;
618 }
619
620 if (caps) {
621 pr_err("%s: unknown clock type 0x%x\n", __func__, caps);
622 goto out;
623 }
624
625 clk = clk_register(NULL, &ingenic_clk->hw);
626 if (IS_ERR(clk)) {
627 pr_err("%s: failed to register clock '%s'\n", __func__,
628 clk_info->name);
629 err = PTR_ERR(clk);
630 goto out;
631 }
632
633 err = clk_register_clkdev(clk, clk_info->name, NULL);
634 if (err)
635 goto out;
636
637 cgu->clocks.clks[idx] = clk;
638out:
639 if (err)
640 kfree(ingenic_clk);
641 return err;
642}
643
644struct ingenic_cgu *
645ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
646 unsigned num_clocks, struct device_node *np)
647{
648 struct ingenic_cgu *cgu;
649
650 cgu = kzalloc(sizeof(*cgu), GFP_KERNEL);
651 if (!cgu)
652 goto err_out;
653
654 cgu->base = of_iomap(np, 0);
655 if (!cgu->base) {
656 pr_err("%s: failed to map CGU registers\n", __func__);
657 goto err_out_free;
658 }
659
660 cgu->np = np;
661 cgu->clock_info = clock_info;
662 cgu->clocks.clk_num = num_clocks;
663
664 spin_lock_init(&cgu->lock);
665
666 return cgu;
667
668err_out_free:
669 kfree(cgu);
670err_out:
671 return NULL;
672}
673
674int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu)
675{
676 unsigned i;
677 int err;
678
679 cgu->clocks.clks = kcalloc(cgu->clocks.clk_num, sizeof(struct clk *),
680 GFP_KERNEL);
681 if (!cgu->clocks.clks) {
682 err = -ENOMEM;
683 goto err_out;
684 }
685
686 for (i = 0; i < cgu->clocks.clk_num; i++) {
687 err = ingenic_register_clock(cgu, i);
688 if (err)
689 goto err_out_unregister;
690 }
691
692 err = of_clk_add_provider(cgu->np, of_clk_src_onecell_get,
693 &cgu->clocks);
694 if (err)
695 goto err_out_unregister;
696
697 return 0;
698
699err_out_unregister:
700 for (i = 0; i < cgu->clocks.clk_num; i++) {
701 if (!cgu->clocks.clks[i])
702 continue;
703 if (cgu->clock_info[i].type & CGU_CLK_EXT)
704 clk_put(cgu->clocks.clks[i]);
705 else
706 clk_unregister(cgu->clocks.clks[i]);
707 }
708 kfree(cgu->clocks.clks);
709err_out:
710 return err;
711}
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
new file mode 100644
index 000000000000..99347e2b97e8
--- /dev/null
+++ b/drivers/clk/ingenic/cgu.h
@@ -0,0 +1,223 @@
1/*
2 * Ingenic SoC CGU driver
3 *
4 * Copyright (c) 2013-2015 Imagination Technologies
5 * Author: Paul Burton <paul.burton@imgtec.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#ifndef __DRIVERS_CLK_INGENIC_CGU_H__
19#define __DRIVERS_CLK_INGENIC_CGU_H__
20
21#include <linux/bitops.h>
22#include <linux/of.h>
23#include <linux/spinlock.h>
24
25/**
26 * struct ingenic_cgu_pll_info - information about a PLL
27 * @reg: the offset of the PLL's control register within the CGU
28 * @m_shift: the number of bits to shift the multiplier value by (ie. the
29 * index of the lowest bit of the multiplier value in the PLL's
30 * control register)
31 * @m_bits: the size of the multiplier field in bits
32 * @m_offset: the multiplier value which encodes to 0 in the PLL's control
33 * register
34 * @n_shift: the number of bits to shift the divider value by (ie. the
35 * index of the lowest bit of the divider value in the PLL's
36 * control register)
37 * @n_bits: the size of the divider field in bits
38 * @n_offset: the divider value which encodes to 0 in the PLL's control
39 * register
40 * @od_shift: the number of bits to shift the post-VCO divider value by (ie.
41 * the index of the lowest bit of the post-VCO divider value in
42 * the PLL's control register)
43 * @od_bits: the size of the post-VCO divider field in bits
44 * @od_max: the maximum post-VCO divider value
45 * @od_encoding: a pointer to an array mapping post-VCO divider values to
46 * their encoded values in the PLL control register, or -1 for
47 * unsupported values
48 * @bypass_bit: the index of the bypass bit in the PLL control register
49 * @enable_bit: the index of the enable bit in the PLL control register
50 * @stable_bit: the index of the stable bit in the PLL control register
51 */
52struct ingenic_cgu_pll_info {
53 unsigned reg;
54 const s8 *od_encoding;
55 u8 m_shift, m_bits, m_offset;
56 u8 n_shift, n_bits, n_offset;
57 u8 od_shift, od_bits, od_max;
58 u8 bypass_bit;
59 u8 enable_bit;
60 u8 stable_bit;
61};
62
63/**
64 * struct ingenic_cgu_mux_info - information about a clock mux
65 * @reg: offset of the mux control register within the CGU
66 * @shift: number of bits to shift the mux value by (ie. the index of
67 * the lowest bit of the mux value within its control register)
68 * @bits: the size of the mux value in bits
69 */
70struct ingenic_cgu_mux_info {
71 unsigned reg;
72 u8 shift;
73 u8 bits;
74};
75
76/**
77 * struct ingenic_cgu_div_info - information about a divider
78 * @reg: offset of the divider control register within the CGU
79 * @shift: number of bits to shift the divide value by (ie. the index of
80 * the lowest bit of the divide value within its control register)
81 * @bits: the size of the divide value in bits
82 * @ce_bit: the index of the change enable bit within reg, or -1 if there
83 * isn't one
84 * @busy_bit: the index of the busy bit within reg, or -1 if there isn't one
85 * @stop_bit: the index of the stop bit within reg, or -1 if there isn't one
86 */
87struct ingenic_cgu_div_info {
88 unsigned reg;
89 u8 shift;
90 u8 bits;
91 s8 ce_bit;
92 s8 busy_bit;
93 s8 stop_bit;
94};
95
96/**
97 * struct ingenic_cgu_fixdiv_info - information about a fixed divider
98 * @div: the divider applied to the parent clock
99 */
100struct ingenic_cgu_fixdiv_info {
101 unsigned div;
102};
103
104/**
105 * struct ingenic_cgu_gate_info - information about a clock gate
106 * @reg: offset of the gate control register within the CGU
107 * @bit: offset of the bit in the register that controls the gate
108 */
109struct ingenic_cgu_gate_info {
110 unsigned reg;
111 u8 bit;
112};
113
114/**
115 * struct ingenic_cgu_custom_info - information about a custom (SoC) clock
116 * @clk_ops: custom clock operation callbacks
117 */
118struct ingenic_cgu_custom_info {
119 struct clk_ops *clk_ops;
120};
121
122/**
123 * struct ingenic_cgu_clk_info - information about a clock
124 * @name: name of the clock
125 * @type: a bitmask formed from CGU_CLK_* values
126 * @parents: an array of the indices of potential parents of this clock
127 * within the clock_info array of the CGU, or -1 in entries
128 * which correspond to no valid parent
129 * @pll: information valid if type includes CGU_CLK_PLL
130 * @gate: information valid if type includes CGU_CLK_GATE
131 * @mux: information valid if type includes CGU_CLK_MUX
132 * @div: information valid if type includes CGU_CLK_DIV
133 * @fixdiv: information valid if type includes CGU_CLK_FIXDIV
134 * @custom: information valid if type includes CGU_CLK_CUSTOM
135 */
136struct ingenic_cgu_clk_info {
137 const char *name;
138
139 enum {
140 CGU_CLK_NONE = 0,
141 CGU_CLK_EXT = BIT(0),
142 CGU_CLK_PLL = BIT(1),
143 CGU_CLK_GATE = BIT(2),
144 CGU_CLK_MUX = BIT(3),
145 CGU_CLK_MUX_GLITCHFREE = BIT(4),
146 CGU_CLK_DIV = BIT(5),
147 CGU_CLK_FIXDIV = BIT(6),
148 CGU_CLK_CUSTOM = BIT(7),
149 } type;
150
151 int parents[4];
152
153 union {
154 struct ingenic_cgu_pll_info pll;
155
156 struct {
157 struct ingenic_cgu_gate_info gate;
158 struct ingenic_cgu_mux_info mux;
159 struct ingenic_cgu_div_info div;
160 struct ingenic_cgu_fixdiv_info fixdiv;
161 };
162
163 struct ingenic_cgu_custom_info custom;
164 };
165};
166
167/**
168 * struct ingenic_cgu - data about the CGU
169 * @np: the device tree node that caused the CGU to be probed
170 * @base: the ioremap'ed base address of the CGU registers
171 * @clock_info: an array containing information about implemented clocks
172 * @clocks: used to provide clocks to DT, allows lookup of struct clk*
173 * @lock: lock to be held whilst manipulating CGU registers
174 */
175struct ingenic_cgu {
176 struct device_node *np;
177 void __iomem *base;
178
179 const struct ingenic_cgu_clk_info *clock_info;
180 struct clk_onecell_data clocks;
181
182 spinlock_t lock;
183};
184
185/**
186 * struct ingenic_clk - private data for a clock
187 * @hw: see Documentation/clk.txt
188 * @cgu: a pointer to the CGU data
189 * @idx: the index of this clock in cgu->clock_info
190 */
191struct ingenic_clk {
192 struct clk_hw hw;
193 struct ingenic_cgu *cgu;
194 unsigned idx;
195};
196
197#define to_ingenic_clk(_hw) container_of(_hw, struct ingenic_clk, hw)
198
199/**
200 * ingenic_cgu_new() - create a new CGU instance
201 * @clock_info: an array of clock information structures describing the clocks
202 * which are implemented by the CGU
203 * @num_clocks: the number of entries in clock_info
204 * @np: the device tree node which causes this CGU to be probed
205 *
206 * Return: a pointer to the CGU instance if initialisation is successful,
207 * otherwise NULL.
208 */
209struct ingenic_cgu *
210ingenic_cgu_new(const struct ingenic_cgu_clk_info *clock_info,
211 unsigned num_clocks, struct device_node *np);
212
213/**
214 * ingenic_cgu_register_clocks() - Registers the clocks
215 * @cgu: pointer to cgu data
216 *
217 * Register the clocks described by the CGU with the common clock framework.
218 *
219 * Return: 0 on success or -errno if unsuccesful.
220 */
221int ingenic_cgu_register_clocks(struct ingenic_cgu *cgu);
222
223#endif /* __DRIVERS_CLK_INGENIC_CGU_H__ */
diff --git a/drivers/clk/ingenic/jz4740-cgu.c b/drivers/clk/ingenic/jz4740-cgu.c
new file mode 100644
index 000000000000..305a26c2a800
--- /dev/null
+++ b/drivers/clk/ingenic/jz4740-cgu.c
@@ -0,0 +1,303 @@
1/*
2 * Ingenic JZ4740 SoC CGU driver
3 *
4 * Copyright (c) 2015 Imagination Technologies
5 * Author: Paul Burton <paul.burton@imgtec.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/clk-provider.h>
19#include <linux/delay.h>
20#include <linux/of.h>
21#include <dt-bindings/clock/jz4740-cgu.h>
22#include <asm/mach-jz4740/clock.h>
23#include "cgu.h"
24
25/* CGU register offsets */
26#define CGU_REG_CPCCR 0x00
27#define CGU_REG_LCR 0x04
28#define CGU_REG_CPPCR 0x10
29#define CGU_REG_CLKGR 0x20
30#define CGU_REG_SCR 0x24
31#define CGU_REG_I2SCDR 0x60
32#define CGU_REG_LPCDR 0x64
33#define CGU_REG_MSCCDR 0x68
34#define CGU_REG_UHCCDR 0x6c
35#define CGU_REG_SSICDR 0x74
36
37/* bits within a PLL control register */
38#define PLLCTL_M_SHIFT 23
39#define PLLCTL_M_MASK (0x1ff << PLLCTL_M_SHIFT)
40#define PLLCTL_N_SHIFT 18
41#define PLLCTL_N_MASK (0x1f << PLLCTL_N_SHIFT)
42#define PLLCTL_OD_SHIFT 16
43#define PLLCTL_OD_MASK (0x3 << PLLCTL_OD_SHIFT)
44#define PLLCTL_STABLE (1 << 10)
45#define PLLCTL_BYPASS (1 << 9)
46#define PLLCTL_ENABLE (1 << 8)
47
48/* bits within the LCR register */
49#define LCR_SLEEP (1 << 0)
50
51/* bits within the CLKGR register */
52#define CLKGR_UDC (1 << 11)
53
54static struct ingenic_cgu *cgu;
55
56static const s8 pll_od_encoding[4] = {
57 0x0, 0x1, -1, 0x3,
58};
59
60static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
61
62 /* External clocks */
63
64 [JZ4740_CLK_EXT] = { "ext", CGU_CLK_EXT },
65 [JZ4740_CLK_RTC] = { "rtc", CGU_CLK_EXT },
66
67 [JZ4740_CLK_PLL] = {
68 "pll", CGU_CLK_PLL,
69 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
70 .pll = {
71 .reg = CGU_REG_CPPCR,
72 .m_shift = 23,
73 .m_bits = 9,
74 .m_offset = 2,
75 .n_shift = 18,
76 .n_bits = 5,
77 .n_offset = 2,
78 .od_shift = 16,
79 .od_bits = 2,
80 .od_max = 4,
81 .od_encoding = pll_od_encoding,
82 .stable_bit = 10,
83 .bypass_bit = 9,
84 .enable_bit = 8,
85 },
86 },
87
88 /* Muxes & dividers */
89
90 [JZ4740_CLK_PLL_HALF] = {
91 "pll half", CGU_CLK_DIV,
92 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
93 .div = { CGU_REG_CPCCR, 21, 1, -1, -1, -1 },
94 },
95
96 [JZ4740_CLK_CCLK] = {
97 "cclk", CGU_CLK_DIV,
98 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
99 .div = { CGU_REG_CPCCR, 0, 4, 22, -1, -1 },
100 },
101
102 [JZ4740_CLK_HCLK] = {
103 "hclk", CGU_CLK_DIV,
104 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
105 .div = { CGU_REG_CPCCR, 4, 4, 22, -1, -1 },
106 },
107
108 [JZ4740_CLK_PCLK] = {
109 "pclk", CGU_CLK_DIV,
110 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
111 .div = { CGU_REG_CPCCR, 8, 4, 22, -1, -1 },
112 },
113
114 [JZ4740_CLK_MCLK] = {
115 "mclk", CGU_CLK_DIV,
116 .parents = { JZ4740_CLK_PLL, -1, -1, -1 },
117 .div = { CGU_REG_CPCCR, 12, 4, 22, -1, -1 },
118 },
119
120 [JZ4740_CLK_LCD] = {
121 "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
122 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
123 .div = { CGU_REG_CPCCR, 16, 5, 22, -1, -1 },
124 .gate = { CGU_REG_CLKGR, 10 },
125 },
126
127 [JZ4740_CLK_LCD_PCLK] = {
128 "lcd_pclk", CGU_CLK_DIV,
129 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
130 .div = { CGU_REG_LPCDR, 0, 11, -1, -1, -1 },
131 },
132
133 [JZ4740_CLK_I2S] = {
134 "i2s", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
135 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
136 .mux = { CGU_REG_CPCCR, 31, 1 },
137 .div = { CGU_REG_I2SCDR, 0, 8, -1, -1, -1 },
138 .gate = { CGU_REG_CLKGR, 6 },
139 },
140
141 [JZ4740_CLK_SPI] = {
142 "spi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
143 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL, -1, -1 },
144 .mux = { CGU_REG_SSICDR, 31, 1 },
145 .div = { CGU_REG_SSICDR, 0, 4, -1, -1, -1 },
146 .gate = { CGU_REG_CLKGR, 4 },
147 },
148
149 [JZ4740_CLK_MMC] = {
150 "mmc", CGU_CLK_DIV | CGU_CLK_GATE,
151 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
152 .div = { CGU_REG_MSCCDR, 0, 5, -1, -1, -1 },
153 .gate = { CGU_REG_CLKGR, 7 },
154 },
155
156 [JZ4740_CLK_UHC] = {
157 "uhc", CGU_CLK_DIV | CGU_CLK_GATE,
158 .parents = { JZ4740_CLK_PLL_HALF, -1, -1, -1 },
159 .div = { CGU_REG_UHCCDR, 0, 4, -1, -1, -1 },
160 .gate = { CGU_REG_CLKGR, 14 },
161 },
162
163 [JZ4740_CLK_UDC] = {
164 "udc", CGU_CLK_MUX | CGU_CLK_DIV,
165 .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
166 .mux = { CGU_REG_CPCCR, 29, 1 },
167 .div = { CGU_REG_CPCCR, 23, 6, -1, -1, -1 },
168 .gate = { CGU_REG_SCR, 6 },
169 },
170
171 /* Gate-only clocks */
172
173 [JZ4740_CLK_UART0] = {
174 "uart0", CGU_CLK_GATE,
175 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
176 .gate = { CGU_REG_CLKGR, 0 },
177 },
178
179 [JZ4740_CLK_UART1] = {
180 "uart1", CGU_CLK_GATE,
181 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
182 .gate = { CGU_REG_CLKGR, 15 },
183 },
184
185 [JZ4740_CLK_DMA] = {
186 "dma", CGU_CLK_GATE,
187 .parents = { JZ4740_CLK_PCLK, -1, -1, -1 },
188 .gate = { CGU_REG_CLKGR, 12 },
189 },
190
191 [JZ4740_CLK_IPU] = {
192 "ipu", CGU_CLK_GATE,
193 .parents = { JZ4740_CLK_PCLK, -1, -1, -1 },
194 .gate = { CGU_REG_CLKGR, 13 },
195 },
196
197 [JZ4740_CLK_ADC] = {
198 "adc", CGU_CLK_GATE,
199 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
200 .gate = { CGU_REG_CLKGR, 8 },
201 },
202
203 [JZ4740_CLK_I2C] = {
204 "i2c", CGU_CLK_GATE,
205 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
206 .gate = { CGU_REG_CLKGR, 3 },
207 },
208
209 [JZ4740_CLK_AIC] = {
210 "aic", CGU_CLK_GATE,
211 .parents = { JZ4740_CLK_EXT, -1, -1, -1 },
212 .gate = { CGU_REG_CLKGR, 5 },
213 },
214};
215
216static void __init jz4740_cgu_init(struct device_node *np)
217{
218 int retval;
219
220 cgu = ingenic_cgu_new(jz4740_cgu_clocks,
221 ARRAY_SIZE(jz4740_cgu_clocks), np);
222 if (!cgu) {
223 pr_err("%s: failed to initialise CGU\n", __func__);
224 return;
225 }
226
227 retval = ingenic_cgu_register_clocks(cgu);
228 if (retval)
229 pr_err("%s: failed to register CGU Clocks\n", __func__);
230}
231CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
232
233void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode)
234{
235 uint32_t lcr = readl(cgu->base + CGU_REG_LCR);
236
237 switch (mode) {
238 case JZ4740_WAIT_MODE_IDLE:
239 lcr &= ~LCR_SLEEP;
240 break;
241
242 case JZ4740_WAIT_MODE_SLEEP:
243 lcr |= LCR_SLEEP;
244 break;
245 }
246
247 writel(lcr, cgu->base + CGU_REG_LCR);
248}
249
250void jz4740_clock_udc_disable_auto_suspend(void)
251{
252 uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
253
254 clkgr &= ~CLKGR_UDC;
255 writel(clkgr, cgu->base + CGU_REG_CLKGR);
256}
257EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend);
258
259void jz4740_clock_udc_enable_auto_suspend(void)
260{
261 uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR);
262
263 clkgr |= CLKGR_UDC;
264 writel(clkgr, cgu->base + CGU_REG_CLKGR);
265}
266EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend);
267
268#define JZ_CLOCK_GATE_UART0 BIT(0)
269#define JZ_CLOCK_GATE_TCU BIT(1)
270#define JZ_CLOCK_GATE_DMAC BIT(12)
271
272void jz4740_clock_suspend(void)
273{
274 uint32_t clkgr, cppcr;
275
276 clkgr = readl(cgu->base + CGU_REG_CLKGR);
277 clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0;
278 writel(clkgr, cgu->base + CGU_REG_CLKGR);
279
280 cppcr = readl(cgu->base + CGU_REG_CPPCR);
281 cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
282 writel(cppcr, cgu->base + CGU_REG_CPPCR);
283}
284
285void jz4740_clock_resume(void)
286{
287 uint32_t clkgr, cppcr, stable;
288
289 cppcr = readl(cgu->base + CGU_REG_CPPCR);
290 cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit);
291 writel(cppcr, cgu->base + CGU_REG_CPPCR);
292
293 stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit);
294 do {
295 cppcr = readl(cgu->base + CGU_REG_CPPCR);
296 } while (!(cppcr & stable));
297
298 clkgr = readl(cgu->base + CGU_REG_CLKGR);
299 clkgr &= ~JZ_CLOCK_GATE_TCU;
300 clkgr &= ~JZ_CLOCK_GATE_DMAC;
301 clkgr &= ~JZ_CLOCK_GATE_UART0;
302 writel(clkgr, cgu->base + CGU_REG_CLKGR);
303}
diff --git a/drivers/clk/ingenic/jz4780-cgu.c b/drivers/clk/ingenic/jz4780-cgu.c
new file mode 100644
index 000000000000..431f962300b6
--- /dev/null
+++ b/drivers/clk/ingenic/jz4780-cgu.c
@@ -0,0 +1,733 @@
1/*
2 * Ingenic JZ4780 SoC CGU driver
3 *
4 * Copyright (c) 2013-2015 Imagination Technologies
5 * Author: Paul Burton <paul.burton@imgtec.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/clk-provider.h>
19#include <linux/delay.h>
20#include <linux/of.h>
21#include <dt-bindings/clock/jz4780-cgu.h>
22#include "cgu.h"
23
24/* CGU register offsets */
25#define CGU_REG_CLOCKCONTROL 0x00
26#define CGU_REG_PLLCONTROL 0x0c
27#define CGU_REG_APLL 0x10
28#define CGU_REG_MPLL 0x14
29#define CGU_REG_EPLL 0x18
30#define CGU_REG_VPLL 0x1c
31#define CGU_REG_CLKGR0 0x20
32#define CGU_REG_OPCR 0x24
33#define CGU_REG_CLKGR1 0x28
34#define CGU_REG_DDRCDR 0x2c
35#define CGU_REG_VPUCDR 0x30
36#define CGU_REG_USBPCR 0x3c
37#define CGU_REG_USBRDT 0x40
38#define CGU_REG_USBVBFIL 0x44
39#define CGU_REG_USBPCR1 0x48
40#define CGU_REG_LP0CDR 0x54
41#define CGU_REG_I2SCDR 0x60
42#define CGU_REG_LP1CDR 0x64
43#define CGU_REG_MSC0CDR 0x68
44#define CGU_REG_UHCCDR 0x6c
45#define CGU_REG_SSICDR 0x74
46#define CGU_REG_CIMCDR 0x7c
47#define CGU_REG_PCMCDR 0x84
48#define CGU_REG_GPUCDR 0x88
49#define CGU_REG_HDMICDR 0x8c
50#define CGU_REG_MSC1CDR 0xa4
51#define CGU_REG_MSC2CDR 0xa8
52#define CGU_REG_BCHCDR 0xac
53#define CGU_REG_CLOCKSTATUS 0xd4
54
55/* bits within the OPCR register */
56#define OPCR_SPENDN0 (1 << 7)
57#define OPCR_SPENDN1 (1 << 6)
58
59/* bits within the USBPCR register */
60#define USBPCR_USB_MODE BIT(31)
61#define USBPCR_IDPULLUP_MASK (0x3 << 28)
62#define USBPCR_COMMONONN BIT(25)
63#define USBPCR_VBUSVLDEXT BIT(24)
64#define USBPCR_VBUSVLDEXTSEL BIT(23)
65#define USBPCR_POR BIT(22)
66#define USBPCR_OTG_DISABLE BIT(20)
67#define USBPCR_COMPDISTUNE_MASK (0x7 << 17)
68#define USBPCR_OTGTUNE_MASK (0x7 << 14)
69#define USBPCR_SQRXTUNE_MASK (0x7 << 11)
70#define USBPCR_TXFSLSTUNE_MASK (0xf << 7)
71#define USBPCR_TXPREEMPHTUNE BIT(6)
72#define USBPCR_TXHSXVTUNE_MASK (0x3 << 4)
73#define USBPCR_TXVREFTUNE_MASK 0xf
74
75/* bits within the USBPCR1 register */
76#define USBPCR1_REFCLKSEL_SHIFT 26
77#define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
78#define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
79#define USBPCR1_REFCLKDIV_SHIFT 24
80#define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
81#define USBPCR1_REFCLKDIV_19_2 (0x3 << USBPCR1_REFCLKDIV_SHIFT)
82#define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
83#define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
84#define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
85#define USBPCR1_USB_SEL BIT(28)
86#define USBPCR1_WORD_IF0 BIT(19)
87#define USBPCR1_WORD_IF1 BIT(18)
88
89/* bits within the USBRDT register */
90#define USBRDT_VBFIL_LD_EN BIT(25)
91#define USBRDT_USBRDT_MASK 0x7fffff
92
93/* bits within the USBVBFIL register */
94#define USBVBFIL_IDDIGFIL_SHIFT 16
95#define USBVBFIL_IDDIGFIL_MASK (0xffff << USBVBFIL_IDDIGFIL_SHIFT)
96#define USBVBFIL_USBVBFIL_MASK (0xffff)
97
98static struct ingenic_cgu *cgu;
99
100static u8 jz4780_otg_phy_get_parent(struct clk_hw *hw)
101{
102 /* we only use CLKCORE, revisit if that ever changes */
103 return 0;
104}
105
106static int jz4780_otg_phy_set_parent(struct clk_hw *hw, u8 idx)
107{
108 unsigned long flags;
109 u32 usbpcr1;
110
111 if (idx > 0)
112 return -EINVAL;
113
114 spin_lock_irqsave(&cgu->lock, flags);
115
116 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
117 usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK;
118 /* we only use CLKCORE */
119 usbpcr1 |= USBPCR1_REFCLKSEL_CORE;
120 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
121
122 spin_unlock_irqrestore(&cgu->lock, flags);
123 return 0;
124}
125
126static unsigned long jz4780_otg_phy_recalc_rate(struct clk_hw *hw,
127 unsigned long parent_rate)
128{
129 u32 usbpcr1;
130 unsigned refclk_div;
131
132 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
133 refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK;
134
135 switch (refclk_div) {
136 case USBPCR1_REFCLKDIV_12:
137 return 12000000;
138
139 case USBPCR1_REFCLKDIV_24:
140 return 24000000;
141
142 case USBPCR1_REFCLKDIV_48:
143 return 48000000;
144
145 case USBPCR1_REFCLKDIV_19_2:
146 return 19200000;
147 }
148
149 BUG();
150 return parent_rate;
151}
152
153static long jz4780_otg_phy_round_rate(struct clk_hw *hw, unsigned long req_rate,
154 unsigned long *parent_rate)
155{
156 if (req_rate < 15600000)
157 return 12000000;
158
159 if (req_rate < 21600000)
160 return 19200000;
161
162 if (req_rate < 36000000)
163 return 24000000;
164
165 return 48000000;
166}
167
168static int jz4780_otg_phy_set_rate(struct clk_hw *hw, unsigned long req_rate,
169 unsigned long parent_rate)
170{
171 unsigned long flags;
172 u32 usbpcr1, div_bits;
173
174 switch (req_rate) {
175 case 12000000:
176 div_bits = USBPCR1_REFCLKDIV_12;
177 break;
178
179 case 19200000:
180 div_bits = USBPCR1_REFCLKDIV_19_2;
181 break;
182
183 case 24000000:
184 div_bits = USBPCR1_REFCLKDIV_24;
185 break;
186
187 case 48000000:
188 div_bits = USBPCR1_REFCLKDIV_48;
189 break;
190
191 default:
192 return -EINVAL;
193 }
194
195 spin_lock_irqsave(&cgu->lock, flags);
196
197 usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1);
198 usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK;
199 usbpcr1 |= div_bits;
200 writel(usbpcr1, cgu->base + CGU_REG_USBPCR1);
201
202 spin_unlock_irqrestore(&cgu->lock, flags);
203 return 0;
204}
205
206static struct clk_ops jz4780_otg_phy_ops = {
207 .get_parent = jz4780_otg_phy_get_parent,
208 .set_parent = jz4780_otg_phy_set_parent,
209
210 .recalc_rate = jz4780_otg_phy_recalc_rate,
211 .round_rate = jz4780_otg_phy_round_rate,
212 .set_rate = jz4780_otg_phy_set_rate,
213};
214
215static const s8 pll_od_encoding[16] = {
216 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
217 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
218};
219
220static const struct ingenic_cgu_clk_info jz4780_cgu_clocks[] = {
221
222 /* External clocks */
223
224 [JZ4780_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
225 [JZ4780_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
226
227 /* PLLs */
228
229#define DEF_PLL(name) { \
230 .reg = CGU_REG_ ## name, \
231 .m_shift = 19, \
232 .m_bits = 13, \
233 .m_offset = 1, \
234 .n_shift = 13, \
235 .n_bits = 6, \
236 .n_offset = 1, \
237 .od_shift = 9, \
238 .od_bits = 4, \
239 .od_max = 16, \
240 .od_encoding = pll_od_encoding, \
241 .stable_bit = 6, \
242 .bypass_bit = 1, \
243 .enable_bit = 0, \
244}
245
246 [JZ4780_CLK_APLL] = {
247 "apll", CGU_CLK_PLL,
248 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
249 .pll = DEF_PLL(APLL),
250 },
251
252 [JZ4780_CLK_MPLL] = {
253 "mpll", CGU_CLK_PLL,
254 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
255 .pll = DEF_PLL(MPLL),
256 },
257
258 [JZ4780_CLK_EPLL] = {
259 "epll", CGU_CLK_PLL,
260 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
261 .pll = DEF_PLL(EPLL),
262 },
263
264 [JZ4780_CLK_VPLL] = {
265 "vpll", CGU_CLK_PLL,
266 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
267 .pll = DEF_PLL(VPLL),
268 },
269
270#undef DEF_PLL
271
272 /* Custom (SoC-specific) OTG PHY */
273
274 [JZ4780_CLK_OTGPHY] = {
275 "otg_phy", CGU_CLK_CUSTOM,
276 .parents = { -1, -1, JZ4780_CLK_EXCLK, -1 },
277 .custom = { &jz4780_otg_phy_ops },
278 },
279
280 /* Muxes & dividers */
281
282 [JZ4780_CLK_SCLKA] = {
283 "sclk_a", CGU_CLK_MUX,
284 .parents = { -1, JZ4780_CLK_APLL, JZ4780_CLK_EXCLK,
285 JZ4780_CLK_RTCLK },
286 .mux = { CGU_REG_CLOCKCONTROL, 30, 2 },
287 },
288
289 [JZ4780_CLK_CPUMUX] = {
290 "cpumux", CGU_CLK_MUX,
291 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
292 JZ4780_CLK_EPLL },
293 .mux = { CGU_REG_CLOCKCONTROL, 28, 2 },
294 },
295
296 [JZ4780_CLK_CPU] = {
297 "cpu", CGU_CLK_DIV,
298 .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 },
299 .div = { CGU_REG_CLOCKCONTROL, 0, 4, 22, -1, -1 },
300 },
301
302 [JZ4780_CLK_L2CACHE] = {
303 "l2cache", CGU_CLK_DIV,
304 .parents = { JZ4780_CLK_CPUMUX, -1, -1, -1 },
305 .div = { CGU_REG_CLOCKCONTROL, 4, 4, -1, -1, -1 },
306 },
307
308 [JZ4780_CLK_AHB0] = {
309 "ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
310 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
311 JZ4780_CLK_EPLL },
312 .mux = { CGU_REG_CLOCKCONTROL, 26, 2 },
313 .div = { CGU_REG_CLOCKCONTROL, 8, 4, 21, -1, -1 },
314 },
315
316 [JZ4780_CLK_AHB2PMUX] = {
317 "ahb2_apb_mux", CGU_CLK_MUX,
318 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
319 JZ4780_CLK_RTCLK },
320 .mux = { CGU_REG_CLOCKCONTROL, 24, 2 },
321 },
322
323 [JZ4780_CLK_AHB2] = {
324 "ahb2", CGU_CLK_DIV,
325 .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 },
326 .div = { CGU_REG_CLOCKCONTROL, 12, 4, 20, -1, -1 },
327 },
328
329 [JZ4780_CLK_PCLK] = {
330 "pclk", CGU_CLK_DIV,
331 .parents = { JZ4780_CLK_AHB2PMUX, -1, -1, -1 },
332 .div = { CGU_REG_CLOCKCONTROL, 16, 4, 20, -1, -1 },
333 },
334
335 [JZ4780_CLK_DDR] = {
336 "ddr", CGU_CLK_MUX | CGU_CLK_DIV,
337 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
338 .mux = { CGU_REG_DDRCDR, 30, 2 },
339 .div = { CGU_REG_DDRCDR, 0, 4, 29, 28, 27 },
340 },
341
342 [JZ4780_CLK_VPU] = {
343 "vpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
344 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
345 JZ4780_CLK_EPLL, -1 },
346 .mux = { CGU_REG_VPUCDR, 30, 2 },
347 .div = { CGU_REG_VPUCDR, 0, 4, 29, 28, 27 },
348 .gate = { CGU_REG_CLKGR1, 2 },
349 },
350
351 [JZ4780_CLK_I2SPLL] = {
352 "i2s_pll", CGU_CLK_MUX | CGU_CLK_DIV,
353 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_EPLL, -1, -1 },
354 .mux = { CGU_REG_I2SCDR, 30, 1 },
355 .div = { CGU_REG_I2SCDR, 0, 8, 29, 28, 27 },
356 },
357
358 [JZ4780_CLK_I2S] = {
359 "i2s", CGU_CLK_MUX,
360 .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_I2SPLL, -1, -1 },
361 .mux = { CGU_REG_I2SCDR, 31, 1 },
362 },
363
364 [JZ4780_CLK_LCD0PIXCLK] = {
365 "lcd0pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
366 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
367 JZ4780_CLK_VPLL, -1 },
368 .mux = { CGU_REG_LP0CDR, 30, 2 },
369 .div = { CGU_REG_LP0CDR, 0, 8, 28, 27, 26 },
370 },
371
372 [JZ4780_CLK_LCD1PIXCLK] = {
373 "lcd1pixclk", CGU_CLK_MUX | CGU_CLK_DIV,
374 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
375 JZ4780_CLK_VPLL, -1 },
376 .mux = { CGU_REG_LP1CDR, 30, 2 },
377 .div = { CGU_REG_LP1CDR, 0, 8, 28, 27, 26 },
378 },
379
380 [JZ4780_CLK_MSCMUX] = {
381 "msc_mux", CGU_CLK_MUX,
382 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1 },
383 .mux = { CGU_REG_MSC0CDR, 30, 2 },
384 },
385
386 [JZ4780_CLK_MSC0] = {
387 "msc0", CGU_CLK_DIV | CGU_CLK_GATE,
388 .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
389 .div = { CGU_REG_MSC0CDR, 0, 8, 29, 28, 27 },
390 .gate = { CGU_REG_CLKGR0, 3 },
391 },
392
393 [JZ4780_CLK_MSC1] = {
394 "msc1", CGU_CLK_DIV | CGU_CLK_GATE,
395 .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
396 .div = { CGU_REG_MSC1CDR, 0, 8, 29, 28, 27 },
397 .gate = { CGU_REG_CLKGR0, 11 },
398 },
399
400 [JZ4780_CLK_MSC2] = {
401 "msc2", CGU_CLK_DIV | CGU_CLK_GATE,
402 .parents = { JZ4780_CLK_MSCMUX, -1, -1, -1 },
403 .div = { CGU_REG_MSC2CDR, 0, 8, 29, 28, 27 },
404 .gate = { CGU_REG_CLKGR0, 12 },
405 },
406
407 [JZ4780_CLK_UHC] = {
408 "uhc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
409 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
410 JZ4780_CLK_EPLL, JZ4780_CLK_OTGPHY },
411 .mux = { CGU_REG_UHCCDR, 30, 2 },
412 .div = { CGU_REG_UHCCDR, 0, 8, 29, 28, 27 },
413 .gate = { CGU_REG_CLKGR0, 24 },
414 },
415
416 [JZ4780_CLK_SSIPLL] = {
417 "ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
418 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 },
419 .mux = { CGU_REG_SSICDR, 30, 1 },
420 .div = { CGU_REG_SSICDR, 0, 8, 29, 28, 27 },
421 },
422
423 [JZ4780_CLK_SSI] = {
424 "ssi", CGU_CLK_MUX,
425 .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_SSIPLL, -1, -1 },
426 .mux = { CGU_REG_SSICDR, 31, 1 },
427 },
428
429 [JZ4780_CLK_CIMMCLK] = {
430 "cim_mclk", CGU_CLK_MUX | CGU_CLK_DIV,
431 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL, -1, -1 },
432 .mux = { CGU_REG_CIMCDR, 31, 1 },
433 .div = { CGU_REG_CIMCDR, 0, 8, 30, 29, 28 },
434 },
435
436 [JZ4780_CLK_PCMPLL] = {
437 "pcm_pll", CGU_CLK_MUX | CGU_CLK_DIV,
438 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
439 JZ4780_CLK_EPLL, JZ4780_CLK_VPLL },
440 .mux = { CGU_REG_PCMCDR, 29, 2 },
441 .div = { CGU_REG_PCMCDR, 0, 8, 28, 27, 26 },
442 },
443
444 [JZ4780_CLK_PCM] = {
445 "pcm", CGU_CLK_MUX | CGU_CLK_GATE,
446 .parents = { JZ4780_CLK_EXCLK, JZ4780_CLK_PCMPLL, -1, -1 },
447 .mux = { CGU_REG_PCMCDR, 31, 1 },
448 .gate = { CGU_REG_CLKGR1, 3 },
449 },
450
451 [JZ4780_CLK_GPU] = {
452 "gpu", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
453 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
454 JZ4780_CLK_EPLL },
455 .mux = { CGU_REG_GPUCDR, 30, 2 },
456 .div = { CGU_REG_GPUCDR, 0, 4, 29, 28, 27 },
457 .gate = { CGU_REG_CLKGR1, 4 },
458 },
459
460 [JZ4780_CLK_HDMI] = {
461 "hdmi", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
462 .parents = { JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
463 JZ4780_CLK_VPLL, -1 },
464 .mux = { CGU_REG_HDMICDR, 30, 2 },
465 .div = { CGU_REG_HDMICDR, 0, 8, 29, 28, 26 },
466 .gate = { CGU_REG_CLKGR1, 9 },
467 },
468
469 [JZ4780_CLK_BCH] = {
470 "bch", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
471 .parents = { -1, JZ4780_CLK_SCLKA, JZ4780_CLK_MPLL,
472 JZ4780_CLK_EPLL },
473 .mux = { CGU_REG_BCHCDR, 30, 2 },
474 .div = { CGU_REG_BCHCDR, 0, 4, 29, 28, 27 },
475 .gate = { CGU_REG_CLKGR0, 1 },
476 },
477
478 /* Gate-only clocks */
479
480 [JZ4780_CLK_NEMC] = {
481 "nemc", CGU_CLK_GATE,
482 .parents = { JZ4780_CLK_AHB2, -1, -1, -1 },
483 .gate = { CGU_REG_CLKGR0, 0 },
484 },
485
486 [JZ4780_CLK_OTG0] = {
487 "otg0", CGU_CLK_GATE,
488 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
489 .gate = { CGU_REG_CLKGR0, 2 },
490 },
491
492 [JZ4780_CLK_SSI0] = {
493 "ssi0", CGU_CLK_GATE,
494 .parents = { JZ4780_CLK_SSI, -1, -1, -1 },
495 .gate = { CGU_REG_CLKGR0, 4 },
496 },
497
498 [JZ4780_CLK_SMB0] = {
499 "smb0", CGU_CLK_GATE,
500 .parents = { JZ4780_CLK_PCLK, -1, -1, -1 },
501 .gate = { CGU_REG_CLKGR0, 5 },
502 },
503
504 [JZ4780_CLK_SMB1] = {
505 "smb1", CGU_CLK_GATE,
506 .parents = { JZ4780_CLK_PCLK, -1, -1, -1 },
507 .gate = { CGU_REG_CLKGR0, 6 },
508 },
509
510 [JZ4780_CLK_SCC] = {
511 "scc", CGU_CLK_GATE,
512 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
513 .gate = { CGU_REG_CLKGR0, 7 },
514 },
515
516 [JZ4780_CLK_AIC] = {
517 "aic", CGU_CLK_GATE,
518 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
519 .gate = { CGU_REG_CLKGR0, 8 },
520 },
521
522 [JZ4780_CLK_TSSI0] = {
523 "tssi0", CGU_CLK_GATE,
524 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
525 .gate = { CGU_REG_CLKGR0, 9 },
526 },
527
528 [JZ4780_CLK_OWI] = {
529 "owi", CGU_CLK_GATE,
530 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
531 .gate = { CGU_REG_CLKGR0, 10 },
532 },
533
534 [JZ4780_CLK_KBC] = {
535 "kbc", CGU_CLK_GATE,
536 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
537 .gate = { CGU_REG_CLKGR0, 13 },
538 },
539
540 [JZ4780_CLK_SADC] = {
541 "sadc", CGU_CLK_GATE,
542 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
543 .gate = { CGU_REG_CLKGR0, 14 },
544 },
545
546 [JZ4780_CLK_UART0] = {
547 "uart0", CGU_CLK_GATE,
548 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
549 .gate = { CGU_REG_CLKGR0, 15 },
550 },
551
552 [JZ4780_CLK_UART1] = {
553 "uart1", CGU_CLK_GATE,
554 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
555 .gate = { CGU_REG_CLKGR0, 16 },
556 },
557
558 [JZ4780_CLK_UART2] = {
559 "uart2", CGU_CLK_GATE,
560 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
561 .gate = { CGU_REG_CLKGR0, 17 },
562 },
563
564 [JZ4780_CLK_UART3] = {
565 "uart3", CGU_CLK_GATE,
566 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
567 .gate = { CGU_REG_CLKGR0, 18 },
568 },
569
570 [JZ4780_CLK_SSI1] = {
571 "ssi1", CGU_CLK_GATE,
572 .parents = { JZ4780_CLK_SSI, -1, -1, -1 },
573 .gate = { CGU_REG_CLKGR0, 19 },
574 },
575
576 [JZ4780_CLK_SSI2] = {
577 "ssi2", CGU_CLK_GATE,
578 .parents = { JZ4780_CLK_SSI, -1, -1, -1 },
579 .gate = { CGU_REG_CLKGR0, 20 },
580 },
581
582 [JZ4780_CLK_PDMA] = {
583 "pdma", CGU_CLK_GATE,
584 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
585 .gate = { CGU_REG_CLKGR0, 21 },
586 },
587
588 [JZ4780_CLK_GPS] = {
589 "gps", CGU_CLK_GATE,
590 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
591 .gate = { CGU_REG_CLKGR0, 22 },
592 },
593
594 [JZ4780_CLK_MAC] = {
595 "mac", CGU_CLK_GATE,
596 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
597 .gate = { CGU_REG_CLKGR0, 23 },
598 },
599
600 [JZ4780_CLK_SMB2] = {
601 "smb2", CGU_CLK_GATE,
602 .parents = { JZ4780_CLK_PCLK, -1, -1, -1 },
603 .gate = { CGU_REG_CLKGR0, 24 },
604 },
605
606 [JZ4780_CLK_CIM] = {
607 "cim", CGU_CLK_GATE,
608 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
609 .gate = { CGU_REG_CLKGR0, 26 },
610 },
611
612 [JZ4780_CLK_LCD] = {
613 "lcd", CGU_CLK_GATE,
614 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
615 .gate = { CGU_REG_CLKGR0, 28 },
616 },
617
618 [JZ4780_CLK_TVE] = {
619 "tve", CGU_CLK_GATE,
620 .parents = { JZ4780_CLK_LCD, -1, -1, -1 },
621 .gate = { CGU_REG_CLKGR0, 27 },
622 },
623
624 [JZ4780_CLK_IPU] = {
625 "ipu", CGU_CLK_GATE,
626 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
627 .gate = { CGU_REG_CLKGR0, 29 },
628 },
629
630 [JZ4780_CLK_DDR0] = {
631 "ddr0", CGU_CLK_GATE,
632 .parents = { JZ4780_CLK_DDR, -1, -1, -1 },
633 .gate = { CGU_REG_CLKGR0, 30 },
634 },
635
636 [JZ4780_CLK_DDR1] = {
637 "ddr1", CGU_CLK_GATE,
638 .parents = { JZ4780_CLK_DDR, -1, -1, -1 },
639 .gate = { CGU_REG_CLKGR0, 31 },
640 },
641
642 [JZ4780_CLK_SMB3] = {
643 "smb3", CGU_CLK_GATE,
644 .parents = { JZ4780_CLK_PCLK, -1, -1, -1 },
645 .gate = { CGU_REG_CLKGR1, 0 },
646 },
647
648 [JZ4780_CLK_TSSI1] = {
649 "tssi1", CGU_CLK_GATE,
650 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
651 .gate = { CGU_REG_CLKGR1, 1 },
652 },
653
654 [JZ4780_CLK_COMPRESS] = {
655 "compress", CGU_CLK_GATE,
656 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
657 .gate = { CGU_REG_CLKGR1, 5 },
658 },
659
660 [JZ4780_CLK_AIC1] = {
661 "aic1", CGU_CLK_GATE,
662 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
663 .gate = { CGU_REG_CLKGR1, 6 },
664 },
665
666 [JZ4780_CLK_GPVLC] = {
667 "gpvlc", CGU_CLK_GATE,
668 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
669 .gate = { CGU_REG_CLKGR1, 7 },
670 },
671
672 [JZ4780_CLK_OTG1] = {
673 "otg1", CGU_CLK_GATE,
674 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
675 .gate = { CGU_REG_CLKGR1, 8 },
676 },
677
678 [JZ4780_CLK_UART4] = {
679 "uart4", CGU_CLK_GATE,
680 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
681 .gate = { CGU_REG_CLKGR1, 10 },
682 },
683
684 [JZ4780_CLK_AHBMON] = {
685 "ahb_mon", CGU_CLK_GATE,
686 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
687 .gate = { CGU_REG_CLKGR1, 11 },
688 },
689
690 [JZ4780_CLK_SMB4] = {
691 "smb4", CGU_CLK_GATE,
692 .parents = { JZ4780_CLK_PCLK, -1, -1, -1 },
693 .gate = { CGU_REG_CLKGR1, 12 },
694 },
695
696 [JZ4780_CLK_DES] = {
697 "des", CGU_CLK_GATE,
698 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
699 .gate = { CGU_REG_CLKGR1, 13 },
700 },
701
702 [JZ4780_CLK_X2D] = {
703 "x2d", CGU_CLK_GATE,
704 .parents = { JZ4780_CLK_EXCLK, -1, -1, -1 },
705 .gate = { CGU_REG_CLKGR1, 14 },
706 },
707
708 [JZ4780_CLK_CORE1] = {
709 "core1", CGU_CLK_GATE,
710 .parents = { JZ4780_CLK_CPU, -1, -1, -1 },
711 .gate = { CGU_REG_CLKGR1, 15 },
712 },
713
714};
715
716static void __init jz4780_cgu_init(struct device_node *np)
717{
718 int retval;
719
720 cgu = ingenic_cgu_new(jz4780_cgu_clocks,
721 ARRAY_SIZE(jz4780_cgu_clocks), np);
722 if (!cgu) {
723 pr_err("%s: failed to initialise CGU\n", __func__);
724 return;
725 }
726
727 retval = ingenic_cgu_register_clocks(cgu);
728 if (retval) {
729 pr_err("%s: failed to register CGU Clocks\n", __func__);
730 return;
731 }
732}
733CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
diff --git a/drivers/cpufreq/ls1x-cpufreq.c b/drivers/cpufreq/ls1x-cpufreq.c
index f0913eee2f50..262581b3318d 100644
--- a/drivers/cpufreq/ls1x-cpufreq.c
+++ b/drivers/cpufreq/ls1x-cpufreq.c
@@ -17,8 +17,8 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19 19
20#include <asm/mach-loongson1/cpufreq.h> 20#include <cpufreq.h>
21#include <asm/mach-loongson1/loongson1.h> 21#include <loongson1.h>
22 22
23static struct { 23static struct {
24 struct device *dev; 24 struct device *dev;
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6517132e5d8b..99c69a3205c4 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -136,6 +136,7 @@ config QCOM_SCM
136 bool 136 bool
137 depends on ARM || ARM64 137 depends on ARM || ARM64
138 138
139source "drivers/firmware/broadcom/Kconfig"
139source "drivers/firmware/google/Kconfig" 140source "drivers/firmware/google/Kconfig"
140source "drivers/firmware/efi/Kconfig" 141source "drivers/firmware/efi/Kconfig"
141 142
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 3001f1ae1062..4a4b897f9314 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_QCOM_SCM) += qcom_scm.o
15obj-$(CONFIG_QCOM_SCM) += qcom_scm-32.o 15obj-$(CONFIG_QCOM_SCM) += qcom_scm-32.o
16CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) 16CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
17 17
18obj-y += broadcom/
18obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 19obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
19obj-$(CONFIG_EFI) += efi/ 20obj-$(CONFIG_EFI) += efi/
20obj-$(CONFIG_UEFI_CPER) += efi/ 21obj-$(CONFIG_UEFI_CPER) += efi/
diff --git a/drivers/firmware/broadcom/Kconfig b/drivers/firmware/broadcom/Kconfig
new file mode 100644
index 000000000000..6bed119930dd
--- /dev/null
+++ b/drivers/firmware/broadcom/Kconfig
@@ -0,0 +1,11 @@
1config BCM47XX_NVRAM
2 bool "Broadcom NVRAM driver"
3 depends on BCM47XX || ARCH_BCM_5301X
4 help
5 Broadcom home routers contain flash partition called "nvram" with all
6 important hardware configuration as well as some minor user setup.
7 NVRAM partition contains a text-like data representing name=value
8 pairs.
9 This driver provides an easy way to get value of requested parameter.
10 It simply reads content of NVRAM and parses it. It doesn't control any
11 hardware part itself.
diff --git a/drivers/firmware/broadcom/Makefile b/drivers/firmware/broadcom/Makefile
new file mode 100644
index 000000000000..d0e683583cd6
--- /dev/null
+++ b/drivers/firmware/broadcom/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_BCM47XX_NVRAM) += bcm47xx_nvram.o
diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c
new file mode 100644
index 000000000000..87add3fdce52
--- /dev/null
+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c
@@ -0,0 +1,248 @@
1/*
2 * BCM947xx nvram variable access
3 *
4 * Copyright (C) 2005 Broadcom Corporation
5 * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
6 * Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/io.h>
15#include <linux/types.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/string.h>
19#include <linux/mtd/mtd.h>
20#include <linux/bcm47xx_nvram.h>
21
22#define NVRAM_MAGIC 0x48534C46 /* 'FLSH' */
23#define NVRAM_SPACE 0x10000
24#define NVRAM_MAX_GPIO_ENTRIES 32
25#define NVRAM_MAX_GPIO_VALUE_LEN 30
26
27#define FLASH_MIN 0x00020000 /* Minimum flash size */
28
29struct nvram_header {
30 u32 magic;
31 u32 len;
32 u32 crc_ver_init; /* 0:7 crc, 8:15 ver, 16:31 sdram_init */
33 u32 config_refresh; /* 0:15 sdram_config, 16:31 sdram_refresh */
34 u32 config_ncdl; /* ncdl values for memc */
35};
36
37static char nvram_buf[NVRAM_SPACE];
38static size_t nvram_len;
39static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
40
41static u32 find_nvram_size(void __iomem *end)
42{
43 struct nvram_header __iomem *header;
44 int i;
45
46 for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
47 header = (struct nvram_header *)(end - nvram_sizes[i]);
48 if (header->magic == NVRAM_MAGIC)
49 return nvram_sizes[i];
50 }
51
52 return 0;
53}
54
55/* Probe for NVRAM header */
56static int nvram_find_and_copy(void __iomem *iobase, u32 lim)
57{
58 struct nvram_header __iomem *header;
59 int i;
60 u32 off;
61 u32 *src, *dst;
62 u32 size;
63
64 if (nvram_len) {
65 pr_warn("nvram already initialized\n");
66 return -EEXIST;
67 }
68
69 /* TODO: when nvram is on nand flash check for bad blocks first. */
70 off = FLASH_MIN;
71 while (off <= lim) {
72 /* Windowed flash access */
73 size = find_nvram_size(iobase + off);
74 if (size) {
75 header = (struct nvram_header *)(iobase + off - size);
76 goto found;
77 }
78 off <<= 1;
79 }
80
81 /* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
82 header = (struct nvram_header *)(iobase + 4096);
83 if (header->magic == NVRAM_MAGIC) {
84 size = NVRAM_SPACE;
85 goto found;
86 }
87
88 header = (struct nvram_header *)(iobase + 1024);
89 if (header->magic == NVRAM_MAGIC) {
90 size = NVRAM_SPACE;
91 goto found;
92 }
93
94 pr_err("no nvram found\n");
95 return -ENXIO;
96
97found:
98 src = (u32 *)header;
99 dst = (u32 *)nvram_buf;
100 for (i = 0; i < sizeof(struct nvram_header); i += 4)
101 *dst++ = __raw_readl(src++);
102 header = (struct nvram_header *)nvram_buf;
103 nvram_len = header->len;
104 if (nvram_len > size) {
105 pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n");
106 nvram_len = size;
107 }
108 if (nvram_len >= NVRAM_SPACE) {
109 pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
110 header->len, NVRAM_SPACE - 1);
111 nvram_len = NVRAM_SPACE - 1;
112 }
113 /* proceed reading data after header */
114 for (; i < nvram_len; i += 4)
115 *dst++ = readl(src++);
116 nvram_buf[NVRAM_SPACE - 1] = '\0';
117
118 return 0;
119}
120
121/*
122 * On bcm47xx we need access to the NVRAM very early, so we can't use mtd
123 * subsystem to access flash. We can't even use platform device / driver to
124 * store memory offset.
125 * To handle this we provide following symbol. It's supposed to be called as
126 * soon as we get info about flash device, before any NVRAM entry is needed.
127 */
128int bcm47xx_nvram_init_from_mem(u32 base, u32 lim)
129{
130 void __iomem *iobase;
131 int err;
132
133 iobase = ioremap_nocache(base, lim);
134 if (!iobase)
135 return -ENOMEM;
136
137 err = nvram_find_and_copy(iobase, lim);
138
139 iounmap(iobase);
140
141 return err;
142}
143
144static int nvram_init(void)
145{
146#ifdef CONFIG_MTD
147 struct mtd_info *mtd;
148 struct nvram_header header;
149 size_t bytes_read;
150 int err;
151
152 mtd = get_mtd_device_nm("nvram");
153 if (IS_ERR(mtd))
154 return -ENODEV;
155
156 err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header);
157 if (!err && header.magic == NVRAM_MAGIC &&
158 header.len > sizeof(header)) {
159 nvram_len = header.len;
160 if (nvram_len >= NVRAM_SPACE) {
161 pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
162 header.len, NVRAM_SPACE);
163 nvram_len = NVRAM_SPACE - 1;
164 }
165
166 err = mtd_read(mtd, 0, nvram_len, &nvram_len,
167 (u8 *)nvram_buf);
168 return err;
169 }
170#endif
171
172 return -ENXIO;
173}
174
175int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len)
176{
177 char *var, *value, *end, *eq;
178 int err;
179
180 if (!name)
181 return -EINVAL;
182
183 if (!nvram_len) {
184 err = nvram_init();
185 if (err)
186 return err;
187 }
188
189 /* Look for name=value and return value */
190 var = &nvram_buf[sizeof(struct nvram_header)];
191 end = nvram_buf + sizeof(nvram_buf);
192 while (var < end && *var) {
193 eq = strchr(var, '=');
194 if (!eq)
195 break;
196 value = eq + 1;
197 if (eq - var == strlen(name) &&
198 strncmp(var, name, eq - var) == 0)
199 return snprintf(val, val_len, "%s", value);
200 var = value + strlen(value) + 1;
201 }
202 return -ENOENT;
203}
204EXPORT_SYMBOL(bcm47xx_nvram_getenv);
205
206int bcm47xx_nvram_gpio_pin(const char *name)
207{
208 int i, err;
209 char nvram_var[] = "gpioXX";
210 char buf[NVRAM_MAX_GPIO_VALUE_LEN];
211
212 /* TODO: Optimize it to don't call getenv so many times */
213 for (i = 0; i < NVRAM_MAX_GPIO_ENTRIES; i++) {
214 err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i);
215 if (err <= 0)
216 continue;
217 err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf));
218 if (err <= 0)
219 continue;
220 if (!strcmp(name, buf))
221 return i;
222 }
223 return -ENOENT;
224}
225EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
226
227char *bcm47xx_nvram_get_contents(size_t *nvram_size)
228{
229 int err;
230 char *nvram;
231
232 if (!nvram_len) {
233 err = nvram_init();
234 if (err)
235 return NULL;
236 }
237
238 *nvram_size = nvram_len - sizeof(struct nvram_header);
239 nvram = vmalloc(*nvram_size);
240 if (!nvram)
241 return NULL;
242 memcpy(nvram, &nvram_buf[sizeof(struct nvram_header)], *nvram_size);
243
244 return nvram;
245}
246EXPORT_SYMBOL(bcm47xx_nvram_get_contents);
247
248MODULE_LICENSE("GPLv2");
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 8a7d7807b596..120d81543e53 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -86,6 +86,11 @@ config IMGPDC_IRQ
86 select GENERIC_IRQ_CHIP 86 select GENERIC_IRQ_CHIP
87 select IRQ_DOMAIN 87 select IRQ_DOMAIN
88 88
89config IRQ_MIPS_CPU
90 bool
91 select GENERIC_IRQ_CHIP
92 select IRQ_DOMAIN
93
89config CLPS711X_IRQCHIP 94config CLPS711X_IRQCHIP
90 bool 95 bool
91 depends on ARCH_CLPS711X 96 depends on ARCH_CLPS711X
@@ -160,10 +165,15 @@ config MIPS_GIC
160 bool 165 bool
161 select MIPS_CM 166 select MIPS_CM
162 167
168config INGENIC_IRQ
169 bool
170 depends on MACH_INGENIC
171 default y
172
163config RENESAS_H8300H_INTC 173config RENESAS_H8300H_INTC
164 bool 174 bool
165 select IRQ_DOMAIN 175 select IRQ_DOMAIN
166 176
167config RENESAS_H8S_INTC 177config RENESAS_H8S_INTC
168 bool 178 bool
169 select IRQ_DOMAIN \ No newline at end of file 179 select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 5c9adf1f554d..b8d4e9691890 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_ARM_VIC) += irq-vic.o
28obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o 28obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
29obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o 29obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o
30obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o 30obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
31obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
31obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o 32obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
32obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o 33obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
33obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o 34obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
@@ -50,3 +51,4 @@ obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
50obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o 51obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o
51obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o 52obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
52obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o 53obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
54obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o
diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c
new file mode 100644
index 000000000000..005de3f932ae
--- /dev/null
+++ b/drivers/irqchip/irq-ingenic.c
@@ -0,0 +1,177 @@
1/*
2 * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
3 * JZ4740 platform IRQ support
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * You should have received a copy of the GNU General Public License along
11 * with this program; if not, write to the Free Software Foundation, Inc.,
12 * 675 Mass Ave, Cambridge, MA 02139, USA.
13 *
14 */
15
16#include <linux/errno.h>
17#include <linux/init.h>
18#include <linux/types.h>
19#include <linux/interrupt.h>
20#include <linux/ioport.h>
21#include <linux/irqchip/ingenic.h>
22#include <linux/of_address.h>
23#include <linux/of_irq.h>
24#include <linux/timex.h>
25#include <linux/slab.h>
26#include <linux/delay.h>
27
28#include <asm/io.h>
29#include <asm/mach-jz4740/irq.h>
30
31#include "irqchip.h"
32
33struct ingenic_intc_data {
34 void __iomem *base;
35 unsigned num_chips;
36};
37
38#define JZ_REG_INTC_STATUS 0x00
39#define JZ_REG_INTC_MASK 0x04
40#define JZ_REG_INTC_SET_MASK 0x08
41#define JZ_REG_INTC_CLEAR_MASK 0x0c
42#define JZ_REG_INTC_PENDING 0x10
43#define CHIP_SIZE 0x20
44
45static irqreturn_t intc_cascade(int irq, void *data)
46{
47 struct ingenic_intc_data *intc = irq_get_handler_data(irq);
48 uint32_t irq_reg;
49 unsigned i;
50
51 for (i = 0; i < intc->num_chips; i++) {
52 irq_reg = readl(intc->base + (i * CHIP_SIZE) +
53 JZ_REG_INTC_PENDING);
54 if (!irq_reg)
55 continue;
56
57 generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE);
58 }
59
60 return IRQ_HANDLED;
61}
62
63static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
64{
65 struct irq_chip_regs *regs = &gc->chip_types->regs;
66
67 writel(mask, gc->reg_base + regs->enable);
68 writel(~mask, gc->reg_base + regs->disable);
69}
70
71void ingenic_intc_irq_suspend(struct irq_data *data)
72{
73 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
74 intc_irq_set_mask(gc, gc->wake_active);
75}
76
77void ingenic_intc_irq_resume(struct irq_data *data)
78{
79 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
80 intc_irq_set_mask(gc, gc->mask_cache);
81}
82
83static struct irqaction intc_cascade_action = {
84 .handler = intc_cascade,
85 .name = "SoC intc cascade interrupt",
86};
87
88static int __init ingenic_intc_of_init(struct device_node *node,
89 unsigned num_chips)
90{
91 struct ingenic_intc_data *intc;
92 struct irq_chip_generic *gc;
93 struct irq_chip_type *ct;
94 struct irq_domain *domain;
95 int parent_irq, err = 0;
96 unsigned i;
97
98 intc = kzalloc(sizeof(*intc), GFP_KERNEL);
99 if (!intc) {
100 err = -ENOMEM;
101 goto out_err;
102 }
103
104 parent_irq = irq_of_parse_and_map(node, 0);
105 if (!parent_irq) {
106 err = -EINVAL;
107 goto out_free;
108 }
109
110 err = irq_set_handler_data(parent_irq, intc);
111 if (err)
112 goto out_unmap_irq;
113
114 intc->num_chips = num_chips;
115 intc->base = of_iomap(node, 0);
116 if (!intc->base) {
117 err = -ENODEV;
118 goto out_unmap_irq;
119 }
120
121 for (i = 0; i < num_chips; i++) {
122 /* Mask all irqs */
123 writel(0xffffffff, intc->base + (i * CHIP_SIZE) +
124 JZ_REG_INTC_SET_MASK);
125
126 gc = irq_alloc_generic_chip("INTC", 1,
127 JZ4740_IRQ_BASE + (i * 32),
128 intc->base + (i * CHIP_SIZE),
129 handle_level_irq);
130
131 gc->wake_enabled = IRQ_MSK(32);
132
133 ct = gc->chip_types;
134 ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
135 ct->regs.disable = JZ_REG_INTC_SET_MASK;
136 ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
137 ct->chip.irq_mask = irq_gc_mask_disable_reg;
138 ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
139 ct->chip.irq_set_wake = irq_gc_set_wake;
140 ct->chip.irq_suspend = ingenic_intc_irq_suspend;
141 ct->chip.irq_resume = ingenic_intc_irq_resume;
142
143 irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
144 IRQ_NOPROBE | IRQ_LEVEL);
145 }
146
147 domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
148 &irq_domain_simple_ops, NULL);
149 if (!domain)
150 pr_warn("unable to register IRQ domain\n");
151
152 setup_irq(parent_irq, &intc_cascade_action);
153 return 0;
154
155out_unmap_irq:
156 irq_dispose_mapping(parent_irq);
157out_free:
158 kfree(intc);
159out_err:
160 return err;
161}
162
163static int __init intc_1chip_of_init(struct device_node *node,
164 struct device_node *parent)
165{
166 return ingenic_intc_of_init(node, 1);
167}
168IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
169
170static int __init intc_2chip_of_init(struct device_node *node,
171 struct device_node *parent)
172{
173 return ingenic_intc_of_init(node, 2);
174}
175IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
176IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
177IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);
diff --git a/drivers/irqchip/irq-mips-cpu.c b/drivers/irqchip/irq-mips-cpu.c
new file mode 100644
index 000000000000..a43c41988009
--- /dev/null
+++ b/drivers/irqchip/irq-mips-cpu.c
@@ -0,0 +1,172 @@
1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * Copyright (C) 2001 Ralf Baechle
6 * Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
7 * Author: Maciej W. Rozycki <macro@mips.com>
8 *
9 * This file define the irq handler for MIPS CPU interrupts.
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
15 */
16
17/*
18 * Almost all MIPS CPUs define 8 interrupt sources. They are typically
19 * level triggered (i.e., cannot be cleared from CPU; must be cleared from
20 * device). The first two are software interrupts which we don't really
21 * use or support. The last one is usually the CPU timer interrupt if
22 * counter register is present or, for CPUs with an external FPU, by
23 * convention it's the FPU exception interrupt.
24 *
25 * Don't even think about using this on SMP. You have been warned.
26 *
27 * This file exports one global function:
28 * void mips_cpu_irq_init(void);
29 */
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/kernel.h>
33#include <linux/irq.h>
34#include <linux/irqdomain.h>
35
36#include <asm/irq_cpu.h>
37#include <asm/mipsregs.h>
38#include <asm/mipsmtregs.h>
39#include <asm/setup.h>
40
41#include "irqchip.h"
42
43static inline void unmask_mips_irq(struct irq_data *d)
44{
45 set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
46 irq_enable_hazard();
47}
48
49static inline void mask_mips_irq(struct irq_data *d)
50{
51 clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
52 irq_disable_hazard();
53}
54
55static struct irq_chip mips_cpu_irq_controller = {
56 .name = "MIPS",
57 .irq_ack = mask_mips_irq,
58 .irq_mask = mask_mips_irq,
59 .irq_mask_ack = mask_mips_irq,
60 .irq_unmask = unmask_mips_irq,
61 .irq_eoi = unmask_mips_irq,
62 .irq_disable = mask_mips_irq,
63 .irq_enable = unmask_mips_irq,
64};
65
66/*
67 * Basically the same as above but taking care of all the MT stuff
68 */
69
70static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
71{
72 unsigned int vpflags = dvpe();
73
74 clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
75 evpe(vpflags);
76 unmask_mips_irq(d);
77 return 0;
78}
79
80/*
81 * While we ack the interrupt interrupts are disabled and thus we don't need
82 * to deal with concurrency issues. Same for mips_cpu_irq_end.
83 */
84static void mips_mt_cpu_irq_ack(struct irq_data *d)
85{
86 unsigned int vpflags = dvpe();
87 clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
88 evpe(vpflags);
89 mask_mips_irq(d);
90}
91
92static struct irq_chip mips_mt_cpu_irq_controller = {
93 .name = "MIPS",
94 .irq_startup = mips_mt_cpu_irq_startup,
95 .irq_ack = mips_mt_cpu_irq_ack,
96 .irq_mask = mask_mips_irq,
97 .irq_mask_ack = mips_mt_cpu_irq_ack,
98 .irq_unmask = unmask_mips_irq,
99 .irq_eoi = unmask_mips_irq,
100 .irq_disable = mask_mips_irq,
101 .irq_enable = unmask_mips_irq,
102};
103
104asmlinkage void __weak plat_irq_dispatch(void)
105{
106 unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
107 int irq;
108
109 if (!pending) {
110 spurious_interrupt();
111 return;
112 }
113
114 pending >>= CAUSEB_IP;
115 while (pending) {
116 irq = fls(pending) - 1;
117 do_IRQ(MIPS_CPU_IRQ_BASE + irq);
118 pending &= ~BIT(irq);
119 }
120}
121
122static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
123 irq_hw_number_t hw)
124{
125 static struct irq_chip *chip;
126
127 if (hw < 2 && cpu_has_mipsmt) {
128 /* Software interrupts are used for MT/CMT IPI */
129 chip = &mips_mt_cpu_irq_controller;
130 } else {
131 chip = &mips_cpu_irq_controller;
132 }
133
134 if (cpu_has_vint)
135 set_vi_handler(hw, plat_irq_dispatch);
136
137 irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
138
139 return 0;
140}
141
142static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
143 .map = mips_cpu_intc_map,
144 .xlate = irq_domain_xlate_onecell,
145};
146
147static void __init __mips_cpu_irq_init(struct device_node *of_node)
148{
149 struct irq_domain *domain;
150
151 /* Mask interrupts. */
152 clear_c0_status(ST0_IM);
153 clear_c0_cause(CAUSEF_IP);
154
155 domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
156 &mips_cpu_intc_irq_domain_ops, NULL);
157 if (!domain)
158 panic("Failed to add irqdomain for MIPS CPU");
159}
160
161void __init mips_cpu_irq_init(void)
162{
163 __mips_cpu_irq_init(NULL);
164}
165
166int __init mips_cpu_irq_of_init(struct device_node *of_node,
167 struct device_node *parent)
168{
169 __mips_cpu_irq_init(of_node);
170 return 0;
171}
172IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 487d057431cc..c0e6ede3e27d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -267,6 +267,13 @@ config PHY_EXYNOS5_USBDRD
267 This driver provides PHY interface for USB 3.0 DRD controller 267 This driver provides PHY interface for USB 3.0 DRD controller
268 present on Exynos5 SoC series. 268 present on Exynos5 SoC series.
269 269
270config PHY_PISTACHIO_USB
271 tristate "IMG Pistachio USB2.0 PHY driver"
272 depends on MACH_PISTACHIO
273 select GENERIC_PHY
274 help
275 Enable this to support the USB2.0 PHY on the IMG Pistachio SoC.
276
270config PHY_QCOM_APQ8064_SATA 277config PHY_QCOM_APQ8064_SATA
271 tristate "Qualcomm APQ8064 SATA SerDes/PHY driver" 278 tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
272 depends on ARCH_QCOM 279 depends on ARCH_QCOM
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 42f58e95aff0..f344e1b2e825 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -44,3 +44,4 @@ obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
44obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o 44obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
45obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o 45obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
46obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o 46obj-$(CONFIG_PHY_BRCMSTB_SATA) += phy-brcmstb-sata.o
47obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
diff --git a/drivers/phy/phy-pistachio-usb.c b/drivers/phy/phy-pistachio-usb.c
new file mode 100644
index 000000000000..c6db35e6bb63
--- /dev/null
+++ b/drivers/phy/phy-pistachio-usb.c
@@ -0,0 +1,206 @@
1/*
2 * IMG Pistachio USB PHY driver
3 *
4 * Copyright (C) 2015 Google, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 */
10
11#include <linux/clk.h>
12#include <linux/delay.h>
13#include <linux/io.h>
14#include <linux/kernel.h>
15#include <linux/mfd/syscon.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/phy/phy.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21
22#include <dt-bindings/phy/phy-pistachio-usb.h>
23
24#define USB_PHY_CONTROL1 0x04
25#define USB_PHY_CONTROL1_FSEL_SHIFT 2
26#define USB_PHY_CONTROL1_FSEL_MASK 0x7
27
28#define USB_PHY_STRAP_CONTROL 0x10
29#define USB_PHY_STRAP_CONTROL_REFCLK_SHIFT 4
30#define USB_PHY_STRAP_CONTROL_REFCLK_MASK 0x3
31
32#define USB_PHY_STATUS 0x14
33#define USB_PHY_STATUS_RX_PHY_CLK BIT(9)
34#define USB_PHY_STATUS_RX_UTMI_CLK BIT(8)
35#define USB_PHY_STATUS_VBUS_FAULT BIT(7)
36
37struct pistachio_usb_phy {
38 struct device *dev;
39 struct regmap *cr_top;
40 struct clk *phy_clk;
41 unsigned int refclk;
42};
43
44static const unsigned long fsel_rate_map[] = {
45 9600000,
46 10000000,
47 12000000,
48 19200000,
49 20000000,
50 24000000,
51 0,
52 50000000,
53};
54
55static int pistachio_usb_phy_power_on(struct phy *phy)
56{
57 struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy);
58 unsigned long timeout, rate;
59 unsigned int i;
60 int ret;
61
62 ret = clk_prepare_enable(p_phy->phy_clk);
63 if (ret < 0) {
64 dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret);
65 return ret;
66 }
67
68 regmap_update_bits(p_phy->cr_top, USB_PHY_STRAP_CONTROL,
69 USB_PHY_STRAP_CONTROL_REFCLK_MASK <<
70 USB_PHY_STRAP_CONTROL_REFCLK_SHIFT,
71 p_phy->refclk << USB_PHY_STRAP_CONTROL_REFCLK_SHIFT);
72
73 rate = clk_get_rate(p_phy->phy_clk);
74 if (p_phy->refclk == REFCLK_XO_CRYSTAL && rate != 12000000) {
75 dev_err(p_phy->dev, "Unsupported rate for XO crystal: %ld\n",
76 rate);
77 ret = -EINVAL;
78 goto disable_clk;
79 }
80
81 for (i = 0; i < ARRAY_SIZE(fsel_rate_map); i++) {
82 if (rate == fsel_rate_map[i])
83 break;
84 }
85 if (i == ARRAY_SIZE(fsel_rate_map)) {
86 dev_err(p_phy->dev, "Unsupported clock rate: %lu\n", rate);
87 ret = -EINVAL;
88 goto disable_clk;
89 }
90
91 regmap_update_bits(p_phy->cr_top, USB_PHY_CONTROL1,
92 USB_PHY_CONTROL1_FSEL_MASK <<
93 USB_PHY_CONTROL1_FSEL_SHIFT,
94 i << USB_PHY_CONTROL1_FSEL_SHIFT);
95
96 timeout = jiffies + msecs_to_jiffies(200);
97 while (time_before(jiffies, timeout)) {
98 unsigned int val;
99
100 regmap_read(p_phy->cr_top, USB_PHY_STATUS, &val);
101 if (val & USB_PHY_STATUS_VBUS_FAULT) {
102 dev_err(p_phy->dev, "VBUS fault detected\n");
103 ret = -EIO;
104 goto disable_clk;
105 }
106 if ((val & USB_PHY_STATUS_RX_PHY_CLK) &&
107 (val & USB_PHY_STATUS_RX_UTMI_CLK))
108 return 0;
109 usleep_range(1000, 1500);
110 }
111
112 dev_err(p_phy->dev, "Timed out waiting for PHY to power on\n");
113 ret = -ETIMEDOUT;
114
115disable_clk:
116 clk_disable_unprepare(p_phy->phy_clk);
117 return ret;
118}
119
120static int pistachio_usb_phy_power_off(struct phy *phy)
121{
122 struct pistachio_usb_phy *p_phy = phy_get_drvdata(phy);
123
124 clk_disable_unprepare(p_phy->phy_clk);
125
126 return 0;
127}
128
129static const struct phy_ops pistachio_usb_phy_ops = {
130 .power_on = pistachio_usb_phy_power_on,
131 .power_off = pistachio_usb_phy_power_off,
132 .owner = THIS_MODULE,
133};
134
135static int pistachio_usb_phy_probe(struct platform_device *pdev)
136{
137 struct pistachio_usb_phy *p_phy;
138 struct phy_provider *provider;
139 struct phy *phy;
140 int ret;
141
142 p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL);
143 if (!p_phy)
144 return -ENOMEM;
145 p_phy->dev = &pdev->dev;
146 platform_set_drvdata(pdev, p_phy);
147
148 p_phy->cr_top = syscon_regmap_lookup_by_phandle(p_phy->dev->of_node,
149 "img,cr-top");
150 if (IS_ERR(p_phy->cr_top)) {
151 dev_err(p_phy->dev, "Failed to get CR_TOP registers: %ld\n",
152 PTR_ERR(p_phy->cr_top));
153 return PTR_ERR(p_phy->cr_top);
154 }
155
156 p_phy->phy_clk = devm_clk_get(p_phy->dev, "usb_phy");
157 if (IS_ERR(p_phy->phy_clk)) {
158 dev_err(p_phy->dev, "Failed to get usb_phy clock: %ld\n",
159 PTR_ERR(p_phy->phy_clk));
160 return PTR_ERR(p_phy->phy_clk);
161 }
162
163 ret = of_property_read_u32(p_phy->dev->of_node, "img,refclk",
164 &p_phy->refclk);
165 if (ret < 0) {
166 dev_err(p_phy->dev, "No reference clock selector specified\n");
167 return ret;
168 }
169
170 phy = devm_phy_create(p_phy->dev, NULL, &pistachio_usb_phy_ops);
171 if (IS_ERR(phy)) {
172 dev_err(p_phy->dev, "Failed to create PHY: %ld\n",
173 PTR_ERR(phy));
174 return PTR_ERR(phy);
175 }
176 phy_set_drvdata(phy, p_phy);
177
178 provider = devm_of_phy_provider_register(p_phy->dev,
179 of_phy_simple_xlate);
180 if (IS_ERR(provider)) {
181 dev_err(p_phy->dev, "Failed to register PHY provider: %ld\n",
182 PTR_ERR(provider));
183 return PTR_ERR(provider);
184 }
185
186 return 0;
187}
188
189static const struct of_device_id pistachio_usb_phy_of_match[] = {
190 { .compatible = "img,pistachio-usb-phy", },
191 { },
192};
193MODULE_DEVICE_TABLE(of, pistachio_usb_phy_of_match);
194
195static struct platform_driver pistachio_usb_phy_driver = {
196 .probe = pistachio_usb_phy_probe,
197 .driver = {
198 .name = "pistachio-usb-phy",
199 .of_match_table = pistachio_usb_phy_of_match,
200 },
201};
202module_platform_driver(pistachio_usb_phy_driver);
203
204MODULE_AUTHOR("Andrew Bresticker <abrestic@chromium.org>");
205MODULE_DESCRIPTION("IMG Pistachio USB2.0 PHY driver");
206MODULE_LICENSE("GPL v2");
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index db2fe4ab4b4a..83b4b89b9d5a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1503,7 +1503,7 @@ config RTC_DRV_PUV3
1503 1503
1504config RTC_DRV_LOONGSON1 1504config RTC_DRV_LOONGSON1
1505 tristate "loongson1 RTC support" 1505 tristate "loongson1 RTC support"
1506 depends on MACH_LOONGSON1 1506 depends on MACH_LOONGSON32
1507 help 1507 help
1508 This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year 1508 This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year
1509 counter) to be used as a RTC. 1509 counter) to be used as a RTC.
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c
index 8445e564094a..22a9ec4f2b83 100644
--- a/drivers/rtc/rtc-ls1x.c
+++ b/drivers/rtc/rtc-ls1x.c
@@ -17,7 +17,7 @@
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <asm/mach-loongson1/loongson1.h> 20#include <loongson1.h>
21 21
22#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20) 22#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20)
23#define LS1X_RTC_REGS(x) \ 23#define LS1X_RTC_REGS(x) \
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
new file mode 100644
index 000000000000..21bf81fe794f
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -0,0 +1,266 @@
1/*
2 * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de>
3 * Copyright (C) 2015 Imagination Technologies
4 *
5 * Ingenic SoC UART support
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 * You should have received a copy of the GNU General Public License along
13 * with this program; if not, write to the Free Software Foundation, Inc.,
14 * 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17#include <linux/clk.h>
18#include <linux/console.h>
19#include <linux/io.h>
20#include <linux/libfdt.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_fdt.h>
24#include <linux/platform_device.h>
25#include <linux/serial_8250.h>
26#include <linux/serial_core.h>
27#include <linux/serial_reg.h>
28
29struct ingenic_uart_data {
30 struct clk *clk_module;
31 struct clk *clk_baud;
32 int line;
33};
34
35#define UART_FCR_UME BIT(4)
36
37static struct earlycon_device *early_device;
38
39static uint8_t __init early_in(struct uart_port *port, int offset)
40{
41 return readl(port->membase + (offset << 2));
42}
43
44static void __init early_out(struct uart_port *port, int offset, uint8_t value)
45{
46 writel(value, port->membase + (offset << 2));
47}
48
49static void __init ingenic_early_console_putc(struct uart_port *port, int c)
50{
51 uint8_t lsr;
52
53 do {
54 lsr = early_in(port, UART_LSR);
55 } while ((lsr & UART_LSR_TEMT) == 0);
56
57 early_out(port, UART_TX, c);
58}
59
60static void __init ingenic_early_console_write(struct console *console,
61 const char *s, unsigned int count)
62{
63 uart_console_write(&early_device->port, s, count,
64 ingenic_early_console_putc);
65}
66
67static void __init ingenic_early_console_setup_clock(struct earlycon_device *dev)
68{
69 void *fdt = initial_boot_params;
70 const __be32 *prop;
71 int offset;
72
73 offset = fdt_path_offset(fdt, "/ext");
74 if (offset < 0)
75 return;
76
77 prop = fdt_getprop(fdt, offset, "clock-frequency", NULL);
78 if (!prop)
79 return;
80
81 dev->port.uartclk = be32_to_cpup(prop);
82}
83
84static int __init ingenic_early_console_setup(struct earlycon_device *dev,
85 const char *opt)
86{
87 struct uart_port *port = &dev->port;
88 unsigned int baud, divisor;
89
90 if (!dev->port.membase)
91 return -ENODEV;
92
93 ingenic_early_console_setup_clock(dev);
94
95 baud = dev->baud ?: 115200;
96 divisor = DIV_ROUND_CLOSEST(port->uartclk, 16 * baud);
97
98 early_out(port, UART_IER, 0);
99 early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
100 early_out(port, UART_DLL, 0);
101 early_out(port, UART_DLM, 0);
102 early_out(port, UART_LCR, UART_LCR_WLEN8);
103 early_out(port, UART_FCR, UART_FCR_UME | UART_FCR_CLEAR_XMIT |
104 UART_FCR_CLEAR_RCVR | UART_FCR_ENABLE_FIFO);
105 early_out(port, UART_MCR, UART_MCR_RTS | UART_MCR_DTR);
106
107 early_out(port, UART_LCR, UART_LCR_DLAB | UART_LCR_WLEN8);
108 early_out(port, UART_DLL, divisor & 0xff);
109 early_out(port, UART_DLM, (divisor >> 8) & 0xff);
110 early_out(port, UART_LCR, UART_LCR_WLEN8);
111
112 early_device = dev;
113 dev->con->write = ingenic_early_console_write;
114
115 return 0;
116}
117
118EARLYCON_DECLARE(jz4740_uart, ingenic_early_console_setup);
119OF_EARLYCON_DECLARE(jz4740_uart, "ingenic,jz4740-uart",
120 ingenic_early_console_setup);
121
122EARLYCON_DECLARE(jz4775_uart, ingenic_early_console_setup);
123OF_EARLYCON_DECLARE(jz4775_uart, "ingenic,jz4775-uart",
124 ingenic_early_console_setup);
125
126EARLYCON_DECLARE(jz4780_uart, ingenic_early_console_setup);
127OF_EARLYCON_DECLARE(jz4780_uart, "ingenic,jz4780-uart",
128 ingenic_early_console_setup);
129
130static void ingenic_uart_serial_out(struct uart_port *p, int offset, int value)
131{
132 switch (offset) {
133 case UART_FCR:
134 /* UART module enable */
135 value |= UART_FCR_UME;
136 break;
137
138 case UART_IER:
139 value |= (value & 0x4) << 2;
140 break;
141
142 default:
143 break;
144 }
145
146 writeb(value, p->membase + (offset << p->regshift));
147}
148
149static int ingenic_uart_probe(struct platform_device *pdev)
150{
151 struct uart_8250_port uart = {};
152 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
153 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
154 struct ingenic_uart_data *data;
155 int err, line;
156
157 if (!regs || !irq) {
158 dev_err(&pdev->dev, "no registers/irq defined\n");
159 return -EINVAL;
160 }
161
162 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
163 if (!data)
164 return -ENOMEM;
165
166 spin_lock_init(&uart.port.lock);
167 uart.port.type = PORT_16550;
168 uart.port.flags = UPF_SKIP_TEST | UPF_IOREMAP | UPF_FIXED_TYPE;
169 uart.port.iotype = UPIO_MEM;
170 uart.port.mapbase = regs->start;
171 uart.port.regshift = 2;
172 uart.port.serial_out = ingenic_uart_serial_out;
173 uart.port.irq = irq->start;
174 uart.port.dev = &pdev->dev;
175
176 /* Check for a fixed line number */
177 line = of_alias_get_id(pdev->dev.of_node, "serial");
178 if (line >= 0)
179 uart.port.line = line;
180
181 uart.port.membase = devm_ioremap(&pdev->dev, regs->start,
182 resource_size(regs));
183 if (!uart.port.membase)
184 return -ENOMEM;
185
186 data->clk_module = devm_clk_get(&pdev->dev, "module");
187 if (IS_ERR(data->clk_module)) {
188 err = PTR_ERR(data->clk_module);
189 if (err != -EPROBE_DEFER)
190 dev_err(&pdev->dev,
191 "unable to get module clock: %d\n", err);
192 return err;
193 }
194
195 data->clk_baud = devm_clk_get(&pdev->dev, "baud");
196 if (IS_ERR(data->clk_baud)) {
197 err = PTR_ERR(data->clk_baud);
198 if (err != -EPROBE_DEFER)
199 dev_err(&pdev->dev,
200 "unable to get baud clock: %d\n", err);
201 return err;
202 }
203
204 err = clk_prepare_enable(data->clk_module);
205 if (err) {
206 dev_err(&pdev->dev, "could not enable module clock: %d\n", err);
207 goto out;
208 }
209
210 err = clk_prepare_enable(data->clk_baud);
211 if (err) {
212 dev_err(&pdev->dev, "could not enable baud clock: %d\n", err);
213 goto out_disable_moduleclk;
214 }
215 uart.port.uartclk = clk_get_rate(data->clk_baud);
216
217 data->line = serial8250_register_8250_port(&uart);
218 if (data->line < 0) {
219 err = data->line;
220 goto out_disable_baudclk;
221 }
222
223 platform_set_drvdata(pdev, data);
224 return 0;
225
226out_disable_baudclk:
227 clk_disable_unprepare(data->clk_baud);
228out_disable_moduleclk:
229 clk_disable_unprepare(data->clk_module);
230out:
231 return err;
232}
233
234static int ingenic_uart_remove(struct platform_device *pdev)
235{
236 struct ingenic_uart_data *data = platform_get_drvdata(pdev);
237
238 serial8250_unregister_port(data->line);
239 clk_disable_unprepare(data->clk_module);
240 clk_disable_unprepare(data->clk_baud);
241 return 0;
242}
243
244static const struct of_device_id of_match[] = {
245 { .compatible = "ingenic,jz4740-uart" },
246 { .compatible = "ingenic,jz4775-uart" },
247 { .compatible = "ingenic,jz4780-uart" },
248 { /* sentinel */ }
249};
250MODULE_DEVICE_TABLE(of, of_match);
251
252static struct platform_driver ingenic_uart_platform_driver = {
253 .driver = {
254 .name = "ingenic-uart",
255 .owner = THIS_MODULE,
256 .of_match_table = of_match,
257 },
258 .probe = ingenic_uart_probe,
259 .remove = ingenic_uart_remove,
260};
261
262module_platform_driver(ingenic_uart_platform_driver);
263
264MODULE_AUTHOR("Paul Burton");
265MODULE_LICENSE("GPL");
266MODULE_DESCRIPTION("Ingenic SoC UART driver");
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index a74a8e4717d4..e1de1181b322 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -357,3 +357,12 @@ config SERIAL_8250_UNIPHIER
357 help 357 help
358 If you have a UniPhier based board and want to use the on-chip 358 If you have a UniPhier based board and want to use the on-chip
359 serial ports, say Y to this option. If unsure, say N. 359 serial ports, say Y to this option. If unsure, say N.
360
361config SERIAL_8250_INGENIC
362 bool "Support for Ingenic SoC serial ports"
363 depends on SERIAL_8250_CONSOLE && OF_FLATTREE
364 select LIBFDT
365 select SERIAL_EARLYCON
366 help
367 If you have a system using an Ingenic SoC and wish to make use of
368 its UARTs, say Y to this option. If unsure, say N.
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 6fa22ffad63d..706295913c34 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -25,3 +25,6 @@ obj-$(CONFIG_SERIAL_8250_FINTEK) += 8250_fintek.o
25obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o 25obj-$(CONFIG_SERIAL_8250_LPC18XX) += 8250_lpc18xx.o
26obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o 26obj-$(CONFIG_SERIAL_8250_MT6577) += 8250_mtk.o
27obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o 27obj-$(CONFIG_SERIAL_8250_UNIPHIER) += 8250_uniphier.o
28obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o
29
30CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 1c4791033b72..2847108cc8dd 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -462,6 +462,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
462 /* v: May be registered for frame buffer console restore */ 462 /* v: May be registered for frame buffer console restore */
463 NULL, /* v */ 463 NULL, /* v */
464 &sysrq_showstate_blocked_op, /* w */ 464 &sysrq_showstate_blocked_op, /* w */
465 /* x: May be registered on mips for TLB dump */
465 /* x: May be registered on ppc/powerpc for xmon */ 466 /* x: May be registered on ppc/powerpc for xmon */
466 /* x: May be registered on sparc64 for global PMU dump */ 467 /* x: May be registered on sparc64 for global PMU dump */
467 NULL, /* x */ 468 NULL, /* x */
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 547cee83400b..8afc3c1efdab 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -295,7 +295,7 @@ config USB_OCTEON_EHCI
295 bool "Octeon on-chip EHCI support (DEPRECATED)" 295 bool "Octeon on-chip EHCI support (DEPRECATED)"
296 depends on CAVIUM_OCTEON_SOC 296 depends on CAVIUM_OCTEON_SOC
297 default n 297 default n
298 select USB_EHCI_BIG_ENDIAN_MMIO 298 select USB_EHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
299 select USB_EHCI_HCD_PLATFORM 299 select USB_EHCI_HCD_PLATFORM
300 help 300 help
301 This option is deprecated now and the driver was removed, use 301 This option is deprecated now and the driver was removed, use
@@ -568,7 +568,7 @@ config USB_OCTEON_OHCI
568 bool "Octeon on-chip OHCI support (DEPRECATED)" 568 bool "Octeon on-chip OHCI support (DEPRECATED)"
569 depends on CAVIUM_OCTEON_SOC 569 depends on CAVIUM_OCTEON_SOC
570 default USB_OCTEON_EHCI 570 default USB_OCTEON_EHCI
571 select USB_OHCI_BIG_ENDIAN_MMIO 571 select USB_OHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
572 select USB_OHCI_LITTLE_ENDIAN 572 select USB_OHCI_LITTLE_ENDIAN
573 select USB_OHCI_HCD_PLATFORM 573 select USB_OHCI_HCD_PLATFORM
574 help 574 help