diff options
-rw-r--r-- | drivers/soc/tegra/pmc.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 0f096e76574a..c956395cf46f 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c | |||
@@ -70,6 +70,10 @@ | |||
70 | 70 | ||
71 | #define PMC_SCRATCH41 0x140 | 71 | #define PMC_SCRATCH41 0x140 |
72 | 72 | ||
73 | #define PMC_SENSOR_CTRL 0x1b0 | ||
74 | #define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2) | ||
75 | #define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1) | ||
76 | |||
73 | #define IO_DPD_REQ 0x1b8 | 77 | #define IO_DPD_REQ 0x1b8 |
74 | #define IO_DPD_REQ_CODE_IDLE (0 << 30) | 78 | #define IO_DPD_REQ_CODE_IDLE (0 << 30) |
75 | #define IO_DPD_REQ_CODE_OFF (1 << 30) | 79 | #define IO_DPD_REQ_CODE_OFF (1 << 30) |
@@ -81,6 +85,18 @@ | |||
81 | #define IO_DPD2_STATUS 0x1c4 | 85 | #define IO_DPD2_STATUS 0x1c4 |
82 | #define SEL_DPD_TIM 0x1c8 | 86 | #define SEL_DPD_TIM 0x1c8 |
83 | 87 | ||
88 | #define PMC_SCRATCH54 0x258 | ||
89 | #define PMC_SCRATCH54_DATA_SHIFT 8 | ||
90 | #define PMC_SCRATCH54_ADDR_SHIFT 0 | ||
91 | |||
92 | #define PMC_SCRATCH55 0x25c | ||
93 | #define PMC_SCRATCH55_RESET_TEGRA (1 << 31) | ||
94 | #define PMC_SCRATCH55_CNTRL_ID_SHIFT 27 | ||
95 | #define PMC_SCRATCH55_PINMUX_SHIFT 24 | ||
96 | #define PMC_SCRATCH55_16BITOP (1 << 15) | ||
97 | #define PMC_SCRATCH55_CHECKSUM_SHIFT 16 | ||
98 | #define PMC_SCRATCH55_I2CSLV1_SHIFT 0 | ||
99 | |||
84 | #define GPU_RG_CNTRL 0x2d4 | 100 | #define GPU_RG_CNTRL 0x2d4 |
85 | 101 | ||
86 | struct tegra_pmc_soc { | 102 | struct tegra_pmc_soc { |
@@ -89,6 +105,7 @@ struct tegra_pmc_soc { | |||
89 | unsigned int num_cpu_powergates; | 105 | unsigned int num_cpu_powergates; |
90 | const u8 *cpu_powergates; | 106 | const u8 *cpu_powergates; |
91 | 107 | ||
108 | bool has_tsense_reset; | ||
92 | bool has_gpu_clamps; | 109 | bool has_gpu_clamps; |
93 | }; | 110 | }; |
94 | 111 | ||
@@ -112,6 +129,7 @@ struct tegra_pmc_soc { | |||
112 | * @powergates_lock: mutex for power gate register access | 129 | * @powergates_lock: mutex for power gate register access |
113 | */ | 130 | */ |
114 | struct tegra_pmc { | 131 | struct tegra_pmc { |
132 | struct device *dev; | ||
115 | void __iomem *base; | 133 | void __iomem *base; |
116 | struct clk *clk; | 134 | struct clk *clk; |
117 | 135 | ||
@@ -705,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc) | |||
705 | tegra_pmc_writel(value, PMC_CNTRL); | 723 | tegra_pmc_writel(value, PMC_CNTRL); |
706 | } | 724 | } |
707 | 725 | ||
726 | void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) | ||
727 | { | ||
728 | static const char disabled[] = "emergency thermal reset disabled"; | ||
729 | u32 pmu_addr, ctrl_id, reg_addr, reg_data, pinmux; | ||
730 | struct device *dev = pmc->dev; | ||
731 | struct device_node *np; | ||
732 | u32 value, checksum; | ||
733 | |||
734 | if (!pmc->soc->has_tsense_reset) | ||
735 | goto out; | ||
736 | |||
737 | np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); | ||
738 | if (!np) { | ||
739 | dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); | ||
740 | goto out; | ||
741 | } | ||
742 | |||
743 | if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) { | ||
744 | dev_err(dev, "I2C controller ID missing, %s.\n", disabled); | ||
745 | goto out; | ||
746 | } | ||
747 | |||
748 | if (of_property_read_u32(np, "nvidia,bus-addr", &pmu_addr)) { | ||
749 | dev_err(dev, "nvidia,bus-addr missing, %s.\n", disabled); | ||
750 | goto out; | ||
751 | } | ||
752 | |||
753 | if (of_property_read_u32(np, "nvidia,reg-addr", ®_addr)) { | ||
754 | dev_err(dev, "nvidia,reg-addr missing, %s.\n", disabled); | ||
755 | goto out; | ||
756 | } | ||
757 | |||
758 | if (of_property_read_u32(np, "nvidia,reg-data", ®_data)) { | ||
759 | dev_err(dev, "nvidia,reg-data missing, %s.\n", disabled); | ||
760 | goto out; | ||
761 | } | ||
762 | |||
763 | if (of_property_read_u32(np, "nvidia,pinmux-id", &pinmux)) | ||
764 | pinmux = 0; | ||
765 | |||
766 | value = tegra_pmc_readl(PMC_SENSOR_CTRL); | ||
767 | value |= PMC_SENSOR_CTRL_SCRATCH_WRITE; | ||
768 | tegra_pmc_writel(value, PMC_SENSOR_CTRL); | ||
769 | |||
770 | value = (reg_data << PMC_SCRATCH54_DATA_SHIFT) | | ||
771 | (reg_addr << PMC_SCRATCH54_ADDR_SHIFT); | ||
772 | tegra_pmc_writel(value, PMC_SCRATCH54); | ||
773 | |||
774 | value = PMC_SCRATCH55_RESET_TEGRA; | ||
775 | value |= ctrl_id << PMC_SCRATCH55_CNTRL_ID_SHIFT; | ||
776 | value |= pinmux << PMC_SCRATCH55_PINMUX_SHIFT; | ||
777 | value |= pmu_addr << PMC_SCRATCH55_I2CSLV1_SHIFT; | ||
778 | |||
779 | /* | ||
780 | * Calculate checksum of SCRATCH54, SCRATCH55 fields. Bits 23:16 will | ||
781 | * contain the checksum and are currently zero, so they are not added. | ||
782 | */ | ||
783 | checksum = reg_addr + reg_data + (value & 0xff) + ((value >> 8) & 0xff) | ||
784 | + ((value >> 24) & 0xff); | ||
785 | checksum &= 0xff; | ||
786 | checksum = 0x100 - checksum; | ||
787 | |||
788 | value |= checksum << PMC_SCRATCH55_CHECKSUM_SHIFT; | ||
789 | |||
790 | tegra_pmc_writel(value, PMC_SCRATCH55); | ||
791 | |||
792 | value = tegra_pmc_readl(PMC_SENSOR_CTRL); | ||
793 | value |= PMC_SENSOR_CTRL_ENABLE_RST; | ||
794 | tegra_pmc_writel(value, PMC_SENSOR_CTRL); | ||
795 | |||
796 | dev_info(pmc->dev, "emergency thermal reset enabled\n"); | ||
797 | |||
798 | out: | ||
799 | of_node_put(np); | ||
800 | return; | ||
801 | } | ||
802 | |||
708 | static int tegra_pmc_probe(struct platform_device *pdev) | 803 | static int tegra_pmc_probe(struct platform_device *pdev) |
709 | { | 804 | { |
710 | void __iomem *base = pmc->base; | 805 | void __iomem *base = pmc->base; |
@@ -730,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev) | |||
730 | return err; | 825 | return err; |
731 | } | 826 | } |
732 | 827 | ||
828 | pmc->dev = &pdev->dev; | ||
829 | |||
733 | tegra_pmc_init(pmc); | 830 | tegra_pmc_init(pmc); |
734 | 831 | ||
832 | tegra_pmc_init_tsense_reset(pmc); | ||
833 | |||
735 | if (IS_ENABLED(CONFIG_DEBUG_FS)) { | 834 | if (IS_ENABLED(CONFIG_DEBUG_FS)) { |
736 | err = tegra_powergate_debugfs_init(); | 835 | err = tegra_powergate_debugfs_init(); |
737 | if (err < 0) | 836 | if (err < 0) |
@@ -775,6 +874,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { | |||
775 | .powergates = tegra20_powergates, | 874 | .powergates = tegra20_powergates, |
776 | .num_cpu_powergates = 0, | 875 | .num_cpu_powergates = 0, |
777 | .cpu_powergates = NULL, | 876 | .cpu_powergates = NULL, |
877 | .has_tsense_reset = false, | ||
778 | .has_gpu_clamps = false, | 878 | .has_gpu_clamps = false, |
779 | }; | 879 | }; |
780 | 880 | ||
@@ -807,6 +907,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { | |||
807 | .powergates = tegra30_powergates, | 907 | .powergates = tegra30_powergates, |
808 | .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), | 908 | .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), |
809 | .cpu_powergates = tegra30_cpu_powergates, | 909 | .cpu_powergates = tegra30_cpu_powergates, |
910 | .has_tsense_reset = true, | ||
810 | .has_gpu_clamps = false, | 911 | .has_gpu_clamps = false, |
811 | }; | 912 | }; |
812 | 913 | ||
@@ -843,6 +944,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { | |||
843 | .powergates = tegra114_powergates, | 944 | .powergates = tegra114_powergates, |
844 | .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), | 945 | .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), |
845 | .cpu_powergates = tegra114_cpu_powergates, | 946 | .cpu_powergates = tegra114_cpu_powergates, |
947 | .has_tsense_reset = true, | ||
846 | .has_gpu_clamps = false, | 948 | .has_gpu_clamps = false, |
847 | }; | 949 | }; |
848 | 950 | ||
@@ -885,6 +987,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { | |||
885 | .powergates = tegra124_powergates, | 987 | .powergates = tegra124_powergates, |
886 | .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), | 988 | .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), |
887 | .cpu_powergates = tegra124_cpu_powergates, | 989 | .cpu_powergates = tegra124_cpu_powergates, |
990 | .has_tsense_reset = true, | ||
888 | .has_gpu_clamps = true, | 991 | .has_gpu_clamps = true, |
889 | }; | 992 | }; |
890 | 993 | ||