diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/clocksource/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/clocksource/Makefile | 2 | ||||
| -rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra.c | 1 | ||||
| -rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra30.c | 9 | ||||
| -rw-r--r-- | drivers/soc/tegra/pmc.c | 124 |
5 files changed, 128 insertions, 11 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index fc01ec27d3c8..c062b6105d49 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
| @@ -47,6 +47,9 @@ config SUN5I_HSTIMER | |||
| 47 | select CLKSRC_MMIO | 47 | select CLKSRC_MMIO |
| 48 | bool | 48 | bool |
| 49 | 49 | ||
| 50 | config TEGRA_TIMER | ||
| 51 | bool | ||
| 52 | |||
| 50 | config VT8500_TIMER | 53 | config VT8500_TIMER |
| 51 | bool | 54 | bool |
| 52 | 55 | ||
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 94d90b24b56b..ba9ebd868ec5 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
| @@ -27,7 +27,7 @@ obj-$(CONFIG_ARCH_U300) += timer-u300.o | |||
| 27 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o | 27 | obj-$(CONFIG_SUN4I_TIMER) += sun4i_timer.o |
| 28 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o | 28 | obj-$(CONFIG_SUN5I_HSTIMER) += timer-sun5i.o |
| 29 | obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o | 29 | obj-$(CONFIG_MESON6_TIMER) += meson6_timer.o |
| 30 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 30 | obj-$(CONFIG_TEGRA_TIMER) += tegra20_timer.o |
| 31 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 31 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
| 32 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o | 32 | obj-$(CONFIG_ARCH_NSPIRE) += zevio-timer.o |
| 33 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o | 33 | obj-$(CONFIG_ARCH_BCM_MOBILE) += bcm_kona_timer.o |
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 011a3363c265..c0d660f1aaac 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c | |||
| @@ -81,6 +81,7 @@ static const struct of_device_id car_match[] __initconst = { | |||
| 81 | { .compatible = "nvidia,tegra30-car", }, | 81 | { .compatible = "nvidia,tegra30-car", }, |
| 82 | { .compatible = "nvidia,tegra114-car", }, | 82 | { .compatible = "nvidia,tegra114-car", }, |
| 83 | { .compatible = "nvidia,tegra124-car", }, | 83 | { .compatible = "nvidia,tegra124-car", }, |
| 84 | { .compatible = "nvidia,tegra132-car", }, | ||
| 84 | {}, | 85 | {}, |
| 85 | }; | 86 | }; |
| 86 | 87 | ||
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index 8646fa920d8d..4d2f71bf65c5 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c | |||
| @@ -56,7 +56,7 @@ struct tegra_fuse_info { | |||
| 56 | 56 | ||
| 57 | static void __iomem *fuse_base; | 57 | static void __iomem *fuse_base; |
| 58 | static struct clk *fuse_clk; | 58 | static struct clk *fuse_clk; |
| 59 | static struct tegra_fuse_info *fuse_info; | 59 | static const struct tegra_fuse_info *fuse_info; |
| 60 | 60 | ||
| 61 | u32 tegra30_fuse_readl(const unsigned int offset) | 61 | u32 tegra30_fuse_readl(const unsigned int offset) |
| 62 | { | 62 | { |
| @@ -78,18 +78,18 @@ u32 tegra30_fuse_readl(const unsigned int offset) | |||
| 78 | return val; | 78 | return val; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static struct tegra_fuse_info tegra30_info = { | 81 | static const struct tegra_fuse_info tegra30_info = { |
| 82 | .size = 0x2a4, | 82 | .size = 0x2a4, |
| 83 | .spare_bit = 0x144, | 83 | .spare_bit = 0x144, |
| 84 | .speedo_idx = SPEEDO_TEGRA30, | 84 | .speedo_idx = SPEEDO_TEGRA30, |
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | static struct tegra_fuse_info tegra114_info = { | 87 | static const struct tegra_fuse_info tegra114_info = { |
| 88 | .size = 0x2a0, | 88 | .size = 0x2a0, |
| 89 | .speedo_idx = SPEEDO_TEGRA114, | 89 | .speedo_idx = SPEEDO_TEGRA114, |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | static struct tegra_fuse_info tegra124_info = { | 92 | static const struct tegra_fuse_info tegra124_info = { |
| 93 | .size = 0x300, | 93 | .size = 0x300, |
| 94 | .speedo_idx = SPEEDO_TEGRA124, | 94 | .speedo_idx = SPEEDO_TEGRA124, |
| 95 | }; | 95 | }; |
| @@ -182,6 +182,7 @@ static void __init legacy_fuse_init(void) | |||
| 182 | fuse_info = &tegra114_info; | 182 | fuse_info = &tegra114_info; |
| 183 | break; | 183 | break; |
| 184 | case TEGRA124: | 184 | case TEGRA124: |
| 185 | case TEGRA132: | ||
| 185 | fuse_info = &tegra124_info; | 186 | fuse_info = &tegra124_info; |
| 186 | break; | 187 | break; |
| 187 | default: | 188 | default: |
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index a2c0ceb95f8f..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 { |
| @@ -88,6 +104,9 @@ struct tegra_pmc_soc { | |||
| 88 | const char *const *powergates; | 104 | const char *const *powergates; |
| 89 | unsigned int num_cpu_powergates; | 105 | unsigned int num_cpu_powergates; |
| 90 | const u8 *cpu_powergates; | 106 | const u8 *cpu_powergates; |
| 107 | |||
| 108 | bool has_tsense_reset; | ||
| 109 | bool has_gpu_clamps; | ||
| 91 | }; | 110 | }; |
| 92 | 111 | ||
| 93 | /** | 112 | /** |
| @@ -110,6 +129,7 @@ struct tegra_pmc_soc { | |||
| 110 | * @powergates_lock: mutex for power gate register access | 129 | * @powergates_lock: mutex for power gate register access |
| 111 | */ | 130 | */ |
| 112 | struct tegra_pmc { | 131 | struct tegra_pmc { |
| 132 | struct device *dev; | ||
| 113 | void __iomem *base; | 133 | void __iomem *base; |
| 114 | struct clk *clk; | 134 | struct clk *clk; |
| 115 | 135 | ||
| @@ -225,11 +245,11 @@ int tegra_powergate_remove_clamping(int id) | |||
| 225 | return -EINVAL; | 245 | return -EINVAL; |
| 226 | 246 | ||
| 227 | /* | 247 | /* |
| 228 | * The Tegra124 GPU has a separate register (with different semantics) | 248 | * On Tegra124 and later, the clamps for the GPU are controlled by a |
| 229 | * to remove clamps. | 249 | * separate register (with different semantics). |
| 230 | */ | 250 | */ |
| 231 | if (tegra_get_chip_id() == TEGRA124) { | 251 | if (id == TEGRA_POWERGATE_3D) { |
| 232 | if (id == TEGRA_POWERGATE_3D) { | 252 | if (pmc->soc->has_gpu_clamps) { |
| 233 | tegra_pmc_writel(0, GPU_RG_CNTRL); | 253 | tegra_pmc_writel(0, GPU_RG_CNTRL); |
| 234 | return 0; | 254 | return 0; |
| 235 | } | 255 | } |
| @@ -703,6 +723,83 @@ static void tegra_pmc_init(struct tegra_pmc *pmc) | |||
| 703 | tegra_pmc_writel(value, PMC_CNTRL); | 723 | tegra_pmc_writel(value, PMC_CNTRL); |
| 704 | } | 724 | } |
| 705 | 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 | |||
| 706 | static int tegra_pmc_probe(struct platform_device *pdev) | 803 | static int tegra_pmc_probe(struct platform_device *pdev) |
| 707 | { | 804 | { |
| 708 | void __iomem *base = pmc->base; | 805 | void __iomem *base = pmc->base; |
| @@ -728,8 +825,12 @@ static int tegra_pmc_probe(struct platform_device *pdev) | |||
| 728 | return err; | 825 | return err; |
| 729 | } | 826 | } |
| 730 | 827 | ||
| 828 | pmc->dev = &pdev->dev; | ||
| 829 | |||
| 731 | tegra_pmc_init(pmc); | 830 | tegra_pmc_init(pmc); |
| 732 | 831 | ||
| 832 | tegra_pmc_init_tsense_reset(pmc); | ||
| 833 | |||
| 733 | if (IS_ENABLED(CONFIG_DEBUG_FS)) { | 834 | if (IS_ENABLED(CONFIG_DEBUG_FS)) { |
| 734 | err = tegra_powergate_debugfs_init(); | 835 | err = tegra_powergate_debugfs_init(); |
| 735 | if (err < 0) | 836 | if (err < 0) |
| @@ -739,7 +840,7 @@ static int tegra_pmc_probe(struct platform_device *pdev) | |||
| 739 | return 0; | 840 | return 0; |
| 740 | } | 841 | } |
| 741 | 842 | ||
| 742 | #ifdef CONFIG_PM_SLEEP | 843 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) |
| 743 | static int tegra_pmc_suspend(struct device *dev) | 844 | static int tegra_pmc_suspend(struct device *dev) |
| 744 | { | 845 | { |
| 745 | tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); | 846 | tegra_pmc_writel(virt_to_phys(tegra_resume), PMC_SCRATCH41); |
| @@ -753,10 +854,11 @@ static int tegra_pmc_resume(struct device *dev) | |||
| 753 | 854 | ||
| 754 | return 0; | 855 | return 0; |
| 755 | } | 856 | } |
| 756 | #endif | ||
| 757 | 857 | ||
| 758 | static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume); | 858 | static SIMPLE_DEV_PM_OPS(tegra_pmc_pm_ops, tegra_pmc_suspend, tegra_pmc_resume); |
| 759 | 859 | ||
| 860 | #endif | ||
| 861 | |||
| 760 | static const char * const tegra20_powergates[] = { | 862 | static const char * const tegra20_powergates[] = { |
| 761 | [TEGRA_POWERGATE_CPU] = "cpu", | 863 | [TEGRA_POWERGATE_CPU] = "cpu", |
| 762 | [TEGRA_POWERGATE_3D] = "3d", | 864 | [TEGRA_POWERGATE_3D] = "3d", |
| @@ -772,6 +874,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { | |||
| 772 | .powergates = tegra20_powergates, | 874 | .powergates = tegra20_powergates, |
| 773 | .num_cpu_powergates = 0, | 875 | .num_cpu_powergates = 0, |
| 774 | .cpu_powergates = NULL, | 876 | .cpu_powergates = NULL, |
| 877 | .has_tsense_reset = false, | ||
| 878 | .has_gpu_clamps = false, | ||
| 775 | }; | 879 | }; |
| 776 | 880 | ||
| 777 | static const char * const tegra30_powergates[] = { | 881 | static const char * const tegra30_powergates[] = { |
| @@ -803,6 +907,8 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { | |||
| 803 | .powergates = tegra30_powergates, | 907 | .powergates = tegra30_powergates, |
| 804 | .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), | 908 | .num_cpu_powergates = ARRAY_SIZE(tegra30_cpu_powergates), |
| 805 | .cpu_powergates = tegra30_cpu_powergates, | 909 | .cpu_powergates = tegra30_cpu_powergates, |
| 910 | .has_tsense_reset = true, | ||
| 911 | .has_gpu_clamps = false, | ||
| 806 | }; | 912 | }; |
| 807 | 913 | ||
| 808 | static const char * const tegra114_powergates[] = { | 914 | static const char * const tegra114_powergates[] = { |
| @@ -838,6 +944,8 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { | |||
| 838 | .powergates = tegra114_powergates, | 944 | .powergates = tegra114_powergates, |
| 839 | .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), | 945 | .num_cpu_powergates = ARRAY_SIZE(tegra114_cpu_powergates), |
| 840 | .cpu_powergates = tegra114_cpu_powergates, | 946 | .cpu_powergates = tegra114_cpu_powergates, |
| 947 | .has_tsense_reset = true, | ||
| 948 | .has_gpu_clamps = false, | ||
| 841 | }; | 949 | }; |
| 842 | 950 | ||
| 843 | static const char * const tegra124_powergates[] = { | 951 | static const char * const tegra124_powergates[] = { |
| @@ -879,6 +987,8 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { | |||
| 879 | .powergates = tegra124_powergates, | 987 | .powergates = tegra124_powergates, |
| 880 | .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), | 988 | .num_cpu_powergates = ARRAY_SIZE(tegra124_cpu_powergates), |
| 881 | .cpu_powergates = tegra124_cpu_powergates, | 989 | .cpu_powergates = tegra124_cpu_powergates, |
| 990 | .has_tsense_reset = true, | ||
| 991 | .has_gpu_clamps = true, | ||
| 882 | }; | 992 | }; |
| 883 | 993 | ||
| 884 | static const struct of_device_id tegra_pmc_match[] = { | 994 | static const struct of_device_id tegra_pmc_match[] = { |
| @@ -894,7 +1004,9 @@ static struct platform_driver tegra_pmc_driver = { | |||
| 894 | .name = "tegra-pmc", | 1004 | .name = "tegra-pmc", |
| 895 | .suppress_bind_attrs = true, | 1005 | .suppress_bind_attrs = true, |
| 896 | .of_match_table = tegra_pmc_match, | 1006 | .of_match_table = tegra_pmc_match, |
| 1007 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) | ||
| 897 | .pm = &tegra_pmc_pm_ops, | 1008 | .pm = &tegra_pmc_pm_ops, |
| 1009 | #endif | ||
| 898 | }, | 1010 | }, |
| 899 | .probe = tegra_pmc_probe, | 1011 | .probe = tegra_pmc_probe, |
| 900 | }; | 1012 | }; |
