Merge tag 'tegra-for-3.20-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra...
authorOlof Johansson <olof@lixom.net>
Fri, 23 Jan 2015 22:53:54 +0000 (14:53 -0800)
committerOlof Johansson <olof@lixom.net>
Fri, 23 Jan 2015 22:53:54 +0000 (14:53 -0800)
Merge "ARM: tegra: Core code changes for v3.20" from Thierry Reding:

This contains a couple of preparatory patches for 64-bit support. A new
feature is implemented in the power-management controller which allows
it to switch off the SoC if it overheats.

* tag 'tegra-for-3.20-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux:
  soc: tegra: Add thermal reset (thermtrip) support to PMC
  ARM: tegra: Add PMC thermtrip programming to Jetson TK1 device tree
  of: Add descriptions of thermtrip properties to Tegra PMC bindings
  soc/tegra: pmc: Add Tegra132 support
  soc/tegra: fuse: Add Tegra132 support
  soc/tegra: fuse: Constify tegra_fuse_info structures
  soc/tegra: Add Tegra132 support
  clocksource: Build Tegra timer on 32-bit ARM only
  soc/tegra: pmc: restrict compilation of suspend-related support to ARM

Signed-off-by: Olof Johansson <olof@lixom.net>
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
arch/arm/boot/dts/tegra124-jetson-tk1.dts
arch/arm/mach-tegra/Kconfig
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/fuse/fuse-tegra30.c
drivers/soc/tegra/pmc.c
include/soc/tegra/fuse.h
include/soc/tegra/pm.h

index 68ac65f..2fd5051 100644 (file)
@@ -47,6 +47,23 @@ Required properties when nvidia,suspend-mode=<0>:
   sleep mode, the warm boot code will restore some PLLs, clocks and then
   bring up CPU0 for resuming the system.
 
+Hardware-triggered thermal reset:
+On Tegra30, Tegra114 and Tegra124, if the 'i2c-thermtrip' subnode exists,
+hardware-triggered thermal reset will be enabled.
+
+Required properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'):
+- nvidia,i2c-controller-id : ID of I2C controller to send poweroff command to. Valid values are
+                             described in section 9.2.148 "APBDEV_PMC_SCRATCH53_0" of the
+                             Tegra K1 Technical Reference Manual.
+- nvidia,bus-addr : Bus address of the PMU on the I2C bus
+- nvidia,reg-addr : I2C register address to write poweroff command to
+- nvidia,reg-data : Poweroff command to write to PMU
+
+Optional properties for hardware-triggered thermal reset (inside 'i2c-thermtrip'):
+- nvidia,pinmux-id : Pinmux used by the hardware when issuing poweroff command.
+                     Defaults to 0. Valid values are described in section 12.5.2
+                     "Pinmux Support" of the Tegra4 Technical Reference Manual.
+
 Example:
 
 / SoC dts including file
