Lines Matching +full:led +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0
3 * Intel Lightning Mountain SoC LED Serial Shift Output Controller driver
23 #define SSO_DEV_NAME "lgm-sso"
55 #define DATA_CLK_EDGE 0 /* 0-rising, 1-falling */
63 * SW - Software has to update the SWU bit
64 * GPTC - General Purpose timer is used as clock source
65 * FPID - Divided FSC clock (FPID) is used as clock source
69 US_GPTC = 1,
74 MAX_FPID_FREQ_RANK = 5, /* 1 to 4 */
94 CLK_SRC_GPTC = 1,
105 unsigned int retain_state_suspended:1;
106 unsigned int retain_state_shutdown:1;
107 unsigned int panic_indicator:1;
108 unsigned int hw_blink:1;
109 unsigned int hw_trig:1;
110 unsigned int blinking:1;
149 if (rate <= priv->freq[i]) in sso_get_blink_rate_idx()
153 return -1; in sso_get_blink_rate_idx()
179 return pin - LED_GRP1_PIN_MAX; in sso_led_pin_blink_off()
181 return pin - LED_GRP0_PIN_MAX; in sso_led_pin_blink_off()
182 else /* led 0 - 23 in led 32 location */ in sso_led_pin_blink_off()
183 return SSO_LED_MAX_NUM - LED_GRP1_PIN_MAX; in sso_led_pin_blink_off()
213 val_freq = freq_idx - 1; in sso_led_freq_set()
215 val_freq = freq_idx - MAX_FPID_FREQ_RANK; in sso_led_freq_set()
222 regmap_update_bits(priv->mmap, reg, GENMASK(high, low), val); in sso_led_freq_set()
229 regmap_update_bits(priv->mmap, reg, GENMASK(high, low), val); in sso_led_freq_set()
237 struct sso_led *led; in sso_led_brightness_set() local
240 led = cdev_to_sso_led_data(led_cdev); in sso_led_brightness_set()
241 priv = led->priv; in sso_led_brightness_set()
242 desc = &led->desc; in sso_led_brightness_set()
244 desc->brightness = brightness; in sso_led_brightness_set()
245 regmap_write(priv->mmap, DUTY_CYCLE(desc->pin), brightness); in sso_led_brightness_set()
250 val = 1; in sso_led_brightness_set()
253 if (desc->hw_blink && !val && desc->blinking) { in sso_led_brightness_set()
254 desc->blinking = 0; in sso_led_brightness_set()
255 regmap_update_bits(priv->mmap, SSO_CON2, BIT(desc->pin), 0); in sso_led_brightness_set()
256 } else if (desc->hw_blink && val && !desc->blinking) { in sso_led_brightness_set()
257 desc->blinking = 1; in sso_led_brightness_set()
258 regmap_update_bits(priv->mmap, SSO_CON2, BIT(desc->pin), in sso_led_brightness_set()
259 1 << desc->pin); in sso_led_brightness_set()
262 if (!desc->hw_trig) in sso_led_brightness_set()
263 gpiod_set_value(led->gpiod, val); in sso_led_brightness_set()
268 struct sso_led *led = cdev_to_sso_led_data(led_cdev); in sso_led_brightness_get() local
270 return (enum led_brightness)led->desc.brightness; in sso_led_brightness_get()
274 delay_to_freq_idx(struct sso_led *led, unsigned long *delay_on, in delay_to_freq_idx() argument
277 struct sso_led_priv *priv = led->priv; in delay_to_freq_idx()
283 *delay_on = *delay_off = (1000 / priv->freq[0]) / 2; in delay_to_freq_idx()
291 if (freq_idx == -1) in delay_to_freq_idx()
292 freq_idx = MAX_FREQ_RANK - 1; in delay_to_freq_idx()
294 delay = 1000 / priv->freq[freq_idx]; in delay_to_freq_idx()
298 *delay_on = *delay_off = 1; in delay_to_freq_idx()
308 struct sso_led *led; in sso_led_blink_set() local
311 led = cdev_to_sso_led_data(led_cdev); in sso_led_blink_set()
312 priv = led->priv; in sso_led_blink_set()
313 freq_idx = delay_to_freq_idx(led, delay_on, delay_off); in sso_led_blink_set()
315 sso_led_freq_set(priv, led->desc.pin, freq_idx); in sso_led_blink_set()
316 regmap_update_bits(priv->mmap, SSO_CON2, BIT(led->desc.pin), in sso_led_blink_set()
317 1 << led->desc.pin); in sso_led_blink_set()
318 led->desc.freq_idx = freq_idx; in sso_led_blink_set()
319 led->desc.blink_rate = priv->freq[freq_idx]; in sso_led_blink_set()
320 led->desc.blinking = 1; in sso_led_blink_set()
322 return 1; in sso_led_blink_set()
325 static void sso_led_hw_cfg(struct sso_led_priv *priv, struct sso_led *led) in sso_led_hw_cfg() argument
327 struct sso_led_desc *desc = &led->desc; in sso_led_hw_cfg()
330 if (desc->hw_blink) { in sso_led_hw_cfg()
331 sso_led_freq_set(priv, desc->pin, desc->freq_idx); in sso_led_hw_cfg()
332 regmap_update_bits(priv->mmap, SSO_CON2, BIT(desc->pin), in sso_led_hw_cfg()
333 1 << desc->pin); in sso_led_hw_cfg()
336 if (desc->hw_trig) in sso_led_hw_cfg()
337 regmap_update_bits(priv->mmap, SSO_CON3, BIT(desc->pin), in sso_led_hw_cfg()
338 1 << desc->pin); in sso_led_hw_cfg()
341 regmap_write(priv->mmap, DUTY_CYCLE(desc->pin), desc->brightness); in sso_led_hw_cfg()
344 if (!desc->hw_trig && desc->brightness) in sso_led_hw_cfg()
345 gpiod_set_value(led->gpiod, 1); in sso_led_hw_cfg()
348 static int sso_create_led(struct sso_led_priv *priv, struct sso_led *led, in sso_create_led() argument
351 struct sso_led_desc *desc = &led->desc; in sso_create_led()
359 led->cdev.default_trigger = desc->default_trigger; in sso_create_led()
360 led->cdev.brightness_set = sso_led_brightness_set; in sso_create_led()
361 led->cdev.brightness_get = sso_led_brightness_get; in sso_create_led()
362 led->cdev.brightness = desc->brightness; in sso_create_led()
363 led->cdev.max_brightness = LED_FULL; in sso_create_led()
365 if (desc->retain_state_shutdown) in sso_create_led()
366 led->cdev.flags |= LED_RETAIN_AT_SHUTDOWN; in sso_create_led()
367 if (desc->retain_state_suspended) in sso_create_led()
368 led->cdev.flags |= LED_CORE_SUSPENDRESUME; in sso_create_led()
369 if (desc->panic_indicator) in sso_create_led()
370 led->cdev.flags |= LED_PANIC_INDICATOR; in sso_create_led()
372 if (desc->hw_blink) in sso_create_led()
373 led->cdev.blink_set = sso_led_blink_set; in sso_create_led()
375 sso_led_hw_cfg(priv, led); in sso_create_led()
377 err = devm_led_classdev_register_ext(priv->dev, &led->cdev, &init_data); in sso_create_led()
381 list_add(&led->list, &priv->led_list); in sso_create_led()
390 priv->freq[0] = 0; in sso_init_freq()
391 for (i = 1; i < MAX_FREQ_RANK; i++) { in sso_init_freq()
393 priv->freq[i] = priv->fpid_clkrate / freq_div_tbl[i - 1]; in sso_init_freq()
395 priv->freq[i] = priv->gptc_clkrate / in sso_init_freq()
396 freq_div_tbl[i - MAX_FPID_FREQ_RANK]; in sso_init_freq()
398 priv->freq[i] = priv->gptc_clkrate; in sso_init_freq()
407 if (priv->gpio.alloc_bitmap & BIT(offset)) in sso_gpio_request()
408 return -EINVAL; in sso_gpio_request()
410 priv->gpio.alloc_bitmap |= BIT(offset); in sso_gpio_request()
411 regmap_write(priv->mmap, DUTY_CYCLE(offset), 0xFF); in sso_gpio_request()
420 priv->gpio.alloc_bitmap &= ~BIT(offset); in sso_gpio_free()
421 regmap_write(priv->mmap, DUTY_CYCLE(offset), 0x0); in sso_gpio_free()
435 regmap_update_bits(priv->mmap, SSO_CPU, BIT(offset), bit << offset); in sso_gpio_dir_out()
436 if (!priv->gpio.freq) in sso_gpio_dir_out()
437 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_SWU, in sso_gpio_dir_out()
448 regmap_read(priv->mmap, SSO_CPU, &reg_val); in sso_gpio_get()
457 regmap_update_bits(priv->mmap, SSO_CPU, BIT(offset), value << offset); in sso_gpio_set()
458 if (!priv->gpio.freq) in sso_gpio_set()
459 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_SWU, in sso_gpio_set()
465 struct gpio_chip *gc = &priv->gpio.chip; in sso_gpio_gc_init()
467 gc->request = sso_gpio_request; in sso_gpio_gc_init()
468 gc->free = sso_gpio_free; in sso_gpio_gc_init()
469 gc->get_direction = sso_gpio_get_dir; in sso_gpio_gc_init()
470 gc->direction_output = sso_gpio_dir_out; in sso_gpio_gc_init()
471 gc->get = sso_gpio_get; in sso_gpio_gc_init()
472 gc->set = sso_gpio_set; in sso_gpio_gc_init()
474 gc->label = "lgm-sso"; in sso_gpio_gc_init()
475 gc->base = -1; in sso_gpio_gc_init()
476 /* To exclude pins from control, use "gpio-reserved-ranges" */ in sso_gpio_gc_init()
477 gc->ngpio = priv->gpio.pins; in sso_gpio_gc_init()
478 gc->parent = dev; in sso_gpio_gc_init()
479 gc->owner = THIS_MODULE; in sso_gpio_gc_init()
493 return -1; in sso_gpio_get_freq_idx()
502 if (shift_clk_freq_tbl[idx] <= priv->gpio.shift_clk_freq) { in sso_register_shift_clk()
509 dev_warn(priv->dev, "%s: Invalid freq %d\n", in sso_register_shift_clk()
510 __func__, priv->gpio.shift_clk_freq); in sso_register_shift_clk()
512 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_FCDSC, in sso_register_shift_clk()
521 freq_idx = sso_gpio_get_freq_idx(priv->gpio.freq); in sso_gpio_freq_set()
522 if (freq_idx == -1) in sso_gpio_freq_set()
523 freq_idx = ARRAY_SIZE(freq_tbl) - 1; in sso_gpio_freq_set()
527 if (!priv->gpio.freq) { in sso_gpio_freq_set()
528 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_BLINK_R, 0); in sso_gpio_freq_set()
529 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_US, in sso_gpio_freq_set()
532 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_BLINK_R, in sso_gpio_freq_set()
534 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_US, in sso_gpio_freq_set()
536 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_FPID, in sso_gpio_freq_set()
539 regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_BLINK_R, in sso_gpio_freq_set()
541 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_US, in sso_gpio_freq_set()
543 regmap_update_bits(priv->mmap, SSO_CON1, SSO_CON1_GPTD, in sso_gpio_freq_set()
556 for (i = 0; i < priv->gpio.pins; i++) { in sso_gpio_hw_init()
557 err = regmap_write(priv->mmap, DUTY_CYCLE(i), 0); in sso_gpio_hw_init()
563 for (i = 1; i <= MAX_GROUP_NUM; i++) { in sso_gpio_hw_init()
564 activate = !!(i * PINS_PER_GROUP <= priv->gpio.pins || in sso_gpio_hw_init()
565 priv->gpio.pins > (i - 1) * PINS_PER_GROUP); in sso_gpio_hw_init()
566 err = regmap_update_bits(priv->mmap, SSO_CON1, BIT(i - 1), in sso_gpio_hw_init()
567 activate << (i - 1)); in sso_gpio_hw_init()
573 err = regmap_write(priv->mmap, SSO_CON3, 0); in sso_gpio_hw_init()
578 err = regmap_write(priv->mmap, SSO_CON2, 0); in sso_gpio_hw_init()
583 err = regmap_write(priv->mmap, SSO_CPU, 0); in sso_gpio_hw_init()
588 err = regmap_update_bits(priv->mmap, SSO_CON0, SSO_CON0_RZFL, in sso_gpio_hw_init()
589 FIELD_PREP(SSO_CON0_RZFL, priv->gpio.edge)); in sso_gpio_hw_init()
602 static void sso_led_shutdown(struct sso_led *led) in sso_led_shutdown() argument
604 struct sso_led_priv *priv = led->priv; in sso_led_shutdown()
606 /* unregister led */ in sso_led_shutdown()
607 devm_led_classdev_unregister(priv->dev, &led->cdev); in sso_led_shutdown()
610 if (led->desc.hw_trig) in sso_led_shutdown()
611 regmap_update_bits(priv->mmap, SSO_CON3, BIT(led->desc.pin), 0); in sso_led_shutdown()
613 led->priv = NULL; in sso_led_shutdown()
620 struct device *dev = priv->dev; in __sso_led_dt_parse()
622 struct sso_led *led; in __sso_led_dt_parse() local
628 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL); in __sso_led_dt_parse()
629 if (!led) { in __sso_led_dt_parse()
630 ret = -ENOMEM; in __sso_led_dt_parse()
634 INIT_LIST_HEAD(&led->list); in __sso_led_dt_parse()
635 led->priv = priv; in __sso_led_dt_parse()
636 desc = &led->desc; in __sso_led_dt_parse()
638 led->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, in __sso_led_dt_parse()
641 if (IS_ERR(led->gpiod)) { in __sso_led_dt_parse()
642 ret = dev_err_probe(dev, PTR_ERR(led->gpiod), "led: get gpio fail!\n"); in __sso_led_dt_parse()
647 "linux,default-trigger", in __sso_led_dt_parse()
648 &desc->default_trigger); in __sso_led_dt_parse()
651 "retain-state-suspended")) in __sso_led_dt_parse()
652 desc->retain_state_suspended = 1; in __sso_led_dt_parse()
655 "retain-state-shutdown")) in __sso_led_dt_parse()
656 desc->retain_state_shutdown = 1; in __sso_led_dt_parse()
658 if (fwnode_property_present(fwnode_child, "panic-indicator")) in __sso_led_dt_parse()
659 desc->panic_indicator = 1; in __sso_led_dt_parse()
665 dev_err(dev, "invalid LED pin:%u\n", prop); in __sso_led_dt_parse()
666 ret = -EINVAL; in __sso_led_dt_parse()
669 desc->pin = prop; in __sso_led_dt_parse()
671 if (fwnode_property_present(fwnode_child, "intel,sso-hw-blink")) in __sso_led_dt_parse()
672 desc->hw_blink = 1; in __sso_led_dt_parse()
674 desc->hw_trig = fwnode_property_read_bool(fwnode_child, in __sso_led_dt_parse()
675 "intel,sso-hw-trigger"); in __sso_led_dt_parse()
676 if (desc->hw_trig) { in __sso_led_dt_parse()
677 desc->default_trigger = NULL; in __sso_led_dt_parse()
678 desc->retain_state_shutdown = 0; in __sso_led_dt_parse()
679 desc->retain_state_suspended = 0; in __sso_led_dt_parse()
680 desc->panic_indicator = 0; in __sso_led_dt_parse()
681 desc->hw_blink = 0; in __sso_led_dt_parse()
685 "intel,sso-blink-rate-hz", &prop)) { in __sso_led_dt_parse()
687 desc->freq_idx = 0; in __sso_led_dt_parse()
688 desc->blink_rate = priv->freq[desc->freq_idx]; in __sso_led_dt_parse()
690 desc->freq_idx = sso_get_blink_rate_idx(priv, prop); in __sso_led_dt_parse()
691 if (desc->freq_idx == -1) in __sso_led_dt_parse()
692 desc->freq_idx = MAX_FREQ_RANK - 1; in __sso_led_dt_parse()
694 desc->blink_rate = priv->freq[desc->freq_idx]; in __sso_led_dt_parse()
697 if (!fwnode_property_read_string(fwnode_child, "default-state", &tmp)) { in __sso_led_dt_parse()
699 desc->brightness = LED_FULL; in __sso_led_dt_parse()
702 ret = sso_create_led(priv, led, fwnode_child); in __sso_led_dt_parse()
712 list_for_each_entry(led, &priv->led_list, list) in __sso_led_dt_parse()
713 sso_led_shutdown(led); in __sso_led_dt_parse()
720 struct fwnode_handle *fwnode = dev_fwnode(priv->dev); in sso_led_dt_parse()
722 struct device *dev = priv->dev; in sso_led_dt_parse()
743 struct device *dev = priv->dev; in sso_probe_gpios()
746 if (device_property_read_u32(dev, "ngpios", &priv->gpio.pins)) in sso_probe_gpios()
747 priv->gpio.pins = MAX_PIN_NUM_PER_BANK; in sso_probe_gpios()
749 if (priv->gpio.pins > MAX_PIN_NUM_PER_BANK) in sso_probe_gpios()
750 return -EINVAL; in sso_probe_gpios()
752 if (device_property_read_u32(dev, "intel,sso-update-rate-hz", in sso_probe_gpios()
753 &priv->gpio.freq)) in sso_probe_gpios()
754 priv->gpio.freq = 0; in sso_probe_gpios()
756 priv->gpio.edge = DATA_CLK_EDGE; in sso_probe_gpios()
757 priv->gpio.shift_clk_freq = -1; in sso_probe_gpios()
770 clk_bulk_disable_unprepare(ARRAY_SIZE(priv->clocks), priv->clocks); in sso_clock_disable_unprepare()
775 struct device *dev = &pdev->dev; in intel_sso_led_probe()
781 return -ENOMEM; in intel_sso_led_probe()
783 priv->pdev = pdev; in intel_sso_led_probe()
784 priv->dev = dev; in intel_sso_led_probe()
787 priv->clocks[0].id = "sso"; in intel_sso_led_probe()
790 priv->clocks[1].id = "fpid"; in intel_sso_led_probe()
792 ret = devm_clk_bulk_get(dev, ARRAY_SIZE(priv->clocks), priv->clocks); in intel_sso_led_probe()
798 ret = clk_bulk_prepare_enable(ARRAY_SIZE(priv->clocks), priv->clocks); in intel_sso_led_probe()
808 priv->fpid_clkrate = clk_get_rate(priv->clocks[1].clk); in intel_sso_led_probe()
810 priv->mmap = syscon_node_to_regmap(dev->of_node); in intel_sso_led_probe()
812 priv->mmap = syscon_node_to_regmap(dev->of_node); in intel_sso_led_probe()
813 if (IS_ERR(priv->mmap)) { in intel_sso_led_probe()
815 return PTR_ERR(priv->mmap); in intel_sso_led_probe()
820 regmap_exit(priv->mmap); in intel_sso_led_probe()
824 INIT_LIST_HEAD(&priv->led_list); in intel_sso_led_probe()
829 priv->gptc_clkrate = DEF_GPTC_CLK_RATE; in intel_sso_led_probe()
833 regmap_exit(priv->mmap); in intel_sso_led_probe()
836 dev_info(priv->dev, "sso LED init success!\n"); in intel_sso_led_probe()
844 struct sso_led *led, *n; in intel_sso_led_remove() local
848 list_for_each_entry_safe(led, n, &priv->led_list, list) { in intel_sso_led_remove()
849 list_del(&led->list); in intel_sso_led_remove()
850 sso_led_shutdown(led); in intel_sso_led_remove()
853 regmap_exit(priv->mmap); in intel_sso_led_remove()
859 { .compatible = "intel,lgm-ssoled" },
869 .name = "lgm-ssoled",
876 MODULE_DESCRIPTION("Intel SSO LED/GPIO driver");