Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Jan 2019 01:32:35 +0000 (17:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 1 Jan 2019 01:32:35 +0000 (17:32 -0800)
Pull ARM SoC driver updates from Olof Johansson:
 "Misc driver updates for platforms, many of them power related.

   - Rockchip adds power domain support for rk3066 and rk3188

   - Amlogic adds a power measurement driver

   - Allwinner adds SRAM support for three platforms (F1C100, H5, A64
     C1)

   - Wakeup and ti-sysc (platform bus) fixes for OMAP/DRA7

   - Broadcom fixes suspend/resume with Thumb2 kernels, and improves
     stability of a handful of firmware/platform interfaces

   - PXA completes their conversion to dmaengine framework

   - Renesas does a bunch of PM cleanups across many platforms

   - Tegra adds support for suspend/resume on T186/T194, which includes
     some driver cleanups and addition of wake events

   - Tegra also adds a driver for memory controller (EMC) on Tegra2

   - i.MX tweaks power domain bindings, and adds support for i.MX8MQ in
     GPC

   - Atmel adds identifiers and LPDDR2 support for a new SoC, SAM9X60

  and misc cleanups across several platforms"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (73 commits)
  ARM: at91: add support in soc driver for new SAM9X60
  ARM: at91: add support in soc driver for LPDDR2 SiP
  memory: omap-gpmc: Use of_node_name_eq for node name comparisons
  bus: ti-sysc: Check for no-reset and no-idle flags at the child level
  ARM: OMAP2+: Check also the first dts child for hwmod flags
  soc: amlogic: meson-clk-measure: Add missing REGMAP_MMIO dependency
  soc: imx: gpc: Increase GPC_CLK_MAX to 7
  soc: renesas: rcar-sysc: Fix power domain control after system resume
  soc: renesas: rcar-sysc: Merge PM Domain registration and linking
  soc: renesas: rcar-sysc: Remove rcar_sysc_power_{down,up}() helpers
  soc: renesas: r8a77990-sysc: Fix initialization order of 3DG-{A,B}
  dt-bindings: sram: sunxi: Add compatible for the A64 SRAM C1
  dt-bindings: sram: sunxi: Add bindings for the H5 with SRAM C1
  dt-bindings: sram: Add Allwinner suniv F1C100s
  soc: sunxi: sram: Add support for the H5 SoC system control
  soc: sunxi: sram: Enable EMAC clock access for H3 variant
  soc: imx: gpcv2: add support for i.MX8MQ SoC
  soc: imx: gpcv2: move register access table to domain data
  soc: imx: gpcv2: prefix i.MX7 specific defines
  dmaengine: pxa: make the filter function internal
  ...

1  2 
arch/arm/mach-omap2/omap_hwmod.c
drivers/gpu/drm/msm/adreno/a6xx_gmu.c
drivers/memory/omap-gpmc.c
drivers/soc/tegra/pmc.c
include/soc/tegra/pmc.h

index 921c9aaee63f590bc352ad14f16e3c3206fb6832,b506d5d9da82210dc347675a8b5cb42a6110b98a..b5531dd3ae9c36b5b165b314ba39d2e0a9cd8264
@@@ -2345,6 -2345,17 +2345,17 @@@ static int __init _init_mpu_rt_base(str
        return 0;
  }
  
+ static void __init parse_module_flags(struct omap_hwmod *oh,
+                                     struct device_node *np)
+ {
+       if (of_find_property(np, "ti,no-reset-on-init", NULL))
+               oh->flags |= HWMOD_INIT_NO_RESET;
+       if (of_find_property(np, "ti,no-idle-on-init", NULL))
+               oh->flags |= HWMOD_INIT_NO_IDLE;
+       if (of_find_property(np, "ti,no-idle", NULL))
+               oh->flags |= HWMOD_NO_IDLE;
+ }
  /**
   * _init - initialize internal data for the hwmod @oh
   * @oh: struct omap_hwmod *
@@@ -2392,12 -2403,12 +2403,12 @@@ static int __init _init(struct omap_hwm
        }
  
        if (np) {
-               if (of_find_property(np, "ti,no-reset-on-init", NULL))
-                       oh->flags |= HWMOD_INIT_NO_RESET;
-               if (of_find_property(np, "ti,no-idle-on-init", NULL))
-                       oh->flags |= HWMOD_INIT_NO_IDLE;
-               if (of_find_property(np, "ti,no-idle", NULL))
-                       oh->flags |= HWMOD_NO_IDLE;
+               struct device_node *child;
+               parse_module_flags(oh, np);
+               child = of_get_next_child(np, NULL);
+               if (child)
+                       parse_module_flags(oh, child);
        }
  
        oh->_state = _HWMOD_STATE_INITIALIZED;
   * a stub; implementing this properly requires iclk autoidle usecounting in
   * the clock code.   No return value.
   */
 -static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
 +static void _setup_iclk_autoidle(struct omap_hwmod *oh)
  {
        struct omap_hwmod_ocp_if *os;
  
   * reset.  Returns 0 upon success or a negative error code upon
   * failure.
   */
 -static int __init _setup_reset(struct omap_hwmod *oh)
 +static int _setup_reset(struct omap_hwmod *oh)
  {
        int r;
  
   *
   * No return value.
   */
 -static void __init _setup_postsetup(struct omap_hwmod *oh)
 +static void _setup_postsetup(struct omap_hwmod *oh)
  {
        u8 postsetup_state;
  
index c58e953fefa3b25343e1b7d3ebeb8ce1277c8b8f,0fb4718ef0df9c9ba7cfa72f71f0da952f9fb2c7..5beb83d1cf87769948575b74957777ce0e5b5d6e
@@@ -51,31 -51,10 +51,31 @@@ static irqreturn_t a6xx_hfi_irq(int irq
        return IRQ_HANDLED;
  }
  
 +bool a6xx_gmu_sptprac_is_on(struct a6xx_gmu *gmu)
 +{
 +      u32 val;
 +
 +      /* This can be called from gpu state code so make sure GMU is valid */
 +      if (IS_ERR_OR_NULL(gmu->mmio))
 +              return false;
 +
 +      val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
 +
 +      return !(val &
 +              (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_OFF |
 +              A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SP_CLOCK_OFF));
 +}
 +
  /* Check to see if the GX rail is still powered */
 -static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
 +bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
  {
 -      u32 val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
 +      u32 val;
 +
 +      /* This can be called from gpu state code so make sure GMU is valid */
 +      if (IS_ERR_OR_NULL(gmu->mmio))
 +              return false;
 +
 +      val = gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS);
  
        return !(val &
                (A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF |
@@@ -174,7 -153,7 +174,7 @@@ static int a6xx_gmu_start(struct a6xx_g
                val == 0xbabeface, 100, 10000);
  
        if (ret)
 -              dev_err(gmu->dev, "GMU firmware initialization timed out\n");
 +              DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n");
  
        return ret;
  }
@@@ -189,7 -168,7 +189,7 @@@ static int a6xx_gmu_hfi_start(struct a6
        ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_HFI_CTRL_STATUS, val,
                val & 1, 100, 10000);
        if (ret)
 -              dev_err(gmu->dev, "Unable to start the HFI queues\n");
 +              DRM_DEV_ERROR(gmu->dev, "Unable to start the HFI queues\n");
  
        return ret;
  }
@@@ -230,7 -209,7 +230,7 @@@ int a6xx_gmu_set_oob(struct a6xx_gmu *g
                val & (1 << ack), 100, 10000);
  
        if (ret)
 -              dev_err(gmu->dev,
 +              DRM_DEV_ERROR(gmu->dev,
                        "Timeout waiting for GMU OOB set %s: 0x%x\n",
                                name,
                                gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO));
@@@ -272,7 -251,7 +272,7 @@@ static int a6xx_sptprac_enable(struct a
                (val & 0x38) == 0x28, 1, 100);
  
        if (ret) {
 -              dev_err(gmu->dev, "Unable to power on SPTPRAC: 0x%x\n",
 +              DRM_DEV_ERROR(gmu->dev, "Unable to power on SPTPRAC: 0x%x\n",
                        gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS));
        }
  
@@@ -294,7 -273,7 +294,7 @@@ static void a6xx_sptprac_disable(struc
                (val & 0x04), 100, 10000);
  
        if (ret)
 -              dev_err(gmu->dev, "failed to power off SPTPRAC: 0x%x\n",
 +              DRM_DEV_ERROR(gmu->dev, "failed to power off SPTPRAC: 0x%x\n",
                        gmu_read(gmu, REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS));
  }
  
@@@ -338,7 -317,7 +338,7 @@@ static int a6xx_gmu_notify_slumber(stru
                /* Check to see if the GMU really did slumber */
                if (gmu_read(gmu, REG_A6XX_GPU_GMU_CX_GMU_RPMH_POWER_STATE)
                        != 0x0f) {
 -                      dev_err(gmu->dev, "The GMU did not go into slumber\n");
 +                      DRM_DEV_ERROR(gmu->dev, "The GMU did not go into slumber\n");
                        ret = -ETIMEDOUT;
                }
        }
@@@ -360,27 -339,23 +360,27 @@@ static int a6xx_rpmh_start(struct a6xx_
        ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_RSCC_CONTROL_ACK, val,
                val & (1 << 1), 100, 10000);
        if (ret) {
 -              dev_err(gmu->dev, "Unable to power on the GPU RSC\n");
 +              DRM_DEV_ERROR(gmu->dev, "Unable to power on the GPU RSC\n");
                return ret;
        }
  
        ret = gmu_poll_timeout(gmu, REG_A6XX_RSCC_SEQ_BUSY_DRV0, val,
                !val, 100, 10000);
  
 -      if (!ret) {
 -              gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
 -
 -              /* Re-enable the power counter */
 -              gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
 -              return 0;
 +      if (ret) {
 +              DRM_DEV_ERROR(gmu->dev, "GPU RSC sequence stuck while waking up the GPU\n");
 +              return ret;
        }
  
 -      dev_err(gmu->dev, "GPU RSC sequence stuck while waking up the GPU\n");
 -      return ret;
 +      gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
 +
 +      /* Set up CX GMU counter 0 to count busy ticks */
 +      gmu_write(gmu, REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_MASK, 0xff000000);
 +      gmu_rmw(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_SELECT_0, 0xff, 0x20);
 +
 +      /* Enable the power counter */
 +      gmu_write(gmu, REG_A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
 +      return 0;
  }
  
  static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
        ret = gmu_poll_timeout(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0,
                val, val & (1 << 16), 100, 10000);
        if (ret)
 -              dev_err(gmu->dev, "Unable to power off the GPU RSC\n");
 +              DRM_DEV_ERROR(gmu->dev, "Unable to power off the GPU RSC\n");
  
        gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
  }
@@@ -545,7 -520,7 +545,7 @@@ static int a6xx_gmu_fw_start(struct a6x
  
                /* Sanity check the size of the firmware that was loaded */
                if (adreno_gpu->fw[ADRENO_FW_GMU]->size > 0x8000) {
 -                      dev_err(gmu->dev,
 +                      DRM_DEV_ERROR(gmu->dev,
                                "GMU firmware is bigger than the available region\n");
                        return -EINVAL;
                }
@@@ -789,7 -764,7 +789,7 @@@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx
                 */
  
                if (ret)
 -                      dev_err(gmu->dev,
 +                      DRM_DEV_ERROR(gmu->dev,
                                "Unable to slumber GMU: status = 0%x/0%x\n",
                                gmu_read(gmu,
                                        REG_A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS),
@@@ -868,7 -843,7 +868,7 @@@ static struct a6xx_gmu_bo *a6xx_gmu_mem
                        IOMMU_READ | IOMMU_WRITE);
  
                if (ret) {
 -                      dev_err(gmu->dev, "Unable to map GMU buffer object\n");
 +                      DRM_DEV_ERROR(gmu->dev, "Unable to map GMU buffer object\n");
  
                        for (i = i - 1 ; i >= 0; i--)
                                iommu_unmap(gmu->domain,
@@@ -927,26 -902,6 +927,6 @@@ static int a6xx_gmu_memory_probe(struc
        return ret;
  }
  
- /* Get the list of RPMh voltage levels from cmd-db */
- static int a6xx_gmu_rpmh_arc_cmds(const char *id, void *vals, int size)
- {
-       u32 len = cmd_db_read_aux_data_len(id);
-       if (!len)
-               return 0;
-       if (WARN_ON(len > size))
-               return -EINVAL;
-       cmd_db_read_aux_data(id, vals, len);
-       /*
-        * The data comes back as an array of unsigned shorts so adjust the
-        * count accordingly
-        */
-       return len >> 1;
- }
  /* Return the 'arc-level' for the given frequency */
  static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
  {
  }
  
  static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
-               unsigned long *freqs, int freqs_count,
-               u16 *pri, int pri_count,
-               u16 *sec, int sec_count)
+               unsigned long *freqs, int freqs_count, const char *id)
  {
        int i, j;
+       const u16 *pri, *sec;
+       size_t pri_count, sec_count;
+       pri = cmd_db_read_aux_data(id, &pri_count);
+       if (IS_ERR(pri))
+               return PTR_ERR(pri);
+       /*
+        * The data comes back as an array of unsigned shorts so adjust the
+        * count accordingly
+        */
+       pri_count >>= 1;
+       if (!pri_count)
+               return -EINVAL;
+       sec = cmd_db_read_aux_data("mx.lvl", &sec_count);
+       if (IS_ERR(sec))
+               return PTR_ERR(sec);
+       sec_count >>= 1;
+       if (!sec_count)
+               return -EINVAL;
  
        /* Construct a vote for each frequency */
        for (i = 0; i < freqs_count; i++) {
                }
  
                if (j == pri_count) {
 -                      dev_err(dev,
 +                      DRM_DEV_ERROR(dev,
                                "Level %u not found in in the RPMh list\n",
                                        level);
 -                      dev_err(dev, "Available levels:\n");
 +                      DRM_DEV_ERROR(dev, "Available levels:\n");
                        for (j = 0; j < pri_count; j++)
 -                              dev_err(dev, "  %u\n", pri[j]);
 +                              DRM_DEV_ERROR(dev, "  %u\n", pri[j]);
  
                        return -EINVAL;
                }
@@@ -1037,25 -1011,15 +1036,15 @@@ static int a6xx_gmu_rpmh_votes_init(str
        struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
        struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
        struct msm_gpu *gpu = &adreno_gpu->base;
-       u16 gx[16], cx[16], mx[16];
-       u32 gxcount, cxcount, mxcount;
        int ret;
  
-       /* Get the list of available voltage levels for each component */
-       gxcount = a6xx_gmu_rpmh_arc_cmds("gfx.lvl", gx, sizeof(gx));
-       cxcount = a6xx_gmu_rpmh_arc_cmds("cx.lvl", cx, sizeof(cx));
-       mxcount = a6xx_gmu_rpmh_arc_cmds("mx.lvl", mx, sizeof(mx));
        /* Build the GX votes */
        ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes,
-               gmu->gpu_freqs, gmu->nr_gpu_freqs,
-               gx, gxcount, mx, mxcount);
+               gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl");
  
        /* Build the CX votes */
        ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes,
-               gmu->gmu_freqs, gmu->nr_gmu_freqs,
-               cx, cxcount, mx, mxcount);
+               gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl");
  
        return ret;
  }
@@@ -1106,7 -1070,7 +1095,7 @@@ static int a6xx_gmu_pwrlevels_probe(str
         */
        ret = dev_pm_opp_of_add_table(gmu->dev);
        if (ret) {
 -              dev_err(gmu->dev, "Unable to set the OPP table for the GMU\n");
 +              DRM_DEV_ERROR(gmu->dev, "Unable to set the OPP table for the GMU\n");
                return ret;
        }
  
@@@ -1147,13 -1111,13 +1136,13 @@@ static void __iomem *a6xx_gmu_get_mmio(
                        IORESOURCE_MEM, name);
  
        if (!res) {
 -              dev_err(&pdev->dev, "Unable to find the %s registers\n", name);
 +              DRM_DEV_ERROR(&pdev->dev, "Unable to find the %s registers\n", name);
                return ERR_PTR(-EINVAL);
        }
  
        ret = devm_ioremap(&pdev->dev, res->start, resource_size(res));
        if (!ret) {
 -              dev_err(&pdev->dev, "Unable to map the %s registers\n", name);
 +              DRM_DEV_ERROR(&pdev->dev, "Unable to map the %s registers\n", name);
                return ERR_PTR(-EINVAL);
        }
  
@@@ -1170,7 -1134,7 +1159,7 @@@ static int a6xx_gmu_get_irq(struct a6xx
        ret = devm_request_irq(&pdev->dev, irq, handler, IRQF_TRIGGER_HIGH,
                name, gmu);
        if (ret) {
 -              dev_err(&pdev->dev, "Unable to get interrupt %s\n", name);
 +              DRM_DEV_ERROR(&pdev->dev, "Unable to get interrupt %s\n", name);
                return ret;
        }
  
index a2188f7c04c66ed7637cdcf7ab8aedb7bcb5d83f,a66dea4f1ed2500bd0b7dfed1e84428c2b1c9ae2..f6297599433f14ee73259aa34b54cbf9eb538c9d
@@@ -21,7 -21,6 +21,7 @@@
  #include <linux/spinlock.h>
  #include <linux/io.h>
  #include <linux/gpio/driver.h>
 +#include <linux/gpio/consumer.h> /* GPIO descriptor enum */
  #include <linux/interrupt.h>
  #include <linux/irqdomain.h>
  #include <linux/platform_device.h>
@@@ -2061,7 -2060,7 +2061,7 @@@ static int gpmc_probe_generic_child(str
         * timings.
         */
        name = gpmc_cs_get_name(cs);
-       if (name && of_node_cmp(child->name, name) == 0)
+       if (name && of_node_name_eq(child, name))
                goto no_timings;
  
        ret = gpmc_cs_request(cs, resource_size(&res), &base);
                dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
                return ret;
        }
-       gpmc_cs_set_name(cs, child->name);
+       gpmc_cs_set_name(cs, child->full_name);
  
        gpmc_read_settings_dt(child, &gpmc_s);
        gpmc_read_timings_dt(child, &gpmc_t);
                goto err;
        }
  
-       if (of_node_cmp(child->name, "nand") == 0) {
+       if (of_node_name_eq(child, "nand")) {
                /* Warn about older DT blobs with no compatible property */
                if (!of_property_read_bool(child, "compatible")) {
                        dev_warn(&pdev->dev,
                }
        }
  
-       if (of_node_cmp(child->name, "onenand") == 0) {
+       if (of_node_name_eq(child, "onenand")) {
                /* Warn about older DT blobs with no compatible property */
                if (!of_property_read_bool(child, "compatible")) {
                        dev_warn(&pdev->dev,
                        gpmc_s.device_width = GPMC_DEVWIDTH_16BIT;
                        break;
                default:
 -                      dev_err(&pdev->dev, "%s: invalid 'nand-bus-width'\n",
 -                              child->name);
 +                      dev_err(&pdev->dev, "%pOFn: invalid 'nand-bus-width'\n",
 +                              child);
                        ret = -EINVAL;
                        goto err;
                }
                unsigned int wait_pin = gpmc_s.wait_pin;
  
                waitpin_desc = gpiochip_request_own_desc(&gpmc->gpio_chip,
 -                                                       wait_pin, "WAITPIN");
 +                                                       wait_pin, "WAITPIN",
 +                                                       0);
                if (IS_ERR(waitpin_desc)) {
                        dev_err(&pdev->dev, "invalid wait-pin: %d\n", wait_pin);
                        ret = PTR_ERR(waitpin_desc);
  
        ret = gpmc_cs_set_timings(cs, &gpmc_t, &gpmc_s);
        if (ret) {
 -              dev_err(&pdev->dev, "failed to set gpmc timings for: %s\n",
 -                      child->name);
 +              dev_err(&pdev->dev, "failed to set gpmc timings for: %pOFn\n",
 +                      child);
                goto err_cs;
        }
  
@@@ -2217,7 -2215,7 +2217,7 @@@ no_timings
  
  err_child_fail:
  
 -      dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
 +      dev_err(&pdev->dev, "failed to create gpmc child %pOFn\n", child);
        ret = -ENODEV;
  
  err_cs:
@@@ -2267,10 -2265,14 +2267,10 @@@ static void gpmc_probe_dt_children(stru
        struct device_node *child;
  
        for_each_available_child_of_node(pdev->dev.of_node, child) {
 -
 -              if (!child->name)
 -                      continue;
 -
                ret = gpmc_probe_generic_child(pdev, child);
                if (ret) {
 -                      dev_err(&pdev->dev, "failed to probe DT child '%s': %d\n",
 -                              child->name, ret);
 +                      dev_err(&pdev->dev, "failed to probe DT child '%pOFn': %d\n",
 +                              child, ret);
                }
        }
  }
diff --combined drivers/soc/tegra/pmc.c
index b30af18516d6636b72f0d503c590a7b027974913,8c46b0aace0b2132dc5eb3890802d1131112f6a8..7ea3280279ff56cb9d8932d37f16d9c7268f33cf
@@@ -2,6 -2,7 +2,7 @@@
   * drivers/soc/tegra/pmc.c
   *
   * Copyright (c) 2010 Google, Inc
+  * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
   *
   * Author:
   *    Colin Cross <ccross@google.com>
  #include <linux/init.h>
  #include <linux/io.h>
  #include <linux/iopoll.h>
+ #include <linux/irq.h>
+ #include <linux/irqdomain.h>
  #include <linux/of.h>
  #include <linux/of_address.h>
  #include <linux/of_clk.h>
+ #include <linux/of_irq.h>
  #include <linux/of_platform.h>
  #include <linux/pinctrl/pinctrl.h>
  #include <linux/pinctrl/pinconf.h>
  #include <soc/tegra/fuse.h>
  #include <soc/tegra/pmc.h>
  
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
  #include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
+ #include <dt-bindings/gpio/tegra186-gpio.h>
+ #include <dt-bindings/gpio/tegra194-gpio.h>
  
  #define PMC_CNTRL                     0x0
  #define  PMC_CNTRL_INTR_POLARITY      BIT(17) /* inverts INTR polarity */
@@@ -92,7 -99,6 +99,6 @@@
  #define  PMC_SENSOR_CTRL_SCRATCH_WRITE        BIT(2)
  #define  PMC_SENSOR_CTRL_ENABLE_RST   BIT(1)
  
- #define PMC_RST_STATUS                        0x1b4
  #define  PMC_RST_STATUS_POR           0
  #define  PMC_RST_STATUS_WATCHDOG      1
  #define  PMC_RST_STATUS_SENSOR                2
  #define GPU_RG_CNTRL                  0x2d4
  
  /* Tegra186 and later */
+ #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
+ #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
+ #define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
+ #define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
+ #define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
+ #define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2))
+ #define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2))
+ #define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2))
+ #define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2))
  #define WAKE_AOWAKE_CTRL 0x4f4
  #define  WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
  
@@@ -151,8 -167,45 +167,45 @@@ struct tegra_pmc_regs 
        unsigned int dpd_status;
        unsigned int dpd2_req;
        unsigned int dpd2_status;
+       unsigned int rst_status;
+       unsigned int rst_source_shift;
+       unsigned int rst_source_mask;
+       unsigned int rst_level_shift;
+       unsigned int rst_level_mask;
+ };
+ struct tegra_wake_event {
+       const char *name;
+       unsigned int id;
+       unsigned int irq;
+       struct {
+               unsigned int instance;
+               unsigned int pin;
+       } gpio;
  };
  
+ #define TEGRA_WAKE_IRQ(_name, _id, _irq)              \
+       {                                               \
+               .name = _name,                          \
+               .id = _id,                              \
+               .irq = _irq,                            \
+               .gpio = {                               \
+                       .instance = UINT_MAX,           \
+                       .pin = UINT_MAX,                \
+               },                                      \
+       }
+ #define TEGRA_WAKE_GPIO(_name, _id, _instance, _pin)  \
+       {                                               \
+               .name = _name,                          \
+               .id = _id,                              \
+               .irq = 0,                               \
+               .gpio = {                               \
+                       .instance = _instance,          \
+                       .pin = _pin,                    \
+               },                                      \
+       }
  struct tegra_pmc_soc {
        unsigned int num_powergates;
        const char *const *powergates;
        void (*setup_irq_polarity)(struct tegra_pmc *pmc,
                                   struct device_node *np,
                                   bool invert);
+       const char * const *reset_sources;
+       unsigned int num_reset_sources;
+       const char * const *reset_levels;
+       unsigned int num_reset_levels;
+       const struct tegra_wake_event *wake_events;
+       unsigned int num_wake_events;
+ };
+ static const char * const tegra186_reset_sources[] = {
+       "SYS_RESET",
+       "AOWDT",
+       "MCCPLEXWDT",
+       "BPMPWDT",
+       "SCEWDT",
+       "SPEWDT",
+       "APEWDT",
+       "BCCPLEXWDT",
+       "SENSOR",
+       "AOTAG",
+       "VFSENSOR",
+       "SWREST",
+       "SC7",
+       "HSM",
+       "CORESIGHT"
+ };
+ static const char * const tegra186_reset_levels[] = {
+       "L0", "L1", "L2", "WARM"
+ };
+ static const char * const tegra30_reset_sources[] = {
+       "POWER_ON_RESET",
+       "WATCHDOG",
+       "SENSOR",
+       "SW_MAIN",
+       "LP0",
+       "AOTAG"
  };
  
  /**
@@@ -230,6 -322,9 +322,9 @@@ struct tegra_pmc 
        struct mutex powergates_lock;
  
        struct pinctrl_dev *pctl_dev;
+       struct irq_domain *domain;
+       struct irq_chip irq;
  };
  
  static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@@ -538,16 -633,10 +633,10 @@@ EXPORT_SYMBOL(tegra_powergate_power_off
   */
  int tegra_powergate_is_powered(unsigned int id)
  {
-       int status;
        if (!tegra_powergate_is_valid(id))
                return -EINVAL;
  
-       mutex_lock(&pmc->powergates_lock);
-       status = tegra_powergate_state(id);
-       mutex_unlock(&pmc->powergates_lock);
-       return status;
+       return tegra_powergate_state(id);
  }
  
  /**
@@@ -600,6 -689,7 +689,6 @@@ int tegra_powergate_sequence_power_up(u
  }
  EXPORT_SYMBOL(tegra_powergate_sequence_power_up);
  
 -#ifdef CONFIG_SMP
  /**
   * tegra_get_cpu_powergate_id() - convert from CPU ID to partition ID
   * @cpuid: CPU partition ID
@@@ -659,6 -749,7 +748,6 @@@ int tegra_pmc_cpu_remove_clamping(unsig
  
        return tegra_powergate_remove_clamping(id);
  }
 -#endif /* CONFIG_SMP */
  
  static int tegra_pmc_restart_notify(struct notifier_block *this,
                                    unsigned long action, void *data)
@@@ -715,17 -806,7 +804,7 @@@ static int powergate_show(struct seq_fi
        return 0;
  }
  
- static int powergate_open(struct inode *inode, struct file *file)
- {
-       return single_open(file, powergate_show, inode->i_private);
- }
- static const struct file_operations powergate_fops = {
-       .open = powergate_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
- };
+ DEFINE_SHOW_ATTRIBUTE(powergate);
  
  static int tegra_powergate_debugfs_init(void)
  {
@@@ -845,22 -926,6 +924,6 @@@ static void tegra_powergate_add(struct 
                goto remove_resets;
        }
  
-       /*
-        * FIXME: If XHCI is enabled for Tegra, then power-up the XUSB
-        * host and super-speed partitions. Once the XHCI driver
-        * manages the partitions itself this code can be removed. Note
-        * that we don't register these partitions with the genpd core
-        * to avoid it from powering down the partitions as they appear
-        * to be unused.
-        */
-       if (IS_ENABLED(CONFIG_USB_XHCI_TEGRA) &&
-           (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC)) {
-               if (off)
-                       WARN_ON(tegra_powergate_power_up(pg, true));
-               goto remove_resets;
-       }
        err = pm_genpd_init(&pg->genpd, NULL, off);
        if (err < 0) {
                pr_err("failed to initialise PM domain %pOFn: %d\n", np,
@@@ -1541,6 -1606,225 +1604,225 @@@ static int tegra_pmc_pinctrl_init(struc
        return err;
  }
  
+ static ssize_t reset_reason_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+ {
+       u32 value, rst_src;
+       value = tegra_pmc_readl(pmc->soc->regs->rst_status);
+       rst_src = (value & pmc->soc->regs->rst_source_mask) >>
+                       pmc->soc->regs->rst_source_shift;
+       return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
+ }
+ static DEVICE_ATTR_RO(reset_reason);
+ static ssize_t reset_level_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+ {
+       u32 value, rst_lvl;
+       value = tegra_pmc_readl(pmc->soc->regs->rst_status);
+       rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
+                       pmc->soc->regs->rst_level_shift;
+       return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
+ }
+ static DEVICE_ATTR_RO(reset_level);
+ static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
+ {
+       struct device *dev = pmc->dev;
+       int err = 0;
+       if (pmc->soc->reset_sources) {
+               err = device_create_file(dev, &dev_attr_reset_reason);
+               if (err < 0)
+                       dev_warn(dev,
+                               "failed to create attr \"reset_reason\": %d\n",
+                               err);
+       }
+       if (pmc->soc->reset_levels) {
+               err = device_create_file(dev, &dev_attr_reset_level);
+               if (err < 0)
+                       dev_warn(dev,
+                               "failed to create attr \"reset_level\": %d\n",
+                               err);
+       }
+ }
+ static int tegra_pmc_irq_translate(struct irq_domain *domain,
+                                  struct irq_fwspec *fwspec,
+                                  unsigned long *hwirq,
+                                  unsigned int *type)
+ {
+       if (WARN_ON(fwspec->param_count < 2))
+               return -EINVAL;
+       *hwirq = fwspec->param[0];
+       *type = fwspec->param[1];
+       return 0;
+ }
+ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
+                              unsigned int num_irqs, void *data)
+ {
+       struct tegra_pmc *pmc = domain->host_data;
+       const struct tegra_pmc_soc *soc = pmc->soc;
+       struct irq_fwspec *fwspec = data;
+       unsigned int i;
+       int err = 0;
+       for (i = 0; i < soc->num_wake_events; i++) {
+               const struct tegra_wake_event *event = &soc->wake_events[i];
+               if (fwspec->param_count == 2) {
+                       struct irq_fwspec spec;
+                       if (event->id != fwspec->param[0])
+                               continue;
+                       err = irq_domain_set_hwirq_and_chip(domain, virq,
+                                                           event->id,
+                                                           &pmc->irq, pmc);
+                       if (err < 0)
+                               break;
+                       spec.fwnode = &pmc->dev->of_node->fwnode;
+                       spec.param_count = 3;
+                       spec.param[0] = GIC_SPI;
+                       spec.param[1] = event->irq;
+                       spec.param[2] = fwspec->param[1];
+                       err = irq_domain_alloc_irqs_parent(domain, virq,
+                                                          num_irqs, &spec);
+                       break;
+               }
+               if (fwspec->param_count == 3) {
+                       if (event->gpio.instance != fwspec->param[0] ||
+                           event->gpio.pin != fwspec->param[1])
+                               continue;
+                       err = irq_domain_set_hwirq_and_chip(domain, virq,
+                                                           event->id,
+                                                           &pmc->irq, pmc);
+                       break;
+               }
+       }
+       if (i == soc->num_wake_events)
+               err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
+                                                   &pmc->irq, pmc);
+       return err;
+ }
+ static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
+       .translate = tegra_pmc_irq_translate,
+       .alloc = tegra_pmc_irq_alloc,
+ };
+ static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
+ {
+       struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
+       unsigned int offset, bit;
+       u32 value;
+       offset = data->hwirq / 32;
+       bit = data->hwirq % 32;
+       /* clear wake status */
+       writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(data->hwirq));
+       /* route wake to tier 2 */
+       value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
+       if (!on)
+               value &= ~(1 << bit);
+       else
+               value |= 1 << bit;
+       writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
+       /* enable wakeup event */
+       writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(data->hwirq));
+       return 0;
+ }
+ static int tegra_pmc_irq_set_type(struct irq_data *data, unsigned int type)
+ {
+       struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
+       u32 value;
+       if (data->hwirq == ULONG_MAX)
+               return 0;
+       value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
+       switch (type) {
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_LEVEL_HIGH:
+               value |= WAKE_AOWAKE_CNTRL_LEVEL;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_LEVEL_LOW:
+               value &= ~WAKE_AOWAKE_CNTRL_LEVEL;
+               break;
+       case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
+               value ^= WAKE_AOWAKE_CNTRL_LEVEL;
+               break;
+       default:
+               return -EINVAL;
+       }
+       writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
+       return 0;
+ }
+ static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
+ {
+       struct irq_domain *parent = NULL;
+       struct device_node *np;
+       np = of_irq_find_parent(pmc->dev->of_node);
+       if (np) {
+               parent = irq_find_host(np);
+               of_node_put(np);
+       }
+       if (!parent)
+               return 0;
+       pmc->irq.name = dev_name(pmc->dev);
+       pmc->irq.irq_mask = irq_chip_mask_parent;
+       pmc->irq.irq_unmask = irq_chip_unmask_parent;
+       pmc->irq.irq_eoi = irq_chip_eoi_parent;
+       pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
+       pmc->irq.irq_set_type = tegra_pmc_irq_set_type;
+       pmc->irq.irq_set_wake = tegra_pmc_irq_set_wake;
+       pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
+                                              &tegra_pmc_irq_domain_ops, pmc);
+       if (!pmc->domain) {
+               dev_err(pmc->dev, "failed to allocate domain\n");
+               return -ENOMEM;
+       }
+       return 0;
+ }
  static int tegra_pmc_probe(struct platform_device *pdev)
  {
        void __iomem *base;
  
        tegra_pmc_init_tsense_reset(pmc);
  
+       tegra_pmc_reset_sysfs_init(pmc);
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_powergate_debugfs_init();
                if (err < 0)
        if (err)
                goto cleanup_restart_handler;
  
+       err = tegra_pmc_irq_init(pmc);
+       if (err < 0)
+               goto cleanup_restart_handler;
        mutex_lock(&pmc->powergates_lock);
        iounmap(pmc->base);
        pmc->base = base;
@@@ -1676,6 -1966,11 +1964,11 @@@ static const struct tegra_pmc_regs tegr
        .dpd_status = 0x1bc,
        .dpd2_req = 0x1c0,
        .dpd2_status = 0x1c4,
+       .rst_status = 0x1b4,
+       .rst_source_shift = 0x0,
+       .rst_source_mask = 0x7,
+       .rst_level_shift = 0x0,
+       .rst_level_mask = 0x0,
  };
  
  static void tegra20_pmc_init(struct tegra_pmc *pmc)
@@@ -1733,6 -2028,10 +2026,10 @@@ static const struct tegra_pmc_soc tegra
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+       .reset_sources = NULL,
+       .num_reset_sources = 0,
+       .reset_levels = NULL,
+       .num_reset_levels = 0,
  };
  
  static const char * const tegra30_powergates[] = {
@@@ -1774,6 -2073,10 +2071,10 @@@ static const struct tegra_pmc_soc tegra
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+       .reset_sources = tegra30_reset_sources,
+       .num_reset_sources = 5,
+       .reset_levels = NULL,
+       .num_reset_levels = 0,
  };
  
  static const char * const tegra114_powergates[] = {
@@@ -1819,6 -2122,10 +2120,10 @@@ static const struct tegra_pmc_soc tegra
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+       .reset_sources = tegra30_reset_sources,
+       .num_reset_sources = 5,
+       .reset_levels = NULL,
+       .num_reset_levels = 0,
  };
  
  static const char * const tegra124_powergates[] = {
@@@ -1924,6 -2231,10 +2229,10 @@@ static const struct tegra_pmc_soc tegra
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+       .reset_sources = tegra30_reset_sources,
+       .num_reset_sources = 5,
+       .reset_levels = NULL,
+       .num_reset_levels = 0,
  };
  
  static const char * const tegra210_powergates[] = {
@@@ -2025,6 -2336,10 +2334,10 @@@ static const struct tegra_pmc_soc tegra
        .regs = &tegra20_pmc_regs,
        .init = tegra20_pmc_init,
        .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
+       .reset_sources = tegra30_reset_sources,
+       .num_reset_sources = 5,
+       .reset_levels = NULL,
+       .num_reset_levels = 0,
  };
  
  #define TEGRA186_IO_PAD_TABLE(_pad)                                        \
@@@ -2082,6 -2397,11 +2395,11 @@@ static const struct tegra_pmc_regs tegr
        .dpd_status = 0x78,
        .dpd2_req = 0x7c,
        .dpd2_status = 0x80,
+       .rst_status = 0x70,
+       .rst_source_shift = 0x2,
+       .rst_source_mask = 0x3C,
+       .rst_level_shift = 0x0,
+       .rst_level_mask = 0x3,
  };
  
  static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
        iounmap(wake);
  }
  
+ static const struct tegra_wake_event tegra186_wake_events[] = {
+       TEGRA_WAKE_GPIO("power", 29, 1, TEGRA_AON_GPIO(FF, 0)),
+       TEGRA_WAKE_IRQ("rtc", 73, 10),
+ };
  static const struct tegra_pmc_soc tegra186_pmc_soc = {
        .num_powergates = 0,
        .powergates = NULL,
        .regs = &tegra186_pmc_regs,
        .init = NULL,
        .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .reset_sources = tegra186_reset_sources,
+       .num_reset_sources = 14,
+       .reset_levels = tegra186_reset_levels,
+       .num_reset_levels = 3,
+       .num_wake_events = ARRAY_SIZE(tegra186_wake_events),
+       .wake_events = tegra186_wake_events,
+ };
+ static const struct tegra_io_pad_soc tegra194_io_pads[] = {
+       { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_EQOS, .dpd = 8, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK2_BIAS, .dpd = 9, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 10, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DAP3, .dpd = 11, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DAP5, .dpd = 12, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PWR_CTL, .dpd = 15, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SOC_GPIO53, .dpd = 16, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_GP_PWM2, .dpd = 18, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_GP_PWM3, .dpd = 19, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SOC_GPIO12, .dpd = 20, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SOC_GPIO13, .dpd = 21, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SOC_GPIO10, .dpd = 22, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_UART4, .dpd = 23, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_UART5, .dpd = 24, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HDMI_DP3, .dpd = 26, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HDMI_DP2, .dpd = 27, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_CTL2, .dpd = 33, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_L0_RST_N, .dpd = 34, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_L1_RST_N, .dpd = 35, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_PEX_L5_RST_N, .dpd = 37, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIG, .dpd = 50, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CSIH, .dpd = 51, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX },
+       { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX },
+ };
+ static const struct tegra_wake_event tegra194_wake_events[] = {
+       TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
+       TEGRA_WAKE_IRQ("rtc", 73, 10),
+ };
+ static const struct tegra_pmc_soc tegra194_pmc_soc = {
+       .num_powergates = 0,
+       .powergates = NULL,
+       .num_cpu_powergates = 0,
+       .cpu_powergates = NULL,
+       .has_tsense_reset = false,
+       .has_gpu_clamps = false,
+       .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
+       .io_pads = tegra194_io_pads,
+       .regs = &tegra186_pmc_regs,
+       .init = NULL,
+       .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
+       .num_wake_events = ARRAY_SIZE(tegra194_wake_events),
+       .wake_events = tegra194_wake_events,
  };
  
  static const struct of_device_id tegra_pmc_match[] = {
-       { .compatible = "nvidia,tegra194-pmc", .data = &tegra186_pmc_soc },
+       { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc },
        { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc },
        { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc },
        { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc },
diff --combined include/soc/tegra/pmc.h
index bf761e68a7c759f5bc6f4564767a78dd95c8f4a5,fd816f6aa9cc48d76d6f5c1ea78aab9369cced72..a9db1b501de1f668b356170aa1a8d80652c2f190
  struct clk;
  struct reset_control;
  
 -#ifdef CONFIG_SMP
  bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
  int tegra_pmc_cpu_power_on(unsigned int cpuid);
  int tegra_pmc_cpu_remove_clamping(unsigned int cpuid);
 -#endif /* CONFIG_SMP */
  
  /*
   * powergate and I/O rail APIs
@@@ -88,6 -90,10 +88,10 @@@ enum tegra_io_pad 
        TEGRA_IO_PAD_CSID,
        TEGRA_IO_PAD_CSIE,
        TEGRA_IO_PAD_CSIF,
+       TEGRA_IO_PAD_CSIG,
+       TEGRA_IO_PAD_CSIH,
+       TEGRA_IO_PAD_DAP3,
+       TEGRA_IO_PAD_DAP5,
        TEGRA_IO_PAD_DBG,
        TEGRA_IO_PAD_DEBUG_NONAO,
        TEGRA_IO_PAD_DMIC,
        TEGRA_IO_PAD_EDP,
        TEGRA_IO_PAD_EMMC,
        TEGRA_IO_PAD_EMMC2,
+       TEGRA_IO_PAD_EQOS,
        TEGRA_IO_PAD_GPIO,
+       TEGRA_IO_PAD_GP_PWM2,
+       TEGRA_IO_PAD_GP_PWM3,
        TEGRA_IO_PAD_HDMI,
        TEGRA_IO_PAD_HDMI_DP0,
        TEGRA_IO_PAD_HDMI_DP1,
+       TEGRA_IO_PAD_HDMI_DP2,
+       TEGRA_IO_PAD_HDMI_DP3,
        TEGRA_IO_PAD_HSIC,
        TEGRA_IO_PAD_HV,
        TEGRA_IO_PAD_LVDS,
        TEGRA_IO_PAD_PEX_CLK_BIAS,
        TEGRA_IO_PAD_PEX_CLK1,
        TEGRA_IO_PAD_PEX_CLK2,
+       TEGRA_IO_PAD_PEX_CLK2_BIAS,
        TEGRA_IO_PAD_PEX_CLK3,
        TEGRA_IO_PAD_PEX_CNTRL,
+       TEGRA_IO_PAD_PEX_CTL2,
+       TEGRA_IO_PAD_PEX_L0_RST_N,
+       TEGRA_IO_PAD_PEX_L1_RST_N,
+       TEGRA_IO_PAD_PEX_L5_RST_N,
+       TEGRA_IO_PAD_PWR_CTL,
        TEGRA_IO_PAD_SDMMC1,
        TEGRA_IO_PAD_SDMMC1_HV,
        TEGRA_IO_PAD_SDMMC2,
        TEGRA_IO_PAD_SDMMC3,
        TEGRA_IO_PAD_SDMMC3_HV,
        TEGRA_IO_PAD_SDMMC4,
+       TEGRA_IO_PAD_SOC_GPIO10,
+       TEGRA_IO_PAD_SOC_GPIO12,
+       TEGRA_IO_PAD_SOC_GPIO13,
+       TEGRA_IO_PAD_SOC_GPIO53,
        TEGRA_IO_PAD_SPI,
        TEGRA_IO_PAD_SPI_HV,
        TEGRA_IO_PAD_SYS_DDC,
        TEGRA_IO_PAD_UART,
+       TEGRA_IO_PAD_UART4,
+       TEGRA_IO_PAD_UART5,
        TEGRA_IO_PAD_UFS,
        TEGRA_IO_PAD_USB0,
        TEGRA_IO_PAD_USB1,