=============================== ======= =======================================
 fan[1-3]_input                  RO      Fan speed in RPM.
 fan[1-3]_label                  RO      Fan label.
+fan[1-3]_min                    RO      Minimal Fan speed in RPM
+fan[1-3]_max                    RO      Maximal Fan speed in RPM
+fan[1-3]_target                 RO      Expected Fan speed in RPM
 pwm[1-3]                        RW      Control the fan PWM duty-cycle.
 pwm1_enable                     WO      Enable or disable automatic BIOS fan
                                         control (not supported on all laptops,
 
        int temp_type[DELL_SMM_NO_TEMP];
        bool fan[DELL_SMM_NO_FANS];
        int fan_type[DELL_SMM_NO_FANS];
+       int *fan_nominal_speed[DELL_SMM_NO_FANS];
 };
 
 MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
                        if (data->fan[channel] && !data->disallow_fan_type_call)
                                return 0444;
 
+                       break;
+               case hwmon_fan_min:
+               case hwmon_fan_max:
+               case hwmon_fan_target:
+                       if (data->fan_nominal_speed[channel])
+                               return 0444;
+
                        break;
                default:
                        break;
 
                        *val = ret;
 
+                       return 0;
+               case hwmon_fan_min:
+                       *val = data->fan_nominal_speed[channel][0];
+
+                       return 0;
+               case hwmon_fan_max:
+                       *val = data->fan_nominal_speed[channel][data->i8k_fan_max];
+
+                       return 0;
+               case hwmon_fan_target:
+                       ret = i8k_get_fan_status(data, channel);
+                       if (ret < 0)
+                               return ret;
+
+                       if (ret > data->i8k_fan_max)
+                               ret = data->i8k_fan_max;
+
+                       *val = data->fan_nominal_speed[channel][ret];
+
                        return 0;
                default:
                        break;
                           HWMON_T_INPUT | HWMON_T_LABEL
                           ),
        HWMON_CHANNEL_INFO(fan,
-                          HWMON_F_INPUT | HWMON_F_LABEL,
-                          HWMON_F_INPUT | HWMON_F_LABEL,
-                          HWMON_F_INPUT | HWMON_F_LABEL
+                          HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+                          HWMON_F_TARGET,
+                          HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+                          HWMON_F_TARGET,
+                          HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_MIN | HWMON_F_MAX |
+                          HWMON_F_TARGET
                           ),
        HWMON_CHANNEL_INFO(pwm,
                           HWMON_PWM_INPUT | HWMON_PWM_ENABLE,
 {
        struct dell_smm_data *data = dev_get_drvdata(dev);
        struct device *dell_smm_hwmon_dev;
-       int i, err;
+       int i, state, err;
 
        for (i = 0; i < DELL_SMM_NO_TEMP; i++) {
                data->temp_type[i] = i8k_get_temp_type(i);
                err = i8k_get_fan_status(data, i);
                if (err < 0)
                        err = i8k_get_fan_type(data, i);
-               if (err >= 0)
-                       data->fan[i] = true;
+
+               if (err < 0)
+                       continue;
+
+               data->fan[i] = true;
+               data->fan_nominal_speed[i] = devm_kmalloc_array(dev, data->i8k_fan_max + 1,
+                                                               sizeof(*data->fan_nominal_speed[i]),
+                                                               GFP_KERNEL);
+               if (!data->fan_nominal_speed[i])
+                       continue;
+
+               for (state = 0; state <= data->i8k_fan_max; state++) {
+                       err = i8k_get_fan_nominal_speed(data, i, state);
+                       if (err < 0) {
+                               /* Mark nominal speed table as invalid in case of error */
+                               devm_kfree(dev, data->fan_nominal_speed[i]);
+                               data->fan_nominal_speed[i] = NULL;
+                               break;
+                       }
+                       data->fan_nominal_speed[i][state] = err;
+               }
        }
 
        dell_smm_hwmon_dev = devm_hwmon_device_register_with_info(dev, "dell_smm", data,