aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-tegra/clock.c4
-rw-r--r--arch/arm/mach-tegra/tegra20_clocks.c70
-rw-r--r--arch/arm/mach-tegra/tegra20_clocks_data.c2
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks.c72
-rw-r--r--arch/arm/mach-tegra/tegra30_clocks_data.c3
-rw-r--r--arch/arm/mach-tegra/tegra_cpu_car.h87
6 files changed, 238 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index 632133fc985b..fd82085eca5d 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -31,6 +31,10 @@
31 31
32#include "board.h" 32#include "board.h"
33#include "clock.h" 33#include "clock.h"
34#include "tegra_cpu_car.h"
35
36/* Global data of Tegra CPU CAR ops */
37struct tegra_cpu_car_ops *tegra_cpu_car_ops;
34 38
35/* 39/*
36 * Locking: 40 * Locking:
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
index 840ab262272a..9273b0dffc66 100644
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ b/arch/arm/mach-tegra/tegra20_clocks.c
@@ -33,6 +33,7 @@
33#include "clock.h" 33#include "clock.h"
34#include "fuse.h" 34#include "fuse.h"
35#include "tegra2_emc.h" 35#include "tegra2_emc.h"
36#include "tegra_cpu_car.h"
36 37
37#define RST_DEVICES 0x004 38#define RST_DEVICES 0x004
38#define RST_DEVICES_SET 0x300 39#define RST_DEVICES_SET 0x300
@@ -152,6 +153,14 @@
152#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 153#define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16
153#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff 154#define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff
154 155
156/* Tegra CPU clock and reset control regs */
157#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c
158#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340
159#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344
160
161#define CPU_CLOCK(cpu) (0x1 << (8 + cpu))
162#define CPU_RESET(cpu) (0x1111ul << (cpu))
163
155static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); 164static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
156static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); 165static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
157 166
@@ -1553,3 +1562,64 @@ struct clk_ops tegra_cdev_clk_ops = {
1553 .disable = tegra20_cdev_clk_disable, 1562 .disable = tegra20_cdev_clk_disable,
1554 .recalc_rate = tegra20_cdev_recalc_rate, 1563 .recalc_rate = tegra20_cdev_recalc_rate,
1555}; 1564};
1565
1566/* Tegra20 CPU clock and reset control functions */
1567static void tegra20_wait_cpu_in_reset(u32 cpu)
1568{
1569 unsigned int reg;
1570
1571 do {
1572 reg = readl(reg_clk_base +
1573 TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
1574 cpu_relax();
1575 } while (!(reg & (1 << cpu))); /* check CPU been reset or not */
1576
1577 return;
1578}
1579
1580static void tegra20_put_cpu_in_reset(u32 cpu)
1581{
1582 writel(CPU_RESET(cpu),
1583 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
1584 dmb();
1585}
1586
1587static void tegra20_cpu_out_of_reset(u32 cpu)
1588{
1589 writel(CPU_RESET(cpu),
1590 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
1591 wmb();
1592}
1593
1594static void tegra20_enable_cpu_clock(u32 cpu)
1595{
1596 unsigned int reg;
1597
1598 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1599 writel(reg & ~CPU_CLOCK(cpu),
1600 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1601 barrier();
1602 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1603}
1604
1605static void tegra20_disable_cpu_clock(u32 cpu)
1606{
1607 unsigned int reg;
1608
1609 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1610 writel(reg | CPU_CLOCK(cpu),
1611 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
1612}
1613
1614static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
1615 .wait_for_reset = tegra20_wait_cpu_in_reset,
1616 .put_in_reset = tegra20_put_cpu_in_reset,
1617 .out_of_reset = tegra20_cpu_out_of_reset,
1618 .enable_clock = tegra20_enable_cpu_clock,
1619 .disable_clock = tegra20_disable_cpu_clock,
1620};
1621
1622void __init tegra20_cpu_car_ops_init(void)
1623{
1624 tegra_cpu_car_ops = &tegra20_cpu_car_ops;
1625}
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
index 1a35c003fba8..e81dcd239c95 100644
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra20_clocks_data.c
@@ -34,6 +34,7 @@
34#include "fuse.h" 34#include "fuse.h"
35#include "tegra2_emc.h" 35#include "tegra2_emc.h"
36#include "tegra20_clocks.h" 36#include "tegra20_clocks.h"
37#include "tegra_cpu_car.h"
37 38
38/* Clock definitions */ 39/* Clock definitions */
39 40
@@ -1139,4 +1140,5 @@ void __init tegra2_init_clocks(void)
1139 } 1140 }
1140 1141
1141 init_audio_sync_clock_mux(); 1142 init_audio_sync_clock_mux();
1143 tegra20_cpu_car_ops_init();
1142} 1144}
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
index 63615dadfbb2..5cd502c27163 100644
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ b/arch/arm/mach-tegra/tegra30_clocks.c
@@ -35,6 +35,7 @@
35 35
36#include "clock.h" 36#include "clock.h"
37#include "fuse.h" 37#include "fuse.h"
38#include "tegra_cpu_car.h"
38 39
39#define USE_PLL_LOCK_BITS 0 40#define USE_PLL_LOCK_BITS 0
40 41
@@ -299,6 +300,16 @@
299/* FIXME: recommended safety delay after lock is detected */ 300/* FIXME: recommended safety delay after lock is detected */
300#define PLL_POST_LOCK_DELAY 100 301#define PLL_POST_LOCK_DELAY 100
301 302
303/* Tegra CPU clock and reset control regs */
304#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX 0x4c
305#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET 0x340
306#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR 0x344
307#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR 0x34c
308#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
309
310#define CPU_CLOCK(cpu) (0x1 << (8 + cpu))
311#define CPU_RESET(cpu) (0x1111ul << (cpu))
312
302/** 313/**
303* Structure defining the fields for USB UTMI clocks Parameters. 314* Structure defining the fields for USB UTMI clocks Parameters.
304*/ 315*/
@@ -2221,3 +2232,64 @@ struct clk_ops tegra_cml_clk_ops = {
2221struct clk_ops tegra_pciex_clk_ops = { 2232struct clk_ops tegra_pciex_clk_ops = {
2222 .recalc_rate = tegra30_clk_fixed_recalc_rate, 2233 .recalc_rate = tegra30_clk_fixed_recalc_rate,
2223}; 2234};
2235
2236/* Tegra30 CPU clock and reset control functions */
2237static void tegra30_wait_cpu_in_reset(u32 cpu)
2238{
2239 unsigned int reg;
2240
2241 do {
2242 reg = readl(reg_clk_base +
2243 TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
2244 cpu_relax();
2245 } while (!(reg & (1 << cpu))); /* check CPU been reset or not */
2246
2247 return;
2248}
2249
2250static void tegra30_put_cpu_in_reset(u32 cpu)
2251{
2252 writel(CPU_RESET(cpu),
2253 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
2254 dmb();
2255}
2256
2257static void tegra30_cpu_out_of_reset(u32 cpu)
2258{
2259 writel(CPU_RESET(cpu),
2260 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
2261 wmb();
2262}
2263
2264static void tegra30_enable_cpu_clock(u32 cpu)
2265{
2266 unsigned int reg;
2267
2268 writel(CPU_CLOCK(cpu),
2269 reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
2270 reg = readl(reg_clk_base +
2271 TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
2272}
2273
2274static void tegra30_disable_cpu_clock(u32 cpu)
2275{
2276
2277 unsigned int reg;
2278
2279 reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
2280 writel(reg | CPU_CLOCK(cpu),
2281 reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
2282}
2283
2284static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
2285 .wait_for_reset = tegra30_wait_cpu_in_reset,
2286 .put_in_reset = tegra30_put_cpu_in_reset,
2287 .out_of_reset = tegra30_cpu_out_of_reset,
2288 .enable_clock = tegra30_enable_cpu_clock,
2289 .disable_clock = tegra30_disable_cpu_clock,
2290};
2291
2292void __init tegra30_cpu_car_ops_init(void)
2293{
2294 tegra_cpu_car_ops = &tegra30_cpu_car_ops;
2295}
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
index 34b61a4934a3..c10449603df0 100644
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ b/arch/arm/mach-tegra/tegra30_clocks_data.c
@@ -32,6 +32,7 @@
32#include "clock.h" 32#include "clock.h"
33#include "fuse.h" 33#include "fuse.h"
34#include "tegra30_clocks.h" 34#include "tegra30_clocks.h"
35#include "tegra_cpu_car.h"
35 36
36#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags, \ 37#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags, \
37 _parent_names, _parents, _parent) \ 38 _parent_names, _parents, _parent) \
@@ -1366,4 +1367,6 @@ void __init tegra30_init_clocks(void)
1366 1367
1367 for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++) 1368 for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
1368 tegra30_init_one_clock(tegra_clk_out_list[i]); 1369 tegra30_init_one_clock(tegra_clk_out_list[i]);
1370
1371 tegra30_cpu_car_ops_init();
1369} 1372}
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/arch/arm/mach-tegra/tegra_cpu_car.h
new file mode 100644
index 000000000000..30d063ad2bef
--- /dev/null
+++ b/arch/arm/mach-tegra/tegra_cpu_car.h
@@ -0,0 +1,87 @@
1/*
2 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef __MACH_TEGRA_CPU_CAR_H
18#define __MACH_TEGRA_CPU_CAR_H
19
20/*
21 * Tegra CPU clock and reset control ops
22 *
23 * wait_for_reset:
24 * keep waiting until the CPU in reset state
25 * put_in_reset:
26 * put the CPU in reset state
27 * out_of_reset:
28 * release the CPU from reset state
29 * enable_clock:
30 * CPU clock un-gate
31 * disable_clock:
32 * CPU clock gate
33 */
34struct tegra_cpu_car_ops {
35 void (*wait_for_reset)(u32 cpu);
36 void (*put_in_reset)(u32 cpu);
37 void (*out_of_reset)(u32 cpu);
38 void (*enable_clock)(u32 cpu);
39 void (*disable_clock)(u32 cpu);
40};
41
42extern struct tegra_cpu_car_ops *tegra_cpu_car_ops;
43
44static inline void tegra_wait_cpu_in_reset(u32 cpu)
45{
46 if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset))
47 return;
48
49 tegra_cpu_car_ops->wait_for_reset(cpu);
50}
51
52static inline void tegra_put_cpu_in_reset(u32 cpu)
53{
54 if (WARN_ON(!tegra_cpu_car_ops->put_in_reset))
55 return;
56
57 tegra_cpu_car_ops->put_in_reset(cpu);
58}
59
60static inline void tegra_cpu_out_of_reset(u32 cpu)
61{
62 if (WARN_ON(!tegra_cpu_car_ops->out_of_reset))
63 return;
64
65 tegra_cpu_car_ops->out_of_reset(cpu);
66}
67
68static inline void tegra_enable_cpu_clock(u32 cpu)
69{
70 if (WARN_ON(!tegra_cpu_car_ops->enable_clock))
71 return;
72
73 tegra_cpu_car_ops->enable_clock(cpu);
74}
75
76static inline void tegra_disable_cpu_clock(u32 cpu)
77{
78 if (WARN_ON(!tegra_cpu_car_ops->disable_clock))
79 return;
80
81 tegra_cpu_car_ops->disable_clock(cpu);
82}
83
84void tegra20_cpu_car_ops_init(void);
85void tegra30_cpu_car_ops_init(void);
86
87#endif /* __MACH_TEGRA_CPU_CAR_H */