1
1
// SPDX-License-Identifier: GPL-3.0+
2
2
/*
3
3
* Platform driver for Ayn x86 Handhelds that expose fan reading and
4
- * control via hwmon sysfs , as well as temperature sensor readings
5
- * exposed by the EC and RGB control via platform sysfs.
4
+ * control, as well as temperature sensor readings exposed by the EC
5
+ * via hwmon sysfs.
6
6
*
7
- * Fan control is provided via pwm interface in the range [0-254].
8
- * They use [0-128] as range in the EC, the written value is
9
- * scaled to accommodate for that.
7
+ * Fan control is provided via pwm interface in the range [0-255].
8
+ * Ayn use [0-128] as the range in the EC, the written value is
9
+ * scaled to accommodate. The EC also provides a configurable fan
10
+ * curve with five set points that associate a temperature [0-100]
11
+ * in Celcius with a fan speed [0-128]. The auto_point fan speeds
12
+ * are scaled from the range [0-255]. Temperature readings are
13
+ * scaled from the hwmon expected millidegrees to degrees when read.
10
14
*
11
15
* Copyright (C) 2023 Derek J. Clark <[email protected] >
12
16
*/
13
17
14
18
#include <linux/acpi.h>
15
19
#include <linux/dmi.h>
16
- #include <linux/hwmon.h>
17
20
#include <linux/hwmon-sysfs.h>
21
+ #include <linux/hwmon.h>
18
22
#include <linux/init.h>
19
23
#include <linux/kernel.h>
20
24
#include <linux/module.h>
@@ -68,14 +72,6 @@ static enum ayn_model model;
68
72
#define AYN_SENSOR_PWM_FAN_TEMP_4_REG 0x19
69
73
#define AYN_SENSOR_PWM_FAN_TEMP_5_REG 0x1B
70
74
71
-
72
- /* EC Controlled PWM RGB registers */
73
- /* TODO:*/
74
- #define AYN_SENSOR_PWM_RGB_R_REG 0xB0 /* PWM Red Duty cycle, range 0x00-0xFF */
75
- #define AYN_SENSOR_PWM_RGB_G_REG 0xB1 /* PWM Green Duty cycle, range 0x00-0xFF */
76
- #define AYN_SENSOR_PWM_RGB_B_REG 0xB2 /* PWM Blue Duty cycle, range 0x00-0xFF */
77
- #define AYN_SENSOR_PWM_RGB_MODE_REG 0xB3 /* RGB PWM Mode */
78
-
79
75
static const struct dmi_system_id dmi_table [] = {
80
76
{
81
77
.matches = {
@@ -141,10 +137,57 @@ static int write_to_ec(u8 reg, u8 val)
141
137
return ret ;
142
138
}
143
139
140
+ /* Thermal Sensors */
141
+ struct thermal_sensor {
142
+ char * name ;
143
+ int reg ;
144
+ };
145
+
146
+ static struct thermal_sensor thermal_sensors [] = {
147
+ {"Battery" , AYN_SENSOR_BAT_TEMP_REG },
148
+ {"Motherboard" , AYN_SENSOR_MB_TEMP_REG },
149
+ {"Charger IC" , AYN_SENSOR_CHARGE_TEMP_REG },
150
+ {"vCore" , AYN_SENSOR_VCORE_TEMP_REG },
151
+ {"CPU Core" , AYN_SENSOR_PROC_TEMP_REG },
152
+ {0 , }
153
+ };
154
+
155
+ static long thermal_sensor_temp (u8 reg , long * val )
156
+ {
157
+ long retval ;
158
+ retval = read_from_ec (reg , 1 , val );
159
+ if (retval )
160
+ return retval ;
161
+ * val = * val * (long )1000 ; //convert from hwmon expected millidegree to degree
162
+ return retval ;
163
+ };
164
+
165
+ static ssize_t thermal_sensor_show (struct device * dev ,
166
+ struct device_attribute * attr , char * buf )
167
+ {
168
+ int index ;
169
+ long retval ;
170
+ long val ;
171
+ index = to_sensor_dev_attr (attr )-> index ;
172
+ retval = thermal_sensor_temp (thermal_sensors [index ].reg , & val );
173
+ if (retval )
174
+ return retval ;
175
+ return sprintf (buf , "%ld\n" , val );
176
+ }
177
+
178
+ static ssize_t thermal_sensor_label (struct device * dev ,
179
+ struct device_attribute * attr , char * buf )
180
+ {
181
+ int index ;
182
+ index = to_sensor_dev_attr (attr )-> index ;
183
+ return sprintf (buf , "%s\n" , thermal_sensors [index ].name );
184
+ }
185
+
186
+ /* PWM mode functions */
144
187
/* Callbacks for pwm_auto_point attributes */
145
188
static ssize_t pwm_curve_store (struct device * dev ,
146
- struct device_attribute * attr , const char * buf ,
147
- size_t count )
189
+ struct device_attribute * attr , const char * buf ,
190
+ size_t count )
148
191
{
149
192
int index ;
150
193
int retval ;
@@ -197,7 +240,7 @@ static ssize_t pwm_curve_store(struct device *dev,
197
240
case 2 :
198
241
case 3 :
199
242
case 4 :
200
- if (val < 0 || val > 254 )
243
+ if (val < 0 || val > 255 )
201
244
return - EINVAL ;
202
245
val = val >> 1 ;
203
246
break ;
@@ -220,7 +263,7 @@ static ssize_t pwm_curve_store(struct device *dev,
220
263
}
221
264
222
265
static ssize_t pwm_curve_show (struct device * dev ,
223
- struct device_attribute * attr , char * buf )
266
+ struct device_attribute * attr , char * buf )
224
267
{
225
268
int index ;
226
269
int retval ;
@@ -283,53 +326,6 @@ static ssize_t pwm_curve_show(struct device *dev,
283
326
return sysfs_emit (buf , "%ld\n" , val );
284
327
}
285
328
286
- /* Thermal Sensors */
287
- struct thermal_sensor {
288
- char * name ;
289
- int reg ;
290
- };
291
-
292
- static struct thermal_sensor thermal_sensors [] = {
293
- {"Battery" , AYN_SENSOR_BAT_TEMP_REG },
294
- {"Motherboard" , AYN_SENSOR_MB_TEMP_REG },
295
- {"Charger IC" , AYN_SENSOR_CHARGE_TEMP_REG },
296
- {"vCore" , AYN_SENSOR_VCORE_TEMP_REG },
297
- {"CPU Core" , AYN_SENSOR_PROC_TEMP_REG },
298
- {0 , }
299
- };
300
-
301
- static long thermal_sensor_temp (u8 reg , long * val )
302
- {
303
- long retval ;
304
- retval = read_from_ec (reg , 1 , val );
305
- if (retval )
306
- return retval ;
307
- * val = * val * (long )1000 ; //convert from hwmon expected millidegree to degree
308
- return retval ;
309
- };
310
-
311
- static ssize_t thermal_sensor_show (struct device * dev ,
312
- struct device_attribute * attr , char * buf )
313
- {
314
- int index ;
315
- long retval ;
316
- long val ;
317
- index = to_sensor_dev_attr (attr )-> index ;
318
- retval = thermal_sensor_temp (thermal_sensors [index ].reg , & val );
319
- if (retval )
320
- return retval ;
321
- return sprintf (buf , "%ld\n" , val );
322
- }
323
-
324
- static ssize_t thermal_sensor_label (struct device * dev ,
325
- struct device_attribute * attr , char * buf )
326
- {
327
- int index ;
328
- index = to_sensor_dev_attr (attr )-> index ;
329
- return sprintf (buf , "%s\n" , thermal_sensors [index ].name );
330
- }
331
-
332
- /* PWM mode functions */
333
329
/* Manual provides direct control of the PWM */
334
330
static int ayn_pwm_manual (void )
335
331
{
@@ -351,7 +347,7 @@ static int ayn_pwm_user(void)
351
347
352
348
/* Callbacks for hwmon interface */
353
349
static umode_t ayn_ec_hwmon_is_visible (const void * drvdata ,
354
- enum hwmon_sensor_types type , u32 attr , int channel )
350
+ enum hwmon_sensor_types type , u32 attr , int channel )
355
351
{
356
352
switch (type ) {
357
353
case hwmon_fan :
@@ -363,8 +359,9 @@ static umode_t ayn_ec_hwmon_is_visible(const void *drvdata,
363
359
}
364
360
}
365
361
366
- static int ayn_platform_read (struct device * dev , enum hwmon_sensor_types type ,
367
- u32 attr , int channel , long * val )
362
+ static int ayn_platform_read (struct device * dev ,
363
+ enum hwmon_sensor_types type , u32 attr , int channel ,
364
+ long * val )
368
365
{
369
366
int ret ;
370
367
@@ -396,7 +393,8 @@ static int ayn_platform_read(struct device *dev, enum hwmon_sensor_types type,
396
393
case hwmon_pwm_mode :
397
394
ret = read_from_ec (AYN_SENSOR_PWM_FAN_MODE_REG , 1 , val );
398
395
switch (* val ) {
399
- /* EC uses 0 for manual and 1 for automatic, reflect hwmon usage instead */
396
+ /* EC uses 0 for manual and 1 for automatic,
397
+ * reflect hwmon usage instead */
400
398
case 0 :
401
399
* val = 1 ;
402
400
break ;
@@ -418,7 +416,7 @@ static int ayn_platform_read(struct device *dev, enum hwmon_sensor_types type,
418
416
}
419
417
420
418
static int ayn_platform_write (struct device * dev , enum hwmon_sensor_types type ,
421
- u32 attr , int channel , long val )
419
+ u32 attr , int channel , long val )
422
420
{
423
421
switch (type ) {
424
422
case hwmon_pwm :
@@ -432,7 +430,7 @@ static int ayn_platform_write(struct device *dev, enum hwmon_sensor_types type,
432
430
return ayn_pwm_auto ();
433
431
return - EINVAL ;
434
432
case hwmon_pwm_input :
435
- if (val < 0 || val > 254 )
433
+ if (val < 0 || val > 255 )
436
434
return - EINVAL ;
437
435
switch (model ) {
438
436
case ayn_loki_max :
@@ -455,26 +453,14 @@ static int ayn_platform_write(struct device *dev, enum hwmon_sensor_types type,
455
453
}
456
454
457
455
/* Known sensors in the AYN EC controllers */
458
- static const struct hwmon_channel_info * const ayn_platform_sensors [] = {
456
+ static const struct hwmon_channel_info * ayn_platform_sensors [] = {
459
457
HWMON_CHANNEL_INFO (fan ,
460
458
HWMON_F_INPUT ),
461
459
HWMON_CHANNEL_INFO (pwm ,
462
460
HWMON_PWM_INPUT | HWMON_PWM_MODE ),
463
461
NULL ,
464
462
};
465
463
466
- /* Fan curve attributes */
467
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point1_pwm , pwm_curve , 0 ) ;
468
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point2_pwm , pwm_curve , 1 ) ;
469
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point3_pwm , pwm_curve , 2 ) ;
470
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point4_pwm , pwm_curve , 3 ) ;
471
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point5_pwm , pwm_curve , 4 ) ;
472
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point1_temp , pwm_curve , 5 ) ;
473
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point2_temp , pwm_curve , 6 ) ;
474
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point3_temp , pwm_curve , 7 ) ;
475
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point4_temp , pwm_curve , 8 ) ;
476
- static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point5_temp , pwm_curve , 9 ) ;
477
-
478
464
/* Temperature Sensor attributes */
479
465
static SENSOR_DEVICE_ATTR (temp1_input , S_IRUGO , thermal_sensor_show , NULL, 0 ) ;
480
466
static SENSOR_DEVICE_ATTR (temp1_label , S_IRUGO , thermal_sensor_label , NULL, 0 ) ;
@@ -487,17 +473,19 @@ static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, thermal_sensor_label, NULL, 3);
487
473
static SENSOR_DEVICE_ATTR (temp5_input , S_IRUGO , thermal_sensor_show , NULL, 4 ) ;
488
474
static SENSOR_DEVICE_ATTR (temp5_label , S_IRUGO , thermal_sensor_label , NULL, 4 ) ;
489
475
476
+ /* Fan curve attributes */
477
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point1_pwm , pwm_curve , 0 ) ;
478
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point2_pwm , pwm_curve , 1 ) ;
479
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point3_pwm , pwm_curve , 2 ) ;
480
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point4_pwm , pwm_curve , 3 ) ;
481
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point5_pwm , pwm_curve , 4 ) ;
482
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point1_temp , pwm_curve , 5 ) ;
483
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point2_temp , pwm_curve , 6 ) ;
484
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point3_temp , pwm_curve , 7 ) ;
485
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point4_temp , pwm_curve , 8 ) ;
486
+ static SENSOR_DEVICE_ATTR_RW (pwm1_auto_point5_temp , pwm_curve , 9 ) ;
487
+
490
488
static struct attribute * ayn_sensors_attrs [] = {
491
- & sensor_dev_attr_pwm1_auto_point1_pwm .dev_attr .attr ,
492
- & sensor_dev_attr_pwm1_auto_point2_pwm .dev_attr .attr ,
493
- & sensor_dev_attr_pwm1_auto_point3_pwm .dev_attr .attr ,
494
- & sensor_dev_attr_pwm1_auto_point4_pwm .dev_attr .attr ,
495
- & sensor_dev_attr_pwm1_auto_point5_pwm .dev_attr .attr ,
496
- & sensor_dev_attr_pwm1_auto_point1_temp .dev_attr .attr ,
497
- & sensor_dev_attr_pwm1_auto_point2_temp .dev_attr .attr ,
498
- & sensor_dev_attr_pwm1_auto_point3_temp .dev_attr .attr ,
499
- & sensor_dev_attr_pwm1_auto_point4_temp .dev_attr .attr ,
500
- & sensor_dev_attr_pwm1_auto_point5_temp .dev_attr .attr ,
501
489
& sensor_dev_attr_temp1_input .dev_attr .attr ,
502
490
& sensor_dev_attr_temp1_label .dev_attr .attr ,
503
491
& sensor_dev_attr_temp2_input .dev_attr .attr ,
@@ -508,6 +496,16 @@ static struct attribute *ayn_sensors_attrs[] = {
508
496
& sensor_dev_attr_temp4_label .dev_attr .attr ,
509
497
& sensor_dev_attr_temp5_input .dev_attr .attr ,
510
498
& sensor_dev_attr_temp5_label .dev_attr .attr ,
499
+ & sensor_dev_attr_pwm1_auto_point1_pwm .dev_attr .attr ,
500
+ & sensor_dev_attr_pwm1_auto_point2_pwm .dev_attr .attr ,
501
+ & sensor_dev_attr_pwm1_auto_point3_pwm .dev_attr .attr ,
502
+ & sensor_dev_attr_pwm1_auto_point4_pwm .dev_attr .attr ,
503
+ & sensor_dev_attr_pwm1_auto_point5_pwm .dev_attr .attr ,
504
+ & sensor_dev_attr_pwm1_auto_point1_temp .dev_attr .attr ,
505
+ & sensor_dev_attr_pwm1_auto_point2_temp .dev_attr .attr ,
506
+ & sensor_dev_attr_pwm1_auto_point3_temp .dev_attr .attr ,
507
+ & sensor_dev_attr_pwm1_auto_point4_temp .dev_attr .attr ,
508
+ & sensor_dev_attr_pwm1_auto_point5_temp .dev_attr .attr ,
511
509
NULL ,
512
510
};
513
511
@@ -534,7 +532,7 @@ static int ayn_platform_probe(struct platform_device *pdev)
534
532
dmi_entry = dmi_first_match (dmi_table );
535
533
536
534
hwdev = devm_hwmon_device_register_with_info (dev ,
537
- "ayn-ec " ,
535
+ "aynec " ,
538
536
NULL ,
539
537
& ayn_ec_chip_info ,
540
538
ayn_sensors_groups );
0 commit comments