aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorJoseph Lo <josephl@nvidia.com>2012-08-16 05:31:48 -0400
committerStephen Warren <swarren@nvidia.com>2012-09-13 13:41:05 -0400
commitdab403ef23f7561f7d77e0dc72dfd1be0fa333c1 (patch)
treecc2159d8851392b017beb1fe0e9127ff1b0fd618 /arch/arm/mach-tegra
parentb4350f40f73b75efdceae3d9e04266979acabd8c (diff)
ARM: tegra: introduce tegra_cpu_car_ops structures
The tegra_cpu_car_ops provide the interface for CPU to control it's clock gating and reset status. The other drivers should use this for CPU control. And should not directly access CAR registers to control CPU. Signed-off-by: Joseph Lo <josephl@nvidia.com> Signed-off-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-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 */