@@ -19,11 +19,32 @@ enum {
/**
*struct ufs_thermal - thermal zone related data
- * @tzone: thermal zone device data
+ * @trip: trip array
*/
static struct ufs_thermal {
struct thermal_zone_device *zone;
-} thermal;
+ int trip[UFS_THERM_MAX_TRIPS];
+} thermal = {
+ .trip = {
+ [UFS_THERM_MAX_TEMP] = 170 * 1000,
+ [UFS_THERM_MIN_TEMP] = -79 * 1000
+ }
+};
+
+void ufs_thermal_exception_event_handler(struct ufs_hba *hba,
+ u32 exception_status)
+{
+ if (WARN_ON_ONCE(!hba->thermal_features))
+ return;
+
+ if (exception_status & MASK_EE_TOO_HIGH_TEMP) {
+ thermal_notify_framework(thermal.zone, UFS_THERM_HIGH_TEMP);
+ dev_info(hba->dev, "High temperature raised\n");
+ } else if (exception_status & MASK_EE_TOO_LOW_TEMP) {
+ thermal_notify_framework(thermal.zone, UFS_THERM_LOW_TEMP);
+ dev_info(hba->dev, "Low temperature raised\n");
+ }
+}
static struct thermal_zone_device_ops ufs_thermal_ops = {
.get_temp = NULL,
@@ -33,8 +54,7 @@ enum {
static int ufs_thermal_enable_ee(struct ufs_hba *hba)
{
- /* later */
- return -EINVAL;
+ return ufshcd_enable_ee(hba, MASK_EE_URGENT_TEMP);
}
static void ufs_thermal_zone_unregister(struct ufs_hba *hba)
@@ -11,9 +11,15 @@
#ifdef CONFIG_THERMAL_UFS
void ufs_thermal_remove(struct ufs_hba *hba);
int ufs_thermal_probe(struct ufs_hba *hba);
+void ufs_thermal_exception_event_handler(struct ufs_hba *hba,
+ u32 exception_status);
#else
static inline void ufs_thermal_remove(struct ufs_hba *hba) {}
static inline int ufs_thermal_probe(struct ufs_hba *hba) {return 0; }
+void ufs_thermal_exception_event_handler(struct ufs_hba *hba,
+ u32 exception_status)
+{
+}
#endif /* CONFIG_THERMAL_UFS */
#endif /* UFS_THERMAL_H */
@@ -363,7 +363,9 @@ enum power_desc_param_offset {
/* Exception event mask values */
enum {
MASK_EE_STATUS = 0xFFFF,
- MASK_EE_URGENT_BKOPS = (1 << 2),
+ MASK_EE_URGENT_BKOPS = BIT(2),
+ MASK_EE_TOO_HIGH_TEMP = BIT(3),
+ MASK_EE_TOO_LOW_TEMP = BIT(4),
};
/* Background operation status */
@@ -375,6 +377,8 @@ enum bkops_status {
BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL,
};
+#define MASK_EE_URGENT_TEMP (MASK_EE_TOO_HIGH_TEMP | MASK_EE_TOO_LOW_TEMP)
+
/* UTP QUERY Transaction Specific Fields OpCode */
enum query_opcode {
UPIU_QUERY_OPCODE_NOP = 0x0,
@@ -42,6 +42,7 @@
#include <linux/nls.h>
#include <linux/of.h>
#include <linux/bitfield.h>
+#include <linux/thermal.h>
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"
@@ -5183,6 +5184,9 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
if (status & MASK_EE_URGENT_BKOPS)
ufshcd_bkops_exception_event_handler(hba);
+ if (status & MASK_EE_URGENT_TEMP)
+ ufs_thermal_exception_event_handler(hba, status);
+
out:
ufshcd_scsi_unblock_requests(hba);
pm_runtime_put_sync(hba->dev);