2020#define RG_DRV_32K_CK_PDN BIT(11)
2121#define RG_DRV_32K_CK_PDN_MASK BIT(11)
2222
23+ /* 32K/1M/6M clock common for WLED device */
24+ #define RG_VWLED_1M_CK_PDN BIT(0)
25+ #define RG_VWLED_32K_CK_PDN BIT(12)
26+ #define RG_VWLED_6M_CK_PDN BIT(13)
27+
2328/*
2429 * Register field for TOP_CKPDN2 to enable
2530 * individual clock for LED device.
@@ -71,7 +76,7 @@ struct mt6323_led {
7176 int id ;
7277 struct mt6323_leds * parent ;
7378 struct led_classdev cdev ;
74- enum led_brightness current_brightness ;
79+ unsigned int current_brightness ;
7580};
7681
7782/**
@@ -84,6 +89,7 @@ struct mt6323_led {
8489 * @num_isink_con: Number of ISINKx_CON registers
8590 * @isink_max_regs: Number of ISINK[0..x] registers
8691 * @isink_en_ctrl: Offset to ISINK_EN_CTRL register
92+ * @iwled_en_ctrl: Offset to IWLED_EN_CTRL register
8793 */
8894struct mt6323_regs {
8995 const u16 * top_ckpdn ;
@@ -94,18 +100,21 @@ struct mt6323_regs {
94100 u8 num_isink_con ;
95101 u8 isink_max_regs ;
96102 u16 isink_en_ctrl ;
103+ u16 iwled_en_ctrl ;
97104};
98105
99106/**
100107 * struct mt6323_hwspec - hardware specific parameters
101108 * @max_period: Maximum period for all LEDs
102109 * @max_leds: Maximum number of supported LEDs
110+ * @max_wleds: Maximum number of WLEDs
103111 * @max_brightness: Maximum brightness for all LEDs
104112 * @unit_duty: Steps of duty per period
105113 */
106114struct mt6323_hwspec {
107115 u16 max_period ;
108116 u8 max_leds ;
117+ u8 max_wleds ;
109118 u16 max_brightness ;
110119 u16 unit_duty ;
111120};
@@ -377,6 +386,117 @@ static int mt6323_led_set_brightness(struct led_classdev *cdev,
377386 return ret ;
378387}
379388
389+ static int mtk_wled_hw_on (struct led_classdev * cdev )
390+ {
391+ struct mt6323_led * led = container_of (cdev , struct mt6323_led , cdev );
392+ struct mt6323_leds * leds = led -> parent ;
393+ const struct mt6323_regs * regs = leds -> pdata -> regs ;
394+ struct regmap * regmap = leds -> hw -> regmap ;
395+ int ret ;
396+
397+ ret = regmap_clear_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_32K_CK_PDN );
398+ if (ret )
399+ return ret ;
400+
401+ ret = regmap_clear_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_6M_CK_PDN );
402+ if (ret )
403+ return ret ;
404+
405+ ret = regmap_clear_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_1M_CK_PDN );
406+ if (ret )
407+ return ret ;
408+
409+ usleep_range (5000 , 6000 );
410+
411+ /* Enable WLED channel pair */
412+ ret = regmap_set_bits (regmap , regs -> iwled_en_ctrl , BIT (led -> id ));
413+ if (ret )
414+ return ret ;
415+
416+ ret = regmap_set_bits (regmap , regs -> iwled_en_ctrl , BIT (led -> id + 1 ));
417+ if (ret )
418+ return ret ;
419+
420+ return 0 ;
421+ }
422+
423+ static int mtk_wled_hw_off (struct led_classdev * cdev )
424+ {
425+ struct mt6323_led * led = container_of (cdev , struct mt6323_led , cdev );
426+ struct mt6323_leds * leds = led -> parent ;
427+ const struct mt6323_regs * regs = leds -> pdata -> regs ;
428+ struct regmap * regmap = leds -> hw -> regmap ;
429+ int ret ;
430+
431+ ret = regmap_clear_bits (regmap , regs -> iwled_en_ctrl , BIT (led -> id + 1 ));
432+ if (ret )
433+ return ret ;
434+
435+ ret = regmap_clear_bits (regmap , regs -> iwled_en_ctrl , BIT (led -> id ));
436+ if (ret )
437+ return ret ;
438+
439+ ret = regmap_set_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_32K_CK_PDN );
440+ if (ret )
441+ return ret ;
442+
443+ ret = regmap_set_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_6M_CK_PDN );
444+ if (ret )
445+ return ret ;
446+
447+ ret = regmap_set_bits (regmap , regs -> top_ckpdn [0 ], RG_VWLED_1M_CK_PDN );
448+ if (ret )
449+ return ret ;
450+
451+ return 0 ;
452+ }
453+
454+ static unsigned int mt6323_get_wled_brightness (struct led_classdev * cdev )
455+ {
456+ struct mt6323_led * led = container_of (cdev , struct mt6323_led , cdev );
457+ struct mt6323_leds * leds = led -> parent ;
458+ const struct mt6323_regs * regs = leds -> pdata -> regs ;
459+ struct regmap * regmap = leds -> hw -> regmap ;
460+ unsigned int status ;
461+ int ret ;
462+
463+ ret = regmap_read (regmap , regs -> iwled_en_ctrl , & status );
464+ if (ret )
465+ return 0 ;
466+
467+ /* Always two channels per WLED */
468+ status &= BIT (led -> id ) | BIT (led -> id + 1 );
469+
470+ return status ? led -> current_brightness : 0 ;
471+ }
472+
473+ static int mt6323_wled_set_brightness (struct led_classdev * cdev ,
474+ unsigned int brightness )
475+ {
476+ struct mt6323_led * led = container_of (cdev , struct mt6323_led , cdev );
477+ struct mt6323_leds * leds = led -> parent ;
478+ int ret = 0 ;
479+
480+ mutex_lock (& leds -> lock );
481+
482+ if (brightness ) {
483+ if (!led -> current_brightness )
484+ ret = mtk_wled_hw_on (cdev );
485+ if (ret )
486+ goto out ;
487+ } else {
488+ ret = mtk_wled_hw_off (cdev );
489+ if (ret )
490+ goto out ;
491+ }
492+
493+ led -> current_brightness = brightness ;
494+ out :
495+ mutex_unlock (& leds -> lock );
496+
497+ return ret ;
498+ }
499+
380500static int mt6323_led_set_dt_default (struct led_classdev * cdev ,
381501 struct device_node * np )
382502{
@@ -416,6 +536,7 @@ static int mt6323_led_probe(struct platform_device *pdev)
416536 int ret ;
417537 unsigned int status ;
418538 u32 reg ;
539+ u8 max_leds ;
419540
420541 leds = devm_kzalloc (dev , sizeof (* leds ), GFP_KERNEL );
421542 if (!leds )
@@ -426,6 +547,7 @@ static int mt6323_led_probe(struct platform_device *pdev)
426547 leds -> pdata = device_get_match_data (dev );
427548 regs = leds -> pdata -> regs ;
428549 spec = leds -> pdata -> spec ;
550+ max_leds = spec -> max_leds + spec -> max_wleds ;
429551
430552 /*
431553 * leds->hw points to the underlying bus for the register
@@ -445,14 +567,15 @@ static int mt6323_led_probe(struct platform_device *pdev)
445567
446568 for_each_available_child_of_node (np , child ) {
447569 struct led_init_data init_data = {};
570+ bool is_wled ;
448571
449572 ret = of_property_read_u32 (child , "reg" , & reg );
450573 if (ret ) {
451574 dev_err (dev , "Failed to read led 'reg' property\n" );
452575 goto put_child_node ;
453576 }
454577
455- if (reg >= spec -> max_leds || reg >= MAX_SUPPORTED_LEDS ||
578+ if (reg >= max_leds || reg >= MAX_SUPPORTED_LEDS ||
456579 leds -> led [reg ]) {
457580 dev_err (dev , "Invalid led reg %u\n" , reg );
458581 ret = - EINVAL ;
@@ -465,14 +588,24 @@ static int mt6323_led_probe(struct platform_device *pdev)
465588 goto put_child_node ;
466589 }
467590
591+ is_wled = of_property_read_bool (child , "mediatek,is-wled" );
592+
468593 leds -> led [reg ] = led ;
469594 leds -> led [reg ]-> id = reg ;
470595 leds -> led [reg ]-> cdev .max_brightness = spec -> max_brightness ;
471- leds -> led [reg ]-> cdev .brightness_set_blocking =
472- mt6323_led_set_brightness ;
473- leds -> led [reg ]-> cdev .blink_set = mt6323_led_set_blink ;
474- leds -> led [reg ]-> cdev .brightness_get =
475- mt6323_get_led_hw_brightness ;
596+
597+ if (is_wled ) {
598+ leds -> led [reg ]-> cdev .brightness_set_blocking =
599+ mt6323_wled_set_brightness ;
600+ leds -> led [reg ]-> cdev .brightness_get =
601+ mt6323_get_wled_brightness ;
602+ } else {
603+ leds -> led [reg ]-> cdev .brightness_set_blocking =
604+ mt6323_led_set_brightness ;
605+ leds -> led [reg ]-> cdev .blink_set = mt6323_led_set_blink ;
606+ leds -> led [reg ]-> cdev .brightness_get =
607+ mt6323_get_led_hw_brightness ;
608+ }
476609 leds -> led [reg ]-> parent = leds ;
477610
478611 ret = mt6323_led_set_dt_default (& leds -> led [reg ]-> cdev , child );
@@ -540,13 +673,31 @@ static const struct mt6323_regs mt6331_registers = {
540673 .isink_en_ctrl = 0x43a ,
541674};
542675
676+ static const struct mt6323_regs mt6332_registers = {
677+ .top_ckpdn = (const u16 []){ 0x8094 , 0x809a , 0x80a0 },
678+ .num_top_ckpdn = 3 ,
679+ .top_ckcon = (const u16 []){ 0x80a6 , 0x80ac },
680+ .num_top_ckcon = 2 ,
681+ .isink_con = (const u16 []){ 0x8cd4 },
682+ .num_isink_con = 1 ,
683+ .isink_max_regs = 12 , /* IWLED[0..2, 3..9] */
684+ .iwled_en_ctrl = 0x8cda ,
685+ };
686+
543687static const struct mt6323_hwspec mt6323_spec = {
544688 .max_period = 10000 ,
545689 .max_leds = 4 ,
546690 .max_brightness = 6 ,
547691 .unit_duty = 3125 ,
548692};
549693
694+ static const struct mt6323_hwspec mt6332_spec = {
695+ /* There are no LEDs in MT6332. Only WLEDs are present. */
696+ .max_leds = 0 ,
697+ .max_wleds = 1 ,
698+ .max_brightness = 1024 ,
699+ };
700+
550701static const struct mt6323_data mt6323_pdata = {
551702 .regs = & mt6323_registers ,
552703 .spec = & mt6323_spec ,
@@ -557,9 +708,15 @@ static const struct mt6323_data mt6331_pdata = {
557708 .spec = & mt6323_spec ,
558709};
559710
711+ static const struct mt6323_data mt6332_pdata = {
712+ .regs = & mt6332_registers ,
713+ .spec = & mt6332_spec ,
714+ };
715+
560716static const struct of_device_id mt6323_led_dt_match [] = {
561717 { .compatible = "mediatek,mt6323-led" , .data = & mt6323_pdata },
562718 { .compatible = "mediatek,mt6331-led" , .data = & mt6331_pdata },
719+ { .compatible = "mediatek,mt6332-led" , .data = & mt6332_pdata },
563720 {},
564721};
565722MODULE_DEVICE_TABLE (of , mt6323_led_dt_match );
0 commit comments