0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0059
0060 #include <linux/module.h>
0061 #include <linux/slab.h>
0062 #include <linux/interrupt.h>
0063 #include <linux/thermal.h>
0064 #include <asm/cpu_device_id.h>
0065 #include <asm/iosf_mbi.h>
0066
0067
0068 #define QRK_DTS_REG_OFFSET_RESET 0x34
0069 #define QRK_DTS_RESET_BIT BIT(0)
0070
0071
0072 #define QRK_DTS_REG_OFFSET_ENABLE 0xB0
0073 #define QRK_DTS_ENABLE_BIT BIT(15)
0074
0075
0076 #define QRK_DTS_REG_OFFSET_TEMP 0xB1
0077 #define QRK_DTS_MASK_TEMP 0xFF
0078 #define QRK_DTS_OFFSET_TEMP 0
0079 #define QRK_DTS_OFFSET_REL_TEMP 16
0080 #define QRK_DTS_TEMP_BASE 50
0081
0082
0083 #define QRK_DTS_REG_OFFSET_PTPS 0xB2
0084 #define QRK_DTS_MASK_TP_THRES 0xFF
0085 #define QRK_DTS_SHIFT_TP 8
0086 #define QRK_DTS_ID_TP_CRITICAL 0
0087 #define QRK_DTS_SAFE_TP_THRES 105
0088
0089
0090 #define QRK_DTS_REG_OFFSET_LOCK 0x71
0091 #define QRK_DTS_LOCK_BIT BIT(5)
0092
0093
0094 #define QRK_MAX_DTS_TRIPS 2
0095
0096 #define QRK_DTS_WR_MASK_SET 0x3
0097
0098 #define QRK_DTS_WR_MASK_CLR 0
0099
0100 #define DEFAULT_POLL_DELAY 2000
0101
0102 struct soc_sensor_entry {
0103 bool locked;
0104 u32 store_ptps;
0105 u32 store_dts_enable;
0106 struct thermal_zone_device *tzone;
0107 };
0108
0109 static struct soc_sensor_entry *soc_dts;
0110
0111 static int polling_delay = DEFAULT_POLL_DELAY;
0112 module_param(polling_delay, int, 0644);
0113 MODULE_PARM_DESC(polling_delay,
0114 "Polling interval for checking trip points (in milliseconds)");
0115
0116 static DEFINE_MUTEX(dts_update_mutex);
0117
0118 static int soc_dts_enable(struct thermal_zone_device *tzd)
0119 {
0120 u32 out;
0121 struct soc_sensor_entry *aux_entry = tzd->devdata;
0122 int ret;
0123
0124 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0125 QRK_DTS_REG_OFFSET_ENABLE, &out);
0126 if (ret)
0127 return ret;
0128
0129 if (out & QRK_DTS_ENABLE_BIT)
0130 return 0;
0131
0132 if (!aux_entry->locked) {
0133 out |= QRK_DTS_ENABLE_BIT;
0134 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
0135 QRK_DTS_REG_OFFSET_ENABLE, out);
0136 if (ret)
0137 return ret;
0138 } else {
0139 pr_info("DTS is locked. Cannot enable DTS\n");
0140 ret = -EPERM;
0141 }
0142
0143 return ret;
0144 }
0145
0146 static int soc_dts_disable(struct thermal_zone_device *tzd)
0147 {
0148 u32 out;
0149 struct soc_sensor_entry *aux_entry = tzd->devdata;
0150 int ret;
0151
0152 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0153 QRK_DTS_REG_OFFSET_ENABLE, &out);
0154 if (ret)
0155 return ret;
0156
0157 if (!(out & QRK_DTS_ENABLE_BIT))
0158 return 0;
0159
0160 if (!aux_entry->locked) {
0161 out &= ~QRK_DTS_ENABLE_BIT;
0162 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
0163 QRK_DTS_REG_OFFSET_ENABLE, out);
0164
0165 if (ret)
0166 return ret;
0167 } else {
0168 pr_info("DTS is locked. Cannot disable DTS\n");
0169 ret = -EPERM;
0170 }
0171
0172 return ret;
0173 }
0174
0175 static int _get_trip_temp(int trip, int *temp)
0176 {
0177 int status;
0178 u32 out;
0179
0180 mutex_lock(&dts_update_mutex);
0181 status = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0182 QRK_DTS_REG_OFFSET_PTPS, &out);
0183 mutex_unlock(&dts_update_mutex);
0184
0185 if (status)
0186 return status;
0187
0188
0189
0190
0191
0192
0193
0194 *temp = (out >> (trip * QRK_DTS_SHIFT_TP)) & QRK_DTS_MASK_TP_THRES;
0195 *temp -= QRK_DTS_TEMP_BASE;
0196
0197 return 0;
0198 }
0199
0200 static inline int sys_get_trip_temp(struct thermal_zone_device *tzd,
0201 int trip, int *temp)
0202 {
0203 return _get_trip_temp(trip, temp);
0204 }
0205
0206 static inline int sys_get_crit_temp(struct thermal_zone_device *tzd, int *temp)
0207 {
0208 return _get_trip_temp(QRK_DTS_ID_TP_CRITICAL, temp);
0209 }
0210
0211 static int update_trip_temp(struct soc_sensor_entry *aux_entry,
0212 int trip, int temp)
0213 {
0214 u32 out;
0215 u32 temp_out;
0216 u32 store_ptps;
0217 int ret;
0218
0219 mutex_lock(&dts_update_mutex);
0220 if (aux_entry->locked) {
0221 ret = -EPERM;
0222 goto failed;
0223 }
0224
0225 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0226 QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
0227 if (ret)
0228 goto failed;
0229
0230
0231
0232
0233
0234
0235
0236 if (temp > QRK_DTS_SAFE_TP_THRES)
0237 temp = QRK_DTS_SAFE_TP_THRES;
0238
0239
0240
0241
0242
0243
0244
0245 temp_out = temp + QRK_DTS_TEMP_BASE;
0246 out = (store_ptps & ~(QRK_DTS_MASK_TP_THRES <<
0247 (trip * QRK_DTS_SHIFT_TP)));
0248 out |= (temp_out & QRK_DTS_MASK_TP_THRES) <<
0249 (trip * QRK_DTS_SHIFT_TP);
0250
0251 ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
0252 QRK_DTS_REG_OFFSET_PTPS, out);
0253
0254 failed:
0255 mutex_unlock(&dts_update_mutex);
0256 return ret;
0257 }
0258
0259 static inline int sys_set_trip_temp(struct thermal_zone_device *tzd, int trip,
0260 int temp)
0261 {
0262 return update_trip_temp(tzd->devdata, trip, temp);
0263 }
0264
0265 static int sys_get_trip_type(struct thermal_zone_device *thermal,
0266 int trip, enum thermal_trip_type *type)
0267 {
0268 if (trip)
0269 *type = THERMAL_TRIP_HOT;
0270 else
0271 *type = THERMAL_TRIP_CRITICAL;
0272
0273 return 0;
0274 }
0275
0276 static int sys_get_curr_temp(struct thermal_zone_device *tzd,
0277 int *temp)
0278 {
0279 u32 out;
0280 int ret;
0281
0282 mutex_lock(&dts_update_mutex);
0283 ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0284 QRK_DTS_REG_OFFSET_TEMP, &out);
0285 mutex_unlock(&dts_update_mutex);
0286
0287 if (ret)
0288 return ret;
0289
0290
0291
0292
0293
0294
0295 out = (out >> QRK_DTS_OFFSET_TEMP) & QRK_DTS_MASK_TEMP;
0296 *temp = out - QRK_DTS_TEMP_BASE;
0297
0298 return 0;
0299 }
0300
0301 static int sys_change_mode(struct thermal_zone_device *tzd,
0302 enum thermal_device_mode mode)
0303 {
0304 int ret;
0305
0306 mutex_lock(&dts_update_mutex);
0307 if (mode == THERMAL_DEVICE_ENABLED)
0308 ret = soc_dts_enable(tzd);
0309 else
0310 ret = soc_dts_disable(tzd);
0311 mutex_unlock(&dts_update_mutex);
0312
0313 return ret;
0314 }
0315
0316 static struct thermal_zone_device_ops tzone_ops = {
0317 .get_temp = sys_get_curr_temp,
0318 .get_trip_temp = sys_get_trip_temp,
0319 .get_trip_type = sys_get_trip_type,
0320 .set_trip_temp = sys_set_trip_temp,
0321 .get_crit_temp = sys_get_crit_temp,
0322 .change_mode = sys_change_mode,
0323 };
0324
0325 static void free_soc_dts(struct soc_sensor_entry *aux_entry)
0326 {
0327 if (aux_entry) {
0328 if (!aux_entry->locked) {
0329 mutex_lock(&dts_update_mutex);
0330 iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
0331 QRK_DTS_REG_OFFSET_ENABLE,
0332 aux_entry->store_dts_enable);
0333
0334 iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
0335 QRK_DTS_REG_OFFSET_PTPS,
0336 aux_entry->store_ptps);
0337 mutex_unlock(&dts_update_mutex);
0338 }
0339 thermal_zone_device_unregister(aux_entry->tzone);
0340 kfree(aux_entry);
0341 }
0342 }
0343
0344 static struct soc_sensor_entry *alloc_soc_dts(void)
0345 {
0346 struct soc_sensor_entry *aux_entry;
0347 int err;
0348 u32 out;
0349 int wr_mask;
0350
0351 aux_entry = kzalloc(sizeof(*aux_entry), GFP_KERNEL);
0352 if (!aux_entry) {
0353 err = -ENOMEM;
0354 return ERR_PTR(-ENOMEM);
0355 }
0356
0357
0358 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0359 QRK_DTS_REG_OFFSET_LOCK, &out);
0360 if (err)
0361 goto err_ret;
0362
0363 if (out & QRK_DTS_LOCK_BIT) {
0364 aux_entry->locked = true;
0365 wr_mask = QRK_DTS_WR_MASK_CLR;
0366 } else {
0367 aux_entry->locked = false;
0368 wr_mask = QRK_DTS_WR_MASK_SET;
0369 }
0370
0371
0372 if (!aux_entry->locked) {
0373
0374 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0375 QRK_DTS_REG_OFFSET_ENABLE,
0376 &aux_entry->store_dts_enable);
0377 if (err)
0378 goto err_ret;
0379
0380
0381 err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
0382 QRK_DTS_REG_OFFSET_PTPS,
0383 &aux_entry->store_ptps);
0384 if (err)
0385 goto err_ret;
0386 }
0387
0388 aux_entry->tzone = thermal_zone_device_register("quark_dts",
0389 QRK_MAX_DTS_TRIPS,
0390 wr_mask,
0391 aux_entry, &tzone_ops, NULL, 0, polling_delay);
0392 if (IS_ERR(aux_entry->tzone)) {
0393 err = PTR_ERR(aux_entry->tzone);
0394 goto err_ret;
0395 }
0396
0397 err = thermal_zone_device_enable(aux_entry->tzone);
0398 if (err)
0399 goto err_aux_status;
0400
0401 return aux_entry;
0402
0403 err_aux_status:
0404 thermal_zone_device_unregister(aux_entry->tzone);
0405 err_ret:
0406 kfree(aux_entry);
0407 return ERR_PTR(err);
0408 }
0409
0410 static const struct x86_cpu_id qrk_thermal_ids[] __initconst = {
0411 X86_MATCH_VENDOR_FAM_MODEL(INTEL, 5, INTEL_FAM5_QUARK_X1000, NULL),
0412 {}
0413 };
0414 MODULE_DEVICE_TABLE(x86cpu, qrk_thermal_ids);
0415
0416 static int __init intel_quark_thermal_init(void)
0417 {
0418 int err = 0;
0419
0420 if (!x86_match_cpu(qrk_thermal_ids) || !iosf_mbi_available())
0421 return -ENODEV;
0422
0423 soc_dts = alloc_soc_dts();
0424 if (IS_ERR(soc_dts)) {
0425 err = PTR_ERR(soc_dts);
0426 goto err_free;
0427 }
0428
0429 return 0;
0430
0431 err_free:
0432 free_soc_dts(soc_dts);
0433 return err;
0434 }
0435
0436 static void __exit intel_quark_thermal_exit(void)
0437 {
0438 free_soc_dts(soc_dts);
0439 }
0440
0441 module_init(intel_quark_thermal_init)
0442 module_exit(intel_quark_thermal_exit)
0443
0444 MODULE_DESCRIPTION("Intel Quark DTS Thermal Driver");
0445 MODULE_AUTHOR("Ong Boon Leong <boon.leong.ong@intel.com>");
0446 MODULE_LICENSE("Dual BSD/GPL");