diff options
Diffstat (limited to 'drivers/clk/tegra/clk-tegra210.c')
-rw-r--r-- | drivers/clk/tegra/clk-tegra210.c | 361 |
1 files changed, 357 insertions, 4 deletions
diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 9e6260869eb9..9fb5d51ccce4 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c | |||
@@ -22,10 +22,12 @@ | |||
22 | #include <linux/of_address.h> | 22 | #include <linux/of_address.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/mutex.h> | ||
25 | #include <linux/clk/tegra.h> | 26 | #include <linux/clk/tegra.h> |
26 | #include <dt-bindings/clock/tegra210-car.h> | 27 | #include <dt-bindings/clock/tegra210-car.h> |
27 | #include <dt-bindings/reset/tegra210-car.h> | 28 | #include <dt-bindings/reset/tegra210-car.h> |
28 | #include <linux/iopoll.h> | 29 | #include <linux/iopoll.h> |
30 | #include <soc/tegra/pmc.h> | ||
29 | 31 | ||
30 | #include "clk.h" | 32 | #include "clk.h" |
31 | #include "clk-id.h" | 33 | #include "clk-id.h" |
@@ -41,6 +43,7 @@ | |||
41 | #define CLK_SOURCE_CSITE 0x1d4 | 43 | #define CLK_SOURCE_CSITE 0x1d4 |
42 | #define CLK_SOURCE_EMC 0x19c | 44 | #define CLK_SOURCE_EMC 0x19c |
43 | #define CLK_SOURCE_SOR1 0x410 | 45 | #define CLK_SOURCE_SOR1 0x410 |
46 | #define CLK_SOURCE_LA 0x1f8 | ||
44 | 47 | ||
45 | #define PLLC_BASE 0x80 | 48 | #define PLLC_BASE 0x80 |
46 | #define PLLC_OUT 0x84 | 49 | #define PLLC_OUT 0x84 |
@@ -231,6 +234,30 @@ | |||
231 | #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8 | 234 | #define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8 |
232 | #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac | 235 | #define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac |
233 | 236 | ||
237 | #define LVL2_CLK_GATE_OVRA 0xf8 | ||
238 | #define LVL2_CLK_GATE_OVRC 0x3a0 | ||
239 | #define LVL2_CLK_GATE_OVRD 0x3a4 | ||
240 | #define LVL2_CLK_GATE_OVRE 0x554 | ||
241 | |||
242 | /* I2S registers to handle during APE MBIST WAR */ | ||
243 | #define TEGRA210_I2S_BASE 0x1000 | ||
244 | #define TEGRA210_I2S_SIZE 0x100 | ||
245 | #define TEGRA210_I2S_CTRLS 5 | ||
246 | #define TEGRA210_I2S_CG 0x88 | ||
247 | #define TEGRA210_I2S_CTRL 0xa0 | ||
248 | |||
249 | /* DISPA registers to handle during MBIST WAR */ | ||
250 | #define DC_CMD_DISPLAY_COMMAND 0xc8 | ||
251 | #define DC_COM_DSC_TOP_CTL 0xcf8 | ||
252 | |||
253 | /* VIC register to handle during MBIST WAR */ | ||
254 | #define NV_PVIC_THI_SLCG_OVERRIDE_LOW 0x8c | ||
255 | |||
256 | /* APE, DISPA and VIC base addesses needed for MBIST WAR */ | ||
257 | #define TEGRA210_AHUB_BASE 0x702d0000 | ||
258 | #define TEGRA210_DISPA_BASE 0x54200000 | ||
259 | #define TEGRA210_VIC_BASE 0x54340000 | ||
260 | |||
234 | /* | 261 | /* |
235 | * SDM fractional divisor is 16-bit 2's complement signed number within | 262 | * SDM fractional divisor is 16-bit 2's complement signed number within |
236 | * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned | 263 | * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned |
@@ -255,8 +282,22 @@ static struct cpu_clk_suspend_context { | |||
255 | } tegra210_cpu_clk_sctx; | 282 | } tegra210_cpu_clk_sctx; |
256 | #endif | 283 | #endif |
257 | 284 | ||
285 | struct tegra210_domain_mbist_war { | ||
286 | void (*handle_lvl2_ovr)(struct tegra210_domain_mbist_war *mbist); | ||
287 | const u32 lvl2_offset; | ||
288 | const u32 lvl2_mask; | ||
289 | const unsigned int num_clks; | ||
290 | const unsigned int *clk_init_data; | ||
291 | struct clk_bulk_data *clks; | ||
292 | }; | ||
293 | |||
294 | static struct clk **clks; | ||
295 | |||
258 | static void __iomem *clk_base; | 296 | static void __iomem *clk_base; |
259 | static void __iomem *pmc_base; | 297 | static void __iomem *pmc_base; |
298 | static void __iomem *ahub_base; | ||
299 | static void __iomem *dispa_base; | ||
300 | static void __iomem *vic_base; | ||
260 | 301 | ||
261 | static unsigned long osc_freq; | 302 | static unsigned long osc_freq; |
262 | static unsigned long pll_ref_freq; | 303 | static unsigned long pll_ref_freq; |
@@ -267,6 +308,7 @@ static DEFINE_SPINLOCK(pll_re_lock); | |||
267 | static DEFINE_SPINLOCK(pll_u_lock); | 308 | static DEFINE_SPINLOCK(pll_u_lock); |
268 | static DEFINE_SPINLOCK(sor1_lock); | 309 | static DEFINE_SPINLOCK(sor1_lock); |
269 | static DEFINE_SPINLOCK(emc_lock); | 310 | static DEFINE_SPINLOCK(emc_lock); |
311 | static DEFINE_MUTEX(lvl2_ovr_lock); | ||
270 | 312 | ||
271 | /* possible OSC frequencies in Hz */ | 313 | /* possible OSC frequencies in Hz */ |
272 | static unsigned long tegra210_input_freq[] = { | 314 | static unsigned long tegra210_input_freq[] = { |
@@ -310,6 +352,8 @@ static const char *mux_pllmcp_clkm[] = { | |||
310 | #define PLLA_MISC2_WRITE_MASK 0x06ffffff | 352 | #define PLLA_MISC2_WRITE_MASK 0x06ffffff |
311 | 353 | ||
312 | /* PLLD */ | 354 | /* PLLD */ |
355 | #define PLLD_BASE_CSI_CLKSOURCE (1 << 23) | ||
356 | |||
313 | #define PLLD_MISC0_EN_SDM (1 << 16) | 357 | #define PLLD_MISC0_EN_SDM (1 << 16) |
314 | #define PLLD_MISC0_LOCK_OVERRIDE (1 << 17) | 358 | #define PLLD_MISC0_LOCK_OVERRIDE (1 << 17) |
315 | #define PLLD_MISC0_LOCK_ENABLE (1 << 18) | 359 | #define PLLD_MISC0_LOCK_ENABLE (1 << 18) |
@@ -513,6 +557,115 @@ void tegra210_set_sata_pll_seq_sw(bool state) | |||
513 | } | 557 | } |
514 | EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw); | 558 | EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw); |
515 | 559 | ||
560 | static void tegra210_generic_mbist_war(struct tegra210_domain_mbist_war *mbist) | ||
561 | { | ||
562 | u32 val; | ||
563 | |||
564 | val = readl_relaxed(clk_base + mbist->lvl2_offset); | ||
565 | writel_relaxed(val | mbist->lvl2_mask, clk_base + mbist->lvl2_offset); | ||
566 | fence_udelay(1, clk_base); | ||
567 | writel_relaxed(val, clk_base + mbist->lvl2_offset); | ||
568 | fence_udelay(1, clk_base); | ||
569 | } | ||
570 | |||
571 | static void tegra210_venc_mbist_war(struct tegra210_domain_mbist_war *mbist) | ||
572 | { | ||
573 | u32 csi_src, ovra, ovre; | ||
574 | unsigned long flags = 0; | ||
575 | |||
576 | spin_lock_irqsave(&pll_d_lock, flags); | ||
577 | |||
578 | csi_src = readl_relaxed(clk_base + PLLD_BASE); | ||
579 | writel_relaxed(csi_src | PLLD_BASE_CSI_CLKSOURCE, clk_base + PLLD_BASE); | ||
580 | fence_udelay(1, clk_base); | ||
581 | |||
582 | ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA); | ||
583 | writel_relaxed(ovra | BIT(15), clk_base + LVL2_CLK_GATE_OVRA); | ||
584 | ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); | ||
585 | writel_relaxed(ovre | BIT(3), clk_base + LVL2_CLK_GATE_OVRE); | ||
586 | fence_udelay(1, clk_base); | ||
587 | |||
588 | writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA); | ||
589 | writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); | ||
590 | writel_relaxed(csi_src, clk_base + PLLD_BASE); | ||
591 | fence_udelay(1, clk_base); | ||
592 | |||
593 | spin_unlock_irqrestore(&pll_d_lock, flags); | ||
594 | } | ||
595 | |||
596 | static void tegra210_disp_mbist_war(struct tegra210_domain_mbist_war *mbist) | ||
597 | { | ||
598 | u32 ovra, dsc_top_ctrl; | ||
599 | |||
600 | ovra = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRA); | ||
601 | writel_relaxed(ovra | BIT(1), clk_base + LVL2_CLK_GATE_OVRA); | ||
602 | fence_udelay(1, clk_base); | ||
603 | |||
604 | dsc_top_ctrl = readl_relaxed(dispa_base + DC_COM_DSC_TOP_CTL); | ||
605 | writel_relaxed(dsc_top_ctrl | BIT(2), dispa_base + DC_COM_DSC_TOP_CTL); | ||
606 | readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND); | ||
607 | writel_relaxed(dsc_top_ctrl, dispa_base + DC_COM_DSC_TOP_CTL); | ||
608 | readl_relaxed(dispa_base + DC_CMD_DISPLAY_COMMAND); | ||
609 | |||
610 | writel_relaxed(ovra, clk_base + LVL2_CLK_GATE_OVRA); | ||
611 | fence_udelay(1, clk_base); | ||
612 | } | ||
613 | |||
614 | static void tegra210_vic_mbist_war(struct tegra210_domain_mbist_war *mbist) | ||
615 | { | ||
616 | u32 ovre, val; | ||
617 | |||
618 | ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); | ||
619 | writel_relaxed(ovre | BIT(5), clk_base + LVL2_CLK_GATE_OVRE); | ||
620 | fence_udelay(1, clk_base); | ||
621 | |||
622 | val = readl_relaxed(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); | ||
623 | writel_relaxed(val | BIT(0) | GENMASK(7, 2) | BIT(24), | ||
624 | vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); | ||
625 | fence_udelay(1, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); | ||
626 | |||
627 | writel_relaxed(val, vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); | ||
628 | readl(vic_base + NV_PVIC_THI_SLCG_OVERRIDE_LOW); | ||
629 | |||
630 | writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); | ||
631 | fence_udelay(1, clk_base); | ||
632 | } | ||
633 | |||
634 | static void tegra210_ape_mbist_war(struct tegra210_domain_mbist_war *mbist) | ||
635 | { | ||
636 | void __iomem *i2s_base; | ||
637 | unsigned int i; | ||
638 | u32 ovrc, ovre; | ||
639 | |||
640 | ovrc = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRC); | ||
641 | ovre = readl_relaxed(clk_base + LVL2_CLK_GATE_OVRE); | ||
642 | writel_relaxed(ovrc | BIT(1), clk_base + LVL2_CLK_GATE_OVRC); | ||
643 | writel_relaxed(ovre | BIT(10) | BIT(11), | ||
644 | clk_base + LVL2_CLK_GATE_OVRE); | ||
645 | fence_udelay(1, clk_base); | ||
646 | |||
647 | i2s_base = ahub_base + TEGRA210_I2S_BASE; | ||
648 | |||
649 | for (i = 0; i < TEGRA210_I2S_CTRLS; i++) { | ||
650 | u32 i2s_ctrl; | ||
651 | |||
652 | i2s_ctrl = readl_relaxed(i2s_base + TEGRA210_I2S_CTRL); | ||
653 | writel_relaxed(i2s_ctrl | BIT(10), | ||
654 | i2s_base + TEGRA210_I2S_CTRL); | ||
655 | writel_relaxed(0, i2s_base + TEGRA210_I2S_CG); | ||
656 | readl(i2s_base + TEGRA210_I2S_CG); | ||
657 | writel_relaxed(1, i2s_base + TEGRA210_I2S_CG); | ||
658 | writel_relaxed(i2s_ctrl, i2s_base + TEGRA210_I2S_CTRL); | ||
659 | readl(i2s_base + TEGRA210_I2S_CTRL); | ||
660 | |||
661 | i2s_base += TEGRA210_I2S_SIZE; | ||
662 | } | ||
663 | |||
664 | writel_relaxed(ovrc, clk_base + LVL2_CLK_GATE_OVRC); | ||
665 | writel_relaxed(ovre, clk_base + LVL2_CLK_GATE_OVRE); | ||
666 | fence_udelay(1, clk_base); | ||
667 | } | ||
668 | |||
516 | static inline void _pll_misc_chk_default(void __iomem *base, | 669 | static inline void _pll_misc_chk_default(void __iomem *base, |
517 | struct tegra_clk_pll_params *params, | 670 | struct tegra_clk_pll_params *params, |
518 | u8 misc_num, u32 default_val, u32 mask) | 671 | u8 misc_num, u32 default_val, u32 mask) |
@@ -2411,13 +2564,150 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = { | |||
2411 | { "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" }, | 2564 | { "pll_a1", &pll_a1_params, tegra_clk_pll_a1, "pll_ref" }, |
2412 | }; | 2565 | }; |
2413 | 2566 | ||
2414 | static struct clk **clks; | ||
2415 | |||
2416 | static const char * const aclk_parents[] = { | 2567 | static const char * const aclk_parents[] = { |
2417 | "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3", | 2568 | "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3", |
2418 | "clk_m" | 2569 | "clk_m" |
2419 | }; | 2570 | }; |
2420 | 2571 | ||
2572 | static const unsigned int nvjpg_slcg_clkids[] = { TEGRA210_CLK_NVDEC }; | ||
2573 | static const unsigned int nvdec_slcg_clkids[] = { TEGRA210_CLK_NVJPG }; | ||
2574 | static const unsigned int sor_slcg_clkids[] = { TEGRA210_CLK_HDA2CODEC_2X, | ||
2575 | TEGRA210_CLK_HDA2HDMI, TEGRA210_CLK_DISP1, TEGRA210_CLK_DISP2 }; | ||
2576 | static const unsigned int disp_slcg_clkids[] = { TEGRA210_CLK_LA, | ||
2577 | TEGRA210_CLK_HOST1X}; | ||
2578 | static const unsigned int xusba_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST, | ||
2579 | TEGRA210_CLK_XUSB_DEV }; | ||
2580 | static const unsigned int xusbb_slcg_clkids[] = { TEGRA210_CLK_XUSB_HOST, | ||
2581 | TEGRA210_CLK_XUSB_SS }; | ||
2582 | static const unsigned int xusbc_slcg_clkids[] = { TEGRA210_CLK_XUSB_DEV, | ||
2583 | TEGRA210_CLK_XUSB_SS }; | ||
2584 | static const unsigned int venc_slcg_clkids[] = { TEGRA210_CLK_HOST1X, | ||
2585 | TEGRA210_CLK_PLL_D }; | ||
2586 | static const unsigned int ape_slcg_clkids[] = { TEGRA210_CLK_ACLK, | ||
2587 | TEGRA210_CLK_I2S0, TEGRA210_CLK_I2S1, TEGRA210_CLK_I2S2, | ||
2588 | TEGRA210_CLK_I2S3, TEGRA210_CLK_I2S4, TEGRA210_CLK_SPDIF_OUT, | ||
2589 | TEGRA210_CLK_D_AUDIO }; | ||
2590 | static const unsigned int vic_slcg_clkids[] = { TEGRA210_CLK_HOST1X }; | ||
2591 | |||
2592 | static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = { | ||
2593 | [TEGRA_POWERGATE_VENC] = { | ||
2594 | .handle_lvl2_ovr = tegra210_venc_mbist_war, | ||
2595 | .num_clks = ARRAY_SIZE(venc_slcg_clkids), | ||
2596 | .clk_init_data = venc_slcg_clkids, | ||
2597 | }, | ||
2598 | [TEGRA_POWERGATE_SATA] = { | ||
2599 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2600 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2601 | .lvl2_mask = BIT(0) | BIT(17) | BIT(19), | ||
2602 | }, | ||
2603 | [TEGRA_POWERGATE_MPE] = { | ||
2604 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2605 | .lvl2_offset = LVL2_CLK_GATE_OVRE, | ||
2606 | .lvl2_mask = BIT(2), | ||
2607 | }, | ||
2608 | [TEGRA_POWERGATE_SOR] = { | ||
2609 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2610 | .num_clks = ARRAY_SIZE(sor_slcg_clkids), | ||
2611 | .clk_init_data = sor_slcg_clkids, | ||
2612 | .lvl2_offset = LVL2_CLK_GATE_OVRA, | ||
2613 | .lvl2_mask = BIT(1) | BIT(2), | ||
2614 | }, | ||
2615 | [TEGRA_POWERGATE_DIS] = { | ||
2616 | .handle_lvl2_ovr = tegra210_disp_mbist_war, | ||
2617 | .num_clks = ARRAY_SIZE(disp_slcg_clkids), | ||
2618 | .clk_init_data = disp_slcg_clkids, | ||
2619 | }, | ||
2620 | [TEGRA_POWERGATE_DISB] = { | ||
2621 | .num_clks = ARRAY_SIZE(disp_slcg_clkids), | ||
2622 | .clk_init_data = disp_slcg_clkids, | ||
2623 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2624 | .lvl2_offset = LVL2_CLK_GATE_OVRA, | ||
2625 | .lvl2_mask = BIT(2), | ||
2626 | }, | ||
2627 | [TEGRA_POWERGATE_XUSBA] = { | ||
2628 | .num_clks = ARRAY_SIZE(xusba_slcg_clkids), | ||
2629 | .clk_init_data = xusba_slcg_clkids, | ||
2630 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2631 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2632 | .lvl2_mask = BIT(30) | BIT(31), | ||
2633 | }, | ||
2634 | [TEGRA_POWERGATE_XUSBB] = { | ||
2635 | .num_clks = ARRAY_SIZE(xusbb_slcg_clkids), | ||
2636 | .clk_init_data = xusbb_slcg_clkids, | ||
2637 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2638 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2639 | .lvl2_mask = BIT(30) | BIT(31), | ||
2640 | }, | ||
2641 | [TEGRA_POWERGATE_XUSBC] = { | ||
2642 | .num_clks = ARRAY_SIZE(xusbc_slcg_clkids), | ||
2643 | .clk_init_data = xusbc_slcg_clkids, | ||
2644 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2645 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2646 | .lvl2_mask = BIT(30) | BIT(31), | ||
2647 | }, | ||
2648 | [TEGRA_POWERGATE_VIC] = { | ||
2649 | .num_clks = ARRAY_SIZE(vic_slcg_clkids), | ||
2650 | .clk_init_data = vic_slcg_clkids, | ||
2651 | .handle_lvl2_ovr = tegra210_vic_mbist_war, | ||
2652 | }, | ||
2653 | [TEGRA_POWERGATE_NVDEC] = { | ||
2654 | .num_clks = ARRAY_SIZE(nvdec_slcg_clkids), | ||
2655 | .clk_init_data = nvdec_slcg_clkids, | ||
2656 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2657 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2658 | .lvl2_mask = BIT(9) | BIT(31), | ||
2659 | }, | ||
2660 | [TEGRA_POWERGATE_NVJPG] = { | ||
2661 | .num_clks = ARRAY_SIZE(nvjpg_slcg_clkids), | ||
2662 | .clk_init_data = nvjpg_slcg_clkids, | ||
2663 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2664 | .lvl2_offset = LVL2_CLK_GATE_OVRC, | ||
2665 | .lvl2_mask = BIT(9) | BIT(31), | ||
2666 | }, | ||
2667 | [TEGRA_POWERGATE_AUD] = { | ||
2668 | .num_clks = ARRAY_SIZE(ape_slcg_clkids), | ||
2669 | .clk_init_data = ape_slcg_clkids, | ||
2670 | .handle_lvl2_ovr = tegra210_ape_mbist_war, | ||
2671 | }, | ||
2672 | [TEGRA_POWERGATE_VE2] = { | ||
2673 | .handle_lvl2_ovr = tegra210_generic_mbist_war, | ||
2674 | .lvl2_offset = LVL2_CLK_GATE_OVRD, | ||
2675 | .lvl2_mask = BIT(22), | ||
2676 | }, | ||
2677 | }; | ||
2678 | |||
2679 | int tegra210_clk_handle_mbist_war(unsigned int id) | ||
2680 | { | ||
2681 | int err; | ||
2682 | struct tegra210_domain_mbist_war *mbist_war; | ||
2683 | |||
2684 | if (id >= ARRAY_SIZE(tegra210_pg_mbist_war)) { | ||
2685 | WARN(1, "unknown domain id in MBIST WAR handler\n"); | ||
2686 | return -EINVAL; | ||
2687 | } | ||
2688 | |||
2689 | mbist_war = &tegra210_pg_mbist_war[id]; | ||
2690 | if (!mbist_war->handle_lvl2_ovr) | ||
2691 | return 0; | ||
2692 | |||
2693 | if (mbist_war->num_clks && !mbist_war->clks) | ||
2694 | return -ENODEV; | ||
2695 | |||
2696 | err = clk_bulk_prepare_enable(mbist_war->num_clks, mbist_war->clks); | ||
2697 | if (err < 0) | ||
2698 | return err; | ||
2699 | |||
2700 | mutex_lock(&lvl2_ovr_lock); | ||
2701 | |||
2702 | mbist_war->handle_lvl2_ovr(mbist_war); | ||
2703 | |||
2704 | mutex_unlock(&lvl2_ovr_lock); | ||
2705 | |||
2706 | clk_bulk_disable_unprepare(mbist_war->num_clks, mbist_war->clks); | ||
2707 | |||
2708 | return 0; | ||
2709 | } | ||
2710 | |||
2421 | void tegra210_put_utmipll_in_iddq(void) | 2711 | void tegra210_put_utmipll_in_iddq(void) |
2422 | { | 2712 | { |
2423 | u32 reg; | 2713 | u32 reg; |
@@ -2654,6 +2944,13 @@ static struct tegra_periph_init_data tegra210_periph[] = { | |||
2654 | sor1_parents_idx, 0, &sor1_lock), | 2944 | sor1_parents_idx, 0, &sor1_lock), |
2655 | }; | 2945 | }; |
2656 | 2946 | ||
2947 | static const char * const la_parents[] = { | ||
2948 | "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_re_out1", "pll_a1", "clk_m", "pll_c4_out0" | ||
2949 | }; | ||
2950 | |||
2951 | static struct tegra_clk_periph tegra210_la = | ||
2952 | TEGRA_CLK_PERIPH(29, 7, 9, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP, 76, 0, NULL, 0); | ||
2953 | |||
2657 | static __init void tegra210_periph_clk_init(void __iomem *clk_base, | 2954 | static __init void tegra210_periph_clk_init(void __iomem *clk_base, |
2658 | void __iomem *pmc_base) | 2955 | void __iomem *pmc_base) |
2659 | { | 2956 | { |
@@ -2700,6 +2997,12 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base, | |||
2700 | periph_clk_enb_refcnt); | 2997 | periph_clk_enb_refcnt); |
2701 | clks[TEGRA210_CLK_DSIB] = clk; | 2998 | clks[TEGRA210_CLK_DSIB] = clk; |
2702 | 2999 | ||
3000 | /* la */ | ||
3001 | clk = tegra_clk_register_periph("la", la_parents, | ||
3002 | ARRAY_SIZE(la_parents), &tegra210_la, clk_base, | ||
3003 | CLK_SOURCE_LA, 0); | ||
3004 | clks[TEGRA210_CLK_LA] = clk; | ||
3005 | |||
2703 | /* emc mux */ | 3006 | /* emc mux */ |
2704 | clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, | 3007 | clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, |
2705 | ARRAY_SIZE(mux_pllmcp_clkm), 0, | 3008 | ARRAY_SIZE(mux_pllmcp_clkm), 0, |
@@ -3025,7 +3328,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { | |||
3025 | { TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, | 3328 | { TEGRA210_CLK_I2S4, TEGRA210_CLK_PLL_A_OUT0, 11289600, 0 }, |
3026 | { TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 }, | 3329 | { TEGRA210_CLK_HOST1X, TEGRA210_CLK_PLL_P, 136000000, 1 }, |
3027 | { TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 }, | 3330 | { TEGRA210_CLK_SCLK_MUX, TEGRA210_CLK_PLL_P, 0, 1 }, |
3028 | { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 1 }, | 3331 | { TEGRA210_CLK_SCLK, TEGRA210_CLK_CLK_MAX, 102000000, 0 }, |
3029 | { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 }, | 3332 | { TEGRA210_CLK_DFLL_SOC, TEGRA210_CLK_PLL_P, 51000000, 1 }, |
3030 | { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, | 3333 | { TEGRA210_CLK_DFLL_REF, TEGRA210_CLK_PLL_P, 51000000, 1 }, |
3031 | { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, | 3334 | { TEGRA210_CLK_SBC4, TEGRA210_CLK_PLL_P, 12000000, 1 }, |
@@ -3040,7 +3343,6 @@ static struct tegra_clk_init_table init_table[] __initdata = { | |||
3040 | { TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 }, | 3343 | { TEGRA210_CLK_XUSB_DEV_SRC, TEGRA210_CLK_PLL_P_OUT_XUSB, 102000000, 0 }, |
3041 | { TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 }, | 3344 | { TEGRA210_CLK_SATA, TEGRA210_CLK_PLL_P, 104000000, 0 }, |
3042 | { TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 }, | 3345 | { TEGRA210_CLK_SATA_OOB, TEGRA210_CLK_PLL_P, 204000000, 0 }, |
3043 | { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 }, | ||
3044 | { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 }, | 3346 | { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 }, |
3045 | { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 }, | 3347 | { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 }, |
3046 | /* TODO find a way to enable this on-demand */ | 3348 | /* TODO find a way to enable this on-demand */ |
@@ -3149,6 +3451,37 @@ static int tegra210_reset_deassert(unsigned long id) | |||
3149 | return 0; | 3451 | return 0; |
3150 | } | 3452 | } |
3151 | 3453 | ||
3454 | static void tegra210_mbist_clk_init(void) | ||
3455 | { | ||
3456 | unsigned int i, j; | ||
3457 | |||
3458 | for (i = 0; i < ARRAY_SIZE(tegra210_pg_mbist_war); i++) { | ||
3459 | unsigned int num_clks = tegra210_pg_mbist_war[i].num_clks; | ||
3460 | struct clk_bulk_data *clk_data; | ||
3461 | |||
3462 | if (!num_clks) | ||
3463 | continue; | ||
3464 | |||
3465 | clk_data = kmalloc_array(num_clks, sizeof(*clk_data), | ||
3466 | GFP_KERNEL); | ||
3467 | if (WARN_ON(!clk_data)) | ||
3468 | return; | ||
3469 | |||
3470 | tegra210_pg_mbist_war[i].clks = clk_data; | ||
3471 | for (j = 0; j < num_clks; j++) { | ||
3472 | int clk_id = tegra210_pg_mbist_war[i].clk_init_data[j]; | ||
3473 | struct clk *clk = clks[clk_id]; | ||
3474 | |||
3475 | if (WARN(IS_ERR(clk), "clk_id: %d\n", clk_id)) { | ||
3476 | kfree(clk_data); | ||
3477 | tegra210_pg_mbist_war[i].clks = NULL; | ||
3478 | break; | ||
3479 | } | ||
3480 | clk_data[j].clk = clk; | ||
3481 | } | ||
3482 | } | ||
3483 | } | ||
3484 | |||
3152 | /** | 3485 | /** |
3153 | * tegra210_clock_init - Tegra210-specific clock initialization | 3486 | * tegra210_clock_init - Tegra210-specific clock initialization |
3154 | * @np: struct device_node * of the DT node for the SoC CAR IP block | 3487 | * @np: struct device_node * of the DT node for the SoC CAR IP block |
@@ -3183,6 +3516,24 @@ static void __init tegra210_clock_init(struct device_node *np) | |||
3183 | return; | 3516 | return; |
3184 | } | 3517 | } |
3185 | 3518 | ||
3519 | ahub_base = ioremap(TEGRA210_AHUB_BASE, SZ_64K); | ||
3520 | if (!ahub_base) { | ||
3521 | pr_err("ioremap tegra210 APE failed\n"); | ||
3522 | return; | ||
3523 | } | ||
3524 | |||
3525 | dispa_base = ioremap(TEGRA210_DISPA_BASE, SZ_256K); | ||
3526 | if (!dispa_base) { | ||
3527 | pr_err("ioremap tegra210 DISPA failed\n"); | ||
3528 | return; | ||
3529 | } | ||
3530 | |||
3531 | vic_base = ioremap(TEGRA210_VIC_BASE, SZ_256K); | ||
3532 | if (!vic_base) { | ||
3533 | pr_err("ioremap tegra210 VIC failed\n"); | ||
3534 | return; | ||
3535 | } | ||
3536 | |||
3186 | clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX, | 3537 | clks = tegra_clk_init(clk_base, TEGRA210_CLK_CLK_MAX, |
3187 | TEGRA210_CAR_BANK_COUNT); | 3538 | TEGRA210_CAR_BANK_COUNT); |
3188 | if (!clks) | 3539 | if (!clks) |
@@ -3219,6 +3570,8 @@ static void __init tegra210_clock_init(struct device_node *np) | |||
3219 | tegra_add_of_provider(np); | 3570 | tegra_add_of_provider(np); |
3220 | tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); | 3571 | tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); |
3221 | 3572 | ||
3573 | tegra210_mbist_clk_init(); | ||
3574 | |||
3222 | tegra_cpu_car_ops = &tegra210_cpu_car_ops; | 3575 | tegra_cpu_car_ops = &tegra210_cpu_car_ops; |
3223 | } | 3576 | } |
3224 | CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init); | 3577 | CLK_OF_DECLARE(tegra210, "nvidia,tegra210-car", tegra210_clock_init); |