@@ -68,6 +85,15 @@ pmc@7000f400 {
 
 / Tegra board dts file
 {
+       ...
+       pmc@7000f400 {
+               i2c-thermtrip {
+                       nvidia,i2c-controller-id = <4>;
+                       nvidia,bus-addr = <0x40>;
+                       nvidia,reg-addr = <0x36>;
+                       nvidia,reg-data = <0x2>;
+               };
+       };
        ...
        clocks {
                compatible = "simple-bus";
index 4eb540b..dbfaba0 100644 (file)
                nvidia,core-pwr-off-time = <61036>;
                nvidia,core-power-req-active-high;
                nvidia,sys-clock-req-active-high;
+
+               i2c-thermtrip {
+                       nvidia,i2c-controller-id = <4>;
+                       nvidia,bus-addr = <0x40>;
+                       nvidia,reg-addr = <0x36>;
+                       nvidia,reg-data = <0x2>;
+               };
        };
 
        /* Serial ATA */
index d0be9a1..5d1a318 100644 (file)
@@ -27,6 +27,7 @@ config ARCH_TEGRA_2x_SOC
        select PINCTRL_TEGRA20
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -37,6 +38,7 @@ config ARCH_TEGRA_3x_SOC
        select ARM_ERRATA_764369 if SMP
        select PINCTRL_TEGRA30
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T30 processor family, based on the
          ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -47,6 +49,7 @@ config ARCH_TEGRA_114_SOC
        select ARM_L1_CACHE_SHIFT_6
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA114
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T114 processor family, based on the
          ARM CortexA15MP CPU
@@ -56,6 +59,7 @@ config ARCH_TEGRA_124_SOC
        select ARM_L1_CACHE_SHIFT_6
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA124
+       select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T124 processor family, based on the
          ARM CortexA15MP CPU
index fc01ec2..c062b61 100644 (file)
@@ -47,6 +47,9 @@ config SUN5I_HSTIMER
        select CLKSRC_MMIO
        bool
 
+config TEGRA_TIMER
+       bool
+
 config VT8500_TIMER
        bool
 
index 94d90b2..ba9ebd8 100644 (file)
@@ -27,7 +27,7 @@ obj-$(CONFIG_ARCH_U300)               += timer-u300.o
 obj-$(CONFIG_SUN4I_TIMER)      += sun4i_timer.o
 obj-$(CONFIG_SUN5I_HSTIMER)    += timer-sun5i.o
 obj-$(CONFIG_MESON6_TIMER)     += meson6_timer.o
-obj-$(CONFIG_ARCH_TEGRA)       += tegra20_timer.o
+obj-$(CONFIG_TEGRA_TIMER)      += tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)     += vt8500_timer.o
 obj-$(CONFIG_ARCH_NSPIRE)      += zevio-timer.o
 obj-$(CONFIG_ARCH_BCM_MOBILE)  += bcm_kona_timer.o
index 011a336..c0d660f 100644 (file)
@@ -81,6 +81,7 @@ static const struct of_device_id car_match[] __initconst = {
        { .compatible = "nvidia,tegra30-car", },
        { .compatible = "nvidia,tegra114-car", },
        { .compatible = "nvidia,tegra124-car", },
+       { .compatible = "nvidia,tegra132-car", },
        {},
 };
 
index 8646fa9..4d2f71b 100644 (file)
@@ -56,7 +56,7 @@ struct tegra_fuse_info {
 
 static void __iomem *fuse_base;
 static struct clk *fuse_clk;
-static struct tegra_fuse_info *fuse_info;
+static const struct tegra_fuse_info *fuse_info;
 
 u32 tegra30_fuse_readl(const unsigned int offset)
 {
@@ -78,18 +78,18 @@ u32 tegra30_fuse_readl(const unsigned int offset)
        return val;
 }
 
-static struct tegra_fuse_info tegra30_info = {
+static const struct tegra_fuse_info tegra30_info = {
        .size                   = 0x2a4,
        .spare_bit              = 0x144,
        .speedo_idx             = SPEEDO_TEGRA30,
 };
 
-static struct tegra_fuse_info tegra114_info = {
+static const struct tegra_fuse_info tegra114_info = {
        .size                   = 0x2a0,
        .speedo_idx             = SPEEDO_TEGRA114,
 };
 
-static struct tegra_fuse_info tegra124_info = {
+static const struct tegra_fuse_info tegra124_info = {
        .size                   = 0x300,
        .speedo_idx             = SPEEDO_TEGRA124,
 };
@@ -182,6 +182,7 @@ static void __init legacy_fuse_init(void)
                fuse_info = &tegra114_info;
                break;
        case TEGRA124:
+       case TEGRA132:
                fuse_info = &tegra124_info;
                break;
        default:
index a2c0ceb..c956395 100644 (file)
 
 #define PMC_SCRATCH41                  0x140
 
+#define PMC_SENSOR_CTRL                        0x1b0
+#define PMC_SENSOR_CTRL_SCRATCH_WRITE  (1 << 2)
+#define PMC_SENSOR_CTRL_ENABLE_RST     (1 << 1)
+
 #define IO_DPD_REQ                     0x1b8
 #define  IO_DPD_REQ_CODE_IDLE          (0 << 30)
 #define  IO_DPD_REQ_CODE_OFF           (1 << 30)
 #define IO_DPD2_STATUS                 0x1c4
 #define SEL_DPD_TIM                    0x1c8
 
+#define PMC_SCRATCH54                  0x258
+#define PMC_SCRATCH54_DATA_SHIFT       8
+#define PMC_SCRATCH54_ADDR_SHIFT       0
+
+#define PMC_SCRATCH55                  0x25c
+#define PMC_SCRATCH55_RESET_TEGRA      (1 << 31)
+#define PMC_SCRATCH55_CNTRL_ID_SHIFT   27
+#define PMC_SCRATCH55_PINMUX_SHIFT     24
+#define PMC_SCRATCH55_16BITOP          (1 << 15)
+#define PMC_SCRATCH55_CHECKSUM_SHIFT   16
+#define PMC_SCRATCH55_I2CSLV1_SHIFT    0
+
 #define GPU_RG_CNTRL                   0x2d4
 
 struct tegra_pmc_soc {
@@ -88,6 +104,9 @@ struct tegra_pmc_soc {
        const char *const *powergates;
        unsigned int num_cpu_powergates;
        const u8 *cpu_powergates;
+
+       bool has_tsense_reset;
+       bool has_gpu_clamps;
 };
 
 /**
@@ -110,6 +129,7 @@ struct tegra_pmc_soc {
  * @powergates_lock: mutex for power gate register access
  */
 struct tegra_pmc {
+       struct device *dev;
        void __iomem *base;
        struct clk *clk;
 
@@ -225,11 +245,11 @@ int tegra_powergate_remove_clamping(int id)
                return -EINVAL;
 
        /*
-        * The Tegra124 GPU has a separate register (with different semantics)
-        * to remove clamps.
+        * On Tegra124 and later, the clamps for the GPU are controlled by a
+        * separate register (with different semantics).
         */
-       if (tegra_get_chip_id() == TEGRA124) {
-               if (id == TEGRA_POWERGATE_3D) {
+       if (id == TEGRA_POWERGATE_3D) {
+               if (pmc->soc->has_gpu_clamps) {
                        tegra_pmc_writel(0, GPU_RG_CNTRL);
                        return 0;
                }
@@ -703,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc)
        tegra_pmc_writel(value, PMC_CNTRL);
 }
 
+void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
+{
+       static const char disabled[] = "emergency thermal reset disabled";
+       u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux;
+       struct device *dev = pmc->dev;
+       struct device_node *np;
+       u32 value, checksum;
+
+       if (!pmc->soc->has_tsense_reset)
+               goto out;
+
+       np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip");
+       if (!np) {
+               dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
+               dev_err(dev, "I2C controller ID missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) {
+               dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,reg-addr", &reg_addr)) {
+               dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,reg-data", &reg_data)) {
+               dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled);
+               goto out;
+       }
+
+       if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux))
+               pinmux = 0;
+
+       value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+       value |= PMC_SENSOR_CTRL_SCRATCH_WRITE;
+       tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+       value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) |
+               (reg_addr << PMC_SCRATCH54_ADDR_SHIFT);
+       tegra_pmc_writel(value, PMC_SCRATCH54);
+
+       value = PMC_SCRATCH55_RESET_TEGRA;
+       value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT;
+       value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT;
+       value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT;
+
+       /*
+        * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will
+        * contain the checksum and are currently zero, so they are not added.
+        */
+       checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff)
+               + ((value >> 24) & 0xff);
+       checksum &= 0xff;
+       checksum = 0x100 - checksum;
+
+       value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT;
+
+       tegra_pmc_writel(value, PMC_SCRATCH55);
+
+       value = tegra_pmc_readl(PMC_SENSOR_CTRL);
+       value |= PMC_SENSOR_CTRL_ENABLE_RST;
+       tegra_pmc_writel(value, PMC_SENSOR_CTRL);
+
+       dev_info(pmc->dev, "emergency thermal reset enabled\n");
+
+out:
+       of_node_put(np);
+       return;
+}
+
 static int tegra_pmc_probe(struct platform_device *pdev)
 {
        void __iomem *base = pmc->base;
@@ -728,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev)
                return err;
        }
 
+       pmc->dev = &pdev->dev;
+
        tegra_pmc_init(pmc);
 
+       tegra_pmc_init_tsense_reset(pmc);
+
        if (IS_ENABLED(CONFIG_DEBUG_FS)) {
                err = tegra_powergate_debugfs_init();
                if (err < 0)
@@ -739,7 +840,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
 static int tegra_pmc_suspend(struct device *dev)
 {
        tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41);
@@ -753,10 +854,11 @@ static int tegra_pmc_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume);
 
+#endif
+
 static const char * const tegra20_powergates[] = {
        [TEGRA_POWERGATE_CPU] = "cpu",
        [TEGRA_POWERGATE_3D] = "3d",
@@ -772,6 +874,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
        .powergates = tegra20_powergates,
        .num_cpu_powergates = 0,
        .cpu_powergates = NULL,
+       .has_tsense_reset = false,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra30_powergates[] = {
@@ -803,6 +907,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
        .powergates = tegra30_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates),
        .cpu_powergates = tegra30_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra114_powergates[] = {
@@ -838,6 +944,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
        .powergates = tegra114_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates),
        .cpu_powergates = tegra114_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = false,
 };
 
 static const char * const tegra124_powergates[] = {
@@ -879,6 +987,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
        .powergates = tegra124_powergates,
        .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates),
        .cpu_powergates = tegra124_cpu_powergates,
+       .has_tsense_reset = true,
+       .has_gpu_clamps = true,
 };
 
 static const struct of_device_id tegra_pmc_match[] = {
@@ -894,7 +1004,9 @@ static struct platform_driver tegra_pmc_driver = {
                .name = "tegra-pmc",
                .suppress_bind_attrs = true,
                .of_match_table = tegra_pmc_match,
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
                .pm = &tegra_pmc_pm_ops,
+#endif
        },
        .probe = tegra_pmc_probe,
 };
index 8e12494..b5f7b5f 100644 (file)
@@ -21,6 +21,7 @@
 #define TEGRA30                0x30
 #define TEGRA114       0x35
 #define TEGRA124       0x40
+#define TEGRA132       0x13
 
 #define TEGRA_FUSE_SKU_CALIB_0 0xf0
 #define TEGRA30_FUSE_SATA_CALIB        0x124
index 30fe207..0390910 100644 (file)
@@ -17,7 +17,7 @@ enum tegra_suspend_mode {
        TEGRA_MAX_SUSPEND_MODE,
 };
 
-#ifdef CONFIG_PM_SLEEP
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM)
 enum tegra_suspend_mode
 tegra_pm_validate_suspend_mode(enum tegra_suspend_mode mode);