0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/err.h>
0009 #include <linux/init.h>
0010 #include <linux/io.h>
0011 #include <linux/kernel.h>
0012 #include <linux/module.h>
0013 #include <linux/of.h>
0014 #include <linux/of_platform.h>
0015 #include <linux/pm_runtime.h>
0016 #include <linux/thermal.h>
0017 #include <linux/types.h>
0018
0019 #include "thermal_hwmon.h"
0020
0021 #define K3_VTM_DEVINFO_PWR0_OFFSET 0x4
0022 #define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK 0xf0
0023 #define K3_VTM_TMPSENS0_CTRL_OFFSET 0x80
0024 #define K3_VTM_REGS_PER_TS 0x10
0025 #define K3_VTM_TS_STAT_DTEMP_MASK 0x3ff
0026 #define K3_VTM_TMPSENS_CTRL_CBIASSEL BIT(0)
0027 #define K3_VTM_TMPSENS_CTRL_SOC BIT(5)
0028 #define K3_VTM_TMPSENS_CTRL_CLRZ BIT(6)
0029 #define K3_VTM_TMPSENS_CTRL_CLKON_REQ BIT(7)
0030
0031 #define K3_VTM_ADC_BEGIN_VAL 540
0032 #define K3_VTM_ADC_END_VAL 944
0033
0034 static const int k3_adc_to_temp[] = {
0035 -40000, -40000, -40000, -40000, -39800, -39400, -39000, -38600, -38200,
0036 -37800, -37400, -37000, -36600, -36200, -35800, -35300, -34700, -34200,
0037 -33800, -33400, -33000, -32600, -32200, -31800, -31400, -31000, -30600,
0038 -30200, -29800, -29400, -29000, -28600, -28200, -27700, -27100, -26600,
0039 -26200, -25800, -25400, -25000, -24600, -24200, -23800, -23400, -23000,
0040 -22600, -22200, -21800, -21400, -21000, -20500, -19900, -19400, -19000,
0041 -18600, -18200, -17800, -17400, -17000, -16600, -16200, -15800, -15400,
0042 -15000, -14600, -14200, -13800, -13400, -13000, -12500, -11900, -11400,
0043 -11000, -10600, -10200, -9800, -9400, -9000, -8600, -8200, -7800, -7400,
0044 -7000, -6600, -6200, -5800, -5400, -5000, -4500, -3900, -3400, -3000,
0045 -2600, -2200, -1800, -1400, -1000, -600, -200, 200, 600, 1000, 1400,
0046 1800, 2200, 2600, 3000, 3400, 3900, 4500, 5000, 5400, 5800, 6200, 6600,
0047 7000, 7400, 7800, 8200, 8600, 9000, 9400, 9800, 10200, 10600, 11000,
0048 11400, 11800, 12200, 12700, 13300, 13800, 14200, 14600, 15000, 15400,
0049 15800, 16200, 16600, 17000, 17400, 17800, 18200, 18600, 19000, 19400,
0050 19800, 20200, 20600, 21000, 21400, 21900, 22500, 23000, 23400, 23800,
0051 24200, 24600, 25000, 25400, 25800, 26200, 26600, 27000, 27400, 27800,
0052 28200, 28600, 29000, 29400, 29800, 30200, 30600, 31000, 31400, 31900,
0053 32500, 33000, 33400, 33800, 34200, 34600, 35000, 35400, 35800, 36200,
0054 36600, 37000, 37400, 37800, 38200, 38600, 39000, 39400, 39800, 40200,
0055 40600, 41000, 41400, 41800, 42200, 42600, 43100, 43700, 44200, 44600,
0056 45000, 45400, 45800, 46200, 46600, 47000, 47400, 47800, 48200, 48600,
0057 49000, 49400, 49800, 50200, 50600, 51000, 51400, 51800, 52200, 52600,
0058 53000, 53400, 53800, 54200, 54600, 55000, 55400, 55900, 56500, 57000,
0059 57400, 57800, 58200, 58600, 59000, 59400, 59800, 60200, 60600, 61000,
0060 61400, 61800, 62200, 62600, 63000, 63400, 63800, 64200, 64600, 65000,
0061 65400, 65800, 66200, 66600, 67000, 67400, 67800, 68200, 68600, 69000,
0062 69400, 69800, 70200, 70600, 71000, 71500, 72100, 72600, 73000, 73400,
0063 73800, 74200, 74600, 75000, 75400, 75800, 76200, 76600, 77000, 77400,
0064 77800, 78200, 78600, 79000, 79400, 79800, 80200, 80600, 81000, 81400,
0065 81800, 82200, 82600, 83000, 83400, 83800, 84200, 84600, 85000, 85400,
0066 85800, 86200, 86600, 87000, 87400, 87800, 88200, 88600, 89000, 89400,
0067 89800, 90200, 90600, 91000, 91400, 91800, 92200, 92600, 93000, 93400,
0068 93800, 94200, 94600, 95000, 95400, 95800, 96200, 96600, 97000, 97500,
0069 98100, 98600, 99000, 99400, 99800, 100200, 100600, 101000, 101400,
0070 101800, 102200, 102600, 103000, 103400, 103800, 104200, 104600, 105000,
0071 105400, 105800, 106200, 106600, 107000, 107400, 107800, 108200, 108600,
0072 109000, 109400, 109800, 110200, 110600, 111000, 111400, 111800, 112200,
0073 112600, 113000, 113400, 113800, 114200, 114600, 115000, 115400, 115800,
0074 116200, 116600, 117000, 117400, 117800, 118200, 118600, 119000, 119400,
0075 119800, 120200, 120600, 121000, 121400, 121800, 122200, 122600, 123000,
0076 123400, 123800, 124200, 124600, 124900, 125000,
0077 };
0078
0079 struct k3_bandgap {
0080 void __iomem *base;
0081 const struct k3_bandgap_data *conf;
0082 };
0083
0084
0085 struct k3_thermal_data {
0086 struct thermal_zone_device *tzd;
0087 struct k3_bandgap *bgp;
0088 int sensor_id;
0089 u32 ctrl_offset;
0090 u32 stat_offset;
0091 };
0092
0093 static unsigned int vtm_get_best_value(unsigned int s0, unsigned int s1,
0094 unsigned int s2)
0095 {
0096 int d01 = abs(s0 - s1);
0097 int d02 = abs(s0 - s2);
0098 int d12 = abs(s1 - s2);
0099
0100 if (d01 <= d02 && d01 <= d12)
0101 return (s0 + s1) / 2;
0102
0103 if (d02 <= d01 && d02 <= d12)
0104 return (s0 + s2) / 2;
0105
0106 return (s1 + s2) / 2;
0107 }
0108
0109 static int k3_bgp_read_temp(struct k3_thermal_data *devdata,
0110 int *temp)
0111 {
0112 struct k3_bandgap *bgp;
0113 unsigned int dtemp, s0, s1, s2;
0114
0115 bgp = devdata->bgp;
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 s0 = readl(bgp->base + devdata->stat_offset) &
0127 K3_VTM_TS_STAT_DTEMP_MASK;
0128 s1 = readl(bgp->base + devdata->stat_offset) &
0129 K3_VTM_TS_STAT_DTEMP_MASK;
0130 s2 = readl(bgp->base + devdata->stat_offset) &
0131 K3_VTM_TS_STAT_DTEMP_MASK;
0132 dtemp = vtm_get_best_value(s0, s1, s2);
0133
0134 if (dtemp < K3_VTM_ADC_BEGIN_VAL || dtemp > K3_VTM_ADC_END_VAL)
0135 return -EINVAL;
0136
0137 *temp = k3_adc_to_temp[dtemp - K3_VTM_ADC_BEGIN_VAL];
0138
0139 return 0;
0140 }
0141
0142 static int k3_thermal_get_temp(void *devdata, int *temp)
0143 {
0144 struct k3_thermal_data *data = devdata;
0145 int ret = 0;
0146
0147 ret = k3_bgp_read_temp(data, temp);
0148 if (ret)
0149 return ret;
0150
0151 return ret;
0152 }
0153
0154 static const struct thermal_zone_of_device_ops k3_of_thermal_ops = {
0155 .get_temp = k3_thermal_get_temp,
0156 };
0157
0158 static const struct of_device_id of_k3_bandgap_match[];
0159
0160 static int k3_bandgap_probe(struct platform_device *pdev)
0161 {
0162 int ret = 0, cnt, val, id;
0163 struct resource *res;
0164 struct device *dev = &pdev->dev;
0165 struct k3_bandgap *bgp;
0166 struct k3_thermal_data *data;
0167
0168 if (ARRAY_SIZE(k3_adc_to_temp) != (K3_VTM_ADC_END_VAL + 1 -
0169 K3_VTM_ADC_BEGIN_VAL))
0170 return -EINVAL;
0171
0172 bgp = devm_kzalloc(&pdev->dev, sizeof(*bgp), GFP_KERNEL);
0173 if (!bgp)
0174 return -ENOMEM;
0175
0176 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0177 bgp->base = devm_ioremap_resource(dev, res);
0178 if (IS_ERR(bgp->base))
0179 return PTR_ERR(bgp->base);
0180
0181 pm_runtime_enable(dev);
0182 ret = pm_runtime_get_sync(dev);
0183 if (ret < 0) {
0184 pm_runtime_put_noidle(dev);
0185 pm_runtime_disable(dev);
0186 return ret;
0187 }
0188
0189
0190 val = readl(bgp->base + K3_VTM_DEVINFO_PWR0_OFFSET);
0191 cnt = val & K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK;
0192 cnt >>= __ffs(K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK);
0193
0194 data = devm_kcalloc(dev, cnt, sizeof(*data), GFP_KERNEL);
0195 if (!data) {
0196 ret = -ENOMEM;
0197 goto err_alloc;
0198 }
0199
0200
0201 for (id = 0; id < cnt; id++) {
0202 data[id].sensor_id = id;
0203 data[id].bgp = bgp;
0204 data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET +
0205 id * K3_VTM_REGS_PER_TS;
0206 data[id].stat_offset = data[id].ctrl_offset + 0x8;
0207
0208 val = readl(data[id].bgp->base + data[id].ctrl_offset);
0209 val |= (K3_VTM_TMPSENS_CTRL_SOC |
0210 K3_VTM_TMPSENS_CTRL_CLRZ |
0211 K3_VTM_TMPSENS_CTRL_CLKON_REQ);
0212 val &= ~K3_VTM_TMPSENS_CTRL_CBIASSEL;
0213 writel(val, data[id].bgp->base + data[id].ctrl_offset);
0214
0215 data[id].tzd =
0216 devm_thermal_zone_of_sensor_register(dev, id,
0217 &data[id],
0218 &k3_of_thermal_ops);
0219 if (IS_ERR(data[id].tzd)) {
0220 dev_err(dev, "thermal zone device is NULL\n");
0221 ret = PTR_ERR(data[id].tzd);
0222 goto err_alloc;
0223 }
0224
0225 if (devm_thermal_add_hwmon_sysfs(data[id].tzd))
0226 dev_warn(dev, "Failed to add hwmon sysfs attributes\n");
0227 }
0228
0229 platform_set_drvdata(pdev, bgp);
0230
0231 return 0;
0232
0233 err_alloc:
0234 pm_runtime_put_sync(dev);
0235 pm_runtime_disable(dev);
0236
0237 return ret;
0238 }
0239
0240 static int k3_bandgap_remove(struct platform_device *pdev)
0241 {
0242 pm_runtime_put_sync(&pdev->dev);
0243 pm_runtime_disable(&pdev->dev);
0244
0245 return 0;
0246 }
0247
0248 static const struct of_device_id of_k3_bandgap_match[] = {
0249 {
0250 .compatible = "ti,am654-vtm",
0251 },
0252 { },
0253 };
0254 MODULE_DEVICE_TABLE(of, of_k3_bandgap_match);
0255
0256 static struct platform_driver k3_bandgap_sensor_driver = {
0257 .probe = k3_bandgap_probe,
0258 .remove = k3_bandgap_remove,
0259 .driver = {
0260 .name = "k3-soc-thermal",
0261 .of_match_table = of_k3_bandgap_match,
0262 },
0263 };
0264
0265 module_platform_driver(k3_bandgap_sensor_driver);
0266
0267 MODULE_DESCRIPTION("K3 bandgap temperature sensor driver");
0268 MODULE_LICENSE("GPL v2");
0269 MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");