blob: 5726c232e61d5b748bff834b16406bb609ef05e9 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-only
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * drivers/soc/tegra/pmc.c
4 *
5 * Copyright (c) 2010 Google, Inc
Olivier Deprez157378f2022-04-04 15:47:50 +02006 * Copyright (c) 2018-2020, NVIDIA CORPORATION. All rights reserved.
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00007 *
8 * Author:
9 * Colin Cross <ccross@google.com>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000010 */
11
12#define pr_fmt(fmt) "tegra-pmc: " fmt
13
David Brazdil0f672f62019-12-10 10:32:29 +000014#include <linux/arm-smccc.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000015#include <linux/clk.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020016#include <linux/clk-provider.h>
17#include <linux/clkdev.h>
18#include <linux/clk/clk-conf.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000019#include <linux/clk/tegra.h>
20#include <linux/debugfs.h>
21#include <linux/delay.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020022#include <linux/device.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000023#include <linux/err.h>
24#include <linux/export.h>
25#include <linux/init.h>
26#include <linux/io.h>
27#include <linux/iopoll.h>
David Brazdil0f672f62019-12-10 10:32:29 +000028#include <linux/irqdomain.h>
29#include <linux/irq.h>
30#include <linux/kernel.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000031#include <linux/of_address.h>
32#include <linux/of_clk.h>
David Brazdil0f672f62019-12-10 10:32:29 +000033#include <linux/of.h>
34#include <linux/of_irq.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000035#include <linux/of_platform.h>
David Brazdil0f672f62019-12-10 10:32:29 +000036#include <linux/pinctrl/pinconf-generic.h>
37#include <linux/pinctrl/pinconf.h>
38#include <linux/pinctrl/pinctrl.h>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000039#include <linux/platform_device.h>
40#include <linux/pm_domain.h>
41#include <linux/reboot.h>
42#include <linux/reset.h>
43#include <linux/seq_file.h>
44#include <linux/slab.h>
45#include <linux/spinlock.h>
46
47#include <soc/tegra/common.h>
48#include <soc/tegra/fuse.h>
49#include <soc/tegra/pmc.h>
50
David Brazdil0f672f62019-12-10 10:32:29 +000051#include <dt-bindings/interrupt-controller/arm-gic.h>
52#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
53#include <dt-bindings/gpio/tegra186-gpio.h>
54#include <dt-bindings/gpio/tegra194-gpio.h>
Olivier Deprez157378f2022-04-04 15:47:50 +020055#include <dt-bindings/soc/tegra-pmc.h>
David Brazdil0f672f62019-12-10 10:32:29 +000056
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000057#define PMC_CNTRL 0x0
58#define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */
59#define PMC_CNTRL_CPU_PWRREQ_OE BIT(16) /* CPU pwr req enable */
60#define PMC_CNTRL_CPU_PWRREQ_POLARITY BIT(15) /* CPU pwr req polarity */
61#define PMC_CNTRL_SIDE_EFFECT_LP0 BIT(14) /* LP0 when CPU pwr gated */
62#define PMC_CNTRL_SYSCLK_OE BIT(11) /* system clock enable */
63#define PMC_CNTRL_SYSCLK_POLARITY BIT(10) /* sys clk polarity */
Olivier Deprez157378f2022-04-04 15:47:50 +020064#define PMC_CNTRL_PWRREQ_POLARITY BIT(8)
65#define PMC_CNTRL_BLINK_EN 7
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000066#define PMC_CNTRL_MAIN_RST BIT(4)
67
Olivier Deprez157378f2022-04-04 15:47:50 +020068#define PMC_WAKE_MASK 0x0c
69#define PMC_WAKE_LEVEL 0x10
70#define PMC_WAKE_STATUS 0x14
71#define PMC_SW_WAKE_STATUS 0x18
72#define PMC_DPD_PADS_ORIDE 0x1c
73#define PMC_DPD_PADS_ORIDE_BLINK 20
74
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000075#define DPD_SAMPLE 0x020
76#define DPD_SAMPLE_ENABLE BIT(0)
77#define DPD_SAMPLE_DISABLE (0 << 0)
78
79#define PWRGATE_TOGGLE 0x30
80#define PWRGATE_TOGGLE_START BIT(8)
81
82#define REMOVE_CLAMPING 0x34
83
84#define PWRGATE_STATUS 0x38
85
Olivier Deprez157378f2022-04-04 15:47:50 +020086#define PMC_BLINK_TIMER 0x40
David Brazdil0f672f62019-12-10 10:32:29 +000087#define PMC_IMPL_E_33V_PWR 0x40
88
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000089#define PMC_PWR_DET 0x48
90
91#define PMC_SCRATCH0_MODE_RECOVERY BIT(31)
92#define PMC_SCRATCH0_MODE_BOOTLOADER BIT(30)
93#define PMC_SCRATCH0_MODE_RCM BIT(1)
94#define PMC_SCRATCH0_MODE_MASK (PMC_SCRATCH0_MODE_RECOVERY | \
95 PMC_SCRATCH0_MODE_BOOTLOADER | \
96 PMC_SCRATCH0_MODE_RCM)
97
98#define PMC_CPUPWRGOOD_TIMER 0xc8
99#define PMC_CPUPWROFF_TIMER 0xcc
Olivier Deprez157378f2022-04-04 15:47:50 +0200100#define PMC_COREPWRGOOD_TIMER 0x3c
101#define PMC_COREPWROFF_TIMER 0xe0
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000102
103#define PMC_PWR_DET_VALUE 0xe4
104
105#define PMC_SCRATCH41 0x140
106
Olivier Deprez157378f2022-04-04 15:47:50 +0200107#define PMC_WAKE2_MASK 0x160
108#define PMC_WAKE2_LEVEL 0x164
109#define PMC_WAKE2_STATUS 0x168
110#define PMC_SW_WAKE2_STATUS 0x16c
111
112#define PMC_CLK_OUT_CNTRL 0x1a8
113#define PMC_CLK_OUT_MUX_MASK GENMASK(1, 0)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000114#define PMC_SENSOR_CTRL 0x1b0
115#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
116#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
117
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000118#define PMC_RST_STATUS_POR 0
119#define PMC_RST_STATUS_WATCHDOG 1
120#define PMC_RST_STATUS_SENSOR 2
121#define PMC_RST_STATUS_SW_MAIN 3
122#define PMC_RST_STATUS_LP0 4
123#define PMC_RST_STATUS_AOTAG 5
124
125#define IO_DPD_REQ 0x1b8
126#define IO_DPD_REQ_CODE_IDLE (0U << 30)
127#define IO_DPD_REQ_CODE_OFF (1U << 30)
128#define IO_DPD_REQ_CODE_ON (2U << 30)
129#define IO_DPD_REQ_CODE_MASK (3U << 30)
130
131#define IO_DPD_STATUS 0x1bc
132#define IO_DPD2_REQ 0x1c0
133#define IO_DPD2_STATUS 0x1c4
134#define SEL_DPD_TIM 0x1c8
135
136#define PMC_SCRATCH54 0x258
137#define PMC_SCRATCH54_DATA_SHIFT 8
138#define PMC_SCRATCH54_ADDR_SHIFT 0
139
140#define PMC_SCRATCH55 0x25c
141#define PMC_SCRATCH55_RESET_TEGRA BIT(31)
142#define PMC_SCRATCH55_CNTRL_ID_SHIFT 27
143#define PMC_SCRATCH55_PINMUX_SHIFT 24
144#define PMC_SCRATCH55_16BITOP BIT(15)
145#define PMC_SCRATCH55_CHECKSUM_SHIFT 16
146#define PMC_SCRATCH55_I2CSLV1_SHIFT 0
147
148#define GPU_RG_CNTRL 0x2d4
149
150/* Tegra186 and later */
David Brazdil0f672f62019-12-10 10:32:29 +0000151#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
152#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
153#define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
154#define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
155#define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
156#define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2))
157#define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2))
158#define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2))
159#define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2))
160
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000161#define WAKE_AOWAKE_CTRL 0x4f4
162#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
163
David Brazdil0f672f62019-12-10 10:32:29 +0000164/* for secure PMC */
165#define TEGRA_SMC_PMC 0xc2fffe00
166#define TEGRA_SMC_PMC_READ 0xaa
167#define TEGRA_SMC_PMC_WRITE 0xbb
168
Olivier Deprez157378f2022-04-04 15:47:50 +0200169struct pmc_clk {
170 struct clk_hw hw;
171 unsigned long offs;
172 u32 mux_shift;
173 u32 force_en_shift;
174};
175
176#define to_pmc_clk(_hw) container_of(_hw, struct pmc_clk, hw)
177
178struct pmc_clk_gate {
179 struct clk_hw hw;
180 unsigned long offs;
181 u32 shift;
182};
183
184#define to_pmc_clk_gate(_hw) container_of(_hw, struct pmc_clk_gate, hw)
185
186struct pmc_clk_init_data {
187 char *name;
188 const char *const *parents;
189 int num_parents;
190 int clk_id;
191 u8 mux_shift;
192 u8 force_en_shift;
193};
194
195static const char * const clk_out1_parents[] = { "osc", "osc_div2",
196 "osc_div4", "extern1",
197};
198
199static const char * const clk_out2_parents[] = { "osc", "osc_div2",
200 "osc_div4", "extern2",
201};
202
203static const char * const clk_out3_parents[] = { "osc", "osc_div2",
204 "osc_div4", "extern3",
205};
206
207static const struct pmc_clk_init_data tegra_pmc_clks_data[] = {
208 {
209 .name = "pmc_clk_out_1",
210 .parents = clk_out1_parents,
211 .num_parents = ARRAY_SIZE(clk_out1_parents),
212 .clk_id = TEGRA_PMC_CLK_OUT_1,
213 .mux_shift = 6,
214 .force_en_shift = 2,
215 },
216 {
217 .name = "pmc_clk_out_2",
218 .parents = clk_out2_parents,
219 .num_parents = ARRAY_SIZE(clk_out2_parents),
220 .clk_id = TEGRA_PMC_CLK_OUT_2,
221 .mux_shift = 14,
222 .force_en_shift = 10,
223 },
224 {
225 .name = "pmc_clk_out_3",
226 .parents = clk_out3_parents,
227 .num_parents = ARRAY_SIZE(clk_out3_parents),
228 .clk_id = TEGRA_PMC_CLK_OUT_3,
229 .mux_shift = 22,
230 .force_en_shift = 18,
231 },
232};
233
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000234struct tegra_powergate {
235 struct generic_pm_domain genpd;
236 struct tegra_pmc *pmc;
237 unsigned int id;
238 struct clk **clks;
239 unsigned int num_clks;
240 struct reset_control *reset;
241};
242
243struct tegra_io_pad_soc {
244 enum tegra_io_pad id;
245 unsigned int dpd;
246 unsigned int voltage;
David Brazdil0f672f62019-12-10 10:32:29 +0000247 const char *name;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000248};
249
250struct tegra_pmc_regs {
251 unsigned int scratch0;
252 unsigned int dpd_req;
253 unsigned int dpd_status;
254 unsigned int dpd2_req;
255 unsigned int dpd2_status;
David Brazdil0f672f62019-12-10 10:32:29 +0000256 unsigned int rst_status;
257 unsigned int rst_source_shift;
258 unsigned int rst_source_mask;
259 unsigned int rst_level_shift;
260 unsigned int rst_level_mask;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000261};
262
David Brazdil0f672f62019-12-10 10:32:29 +0000263struct tegra_wake_event {
264 const char *name;
265 unsigned int id;
266 unsigned int irq;
267 struct {
268 unsigned int instance;
269 unsigned int pin;
270 } gpio;
271};
272
273#define TEGRA_WAKE_IRQ(_name, _id, _irq) \
274 { \
275 .name = _name, \
276 .id = _id, \
277 .irq = _irq, \
278 .gpio = { \
279 .instance = UINT_MAX, \
280 .pin = UINT_MAX, \
281 }, \
282 }
283
284#define TEGRA_WAKE_GPIO(_name, _id, _instance, _pin) \
285 { \
286 .name = _name, \
287 .id = _id, \
288 .irq = 0, \
289 .gpio = { \
290 .instance = _instance, \
291 .pin = _pin, \
292 }, \
293 }
294
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000295struct tegra_pmc_soc {
296 unsigned int num_powergates;
297 const char *const *powergates;
298 unsigned int num_cpu_powergates;
299 const u8 *cpu_powergates;
300
301 bool has_tsense_reset;
302 bool has_gpu_clamps;
303 bool needs_mbist_war;
David Brazdil0f672f62019-12-10 10:32:29 +0000304 bool has_impl_33v_pwr;
305 bool maybe_tz_only;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000306
307 const struct tegra_io_pad_soc *io_pads;
308 unsigned int num_io_pads;
309
David Brazdil0f672f62019-12-10 10:32:29 +0000310 const struct pinctrl_pin_desc *pin_descs;
311 unsigned int num_pin_descs;
312
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000313 const struct tegra_pmc_regs *regs;
314 void (*init)(struct tegra_pmc *pmc);
315 void (*setup_irq_polarity)(struct tegra_pmc *pmc,
316 struct device_node *np,
317 bool invert);
Olivier Deprez157378f2022-04-04 15:47:50 +0200318 int (*irq_set_wake)(struct irq_data *data, unsigned int on);
319 int (*irq_set_type)(struct irq_data *data, unsigned int type);
320 int (*powergate_set)(struct tegra_pmc *pmc, unsigned int id,
321 bool new_state);
David Brazdil0f672f62019-12-10 10:32:29 +0000322
323 const char * const *reset_sources;
324 unsigned int num_reset_sources;
325 const char * const *reset_levels;
326 unsigned int num_reset_levels;
327
328 /*
329 * These describe events that can wake the system from sleep (i.e.
330 * LP0 or SC7). Wakeup from other sleep states (such as LP1 or LP2)
331 * are dealt with in the LIC.
332 */
333 const struct tegra_wake_event *wake_events;
334 unsigned int num_wake_events;
David Brazdil0f672f62019-12-10 10:32:29 +0000335
Olivier Deprez157378f2022-04-04 15:47:50 +0200336 const struct pmc_clk_init_data *pmc_clks_data;
337 unsigned int num_pmc_clks;
338 bool has_blink_output;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000339};
340
341/**
342 * struct tegra_pmc - NVIDIA Tegra PMC
343 * @dev: pointer to PMC device structure
344 * @base: pointer to I/O remapped register region
David Brazdil0f672f62019-12-10 10:32:29 +0000345 * @wake: pointer to I/O remapped region for WAKE registers
346 * @aotag: pointer to I/O remapped region for AOTAG registers
347 * @scratch: pointer to I/O remapped region for scratch registers
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000348 * @clk: pointer to pclk clock
349 * @soc: pointer to SoC data structure
David Brazdil0f672f62019-12-10 10:32:29 +0000350 * @tz_only: flag specifying if the PMC can only be accessed via TrustZone
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000351 * @debugfs: pointer to debugfs entry
352 * @rate: currently configured rate of pclk
353 * @suspend_mode: lowest suspend mode available
354 * @cpu_good_time: CPU power good time (in microseconds)
355 * @cpu_off_time: CPU power off time (in microsecends)
356 * @core_osc_time: core power good OSC time (in microseconds)
357 * @core_pmu_time: core power good PMU time (in microseconds)
358 * @core_off_time: core power off time (in microseconds)
359 * @corereq_high: core power request is active-high
360 * @sysclkreq_high: system clock request is active-high
361 * @combined_req: combined power request for CPU & core
362 * @cpu_pwr_good_en: CPU power good signal is enabled
363 * @lp0_vec_phys: physical base address of the LP0 warm boot code
364 * @lp0_vec_size: size of the LP0 warm boot code
365 * @powergates_available: Bitmap of available power gates
366 * @powergates_lock: mutex for power gate register access
David Brazdil0f672f62019-12-10 10:32:29 +0000367 * @pctl_dev: pin controller exposed by the PMC
368 * @domain: IRQ domain provided by the PMC
369 * @irq: chip implementation for the IRQ domain
Olivier Deprez157378f2022-04-04 15:47:50 +0200370 * @clk_nb: pclk clock changes handler
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000371 */
372struct tegra_pmc {
373 struct device *dev;
374 void __iomem *base;
375 void __iomem *wake;
376 void __iomem *aotag;
377 void __iomem *scratch;
378 struct clk *clk;
379 struct dentry *debugfs;
380
381 const struct tegra_pmc_soc *soc;
David Brazdil0f672f62019-12-10 10:32:29 +0000382 bool tz_only;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000383
384 unsigned long rate;
385
386 enum tegra_suspend_mode suspend_mode;
387 u32 cpu_good_time;
388 u32 cpu_off_time;
389 u32 core_osc_time;
390 u32 core_pmu_time;
391 u32 core_off_time;
392 bool corereq_high;
393 bool sysclkreq_high;
394 bool combined_req;
395 bool cpu_pwr_good_en;
396 u32 lp0_vec_phys;
397 u32 lp0_vec_size;
398 DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX);
399
400 struct mutex powergates_lock;
David Brazdil0f672f62019-12-10 10:32:29 +0000401
402 struct pinctrl_dev *pctl_dev;
403
404 struct irq_domain *domain;
405 struct irq_chip irq;
Olivier Deprez157378f2022-04-04 15:47:50 +0200406
407 struct notifier_block clk_nb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000408};
409
410static struct tegra_pmc *pmc = &(struct tegra_pmc) {
411 .base = NULL,
412 .suspend_mode = TEGRA_SUSPEND_NONE,
413};
414
415static inline struct tegra_powergate *
416to_powergate(struct generic_pm_domain *domain)
417{
418 return container_of(domain, struct tegra_powergate, genpd);
419}
420
David Brazdil0f672f62019-12-10 10:32:29 +0000421static u32 tegra_pmc_readl(struct tegra_pmc *pmc, unsigned long offset)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000422{
David Brazdil0f672f62019-12-10 10:32:29 +0000423 struct arm_smccc_res res;
424
425 if (pmc->tz_only) {
426 arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_READ, offset, 0, 0,
427 0, 0, 0, &res);
428 if (res.a0) {
429 if (pmc->dev)
430 dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
431 __func__, res.a0);
432 else
433 pr_warn("%s(): SMC failed: %lu\n", __func__,
434 res.a0);
435 }
436
437 return res.a1;
438 }
439
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000440 return readl(pmc->base + offset);
441}
442
David Brazdil0f672f62019-12-10 10:32:29 +0000443static void tegra_pmc_writel(struct tegra_pmc *pmc, u32 value,
444 unsigned long offset)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000445{
David Brazdil0f672f62019-12-10 10:32:29 +0000446 struct arm_smccc_res res;
447
448 if (pmc->tz_only) {
449 arm_smccc_smc(TEGRA_SMC_PMC, TEGRA_SMC_PMC_WRITE, offset,
450 value, 0, 0, 0, 0, &res);
451 if (res.a0) {
452 if (pmc->dev)
453 dev_warn(pmc->dev, "%s(): SMC failed: %lu\n",
454 __func__, res.a0);
455 else
456 pr_warn("%s(): SMC failed: %lu\n", __func__,
457 res.a0);
458 }
459 } else {
460 writel(value, pmc->base + offset);
461 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000462}
463
David Brazdil0f672f62019-12-10 10:32:29 +0000464static u32 tegra_pmc_scratch_readl(struct tegra_pmc *pmc, unsigned long offset)
465{
466 if (pmc->tz_only)
467 return tegra_pmc_readl(pmc, offset);
468
469 return readl(pmc->scratch + offset);
470}
471
472static void tegra_pmc_scratch_writel(struct tegra_pmc *pmc, u32 value,
473 unsigned long offset)
474{
475 if (pmc->tz_only)
476 tegra_pmc_writel(pmc, value, offset);
477 else
478 writel(value, pmc->scratch + offset);
479}
480
481/*
482 * TODO Figure out a way to call this with the struct tegra_pmc * passed in.
483 * This currently doesn't work because readx_poll_timeout() can only operate
484 * on functions that take a single argument.
485 */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000486static inline bool tegra_powergate_state(int id)
487{
488 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
David Brazdil0f672f62019-12-10 10:32:29 +0000489 return (tegra_pmc_readl(pmc, GPU_RG_CNTRL) & 0x1) == 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000490 else
David Brazdil0f672f62019-12-10 10:32:29 +0000491 return (tegra_pmc_readl(pmc, PWRGATE_STATUS) & BIT(id)) != 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000492}
493
David Brazdil0f672f62019-12-10 10:32:29 +0000494static inline bool tegra_powergate_is_valid(struct tegra_pmc *pmc, int id)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000495{
496 return (pmc->soc && pmc->soc->powergates[id]);
497}
498
David Brazdil0f672f62019-12-10 10:32:29 +0000499static inline bool tegra_powergate_is_available(struct tegra_pmc *pmc, int id)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000500{
501 return test_bit(id, pmc->powergates_available);
502}
503
504static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name)
505{
506 unsigned int i;
507
508 if (!pmc || !pmc->soc || !name)
509 return -EINVAL;
510
511 for (i = 0; i < pmc->soc->num_powergates; i++) {
David Brazdil0f672f62019-12-10 10:32:29 +0000512 if (!tegra_powergate_is_valid(pmc, i))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000513 continue;
514
515 if (!strcmp(name, pmc->soc->powergates[i]))
516 return i;
517 }
518
519 return -ENODEV;
520}
521
Olivier Deprez157378f2022-04-04 15:47:50 +0200522static int tegra20_powergate_set(struct tegra_pmc *pmc, unsigned int id,
523 bool new_state)
524{
525 unsigned int retries = 100;
526 bool status;
527 int ret;
528
529 /*
530 * As per TRM documentation, the toggle command will be dropped by PMC
531 * if there is contention with a HW-initiated toggling (i.e. CPU core
532 * power-gated), the command should be retried in that case.
533 */
534 do {
535 tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
536
537 /* wait for PMC to execute the command */
538 ret = readx_poll_timeout(tegra_powergate_state, id, status,
539 status == new_state, 1, 10);
540 } while (ret == -ETIMEDOUT && retries--);
541
542 return ret;
543}
544
545static inline bool tegra_powergate_toggle_ready(struct tegra_pmc *pmc)
546{
547 return !(tegra_pmc_readl(pmc, PWRGATE_TOGGLE) & PWRGATE_TOGGLE_START);
548}
549
550static int tegra114_powergate_set(struct tegra_pmc *pmc, unsigned int id,
551 bool new_state)
552{
553 bool status;
554 int err;
555
556 /* wait while PMC power gating is contended */
557 err = readx_poll_timeout(tegra_powergate_toggle_ready, pmc, status,
558 status == true, 1, 100);
559 if (err)
560 return err;
561
562 tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
563
564 /* wait for PMC to accept the command */
565 err = readx_poll_timeout(tegra_powergate_toggle_ready, pmc, status,
566 status == true, 1, 100);
567 if (err)
568 return err;
569
570 /* wait for PMC to execute the command */
571 err = readx_poll_timeout(tegra_powergate_state, id, status,
572 status == new_state, 10, 100000);
573 if (err)
574 return err;
575
576 return 0;
577}
578
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000579/**
580 * tegra_powergate_set() - set the state of a partition
David Brazdil0f672f62019-12-10 10:32:29 +0000581 * @pmc: power management controller
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000582 * @id: partition ID
583 * @new_state: new state of the partition
584 */
David Brazdil0f672f62019-12-10 10:32:29 +0000585static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id,
586 bool new_state)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000587{
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000588 int err;
589
590 if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps)
591 return -EINVAL;
592
593 mutex_lock(&pmc->powergates_lock);
594
595 if (tegra_powergate_state(id) == new_state) {
596 mutex_unlock(&pmc->powergates_lock);
597 return 0;
598 }
599
Olivier Deprez157378f2022-04-04 15:47:50 +0200600 err = pmc->soc->powergate_set(pmc, id, new_state);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000601
602 mutex_unlock(&pmc->powergates_lock);
603
604 return err;
605}
606
David Brazdil0f672f62019-12-10 10:32:29 +0000607static int __tegra_powergate_remove_clamping(struct tegra_pmc *pmc,
608 unsigned int id)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000609{
610 u32 mask;
611
612 mutex_lock(&pmc->powergates_lock);
613
614 /*
615 * On Tegra124 and later, the clamps for the GPU are controlled by a
616 * separate register (with different semantics).
617 */
618 if (id == TEGRA_POWERGATE_3D) {
619 if (pmc->soc->has_gpu_clamps) {
David Brazdil0f672f62019-12-10 10:32:29 +0000620 tegra_pmc_writel(pmc, 0, GPU_RG_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000621 goto out;
622 }
623 }
624
625 /*
626 * Tegra 2 has a bug where PCIE and VDE clamping masks are
627 * swapped relatively to the partition ids
628 */
629 if (id == TEGRA_POWERGATE_VDEC)
630 mask = (1 << TEGRA_POWERGATE_PCIE);
631 else if (id == TEGRA_POWERGATE_PCIE)
632 mask = (1 << TEGRA_POWERGATE_VDEC);
633 else
634 mask = (1 << id);
635
David Brazdil0f672f62019-12-10 10:32:29 +0000636 tegra_pmc_writel(pmc, mask, REMOVE_CLAMPING);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000637
638out:
639 mutex_unlock(&pmc->powergates_lock);
640
641 return 0;
642}
643
644static void tegra_powergate_disable_clocks(struct tegra_powergate *pg)
645{
646 unsigned int i;
647
648 for (i = 0; i < pg->num_clks; i++)
649 clk_disable_unprepare(pg->clks[i]);
650}
651
652static int tegra_powergate_enable_clocks(struct tegra_powergate *pg)
653{
654 unsigned int i;
655 int err;
656
657 for (i = 0; i < pg->num_clks; i++) {
658 err = clk_prepare_enable(pg->clks[i]);
659 if (err)
660 goto out;
661 }
662
663 return 0;
664
665out:
666 while (i--)
667 clk_disable_unprepare(pg->clks[i]);
668
669 return err;
670}
671
672int __weak tegra210_clk_handle_mbist_war(unsigned int id)
673{
674 return 0;
675}
676
677static int tegra_powergate_power_up(struct tegra_powergate *pg,
678 bool disable_clocks)
679{
680 int err;
681
682 err = reset_control_assert(pg->reset);
683 if (err)
684 return err;
685
686 usleep_range(10, 20);
687
David Brazdil0f672f62019-12-10 10:32:29 +0000688 err = tegra_powergate_set(pg->pmc, pg->id, true);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000689 if (err < 0)
690 return err;
691
692 usleep_range(10, 20);
693
694 err = tegra_powergate_enable_clocks(pg);
695 if (err)
Olivier Deprez157378f2022-04-04 15:47:50 +0200696 goto powergate_off;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000697
698 usleep_range(10, 20);
699
David Brazdil0f672f62019-12-10 10:32:29 +0000700 err = __tegra_powergate_remove_clamping(pg->pmc, pg->id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000701 if (err)
702 goto disable_clks;
703
704 usleep_range(10, 20);
705
706 err = reset_control_deassert(pg->reset);
707 if (err)
Olivier Deprez157378f2022-04-04 15:47:50 +0200708 goto disable_clks;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000709
710 usleep_range(10, 20);
711
712 if (pg->pmc->soc->needs_mbist_war)
713 err = tegra210_clk_handle_mbist_war(pg->id);
714 if (err)
715 goto disable_clks;
716
717 if (disable_clocks)
718 tegra_powergate_disable_clocks(pg);
719
720 return 0;
721
722disable_clks:
723 tegra_powergate_disable_clocks(pg);
724 usleep_range(10, 20);
725
726powergate_off:
David Brazdil0f672f62019-12-10 10:32:29 +0000727 tegra_powergate_set(pg->pmc, pg->id, false);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000728
729 return err;
730}
731
732static int tegra_powergate_power_down(struct tegra_powergate *pg)
733{
734 int err;
735
736 err = tegra_powergate_enable_clocks(pg);
737 if (err)
738 return err;
739
740 usleep_range(10, 20);
741
742 err = reset_control_assert(pg->reset);
743 if (err)
744 goto disable_clks;
745
746 usleep_range(10, 20);
747
748 tegra_powergate_disable_clocks(pg);
749
750 usleep_range(10, 20);
751
David Brazdil0f672f62019-12-10 10:32:29 +0000752 err = tegra_powergate_set(pg->pmc, pg->id, false);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000753 if (err)
754 goto assert_resets;
755
756 return 0;
757
758assert_resets:
759 tegra_powergate_enable_clocks(pg);
760 usleep_range(10, 20);
761 reset_control_deassert(pg->reset);
762 usleep_range(10, 20);
763
764disable_clks:
765 tegra_powergate_disable_clocks(pg);
766
767 return err;
768}
769
770static int tegra_genpd_power_on(struct generic_pm_domain *domain)
771{
772 struct tegra_powergate *pg = to_powergate(domain);
David Brazdil0f672f62019-12-10 10:32:29 +0000773 struct device *dev = pg->pmc->dev;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000774 int err;
775
776 err = tegra_powergate_power_up(pg, true);
David Brazdil0f672f62019-12-10 10:32:29 +0000777 if (err) {
778 dev_err(dev, "failed to turn on PM domain %s: %d\n",
779 pg->genpd.name, err);
780 goto out;
781 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000782
David Brazdil0f672f62019-12-10 10:32:29 +0000783 reset_control_release(pg->reset);
784
785out:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000786 return err;
787}
788
789static int tegra_genpd_power_off(struct generic_pm_domain *domain)
790{
791 struct tegra_powergate *pg = to_powergate(domain);
David Brazdil0f672f62019-12-10 10:32:29 +0000792 struct device *dev = pg->pmc->dev;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000793 int err;
794
David Brazdil0f672f62019-12-10 10:32:29 +0000795 err = reset_control_acquire(pg->reset);
796 if (err < 0) {
797 pr_err("failed to acquire resets: %d\n", err);
798 return err;
799 }
800
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000801 err = tegra_powergate_power_down(pg);
David Brazdil0f672f62019-12-10 10:32:29 +0000802 if (err) {
803 dev_err(dev, "failed to turn off PM domain %s: %d\n",
804 pg->genpd.name, err);
805 reset_control_release(pg->reset);
806 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000807
808 return err;
809}
810
811/**
812 * tegra_powergate_power_on() - power on partition
813 * @id: partition ID
814 */
815int tegra_powergate_power_on(unsigned int id)
816{
David Brazdil0f672f62019-12-10 10:32:29 +0000817 if (!tegra_powergate_is_available(pmc, id))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000818 return -EINVAL;
819
David Brazdil0f672f62019-12-10 10:32:29 +0000820 return tegra_powergate_set(pmc, id, true);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000821}
David Brazdil0f672f62019-12-10 10:32:29 +0000822EXPORT_SYMBOL(tegra_powergate_power_on);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000823
824/**
825 * tegra_powergate_power_off() - power off partition
826 * @id: partition ID
827 */
828int tegra_powergate_power_off(unsigned int id)
829{
David Brazdil0f672f62019-12-10 10:32:29 +0000830 if (!tegra_powergate_is_available(pmc, id))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000831 return -EINVAL;
832
David Brazdil0f672f62019-12-10 10:32:29 +0000833 return tegra_powergate_set(pmc, id, false);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000834}
835EXPORT_SYMBOL(tegra_powergate_power_off);
836
837/**
838 * tegra_powergate_is_powered() - check if partition is powered
David Brazdil0f672f62019-12-10 10:32:29 +0000839 * @pmc: power management controller
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000840 * @id: partition ID
841 */
David Brazdil0f672f62019-12-10 10:32:29 +0000842static int tegra_powergate_is_powered(struct tegra_pmc *pmc, unsigned int id)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000843{
David Brazdil0f672f62019-12-10 10:32:29 +0000844 if (!tegra_powergate_is_valid(pmc, id))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000845 return -EINVAL;
846
David Brazdil0f672f62019-12-10 10:32:29 +0000847 return tegra_powergate_state(id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000848}
849
850/**
851 * tegra_powergate_remove_clamping() - remove power clamps for partition
852 * @id: partition ID
853 */
854int tegra_powergate_remove_clamping(unsigned int id)
855{
David Brazdil0f672f62019-12-10 10:32:29 +0000856 if (!tegra_powergate_is_available(pmc, id))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000857 return -EINVAL;
858
David Brazdil0f672f62019-12-10 10:32:29 +0000859 return __tegra_powergate_remove_clamping(pmc, id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000860}
861EXPORT_SYMBOL(tegra_powergate_remove_clamping);
862
863/**
864 * tegra_powergate_sequence_power_up() - power up partition
865 * @id: partition ID
866 * @clk: clock for partition
867 * @rst: reset for partition
868 *
869 * Must be called with clk disabled, and returns with clk enabled.
870 */
871int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
872 struct reset_control *rst)
873{
874 struct tegra_powergate *pg;
875 int err;
876
David Brazdil0f672f62019-12-10 10:32:29 +0000877 if (!tegra_powergate_is_available(pmc, id))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000878 return -EINVAL;
879
880 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
881 if (!pg)
882 return -ENOMEM;
883
884 pg->id = id;
885 pg->clks = &clk;
886 pg->num_clks = 1;
887 pg->reset = rst;
888 pg->pmc = pmc;
889
890 err = tegra_powergate_power_up(pg, false);
891 if (err)
David Brazdil0f672f62019-12-10 10:32:29 +0000892 dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id,
893 err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000894
895 kfree(pg);
896
897 return err;
898}
899EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
900
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000901/**
902 * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
David Brazdil0f672f62019-12-10 10:32:29 +0000903 * @pmc: power management controller
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000904 * @cpuid: CPU partition ID
905 *
906 * Returns the partition ID corresponding to the CPU partition ID or a
907 * negative error code on failure.
908 */
David Brazdil0f672f62019-12-10 10:32:29 +0000909static int tegra_get_cpu_powergate_id(struct tegra_pmc *pmc,
910 unsigned int cpuid)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000911{
912 if (pmc->soc && cpuid < pmc->soc->num_cpu_powergates)
913 return pmc->soc->cpu_powergates[cpuid];
914
915 return -EINVAL;
916}
917
918/**
919 * tegra_pmc_cpu_is_powered() - check if CPU partition is powered
920 * @cpuid: CPU partition ID
921 */
922bool tegra_pmc_cpu_is_powered(unsigned int cpuid)
923{
924 int id;
925
David Brazdil0f672f62019-12-10 10:32:29 +0000926 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000927 if (id < 0)
928 return false;
929
David Brazdil0f672f62019-12-10 10:32:29 +0000930 return tegra_powergate_is_powered(pmc, id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000931}
932
933/**
934 * tegra_pmc_cpu_power_on() - power on CPU partition
935 * @cpuid: CPU partition ID
936 */
937int tegra_pmc_cpu_power_on(unsigned int cpuid)
938{
939 int id;
940
David Brazdil0f672f62019-12-10 10:32:29 +0000941 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000942 if (id < 0)
943 return id;
944
David Brazdil0f672f62019-12-10 10:32:29 +0000945 return tegra_powergate_set(pmc, id, true);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000946}
947
948/**
949 * tegra_pmc_cpu_remove_clamping() - remove power clamps for CPU partition
950 * @cpuid: CPU partition ID
951 */
952int tegra_pmc_cpu_remove_clamping(unsigned int cpuid)
953{
954 int id;
955
David Brazdil0f672f62019-12-10 10:32:29 +0000956 id = tegra_get_cpu_powergate_id(pmc, cpuid);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000957 if (id < 0)
958 return id;
959
960 return tegra_powergate_remove_clamping(id);
961}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000962
963static int tegra_pmc_restart_notify(struct notifier_block *this,
964 unsigned long action, void *data)
965{
966 const char *cmd = data;
967 u32 value;
968
David Brazdil0f672f62019-12-10 10:32:29 +0000969 value = tegra_pmc_scratch_readl(pmc, pmc->soc->regs->scratch0);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000970 value &= ~PMC_SCRATCH0_MODE_MASK;
971
972 if (cmd) {
973 if (strcmp(cmd, "recovery") == 0)
974 value |= PMC_SCRATCH0_MODE_RECOVERY;
975
976 if (strcmp(cmd, "bootloader") == 0)
977 value |= PMC_SCRATCH0_MODE_BOOTLOADER;
978
979 if (strcmp(cmd, "forced-recovery") == 0)
980 value |= PMC_SCRATCH0_MODE_RCM;
981 }
982
David Brazdil0f672f62019-12-10 10:32:29 +0000983 tegra_pmc_scratch_writel(pmc, value, pmc->soc->regs->scratch0);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000984
985 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
David Brazdil0f672f62019-12-10 10:32:29 +0000986 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000987 value |= PMC_CNTRL_MAIN_RST;
David Brazdil0f672f62019-12-10 10:32:29 +0000988 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000989
990 return NOTIFY_DONE;
991}
992
993static struct notifier_block tegra_pmc_restart_handler = {
994 .notifier_call = tegra_pmc_restart_notify,
995 .priority = 128,
996};
997
998static int powergate_show(struct seq_file *s, void *data)
999{
1000 unsigned int i;
1001 int status;
1002
1003 seq_printf(s, " powergate powered\n");
1004 seq_printf(s, "------------------\n");
1005
1006 for (i = 0; i < pmc->soc->num_powergates; i++) {
David Brazdil0f672f62019-12-10 10:32:29 +00001007 status = tegra_powergate_is_powered(pmc, i);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001008 if (status < 0)
1009 continue;
1010
1011 seq_printf(s, " %9s %7s\n", pmc->soc->powergates[i],
1012 status ? "yes" : "no");
1013 }
1014
1015 return 0;
1016}
1017
David Brazdil0f672f62019-12-10 10:32:29 +00001018DEFINE_SHOW_ATTRIBUTE(powergate);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001019
1020static int tegra_powergate_debugfs_init(void)
1021{
1022 pmc->debugfs = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
1023 &powergate_fops);
1024 if (!pmc->debugfs)
1025 return -ENOMEM;
1026
1027 return 0;
1028}
1029
1030static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
1031 struct device_node *np)
1032{
1033 struct clk *clk;
1034 unsigned int i, count;
1035 int err;
1036
1037 count = of_clk_get_parent_count(np);
1038 if (count == 0)
1039 return -ENODEV;
1040
1041 pg->clks = kcalloc(count, sizeof(clk), GFP_KERNEL);
1042 if (!pg->clks)
1043 return -ENOMEM;
1044
1045 for (i = 0; i < count; i++) {
1046 pg->clks[i] = of_clk_get(np, i);
1047 if (IS_ERR(pg->clks[i])) {
1048 err = PTR_ERR(pg->clks[i]);
1049 goto err;
1050 }
1051 }
1052
1053 pg->num_clks = count;
1054
1055 return 0;
1056
1057err:
1058 while (i--)
1059 clk_put(pg->clks[i]);
1060
1061 kfree(pg->clks);
1062
1063 return err;
1064}
1065
1066static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
1067 struct device_node *np, bool off)
1068{
David Brazdil0f672f62019-12-10 10:32:29 +00001069 struct device *dev = pg->pmc->dev;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001070 int err;
1071
David Brazdil0f672f62019-12-10 10:32:29 +00001072 pg->reset = of_reset_control_array_get_exclusive_released(np);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001073 if (IS_ERR(pg->reset)) {
1074 err = PTR_ERR(pg->reset);
David Brazdil0f672f62019-12-10 10:32:29 +00001075 dev_err(dev, "failed to get device resets: %d\n", err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001076 return err;
1077 }
1078
David Brazdil0f672f62019-12-10 10:32:29 +00001079 err = reset_control_acquire(pg->reset);
1080 if (err < 0) {
1081 pr_err("failed to acquire resets: %d\n", err);
1082 goto out;
1083 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001084
David Brazdil0f672f62019-12-10 10:32:29 +00001085 if (off) {
1086 err = reset_control_assert(pg->reset);
1087 } else {
1088 err = reset_control_deassert(pg->reset);
1089 if (err < 0)
1090 goto out;
1091
1092 reset_control_release(pg->reset);
1093 }
1094
1095out:
1096 if (err) {
1097 reset_control_release(pg->reset);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001098 reset_control_put(pg->reset);
David Brazdil0f672f62019-12-10 10:32:29 +00001099 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001100
1101 return err;
1102}
1103
David Brazdil0f672f62019-12-10 10:32:29 +00001104static int tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001105{
David Brazdil0f672f62019-12-10 10:32:29 +00001106 struct device *dev = pmc->dev;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001107 struct tegra_powergate *pg;
David Brazdil0f672f62019-12-10 10:32:29 +00001108 int id, err = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001109 bool off;
1110
1111 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
1112 if (!pg)
David Brazdil0f672f62019-12-10 10:32:29 +00001113 return -ENOMEM;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001114
1115 id = tegra_powergate_lookup(pmc, np->name);
1116 if (id < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001117 dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
1118 err = -ENODEV;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001119 goto free_mem;
1120 }
1121
1122 /*
1123 * Clear the bit for this powergate so it cannot be managed
1124 * directly via the legacy APIs for controlling powergates.
1125 */
1126 clear_bit(id, pmc->powergates_available);
1127
1128 pg->id = id;
1129 pg->genpd.name = np->name;
1130 pg->genpd.power_off = tegra_genpd_power_off;
1131 pg->genpd.power_on = tegra_genpd_power_on;
1132 pg->pmc = pmc;
1133
David Brazdil0f672f62019-12-10 10:32:29 +00001134 off = !tegra_powergate_is_powered(pmc, pg->id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001135
1136 err = tegra_powergate_of_get_clks(pg, np);
1137 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001138 dev_err(dev, "failed to get clocks for %pOFn: %d\n", np, err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001139 goto set_available;
1140 }
1141
1142 err = tegra_powergate_of_get_resets(pg, np, off);
1143 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001144 dev_err(dev, "failed to get resets for %pOFn: %d\n", np, err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001145 goto remove_clks;
1146 }
1147
1148 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
1149 if (off)
1150 WARN_ON(tegra_powergate_power_up(pg, true));
1151
1152 goto remove_resets;
1153 }
1154
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001155 err = pm_genpd_init(&pg->genpd, NULL, off);
1156 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001157 dev_err(dev, "failed to initialise PM domain %pOFn: %d\n", np,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001158 err);
1159 goto remove_resets;
1160 }
1161
1162 err = of_genpd_add_provider_simple(np, &pg->genpd);
1163 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001164 dev_err(dev, "failed to add PM domain provider for %pOFn: %d\n",
1165 np, err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001166 goto remove_genpd;
1167 }
1168
David Brazdil0f672f62019-12-10 10:32:29 +00001169 dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001170
David Brazdil0f672f62019-12-10 10:32:29 +00001171 return 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001172
1173remove_genpd:
1174 pm_genpd_remove(&pg->genpd);
1175
1176remove_resets:
1177 reset_control_put(pg->reset);
1178
1179remove_clks:
1180 while (pg->num_clks--)
1181 clk_put(pg->clks[pg->num_clks]);
1182
1183 kfree(pg->clks);
1184
1185set_available:
1186 set_bit(id, pmc->powergates_available);
1187
1188free_mem:
1189 kfree(pg);
David Brazdil0f672f62019-12-10 10:32:29 +00001190
1191 return err;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001192}
1193
David Brazdil0f672f62019-12-10 10:32:29 +00001194static int tegra_powergate_init(struct tegra_pmc *pmc,
1195 struct device_node *parent)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001196{
1197 struct device_node *np, *child;
David Brazdil0f672f62019-12-10 10:32:29 +00001198 int err = 0;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001199
David Brazdil0f672f62019-12-10 10:32:29 +00001200 np = of_get_child_by_name(parent, "powergates");
1201 if (!np)
1202 return 0;
1203
1204 for_each_child_of_node(np, child) {
1205 err = tegra_powergate_add(pmc, child);
1206 if (err < 0) {
1207 of_node_put(child);
1208 break;
1209 }
1210 }
1211
1212 of_node_put(np);
1213
1214 return err;
1215}
1216
1217static void tegra_powergate_remove(struct generic_pm_domain *genpd)
1218{
1219 struct tegra_powergate *pg = to_powergate(genpd);
1220
1221 reset_control_put(pg->reset);
1222
1223 while (pg->num_clks--)
1224 clk_put(pg->clks[pg->num_clks]);
1225
1226 kfree(pg->clks);
1227
1228 set_bit(pg->id, pmc->powergates_available);
1229
1230 kfree(pg);
1231}
1232
1233static void tegra_powergate_remove_all(struct device_node *parent)
1234{
1235 struct generic_pm_domain *genpd;
1236 struct device_node *np, *child;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001237
1238 np = of_get_child_by_name(parent, "powergates");
1239 if (!np)
1240 return;
1241
David Brazdil0f672f62019-12-10 10:32:29 +00001242 for_each_child_of_node(np, child) {
1243 of_genpd_del_provider(child);
1244
1245 genpd = of_genpd_remove_last(child);
1246 if (IS_ERR(genpd))
1247 continue;
1248
1249 tegra_powergate_remove(genpd);
1250 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001251
1252 of_node_put(np);
1253}
1254
1255static const struct tegra_io_pad_soc *
1256tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id)
1257{
1258 unsigned int i;
1259
1260 for (i = 0; i < pmc->soc->num_io_pads; i++)
1261 if (pmc->soc->io_pads[i].id == id)
1262 return &pmc->soc->io_pads[i];
1263
1264 return NULL;
1265}
1266
David Brazdil0f672f62019-12-10 10:32:29 +00001267static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc,
1268 enum tegra_io_pad id,
1269 unsigned long *request,
1270 unsigned long *status,
1271 u32 *mask)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001272{
1273 const struct tegra_io_pad_soc *pad;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001274
1275 pad = tegra_io_pad_find(pmc, id);
1276 if (!pad) {
David Brazdil0f672f62019-12-10 10:32:29 +00001277 dev_err(pmc->dev, "invalid I/O pad ID %u\n", id);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001278 return -ENOENT;
1279 }
1280
1281 if (pad->dpd == UINT_MAX)
1282 return -ENOTSUPP;
1283
1284 *mask = BIT(pad->dpd % 32);
1285
1286 if (pad->dpd < 32) {
1287 *status = pmc->soc->regs->dpd_status;
1288 *request = pmc->soc->regs->dpd_req;
1289 } else {
1290 *status = pmc->soc->regs->dpd2_status;
1291 *request = pmc->soc->regs->dpd2_req;
1292 }
1293
David Brazdil0f672f62019-12-10 10:32:29 +00001294 return 0;
1295}
1296
1297static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id,
1298 unsigned long *request, unsigned long *status,
1299 u32 *mask)
1300{
1301 unsigned long rate, value;
1302 int err;
1303
1304 err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask);
1305 if (err)
1306 return err;
1307
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001308 if (pmc->clk) {
Olivier Deprez157378f2022-04-04 15:47:50 +02001309 rate = pmc->rate;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001310 if (!rate) {
David Brazdil0f672f62019-12-10 10:32:29 +00001311 dev_err(pmc->dev, "failed to get clock rate\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001312 return -ENODEV;
1313 }
1314
David Brazdil0f672f62019-12-10 10:32:29 +00001315 tegra_pmc_writel(pmc, DPD_SAMPLE_ENABLE, DPD_SAMPLE);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001316
1317 /* must be at least 200 ns, in APB (PCLK) clock cycles */
1318 value = DIV_ROUND_UP(1000000000, rate);
1319 value = DIV_ROUND_UP(200, value);
David Brazdil0f672f62019-12-10 10:32:29 +00001320 tegra_pmc_writel(pmc, value, SEL_DPD_TIM);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001321 }
1322
1323 return 0;
1324}
1325
David Brazdil0f672f62019-12-10 10:32:29 +00001326static int tegra_io_pad_poll(struct tegra_pmc *pmc, unsigned long offset,
1327 u32 mask, u32 val, unsigned long timeout)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001328{
1329 u32 value;
1330
1331 timeout = jiffies + msecs_to_jiffies(timeout);
1332
1333 while (time_after(timeout, jiffies)) {
David Brazdil0f672f62019-12-10 10:32:29 +00001334 value = tegra_pmc_readl(pmc, offset);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001335 if ((value & mask) == val)
1336 return 0;
1337
1338 usleep_range(250, 1000);
1339 }
1340
1341 return -ETIMEDOUT;
1342}
1343
David Brazdil0f672f62019-12-10 10:32:29 +00001344static void tegra_io_pad_unprepare(struct tegra_pmc *pmc)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001345{
1346 if (pmc->clk)
David Brazdil0f672f62019-12-10 10:32:29 +00001347 tegra_pmc_writel(pmc, DPD_SAMPLE_DISABLE, DPD_SAMPLE);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001348}
1349
1350/**
1351 * tegra_io_pad_power_enable() - enable power to I/O pad
1352 * @id: Tegra I/O pad ID for which to enable power
1353 *
1354 * Returns: 0 on success or a negative error code on failure.
1355 */
1356int tegra_io_pad_power_enable(enum tegra_io_pad id)
1357{
1358 unsigned long request, status;
1359 u32 mask;
1360 int err;
1361
1362 mutex_lock(&pmc->powergates_lock);
1363
David Brazdil0f672f62019-12-10 10:32:29 +00001364 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001365 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001366 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001367 goto unlock;
1368 }
1369
David Brazdil0f672f62019-12-10 10:32:29 +00001370 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_OFF | mask, request);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001371
David Brazdil0f672f62019-12-10 10:32:29 +00001372 err = tegra_io_pad_poll(pmc, status, mask, 0, 250);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001373 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001374 dev_err(pmc->dev, "failed to enable I/O pad: %d\n", err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001375 goto unlock;
1376 }
1377
David Brazdil0f672f62019-12-10 10:32:29 +00001378 tegra_io_pad_unprepare(pmc);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001379
1380unlock:
1381 mutex_unlock(&pmc->powergates_lock);
1382 return err;
1383}
1384EXPORT_SYMBOL(tegra_io_pad_power_enable);
1385
1386/**
1387 * tegra_io_pad_power_disable() - disable power to I/O pad
1388 * @id: Tegra I/O pad ID for which to disable power
1389 *
1390 * Returns: 0 on success or a negative error code on failure.
1391 */
1392int tegra_io_pad_power_disable(enum tegra_io_pad id)
1393{
1394 unsigned long request, status;
1395 u32 mask;
1396 int err;
1397
1398 mutex_lock(&pmc->powergates_lock);
1399
David Brazdil0f672f62019-12-10 10:32:29 +00001400 err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001401 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001402 dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001403 goto unlock;
1404 }
1405
David Brazdil0f672f62019-12-10 10:32:29 +00001406 tegra_pmc_writel(pmc, IO_DPD_REQ_CODE_ON | mask, request);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001407
David Brazdil0f672f62019-12-10 10:32:29 +00001408 err = tegra_io_pad_poll(pmc, status, mask, mask, 250);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001409 if (err < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001410 dev_err(pmc->dev, "failed to disable I/O pad: %d\n", err);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001411 goto unlock;
1412 }
1413
David Brazdil0f672f62019-12-10 10:32:29 +00001414 tegra_io_pad_unprepare(pmc);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001415
1416unlock:
1417 mutex_unlock(&pmc->powergates_lock);
1418 return err;
1419}
1420EXPORT_SYMBOL(tegra_io_pad_power_disable);
1421
David Brazdil0f672f62019-12-10 10:32:29 +00001422static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id)
1423{
1424 unsigned long request, status;
1425 u32 mask, value;
1426 int err;
1427
1428 err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status,
1429 &mask);
1430 if (err)
1431 return err;
1432
1433 value = tegra_pmc_readl(pmc, status);
1434
1435 return !(value & mask);
1436}
1437
1438static int tegra_io_pad_set_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id,
1439 int voltage)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001440{
1441 const struct tegra_io_pad_soc *pad;
1442 u32 value;
1443
1444 pad = tegra_io_pad_find(pmc, id);
1445 if (!pad)
1446 return -ENOENT;
1447
1448 if (pad->voltage == UINT_MAX)
1449 return -ENOTSUPP;
1450
1451 mutex_lock(&pmc->powergates_lock);
1452
David Brazdil0f672f62019-12-10 10:32:29 +00001453 if (pmc->soc->has_impl_33v_pwr) {
1454 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001455
David Brazdil0f672f62019-12-10 10:32:29 +00001456 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
1457 value &= ~BIT(pad->voltage);
1458 else
1459 value |= BIT(pad->voltage);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001460
David Brazdil0f672f62019-12-10 10:32:29 +00001461 tegra_pmc_writel(pmc, value, PMC_IMPL_E_33V_PWR);
1462 } else {
1463 /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */
1464 value = tegra_pmc_readl(pmc, PMC_PWR_DET);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001465 value |= BIT(pad->voltage);
David Brazdil0f672f62019-12-10 10:32:29 +00001466 tegra_pmc_writel(pmc, value, PMC_PWR_DET);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001467
David Brazdil0f672f62019-12-10 10:32:29 +00001468 /* update I/O voltage */
1469 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
1470
1471 if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8)
1472 value &= ~BIT(pad->voltage);
1473 else
1474 value |= BIT(pad->voltage);
1475
1476 tegra_pmc_writel(pmc, value, PMC_PWR_DET_VALUE);
1477 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001478
1479 mutex_unlock(&pmc->powergates_lock);
1480
1481 usleep_range(100, 250);
1482
1483 return 0;
1484}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001485
David Brazdil0f672f62019-12-10 10:32:29 +00001486static int tegra_io_pad_get_voltage(struct tegra_pmc *pmc, enum tegra_io_pad id)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001487{
1488 const struct tegra_io_pad_soc *pad;
1489 u32 value;
1490
1491 pad = tegra_io_pad_find(pmc, id);
1492 if (!pad)
1493 return -ENOENT;
1494
1495 if (pad->voltage == UINT_MAX)
1496 return -ENOTSUPP;
1497
David Brazdil0f672f62019-12-10 10:32:29 +00001498 if (pmc->soc->has_impl_33v_pwr)
1499 value = tegra_pmc_readl(pmc, PMC_IMPL_E_33V_PWR);
1500 else
1501 value = tegra_pmc_readl(pmc, PMC_PWR_DET_VALUE);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001502
1503 if ((value & BIT(pad->voltage)) == 0)
David Brazdil0f672f62019-12-10 10:32:29 +00001504 return TEGRA_IO_PAD_VOLTAGE_1V8;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001505
David Brazdil0f672f62019-12-10 10:32:29 +00001506 return TEGRA_IO_PAD_VOLTAGE_3V3;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001507}
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001508
1509/**
1510 * tegra_io_rail_power_on() - enable power to I/O rail
1511 * @id: Tegra I/O pad ID for which to enable power
1512 *
1513 * See also: tegra_io_pad_power_enable()
1514 */
1515int tegra_io_rail_power_on(unsigned int id)
1516{
1517 return tegra_io_pad_power_enable(id);
1518}
1519EXPORT_SYMBOL(tegra_io_rail_power_on);
1520
1521/**
1522 * tegra_io_rail_power_off() - disable power to I/O rail
1523 * @id: Tegra I/O pad ID for which to disable power
1524 *
1525 * See also: tegra_io_pad_power_disable()
1526 */
1527int tegra_io_rail_power_off(unsigned int id)
1528{
1529 return tegra_io_pad_power_disable(id);
1530}
1531EXPORT_SYMBOL(tegra_io_rail_power_off);
1532
1533#ifdef CONFIG_PM_SLEEP
1534enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
1535{
1536 return pmc->suspend_mode;
1537}
1538
1539void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
1540{
1541 if (mode < TEGRA_SUSPEND_NONE || mode >= TEGRA_MAX_SUSPEND_MODE)
1542 return;
1543
1544 pmc->suspend_mode = mode;
1545}
1546
1547void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
1548{
1549 unsigned long long rate = 0;
Olivier Deprez157378f2022-04-04 15:47:50 +02001550 u64 ticks;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001551 u32 value;
1552
1553 switch (mode) {
1554 case TEGRA_SUSPEND_LP1:
1555 rate = 32768;
1556 break;
1557
1558 case TEGRA_SUSPEND_LP2:
Olivier Deprez157378f2022-04-04 15:47:50 +02001559 rate = pmc->rate;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001560 break;
1561
1562 default:
1563 break;
1564 }
1565
1566 if (WARN_ON_ONCE(rate == 0))
1567 rate = 100000000;
1568
Olivier Deprez157378f2022-04-04 15:47:50 +02001569 ticks = pmc->cpu_good_time * rate + USEC_PER_SEC - 1;
1570 do_div(ticks, USEC_PER_SEC);
1571 tegra_pmc_writel(pmc, ticks, PMC_CPUPWRGOOD_TIMER);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001572
Olivier Deprez157378f2022-04-04 15:47:50 +02001573 ticks = pmc->cpu_off_time * rate + USEC_PER_SEC - 1;
1574 do_div(ticks, USEC_PER_SEC);
1575 tegra_pmc_writel(pmc, ticks, PMC_CPUPWROFF_TIMER);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001576
David Brazdil0f672f62019-12-10 10:32:29 +00001577 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001578 value &= ~PMC_CNTRL_SIDE_EFFECT_LP0;
1579 value |= PMC_CNTRL_CPU_PWRREQ_OE;
David Brazdil0f672f62019-12-10 10:32:29 +00001580 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001581}
1582#endif
1583
1584static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
1585{
1586 u32 value, values[2];
1587
1588 if (of_property_read_u32(np, "nvidia,suspend-mode", &value)) {
1589 } else {
1590 switch (value) {
1591 case 0:
1592 pmc->suspend_mode = TEGRA_SUSPEND_LP0;
1593 break;
1594
1595 case 1:
1596 pmc->suspend_mode = TEGRA_SUSPEND_LP1;
1597 break;
1598
1599 case 2:
1600 pmc->suspend_mode = TEGRA_SUSPEND_LP2;
1601 break;
1602
1603 default:
1604 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1605 break;
1606 }
1607 }
1608
1609 pmc->suspend_mode = tegra_pm_validate_suspend_mode(pmc->suspend_mode);
1610
1611 if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &value))
1612 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1613
1614 pmc->cpu_good_time = value;
1615
1616 if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &value))
1617 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1618
1619 pmc->cpu_off_time = value;
1620
1621 if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
1622 values, ARRAY_SIZE(values)))
1623 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1624
1625 pmc->core_osc_time = values[0];
1626 pmc->core_pmu_time = values[1];
1627
1628 if (of_property_read_u32(np, "nvidia,core-pwr-off-time", &value))
1629 pmc->suspend_mode = TEGRA_SUSPEND_NONE;
1630
1631 pmc->core_off_time = value;
1632
1633 pmc->corereq_high = of_property_read_bool(np,
1634 "nvidia,core-power-req-active-high");
1635
1636 pmc->sysclkreq_high = of_property_read_bool(np,
1637 "nvidia,sys-clock-req-active-high");
1638
1639 pmc->combined_req = of_property_read_bool(np,
1640 "nvidia,combined-power-req");
1641
1642 pmc->cpu_pwr_good_en = of_property_read_bool(np,
1643 "nvidia,cpu-pwr-good-en");
1644
1645 if (of_property_read_u32_array(np, "nvidia,lp0-vec", values,
1646 ARRAY_SIZE(values)))
1647 if (pmc->suspend_mode == TEGRA_SUSPEND_LP0)
1648 pmc->suspend_mode = TEGRA_SUSPEND_LP1;
1649
1650 pmc->lp0_vec_phys = values[0];
1651 pmc->lp0_vec_size = values[1];
1652
1653 return 0;
1654}
1655
1656static void tegra_pmc_init(struct tegra_pmc *pmc)
1657{
1658 if (pmc->soc->init)
1659 pmc->soc->init(pmc);
1660}
1661
1662static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
1663{
1664 static const char disabled[] = "emergency thermal reset disabled";
1665 u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
1666 struct device *dev = pmc->dev;
1667 struct device_node *np;
1668 u32 value, checksum;
1669
1670 if (!pmc->soc->has_tsense_reset)
1671 return;
1672
1673 np = of_get_child_by_name(pmc->dev->of_node, "i2c-thermtrip");
1674 if (!np) {
1675 dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
1676 return;
1677 }
1678
1679 if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
1680 dev_err(dev, "I2C controller ID missing, %s.\n", disabled);
1681 goto out;
1682 }
1683
1684 if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) {
1685 dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled);
1686 goto out;
1687 }
1688
1689 if (of_property_read_u32(np, "nvidia,reg-addr", &reg_addr)) {
1690 dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled);
1691 goto out;
1692 }
1693
1694 if (of_property_read_u32(np, "nvidia,reg-data", &reg_data)) {
1695 dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled);
1696 goto out;
1697 }
1698
1699 if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
1700 pinmux = 0;
1701
David Brazdil0f672f62019-12-10 10:32:29 +00001702 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001703 value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
David Brazdil0f672f62019-12-10 10:32:29 +00001704 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001705
1706 value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
1707 (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
David Brazdil0f672f62019-12-10 10:32:29 +00001708 tegra_pmc_writel(pmc, value, PMC_SCRATCH54);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001709
1710 value = PMC_SCRATCH55_RESET_TEGRA;
1711 value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
1712 value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT;
1713 value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT;
1714
1715 /*
1716 * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will
1717 * contain the checksum and are currently zero, so they are not added.
1718 */
1719 checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff)
1720 + ((value >> 24) & 0xff);
1721 checksum &= 0xff;
1722 checksum = 0x100 - checksum;
1723
1724 value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
1725
David Brazdil0f672f62019-12-10 10:32:29 +00001726 tegra_pmc_writel(pmc, value, PMC_SCRATCH55);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001727
David Brazdil0f672f62019-12-10 10:32:29 +00001728 value = tegra_pmc_readl(pmc, PMC_SENSOR_CTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001729 value |= PMC_SENSOR_CTRL_ENABLE_RST;
David Brazdil0f672f62019-12-10 10:32:29 +00001730 tegra_pmc_writel(pmc, value, PMC_SENSOR_CTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001731
1732 dev_info(pmc->dev, "emergency thermal reset enabled\n");
1733
1734out:
1735 of_node_put(np);
1736}
1737
David Brazdil0f672f62019-12-10 10:32:29 +00001738static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev)
1739{
1740 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1741
1742 return pmc->soc->num_io_pads;
1743}
1744
1745static const char *tegra_io_pad_pinctrl_get_group_name(struct pinctrl_dev *pctl,
1746 unsigned int group)
1747{
1748 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl);
1749
1750 return pmc->soc->io_pads[group].name;
1751}
1752
1753static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev,
1754 unsigned int group,
1755 const unsigned int **pins,
1756 unsigned int *num_pins)
1757{
1758 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1759
1760 *pins = &pmc->soc->io_pads[group].id;
1761 *num_pins = 1;
1762
1763 return 0;
1764}
1765
1766static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = {
1767 .get_groups_count = tegra_io_pad_pinctrl_get_groups_count,
1768 .get_group_name = tegra_io_pad_pinctrl_get_group_name,
1769 .get_group_pins = tegra_io_pad_pinctrl_get_group_pins,
1770 .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
1771 .dt_free_map = pinconf_generic_dt_free_map,
1772};
1773
1774static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev,
1775 unsigned int pin, unsigned long *config)
1776{
1777 enum pin_config_param param = pinconf_to_config_param(*config);
1778 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1779 const struct tegra_io_pad_soc *pad;
1780 int ret;
1781 u32 arg;
1782
1783 pad = tegra_io_pad_find(pmc, pin);
1784 if (!pad)
1785 return -EINVAL;
1786
1787 switch (param) {
1788 case PIN_CONFIG_POWER_SOURCE:
1789 ret = tegra_io_pad_get_voltage(pmc, pad->id);
1790 if (ret < 0)
1791 return ret;
1792
1793 arg = ret;
1794 break;
1795
1796 case PIN_CONFIG_LOW_POWER_MODE:
1797 ret = tegra_io_pad_is_powered(pmc, pad->id);
1798 if (ret < 0)
1799 return ret;
1800
1801 arg = !ret;
1802 break;
1803
1804 default:
1805 return -EINVAL;
1806 }
1807
1808 *config = pinconf_to_config_packed(param, arg);
1809
1810 return 0;
1811}
1812
1813static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev,
1814 unsigned int pin, unsigned long *configs,
1815 unsigned int num_configs)
1816{
1817 struct tegra_pmc *pmc = pinctrl_dev_get_drvdata(pctl_dev);
1818 const struct tegra_io_pad_soc *pad;
1819 enum pin_config_param param;
1820 unsigned int i;
1821 int err;
1822 u32 arg;
1823
1824 pad = tegra_io_pad_find(pmc, pin);
1825 if (!pad)
1826 return -EINVAL;
1827
1828 for (i = 0; i < num_configs; ++i) {
1829 param = pinconf_to_config_param(configs[i]);
1830 arg = pinconf_to_config_argument(configs[i]);
1831
1832 switch (param) {
1833 case PIN_CONFIG_LOW_POWER_MODE:
1834 if (arg)
1835 err = tegra_io_pad_power_disable(pad->id);
1836 else
1837 err = tegra_io_pad_power_enable(pad->id);
1838 if (err)
1839 return err;
1840 break;
1841 case PIN_CONFIG_POWER_SOURCE:
1842 if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 &&
1843 arg != TEGRA_IO_PAD_VOLTAGE_3V3)
1844 return -EINVAL;
1845 err = tegra_io_pad_set_voltage(pmc, pad->id, arg);
1846 if (err)
1847 return err;
1848 break;
1849 default:
1850 return -EINVAL;
1851 }
1852 }
1853
1854 return 0;
1855}
1856
1857static const struct pinconf_ops tegra_io_pad_pinconf_ops = {
1858 .pin_config_get = tegra_io_pad_pinconf_get,
1859 .pin_config_set = tegra_io_pad_pinconf_set,
1860 .is_generic = true,
1861};
1862
1863static struct pinctrl_desc tegra_pmc_pctl_desc = {
1864 .pctlops = &tegra_io_pad_pinctrl_ops,
1865 .confops = &tegra_io_pad_pinconf_ops,
1866};
1867
1868static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1869{
1870 int err;
1871
1872 if (!pmc->soc->num_pin_descs)
1873 return 0;
1874
1875 tegra_pmc_pctl_desc.name = dev_name(pmc->dev);
1876 tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs;
1877 tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs;
1878
1879 pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc,
1880 pmc);
1881 if (IS_ERR(pmc->pctl_dev)) {
1882 err = PTR_ERR(pmc->pctl_dev);
1883 dev_err(pmc->dev, "failed to register pin controller: %d\n",
1884 err);
1885 return err;
1886 }
1887
1888 return 0;
1889}
1890
1891static ssize_t reset_reason_show(struct device *dev,
1892 struct device_attribute *attr, char *buf)
1893{
1894 u32 value;
1895
1896 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
1897 value &= pmc->soc->regs->rst_source_mask;
1898 value >>= pmc->soc->regs->rst_source_shift;
1899
1900 if (WARN_ON(value >= pmc->soc->num_reset_sources))
1901 return sprintf(buf, "%s\n", "UNKNOWN");
1902
1903 return sprintf(buf, "%s\n", pmc->soc->reset_sources[value]);
1904}
1905
1906static DEVICE_ATTR_RO(reset_reason);
1907
1908static ssize_t reset_level_show(struct device *dev,
1909 struct device_attribute *attr, char *buf)
1910{
1911 u32 value;
1912
1913 value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
1914 value &= pmc->soc->regs->rst_level_mask;
1915 value >>= pmc->soc->regs->rst_level_shift;
1916
1917 if (WARN_ON(value >= pmc->soc->num_reset_levels))
1918 return sprintf(buf, "%s\n", "UNKNOWN");
1919
1920 return sprintf(buf, "%s\n", pmc->soc->reset_levels[value]);
1921}
1922
1923static DEVICE_ATTR_RO(reset_level);
1924
1925static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
1926{
1927 struct device *dev = pmc->dev;
1928 int err = 0;
1929
1930 if (pmc->soc->reset_sources) {
1931 err = device_create_file(dev, &dev_attr_reset_reason);
1932 if (err < 0)
1933 dev_warn(dev,
1934 "failed to create attr \"reset_reason\": %d\n",
1935 err);
1936 }
1937
1938 if (pmc->soc->reset_levels) {
1939 err = device_create_file(dev, &dev_attr_reset_level);
1940 if (err < 0)
1941 dev_warn(dev,
1942 "failed to create attr \"reset_level\": %d\n",
1943 err);
1944 }
1945}
1946
1947static int tegra_pmc_irq_translate(struct irq_domain *domain,
1948 struct irq_fwspec *fwspec,
1949 unsigned long *hwirq,
1950 unsigned int *type)
1951{
1952 if (WARN_ON(fwspec->param_count < 2))
1953 return -EINVAL;
1954
1955 *hwirq = fwspec->param[0];
1956 *type = fwspec->param[1];
1957
1958 return 0;
1959}
1960
1961static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
1962 unsigned int num_irqs, void *data)
1963{
1964 struct tegra_pmc *pmc = domain->host_data;
1965 const struct tegra_pmc_soc *soc = pmc->soc;
1966 struct irq_fwspec *fwspec = data;
1967 unsigned int i;
1968 int err = 0;
1969
1970 if (WARN_ON(num_irqs > 1))
1971 return -EINVAL;
1972
1973 for (i = 0; i < soc->num_wake_events; i++) {
1974 const struct tegra_wake_event *event = &soc->wake_events[i];
1975
1976 if (fwspec->param_count == 2) {
1977 struct irq_fwspec spec;
1978
1979 if (event->id != fwspec->param[0])
1980 continue;
1981
1982 err = irq_domain_set_hwirq_and_chip(domain, virq,
1983 event->id,
1984 &pmc->irq, pmc);
1985 if (err < 0)
1986 break;
1987
1988 spec.fwnode = &pmc->dev->of_node->fwnode;
1989 spec.param_count = 3;
1990 spec.param[0] = GIC_SPI;
1991 spec.param[1] = event->irq;
1992 spec.param[2] = fwspec->param[1];
1993
1994 err = irq_domain_alloc_irqs_parent(domain, virq,
1995 num_irqs, &spec);
1996
1997 break;
1998 }
1999
2000 if (fwspec->param_count == 3) {
2001 if (event->gpio.instance != fwspec->param[0] ||
2002 event->gpio.pin != fwspec->param[1])
2003 continue;
2004
2005 err = irq_domain_set_hwirq_and_chip(domain, virq,
2006 event->id,
2007 &pmc->irq, pmc);
2008
Olivier Deprez157378f2022-04-04 15:47:50 +02002009 /* GPIO hierarchies stop at the PMC level */
2010 if (!err && domain->parent)
2011 err = irq_domain_disconnect_hierarchy(domain->parent,
2012 virq);
David Brazdil0f672f62019-12-10 10:32:29 +00002013 break;
2014 }
2015 }
2016
Olivier Deprez157378f2022-04-04 15:47:50 +02002017 /* If there is no wake-up event, there is no PMC mapping */
2018 if (i == soc->num_wake_events)
2019 err = irq_domain_disconnect_hierarchy(domain, virq);
Olivier Deprez0e641232021-09-23 10:07:05 +02002020
David Brazdil0f672f62019-12-10 10:32:29 +00002021 return err;
2022}
2023
2024static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
2025 .translate = tegra_pmc_irq_translate,
2026 .alloc = tegra_pmc_irq_alloc,
2027};
2028
Olivier Deprez157378f2022-04-04 15:47:50 +02002029static int tegra210_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
David Brazdil0f672f62019-12-10 10:32:29 +00002030{
2031 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
2032 unsigned int offset, bit;
2033 u32 value;
2034
Olivier Deprez157378f2022-04-04 15:47:50 +02002035 offset = data->hwirq / 32;
2036 bit = data->hwirq % 32;
2037
2038 /* clear wake status */
2039 tegra_pmc_writel(pmc, 0, PMC_SW_WAKE_STATUS);
2040 tegra_pmc_writel(pmc, 0, PMC_SW_WAKE2_STATUS);
2041
2042 tegra_pmc_writel(pmc, 0, PMC_WAKE_STATUS);
2043 tegra_pmc_writel(pmc, 0, PMC_WAKE2_STATUS);
2044
2045 /* enable PMC wake */
2046 if (data->hwirq >= 32)
2047 offset = PMC_WAKE2_MASK;
2048 else
2049 offset = PMC_WAKE_MASK;
2050
2051 value = tegra_pmc_readl(pmc, offset);
2052
2053 if (on)
2054 value |= BIT(bit);
2055 else
2056 value &= ~BIT(bit);
2057
2058 tegra_pmc_writel(pmc, value, offset);
2059
2060 return 0;
2061}
2062
2063static int tegra210_pmc_irq_set_type(struct irq_data *data, unsigned int type)
2064{
2065 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
2066 unsigned int offset, bit;
2067 u32 value;
2068
2069 offset = data->hwirq / 32;
2070 bit = data->hwirq % 32;
2071
2072 if (data->hwirq >= 32)
2073 offset = PMC_WAKE2_LEVEL;
2074 else
2075 offset = PMC_WAKE_LEVEL;
2076
2077 value = tegra_pmc_readl(pmc, offset);
2078
2079 switch (type) {
2080 case IRQ_TYPE_EDGE_RISING:
2081 case IRQ_TYPE_LEVEL_HIGH:
2082 value |= BIT(bit);
2083 break;
2084
2085 case IRQ_TYPE_EDGE_FALLING:
2086 case IRQ_TYPE_LEVEL_LOW:
2087 value &= ~BIT(bit);
2088 break;
2089
2090 case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
2091 value ^= BIT(bit);
2092 break;
2093
2094 default:
2095 return -EINVAL;
2096 }
2097
2098 tegra_pmc_writel(pmc, value, offset);
2099
2100 return 0;
2101}
2102
2103static int tegra186_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
2104{
2105 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
2106 unsigned int offset, bit;
2107 u32 value;
David Brazdil0f672f62019-12-10 10:32:29 +00002108
2109 offset = data->hwirq / 32;
2110 bit = data->hwirq % 32;
2111
2112 /* clear wake status */
2113 writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(data->hwirq));
2114
2115 /* route wake to tier 2 */
2116 value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
2117
2118 if (!on)
2119 value &= ~(1 << bit);
2120 else
2121 value |= 1 << bit;
2122
2123 writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
2124
2125 /* enable wakeup event */
2126 writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(data->hwirq));
2127
2128 return 0;
2129}
2130
Olivier Deprez157378f2022-04-04 15:47:50 +02002131static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type)
David Brazdil0f672f62019-12-10 10:32:29 +00002132{
2133 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
2134 u32 value;
2135
David Brazdil0f672f62019-12-10 10:32:29 +00002136 value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
2137
2138 switch (type) {
2139 case IRQ_TYPE_EDGE_RISING:
2140 case IRQ_TYPE_LEVEL_HIGH:
2141 value |= WAKE_AOWAKE_CNTRL_LEVEL;
2142 break;
2143
2144 case IRQ_TYPE_EDGE_FALLING:
2145 case IRQ_TYPE_LEVEL_LOW:
2146 value &= ~WAKE_AOWAKE_CNTRL_LEVEL;
2147 break;
2148
2149 case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
2150 value ^= WAKE_AOWAKE_CNTRL_LEVEL;
2151 break;
2152
2153 default:
2154 return -EINVAL;
2155 }
2156
2157 writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
2158
2159 return 0;
2160}
2161
Olivier Deprez157378f2022-04-04 15:47:50 +02002162static void tegra_irq_mask_parent(struct irq_data *data)
2163{
2164 if (data->parent_data)
2165 irq_chip_mask_parent(data);
2166}
2167
2168static void tegra_irq_unmask_parent(struct irq_data *data)
2169{
2170 if (data->parent_data)
2171 irq_chip_unmask_parent(data);
2172}
2173
2174static void tegra_irq_eoi_parent(struct irq_data *data)
2175{
2176 if (data->parent_data)
2177 irq_chip_eoi_parent(data);
2178}
2179
2180static int tegra_irq_set_affinity_parent(struct irq_data *data,
2181 const struct cpumask *dest,
2182 bool force)
2183{
2184 if (data->parent_data)
2185 return irq_chip_set_affinity_parent(data, dest, force);
2186
2187 return -EINVAL;
2188}
2189
David Brazdil0f672f62019-12-10 10:32:29 +00002190static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
2191{
2192 struct irq_domain *parent = NULL;
2193 struct device_node *np;
2194
2195 np = of_irq_find_parent(pmc->dev->of_node);
2196 if (np) {
2197 parent = irq_find_host(np);
2198 of_node_put(np);
2199 }
2200
2201 if (!parent)
2202 return 0;
2203
2204 pmc->irq.name = dev_name(pmc->dev);
Olivier Deprez157378f2022-04-04 15:47:50 +02002205 pmc->irq.irq_mask = tegra_irq_mask_parent;
2206 pmc->irq.irq_unmask = tegra_irq_unmask_parent;
2207 pmc->irq.irq_eoi = tegra_irq_eoi_parent;
2208 pmc->irq.irq_set_affinity = tegra_irq_set_affinity_parent;
2209 pmc->irq.irq_set_type = pmc->soc->irq_set_type;
2210 pmc->irq.irq_set_wake = pmc->soc->irq_set_wake;
David Brazdil0f672f62019-12-10 10:32:29 +00002211
2212 pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
2213 &tegra_pmc_irq_domain_ops, pmc);
2214 if (!pmc->domain) {
2215 dev_err(pmc->dev, "failed to allocate domain\n");
2216 return -ENOMEM;
2217 }
2218
2219 return 0;
2220}
2221
Olivier Deprez157378f2022-04-04 15:47:50 +02002222static int tegra_pmc_clk_notify_cb(struct notifier_block *nb,
2223 unsigned long action, void *ptr)
2224{
2225 struct tegra_pmc *pmc = container_of(nb, struct tegra_pmc, clk_nb);
2226 struct clk_notifier_data *data = ptr;
2227
2228 switch (action) {
2229 case PRE_RATE_CHANGE:
2230 mutex_lock(&pmc->powergates_lock);
2231 break;
2232
2233 case POST_RATE_CHANGE:
2234 pmc->rate = data->new_rate;
2235 fallthrough;
2236
2237 case ABORT_RATE_CHANGE:
2238 mutex_unlock(&pmc->powergates_lock);
2239 break;
2240
2241 default:
2242 WARN_ON_ONCE(1);
2243 return notifier_from_errno(-EINVAL);
2244 }
2245
2246 return NOTIFY_OK;
2247}
2248
2249static void pmc_clk_fence_udelay(u32 offset)
2250{
2251 tegra_pmc_readl(pmc, offset);
2252 /* pmc clk propagation delay 2 us */
2253 udelay(2);
2254}
2255
2256static u8 pmc_clk_mux_get_parent(struct clk_hw *hw)
2257{
2258 struct pmc_clk *clk = to_pmc_clk(hw);
2259 u32 val;
2260
2261 val = tegra_pmc_readl(pmc, clk->offs) >> clk->mux_shift;
2262 val &= PMC_CLK_OUT_MUX_MASK;
2263
2264 return val;
2265}
2266
2267static int pmc_clk_mux_set_parent(struct clk_hw *hw, u8 index)
2268{
2269 struct pmc_clk *clk = to_pmc_clk(hw);
2270 u32 val;
2271
2272 val = tegra_pmc_readl(pmc, clk->offs);
2273 val &= ~(PMC_CLK_OUT_MUX_MASK << clk->mux_shift);
2274 val |= index << clk->mux_shift;
2275 tegra_pmc_writel(pmc, val, clk->offs);
2276 pmc_clk_fence_udelay(clk->offs);
2277
2278 return 0;
2279}
2280
2281static int pmc_clk_is_enabled(struct clk_hw *hw)
2282{
2283 struct pmc_clk *clk = to_pmc_clk(hw);
2284 u32 val;
2285
2286 val = tegra_pmc_readl(pmc, clk->offs) & BIT(clk->force_en_shift);
2287
2288 return val ? 1 : 0;
2289}
2290
2291static void pmc_clk_set_state(unsigned long offs, u32 shift, int state)
2292{
2293 u32 val;
2294
2295 val = tegra_pmc_readl(pmc, offs);
2296 val = state ? (val | BIT(shift)) : (val & ~BIT(shift));
2297 tegra_pmc_writel(pmc, val, offs);
2298 pmc_clk_fence_udelay(offs);
2299}
2300
2301static int pmc_clk_enable(struct clk_hw *hw)
2302{
2303 struct pmc_clk *clk = to_pmc_clk(hw);
2304
2305 pmc_clk_set_state(clk->offs, clk->force_en_shift, 1);
2306
2307 return 0;
2308}
2309
2310static void pmc_clk_disable(struct clk_hw *hw)
2311{
2312 struct pmc_clk *clk = to_pmc_clk(hw);
2313
2314 pmc_clk_set_state(clk->offs, clk->force_en_shift, 0);
2315}
2316
2317static const struct clk_ops pmc_clk_ops = {
2318 .get_parent = pmc_clk_mux_get_parent,
2319 .set_parent = pmc_clk_mux_set_parent,
2320 .determine_rate = __clk_mux_determine_rate,
2321 .is_enabled = pmc_clk_is_enabled,
2322 .enable = pmc_clk_enable,
2323 .disable = pmc_clk_disable,
2324};
2325
2326static struct clk *
2327tegra_pmc_clk_out_register(struct tegra_pmc *pmc,
2328 const struct pmc_clk_init_data *data,
2329 unsigned long offset)
2330{
2331 struct clk_init_data init;
2332 struct pmc_clk *pmc_clk;
2333
2334 pmc_clk = devm_kzalloc(pmc->dev, sizeof(*pmc_clk), GFP_KERNEL);
2335 if (!pmc_clk)
2336 return ERR_PTR(-ENOMEM);
2337
2338 init.name = data->name;
2339 init.ops = &pmc_clk_ops;
2340 init.parent_names = data->parents;
2341 init.num_parents = data->num_parents;
2342 init.flags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT |
2343 CLK_SET_PARENT_GATE;
2344
2345 pmc_clk->hw.init = &init;
2346 pmc_clk->offs = offset;
2347 pmc_clk->mux_shift = data->mux_shift;
2348 pmc_clk->force_en_shift = data->force_en_shift;
2349
2350 return clk_register(NULL, &pmc_clk->hw);
2351}
2352
2353static int pmc_clk_gate_is_enabled(struct clk_hw *hw)
2354{
2355 struct pmc_clk_gate *gate = to_pmc_clk_gate(hw);
2356
2357 return tegra_pmc_readl(pmc, gate->offs) & BIT(gate->shift) ? 1 : 0;
2358}
2359
2360static int pmc_clk_gate_enable(struct clk_hw *hw)
2361{
2362 struct pmc_clk_gate *gate = to_pmc_clk_gate(hw);
2363
2364 pmc_clk_set_state(gate->offs, gate->shift, 1);
2365
2366 return 0;
2367}
2368
2369static void pmc_clk_gate_disable(struct clk_hw *hw)
2370{
2371 struct pmc_clk_gate *gate = to_pmc_clk_gate(hw);
2372
2373 pmc_clk_set_state(gate->offs, gate->shift, 0);
2374}
2375
2376static const struct clk_ops pmc_clk_gate_ops = {
2377 .is_enabled = pmc_clk_gate_is_enabled,
2378 .enable = pmc_clk_gate_enable,
2379 .disable = pmc_clk_gate_disable,
2380};
2381
2382static struct clk *
2383tegra_pmc_clk_gate_register(struct tegra_pmc *pmc, const char *name,
2384 const char *parent_name, unsigned long offset,
2385 u32 shift)
2386{
2387 struct clk_init_data init;
2388 struct pmc_clk_gate *gate;
2389
2390 gate = devm_kzalloc(pmc->dev, sizeof(*gate), GFP_KERNEL);
2391 if (!gate)
2392 return ERR_PTR(-ENOMEM);
2393
2394 init.name = name;
2395 init.ops = &pmc_clk_gate_ops;
2396 init.parent_names = &parent_name;
2397 init.num_parents = 1;
2398 init.flags = 0;
2399
2400 gate->hw.init = &init;
2401 gate->offs = offset;
2402 gate->shift = shift;
2403
2404 return clk_register(NULL, &gate->hw);
2405}
2406
2407static void tegra_pmc_clock_register(struct tegra_pmc *pmc,
2408 struct device_node *np)
2409{
2410 struct clk *clk;
2411 struct clk_onecell_data *clk_data;
2412 unsigned int num_clks;
2413 int i, err;
2414
2415 num_clks = pmc->soc->num_pmc_clks;
2416 if (pmc->soc->has_blink_output)
2417 num_clks += 1;
2418
2419 if (!num_clks)
2420 return;
2421
2422 clk_data = devm_kmalloc(pmc->dev, sizeof(*clk_data), GFP_KERNEL);
2423 if (!clk_data)
2424 return;
2425
2426 clk_data->clks = devm_kcalloc(pmc->dev, TEGRA_PMC_CLK_MAX,
2427 sizeof(*clk_data->clks), GFP_KERNEL);
2428 if (!clk_data->clks)
2429 return;
2430
2431 clk_data->clk_num = TEGRA_PMC_CLK_MAX;
2432
2433 for (i = 0; i < TEGRA_PMC_CLK_MAX; i++)
2434 clk_data->clks[i] = ERR_PTR(-ENOENT);
2435
2436 for (i = 0; i < pmc->soc->num_pmc_clks; i++) {
2437 const struct pmc_clk_init_data *data;
2438
2439 data = pmc->soc->pmc_clks_data + i;
2440
2441 clk = tegra_pmc_clk_out_register(pmc, data, PMC_CLK_OUT_CNTRL);
2442 if (IS_ERR(clk)) {
2443 dev_warn(pmc->dev, "unable to register clock %s: %d\n",
2444 data->name, PTR_ERR_OR_ZERO(clk));
2445 return;
2446 }
2447
2448 err = clk_register_clkdev(clk, data->name, NULL);
2449 if (err) {
2450 dev_warn(pmc->dev,
2451 "unable to register %s clock lookup: %d\n",
2452 data->name, err);
2453 return;
2454 }
2455
2456 clk_data->clks[data->clk_id] = clk;
2457 }
2458
2459 if (pmc->soc->has_blink_output) {
2460 tegra_pmc_writel(pmc, 0x0, PMC_BLINK_TIMER);
2461 clk = tegra_pmc_clk_gate_register(pmc,
2462 "pmc_blink_override",
2463 "clk_32k",
2464 PMC_DPD_PADS_ORIDE,
2465 PMC_DPD_PADS_ORIDE_BLINK);
2466 if (IS_ERR(clk)) {
2467 dev_warn(pmc->dev,
2468 "unable to register pmc_blink_override: %d\n",
2469 PTR_ERR_OR_ZERO(clk));
2470 return;
2471 }
2472
2473 clk = tegra_pmc_clk_gate_register(pmc, "pmc_blink",
2474 "pmc_blink_override",
2475 PMC_CNTRL,
2476 PMC_CNTRL_BLINK_EN);
2477 if (IS_ERR(clk)) {
2478 dev_warn(pmc->dev,
2479 "unable to register pmc_blink: %d\n",
2480 PTR_ERR_OR_ZERO(clk));
2481 return;
2482 }
2483
2484 err = clk_register_clkdev(clk, "pmc_blink", NULL);
2485 if (err) {
2486 dev_warn(pmc->dev,
2487 "unable to register pmc_blink lookup: %d\n",
2488 err);
2489 return;
2490 }
2491
2492 clk_data->clks[TEGRA_PMC_CLK_BLINK] = clk;
2493 }
2494
2495 err = of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
2496 if (err)
2497 dev_warn(pmc->dev, "failed to add pmc clock provider: %d\n",
2498 err);
2499}
2500
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002501static int tegra_pmc_probe(struct platform_device *pdev)
2502{
2503 void __iomem *base;
2504 struct resource *res;
2505 int err;
2506
2507 /*
2508 * Early initialisation should have configured an initial
2509 * register mapping and setup the soc data pointer. If these
2510 * are not valid then something went badly wrong!
2511 */
2512 if (WARN_ON(!pmc->base || !pmc->soc))
2513 return -ENODEV;
2514
2515 err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
2516 if (err < 0)
2517 return err;
2518
2519 /* take over the memory region from the early initialization */
2520 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2521 base = devm_ioremap_resource(&pdev->dev, res);
2522 if (IS_ERR(base))
2523 return PTR_ERR(base);
2524
2525 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
2526 if (res) {
2527 pmc->wake = devm_ioremap_resource(&pdev->dev, res);
2528 if (IS_ERR(pmc->wake))
2529 return PTR_ERR(pmc->wake);
2530 } else {
2531 pmc->wake = base;
2532 }
2533
2534 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
2535 if (res) {
2536 pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
2537 if (IS_ERR(pmc->aotag))
2538 return PTR_ERR(pmc->aotag);
2539 } else {
2540 pmc->aotag = base;
2541 }
2542
2543 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
2544 if (res) {
2545 pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
2546 if (IS_ERR(pmc->scratch))
2547 return PTR_ERR(pmc->scratch);
2548 } else {
2549 pmc->scratch = base;
2550 }
2551
2552 pmc->clk = devm_clk_get(&pdev->dev, "pclk");
2553 if (IS_ERR(pmc->clk)) {
2554 err = PTR_ERR(pmc->clk);
2555
2556 if (err != -ENOENT) {
2557 dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
2558 return err;
2559 }
2560
2561 pmc->clk = NULL;
2562 }
2563
Olivier Deprez157378f2022-04-04 15:47:50 +02002564 /*
2565 * PCLK clock rate can't be retrieved using CLK API because it
2566 * causes lockup if CPU enters LP2 idle state from some other
2567 * CLK notifier, hence we're caching the rate's value locally.
2568 */
2569 if (pmc->clk) {
2570 pmc->clk_nb.notifier_call = tegra_pmc_clk_notify_cb;
2571 err = clk_notifier_register(pmc->clk, &pmc->clk_nb);
2572 if (err) {
2573 dev_err(&pdev->dev,
2574 "failed to register clk notifier\n");
2575 return err;
2576 }
2577
2578 pmc->rate = clk_get_rate(pmc->clk);
2579 }
2580
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002581 pmc->dev = &pdev->dev;
2582
2583 tegra_pmc_init(pmc);
2584
2585 tegra_pmc_init_tsense_reset(pmc);
2586
David Brazdil0f672f62019-12-10 10:32:29 +00002587 tegra_pmc_reset_sysfs_init(pmc);
2588
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002589 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
2590 err = tegra_powergate_debugfs_init();
2591 if (err < 0)
David Brazdil0f672f62019-12-10 10:32:29 +00002592 goto cleanup_sysfs;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002593 }
2594
2595 err = register_restart_handler(&tegra_pmc_restart_handler);
2596 if (err) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002597 dev_err(&pdev->dev, "unable to register restart handler, %d\n",
2598 err);
David Brazdil0f672f62019-12-10 10:32:29 +00002599 goto cleanup_debugfs;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002600 }
2601
David Brazdil0f672f62019-12-10 10:32:29 +00002602 err = tegra_pmc_pinctrl_init(pmc);
2603 if (err)
2604 goto cleanup_restart_handler;
2605
2606 err = tegra_powergate_init(pmc, pdev->dev.of_node);
2607 if (err < 0)
2608 goto cleanup_powergates;
2609
2610 err = tegra_pmc_irq_init(pmc);
2611 if (err < 0)
2612 goto cleanup_powergates;
2613
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002614 mutex_lock(&pmc->powergates_lock);
2615 iounmap(pmc->base);
2616 pmc->base = base;
2617 mutex_unlock(&pmc->powergates_lock);
2618
Olivier Deprez157378f2022-04-04 15:47:50 +02002619 tegra_pmc_clock_register(pmc, pdev->dev.of_node);
David Brazdil0f672f62019-12-10 10:32:29 +00002620 platform_set_drvdata(pdev, pmc);
2621
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002622 return 0;
David Brazdil0f672f62019-12-10 10:32:29 +00002623
2624cleanup_powergates:
2625 tegra_powergate_remove_all(pdev->dev.of_node);
2626cleanup_restart_handler:
2627 unregister_restart_handler(&tegra_pmc_restart_handler);
2628cleanup_debugfs:
2629 debugfs_remove(pmc->debugfs);
2630cleanup_sysfs:
2631 device_remove_file(&pdev->dev, &dev_attr_reset_reason);
2632 device_remove_file(&pdev->dev, &dev_attr_reset_level);
Olivier Deprez157378f2022-04-04 15:47:50 +02002633 clk_notifier_unregister(pmc->clk, &pmc->clk_nb);
2634
David Brazdil0f672f62019-12-10 10:32:29 +00002635 return err;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002636}
2637
2638#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
2639static int tegra_pmc_suspend(struct device *dev)
2640{
David Brazdil0f672f62019-12-10 10:32:29 +00002641 struct tegra_pmc *pmc = dev_get_drvdata(dev);
2642
2643 tegra_pmc_writel(pmc, virt_to_phys(tegra_resume), PMC_SCRATCH41);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002644
2645 return 0;
2646}
2647
2648static int tegra_pmc_resume(struct device *dev)
2649{
David Brazdil0f672f62019-12-10 10:32:29 +00002650 struct tegra_pmc *pmc = dev_get_drvdata(dev);
2651
2652 tegra_pmc_writel(pmc, 0x0, PMC_SCRATCH41);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002653
2654 return 0;
2655}
2656
2657static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
2658
2659#endif
2660
2661static const char * const tegra20_powergates[] = {
2662 [TEGRA_POWERGATE_CPU] = "cpu",
2663 [TEGRA_POWERGATE_3D] = "3d",
2664 [TEGRA_POWERGATE_VENC] = "venc",
2665 [TEGRA_POWERGATE_VDEC] = "vdec",
2666 [TEGRA_POWERGATE_PCIE] = "pcie",
2667 [TEGRA_POWERGATE_L2] = "l2",
2668 [TEGRA_POWERGATE_MPE] = "mpe",
2669};
2670
2671static const struct tegra_pmc_regs tegra20_pmc_regs = {
2672 .scratch0 = 0x50,
2673 .dpd_req = 0x1b8,
2674 .dpd_status = 0x1bc,
2675 .dpd2_req = 0x1c0,
2676 .dpd2_status = 0x1c4,
David Brazdil0f672f62019-12-10 10:32:29 +00002677 .rst_status = 0x1b4,
2678 .rst_source_shift = 0x0,
2679 .rst_source_mask = 0x7,
2680 .rst_level_shift = 0x0,
2681 .rst_level_mask = 0x0,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002682};
2683
2684static void tegra20_pmc_init(struct tegra_pmc *pmc)
2685{
Olivier Deprez157378f2022-04-04 15:47:50 +02002686 u32 value, osc, pmu, off;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002687
2688 /* Always enable CPU power request */
David Brazdil0f672f62019-12-10 10:32:29 +00002689 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002690 value |= PMC_CNTRL_CPU_PWRREQ_OE;
David Brazdil0f672f62019-12-10 10:32:29 +00002691 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002692
David Brazdil0f672f62019-12-10 10:32:29 +00002693 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002694
2695 if (pmc->sysclkreq_high)
2696 value &= ~PMC_CNTRL_SYSCLK_POLARITY;
2697 else
2698 value |= PMC_CNTRL_SYSCLK_POLARITY;
2699
Olivier Deprez157378f2022-04-04 15:47:50 +02002700 if (pmc->corereq_high)
2701 value &= ~PMC_CNTRL_PWRREQ_POLARITY;
2702 else
2703 value |= PMC_CNTRL_PWRREQ_POLARITY;
2704
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002705 /* configure the output polarity while the request is tristated */
David Brazdil0f672f62019-12-10 10:32:29 +00002706 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002707
2708 /* now enable the request */
David Brazdil0f672f62019-12-10 10:32:29 +00002709 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002710 value |= PMC_CNTRL_SYSCLK_OE;
David Brazdil0f672f62019-12-10 10:32:29 +00002711 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Olivier Deprez157378f2022-04-04 15:47:50 +02002712
2713 /* program core timings which are applicable only for suspend state */
2714 if (pmc->suspend_mode != TEGRA_SUSPEND_NONE) {
2715 osc = DIV_ROUND_UP(pmc->core_osc_time * 8192, 1000000);
2716 pmu = DIV_ROUND_UP(pmc->core_pmu_time * 32768, 1000000);
2717 off = DIV_ROUND_UP(pmc->core_off_time * 32768, 1000000);
2718 tegra_pmc_writel(pmc, ((osc << 8) & 0xff00) | (pmu & 0xff),
2719 PMC_COREPWRGOOD_TIMER);
2720 tegra_pmc_writel(pmc, off, PMC_COREPWROFF_TIMER);
2721 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002722}
2723
2724static void tegra20_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2725 struct device_node *np,
2726 bool invert)
2727{
2728 u32 value;
2729
David Brazdil0f672f62019-12-10 10:32:29 +00002730 value = tegra_pmc_readl(pmc, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002731
2732 if (invert)
2733 value |= PMC_CNTRL_INTR_POLARITY;
2734 else
2735 value &= ~PMC_CNTRL_INTR_POLARITY;
2736
David Brazdil0f672f62019-12-10 10:32:29 +00002737 tegra_pmc_writel(pmc, value, PMC_CNTRL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002738}
2739
2740static const struct tegra_pmc_soc tegra20_pmc_soc = {
2741 .num_powergates = ARRAY_SIZE(tegra20_powergates),
2742 .powergates = tegra20_powergates,
2743 .num_cpu_powergates = 0,
2744 .cpu_powergates = NULL,
2745 .has_tsense_reset = false,
2746 .has_gpu_clamps = false,
David Brazdil0f672f62019-12-10 10:32:29 +00002747 .needs_mbist_war = false,
2748 .has_impl_33v_pwr = false,
2749 .maybe_tz_only = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002750 .num_io_pads = 0,
2751 .io_pads = NULL,
David Brazdil0f672f62019-12-10 10:32:29 +00002752 .num_pin_descs = 0,
2753 .pin_descs = NULL,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002754 .regs = &tegra20_pmc_regs,
2755 .init = tegra20_pmc_init,
2756 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02002757 .powergate_set = tegra20_powergate_set,
David Brazdil0f672f62019-12-10 10:32:29 +00002758 .reset_sources = NULL,
2759 .num_reset_sources = 0,
2760 .reset_levels = NULL,
2761 .num_reset_levels = 0,
Olivier Deprez157378f2022-04-04 15:47:50 +02002762 .pmc_clks_data = NULL,
2763 .num_pmc_clks = 0,
2764 .has_blink_output = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002765};
2766
2767static const char * const tegra30_powergates[] = {
2768 [TEGRA_POWERGATE_CPU] = "cpu0",
2769 [TEGRA_POWERGATE_3D] = "3d0",
2770 [TEGRA_POWERGATE_VENC] = "venc",
2771 [TEGRA_POWERGATE_VDEC] = "vdec",
2772 [TEGRA_POWERGATE_PCIE] = "pcie",
2773 [TEGRA_POWERGATE_L2] = "l2",
2774 [TEGRA_POWERGATE_MPE] = "mpe",
2775 [TEGRA_POWERGATE_HEG] = "heg",
2776 [TEGRA_POWERGATE_SATA] = "sata",
2777 [TEGRA_POWERGATE_CPU1] = "cpu1",
2778 [TEGRA_POWERGATE_CPU2] = "cpu2",
2779 [TEGRA_POWERGATE_CPU3] = "cpu3",
2780 [TEGRA_POWERGATE_CELP] = "celp",
2781 [TEGRA_POWERGATE_3D1] = "3d1",
2782};
2783
2784static const u8 tegra30_cpu_powergates[] = {
2785 TEGRA_POWERGATE_CPU,
2786 TEGRA_POWERGATE_CPU1,
2787 TEGRA_POWERGATE_CPU2,
2788 TEGRA_POWERGATE_CPU3,
2789};
2790
Olivier Deprez157378f2022-04-04 15:47:50 +02002791static const char * const tegra30_reset_sources[] = {
2792 "POWER_ON_RESET",
2793 "WATCHDOG",
2794 "SENSOR",
2795 "SW_MAIN",
2796 "LP0"
2797};
2798
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002799static const struct tegra_pmc_soc tegra30_pmc_soc = {
2800 .num_powergates = ARRAY_SIZE(tegra30_powergates),
2801 .powergates = tegra30_powergates,
2802 .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
2803 .cpu_powergates = tegra30_cpu_powergates,
2804 .has_tsense_reset = true,
2805 .has_gpu_clamps = false,
David Brazdil0f672f62019-12-10 10:32:29 +00002806 .needs_mbist_war = false,
2807 .has_impl_33v_pwr = false,
2808 .maybe_tz_only = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002809 .num_io_pads = 0,
2810 .io_pads = NULL,
David Brazdil0f672f62019-12-10 10:32:29 +00002811 .num_pin_descs = 0,
2812 .pin_descs = NULL,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002813 .regs = &tegra20_pmc_regs,
2814 .init = tegra20_pmc_init,
2815 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02002816 .powergate_set = tegra20_powergate_set,
David Brazdil0f672f62019-12-10 10:32:29 +00002817 .reset_sources = tegra30_reset_sources,
2818 .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
2819 .reset_levels = NULL,
2820 .num_reset_levels = 0,
Olivier Deprez157378f2022-04-04 15:47:50 +02002821 .pmc_clks_data = tegra_pmc_clks_data,
2822 .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
2823 .has_blink_output = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002824};
2825
2826static const char * const tegra114_powergates[] = {
2827 [TEGRA_POWERGATE_CPU] = "crail",
2828 [TEGRA_POWERGATE_3D] = "3d",
2829 [TEGRA_POWERGATE_VENC] = "venc",
2830 [TEGRA_POWERGATE_VDEC] = "vdec",
2831 [TEGRA_POWERGATE_MPE] = "mpe",
2832 [TEGRA_POWERGATE_HEG] = "heg",
2833 [TEGRA_POWERGATE_CPU1] = "cpu1",
2834 [TEGRA_POWERGATE_CPU2] = "cpu2",
2835 [TEGRA_POWERGATE_CPU3] = "cpu3",
2836 [TEGRA_POWERGATE_CELP] = "celp",
2837 [TEGRA_POWERGATE_CPU0] = "cpu0",
2838 [TEGRA_POWERGATE_C0NC] = "c0nc",
2839 [TEGRA_POWERGATE_C1NC] = "c1nc",
2840 [TEGRA_POWERGATE_DIS] = "dis",
2841 [TEGRA_POWERGATE_DISB] = "disb",
2842 [TEGRA_POWERGATE_XUSBA] = "xusba",
2843 [TEGRA_POWERGATE_XUSBB] = "xusbb",
2844 [TEGRA_POWERGATE_XUSBC] = "xusbc",
2845};
2846
2847static const u8 tegra114_cpu_powergates[] = {
2848 TEGRA_POWERGATE_CPU0,
2849 TEGRA_POWERGATE_CPU1,
2850 TEGRA_POWERGATE_CPU2,
2851 TEGRA_POWERGATE_CPU3,
2852};
2853
2854static const struct tegra_pmc_soc tegra114_pmc_soc = {
2855 .num_powergates = ARRAY_SIZE(tegra114_powergates),
2856 .powergates = tegra114_powergates,
2857 .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
2858 .cpu_powergates = tegra114_cpu_powergates,
2859 .has_tsense_reset = true,
2860 .has_gpu_clamps = false,
David Brazdil0f672f62019-12-10 10:32:29 +00002861 .needs_mbist_war = false,
2862 .has_impl_33v_pwr = false,
2863 .maybe_tz_only = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002864 .num_io_pads = 0,
2865 .io_pads = NULL,
David Brazdil0f672f62019-12-10 10:32:29 +00002866 .num_pin_descs = 0,
2867 .pin_descs = NULL,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002868 .regs = &tegra20_pmc_regs,
2869 .init = tegra20_pmc_init,
2870 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02002871 .powergate_set = tegra114_powergate_set,
David Brazdil0f672f62019-12-10 10:32:29 +00002872 .reset_sources = tegra30_reset_sources,
2873 .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
2874 .reset_levels = NULL,
2875 .num_reset_levels = 0,
Olivier Deprez157378f2022-04-04 15:47:50 +02002876 .pmc_clks_data = tegra_pmc_clks_data,
2877 .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
2878 .has_blink_output = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002879};
2880
2881static const char * const tegra124_powergates[] = {
2882 [TEGRA_POWERGATE_CPU] = "crail",
2883 [TEGRA_POWERGATE_3D] = "3d",
2884 [TEGRA_POWERGATE_VENC] = "venc",
2885 [TEGRA_POWERGATE_PCIE] = "pcie",
2886 [TEGRA_POWERGATE_VDEC] = "vdec",
2887 [TEGRA_POWERGATE_MPE] = "mpe",
2888 [TEGRA_POWERGATE_HEG] = "heg",
2889 [TEGRA_POWERGATE_SATA] = "sata",
2890 [TEGRA_POWERGATE_CPU1] = "cpu1",
2891 [TEGRA_POWERGATE_CPU2] = "cpu2",
2892 [TEGRA_POWERGATE_CPU3] = "cpu3",
2893 [TEGRA_POWERGATE_CELP] = "celp",
2894 [TEGRA_POWERGATE_CPU0] = "cpu0",
2895 [TEGRA_POWERGATE_C0NC] = "c0nc",
2896 [TEGRA_POWERGATE_C1NC] = "c1nc",
2897 [TEGRA_POWERGATE_SOR] = "sor",
2898 [TEGRA_POWERGATE_DIS] = "dis",
2899 [TEGRA_POWERGATE_DISB] = "disb",
2900 [TEGRA_POWERGATE_XUSBA] = "xusba",
2901 [TEGRA_POWERGATE_XUSBB] = "xusbb",
2902 [TEGRA_POWERGATE_XUSBC] = "xusbc",
2903 [TEGRA_POWERGATE_VIC] = "vic",
2904 [TEGRA_POWERGATE_IRAM] = "iram",
2905};
2906
2907static const u8 tegra124_cpu_powergates[] = {
2908 TEGRA_POWERGATE_CPU0,
2909 TEGRA_POWERGATE_CPU1,
2910 TEGRA_POWERGATE_CPU2,
2911 TEGRA_POWERGATE_CPU3,
2912};
2913
David Brazdil0f672f62019-12-10 10:32:29 +00002914#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \
2915 ((struct tegra_io_pad_soc) { \
2916 .id = (_id), \
2917 .dpd = (_dpd), \
2918 .voltage = (_voltage), \
2919 .name = (_name), \
2920 })
2921
2922#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \
2923 ((struct pinctrl_pin_desc) { \
2924 .number = (_id), \
2925 .name = (_name) \
2926 })
2927
Olivier Deprez157378f2022-04-04 15:47:50 +02002928#define TEGRA124_IO_PAD_TABLE(_pad) \
2929 /* .id .dpd .voltage .name */ \
2930 _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
2931 _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \
2932 _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \
2933 _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \
2934 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
2935 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \
2936 _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \
2937 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
2938 _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
2939 _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
2940 _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
2941 _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
2942 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
2943 _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \
2944 _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
2945 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
2946 _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \
2947 _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
2948 _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
2949 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
2950 _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
2951 _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \
2952 _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \
2953 _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \
2954 _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \
2955 _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
2956 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
2957 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
2958 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
2959 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias")
David Brazdil0f672f62019-12-10 10:32:29 +00002960
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002961static const struct tegra_io_pad_soc tegra124_io_pads[] = {
David Brazdil0f672f62019-12-10 10:32:29 +00002962 TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD)
2963};
2964
2965static const struct pinctrl_pin_desc tegra124_pin_descs[] = {
2966 TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002967};
2968
2969static const struct tegra_pmc_soc tegra124_pmc_soc = {
2970 .num_powergates = ARRAY_SIZE(tegra124_powergates),
2971 .powergates = tegra124_powergates,
2972 .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
2973 .cpu_powergates = tegra124_cpu_powergates,
2974 .has_tsense_reset = true,
2975 .has_gpu_clamps = true,
David Brazdil0f672f62019-12-10 10:32:29 +00002976 .needs_mbist_war = false,
2977 .has_impl_33v_pwr = false,
2978 .maybe_tz_only = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002979 .num_io_pads = ARRAY_SIZE(tegra124_io_pads),
2980 .io_pads = tegra124_io_pads,
David Brazdil0f672f62019-12-10 10:32:29 +00002981 .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs),
2982 .pin_descs = tegra124_pin_descs,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002983 .regs = &tegra20_pmc_regs,
2984 .init = tegra20_pmc_init,
2985 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02002986 .powergate_set = tegra114_powergate_set,
David Brazdil0f672f62019-12-10 10:32:29 +00002987 .reset_sources = tegra30_reset_sources,
2988 .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
2989 .reset_levels = NULL,
2990 .num_reset_levels = 0,
Olivier Deprez157378f2022-04-04 15:47:50 +02002991 .pmc_clks_data = tegra_pmc_clks_data,
2992 .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
2993 .has_blink_output = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002994};
2995
2996static const char * const tegra210_powergates[] = {
2997 [TEGRA_POWERGATE_CPU] = "crail",
2998 [TEGRA_POWERGATE_3D] = "3d",
2999 [TEGRA_POWERGATE_VENC] = "venc",
3000 [TEGRA_POWERGATE_PCIE] = "pcie",
3001 [TEGRA_POWERGATE_MPE] = "mpe",
3002 [TEGRA_POWERGATE_SATA] = "sata",
3003 [TEGRA_POWERGATE_CPU1] = "cpu1",
3004 [TEGRA_POWERGATE_CPU2] = "cpu2",
3005 [TEGRA_POWERGATE_CPU3] = "cpu3",
3006 [TEGRA_POWERGATE_CPU0] = "cpu0",
3007 [TEGRA_POWERGATE_C0NC] = "c0nc",
3008 [TEGRA_POWERGATE_SOR] = "sor",
3009 [TEGRA_POWERGATE_DIS] = "dis",
3010 [TEGRA_POWERGATE_DISB] = "disb",
3011 [TEGRA_POWERGATE_XUSBA] = "xusba",
3012 [TEGRA_POWERGATE_XUSBB] = "xusbb",
3013 [TEGRA_POWERGATE_XUSBC] = "xusbc",
3014 [TEGRA_POWERGATE_VIC] = "vic",
3015 [TEGRA_POWERGATE_IRAM] = "iram",
3016 [TEGRA_POWERGATE_NVDEC] = "nvdec",
3017 [TEGRA_POWERGATE_NVJPG] = "nvjpg",
3018 [TEGRA_POWERGATE_AUD] = "aud",
3019 [TEGRA_POWERGATE_DFD] = "dfd",
3020 [TEGRA_POWERGATE_VE2] = "ve2",
3021};
3022
3023static const u8 tegra210_cpu_powergates[] = {
3024 TEGRA_POWERGATE_CPU0,
3025 TEGRA_POWERGATE_CPU1,
3026 TEGRA_POWERGATE_CPU2,
3027 TEGRA_POWERGATE_CPU3,
3028};
3029
Olivier Deprez157378f2022-04-04 15:47:50 +02003030#define TEGRA210_IO_PAD_TABLE(_pad) \
3031 /* .id .dpd .voltage .name */ \
3032 _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \
3033 _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \
3034 _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \
3035 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
3036 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
3037 _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \
3038 _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \
3039 _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \
3040 _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \
3041 _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \
3042 _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \
3043 _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \
3044 _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \
3045 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
3046 _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \
3047 _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \
3048 _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \
3049 _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \
3050 _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \
3051 _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \
3052 _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \
3053 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
3054 _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \
3055 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
3056 _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \
3057 _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \
3058 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
3059 _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \
3060 _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \
3061 _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \
3062 _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \
3063 _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \
3064 _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \
3065 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
3066 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
3067 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
3068 _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \
3069 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias")
David Brazdil0f672f62019-12-10 10:32:29 +00003070
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003071static const struct tegra_io_pad_soc tegra210_io_pads[] = {
David Brazdil0f672f62019-12-10 10:32:29 +00003072 TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD)
3073};
3074
3075static const struct pinctrl_pin_desc tegra210_pin_descs[] = {
3076 TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003077};
3078
Olivier Deprez157378f2022-04-04 15:47:50 +02003079static const char * const tegra210_reset_sources[] = {
3080 "POWER_ON_RESET",
3081 "WATCHDOG",
3082 "SENSOR",
3083 "SW_MAIN",
3084 "LP0",
3085 "AOTAG"
3086};
3087
3088static const struct tegra_wake_event tegra210_wake_events[] = {
3089 TEGRA_WAKE_IRQ("rtc", 16, 2),
3090 TEGRA_WAKE_IRQ("pmu", 51, 86),
3091};
3092
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003093static const struct tegra_pmc_soc tegra210_pmc_soc = {
3094 .num_powergates = ARRAY_SIZE(tegra210_powergates),
3095 .powergates = tegra210_powergates,
3096 .num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates),
3097 .cpu_powergates = tegra210_cpu_powergates,
3098 .has_tsense_reset = true,
3099 .has_gpu_clamps = true,
3100 .needs_mbist_war = true,
David Brazdil0f672f62019-12-10 10:32:29 +00003101 .has_impl_33v_pwr = false,
3102 .maybe_tz_only = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003103 .num_io_pads = ARRAY_SIZE(tegra210_io_pads),
3104 .io_pads = tegra210_io_pads,
David Brazdil0f672f62019-12-10 10:32:29 +00003105 .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs),
3106 .pin_descs = tegra210_pin_descs,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003107 .regs = &tegra20_pmc_regs,
3108 .init = tegra20_pmc_init,
3109 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02003110 .powergate_set = tegra114_powergate_set,
3111 .irq_set_wake = tegra210_pmc_irq_set_wake,
3112 .irq_set_type = tegra210_pmc_irq_set_type,
David Brazdil0f672f62019-12-10 10:32:29 +00003113 .reset_sources = tegra210_reset_sources,
3114 .num_reset_sources = ARRAY_SIZE(tegra210_reset_sources),
3115 .reset_levels = NULL,
3116 .num_reset_levels = 0,
Olivier Deprez157378f2022-04-04 15:47:50 +02003117 .num_wake_events = ARRAY_SIZE(tegra210_wake_events),
3118 .wake_events = tegra210_wake_events,
3119 .pmc_clks_data = tegra_pmc_clks_data,
3120 .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data),
3121 .has_blink_output = true,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003122};
3123
Olivier Deprez157378f2022-04-04 15:47:50 +02003124#define TEGRA186_IO_PAD_TABLE(_pad) \
3125 /* .id .dpd .voltage .name */ \
3126 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
3127 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
3128 _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \
3129 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
3130 _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \
3131 _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \
3132 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
3133 _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \
3134 _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \
3135 _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \
3136 _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \
3137 _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \
3138 _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
3139 _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
3140 _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \
3141 _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \
3142 _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \
3143 _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \
3144 _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
3145 _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \
3146 _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \
3147 _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \
3148 _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \
3149 _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \
3150 _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \
3151 _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \
3152 _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \
3153 _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \
3154 _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \
3155 _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \
3156 _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \
3157 _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \
3158 _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \
3159 _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \
3160 _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \
3161 _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \
3162 _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \
3163 _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv")
David Brazdil0f672f62019-12-10 10:32:29 +00003164
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003165static const struct tegra_io_pad_soc tegra186_io_pads[] = {
David Brazdil0f672f62019-12-10 10:32:29 +00003166 TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD)
3167};
3168
3169static const struct pinctrl_pin_desc tegra186_pin_descs[] = {
3170 TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003171};
3172
3173static const struct tegra_pmc_regs tegra186_pmc_regs = {
3174 .scratch0 = 0x2000,
3175 .dpd_req = 0x74,
3176 .dpd_status = 0x78,
3177 .dpd2_req = 0x7c,
3178 .dpd2_status = 0x80,
David Brazdil0f672f62019-12-10 10:32:29 +00003179 .rst_status = 0x70,
3180 .rst_source_shift = 0x2,
Olivier Deprez157378f2022-04-04 15:47:50 +02003181 .rst_source_mask = 0x3c,
David Brazdil0f672f62019-12-10 10:32:29 +00003182 .rst_level_shift = 0x0,
3183 .rst_level_mask = 0x3,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003184};
3185
3186static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
3187 struct device_node *np,
3188 bool invert)
3189{
3190 struct resource regs;
3191 void __iomem *wake;
3192 u32 value;
3193 int index;
3194
3195 index = of_property_match_string(np, "reg-names", "wake");
3196 if (index < 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00003197 dev_err(pmc->dev, "failed to find PMC wake registers\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003198 return;
3199 }
3200
3201 of_address_to_resource(np, index, &regs);
3202
Olivier Deprez157378f2022-04-04 15:47:50 +02003203 wake = ioremap(regs.start, resource_size(&regs));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003204 if (!wake) {
David Brazdil0f672f62019-12-10 10:32:29 +00003205 dev_err(pmc->dev, "failed to map PMC wake registers\n");
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003206 return;
3207 }
3208
3209 value = readl(wake + WAKE_AOWAKE_CTRL);
3210
3211 if (invert)
3212 value |= WAKE_AOWAKE_CTRL_INTR_POLARITY;
3213 else
3214 value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY;
3215
3216 writel(value, wake + WAKE_AOWAKE_CTRL);
3217
3218 iounmap(wake);
3219}
3220
Olivier Deprez157378f2022-04-04 15:47:50 +02003221static const char * const tegra186_reset_sources[] = {
3222 "SYS_RESET",
3223 "AOWDT",
3224 "MCCPLEXWDT",
3225 "BPMPWDT",
3226 "SCEWDT",
3227 "SPEWDT",
3228 "APEWDT",
3229 "BCCPLEXWDT",
3230 "SENSOR",
3231 "AOTAG",
3232 "VFSENSOR",
3233 "SWREST",
3234 "SC7",
3235 "HSM",
3236 "CORESIGHT"
3237};
3238
3239static const char * const tegra186_reset_levels[] = {
3240 "L0", "L1", "L2", "WARM"
3241};
3242
David Brazdil0f672f62019-12-10 10:32:29 +00003243static const struct tegra_wake_event tegra186_wake_events[] = {
Olivier Deprez157378f2022-04-04 15:47:50 +02003244 TEGRA_WAKE_IRQ("pmu", 24, 209),
David Brazdil0f672f62019-12-10 10:32:29 +00003245 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA186_AON_GPIO(FF, 0)),
3246 TEGRA_WAKE_IRQ("rtc", 73, 10),
3247};
3248
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003249static const struct tegra_pmc_soc tegra186_pmc_soc = {
3250 .num_powergates = 0,
3251 .powergates = NULL,
3252 .num_cpu_powergates = 0,
3253 .cpu_powergates = NULL,
3254 .has_tsense_reset = false,
3255 .has_gpu_clamps = false,
David Brazdil0f672f62019-12-10 10:32:29 +00003256 .needs_mbist_war = false,
3257 .has_impl_33v_pwr = true,
3258 .maybe_tz_only = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003259 .num_io_pads = ARRAY_SIZE(tegra186_io_pads),
3260 .io_pads = tegra186_io_pads,
David Brazdil0f672f62019-12-10 10:32:29 +00003261 .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs),
3262 .pin_descs = tegra186_pin_descs,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003263 .regs = &tegra186_pmc_regs,
3264 .init = NULL,
3265 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02003266 .irq_set_wake = tegra186_pmc_irq_set_wake,
3267 .irq_set_type = tegra186_pmc_irq_set_type,
David Brazdil0f672f62019-12-10 10:32:29 +00003268 .reset_sources = tegra186_reset_sources,
3269 .num_reset_sources = ARRAY_SIZE(tegra186_reset_sources),
3270 .reset_levels = tegra186_reset_levels,
3271 .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
3272 .num_wake_events = ARRAY_SIZE(tegra186_wake_events),
3273 .wake_events = tegra186_wake_events,
Olivier Deprez157378f2022-04-04 15:47:50 +02003274 .pmc_clks_data = NULL,
3275 .num_pmc_clks = 0,
3276 .has_blink_output = false,
David Brazdil0f672f62019-12-10 10:32:29 +00003277};
3278
Olivier Deprez157378f2022-04-04 15:47:50 +02003279#define TEGRA194_IO_PAD_TABLE(_pad) \
3280 /* .id .dpd .voltage .name */ \
3281 _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \
3282 _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \
3283 _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \
3284 _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \
3285 _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \
3286 _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \
3287 _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \
3288 _pad(TEGRA_IO_PAD_EQOS, 8, UINT_MAX, "eqos"), \
3289 _pad(TEGRA_IO_PAD_PEX_CLK_2_BIAS, 9, UINT_MAX, "pex-clk-2-bias"), \
3290 _pad(TEGRA_IO_PAD_PEX_CLK_2, 10, UINT_MAX, "pex-clk-2"), \
3291 _pad(TEGRA_IO_PAD_DAP3, 11, UINT_MAX, "dap3"), \
3292 _pad(TEGRA_IO_PAD_DAP5, 12, UINT_MAX, "dap5"), \
3293 _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \
3294 _pad(TEGRA_IO_PAD_PWR_CTL, 15, UINT_MAX, "pwr-ctl"), \
3295 _pad(TEGRA_IO_PAD_SOC_GPIO53, 16, UINT_MAX, "soc-gpio53"), \
3296 _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \
3297 _pad(TEGRA_IO_PAD_GP_PWM2, 18, UINT_MAX, "gp-pwm2"), \
3298 _pad(TEGRA_IO_PAD_GP_PWM3, 19, UINT_MAX, "gp-pwm3"), \
3299 _pad(TEGRA_IO_PAD_SOC_GPIO12, 20, UINT_MAX, "soc-gpio12"), \
3300 _pad(TEGRA_IO_PAD_SOC_GPIO13, 21, UINT_MAX, "soc-gpio13"), \
3301 _pad(TEGRA_IO_PAD_SOC_GPIO10, 22, UINT_MAX, "soc-gpio10"), \
3302 _pad(TEGRA_IO_PAD_UART4, 23, UINT_MAX, "uart4"), \
3303 _pad(TEGRA_IO_PAD_UART5, 24, UINT_MAX, "uart5"), \
3304 _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \
3305 _pad(TEGRA_IO_PAD_HDMI_DP3, 26, UINT_MAX, "hdmi-dp3"), \
3306 _pad(TEGRA_IO_PAD_HDMI_DP2, 27, UINT_MAX, "hdmi-dp2"), \
3307 _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \
3308 _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \
3309 _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \
3310 _pad(TEGRA_IO_PAD_PEX_CTL2, 33, UINT_MAX, "pex-ctl2"), \
3311 _pad(TEGRA_IO_PAD_PEX_L0_RST_N, 34, UINT_MAX, "pex-l0-rst"), \
3312 _pad(TEGRA_IO_PAD_PEX_L1_RST_N, 35, UINT_MAX, "pex-l1-rst"), \
3313 _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \
3314 _pad(TEGRA_IO_PAD_PEX_L5_RST_N, 37, UINT_MAX, "pex-l5-rst"), \
3315 _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \
3316 _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \
3317 _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \
3318 _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \
3319 _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \
3320 _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \
3321 _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \
3322 _pad(TEGRA_IO_PAD_CSIG, 50, UINT_MAX, "csig"), \
3323 _pad(TEGRA_IO_PAD_CSIH, 51, UINT_MAX, "csih"), \
3324 _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \
3325 _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \
3326 _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \
3327 _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \
3328 _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \
3329 _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv")
3330
David Brazdil0f672f62019-12-10 10:32:29 +00003331static const struct tegra_io_pad_soc tegra194_io_pads[] = {
Olivier Deprez157378f2022-04-04 15:47:50 +02003332 TEGRA194_IO_PAD_TABLE(TEGRA_IO_PAD)
3333};
3334
3335static const struct pinctrl_pin_desc tegra194_pin_descs[] = {
3336 TEGRA194_IO_PAD_TABLE(TEGRA_IO_PIN_DESC)
3337};
3338
3339static const struct tegra_pmc_regs tegra194_pmc_regs = {
3340 .scratch0 = 0x2000,
3341 .dpd_req = 0x74,
3342 .dpd_status = 0x78,
3343 .dpd2_req = 0x7c,
3344 .dpd2_status = 0x80,
3345 .rst_status = 0x70,
3346 .rst_source_shift = 0x2,
3347 .rst_source_mask = 0x7c,
3348 .rst_level_shift = 0x0,
3349 .rst_level_mask = 0x3,
3350};
3351
3352static const char * const tegra194_reset_sources[] = {
3353 "SYS_RESET_N",
3354 "AOWDT",
3355 "BCCPLEXWDT",
3356 "BPMPWDT",
3357 "SCEWDT",
3358 "SPEWDT",
3359 "APEWDT",
3360 "LCCPLEXWDT",
3361 "SENSOR",
3362 "AOTAG",
3363 "VFSENSOR",
3364 "MAINSWRST",
3365 "SC7",
3366 "HSM",
3367 "CSITE",
3368 "RCEWDT",
3369 "PVA0WDT",
3370 "PVA1WDT",
3371 "L1A_ASYNC",
3372 "BPMPBOOT",
3373 "FUSECRC",
David Brazdil0f672f62019-12-10 10:32:29 +00003374};
3375
3376static const struct tegra_wake_event tegra194_wake_events[] = {
Olivier Deprez157378f2022-04-04 15:47:50 +02003377 TEGRA_WAKE_IRQ("pmu", 24, 209),
David Brazdil0f672f62019-12-10 10:32:29 +00003378 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
3379 TEGRA_WAKE_IRQ("rtc", 73, 10),
3380};
3381
3382static const struct tegra_pmc_soc tegra194_pmc_soc = {
3383 .num_powergates = 0,
3384 .powergates = NULL,
3385 .num_cpu_powergates = 0,
3386 .cpu_powergates = NULL,
3387 .has_tsense_reset = false,
3388 .has_gpu_clamps = false,
3389 .needs_mbist_war = false,
Olivier Deprez157378f2022-04-04 15:47:50 +02003390 .has_impl_33v_pwr = true,
David Brazdil0f672f62019-12-10 10:32:29 +00003391 .maybe_tz_only = false,
3392 .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
3393 .io_pads = tegra194_io_pads,
Olivier Deprez157378f2022-04-04 15:47:50 +02003394 .num_pin_descs = ARRAY_SIZE(tegra194_pin_descs),
3395 .pin_descs = tegra194_pin_descs,
3396 .regs = &tegra194_pmc_regs,
David Brazdil0f672f62019-12-10 10:32:29 +00003397 .init = NULL,
3398 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
Olivier Deprez157378f2022-04-04 15:47:50 +02003399 .irq_set_wake = tegra186_pmc_irq_set_wake,
3400 .irq_set_type = tegra186_pmc_irq_set_type,
3401 .reset_sources = tegra194_reset_sources,
3402 .num_reset_sources = ARRAY_SIZE(tegra194_reset_sources),
3403 .reset_levels = tegra186_reset_levels,
3404 .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
David Brazdil0f672f62019-12-10 10:32:29 +00003405 .num_wake_events = ARRAY_SIZE(tegra194_wake_events),
3406 .wake_events = tegra194_wake_events,
Olivier Deprez157378f2022-04-04 15:47:50 +02003407 .pmc_clks_data = NULL,
3408 .num_pmc_clks = 0,
3409 .has_blink_output = false,
3410};
3411
3412static const struct tegra_pmc_regs tegra234_pmc_regs = {
3413 .scratch0 = 0x2000,
3414 .dpd_req = 0,
3415 .dpd_status = 0,
3416 .dpd2_req = 0,
3417 .dpd2_status = 0,
3418 .rst_status = 0x70,
3419 .rst_source_shift = 0x2,
3420 .rst_source_mask = 0xfc,
3421 .rst_level_shift = 0x0,
3422 .rst_level_mask = 0x3,
3423};
3424
3425static const char * const tegra234_reset_sources[] = {
3426 "SYS_RESET_N",
3427 "AOWDT",
3428 "BCCPLEXWDT",
3429 "BPMPWDT",
3430 "SCEWDT",
3431 "SPEWDT",
3432 "APEWDT",
3433 "LCCPLEXWDT",
3434 "SENSOR",
3435 "AOTAG",
3436 "VFSENSOR",
3437 "MAINSWRST",
3438 "SC7",
3439 "HSM",
3440 "CSITE",
3441 "RCEWDT",
3442 "PVA0WDT",
3443 "PVA1WDT",
3444 "L1A_ASYNC",
3445 "BPMPBOOT",
3446 "FUSECRC",
3447};
3448
3449static const struct tegra_pmc_soc tegra234_pmc_soc = {
3450 .num_powergates = 0,
3451 .powergates = NULL,
3452 .num_cpu_powergates = 0,
3453 .cpu_powergates = NULL,
3454 .has_tsense_reset = false,
3455 .has_gpu_clamps = false,
3456 .needs_mbist_war = false,
3457 .has_impl_33v_pwr = true,
3458 .maybe_tz_only = false,
3459 .num_io_pads = 0,
3460 .io_pads = NULL,
3461 .num_pin_descs = 0,
3462 .pin_descs = NULL,
3463 .regs = &tegra234_pmc_regs,
3464 .init = NULL,
3465 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
3466 .irq_set_wake = tegra186_pmc_irq_set_wake,
3467 .irq_set_type = tegra186_pmc_irq_set_type,
3468 .reset_sources = tegra234_reset_sources,
3469 .num_reset_sources = ARRAY_SIZE(tegra234_reset_sources),
3470 .reset_levels = tegra186_reset_levels,
3471 .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
3472 .num_wake_events = 0,
3473 .wake_events = NULL,
3474 .pmc_clks_data = NULL,
3475 .num_pmc_clks = 0,
3476 .has_blink_output = false,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003477};
3478
3479static const struct of_device_id tegra_pmc_match[] = {
Olivier Deprez157378f2022-04-04 15:47:50 +02003480 { .compatible = "nvidia,tegra234-pmc", .data = &tegra234_pmc_soc },
David Brazdil0f672f62019-12-10 10:32:29 +00003481 { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc },
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003482 { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc },
3483 { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc },
3484 { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc },
3485 { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
3486 { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
3487 { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
3488 { .compatible = "nvidia,tegra20-pmc", .data = &tegra20_pmc_soc },
3489 { }
3490};
3491
3492static struct platform_driver tegra_pmc_driver = {
3493 .driver = {
3494 .name = "tegra-pmc",
3495 .suppress_bind_attrs = true,
3496 .of_match_table = tegra_pmc_match,
3497#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
3498 .pm = &tegra_pmc_pm_ops,
3499#endif
3500 },
3501 .probe = tegra_pmc_probe,
3502};
3503builtin_platform_driver(tegra_pmc_driver);
3504
David Brazdil0f672f62019-12-10 10:32:29 +00003505static bool __init tegra_pmc_detect_tz_only(struct tegra_pmc *pmc)
3506{
3507 u32 value, saved;
3508
3509 saved = readl(pmc->base + pmc->soc->regs->scratch0);
3510 value = saved ^ 0xffffffff;
3511
3512 if (value == 0xffffffff)
3513 value = 0xdeadbeef;
3514
3515 /* write pattern and read it back */
3516 writel(value, pmc->base + pmc->soc->regs->scratch0);
3517 value = readl(pmc->base + pmc->soc->regs->scratch0);
3518
3519 /* if we read all-zeroes, access is restricted to TZ only */
3520 if (value == 0) {
3521 pr_info("access to PMC is restricted to TZ\n");
3522 return true;
3523 }
3524
3525 /* restore original value */
3526 writel(saved, pmc->base + pmc->soc->regs->scratch0);
3527
3528 return false;
3529}
3530
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003531/*
3532 * Early initialization to allow access to registers in the very early boot
3533 * process.
3534 */
3535static int __init tegra_pmc_early_init(void)
3536{
3537 const struct of_device_id *match;
3538 struct device_node *np;
3539 struct resource regs;
David Brazdil0f672f62019-12-10 10:32:29 +00003540 unsigned int i;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003541 bool invert;
3542
3543 mutex_init(&pmc->powergates_lock);
3544
3545 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
3546 if (!np) {
3547 /*
3548 * Fall back to legacy initialization for 32-bit ARM only. All
3549 * 64-bit ARM device tree files for Tegra are required to have
3550 * a PMC node.
3551 *
3552 * This is for backwards-compatibility with old device trees
3553 * that didn't contain a PMC node. Note that in this case the
3554 * SoC data can't be matched and therefore powergating is
3555 * disabled.
3556 */
3557 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
3558 pr_warn("DT node not found, powergating disabled\n");
3559
3560 regs.start = 0x7000e400;
3561 regs.end = 0x7000e7ff;
3562 regs.flags = IORESOURCE_MEM;
3563
3564 pr_warn("Using memory region %pR\n", &regs);
3565 } else {
3566 /*
3567 * At this point we're not running on Tegra, so play
3568 * nice with multi-platform kernels.
3569 */
3570 return 0;
3571 }
3572 } else {
3573 /*
3574 * Extract information from the device tree if we've found a
3575 * matching node.
3576 */
3577 if (of_address_to_resource(np, 0, &regs) < 0) {
3578 pr_err("failed to get PMC registers\n");
3579 of_node_put(np);
3580 return -ENXIO;
3581 }
3582 }
3583
Olivier Deprez157378f2022-04-04 15:47:50 +02003584 pmc->base = ioremap(regs.start, resource_size(&regs));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003585 if (!pmc->base) {
3586 pr_err("failed to map PMC registers\n");
3587 of_node_put(np);
3588 return -ENXIO;
3589 }
3590
3591 if (np) {
3592 pmc->soc = match->data;
3593
David Brazdil0f672f62019-12-10 10:32:29 +00003594 if (pmc->soc->maybe_tz_only)
3595 pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
3596
3597 /* Create a bitmap of the available and valid partitions */
3598 for (i = 0; i < pmc->soc->num_powergates; i++)
3599 if (pmc->soc->powergates[i])
3600 set_bit(i, pmc->powergates_available);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00003601
3602 /*
3603 * Invert the interrupt polarity if a PMC device tree node
3604 * exists and contains the nvidia,invert-interrupt property.
3605 */
3606 invert = of_property_read_bool(np, "nvidia,invert-interrupt");
3607
3608 pmc->soc->setup_irq_polarity(pmc, np, invert);
3609
3610 of_node_put(np);
3611 }
3612
3613 return 0;
3614}
3615early_initcall(tegra_pmc_early_init);