2
2
/*
3
3
* CZ.NIC's Turris Omnia LEDs driver
4
4
*
5
- * 2020, 2023 by Marek Behún <kabel@kernel.org>
5
+ * 2020, 2023, 2024 by Marek Behún <kabel@kernel.org>
6
6
*/
7
7
8
8
#include <linux/i2c.h>
9
9
#include <linux/led-class-multicolor.h>
10
10
#include <linux/module.h>
11
11
#include <linux/mutex.h>
12
12
#include <linux/of.h>
13
+ #include <linux/turris-omnia-mcu-interface.h>
13
14
14
15
#define OMNIA_BOARD_LEDS 12
15
16
#define OMNIA_LED_NUM_CHANNELS 3
@@ -56,66 +57,21 @@ struct omnia_leds {
56
57
struct omnia_led leds [];
57
58
};
58
59
59
- static int omnia_cmd_write_u8 (const struct i2c_client * client , u8 cmd , u8 val )
60
+ static int omnia_cmd_set_color (const struct i2c_client * client , u8 led , u8 r , u8 g , u8 b )
60
61
{
61
- u8 buf [2 ] = { cmd , val };
62
- int ret ;
63
-
64
- ret = i2c_master_send (client , buf , sizeof (buf ));
62
+ u8 buf [5 ] = { CMD_LED_COLOR , led , r , g , b };
65
63
66
- return ret < 0 ? ret : 0 ;
67
- }
68
-
69
- static int omnia_cmd_read_raw (struct i2c_adapter * adapter , u8 addr , u8 cmd ,
70
- void * reply , size_t len )
71
- {
72
- struct i2c_msg msgs [2 ];
73
- int ret ;
74
-
75
- msgs [0 ].addr = addr ;
76
- msgs [0 ].flags = 0 ;
77
- msgs [0 ].len = 1 ;
78
- msgs [0 ].buf = & cmd ;
79
- msgs [1 ].addr = addr ;
80
- msgs [1 ].flags = I2C_M_RD ;
81
- msgs [1 ].len = len ;
82
- msgs [1 ].buf = reply ;
83
-
84
- ret = i2c_transfer (adapter , msgs , ARRAY_SIZE (msgs ));
85
- if (likely (ret == ARRAY_SIZE (msgs )))
86
- return 0 ;
87
- else if (ret < 0 )
88
- return ret ;
89
- else
90
- return - EIO ;
91
- }
92
-
93
- static int omnia_cmd_read_u8 (const struct i2c_client * client , u8 cmd )
94
- {
95
- u8 reply ;
96
- int err ;
97
-
98
- err = omnia_cmd_read_raw (client -> adapter , client -> addr , cmd , & reply , 1 );
99
- if (err )
100
- return err ;
101
-
102
- return reply ;
64
+ return omnia_cmd_write (client , buf , sizeof (buf ));
103
65
}
104
66
105
67
static int omnia_led_send_color_cmd (const struct i2c_client * client ,
106
68
struct omnia_led * led )
107
69
{
108
- char cmd [5 ];
109
70
int ret ;
110
71
111
- cmd [0 ] = CMD_LED_COLOR ;
112
- cmd [1 ] = led -> reg ;
113
- cmd [2 ] = led -> subled_info [0 ].brightness ;
114
- cmd [3 ] = led -> subled_info [1 ].brightness ;
115
- cmd [4 ] = led -> subled_info [2 ].brightness ;
116
-
117
72
/* Send the color change command */
118
- ret = i2c_master_send (client , cmd , 5 );
73
+ ret = omnia_cmd_set_color (client , led -> reg , led -> subled_info [0 ].brightness ,
74
+ led -> subled_info [1 ].brightness , led -> subled_info [2 ].brightness );
119
75
if (ret < 0 )
120
76
return ret ;
121
77
@@ -351,14 +307,14 @@ static ssize_t brightness_show(struct device *dev, struct device_attribute *a,
351
307
char * buf )
352
308
{
353
309
struct i2c_client * client = to_i2c_client (dev );
354
- int ret ;
355
-
356
- ret = omnia_cmd_read_u8 (client , CMD_LED_GET_BRIGHTNESS );
310
+ u8 reply ;
311
+ int err ;
357
312
358
- if (ret < 0 )
359
- return ret ;
313
+ err = omnia_cmd_read_u8 (client , CMD_LED_GET_BRIGHTNESS , & reply );
314
+ if (err < 0 )
315
+ return err ;
360
316
361
- return sysfs_emit (buf , "%d\n" , ret );
317
+ return sysfs_emit (buf , "%d\n" , reply );
362
318
}
363
319
364
320
static ssize_t brightness_store (struct device * dev , struct device_attribute * a ,
@@ -385,17 +341,16 @@ static ssize_t gamma_correction_show(struct device *dev,
385
341
{
386
342
struct i2c_client * client = to_i2c_client (dev );
387
343
struct omnia_leds * leds = i2c_get_clientdata (client );
388
- int ret ;
344
+ u8 reply = 0 ;
345
+ int err ;
389
346
390
347
if (leds -> has_gamma_correction ) {
391
- ret = omnia_cmd_read_u8 (client , CMD_GET_GAMMA_CORRECTION );
392
- if (ret < 0 )
393
- return ret ;
394
- } else {
395
- ret = 0 ;
348
+ err = omnia_cmd_read_u8 (client , CMD_GET_GAMMA_CORRECTION , & reply );
349
+ if (err < 0 )
350
+ return err ;
396
351
}
397
352
398
- return sysfs_emit (buf , "%d\n" , !!ret );
353
+ return sysfs_emit (buf , "%d\n" , !!reply );
399
354
}
400
355
401
356
static ssize_t gamma_correction_store (struct device * dev ,
@@ -426,26 +381,51 @@ static struct attribute *omnia_led_controller_attrs[] = {
426
381
};
427
382
ATTRIBUTE_GROUPS (omnia_led_controller );
428
383
429
- static int omnia_mcu_get_features (const struct i2c_client * client )
384
+ static int omnia_mcu_get_features (const struct i2c_client * mcu_client )
430
385
{
431
386
u16 reply ;
432
387
int err ;
433
388
434
- err = omnia_cmd_read_raw (client -> adapter , OMNIA_MCU_I2C_ADDR ,
435
- CMD_GET_STATUS_WORD , & reply , sizeof (reply ));
389
+ err = omnia_cmd_read_u16 (mcu_client , CMD_GET_STATUS_WORD , & reply );
436
390
if (err )
437
391
return err ;
438
392
439
393
/* Check whether MCU firmware supports the CMD_GET_FEAUTRES command */
440
- if (!(le16_to_cpu ( reply ) & STS_FEATURES_SUPPORTED ))
394
+ if (!(reply & STS_FEATURES_SUPPORTED ))
441
395
return 0 ;
442
396
443
- err = omnia_cmd_read_raw (client -> adapter , OMNIA_MCU_I2C_ADDR ,
444
- CMD_GET_FEATURES , & reply , sizeof (reply ));
397
+ err = omnia_cmd_read_u16 (mcu_client , CMD_GET_FEATURES , & reply );
445
398
if (err )
446
399
return err ;
447
400
448
- return le16_to_cpu (reply );
401
+ return reply ;
402
+ }
403
+
404
+ static int omnia_match_mcu_client (struct device * dev , void * data )
405
+ {
406
+ struct i2c_client * client ;
407
+
408
+ client = i2c_verify_client (dev );
409
+ if (!client )
410
+ return 0 ;
411
+
412
+ return client -> addr == OMNIA_MCU_I2C_ADDR ;
413
+ }
414
+
415
+ static int omnia_find_mcu_and_get_features (struct device * dev )
416
+ {
417
+ struct device * mcu_dev ;
418
+ int ret ;
419
+
420
+ mcu_dev = device_find_child (dev -> parent , NULL , omnia_match_mcu_client );
421
+ if (!mcu_dev )
422
+ return - ENODEV ;
423
+
424
+ ret = omnia_mcu_get_features (i2c_verify_client (mcu_dev ));
425
+
426
+ put_device (mcu_dev );
427
+
428
+ return ret ;
449
429
}
450
430
451
431
static int omnia_leds_probe (struct i2c_client * client )
@@ -472,7 +452,7 @@ static int omnia_leds_probe(struct i2c_client *client)
472
452
leds -> client = client ;
473
453
i2c_set_clientdata (client , leds );
474
454
475
- ret = omnia_mcu_get_features ( client );
455
+ ret = omnia_find_mcu_and_get_features ( dev );
476
456
if (ret < 0 ) {
477
457
dev_err (dev , "Cannot determine MCU supported features: %d\n" ,
478
458
ret );
@@ -509,20 +489,11 @@ static int omnia_leds_probe(struct i2c_client *client)
509
489
510
490
static void omnia_leds_remove (struct i2c_client * client )
511
491
{
512
- u8 buf [5 ];
513
-
514
492
/* put all LEDs into default (HW triggered) mode */
515
- omnia_cmd_write_u8 (client , CMD_LED_MODE ,
516
- CMD_LED_MODE_LED (OMNIA_BOARD_LEDS ));
493
+ omnia_cmd_write_u8 (client , CMD_LED_MODE , CMD_LED_MODE_LED (OMNIA_BOARD_LEDS ));
517
494
518
495
/* set all LEDs color to [255, 255, 255] */
519
- buf [0 ] = CMD_LED_COLOR ;
520
- buf [1 ] = OMNIA_BOARD_LEDS ;
521
- buf [2 ] = 255 ;
522
- buf [3 ] = 255 ;
523
- buf [4 ] = 255 ;
524
-
525
- i2c_master_send (client , buf , 5 );
496
+ omnia_cmd_set_color (client , OMNIA_BOARD_LEDS , 255 , 255 , 255 );
526
497
}
527
498
528
499
static const struct of_device_id of_omnia_leds_match [] = {
0 commit comments