blob: dba89fc81a04c4c81a7bbfae3ce3504a6e5afd03 [file] [log] [blame]
Thierry Reding72323982014-07-11 13:19:06 +02001/*
2 * drivers/soc/tegra/pmc.c
3 *
4 * Copyright (c) 2010 Google, Inc
Sandipan Patra5f84bb12018-10-24 12:38:00 +05305 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
Thierry Reding72323982014-07-11 13:19:06 +02006 *
7 * Author:
8 * Colin Cross <ccross@google.com>
9 *
10 * This software is licensed under the terms of the GNU General Public
11 * License version 2, as published by the Free Software Foundation, and
12 * may be copied, distributed, and modified under those terms.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 */
20
Thierry Reding7d71e9032015-04-29 12:42:28 +020021#define pr_fmt(fmt) "tegra-pmc: " fmt
22
Thierry Reding72323982014-07-11 13:19:06 +020023#include <linux/clk.h>
24#include <linux/clk/tegra.h>
25#include <linux/debugfs.h>
26#include <linux/delay.h>
27#include <linux/err.h>
28#include <linux/export.h>
29#include <linux/init.h>
30#include <linux/io.h>
Jon Hunter0a2d87e2016-02-26 15:48:40 +000031#include <linux/iopoll.h>
Thierry Reding19906e62018-09-17 15:08:17 +020032#include <linux/irqdomain.h>
Thierry Reding4659db52019-01-25 11:22:49 +010033#include <linux/irq.h>
34#include <linux/kernel.h>
Thierry Reding72323982014-07-11 13:19:06 +020035#include <linux/of_address.h>
Geert Uytterhoeven3fd01212018-04-18 16:50:04 +020036#include <linux/of_clk.h>
Thierry Reding4659db52019-01-25 11:22:49 +010037#include <linux/of.h>
Thierry Reding19906e62018-09-17 15:08:17 +020038#include <linux/of_irq.h>
Jon Huntera3804512016-03-30 10:15:15 +010039#include <linux/of_platform.h>
Aapo Vienamo4a37f112018-08-10 21:08:12 +030040#include <linux/pinctrl/pinconf-generic.h>
Thierry Reding4659db52019-01-25 11:22:49 +010041#include <linux/pinctrl/pinconf.h>
42#include <linux/pinctrl/pinctrl.h>
Thierry Reding72323982014-07-11 13:19:06 +020043#include <linux/platform_device.h>
Jon Huntera3804512016-03-30 10:15:15 +010044#include <linux/pm_domain.h>
Thierry Reding72323982014-07-11 13:19:06 +020045#include <linux/reboot.h>
46#include <linux/reset.h>
47#include <linux/seq_file.h>
Jon Huntera3804512016-03-30 10:15:15 +010048#include <linux/slab.h>
Thierry Reding72323982014-07-11 13:19:06 +020049#include <linux/spinlock.h>
50
51#include <soc/tegra/common.h>
52#include <soc/tegra/fuse.h>
53#include <soc/tegra/pmc.h>
54
Thierry Reding19906e62018-09-17 15:08:17 +020055#include <dt-bindings/interrupt-controller/arm-gic.h>
Aapo Vienamofccf0f72018-08-10 21:08:11 +030056#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
Thierry Redinge59333c2018-09-19 18:41:59 +020057#include <dt-bindings/gpio/tegra186-gpio.h>
Thierry Redinge3e403c2018-09-19 18:42:37 +020058#include <dt-bindings/gpio/tegra194-gpio.h>
Aapo Vienamofccf0f72018-08-10 21:08:11 +030059
Thierry Reding72323982014-07-11 13:19:06 +020060#define PMC_CNTRL 0x0
Laxman Dewangan6c0bd212016-06-17 18:36:12 +053061#define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */
Thierry Reding95b780b2016-10-10 13:13:36 +020062#define PMC_CNTRL_CPU_PWRREQ_OE BIT(16) /* CPU pwr req enable */
63#define PMC_CNTRL_CPU_PWRREQ_POLARITY BIT(15) /* CPU pwr req polarity */
64#define PMC_CNTRL_SIDE_EFFECT_LP0 BIT(14) /* LP0 when CPU pwr gated */
65#define PMC_CNTRL_SYSCLK_OE BIT(11) /* system clock enable */
66#define PMC_CNTRL_SYSCLK_POLARITY BIT(10) /* sys clk polarity */
67#define PMC_CNTRL_MAIN_RST BIT(4)
Thierry Reding72323982014-07-11 13:19:06 +020068
69#define DPD_SAMPLE 0x020
Laxman Dewangan6c0bd212016-06-17 18:36:12 +053070#define DPD_SAMPLE_ENABLE BIT(0)
Thierry Reding72323982014-07-11 13:19:06 +020071#define DPD_SAMPLE_DISABLE (0 << 0)
72
73#define PWRGATE_TOGGLE 0x30
Laxman Dewangan6c0bd212016-06-17 18:36:12 +053074#define PWRGATE_TOGGLE_START BIT(8)
Thierry Reding72323982014-07-11 13:19:06 +020075
76#define REMOVE_CLAMPING 0x34
77
78#define PWRGATE_STATUS 0x38
79
Aapo Vienamo13136a42018-08-10 21:08:07 +030080#define PMC_IMPL_E_33V_PWR 0x40
81
Laxman Dewangan21b49912016-10-10 15:14:34 +020082#define PMC_PWR_DET 0x48
83
Thierry Reding5be22552017-08-30 12:32:58 +020084#define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
85#define PMC_SCRATCH0_MODE_BOOTLOADER BIT(30)
86#define PMC_SCRATCH0_MODE_RCM BIT(1)
87#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
Thierry Reding72323982014-07-11 13:19:06 +020088 PMC_SCRATCH0_MODE_BOOTLOADER | \
89 PMC_SCRATCH0_MODE_RCM)
90
91#define PMC_CPUPWRGOOD_TIMER 0xc8
92#define PMC_CPUPWROFF_TIMER 0xcc
93
Laxman Dewangan21b49912016-10-10 15:14:34 +020094#define PMC_PWR_DET_VALUE 0xe4
95
Thierry Reding72323982014-07-11 13:19:06 +020096#define PMC_SCRATCH41 0x140
97
Mikko Perttunen3568df32015-01-06 12:52:58 +020098#define PMC_SENSOR_CTRL 0x1b0
Laxman Dewangan6c0bd212016-06-17 18:36:12 +053099#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
100#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
Mikko Perttunen3568df32015-01-06 12:52:58 +0200101
Thierry Redingf5353c62015-12-30 17:13:29 +0100102#define PMC_RST_STATUS_POR 0
103#define PMC_RST_STATUS_WATCHDOG 1
104#define PMC_RST_STATUS_SENSOR 2
105#define PMC_RST_STATUS_SW_MAIN 3
106#define PMC_RST_STATUS_LP0 4
107#define PMC_RST_STATUS_AOTAG 5
108
Thierry Reding72323982014-07-11 13:19:06 +0200109#define IO_DPD_REQ 0x1b8
Laxman Dewangan6c0bd212016-06-17 18:36:12 +0530110#define IO_DPD_REQ_CODE_IDLE (0U << 30)
111#define IO_DPD_REQ_CODE_OFF (1U << 30)
112#define IO_DPD_REQ_CODE_ON (2U << 30)
113#define IO_DPD_REQ_CODE_MASK (3U << 30)
Thierry Reding72323982014-07-11 13:19:06 +0200114
115#define IO_DPD_STATUS 0x1bc
116#define IO_DPD2_REQ 0x1c0
117#define IO_DPD2_STATUS 0x1c4
118#define SEL_DPD_TIM 0x1c8
119
Mikko Perttunen3568df32015-01-06 12:52:58 +0200120#define PMC_SCRATCH54 0x258
Laxman Dewangan6c0bd212016-06-17 18:36:12 +0530121#define PMC_SCRATCH54_DATA_SHIFT 8
122#define PMC_SCRATCH54_ADDR_SHIFT 0
Mikko Perttunen3568df32015-01-06 12:52:58 +0200123
124#define PMC_SCRATCH55 0x25c
Laxman Dewangan6c0bd212016-06-17 18:36:12 +0530125#define PMC_SCRATCH55_RESET_TEGRA BIT(31)
126#define PMC_SCRATCH55_CNTRL_ID_SHIFT 27
127#define PMC_SCRATCH55_PINMUX_SHIFT 24
128#define PMC_SCRATCH55_16BITOP BIT(15)
129#define PMC_SCRATCH55_CHECKSUM_SHIFT 16
130#define PMC_SCRATCH55_I2CSLV1_SHIFT 0
Mikko Perttunen3568df32015-01-06 12:52:58 +0200131
Thierry Reding72323982014-07-11 13:19:06 +0200132#define GPU_RG_CNTRL 0x2d4
133
Thierry Redingc641ec62017-08-30 12:42:34 +0200134/* Tegra186 and later */
Thierry Reding19906e62018-09-17 15:08:17 +0200135#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
136#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
137#define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
138#define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
139#define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
140#define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2))
141#define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2))
142#define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2))
143#define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2))
144
Thierry Redingc641ec62017-08-30 12:42:34 +0200145#define WAKE_AOWAKE_CTRL 0x4f4
146#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
147
Jon Huntera3804512016-03-30 10:15:15 +0100148struct tegra_powergate {
149 struct generic_pm_domain genpd;
150 struct tegra_pmc *pmc;
151 unsigned int id;
152 struct clk **clks;
153 unsigned int num_clks;
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200154 struct reset_control *reset;
Jon Huntera3804512016-03-30 10:15:15 +0100155};
156
Laxman Dewangan21b49912016-10-10 15:14:34 +0200157struct tegra_io_pad_soc {
158 enum tegra_io_pad id;
159 unsigned int dpd;
160 unsigned int voltage;
Aapo Vienamo437c4f22018-08-10 21:08:10 +0300161 const char *name;
Laxman Dewangan21b49912016-10-10 15:14:34 +0200162};
163
Thierry Reding5be22552017-08-30 12:32:58 +0200164struct tegra_pmc_regs {
165 unsigned int scratch0;
166 unsigned int dpd_req;
167 unsigned int dpd_status;
168 unsigned int dpd2_req;
169 unsigned int dpd2_status;
Sandipan Patra5f84bb12018-10-24 12:38:00 +0530170 unsigned int rst_status;
171 unsigned int rst_source_shift;
172 unsigned int rst_source_mask;
173 unsigned int rst_level_shift;
174 unsigned int rst_level_mask;
Thierry Reding5be22552017-08-30 12:32:58 +0200175};
176
Thierry Reding19906e62018-09-17 15:08:17 +0200177struct tegra_wake_event {
178 const char *name;
179 unsigned int id;
180 unsigned int irq;
181 struct {
182 unsigned int instance;
183 unsigned int pin;
184 } gpio;
185};
186
187#define TEGRA_WAKE_IRQ(_name, _id, _irq) \
188 { \
189 .name = _name, \
190 .id = _id, \
191 .irq = _irq, \
192 .gpio = { \
193 .instance = UINT_MAX, \
194 .pin = UINT_MAX, \
195 }, \
196 }
197
198#define TEGRA_WAKE_GPIO(_name, _id, _instance, _pin) \
199 { \
200 .name = _name, \
201 .id = _id, \
202 .irq = 0, \
203 .gpio = { \
204 .instance = _instance, \
205 .pin = _pin, \
206 }, \
207 }
208
Thierry Reding72323982014-07-11 13:19:06 +0200209struct tegra_pmc_soc {
210 unsigned int num_powergates;
211 const char *const *powergates;
212 unsigned int num_cpu_powergates;
213 const u8 *cpu_powergates;
Thierry Redinga9a40a42015-01-09 11:15:33 +0100214
Mikko Perttunen3568df32015-01-06 12:52:58 +0200215 bool has_tsense_reset;
Thierry Redinga9a40a42015-01-09 11:15:33 +0100216 bool has_gpu_clamps;
Peter De Schrijvera263394a2018-01-25 16:00:13 +0200217 bool needs_mbist_war;
Aapo Vienamo13136a42018-08-10 21:08:07 +0300218 bool has_impl_33v_pwr;
Laxman Dewangan21b49912016-10-10 15:14:34 +0200219
220 const struct tegra_io_pad_soc *io_pads;
221 unsigned int num_io_pads;
Thierry Reding5be22552017-08-30 12:32:58 +0200222
Aapo Vienamo4a37f112018-08-10 21:08:12 +0300223 const struct pinctrl_pin_desc *pin_descs;
224 unsigned int num_pin_descs;
225
Thierry Reding5be22552017-08-30 12:32:58 +0200226 const struct tegra_pmc_regs *regs;
227 void (*init)(struct tegra_pmc *pmc);
228 void (*setup_irq_polarity)(struct tegra_pmc *pmc,
229 struct device_node *np,
230 bool invert);
Sandipan Patra5f84bb12018-10-24 12:38:00 +0530231
232 const char * const *reset_sources;
233 unsigned int num_reset_sources;
234 const char * const *reset_levels;
235 unsigned int num_reset_levels;
Thierry Reding19906e62018-09-17 15:08:17 +0200236
237 const struct tegra_wake_event *wake_events;
238 unsigned int num_wake_events;
Sandipan Patra5f84bb12018-10-24 12:38:00 +0530239};
240
241static const char * const tegra186_reset_sources[] = {
242 "SYS_RESET",
243 "AOWDT",
244 "MCCPLEXWDT",
245 "BPMPWDT",
246 "SCEWDT",
247 "SPEWDT",
248 "APEWDT",
249 "BCCPLEXWDT",
250 "SENSOR",
251 "AOTAG",
252 "VFSENSOR",
253 "SWREST",
254 "SC7",
255 "HSM",
256 "CORESIGHT"
257};
258
259static const char * const tegra186_reset_levels[] = {
260 "L0", "L1", "L2", "WARM"
261};
262
263static const char * const tegra30_reset_sources[] = {
264 "POWER_ON_RESET",
265 "WATCHDOG",
266 "SENSOR",
267 "SW_MAIN",
268 "LP0",
269 "AOTAG"
Thierry Reding72323982014-07-11 13:19:06 +0200270};
271
272/**
273 * struct tegra_pmc - NVIDIA Tegra PMC
Jon Hunter35b67292015-12-04 14:57:03 +0000274 * @dev: pointer to PMC device structure
Thierry Reding72323982014-07-11 13:19:06 +0200275 * @base: pointer to I/O remapped register region
Thierry Redingbbe5af62019-01-25 11:22:50 +0100276 * @wake: pointer to I/O remapped region for WAKE registers
277 * @aotag: pointer to I/O remapped region for AOTAG registers
278 * @scratch: pointer to I/O remapped region for scratch registers
Thierry Reding72323982014-07-11 13:19:06 +0200279 * @clk: pointer to pclk clock
Jon Hunter35b67292015-12-04 14:57:03 +0000280 * @soc: pointer to SoC data structure
Jon Hunter3195ac62015-12-04 14:57:05 +0000281 * @debugfs: pointer to debugfs entry
Thierry Reding72323982014-07-11 13:19:06 +0200282 * @rate: currently configured rate of pclk
283 * @suspend_mode: lowest suspend mode available
284 * @cpu_good_time: CPU power good time (in microseconds)
285 * @cpu_off_time: CPU power off time (in microsecends)
286 * @core_osc_time: core power good OSC time (in microseconds)
287 * @core_pmu_time: core power good PMU time (in microseconds)
288 * @core_off_time: core power off time (in microseconds)
289 * @corereq_high: core power request is active-high
290 * @sysclkreq_high: system clock request is active-high
291 * @combined_req: combined power request for CPU & core
292 * @cpu_pwr_good_en: CPU power good signal is enabled
293 * @lp0_vec_phys: physical base address of the LP0 warm boot code
294 * @lp0_vec_size: size of the LP0 warm boot code
Jon Huntera3804512016-03-30 10:15:15 +0100295 * @powergates_available: Bitmap of available power gates
Thierry Reding72323982014-07-11 13:19:06 +0200296 * @powergates_lock: mutex for power gate register access
Thierry Redingbbe5af62019-01-25 11:22:50 +0100297 * @pctl_dev: pin controller exposed by the PMC
298 * @domain: IRQ domain provided by the PMC
299 * @irq: chip implementation for the IRQ domain
Thierry Reding72323982014-07-11 13:19:06 +0200300 */
301struct tegra_pmc {
Mikko Perttunen3568df32015-01-06 12:52:58 +0200302 struct device *dev;
Thierry Reding72323982014-07-11 13:19:06 +0200303 void __iomem *base;
Thierry Redingc641ec62017-08-30 12:42:34 +0200304 void __iomem *wake;
305 void __iomem *aotag;
Thierry Reding5be22552017-08-30 12:32:58 +0200306 void __iomem *scratch;
Thierry Reding72323982014-07-11 13:19:06 +0200307 struct clk *clk;
Jon Hunter3195ac62015-12-04 14:57:05 +0000308 struct dentry *debugfs;
Thierry Reding72323982014-07-11 13:19:06 +0200309
310 const struct tegra_pmc_soc *soc;
311
312 unsigned long rate;
313
314 enum tegra_suspend_mode suspend_mode;
315 u32 cpu_good_time;
316 u32 cpu_off_time;
317 u32 core_osc_time;
318 u32 core_pmu_time;
319 u32 core_off_time;
320 bool corereq_high;
321 bool sysclkreq_high;
322 bool combined_req;
323 bool cpu_pwr_good_en;
324 u32 lp0_vec_phys;
325 u32 lp0_vec_size;
Jon Huntera3804512016-03-30 10:15:15 +0100326 DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
Thierry Reding72323982014-07-11 13:19:06 +0200327
328 struct mutex powergates_lock;
Aapo Vienamo4a37f112018-08-10 21:08:12 +0300329
330 struct pinctrl_dev *pctl_dev;
Thierry Reding19906e62018-09-17 15:08:17 +0200331
332 struct irq_domain *domain;
333 struct irq_chip irq;
Thierry Reding72323982014-07-11 13:19:06 +0200334};
335
336static struct tegra_pmc *pmc = &(struct tegra_pmc) {
337 .base = NULL,
338 .suspend_mode = TEGRA_SUSPEND_NONE,
339};
340
Jon Huntera3804512016-03-30 10:15:15 +0100341static inline struct tegra_powergate *
342to_powergate(struct generic_pm_domain *domain)
343{
344 return container_of(domain, struct tegra_powergate, genpd);
345}
346
Thierry Reding589997a2019-01-25 11:22:52 +0100347static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
Thierry Reding72323982014-07-11 13:19:06 +0200348{
349 return readl(pmc->base + offset);
350}
351
Thierry Reding589997a2019-01-25 11:22:52 +0100352static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
353 unsigned long offset)
Thierry Reding72323982014-07-11 13:19:06 +0200354{
355 writel(value, pmc->base + offset);
356}
357
Thierry Reding589997a2019-01-25 11:22:52 +0100358/*
359 * TODO Figure out a way to call this with the struct tegra_pmc * passed in.
360 * This currently doesn't work because readx_poll_timeout() can only operate
361 * on functions that take a single argument.
362 */
Jon Hunter0ecf2d32016-02-11 18:03:23 +0000363static inline bool tegra_powergate_state(int id)
364{
Jon Hunterbc9af232016-02-15 12:38:11 +0000365 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
Thierry Reding589997a2019-01-25 11:22:52 +0100366 return (tegra_pmc_readl(pmc, GPU_RG_CNTRL) & 0x1) == 0;
Jon Hunterbc9af232016-02-15 12:38:11 +0000367 else
Thierry Reding589997a2019-01-25 11:22:52 +0100368 return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
Jon Hunter0ecf2d32016-02-11 18:03:23 +0000369}
370
Thierry Reding589997a2019-01-25 11:22:52 +0100371static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
Jon Hunter0a243bd2016-02-11 18:03:24 +0000372{
373 return (pmc->soc && pmc->soc->powergates[id]);
374}
375
Thierry Reding589997a2019-01-25 11:22:52 +0100376static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
Jon Huntera3804512016-03-30 10:15:15 +0100377{
378 return test_bit(id, pmc->powergates_available);
379}
380
381static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
382{
383 unsigned int i;
384
385 if (!pmc || !pmc->soc || !name)
386 return -EINVAL;
387
388 for (i = 0; i < pmc->soc->num_powergates; i++) {
Thierry Reding589997a2019-01-25 11:22:52 +0100389 if (!tegra_powergate_is_valid(pmc, i))
Jon Huntera3804512016-03-30 10:15:15 +0100390 continue;
391
392 if (!strcmp(name, pmc->soc->powergates[i]))
393 return i;
394 }
395
Jon Huntera3804512016-03-30 10:15:15 +0100396 return -ENODEV;
397}
398
Thierry Reding72323982014-07-11 13:19:06 +0200399/**
400 * tegra_powergate_set() - set the state of a partition
Thierry Reding589997a2019-01-25 11:22:52 +0100401 * @pmc: power management controller
Thierry Reding72323982014-07-11 13:19:06 +0200402 * @id: partition ID
403 * @new_state: new state of the partition
404 */
Thierry Reding589997a2019-01-25 11:22:52 +0100405static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
406 bool new_state)
Thierry Reding72323982014-07-11 13:19:06 +0200407{
Jon Hunter0a2d87e2016-02-26 15:48:40 +0000408 bool status;
409 int err;
410
Jon Hunterbc9af232016-02-15 12:38:11 +0000411 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
412 return -EINVAL;
413
Thierry Reding72323982014-07-11 13:19:06 +0200414 mutex_lock(&pmc->powergates_lock);
415
Jon Hunter0ecf2d32016-02-11 18:03:23 +0000416 if (tegra_powergate_state(id) == new_state) {
Thierry Reding72323982014-07-11 13:19:06 +0200417 mutex_unlock(&pmc->powergates_lock);
418 return 0;
419 }
420
Thierry Reding589997a2019-01-25 11:22:52 +0100421 tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
Thierry Reding72323982014-07-11 13:19:06 +0200422
Jon Hunter0a2d87e2016-02-26 15:48:40 +0000423 err = readx_poll_timeout(tegra_powergate_state, id, status,
424 status == new_state, 10, 100000);
425
Thierry Reding72323982014-07-11 13:19:06 +0200426 mutex_unlock(&pmc->powergates_lock);
427
Jon Hunter0a2d87e2016-02-26 15:48:40 +0000428 return err;
Thierry Reding72323982014-07-11 13:19:06 +0200429}
430
Thierry Reding589997a2019-01-25 11:22:52 +0100431static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
432 unsigned int id)
Thierry Reding72323982014-07-11 13:19:06 +0200433{
434 u32 mask;
435
Jon Huntere8cf6612016-02-11 18:03:21 +0000436 mutex_lock(&pmc->powergates_lock);
437
Thierry Reding72323982014-07-11 13:19:06 +0200438 /*
Thierry Redinga9a40a42015-01-09 11:15:33 +0100439 * On Tegra124 and later, the clamps for the GPU are controlled by a
440 * separate register (with different semantics).
Thierry Reding72323982014-07-11 13:19:06 +0200441 */
Thierry Redinga9a40a42015-01-09 11:15:33 +0100442 if (id == TEGRA_POWERGATE_3D) {
443 if (pmc->soc->has_gpu_clamps) {
Thierry Reding589997a2019-01-25 11:22:52 +0100444 tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
Jon Huntere8cf6612016-02-11 18:03:21 +0000445 goto out;
Thierry Reding72323982014-07-11 13:19:06 +0200446 }
447 }
448
449 /*
450 * Tegra 2 has a bug where PCIE and VDE clamping masks are
451 * swapped relatively to the partition ids
452 */
453 if (id == TEGRA_POWERGATE_VDEC)
454 mask = (1 << TEGRA_POWERGATE_PCIE);
455 else if (id == TEGRA_POWERGATE_PCIE)
456 mask = (1 << TEGRA_POWERGATE_VDEC);
457 else
458 mask = (1 << id);
459
Thierry Reding589997a2019-01-25 11:22:52 +0100460 tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
Thierry Reding72323982014-07-11 13:19:06 +0200461
Jon Huntere8cf6612016-02-11 18:03:21 +0000462out:
463 mutex_unlock(&pmc->powergates_lock);
464
Thierry Reding72323982014-07-11 13:19:06 +0200465 return 0;
466}
Jon Huntera3804512016-03-30 10:15:15 +0100467
468static void tegra_powergate_disable_clocks(struct tegra_powergate *pg)
469{
470 unsigned int i;
471
472 for (i = 0; i < pg->num_clks; i++)
473 clk_disable_unprepare(pg->clks[i]);
474}
475
476static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
477{
478 unsigned int i;
479 int err;
480
481 for (i = 0; i < pg->num_clks; i++) {
482 err = clk_prepare_enable(pg->clks[i]);
483 if (err)
484 goto out;
485 }
486
487 return 0;
488
489out:
490 while (i--)
491 clk_disable_unprepare(pg->clks[i]);
492
493 return err;
494}
495
Peter De Schrijvera263394a2018-01-25 16:00:13 +0200496int __weak tegra210_clk_handle_mbist_war(unsigned int id)
497{
498 return 0;
499}
500
Jon Huntera3804512016-03-30 10:15:15 +0100501static int tegra_powergate_power_up(struct tegra_powergate *pg,
502 bool disable_clocks)
503{
504 int err;
505
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200506 err = reset_control_assert(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100507 if (err)
508 return err;
509
510 usleep_range(10, 20);
511
Thierry Reding589997a2019-01-25 11:22:52 +0100512 err = tegra_powergate_set(pg->pmc, pg->id, true);
Jon Huntera3804512016-03-30 10:15:15 +0100513 if (err < 0)
514 return err;
515
516 usleep_range(10, 20);
517
518 err = tegra_powergate_enable_clocks(pg);
519 if (err)
520 goto disable_clks;
521
522 usleep_range(10, 20);
523
Thierry Reding589997a2019-01-25 11:22:52 +0100524 err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
Jon Huntera3804512016-03-30 10:15:15 +0100525 if (err)
526 goto disable_clks;
527
528 usleep_range(10, 20);
529
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200530 err = reset_control_deassert(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100531 if (err)
532 goto powergate_off;
533
534 usleep_range(10, 20);
535
Peter De Schrijvera263394a2018-01-25 16:00:13 +0200536 if (pg->pmc->soc->needs_mbist_war)
537 err = tegra210_clk_handle_mbist_war(pg->id);
538 if (err)
539 goto disable_clks;
540
Jon Huntera3804512016-03-30 10:15:15 +0100541 if (disable_clocks)
542 tegra_powergate_disable_clocks(pg);
543
544 return 0;
545
546disable_clks:
547 tegra_powergate_disable_clocks(pg);
548 usleep_range(10, 20);
Thierry Redingda8f4b42016-06-30 12:12:55 +0200549
Jon Huntera3804512016-03-30 10:15:15 +0100550powergate_off:
Thierry Reding589997a2019-01-25 11:22:52 +0100551 tegra_powergate_set(pg->pmc, pg->id, false);
Jon Huntera3804512016-03-30 10:15:15 +0100552
553 return err;
554}
555
556static int tegra_powergate_power_down(struct tegra_powergate *pg)
557{
558 int err;
559
560 err = tegra_powergate_enable_clocks(pg);
561 if (err)
562 return err;
563
564 usleep_range(10, 20);
565
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200566 err = reset_control_assert(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100567 if (err)
568 goto disable_clks;
569
570 usleep_range(10, 20);
571
572 tegra_powergate_disable_clocks(pg);
573
574 usleep_range(10, 20);
575
Thierry Reding589997a2019-01-25 11:22:52 +0100576 err = tegra_powergate_set(pg->pmc, pg->id, false);
Jon Huntera3804512016-03-30 10:15:15 +0100577 if (err)
578 goto assert_resets;
579
580 return 0;
581
582assert_resets:
583 tegra_powergate_enable_clocks(pg);
584 usleep_range(10, 20);
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200585 reset_control_deassert(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100586 usleep_range(10, 20);
Thierry Redingda8f4b42016-06-30 12:12:55 +0200587
Jon Huntera3804512016-03-30 10:15:15 +0100588disable_clks:
589 tegra_powergate_disable_clocks(pg);
590
591 return err;
592}
593
594static int tegra_genpd_power_on(struct generic_pm_domain *domain)
595{
596 struct tegra_powergate *pg = to_powergate(domain);
Thierry Reding589997a2019-01-25 11:22:52 +0100597 struct device *dev = pg->pmc->dev;
Jon Huntera3804512016-03-30 10:15:15 +0100598 int err;
599
600 err = tegra_powergate_power_up(pg, true);
601 if (err)
Thierry Reding589997a2019-01-25 11:22:52 +0100602 dev_err(dev, "failed to turn on PM domain %s: %d\n",
603 pg->genpd.name, err);
Jon Huntera3804512016-03-30 10:15:15 +0100604
605 return err;
606}
607
608static int tegra_genpd_power_off(struct generic_pm_domain *domain)
609{
610 struct tegra_powergate *pg = to_powergate(domain);
Thierry Reding589997a2019-01-25 11:22:52 +0100611 struct device *dev = pg->pmc->dev;
Jon Huntera3804512016-03-30 10:15:15 +0100612 int err;
613
614 err = tegra_powergate_power_down(pg);
615 if (err)
Thierry Reding589997a2019-01-25 11:22:52 +0100616 dev_err(dev, "failed to turn off PM domain %s: %d\n",
617 pg->genpd.name, err);
Jon Huntera3804512016-03-30 10:15:15 +0100618
619 return err;
620}
621
622/**
623 * tegra_powergate_power_on() - power on partition
624 * @id: partition ID
625 */
626int tegra_powergate_power_on(unsigned int id)
627{
Thierry Reding589997a2019-01-25 11:22:52 +0100628 if (!tegra_powergate_is_available(pmc, id))
Jon Huntera3804512016-03-30 10:15:15 +0100629 return -EINVAL;
630
Thierry Reding589997a2019-01-25 11:22:52 +0100631 return tegra_powergate_set(pmc, id, true);
Jon Huntera3804512016-03-30 10:15:15 +0100632}
633
634/**
635 * tegra_powergate_power_off() - power off partition
636 * @id: partition ID
637 */
638int tegra_powergate_power_off(unsigned int id)
639{
Thierry Reding589997a2019-01-25 11:22:52 +0100640 if (!tegra_powergate_is_available(pmc, id))
Jon Huntera3804512016-03-30 10:15:15 +0100641 return -EINVAL;
642
Thierry Reding589997a2019-01-25 11:22:52 +0100643 return tegra_powergate_set(pmc, id, false);
Jon Huntera3804512016-03-30 10:15:15 +0100644}
645EXPORT_SYMBOL(tegra_powergate_power_off);
646
647/**
648 * tegra_powergate_is_powered() - check if partition is powered
Thierry Reding589997a2019-01-25 11:22:52 +0100649 * @pmc: power management controller
Jon Huntera3804512016-03-30 10:15:15 +0100650 * @id: partition ID
651 */
Thierry Reding589997a2019-01-25 11:22:52 +0100652static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
Jon Huntera3804512016-03-30 10:15:15 +0100653{
Thierry Reding589997a2019-01-25 11:22:52 +0100654 if (!tegra_powergate_is_valid(pmc, id))
Jon Huntera3804512016-03-30 10:15:15 +0100655 return -EINVAL;
656
Dmitry Osipenkob6e1fd12018-10-21 21:36:14 +0300657 return tegra_powergate_state(id);
Jon Huntera3804512016-03-30 10:15:15 +0100658}
659
660/**
661 * tegra_powergate_remove_clamping() - remove power clamps for partition
662 * @id: partition ID
663 */
664int tegra_powergate_remove_clamping(unsigned int id)
665{
Thierry Reding589997a2019-01-25 11:22:52 +0100666 if (!tegra_powergate_is_available(pmc, id))
Jon Huntera3804512016-03-30 10:15:15 +0100667 return -EINVAL;
668
Thierry Reding589997a2019-01-25 11:22:52 +0100669 return __tegra_powergate_remove_clamping(pmc, id);
Jon Huntera3804512016-03-30 10:15:15 +0100670}
Thierry Reding72323982014-07-11 13:19:06 +0200671EXPORT_SYMBOL(tegra_powergate_remove_clamping);
672
673/**
674 * tegra_powergate_sequence_power_up() - power up partition
675 * @id: partition ID
676 * @clk: clock for partition
677 * @rst: reset for partition
678 *
679 * Must be called with clk disabled, and returns with clk enabled.
680 */
Jon Hunter70293ed2016-02-11 18:03:22 +0000681int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
Thierry Reding72323982014-07-11 13:19:06 +0200682 struct reset_control *rst)
683{
Viresh Kumar495ac332018-05-03 13:56:17 +0530684 struct tegra_powergate *pg;
Jon Huntera3804512016-03-30 10:15:15 +0100685 int err;
Thierry Reding72323982014-07-11 13:19:06 +0200686
Thierry Reding589997a2019-01-25 11:22:52 +0100687 if (!tegra_powergate_is_available(pmc, id))
Jon Hunter403db2d2016-06-28 11:38:23 +0100688 return -EINVAL;
689
Viresh Kumar495ac332018-05-03 13:56:17 +0530690 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
691 if (!pg)
692 return -ENOMEM;
Thierry Reding72323982014-07-11 13:19:06 +0200693
Viresh Kumar495ac332018-05-03 13:56:17 +0530694 pg->id = id;
695 pg->clks = &clk;
696 pg->num_clks = 1;
697 pg->reset = rst;
698 pg->pmc = pmc;
699
700 err = tegra_powergate_power_up(pg, false);
Jon Huntera3804512016-03-30 10:15:15 +0100701 if (err)
Thierry Reding589997a2019-01-25 11:22:52 +0100702 dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id,
703 err);
Thierry Reding72323982014-07-11 13:19:06 +0200704
Viresh Kumar495ac332018-05-03 13:56:17 +0530705 kfree(pg);
706
Jon Huntera3804512016-03-30 10:15:15 +0100707 return err;
Thierry Reding72323982014-07-11 13:19:06 +0200708}
709EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
710
Thierry Reding72323982014-07-11 13:19:06 +0200711/**
712 * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
Thierry Reding589997a2019-01-25 11:22:52 +0100713 * @pmc: power management controller
Thierry Reding72323982014-07-11 13:19:06 +0200714 * @cpuid: CPU partition ID
715 *
716 * Returns the partition ID corresponding to the CPU partition ID or a
717 * negative error code on failure.
718 */
Thierry Reding589997a2019-01-25 11:22:52 +0100719static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
720 unsigned int cpuid)
Thierry Reding72323982014-07-11 13:19:06 +0200721{
Jon Hunter70293ed2016-02-11 18:03:22 +0000722 if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
Thierry Reding72323982014-07-11 13:19:06 +0200723 return pmc->soc->cpu_powergates[cpuid];
724
725 return -EINVAL;
726}
727
728/**
729 * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
730 * @cpuid: CPU partition ID
731 */
Jon Hunter70293ed2016-02-11 18:03:22 +0000732bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
Thierry Reding72323982014-07-11 13:19:06 +0200733{
734 int id;
735
Thierry Reding589997a2019-01-25 11:22:52 +0100736 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Thierry Reding72323982014-07-11 13:19:06 +0200737 if (id < 0)
738 return false;
739
Thierry Reding589997a2019-01-25 11:22:52 +0100740 return tegra_powergate_is_powered(pmc, id);
Thierry Reding72323982014-07-11 13:19:06 +0200741}
742
743/**
744 * tegra_pmc_cpu_power_on() - power on CPU partition
745 * @cpuid: CPU partition ID
746 */
Jon Hunter70293ed2016-02-11 18:03:22 +0000747int tegra_pmc_cpu_power_on(unsigned int cpuid)
Thierry Reding72323982014-07-11 13:19:06 +0200748{
749 int id;
750
Thierry Reding589997a2019-01-25 11:22:52 +0100751 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Thierry Reding72323982014-07-11 13:19:06 +0200752 if (id < 0)
753 return id;
754
Thierry Reding589997a2019-01-25 11:22:52 +0100755 return tegra_powergate_set(pmc, id, true);
Thierry Reding72323982014-07-11 13:19:06 +0200756}
757
758/**
759 * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
760 * @cpuid: CPU partition ID
761 */
Jon Hunter70293ed2016-02-11 18:03:22 +0000762int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
Thierry Reding72323982014-07-11 13:19:06 +0200763{
764 int id;
765
Thierry Reding589997a2019-01-25 11:22:52 +0100766 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Thierry Reding72323982014-07-11 13:19:06 +0200767 if (id < 0)
768 return id;
769
770 return tegra_powergate_remove_clamping(id);
771}
Thierry Reding72323982014-07-11 13:19:06 +0200772
David Riley78921582015-03-18 10:52:25 +0100773static int tegra_pmc_restart_notify(struct notifier_block *this,
774 unsigned long action, void *data)
Thierry Reding72323982014-07-11 13:19:06 +0200775{
David Riley78921582015-03-18 10:52:25 +0100776 const char *cmd = data;
Thierry Reding72323982014-07-11 13:19:06 +0200777 u32 value;
778
Thierry Reding5be22552017-08-30 12:32:58 +0200779 value = readl(pmc->scratch + pmc->soc->regs->scratch0);
Thierry Reding72323982014-07-11 13:19:06 +0200780 value &= ~PMC_SCRATCH0_MODE_MASK;
781
782 if (cmd) {
783 if (strcmp(cmd, "recovery") == 0)
784 value |= PMC_SCRATCH0_MODE_RECOVERY;
785
786 if (strcmp(cmd, "bootloader") == 0)
787 value |= PMC_SCRATCH0_MODE_BOOTLOADER;
788
789 if (strcmp(cmd, "forced-recovery") == 0)
790 value |= PMC_SCRATCH0_MODE_RCM;
791 }
792
Thierry Reding5be22552017-08-30 12:32:58 +0200793 writel(value, pmc->scratch + pmc->soc->regs->scratch0);
Thierry Reding72323982014-07-11 13:19:06 +0200794
Thierry Redingf5353c62015-12-30 17:13:29 +0100795 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
Thierry Reding589997a2019-01-25 11:22:52 +0100796 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Redingf5353c62015-12-30 17:13:29 +0100797 value |= PMC_CNTRL_MAIN_RST;
Thierry Reding589997a2019-01-25 11:22:52 +0100798 tegra_pmc_writel(pmc, value, PMC_CNTRL);
David Riley78921582015-03-18 10:52:25 +0100799
800 return NOTIFY_DONE;
Thierry Reding72323982014-07-11 13:19:06 +0200801}
802
David Riley78921582015-03-18 10:52:25 +0100803static struct notifier_block tegra_pmc_restart_handler = {
804 .notifier_call = tegra_pmc_restart_notify,
805 .priority = 128,
806};
807
Thierry Reding72323982014-07-11 13:19:06 +0200808static int powergate_show(struct seq_file *s, void *data)
809{
810 unsigned int i;
Jon Hunterc3ea2972016-02-11 18:03:25 +0000811 int status;
Thierry Reding72323982014-07-11 13:19:06 +0200812
813 seq_printf(s, " powergate powered\n");
814 seq_printf(s, "------------------\n");
815
816 for (i = 0; i < pmc->soc->num_powergates; i++) {
Thierry Reding589997a2019-01-25 11:22:52 +0100817 status = tegra_powergate_is_powered(pmc, i);
Jon Hunterc3ea2972016-02-11 18:03:25 +0000818 if (status < 0)
Thierry Reding72323982014-07-11 13:19:06 +0200819 continue;
820
821 seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
Jon Hunterc3ea2972016-02-11 18:03:25 +0000822 status ? "yes" : "no");
Thierry Reding72323982014-07-11 13:19:06 +0200823 }
824
825 return 0;
826}
827
Yangtao Li57ba33d2018-11-22 08:12:07 -0500828DEFINE_SHOW_ATTRIBUTE(powergate);
Thierry Reding72323982014-07-11 13:19:06 +0200829
830static int tegra_powergate_debugfs_init(void)
831{
Jon Hunter3195ac62015-12-04 14:57:05 +0000832 pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
833 &powergate_fops);
834 if (!pmc->debugfs)
Thierry Reding72323982014-07-11 13:19:06 +0200835 return -ENOMEM;
836
837 return 0;
838}
839
Jon Huntera3804512016-03-30 10:15:15 +0100840static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
841 struct device_node *np)
842{
843 struct clk *clk;
844 unsigned int i, count;
845 int err;
846
Geert Uytterhoeven3fd01212018-04-18 16:50:04 +0200847 count = of_clk_get_parent_count(np);
Jon Huntera3804512016-03-30 10:15:15 +0100848 if (count == 0)
849 return -ENODEV;
850
851 pg->clks = kcalloc(count, sizeof(clk), GFP_KERNEL);
852 if (!pg->clks)
853 return -ENOMEM;
854
855 for (i = 0; i < count; i++) {
856 pg->clks[i] = of_clk_get(np, i);
857 if (IS_ERR(pg->clks[i])) {
858 err = PTR_ERR(pg->clks[i]);
859 goto err;
860 }
861 }
862
863 pg->num_clks = count;
864
865 return 0;
866
867err:
868 while (i--)
869 clk_put(pg->clks[i]);
Thierry Redingda8f4b42016-06-30 12:12:55 +0200870
Jon Huntera3804512016-03-30 10:15:15 +0100871 kfree(pg->clks);
872
873 return err;
874}
875
876static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
Jon Hunter05cfb982016-06-29 10:17:47 +0100877 struct device_node *np, bool off)
Jon Huntera3804512016-03-30 10:15:15 +0100878{
Thierry Reding589997a2019-01-25 11:22:52 +0100879 struct device *dev = pg->pmc->dev;
Jon Huntera3804512016-03-30 10:15:15 +0100880 int err;
881
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200882 pg->reset = of_reset_control_array_get_exclusive(np);
883 if (IS_ERR(pg->reset)) {
884 err = PTR_ERR(pg->reset);
Thierry Reding589997a2019-01-25 11:22:52 +0100885 dev_err(dev, "failed to get device resets: %d\n", err);
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200886 return err;
Jon Huntera3804512016-03-30 10:15:15 +0100887 }
888
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200889 if (off)
890 err = reset_control_assert(pg->reset);
891 else
892 err = reset_control_deassert(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100893
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200894 if (err)
895 reset_control_put(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100896
897 return err;
898}
899
900static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
901{
Thierry Reding589997a2019-01-25 11:22:52 +0100902 struct device *dev = pmc->dev;
Jon Huntera3804512016-03-30 10:15:15 +0100903 struct tegra_powergate *pg;
Jon Hunterc2710ac2016-06-30 11:56:24 +0100904 int id, err;
Jon Huntera3804512016-03-30 10:15:15 +0100905 bool off;
Jon Huntera3804512016-03-30 10:15:15 +0100906
907 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
908 if (!pg)
Jon Hunterc2710ac2016-06-30 11:56:24 +0100909 return;
Jon Huntera3804512016-03-30 10:15:15 +0100910
911 id = tegra_powergate_lookup(pmc, np->name);
Jon Hunterc2710ac2016-06-30 11:56:24 +0100912 if (id < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +0100913 dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
Jon Huntera3804512016-03-30 10:15:15 +0100914 goto free_mem;
Jon Hunterc2710ac2016-06-30 11:56:24 +0100915 }
Jon Huntera3804512016-03-30 10:15:15 +0100916
917 /*
918 * Clear the bit for this powergate so it cannot be managed
919 * directly via the legacy APIs for controlling powergates.
920 */
921 clear_bit(id, pmc->powergates_available);
922
923 pg->id = id;
924 pg->genpd.name = np->name;
925 pg->genpd.power_off = tegra_genpd_power_off;
926 pg->genpd.power_on = tegra_genpd_power_on;
927 pg->pmc = pmc;
928
Thierry Reding589997a2019-01-25 11:22:52 +0100929 off = !tegra_powergate_is_powered(pmc, pg->id);
Jon Hunter05cfb982016-06-29 10:17:47 +0100930
Jon Hunterc2710ac2016-06-30 11:56:24 +0100931 err = tegra_powergate_of_get_clks(pg, np);
932 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +0100933 dev_err(dev, "failed to get clocks for %pOFn: %d\n", np, err);
Jon Huntera3804512016-03-30 10:15:15 +0100934 goto set_available;
Jon Hunterc2710ac2016-06-30 11:56:24 +0100935 }
Jon Huntera3804512016-03-30 10:15:15 +0100936
Jon Hunterc2710ac2016-06-30 11:56:24 +0100937 err = tegra_powergate_of_get_resets(pg, np, off);
938 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +0100939 dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err);
Jon Huntera3804512016-03-30 10:15:15 +0100940 goto remove_clks;
Jon Hunterc2710ac2016-06-30 11:56:24 +0100941 }
Jon Huntera3804512016-03-30 10:15:15 +0100942
Jon Hunter0b137342016-10-22 20:23:56 +0100943 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
944 if (off)
945 WARN_ON(tegra_powergate_power_up(pg, true));
946
947 goto remove_resets;
948 }
Jon Huntere2d17962016-06-30 11:56:25 +0100949
Jon Huntercd5ceda2016-10-22 20:23:55 +0100950 err = pm_genpd_init(&pg->genpd, NULL, off);
951 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +0100952 dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np,
Jon Huntercd5ceda2016-10-22 20:23:55 +0100953 err);
954 goto remove_resets;
955 }
Jon Huntera3804512016-03-30 10:15:15 +0100956
Jon Hunterc2710ac2016-06-30 11:56:24 +0100957 err = of_genpd_add_provider_simple(np, &pg->genpd);
958 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +0100959 dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
960 np, err);
Jon Hunter0b137342016-10-22 20:23:56 +0100961 goto remove_genpd;
Jon Hunterc2710ac2016-06-30 11:56:24 +0100962 }
Jon Huntera3804512016-03-30 10:15:15 +0100963
Thierry Reding589997a2019-01-25 11:22:52 +0100964 dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
Jon Huntera3804512016-03-30 10:15:15 +0100965
966 return;
967
Jon Hunter0b137342016-10-22 20:23:56 +0100968remove_genpd:
969 pm_genpd_remove(&pg->genpd);
Jon Huntere2d17962016-06-30 11:56:25 +0100970
Jon Huntera3804512016-03-30 10:15:15 +0100971remove_resets:
Vivek Gautam4c817cc2017-07-19 17:59:08 +0200972 reset_control_put(pg->reset);
Jon Huntera3804512016-03-30 10:15:15 +0100973
974remove_clks:
975 while (pg->num_clks--)
976 clk_put(pg->clks[pg->num_clks]);
Thierry Redingda8f4b42016-06-30 12:12:55 +0200977
Jon Huntera3804512016-03-30 10:15:15 +0100978 kfree(pg->clks);
979
980set_available:
981 set_bit(id, pmc->powergates_available);
982
983free_mem:
984 kfree(pg);
Jon Huntera3804512016-03-30 10:15:15 +0100985}
986
Jon Huntere2d17962016-06-30 11:56:25 +0100987static void tegra_powergate_init(struct tegra_pmc *pmc,
988 struct device_node *parent)
Jon Huntera3804512016-03-30 10:15:15 +0100989{
990 struct device_node *np, *child;
Jon Huntere2d17962016-06-30 11:56:25 +0100991 unsigned int i;
Jon Huntera3804512016-03-30 10:15:15 +0100992
Jon Huntere2d17962016-06-30 11:56:25 +0100993 /* Create a bitmap of the available and valid partitions */
994 for (i = 0; i < pmc->soc->num_powergates; i++)
995 if (pmc->soc->powergates[i])
996 set_bit(i, pmc->powergates_available);
997
998 np = of_get_child_by_name(parent, "powergates");
Jon Huntera3804512016-03-30 10:15:15 +0100999 if (!np)
1000 return;
1001
Tuomas Tynkkynen0c106e52017-07-29 02:58:43 +03001002 for_each_child_of_node(np, child)
Jon Huntera3804512016-03-30 10:15:15 +01001003 tegra_powergate_add(pmc, child);
Jon Huntera3804512016-03-30 10:15:15 +01001004
1005 of_node_put(np);
1006}
1007
Laxman Dewangan21b49912016-10-10 15:14:34 +02001008static const struct tegra_io_pad_soc *
1009tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
Thierry Reding72323982014-07-11 13:19:06 +02001010{
Laxman Dewangan21b49912016-10-10 15:14:34 +02001011 unsigned int i;
1012
1013 for (i = 0; i < pmc->soc->num_io_pads; i++)
1014 if (pmc->soc->io_pads[i].id == id)
1015 return &pmc->soc->io_pads[i];
1016
1017 return NULL;
1018}
1019
Thierry Reding589997a2019-01-25 11:22:52 +01001020static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
1021 enum tegra_io_pad id,
Aapo Vienamo00ead3c2018-08-10 21:08:08 +03001022 unsigned long *request,
1023 unsigned long *status,
1024 u32 *mask)
Laxman Dewangan21b49912016-10-10 15:14:34 +02001025{
1026 const struct tegra_io_pad_soc *pad;
Thierry Reding72323982014-07-11 13:19:06 +02001027
Laxman Dewangan21b49912016-10-10 15:14:34 +02001028 pad = tegra_io_pad_find(pmc, id);
Thierry Reding54e24722016-11-08 10:58:32 +01001029 if (!pad) {
Thierry Reding589997a2019-01-25 11:22:52 +01001030 dev_err(pmc->dev, "invalid I/O pad ID %u\n", id);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001031 return -ENOENT;
Thierry Reding54e24722016-11-08 10:58:32 +01001032 }
Thierry Reding72323982014-07-11 13:19:06 +02001033
Laxman Dewangan21b49912016-10-10 15:14:34 +02001034 if (pad->dpd == UINT_MAX)
1035 return -ENOTSUPP;
Thierry Reding72323982014-07-11 13:19:06 +02001036
Jon Hunter27b12b4e2016-10-22 20:23:53 +01001037 *mask = BIT(pad->dpd % 32);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001038
1039 if (pad->dpd < 32) {
Thierry Reding5be22552017-08-30 12:32:58 +02001040 *status = pmc->soc->regs->dpd_status;
1041 *request = pmc->soc->regs->dpd_req;
Thierry Reding72323982014-07-11 13:19:06 +02001042 } else {
Thierry Reding5be22552017-08-30 12:32:58 +02001043 *status = pmc->soc->regs->dpd2_status;
1044 *request = pmc->soc->regs->dpd2_req;
Thierry Reding72323982014-07-11 13:19:06 +02001045 }
1046
Aapo Vienamo00ead3c2018-08-10 21:08:08 +03001047 return 0;
1048}
1049
Thierry Reding589997a2019-01-25 11:22:52 +01001050static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
1051 unsigned long *request, unsigned long *status,
1052 u32 *mask)
Aapo Vienamo00ead3c2018-08-10 21:08:08 +03001053{
1054 unsigned long rate, value;
1055 int err;
1056
Thierry Reding589997a2019-01-25 11:22:52 +01001057 err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask);
Aapo Vienamo00ead3c2018-08-10 21:08:08 +03001058 if (err)
1059 return err;
1060
Thierry Reding5be22552017-08-30 12:32:58 +02001061 if (pmc->clk) {
1062 rate = clk_get_rate(pmc->clk);
1063 if (!rate) {
Thierry Reding589997a2019-01-25 11:22:52 +01001064 dev_err(pmc->dev, "failed to get clock rate\n");
Thierry Reding5be22552017-08-30 12:32:58 +02001065 return -ENODEV;
1066 }
1067
Thierry Reding589997a2019-01-25 11:22:52 +01001068 tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
Thierry Reding5be22552017-08-30 12:32:58 +02001069
1070 /* must be at least 200 ns, in APB (PCLK) clock cycles */
1071 value = DIV_ROUND_UP(1000000000, rate);
1072 value = DIV_ROUND_UP(200, value);
Thierry Reding589997a2019-01-25 11:22:52 +01001073 tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
Thierry Reding54e24722016-11-08 10:58:32 +01001074 }
Thierry Reding72323982014-07-11 13:19:06 +02001075
Thierry Reding72323982014-07-11 13:19:06 +02001076 return 0;
1077}
1078
Thierry Reding589997a2019-01-25 11:22:52 +01001079static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
1080 u32 mask, u32 val, unsigned long timeout)
Thierry Reding72323982014-07-11 13:19:06 +02001081{
Laxman Dewangan84cf85e2016-06-17 18:36:13 +05301082 u32 value;
Thierry Reding72323982014-07-11 13:19:06 +02001083
1084 timeout = jiffies + msecs_to_jiffies(timeout);
1085
1086 while (time_after(timeout, jiffies)) {
Thierry Reding589997a2019-01-25 11:22:52 +01001087 value = tegra_pmc_readl(pmc, offset);
Thierry Reding72323982014-07-11 13:19:06 +02001088 if ((value & mask) == val)
1089 return 0;
1090
1091 usleep_range(250, 1000);
1092 }
1093
1094 return -ETIMEDOUT;
1095}
1096
Thierry Reding589997a2019-01-25 11:22:52 +01001097static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
Thierry Reding72323982014-07-11 13:19:06 +02001098{
Thierry Reding5be22552017-08-30 12:32:58 +02001099 if (pmc->clk)
Thierry Reding589997a2019-01-25 11:22:52 +01001100 tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
Thierry Reding72323982014-07-11 13:19:06 +02001101}
1102
Laxman Dewangan21b49912016-10-10 15:14:34 +02001103/**
1104 * tegra_io_pad_power_enable() - enable power to I/O pad
1105 * @id: Tegra I/O pad ID for which to enable power
1106 *
1107 * Returns: 0 on success or a negative error code on failure.
1108 */
1109int tegra_io_pad_power_enable(enum tegra_io_pad id)
Thierry Reding72323982014-07-11 13:19:06 +02001110{
Vince Hsua9ccc1232016-08-11 09:13:36 +08001111 unsigned long request, status;
Jon Hunter27b12b4e2016-10-22 20:23:53 +01001112 u32 mask;
Thierry Reding72323982014-07-11 13:19:06 +02001113 int err;
1114
Jon Huntere8cf6612016-02-11 18:03:21 +00001115 mutex_lock(&pmc->powergates_lock);
1116
Thierry Reding589997a2019-01-25 11:22:52 +01001117 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001118 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +01001119 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001120 goto unlock;
1121 }
Thierry Reding72323982014-07-11 13:19:06 +02001122
Thierry Reding589997a2019-01-25 11:22:52 +01001123 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
Thierry Reding72323982014-07-11 13:19:06 +02001124
Thierry Reding589997a2019-01-25 11:22:52 +01001125 err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001126 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +01001127 dev_err(pmc->dev, "failed to enable I/O pad: %d\n", err);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001128 goto unlock;
Thierry Reding592431b2015-08-04 15:25:03 +02001129 }
Thierry Reding72323982014-07-11 13:19:06 +02001130
Thierry Reding589997a2019-01-25 11:22:52 +01001131 tegra_io_pad_unprepare(pmc);
Thierry Reding72323982014-07-11 13:19:06 +02001132
Laxman Dewangan21b49912016-10-10 15:14:34 +02001133unlock:
Jon Huntere8cf6612016-02-11 18:03:21 +00001134 mutex_unlock(&pmc->powergates_lock);
Jon Huntere8cf6612016-02-11 18:03:21 +00001135 return err;
Thierry Reding72323982014-07-11 13:19:06 +02001136}
Laxman Dewangan21b49912016-10-10 15:14:34 +02001137EXPORT_SYMBOL(tegra_io_pad_power_enable);
Thierry Reding72323982014-07-11 13:19:06 +02001138
Laxman Dewangan21b49912016-10-10 15:14:34 +02001139/**
1140 * tegra_io_pad_power_disable() - disable power to I/O pad
1141 * @id: Tegra I/O pad ID for which to disable power
1142 *
1143 * Returns: 0 on success or a negative error code on failure.
1144 */
1145int tegra_io_pad_power_disable(enum tegra_io_pad id)
Thierry Reding72323982014-07-11 13:19:06 +02001146{
Vince Hsua9ccc1232016-08-11 09:13:36 +08001147 unsigned long request, status;
Jon Hunter27b12b4e2016-10-22 20:23:53 +01001148 u32 mask;
Thierry Reding72323982014-07-11 13:19:06 +02001149 int err;
1150
Jon Huntere8cf6612016-02-11 18:03:21 +00001151 mutex_lock(&pmc->powergates_lock);
1152
Thierry Reding589997a2019-01-25 11:22:52 +01001153 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001154 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +01001155 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001156 goto unlock;
Thierry Reding592431b2015-08-04 15:25:03 +02001157 }
Thierry Reding72323982014-07-11 13:19:06 +02001158
Thierry Reding589997a2019-01-25 11:22:52 +01001159 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
Thierry Reding72323982014-07-11 13:19:06 +02001160
Thierry Reding589997a2019-01-25 11:22:52 +01001161 err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001162 if (err < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +01001163 dev_err(pmc->dev, "failed to disable I/O pad: %d\n", err);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001164 goto unlock;
1165 }
Thierry Reding72323982014-07-11 13:19:06 +02001166
Thierry Reding589997a2019-01-25 11:22:52 +01001167 tegra_io_pad_unprepare(pmc);
Thierry Reding72323982014-07-11 13:19:06 +02001168
Laxman Dewangan21b49912016-10-10 15:14:34 +02001169unlock:
1170 mutex_unlock(&pmc->powergates_lock);
1171 return err;
1172}
1173EXPORT_SYMBOL(tegra_io_pad_power_disable);
1174
Thierry Reding589997a2019-01-25 11:22:52 +01001175static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
Aapo Vienamof142b9d2018-08-10 21:08:09 +03001176{
1177 unsigned long request, status;
1178 u32 mask, value;
1179 int err;
1180
Thierry Reding589997a2019-01-25 11:22:52 +01001181 err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status,
1182 &mask);
Aapo Vienamof142b9d2018-08-10 21:08:09 +03001183 if (err)
1184 return err;
1185
Thierry Reding589997a2019-01-25 11:22:52 +01001186 value = tegra_pmc_readl(pmc, status);
Aapo Vienamof142b9d2018-08-10 21:08:09 +03001187
1188 return !(value & mask);
1189}
1190
Thierry Reding589997a2019-01-25 11:22:52 +01001191static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
1192 int voltage)
Laxman Dewangan21b49912016-10-10 15:14:34 +02001193{
1194 const struct tegra_io_pad_soc *pad;
1195 u32 value;
1196
1197 pad = tegra_io_pad_find(pmc, id);
1198 if (!pad)
1199 return -ENOENT;
1200
1201 if (pad->voltage == UINT_MAX)
1202 return -ENOTSUPP;
1203
1204 mutex_lock(&pmc->powergates_lock);
1205
Aapo Vienamo13136a42018-08-10 21:08:07 +03001206 if (pmc->soc->has_impl_33v_pwr) {
Thierry Reding589997a2019-01-25 11:22:52 +01001207 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001208
Aapo Vienamofccf0f72018-08-10 21:08:11 +03001209 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
Aapo Vienamo13136a42018-08-10 21:08:07 +03001210 value &= ~BIT(pad->voltage);
1211 else
1212 value |= BIT(pad->voltage);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001213
Thierry Reding589997a2019-01-25 11:22:52 +01001214 tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
Aapo Vienamo13136a42018-08-10 21:08:07 +03001215 } else {
1216 /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
Thierry Reding589997a2019-01-25 11:22:52 +01001217 value = tegra_pmc_readl(pmc, PMC_PWR_DET);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001218 value |= BIT(pad->voltage);
Thierry Reding589997a2019-01-25 11:22:52 +01001219 tegra_pmc_writel(pmc, value, PMC_PWR_DET);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001220
Aapo Vienamo13136a42018-08-10 21:08:07 +03001221 /* update I/O voltage */
Thierry Reding589997a2019-01-25 11:22:52 +01001222 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
Aapo Vienamo13136a42018-08-10 21:08:07 +03001223
Aapo Vienamofccf0f72018-08-10 21:08:11 +03001224 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
Aapo Vienamo13136a42018-08-10 21:08:07 +03001225 value &= ~BIT(pad->voltage);
1226 else
1227 value |= BIT(pad->voltage);
1228
Thierry Reding589997a2019-01-25 11:22:52 +01001229 tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
Aapo Vienamo13136a42018-08-10 21:08:07 +03001230 }
Laxman Dewangan21b49912016-10-10 15:14:34 +02001231
Jon Huntere8cf6612016-02-11 18:03:21 +00001232 mutex_unlock(&pmc->powergates_lock);
1233
Laxman Dewangan21b49912016-10-10 15:14:34 +02001234 usleep_range(100, 250);
1235
1236 return 0;
1237}
Laxman Dewangan21b49912016-10-10 15:14:34 +02001238
Thierry Reding589997a2019-01-25 11:22:52 +01001239static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
Laxman Dewangan21b49912016-10-10 15:14:34 +02001240{
1241 const struct tegra_io_pad_soc *pad;
1242 u32 value;
1243
1244 pad = tegra_io_pad_find(pmc, id);
1245 if (!pad)
1246 return -ENOENT;
1247
1248 if (pad->voltage == UINT_MAX)
1249 return -ENOTSUPP;
1250
Aapo Vienamo13136a42018-08-10 21:08:07 +03001251 if (pmc->soc->has_impl_33v_pwr)
Thierry Reding589997a2019-01-25 11:22:52 +01001252 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
Aapo Vienamo13136a42018-08-10 21:08:07 +03001253 else
Thierry Reding589997a2019-01-25 11:22:52 +01001254 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
Laxman Dewangan21b49912016-10-10 15:14:34 +02001255
1256 if ((value & BIT(pad->voltage)) == 0)
Aapo Vienamofccf0f72018-08-10 21:08:11 +03001257 return TEGRA_IO_PAD_VOLTAGE_1V8;
Laxman Dewangan21b49912016-10-10 15:14:34 +02001258
Aapo Vienamofccf0f72018-08-10 21:08:11 +03001259 return TEGRA_IO_PAD_VOLTAGE_3V3;
Laxman Dewangan21b49912016-10-10 15:14:34 +02001260}
Laxman Dewangan21b49912016-10-10 15:14:34 +02001261
1262/**
1263 * tegra_io_rail_power_on() - enable power to I/O rail
1264 * @id: Tegra I/O pad ID for which to enable power
1265 *
1266 * See also: tegra_io_pad_power_enable()
1267 */
1268int tegra_io_rail_power_on(unsigned int id)
1269{
1270 return tegra_io_pad_power_enable(id);
1271}
1272EXPORT_SYMBOL(tegra_io_rail_power_on);
1273
1274/**
1275 * tegra_io_rail_power_off() - disable power to I/O rail
1276 * @id: Tegra I/O pad ID for which to disable power
1277 *
1278 * See also: tegra_io_pad_power_disable()
1279 */
1280int tegra_io_rail_power_off(unsigned int id)
1281{
1282 return tegra_io_pad_power_disable(id);
Thierry Reding72323982014-07-11 13:19:06 +02001283}
1284EXPORT_SYMBOL(tegra_io_rail_power_off);
1285
1286#ifdef CONFIG_PM_SLEEP
1287enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
1288{
1289 return pmc->suspend_mode;
1290}
1291
1292void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
1293{
1294 if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
1295 return;
1296
1297 pmc->suspend_mode = mode;
1298}
1299
1300void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
1301{
1302 unsigned long long rate = 0;
1303 u32 value;
1304
1305 switch (mode) {
1306 case TEGRA_SUSPEND_LP1:
1307 rate = 32768;
1308 break;
1309
1310 case TEGRA_SUSPEND_LP2:
1311 rate = clk_get_rate(pmc->clk);
1312 break;
1313
1314 default:
1315 break;
1316 }
1317
1318 if (WARN_ON_ONCE(rate == 0))
1319 rate = 100000000;
1320
1321 if (rate != pmc->rate) {
1322 u64 ticks;
1323
1324 ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
1325 do_div(ticks, USEC_PER_SEC);
Thierry Reding589997a2019-01-25 11:22:52 +01001326 tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
Thierry Reding72323982014-07-11 13:19:06 +02001327
1328 ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
1329 do_div(ticks, USEC_PER_SEC);
Thierry Reding589997a2019-01-25 11:22:52 +01001330 tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
Thierry Reding72323982014-07-11 13:19:06 +02001331
1332 wmb();
1333
1334 pmc->rate = rate;
1335 }
1336
Thierry Reding589997a2019-01-25 11:22:52 +01001337 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Reding72323982014-07-11 13:19:06 +02001338 value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
1339 value |= PMC_CNTRL_CPU_PWRREQ_OE;
Thierry Reding589997a2019-01-25 11:22:52 +01001340 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Thierry Reding72323982014-07-11 13:19:06 +02001341}
1342#endif
1343
1344static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
1345{
1346 u32 value, values[2];
1347
1348 if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
1349 } else {
1350 switch (value) {
1351 case 0:
1352 pmc->suspend_mode = TEGRA_SUSPEND_LP0;
1353 break;
1354
1355 case 1:
1356 pmc->suspend_mode = TEGRA_SUSPEND_LP1;
1357 break;
1358
1359 case 2:
1360 pmc->suspend_mode = TEGRA_SUSPEND_LP2;
1361 break;
1362
1363 default:
1364 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1365 break;
1366 }
1367 }
1368
1369 pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
1370
1371 if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
1372 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1373
1374 pmc->cpu_good_time = value;
1375
1376 if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
1377 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1378
1379 pmc->cpu_off_time = value;
1380
1381 if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
1382 values, ARRAY_SIZE(values)))
1383 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1384
1385 pmc->core_osc_time = values[0];
1386 pmc->core_pmu_time = values[1];
1387
1388 if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
1389 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1390
1391 pmc->core_off_time = value;
1392
1393 pmc->corereq_high = of_property_read_bool(np,
1394 "nvidia,core-power-req-active-high");
1395
1396 pmc->sysclkreq_high = of_property_read_bool(np,
1397 "nvidia,sys-clock-req-active-high");
1398
1399 pmc->combined_req = of_property_read_bool(np,
1400 "nvidia,combined-power-req");
1401
1402 pmc->cpu_pwr_good_en = of_property_read_bool(np,
1403 "nvidia,cpu-pwr-good-en");
1404
1405 if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
1406 ARRAY_SIZE(values)))
1407 if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
1408 pmc->suspend_mode = TEGRA_SUSPEND_LP1;
1409
1410 pmc->lp0_vec_phys = values[0];
1411 pmc->lp0_vec_size = values[1];
1412
1413 return 0;
1414}
1415
1416static void tegra_pmc_init(struct tegra_pmc *pmc)
1417{
Thierry Reding5be22552017-08-30 12:32:58 +02001418 if (pmc->soc->init)
1419 pmc->soc->init(pmc);
Thierry Reding72323982014-07-11 13:19:06 +02001420}
1421
Jon Hunter1e52efdf2015-12-04 14:57:04 +00001422static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
Mikko Perttunen3568df32015-01-06 12:52:58 +02001423{
1424 static const char disabled[] = "emergency thermal reset disabled";
1425 u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
1426 struct device *dev = pmc->dev;
1427 struct device_node *np;
1428 u32 value, checksum;
1429
1430 if (!pmc->soc->has_tsense_reset)
Thierry Reding95169cd2015-07-09 09:59:55 +02001431 return;
Mikko Perttunen3568df32015-01-06 12:52:58 +02001432
Johan Hovold1dc6bd52017-11-15 10:44:58 +01001433 np = of_get_child_by_name(pmc->dev->of_node, "i2c-thermtrip");
Mikko Perttunen3568df32015-01-06 12:52:58 +02001434 if (!np) {
1435 dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
Thierry Reding95169cd2015-07-09 09:59:55 +02001436 return;
Mikko Perttunen3568df32015-01-06 12:52:58 +02001437 }
1438
1439 if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
1440 dev_err(dev, "I2C controller ID missing, %s.\n", disabled);
1441 goto out;
1442 }
1443
1444 if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) {
1445 dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled);
1446 goto out;
1447 }
1448
1449 if (of_property_read_u32(np, "nvidia,reg-addr", &reg_addr)) {
1450 dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled);
1451 goto out;
1452 }
1453
1454 if (of_property_read_u32(np, "nvidia,reg-data", &reg_data)) {
1455 dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled);
1456 goto out;
1457 }
1458
1459 if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
1460 pinmux = 0;
1461
Thierry Reding589997a2019-01-25 11:22:52 +01001462 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001463 value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
Thierry Reding589997a2019-01-25 11:22:52 +01001464 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001465
1466 value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
1467 (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
Thierry Reding589997a2019-01-25 11:22:52 +01001468 tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001469
1470 value = PMC_SCRATCH55_RESET_TEGRA;
1471 value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
1472 value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT;
1473 value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT;
1474
1475 /*
1476 * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will
1477 * contain the checksum and are currently zero, so they are not added.
1478 */
1479 checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff)
1480 + ((value >> 24) & 0xff);
1481 checksum &= 0xff;
1482 checksum = 0x100 - checksum;
1483
1484 value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
1485
Thierry Reding589997a2019-01-25 11:22:52 +01001486 tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001487
Thierry Reding589997a2019-01-25 11:22:52 +01001488 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001489 value |= PMC_SENSOR_CTRL_ENABLE_RST;
Thierry Reding589997a2019-01-25 11:22:52 +01001490 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001491
1492 dev_info(pmc->dev, "emergency thermal reset enabled\n");
1493
1494out:
1495 of_node_put(np);
Mikko Perttunen3568df32015-01-06 12:52:58 +02001496}
1497
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001498static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
1499{
Thierry Reding589997a2019-01-25 11:22:52 +01001500 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1501
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001502 return pmc->soc->num_io_pads;
1503}
1504
Thierry Redingf1d91292019-01-25 11:22:53 +01001505static const char *tegra_io_pad_pinctrl_get_group_name(struct pinctrl_dev *pctl,
1506 unsigned int group)
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001507{
Thierry Reding589997a2019-01-25 11:22:52 +01001508 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
1509
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001510 return pmc->soc->io_pads[group].name;
1511}
1512
1513static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
1514 unsigned int group,
1515 const unsigned int **pins,
1516 unsigned int *num_pins)
1517{
Thierry Reding589997a2019-01-25 11:22:52 +01001518 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1519
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001520 *pins = &pmc->soc->io_pads[group].id;
1521 *num_pins = 1;
Thierry Redingf1d91292019-01-25 11:22:53 +01001522
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001523 return 0;
1524}
1525
1526static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
1527 .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
1528 .get_group_name = tegra_io_pad_pinctrl_get_group_name,
1529 .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
1530 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
1531 .dt_free_map = pinconf_generic_dt_free_map,
1532};
1533
1534static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
1535 unsigned int pin, unsigned long *config)
1536{
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001537 enum pin_config_param param = pinconf_to_config_param(*config);
Thierry Reding589997a2019-01-25 11:22:52 +01001538 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1539 const struct tegra_io_pad_soc *pad;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001540 int ret;
1541 u32 arg;
1542
Thierry Reding589997a2019-01-25 11:22:52 +01001543 pad = tegra_io_pad_find(pmc, pin);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001544 if (!pad)
1545 return -EINVAL;
1546
1547 switch (param) {
1548 case PIN_CONFIG_POWER_SOURCE:
Thierry Reding589997a2019-01-25 11:22:52 +01001549 ret = tegra_io_pad_get_voltage(pmc, pad->id);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001550 if (ret < 0)
1551 return ret;
Thierry Redingf1d91292019-01-25 11:22:53 +01001552
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001553 arg = ret;
1554 break;
Thierry Redingf1d91292019-01-25 11:22:53 +01001555
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001556 case PIN_CONFIG_LOW_POWER_MODE:
Thierry Reding589997a2019-01-25 11:22:52 +01001557 ret = tegra_io_pad_is_powered(pmc, pad->id);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001558 if (ret < 0)
1559 return ret;
Thierry Redingf1d91292019-01-25 11:22:53 +01001560
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001561 arg = !ret;
1562 break;
Thierry Redingf1d91292019-01-25 11:22:53 +01001563
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001564 default:
1565 return -EINVAL;
1566 }
1567
1568 *config = pinconf_to_config_packed(param, arg);
1569
1570 return 0;
1571}
1572
1573static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
1574 unsigned int pin, unsigned long *configs,
1575 unsigned int num_configs)
1576{
Thierry Reding589997a2019-01-25 11:22:52 +01001577 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1578 const struct tegra_io_pad_soc *pad;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001579 enum pin_config_param param;
1580 unsigned int i;
1581 int err;
1582 u32 arg;
1583
Thierry Reding589997a2019-01-25 11:22:52 +01001584 pad = tegra_io_pad_find(pmc, pin);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001585 if (!pad)
1586 return -EINVAL;
1587
1588 for (i = 0; i < num_configs; ++i) {
1589 param = pinconf_to_config_param(configs[i]);
1590 arg = pinconf_to_config_argument(configs[i]);
1591
1592 switch (param) {
1593 case PIN_CONFIG_LOW_POWER_MODE:
1594 if (arg)
1595 err = tegra_io_pad_power_disable(pad->id);
1596 else
1597 err = tegra_io_pad_power_enable(pad->id);
1598 if (err)
1599 return err;
1600 break;
1601 case PIN_CONFIG_POWER_SOURCE:
1602 if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
1603 arg != TEGRA_IO_PAD_VOLTAGE_3V3)
1604 return -EINVAL;
Thierry Reding589997a2019-01-25 11:22:52 +01001605 err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001606 if (err)
1607 return err;
1608 break;
1609 default:
1610 return -EINVAL;
1611 }
1612 }
1613
1614 return 0;
1615}
1616
1617static const struct pinconf_ops tegra_io_pad_pinconf_ops = {
1618 .pin_config_get = tegra_io_pad_pinconf_get,
1619 .pin_config_set = tegra_io_pad_pinconf_set,
1620 .is_generic = true,
1621};
1622
1623static struct pinctrl_desc tegra_pmc_pctl_desc = {
1624 .pctlops = &tegra_io_pad_pinctrl_ops,
1625 .confops = &tegra_io_pad_pinconf_ops,
1626};
1627
1628static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1629{
Thierry Redingf1d91292019-01-25 11:22:53 +01001630 int err;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001631
1632 if (!pmc->soc->num_pin_descs)
1633 return 0;
1634
1635 tegra_pmc_pctl_desc.name = dev_name(pmc->dev);
1636 tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs;
1637 tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs;
1638
1639 pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc,
1640 pmc);
1641 if (IS_ERR(pmc->pctl_dev)) {
1642 err = PTR_ERR(pmc->pctl_dev);
Thierry Redingf1d91292019-01-25 11:22:53 +01001643 dev_err(pmc->dev, "failed to register pin controller: %d\n",
1644 err);
1645 return err;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001646 }
1647
Thierry Redingf1d91292019-01-25 11:22:53 +01001648 return 0;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001649}
1650
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301651static ssize_t reset_reason_show(struct device *dev,
Thierry Redingf1d91292019-01-25 11:22:53 +01001652 struct device_attribute *attr, char *buf)
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301653{
1654 u32 value, rst_src;
1655
Thierry Reding589997a2019-01-25 11:22:52 +01001656 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301657 rst_src = (value & pmc->soc->regs->rst_source_mask) >>
1658 pmc->soc->regs->rst_source_shift;
1659
1660 return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
1661}
1662
1663static DEVICE_ATTR_RO(reset_reason);
1664
1665static ssize_t reset_level_show(struct device *dev,
Thierry Redingf1d91292019-01-25 11:22:53 +01001666 struct device_attribute *attr, char *buf)
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301667{
1668 u32 value, rst_lvl;
1669
Thierry Reding589997a2019-01-25 11:22:52 +01001670 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301671 rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
1672 pmc->soc->regs->rst_level_shift;
1673
1674 return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
1675}
1676
1677static DEVICE_ATTR_RO(reset_level);
1678
1679static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
1680{
1681 struct device *dev = pmc->dev;
1682 int err = 0;
1683
1684 if (pmc->soc->reset_sources) {
1685 err = device_create_file(dev, &dev_attr_reset_reason);
1686 if (err < 0)
1687 dev_warn(dev,
Thierry Redingf1d91292019-01-25 11:22:53 +01001688 "failed to create attr \"reset_reason\": %d\n",
1689 err);
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301690 }
1691
1692 if (pmc->soc->reset_levels) {
1693 err = device_create_file(dev, &dev_attr_reset_level);
1694 if (err < 0)
1695 dev_warn(dev,
Thierry Redingf1d91292019-01-25 11:22:53 +01001696 "failed to create attr \"reset_level\": %d\n",
1697 err);
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301698 }
1699}
1700
Thierry Reding19906e62018-09-17 15:08:17 +02001701static int tegra_pmc_irq_translate(struct irq_domain *domain,
1702 struct irq_fwspec *fwspec,
1703 unsigned long *hwirq,
1704 unsigned int *type)
1705{
1706 if (WARN_ON(fwspec->param_count < 2))
1707 return -EINVAL;
1708
1709 *hwirq = fwspec->param[0];
1710 *type = fwspec->param[1];
1711
1712 return 0;
1713}
1714
1715static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
1716 unsigned int num_irqs, void *data)
1717{
1718 struct tegra_pmc *pmc = domain->host_data;
1719 const struct tegra_pmc_soc *soc = pmc->soc;
1720 struct irq_fwspec *fwspec = data;
1721 unsigned int i;
1722 int err = 0;
1723
1724 for (i = 0; i < soc->num_wake_events; i++) {
1725 const struct tegra_wake_event *event = &soc->wake_events[i];
1726
1727 if (fwspec->param_count == 2) {
1728 struct irq_fwspec spec;
1729
1730 if (event->id != fwspec->param[0])
1731 continue;
1732
1733 err = irq_domain_set_hwirq_and_chip(domain, virq,
1734 event->id,
1735 &pmc->irq, pmc);
1736 if (err < 0)
1737 break;
1738
1739 spec.fwnode = &pmc->dev->of_node->fwnode;
1740 spec.param_count = 3;
1741 spec.param[0] = GIC_SPI;
1742 spec.param[1] = event->irq;
1743 spec.param[2] = fwspec->param[1];
1744
1745 err = irq_domain_alloc_irqs_parent(domain, virq,
1746 num_irqs, &spec);
1747
1748 break;
1749 }
1750
1751 if (fwspec->param_count == 3) {
1752 if (event->gpio.instance != fwspec->param[0] ||
1753 event->gpio.pin != fwspec->param[1])
1754 continue;
1755
1756 err = irq_domain_set_hwirq_and_chip(domain, virq,
1757 event->id,
1758 &pmc->irq, pmc);
1759
1760 break;
1761 }
1762 }
1763
1764 if (i == soc->num_wake_events)
1765 err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
1766 &pmc->irq, pmc);
1767
1768 return err;
1769}
1770
1771static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
1772 .translate = tegra_pmc_irq_translate,
1773 .alloc = tegra_pmc_irq_alloc,
1774};
1775
1776static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
1777{
1778 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
1779 unsigned int offset, bit;
1780 u32 value;
1781
1782 offset = data->hwirq / 32;
1783 bit = data->hwirq % 32;
1784
1785 /* clear wake status */
1786 writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(data->hwirq));
1787
1788 /* route wake to tier 2 */
1789 value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
1790
1791 if (!on)
1792 value &= ~(1 << bit);
1793 else
1794 value |= 1 << bit;
1795
1796 writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
1797
1798 /* enable wakeup event */
1799 writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(data->hwirq));
1800
1801 return 0;
1802}
1803
1804static int tegra_pmc_irq_set_type(struct irq_data *data, unsigned int type)
1805{
1806 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
1807 u32 value;
1808
1809 if (data->hwirq == ULONG_MAX)
1810 return 0;
1811
1812 value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
1813
1814 switch (type) {
1815 case IRQ_TYPE_EDGE_RISING:
1816 case IRQ_TYPE_LEVEL_HIGH:
1817 value |= WAKE_AOWAKE_CNTRL_LEVEL;
1818 break;
1819
1820 case IRQ_TYPE_EDGE_FALLING:
1821 case IRQ_TYPE_LEVEL_LOW:
1822 value &= ~WAKE_AOWAKE_CNTRL_LEVEL;
1823 break;
1824
1825 case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
1826 value ^= WAKE_AOWAKE_CNTRL_LEVEL;
1827 break;
1828
1829 default:
1830 return -EINVAL;
1831 }
1832
1833 writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
1834
1835 return 0;
1836}
1837
1838static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
1839{
1840 struct irq_domain *parent = NULL;
1841 struct device_node *np;
1842
1843 np = of_irq_find_parent(pmc->dev->of_node);
1844 if (np) {
1845 parent = irq_find_host(np);
1846 of_node_put(np);
1847 }
1848
1849 if (!parent)
1850 return 0;
1851
1852 pmc->irq.name = dev_name(pmc->dev);
1853 pmc->irq.irq_mask = irq_chip_mask_parent;
1854 pmc->irq.irq_unmask = irq_chip_unmask_parent;
1855 pmc->irq.irq_eoi = irq_chip_eoi_parent;
1856 pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
1857 pmc->irq.irq_set_type = tegra_pmc_irq_set_type;
1858 pmc->irq.irq_set_wake = tegra_pmc_irq_set_wake;
1859
1860 pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
1861 &tegra_pmc_irq_domain_ops, pmc);
1862 if (!pmc->domain) {
1863 dev_err(pmc->dev, "failed to allocate domain\n");
1864 return -ENOMEM;
1865 }
1866
1867 return 0;
1868}
1869
Thierry Reding72323982014-07-11 13:19:06 +02001870static int tegra_pmc_probe(struct platform_device *pdev)
1871{
Jon Huntere8cf6612016-02-11 18:03:21 +00001872 void __iomem *base;
Thierry Reding72323982014-07-11 13:19:06 +02001873 struct resource *res;
1874 int err;
1875
Jon Huntera83f1fc2016-06-28 11:38:28 +01001876 /*
1877 * Early initialisation should have configured an initial
1878 * register mapping and setup the soc data pointer. If these
1879 * are not valid then something went badly wrong!
1880 */
1881 if (WARN_ON(!pmc->base || !pmc->soc))
1882 return -ENODEV;
1883
Thierry Reding72323982014-07-11 13:19:06 +02001884 err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
1885 if (err < 0)
1886 return err;
1887
1888 /* take over the memory region from the early initialization */
1889 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
Jon Hunter0259f522016-02-11 18:03:20 +00001890 base = devm_ioremap_resource(&pdev->dev, res);
1891 if (IS_ERR(base))
1892 return PTR_ERR(base);
Thierry Reding72323982014-07-11 13:19:06 +02001893
Thierry Redingc641ec62017-08-30 12:42:34 +02001894 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
1895 if (res) {
1896 pmc->wake = devm_ioremap_resource(&pdev->dev, res);
1897 if (IS_ERR(pmc->wake))
1898 return PTR_ERR(pmc->wake);
1899 } else {
1900 pmc->wake = base;
1901 }
1902
1903 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
1904 if (res) {
1905 pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
1906 if (IS_ERR(pmc->aotag))
1907 return PTR_ERR(pmc->aotag);
1908 } else {
1909 pmc->aotag = base;
1910 }
1911
1912 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
1913 if (res) {
1914 pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
1915 if (IS_ERR(pmc->scratch))
1916 return PTR_ERR(pmc->scratch);
1917 } else {
1918 pmc->scratch = base;
1919 }
Thierry Reding5be22552017-08-30 12:32:58 +02001920
Thierry Reding72323982014-07-11 13:19:06 +02001921 pmc->clk = devm_clk_get(&pdev->dev, "pclk");
1922 if (IS_ERR(pmc->clk)) {
1923 err = PTR_ERR(pmc->clk);
Thierry Reding5be22552017-08-30 12:32:58 +02001924
1925 if (err != -ENOENT) {
1926 dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
1927 return err;
1928 }
1929
1930 pmc->clk = NULL;
Thierry Reding72323982014-07-11 13:19:06 +02001931 }
1932
Mikko Perttunen3568df32015-01-06 12:52:58 +02001933 pmc->dev = &pdev->dev;
1934
Thierry Reding72323982014-07-11 13:19:06 +02001935 tegra_pmc_init(pmc);
1936
Mikko Perttunen3568df32015-01-06 12:52:58 +02001937 tegra_pmc_init_tsense_reset(pmc);
1938
Sandipan Patra5f84bb12018-10-24 12:38:00 +05301939 tegra_pmc_reset_sysfs_init(pmc);
1940
Thierry Reding72323982014-07-11 13:19:06 +02001941 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1942 err = tegra_powergate_debugfs_init();
1943 if (err < 0)
1944 return err;
1945 }
1946
David Riley78921582015-03-18 10:52:25 +01001947 err = register_restart_handler(&tegra_pmc_restart_handler);
1948 if (err) {
1949 dev_err(&pdev->dev, "unable to register restart handler, %d\n",
1950 err);
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001951 goto cleanup_debugfs;
David Riley78921582015-03-18 10:52:25 +01001952 }
1953
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001954 err = tegra_pmc_pinctrl_init(pmc);
1955 if (err)
1956 goto cleanup_restart_handler;
1957
Thierry Reding19906e62018-09-17 15:08:17 +02001958 err = tegra_pmc_irq_init(pmc);
1959 if (err < 0)
1960 goto cleanup_restart_handler;
1961
Jon Huntere8cf6612016-02-11 18:03:21 +00001962 mutex_lock(&pmc->powergates_lock);
1963 iounmap(pmc->base);
Jon Hunter0259f522016-02-11 18:03:20 +00001964 pmc->base = base;
Jon Huntere8cf6612016-02-11 18:03:21 +00001965 mutex_unlock(&pmc->powergates_lock);
Jon Hunter0259f522016-02-11 18:03:20 +00001966
Thierry Reding589997a2019-01-25 11:22:52 +01001967 platform_set_drvdata(pdev, pmc);
1968
Thierry Reding72323982014-07-11 13:19:06 +02001969 return 0;
Aapo Vienamo4a37f112018-08-10 21:08:12 +03001970
1971cleanup_restart_handler:
1972 unregister_restart_handler(&tegra_pmc_restart_handler);
1973cleanup_debugfs:
1974 debugfs_remove(pmc->debugfs);
1975 return err;
Thierry Reding72323982014-07-11 13:19:06 +02001976}
1977
Paul Walmsley2b20b612014-12-09 22:36:50 +00001978#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
Thierry Reding72323982014-07-11 13:19:06 +02001979static int tegra_pmc_suspend(struct device *dev)
1980{
Thierry Reding589997a2019-01-25 11:22:52 +01001981 struct tegra_pmc *pmc = dev_get_drvdata(dev);
1982
1983 tegra_pmc_writel(pmc, virt_to_phys(tegra_resume), PMC_SCRATCH41);
Thierry Reding72323982014-07-11 13:19:06 +02001984
1985 return 0;
1986}
1987
1988static int tegra_pmc_resume(struct device *dev)
1989{
Thierry Reding589997a2019-01-25 11:22:52 +01001990 struct tegra_pmc *pmc = dev_get_drvdata(dev);
1991
1992 tegra_pmc_writel(pmc, 0x0, PMC_SCRATCH41);
Thierry Reding72323982014-07-11 13:19:06 +02001993
1994 return 0;
1995}
Thierry Reding72323982014-07-11 13:19:06 +02001996
1997static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
1998
Paul Walmsley2b20b612014-12-09 22:36:50 +00001999#endif
2000
Thierry Reding72323982014-07-11 13:19:06 +02002001static const char * const tegra20_powergates[] = {
2002 [TEGRA_POWERGATE_CPU] = "cpu",
2003 [TEGRA_POWERGATE_3D] = "3d",
2004 [TEGRA_POWERGATE_VENC] = "venc",
2005 [TEGRA_POWERGATE_VDEC] = "vdec",
2006 [TEGRA_POWERGATE_PCIE] = "pcie",
2007 [TEGRA_POWERGATE_L2] = "l2",
2008 [TEGRA_POWERGATE_MPE] = "mpe",
2009};
2010
Thierry Reding5be22552017-08-30 12:32:58 +02002011static const struct tegra_pmc_regs tegra20_pmc_regs = {
2012 .scratch0 = 0x50,
2013 .dpd_req = 0x1b8,
2014 .dpd_status = 0x1bc,
2015 .dpd2_req = 0x1c0,
2016 .dpd2_status = 0x1c4,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302017 .rst_status = 0x1b4,
2018 .rst_source_shift = 0x0,
2019 .rst_source_mask = 0x7,
2020 .rst_level_shift = 0x0,
2021 .rst_level_mask = 0x0,
Thierry Reding5be22552017-08-30 12:32:58 +02002022};
2023
2024static void tegra20_pmc_init(struct tegra_pmc *pmc)
2025{
2026 u32 value;
2027
2028 /* Always enable CPU power request */
Thierry Reding589997a2019-01-25 11:22:52 +01002029 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002030 value |= PMC_CNTRL_CPU_PWRREQ_OE;
Thierry Reding589997a2019-01-25 11:22:52 +01002031 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002032
Thierry Reding589997a2019-01-25 11:22:52 +01002033 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002034
2035 if (pmc->sysclkreq_high)
2036 value &= ~PMC_CNTRL_SYSCLK_POLARITY;
2037 else
2038 value |= PMC_CNTRL_SYSCLK_POLARITY;
2039
2040 /* configure the output polarity while the request is tristated */
Thierry Reding589997a2019-01-25 11:22:52 +01002041 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002042
2043 /* now enable the request */
Thierry Reding589997a2019-01-25 11:22:52 +01002044 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002045 value |= PMC_CNTRL_SYSCLK_OE;
Thierry Reding589997a2019-01-25 11:22:52 +01002046 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002047}
2048
2049static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2050 struct device_node *np,
2051 bool invert)
2052{
2053 u32 value;
2054
Thierry Reding589997a2019-01-25 11:22:52 +01002055 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002056
2057 if (invert)
2058 value |= PMC_CNTRL_INTR_POLARITY;
2059 else
2060 value &= ~PMC_CNTRL_INTR_POLARITY;
2061
Thierry Reding589997a2019-01-25 11:22:52 +01002062 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Thierry Reding5be22552017-08-30 12:32:58 +02002063}
2064
Thierry Reding72323982014-07-11 13:19:06 +02002065static const struct tegra_pmc_soc tegra20_pmc_soc = {
2066 .num_powergates = ARRAY_SIZE(tegra20_powergates),
2067 .powergates = tegra20_powergates,
2068 .num_cpu_powergates = 0,
2069 .cpu_powergates = NULL,
Mikko Perttunen3568df32015-01-06 12:52:58 +02002070 .has_tsense_reset = false,
Thierry Redinga9a40a42015-01-09 11:15:33 +01002071 .has_gpu_clamps = false,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002072 .needs_mbist_war = false,
2073 .has_impl_33v_pwr = false,
Thierry Reding5be22552017-08-30 12:32:58 +02002074 .num_io_pads = 0,
2075 .io_pads = NULL,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002076 .num_pin_descs = 0,
2077 .pin_descs = NULL,
Thierry Reding5be22552017-08-30 12:32:58 +02002078 .regs = &tegra20_pmc_regs,
2079 .init = tegra20_pmc_init,
2080 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302081 .reset_sources = NULL,
2082 .num_reset_sources = 0,
2083 .reset_levels = NULL,
2084 .num_reset_levels = 0,
Thierry Reding72323982014-07-11 13:19:06 +02002085};
2086
2087static const char * const tegra30_powergates[] = {
2088 [TEGRA_POWERGATE_CPU] = "cpu0",
2089 [TEGRA_POWERGATE_3D] = "3d0",
2090 [TEGRA_POWERGATE_VENC] = "venc",
2091 [TEGRA_POWERGATE_VDEC] = "vdec",
2092 [TEGRA_POWERGATE_PCIE] = "pcie",
2093 [TEGRA_POWERGATE_L2] = "l2",
2094 [TEGRA_POWERGATE_MPE] = "mpe",
2095 [TEGRA_POWERGATE_HEG] = "heg",
2096 [TEGRA_POWERGATE_SATA] = "sata",
2097 [TEGRA_POWERGATE_CPU1] = "cpu1",
2098 [TEGRA_POWERGATE_CPU2] = "cpu2",
2099 [TEGRA_POWERGATE_CPU3] = "cpu3",
2100 [TEGRA_POWERGATE_CELP] = "celp",
2101 [TEGRA_POWERGATE_3D1] = "3d1",
2102};
2103
2104static const u8 tegra30_cpu_powergates[] = {
2105 TEGRA_POWERGATE_CPU,
2106 TEGRA_POWERGATE_CPU1,
2107 TEGRA_POWERGATE_CPU2,
2108 TEGRA_POWERGATE_CPU3,
2109};
2110
2111static const struct tegra_pmc_soc tegra30_pmc_soc = {
2112 .num_powergates = ARRAY_SIZE(tegra30_powergates),
2113 .powergates = tegra30_powergates,
2114 .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
2115 .cpu_powergates = tegra30_cpu_powergates,
Mikko Perttunen3568df32015-01-06 12:52:58 +02002116 .has_tsense_reset = true,
Thierry Redinga9a40a42015-01-09 11:15:33 +01002117 .has_gpu_clamps = false,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002118 .needs_mbist_war = false,
Aapo Vienamo13136a42018-08-10 21:08:07 +03002119 .has_impl_33v_pwr = false,
Thierry Reding5be22552017-08-30 12:32:58 +02002120 .num_io_pads = 0,
2121 .io_pads = NULL,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002122 .num_pin_descs = 0,
2123 .pin_descs = NULL,
Thierry Reding5be22552017-08-30 12:32:58 +02002124 .regs = &tegra20_pmc_regs,
2125 .init = tegra20_pmc_init,
2126 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302127 .reset_sources = tegra30_reset_sources,
2128 .num_reset_sources = 5,
2129 .reset_levels = NULL,
2130 .num_reset_levels = 0,
Thierry Reding72323982014-07-11 13:19:06 +02002131};
2132
2133static const char * const tegra114_powergates[] = {
2134 [TEGRA_POWERGATE_CPU] = "crail",
2135 [TEGRA_POWERGATE_3D] = "3d",
2136 [TEGRA_POWERGATE_VENC] = "venc",
2137 [TEGRA_POWERGATE_VDEC] = "vdec",
2138 [TEGRA_POWERGATE_MPE] = "mpe",
2139 [TEGRA_POWERGATE_HEG] = "heg",
2140 [TEGRA_POWERGATE_CPU1] = "cpu1",
2141 [TEGRA_POWERGATE_CPU2] = "cpu2",
2142 [TEGRA_POWERGATE_CPU3] = "cpu3",
2143 [TEGRA_POWERGATE_CELP] = "celp",
2144 [TEGRA_POWERGATE_CPU0] = "cpu0",
2145 [TEGRA_POWERGATE_C0NC] = "c0nc",
2146 [TEGRA_POWERGATE_C1NC] = "c1nc",
2147 [TEGRA_POWERGATE_DIS] = "dis",
2148 [TEGRA_POWERGATE_DISB] = "disb",
2149 [TEGRA_POWERGATE_XUSBA] = "xusba",
2150 [TEGRA_POWERGATE_XUSBB] = "xusbb",
2151 [TEGRA_POWERGATE_XUSBC] = "xusbc",
2152};
2153
2154static const u8 tegra114_cpu_powergates[] = {
2155 TEGRA_POWERGATE_CPU0,
2156 TEGRA_POWERGATE_CPU1,
2157 TEGRA_POWERGATE_CPU2,
2158 TEGRA_POWERGATE_CPU3,
2159};
2160
2161static const struct tegra_pmc_soc tegra114_pmc_soc = {
2162 .num_powergates = ARRAY_SIZE(tegra114_powergates),
2163 .powergates = tegra114_powergates,
2164 .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
2165 .cpu_powergates = tegra114_cpu_powergates,
Mikko Perttunen3568df32015-01-06 12:52:58 +02002166 .has_tsense_reset = true,
Thierry Redinga9a40a42015-01-09 11:15:33 +01002167 .has_gpu_clamps = false,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002168 .needs_mbist_war = false,
Aapo Vienamo13136a42018-08-10 21:08:07 +03002169 .has_impl_33v_pwr = false,
Thierry Reding5be22552017-08-30 12:32:58 +02002170 .num_io_pads = 0,
2171 .io_pads = NULL,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002172 .num_pin_descs = 0,
2173 .pin_descs = NULL,
Thierry Reding5be22552017-08-30 12:32:58 +02002174 .regs = &tegra20_pmc_regs,
2175 .init = tegra20_pmc_init,
2176 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302177 .reset_sources = tegra30_reset_sources,
2178 .num_reset_sources = 5,
2179 .reset_levels = NULL,
2180 .num_reset_levels = 0,
Thierry Reding72323982014-07-11 13:19:06 +02002181};
2182
2183static const char * const tegra124_powergates[] = {
2184 [TEGRA_POWERGATE_CPU] = "crail",
2185 [TEGRA_POWERGATE_3D] = "3d",
2186 [TEGRA_POWERGATE_VENC] = "venc",
2187 [TEGRA_POWERGATE_PCIE] = "pcie",
2188 [TEGRA_POWERGATE_VDEC] = "vdec",
Thierry Reding72323982014-07-11 13:19:06 +02002189 [TEGRA_POWERGATE_MPE] = "mpe",
2190 [TEGRA_POWERGATE_HEG] = "heg",
2191 [TEGRA_POWERGATE_SATA] = "sata",
2192 [TEGRA_POWERGATE_CPU1] = "cpu1",
2193 [TEGRA_POWERGATE_CPU2] = "cpu2",
2194 [TEGRA_POWERGATE_CPU3] = "cpu3",
2195 [TEGRA_POWERGATE_CELP] = "celp",
2196 [TEGRA_POWERGATE_CPU0] = "cpu0",
2197 [TEGRA_POWERGATE_C0NC] = "c0nc",
2198 [TEGRA_POWERGATE_C1NC] = "c1nc",
2199 [TEGRA_POWERGATE_SOR] = "sor",
2200 [TEGRA_POWERGATE_DIS] = "dis",
2201 [TEGRA_POWERGATE_DISB] = "disb",
2202 [TEGRA_POWERGATE_XUSBA] = "xusba",
2203 [TEGRA_POWERGATE_XUSBB] = "xusbb",
2204 [TEGRA_POWERGATE_XUSBC] = "xusbc",
2205 [TEGRA_POWERGATE_VIC] = "vic",
2206 [TEGRA_POWERGATE_IRAM] = "iram",
2207};
2208
2209static const u8 tegra124_cpu_powergates[] = {
2210 TEGRA_POWERGATE_CPU0,
2211 TEGRA_POWERGATE_CPU1,
2212 TEGRA_POWERGATE_CPU2,
2213 TEGRA_POWERGATE_CPU3,
2214};
2215
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002216#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \
2217 ((struct tegra_io_pad_soc) { \
2218 .id = (_id), \
2219 .dpd = (_dpd), \
2220 .voltage = (_voltage), \
2221 .name = (_name), \
2222 })
2223
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002224#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \
2225 ((struct pinctrl_pin_desc) { \
2226 .number = (_id), \
2227 .name = (_name) \
2228 })
2229
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002230#define TEGRA124_IO_PAD_TABLE(_pad) \
2231 /* .id .dpd .voltage .name */ \
2232 _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
2233 _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \
2234 _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \
2235 _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \
2236 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
2237 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \
2238 _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \
2239 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
2240 _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
2241 _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
2242 _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
2243 _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
2244 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
2245 _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \
2246 _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
2247 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
2248 _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \
2249 _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
2250 _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
2251 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
2252 _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
2253 _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \
2254 _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \
2255 _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \
2256 _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \
2257 _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
2258 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
2259 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
2260 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
2261 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias")
2262
Laxman Dewangan21b49912016-10-10 15:14:34 +02002263static const struct tegra_io_pad_soc tegra124_io_pads[] = {
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002264 TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD)
Laxman Dewangan21b49912016-10-10 15:14:34 +02002265};
2266
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002267static const struct pinctrl_pin_desc tegra124_pin_descs[] = {
2268 TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Thierry Reding72323982014-07-11 13:19:06 +02002269};
2270
2271static const struct tegra_pmc_soc tegra124_pmc_soc = {
2272 .num_powergates = ARRAY_SIZE(tegra124_powergates),
2273 .powergates = tegra124_powergates,
2274 .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
2275 .cpu_powergates = tegra124_cpu_powergates,
Mikko Perttunen3568df32015-01-06 12:52:58 +02002276 .has_tsense_reset = true,
Thierry Redinga9a40a42015-01-09 11:15:33 +01002277 .has_gpu_clamps = true,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002278 .needs_mbist_war = false,
Aapo Vienamo13136a42018-08-10 21:08:07 +03002279 .has_impl_33v_pwr = false,
Laxman Dewangan21b49912016-10-10 15:14:34 +02002280 .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
2281 .io_pads = tegra124_io_pads,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002282 .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
2283 .pin_descs = tegra124_pin_descs,
Thierry Reding5be22552017-08-30 12:32:58 +02002284 .regs = &tegra20_pmc_regs,
2285 .init = tegra20_pmc_init,
2286 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302287 .reset_sources = tegra30_reset_sources,
2288 .num_reset_sources = 5,
2289 .reset_levels = NULL,
2290 .num_reset_levels = 0,
Thierry Reding72323982014-07-11 13:19:06 +02002291};
2292
Thierry Redingc2fe4692015-03-23 11:31:29 +01002293static const char * const tegra210_powergates[] = {
2294 [TEGRA_POWERGATE_CPU] = "crail",
2295 [TEGRA_POWERGATE_3D] = "3d",
2296 [TEGRA_POWERGATE_VENC] = "venc",
2297 [TEGRA_POWERGATE_PCIE] = "pcie",
Thierry Redingc2fe4692015-03-23 11:31:29 +01002298 [TEGRA_POWERGATE_MPE] = "mpe",
Thierry Redingc2fe4692015-03-23 11:31:29 +01002299 [TEGRA_POWERGATE_SATA] = "sata",
2300 [TEGRA_POWERGATE_CPU1] = "cpu1",
2301 [TEGRA_POWERGATE_CPU2] = "cpu2",
2302 [TEGRA_POWERGATE_CPU3] = "cpu3",
Thierry Redingc2fe4692015-03-23 11:31:29 +01002303 [TEGRA_POWERGATE_CPU0] = "cpu0",
2304 [TEGRA_POWERGATE_C0NC] = "c0nc",
Thierry Redingc2fe4692015-03-23 11:31:29 +01002305 [TEGRA_POWERGATE_SOR] = "sor",
2306 [TEGRA_POWERGATE_DIS] = "dis",
2307 [TEGRA_POWERGATE_DISB] = "disb",
2308 [TEGRA_POWERGATE_XUSBA] = "xusba",
2309 [TEGRA_POWERGATE_XUSBB] = "xusbb",
2310 [TEGRA_POWERGATE_XUSBC] = "xusbc",
2311 [TEGRA_POWERGATE_VIC] = "vic",
2312 [TEGRA_POWERGATE_IRAM] = "iram",
2313 [TEGRA_POWERGATE_NVDEC] = "nvdec",
2314 [TEGRA_POWERGATE_NVJPG] = "nvjpg",
2315 [TEGRA_POWERGATE_AUD] = "aud",
2316 [TEGRA_POWERGATE_DFD] = "dfd",
2317 [TEGRA_POWERGATE_VE2] = "ve2",
2318};
2319
2320static const u8 tegra210_cpu_powergates[] = {
2321 TEGRA_POWERGATE_CPU0,
2322 TEGRA_POWERGATE_CPU1,
2323 TEGRA_POWERGATE_CPU2,
2324 TEGRA_POWERGATE_CPU3,
2325};
2326
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002327#define TEGRA210_IO_PAD_TABLE(_pad) \
2328 /* .id .dpd .voltage .name */ \
2329 _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \
2330 _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \
2331 _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \
2332 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
2333 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
2334 _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \
2335 _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \
2336 _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \
2337 _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \
2338 _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \
2339 _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \
2340 _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \
2341 _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \
2342 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
2343 _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
2344 _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
2345 _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
2346 _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \
2347 _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \
2348 _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \
2349 _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
2350 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
2351 _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
2352 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
2353 _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
2354 _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
2355 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
2356 _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \
2357 _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \
2358 _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \
2359 _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \
2360 _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \
2361 _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \
2362 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
2363 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
2364 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
2365 _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \
2366 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias")
2367
Laxman Dewangan21b49912016-10-10 15:14:34 +02002368static const struct tegra_io_pad_soc tegra210_io_pads[] = {
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002369 TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD)
Laxman Dewangan21b49912016-10-10 15:14:34 +02002370};
2371
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002372static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
2373 TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Thierry Redingc2fe4692015-03-23 11:31:29 +01002374};
2375
2376static const struct tegra_pmc_soc tegra210_pmc_soc = {
2377 .num_powergates = ARRAY_SIZE(tegra210_powergates),
2378 .powergates = tegra210_powergates,
2379 .num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates),
2380 .cpu_powergates = tegra210_cpu_powergates,
2381 .has_tsense_reset = true,
2382 .has_gpu_clamps = true,
Peter De Schrijvera263394a2018-01-25 16:00:13 +02002383 .needs_mbist_war = true,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002384 .has_impl_33v_pwr = false,
Laxman Dewangan21b49912016-10-10 15:14:34 +02002385 .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
2386 .io_pads = tegra210_io_pads,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002387 .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
2388 .pin_descs = tegra210_pin_descs,
Thierry Reding5be22552017-08-30 12:32:58 +02002389 .regs = &tegra20_pmc_regs,
2390 .init = tegra20_pmc_init,
2391 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302392 .reset_sources = tegra30_reset_sources,
2393 .num_reset_sources = 5,
2394 .reset_levels = NULL,
2395 .num_reset_levels = 0,
Thierry Redingc2fe4692015-03-23 11:31:29 +01002396};
2397
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002398#define TEGRA186_IO_PAD_TABLE(_pad) \
2399 /* .id .dpd .voltage .name */ \
2400 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
2401 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
2402 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
2403 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
2404 _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \
2405 _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \
2406 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
2407 _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \
2408 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
2409 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
2410 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
2411 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \
2412 _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
2413 _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
2414 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
2415 _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \
2416 _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \
2417 _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \
2418 _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
2419 _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \
2420 _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \
2421 _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \
2422 _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \
2423 _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \
2424 _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \
2425 _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \
2426 _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \
2427 _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \
2428 _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \
2429 _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \
2430 _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \
2431 _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \
2432 _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \
2433 _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \
2434 _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \
2435 _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \
2436 _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \
2437 _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv")
2438
Thierry Redingc641ec62017-08-30 12:42:34 +02002439static const struct tegra_io_pad_soc tegra186_io_pads[] = {
Aapo Vienamo437c4f22018-08-10 21:08:10 +03002440 TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD)
Thierry Redingc641ec62017-08-30 12:42:34 +02002441};
2442
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002443static const struct pinctrl_pin_desc tegra186_pin_descs[] = {
2444 TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Thierry Redingc641ec62017-08-30 12:42:34 +02002445};
2446
2447static const struct tegra_pmc_regs tegra186_pmc_regs = {
2448 .scratch0 = 0x2000,
2449 .dpd_req = 0x74,
2450 .dpd_status = 0x78,
2451 .dpd2_req = 0x7c,
2452 .dpd2_status = 0x80,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302453 .rst_status = 0x70,
2454 .rst_source_shift = 0x2,
2455 .rst_source_mask = 0x3C,
2456 .rst_level_shift = 0x0,
2457 .rst_level_mask = 0x3,
Thierry Redingc641ec62017-08-30 12:42:34 +02002458};
2459
2460static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2461 struct device_node *np,
2462 bool invert)
2463{
2464 struct resource regs;
2465 void __iomem *wake;
2466 u32 value;
2467 int index;
2468
2469 index = of_property_match_string(np, "reg-names", "wake");
2470 if (index < 0) {
Thierry Reding589997a2019-01-25 11:22:52 +01002471 dev_err(pmc->dev, "failed to find PMC wake registers\n");
Thierry Redingc641ec62017-08-30 12:42:34 +02002472 return;
2473 }
2474
2475 of_address_to_resource(np, index, &regs);
2476
2477 wake = ioremap_nocache(regs.start, resource_size(&regs));
2478 if (!wake) {
Thierry Reding589997a2019-01-25 11:22:52 +01002479 dev_err(pmc->dev, "failed to map PMC wake registers\n");
Thierry Redingc641ec62017-08-30 12:42:34 +02002480 return;
2481 }
2482
2483 value = readl(wake + WAKE_AOWAKE_CTRL);
2484
2485 if (invert)
2486 value |= WAKE_AOWAKE_CTRL_INTR_POLARITY;
2487 else
2488 value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY;
2489
2490 writel(value, wake + WAKE_AOWAKE_CTRL);
2491
2492 iounmap(wake);
2493}
2494
Thierry Redinge59333c2018-09-19 18:41:59 +02002495static const struct tegra_wake_event tegra186_wake_events[] = {
Thierry Reding532700e2019-01-23 12:38:43 +01002496 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)),
Thierry Redinge59333c2018-09-19 18:41:59 +02002497 TEGRA_WAKE_IRQ("rtc", 73, 10),
2498};
2499
Thierry Redingc641ec62017-08-30 12:42:34 +02002500static const struct tegra_pmc_soc tegra186_pmc_soc = {
2501 .num_powergates = 0,
2502 .powergates = NULL,
2503 .num_cpu_powergates = 0,
2504 .cpu_powergates = NULL,
2505 .has_tsense_reset = false,
2506 .has_gpu_clamps = false,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002507 .needs_mbist_war = false,
Aapo Vienamo13136a42018-08-10 21:08:07 +03002508 .has_impl_33v_pwr = true,
Thierry Redingc641ec62017-08-30 12:42:34 +02002509 .num_io_pads = ARRAY_SIZE(tegra186_io_pads),
2510 .io_pads = tegra186_io_pads,
Aapo Vienamo4a37f112018-08-10 21:08:12 +03002511 .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
2512 .pin_descs = tegra186_pin_descs,
Thierry Redingc641ec62017-08-30 12:42:34 +02002513 .regs = &tegra186_pmc_regs,
2514 .init = NULL,
2515 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
Sandipan Patra5f84bb12018-10-24 12:38:00 +05302516 .reset_sources = tegra186_reset_sources,
2517 .num_reset_sources = 14,
2518 .reset_levels = tegra186_reset_levels,
2519 .num_reset_levels = 3,
Thierry Redinge59333c2018-09-19 18:41:59 +02002520 .num_wake_events = ARRAY_SIZE(tegra186_wake_events),
2521 .wake_events = tegra186_wake_events,
Thierry Redingc641ec62017-08-30 12:42:34 +02002522};
2523
Thierry Redingeac9c482018-01-25 14:43:45 +02002524static const struct tegra_io_pad_soc tegra194_io_pads[] = {
2525 { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
2526 { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
2527 { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
2528 { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX },
2529 { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX },
2530 { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
2531 { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .voltage = UINT_MAX },
2532 { .id = TEGRA_IO_PAD_EQOS, .dpd = 8, .voltage = UINT_MAX },
2533 { .id = TEGRA_IO_PAD_PEX_CLK2_BIAS, .dpd = 9, .voltage = UINT_MAX },
2534 { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 10, .voltage = UINT_MAX },
2535 { .id = TEGRA_IO_PAD_DAP3, .dpd = 11, .voltage = UINT_MAX },
2536 { .id = TEGRA_IO_PAD_DAP5, .dpd = 12, .voltage = UINT_MAX },
2537 { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
2538 { .id = TEGRA_IO_PAD_PWR_CTL, .dpd = 15, .voltage = UINT_MAX },
2539 { .id = TEGRA_IO_PAD_SOC_GPIO53, .dpd = 16, .voltage = UINT_MAX },
2540 { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
2541 { .id = TEGRA_IO_PAD_GP_PWM2, .dpd = 18, .voltage = UINT_MAX },
2542 { .id = TEGRA_IO_PAD_GP_PWM3, .dpd = 19, .voltage = UINT_MAX },
2543 { .id = TEGRA_IO_PAD_SOC_GPIO12, .dpd = 20, .voltage = UINT_MAX },
2544 { .id = TEGRA_IO_PAD_SOC_GPIO13, .dpd = 21, .voltage = UINT_MAX },
2545 { .id = TEGRA_IO_PAD_SOC_GPIO10, .dpd = 22, .voltage = UINT_MAX },
2546 { .id = TEGRA_IO_PAD_UART4, .dpd = 23, .voltage = UINT_MAX },
2547 { .id = TEGRA_IO_PAD_UART5, .dpd = 24, .voltage = UINT_MAX },
2548 { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX },
2549 { .id = TEGRA_IO_PAD_HDMI_DP3, .dpd = 26, .voltage = UINT_MAX },
2550 { .id = TEGRA_IO_PAD_HDMI_DP2, .dpd = 27, .voltage = UINT_MAX },
2551 { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
2552 { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
2553 { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
2554 { .id = TEGRA_IO_PAD_PEX_CTL2, .dpd = 33, .voltage = UINT_MAX },
2555 { .id = TEGRA_IO_PAD_PEX_L0_RST_N, .dpd = 34, .voltage = UINT_MAX },
2556 { .id = TEGRA_IO_PAD_PEX_L1_RST_N, .dpd = 35, .voltage = UINT_MAX },
2557 { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
2558 { .id = TEGRA_IO_PAD_PEX_L5_RST_N, .dpd = 37, .voltage = UINT_MAX },
2559 { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX },
2560 { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX },
2561 { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX },
2562 { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX },
2563 { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX },
2564 { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX },
2565 { .id = TEGRA_IO_PAD_CSIG, .dpd = 50, .voltage = UINT_MAX },
2566 { .id = TEGRA_IO_PAD_CSIH, .dpd = 51, .voltage = UINT_MAX },
2567 { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX },
2568 { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX },
2569 { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX },
2570 { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX },
2571 { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX },
2572};
2573
Thierry Redinge3e403c2018-09-19 18:42:37 +02002574static const struct tegra_wake_event tegra194_wake_events[] = {
2575 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
2576 TEGRA_WAKE_IRQ("rtc", 73, 10),
2577};
2578
Thierry Redingeac9c482018-01-25 14:43:45 +02002579static const struct tegra_pmc_soc tegra194_pmc_soc = {
2580 .num_powergates = 0,
2581 .powergates = NULL,
2582 .num_cpu_powergates = 0,
2583 .cpu_powergates = NULL,
2584 .has_tsense_reset = false,
2585 .has_gpu_clamps = false,
Thierry Redingfa3bc042019-01-25 11:22:54 +01002586 .needs_mbist_war = false,
2587 .has_impl_33v_pwr = false,
Thierry Redingeac9c482018-01-25 14:43:45 +02002588 .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
2589 .io_pads = tegra194_io_pads,
2590 .regs = &tegra186_pmc_regs,
2591 .init = NULL,
2592 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
Thierry Redinge3e403c2018-09-19 18:42:37 +02002593 .num_wake_events = ARRAY_SIZE(tegra194_wake_events),
2594 .wake_events = tegra194_wake_events,
Thierry Reding72323982014-07-11 13:19:06 +02002595};
2596
2597static const struct of_device_id tegra_pmc_match[] = {
Thierry Redingeac9c482018-01-25 14:43:45 +02002598 { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc },
Thierry Redingc641ec62017-08-30 12:42:34 +02002599 { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc },
Thierry Redingc2fe4692015-03-23 11:31:29 +01002600 { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc },
Thierry Reding7d71e9032015-04-29 12:42:28 +02002601 { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc },
Thierry Reding72323982014-07-11 13:19:06 +02002602 { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
2603 { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
2604 { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
2605 { .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
2606 { }
2607};
2608
2609static struct platform_driver tegra_pmc_driver = {
2610 .driver = {
2611 .name = "tegra-pmc",
2612 .suppress_bind_attrs = true,
2613 .of_match_table = tegra_pmc_match,
Paul Walmsley2b20b612014-12-09 22:36:50 +00002614#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
Thierry Reding72323982014-07-11 13:19:06 +02002615 .pm = &tegra_pmc_pm_ops,
Paul Walmsley2b20b612014-12-09 22:36:50 +00002616#endif
Thierry Reding72323982014-07-11 13:19:06 +02002617 },
2618 .probe = tegra_pmc_probe,
2619};
Paul Gortmaker7d4d9ed2015-05-01 20:10:57 -04002620builtin_platform_driver(tegra_pmc_driver);
Thierry Reding72323982014-07-11 13:19:06 +02002621
2622/*
2623 * Early initialization to allow access to registers in the very early boot
2624 * process.
2625 */
2626static int __init tegra_pmc_early_init(void)
2627{
2628 const struct of_device_id *match;
2629 struct device_node *np;
2630 struct resource regs;
2631 bool invert;
Thierry Reding72323982014-07-11 13:19:06 +02002632
Jon Hunter61fd2842016-06-28 11:38:26 +01002633 mutex_init(&pmc->powergates_lock);
2634
Thierry Reding72323982014-07-11 13:19:06 +02002635 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
2636 if (!np) {
Thierry Reding7d71e9032015-04-29 12:42:28 +02002637 /*
2638 * Fall back to legacy initialization for 32-bit ARM only. All
2639 * 64-bit ARM device tree files for Tegra are required to have
2640 * a PMC node.
2641 *
2642 * This is for backwards-compatibility with old device trees
2643 * that didn't contain a PMC node. Note that in this case the
2644 * SoC data can't be matched and therefore powergating is
2645 * disabled.
2646 */
2647 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
2648 pr_warn("DT node not found, powergating disabled\n");
Thierry Reding72323982014-07-11 13:19:06 +02002649
Thierry Reding7d71e9032015-04-29 12:42:28 +02002650 regs.start = 0x7000e400;
2651 regs.end = 0x7000e7ff;
2652 regs.flags = IORESOURCE_MEM;
Thierry Reding72323982014-07-11 13:19:06 +02002653
Thierry Reding7d71e9032015-04-29 12:42:28 +02002654 pr_warn("Using memory region %pR\n", &regs);
2655 } else {
2656 /*
2657 * At this point we're not running on Tegra, so play
2658 * nice with multi-platform kernels.
2659 */
2660 return 0;
2661 }
Thierry Reding72323982014-07-11 13:19:06 +02002662 } else {
Thierry Reding7d71e9032015-04-29 12:42:28 +02002663 /*
2664 * Extract information from the device tree if we've found a
2665 * matching node.
2666 */
2667 if (of_address_to_resource(np, 0, &regs) < 0) {
2668 pr_err("failed to get PMC registers\n");
Jon Hunterb69a6252016-06-28 11:38:27 +01002669 of_node_put(np);
Thierry Reding7d71e9032015-04-29 12:42:28 +02002670 return -ENXIO;
2671 }
Thierry Reding72323982014-07-11 13:19:06 +02002672 }
2673
2674 pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
2675 if (!pmc->base) {
2676 pr_err("failed to map PMC registers\n");
Jon Hunterb69a6252016-06-28 11:38:27 +01002677 of_node_put(np);
Thierry Reding72323982014-07-11 13:19:06 +02002678 return -ENXIO;
2679 }
2680
Jon Hunter11131892016-06-28 11:38:24 +01002681 if (np) {
Jon Hunter718a2422016-06-28 11:38:25 +01002682 pmc->soc = match->data;
2683
Jon Huntere2d17962016-06-30 11:56:25 +01002684 tegra_powergate_init(pmc, np);
Thierry Reding72323982014-07-11 13:19:06 +02002685
Jon Hunter11131892016-06-28 11:38:24 +01002686 /*
2687 * Invert the interrupt polarity if a PMC device tree node
2688 * exists and contains the nvidia,invert-interrupt property.
2689 */
2690 invert = of_property_read_bool(np, "nvidia,invert-interrupt");
Thierry Reding72323982014-07-11 13:19:06 +02002691
Thierry Reding5be22552017-08-30 12:32:58 +02002692 pmc->soc->setup_irq_polarity(pmc, np, invert);
Jon Hunterb69a6252016-06-28 11:38:27 +01002693
2694 of_node_put(np);
Jon Hunter11131892016-06-28 11:38:24 +01002695 }
Thierry Reding72323982014-07-11 13:19:06 +02002696
2697 return 0;
2698}
2699early_initcall(tegra_pmc_early_init);