^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Broadcom BCM2835 SoC temperature sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2016 Martin Sperl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "../thermal_hwmon.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define BCM2835_TS_TSENSCTL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define BCM2835_TS_TSENSSTAT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define BCM2835_TS_TSENSCTL_PRWDW BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define BCM2835_TS_TSENSCTL_RSTB BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * bandgap reference voltage in 6 mV increments
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define BCM2835_TS_TSENSCTL_CTRL_BITS 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define BCM2835_TS_TSENSCTL_CTRL_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define BCM2835_TS_TSENSCTL_CTRL_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) BCM2835_TS_TSENSCTL_CTRL_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define BCM2835_TS_TSENSCTL_CTRL_DEFAULT 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define BCM2835_TS_TSENSCTL_EN_INT BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define BCM2835_TS_TSENSCTL_DIRECT BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define BCM2835_TS_TSENSCTL_CLR_INT BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define BCM2835_TS_TSENSCTL_THOLD_SHIFT 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define BCM2835_TS_TSENSCTL_THOLD_BITS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define BCM2835_TS_TSENSCTL_THOLD_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) BCM2835_TS_TSENSCTL_THOLD_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * time how long the block to be asserted in reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * which based on a clock counter (TSENS clock assumed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT 18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define BCM2835_TS_TSENSCTL_RSTDELAY_BITS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define BCM2835_TS_TSENSCTL_REGULEN BIT(26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define BCM2835_TS_TSENSSTAT_DATA_BITS 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define BCM2835_TS_TSENSSTAT_DATA_SHIFT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define BCM2835_TS_TSENSSTAT_DATA_MASK \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) BCM2835_TS_TSENSSTAT_DATA_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define BCM2835_TS_TSENSSTAT_VALID BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define BCM2835_TS_TSENSSTAT_INTERRUPT BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct bcm2835_thermal_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct thermal_zone_device *tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) void __iomem *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) struct dentry *debugfsdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return offset + slope * adc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) temp -= offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) temp /= slope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (temp < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int bcm2835_thermal_get_temp(void *d, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct bcm2835_thermal_data *data = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (!(val & BCM2835_TS_TSENSSTAT_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *temp = bcm2835_thermal_adc2temp(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) thermal_zone_get_offset(data->tz),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) thermal_zone_get_slope(data->tz));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .name = "ctl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .offset = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) .name = "stat",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) .offset = 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static void bcm2835_thermal_debugfs(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) struct debugfs_regset32 *regset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (!regset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) regset->regs = bcm2835_thermal_regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) regset->base = data->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) static const struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .get_temp = bcm2835_thermal_get_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Note: as per Raspberry Foundation FAQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * the recommended temperature range for the SoC -40C to +85C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * so the trip limit is set to 80C.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * this applies to all the BCM283X SoC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) static const struct of_device_id bcm2835_thermal_of_match_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .compatible = "brcm,bcm2835-thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) .compatible = "brcm,bcm2836-thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) .compatible = "brcm,bcm2837-thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) static int bcm2835_thermal_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) const struct of_device_id *match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct thermal_zone_device *tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct bcm2835_thermal_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) unsigned long rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (!data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) match = of_match_device(bcm2835_thermal_of_match_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) &pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (!match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) data->regs = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (IS_ERR(data->regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) err = PTR_ERR(data->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) dev_err(&pdev->dev, "Could not get registers: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) data->clk = devm_clk_get(&pdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (IS_ERR(data->clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) err = PTR_ERR(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (err != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) dev_err(&pdev->dev, "Could not get clk: %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) err = clk_prepare_enable(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) rate = clk_get_rate(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if ((rate < 1920000) || (rate > 5000000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) dev_warn(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) "Clock %pCn running at %lu Hz is outside of the recommended range: 1.92 to 5MHz\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) data->clk, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* register of thermal sensor and get info from DT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) &bcm2835_thermal_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (IS_ERR(tz)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) err = PTR_ERR(tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) "Failed to register the thermal device: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) goto err_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * right now the FW does set up the HW-block, so we are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * touching the configuration registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * But if the HW is not enabled, then set it up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * using "sane" values used by the firmware right now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) val = readl(data->regs + BCM2835_TS_TSENSCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int trip_temp, offset, slope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) slope = thermal_zone_get_slope(tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) offset = thermal_zone_get_offset(tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * For now we deal only with critical, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * would need to iterate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) "Not able to read trip_temp: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) goto err_tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* set bandgap reference voltage and enable voltage regulator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) BCM2835_TS_TSENSCTL_REGULEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* use the recommended reset duration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* trip_adc value from info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) val |= bcm2835_thermal_temp2adc(trip_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) slope)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) /* write the value back to the register as 2 steps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) writel(val, data->regs + BCM2835_TS_TSENSCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) val |= BCM2835_TS_TSENSCTL_RSTB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) writel(val, data->regs + BCM2835_TS_TSENSCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) data->tz = tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) platform_set_drvdata(pdev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * Thermal_zone doesn't enable hwmon as default,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * enable it here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) tz->tzp->no_hwmon = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) err = thermal_add_hwmon_sysfs(tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) goto err_tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) bcm2835_thermal_debugfs(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) err_tz:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) thermal_zone_of_sensor_unregister(&pdev->dev, tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) err_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) clk_disable_unprepare(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static int bcm2835_thermal_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct bcm2835_thermal_data *data = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) struct thermal_zone_device *tz = data->tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) debugfs_remove_recursive(data->debugfsdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) thermal_zone_of_sensor_unregister(&pdev->dev, tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) clk_disable_unprepare(data->clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static struct platform_driver bcm2835_thermal_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .probe = bcm2835_thermal_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) .remove = bcm2835_thermal_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .name = "bcm2835_thermal",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) .of_match_table = bcm2835_thermal_of_match_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) module_platform_driver(bcm2835_thermal_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) MODULE_AUTHOR("Martin Sperl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) MODULE_LICENSE("GPL");