3030#define MAX_LABEL_LENGTH 32
3131#define NUM_SENSOR_TYPES 5 /* temp, volt, current, power, fan */
3232
33+ static bool melt_my_mac ;
34+ module_param_unsafe (melt_my_mac , bool , 0644 );
35+ MODULE_PARM_DESC (melt_my_mac , "Override the SMC to set your own fan speeds on supported machines" );
36+
3337struct macsmc_hwmon_sensor {
3438 struct apple_smc_key_info info ;
3539 smc_key macsmc_key ;
@@ -41,8 +45,10 @@ struct macsmc_hwmon_fan {
4145 struct macsmc_hwmon_sensor min ;
4246 struct macsmc_hwmon_sensor max ;
4347 struct macsmc_hwmon_sensor set ;
48+ struct macsmc_hwmon_sensor mode ;
4449 char label [MAX_LABEL_LENGTH ];
4550 u32 attrs ;
51+ bool manual ;
4652};
4753
4854struct macsmc_hwmon_sensors {
@@ -152,6 +158,21 @@ static int macsmc_hwmon_read_key(struct apple_smc *smc,
152158 return 0 ;
153159}
154160
161+ static int macsmc_hwmon_write_key (struct apple_smc * smc ,
162+ struct macsmc_hwmon_sensor * sensor , long val ,
163+ int scale )
164+ {
165+ switch (sensor -> info .type_code ) {
166+ /* 32-bit IEEE 754 float */
167+ case __SMC_KEY ('f' , 'l' , 't' , ' ' ):
168+ return apple_smc_write_f32_scaled (smc , sensor -> macsmc_key , val , scale );
169+ case __SMC_KEY ('u' , 'i' , '8' , ' ' ):
170+ return apple_smc_write_u8 (smc , sensor -> macsmc_key , val );
171+ default :
172+ return - EOPNOTSUPP ;
173+ }
174+ }
175+
155176static int macsmc_hwmon_read_fan (struct macsmc_hwmon * hwmon , u32 attr , int chan , long * val )
156177{
157178 if (!(hwmon -> fan .fans [chan ].attrs & BIT (attr )))
@@ -175,6 +196,61 @@ static int macsmc_hwmon_read_fan(struct macsmc_hwmon *hwmon, u32 attr, int chan,
175196 }
176197}
177198
199+ static int macsmc_hwmon_write_fan (struct device * dev , u32 attr , int channel , long val )
200+ {
201+ struct macsmc_hwmon * hwmon = dev_get_drvdata (dev );
202+ int ret = 0 ;
203+ long min = 0 ;
204+ long max = 0 ;
205+
206+ if (!melt_my_mac ||
207+ hwmon -> fan .fans [channel ].mode .macsmc_key == 0 )
208+ return - EOPNOTSUPP ;
209+
210+ if ((channel >= hwmon -> fan .n_fans ) ||
211+ !(hwmon -> fan .fans [channel ].attrs & BIT (attr )) ||
212+ (attr != hwmon_fan_target ))
213+ return - EINVAL ;
214+
215+ /*
216+ * The SMC does no sanity checks on requested fan speeds, so we need to.
217+ */
218+ ret = macsmc_hwmon_read_key (hwmon -> smc , & hwmon -> fan .fans [channel ].min , 1 , & min );
219+ if (ret )
220+ return ret ;
221+ ret = macsmc_hwmon_read_key (hwmon -> smc , & hwmon -> fan .fans [channel ].max , 1 , & max );
222+ if (ret )
223+ return ret ;
224+
225+ if (val >= min && val <= max ) {
226+ if (!hwmon -> fan .fans [channel ].manual ) {
227+ /* Write 1 to mode key for manual control */
228+ ret = macsmc_hwmon_write_key (hwmon -> smc , & hwmon -> fan .fans [channel ].mode , 1 , 1 );
229+ if (ret < 0 )
230+ return ret ;
231+
232+ hwmon -> fan .fans [channel ].manual = true;
233+ dev_info (dev , "Fan %d now under manual control! Set target speed to 0 for automatic control.\n" ,
234+ channel + 1 );
235+ }
236+ return macsmc_hwmon_write_key (hwmon -> smc , & hwmon -> fan .fans [channel ].set , val , 1 );
237+ } else if (!val ) {
238+ if (hwmon -> fan .fans [channel ].manual ) {
239+ dev_info (dev , "Returning control of fan %d to SMC.\n" , channel + 1 );
240+ ret = macsmc_hwmon_write_key (hwmon -> smc , & hwmon -> fan .fans [channel ].mode , 0 , 1 );
241+ if (ret < 0 )
242+ return ret ;
243+
244+ hwmon -> fan .fans [channel ].manual = false;
245+ }
246+ } else {
247+ dev_err (dev , "Requested fan speed %ld out of range [%ld, %ld]" , val , min , max );
248+ return - EINVAL ;
249+ }
250+
251+ return 0 ;
252+ }
253+
178254static int macsmc_hwmon_read (struct device * dev , enum hwmon_sensor_types type ,
179255 u32 attr , int channel , long * val )
180256{
@@ -212,13 +288,38 @@ static int macsmc_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
212288static int macsmc_hwmon_write (struct device * dev , enum hwmon_sensor_types type ,
213289 u32 attr , int channel , long val )
214290{
215- return - EOPNOTSUPP ;
291+ switch (type ) {
292+ case hwmon_fan :
293+ return macsmc_hwmon_write_fan (dev , attr , channel , val );
294+ default :
295+ return - EOPNOTSUPP ;
296+ }
297+ }
298+
299+ static umode_t macsmc_hwmon_fan_is_visible (const void * data , u32 attr , int channel )
300+ {
301+ const struct macsmc_hwmon * hwmon = data ;
302+
303+ if (channel >= hwmon -> fan .n_fans )
304+ return - EINVAL ;
305+
306+ if (melt_my_mac && attr == hwmon_fan_target && hwmon -> fan .fans [channel ].mode .macsmc_key != 0 )
307+ return 0644 ;
308+
309+ return 0444 ;
216310}
217311
218312static umode_t macsmc_hwmon_is_visible (const void * data ,
219313 enum hwmon_sensor_types type , u32 attr ,
220314 int channel )
221315{
316+ switch (type ) {
317+ case hwmon_fan :
318+ return macsmc_hwmon_fan_is_visible (data , attr , channel );
319+ default :
320+ break ;
321+ }
322+
222323 return 0444 ;
223324}
224325
@@ -292,6 +393,7 @@ static int macsmc_hwmon_create_fan(struct device *dev, struct apple_smc *smc,
292393 const char * min ;
293394 const char * max ;
294395 const char * set ;
396+ const char * mode ;
295397 int ret = 0 ;
296398
297399 ret = of_property_read_string (fan_node , "apple,key-id" , & now );
@@ -335,6 +437,18 @@ static int macsmc_hwmon_create_fan(struct device *dev, struct apple_smc *smc,
335437 fan -> attrs |= HWMON_F_TARGET ;
336438 }
337439
440+ ret = of_property_read_string (fan_node , "apple,fan-mode" , & mode );
441+ if (ret )
442+ dev_warn (dev , "No fan mode key for %s" , fan -> label );
443+ else {
444+ ret = macsmc_hwmon_parse_key (dev , smc , & fan -> mode , mode );
445+ if (ret )
446+ return ret ;
447+ }
448+
449+ /* Initialise fan control mode to automatic */
450+ fan -> manual = false;
451+
338452 return 0 ;
339453}
340454
0 commit comments