// SPDX-License-Identifier: GPL-2.0+ /* Copyright (c) 2016 Broadcom Corporation All Rights Reserved */ /* * Created on: Apr 2019 * Author: samyon.furman@broadcom.com */ #include "os_dep.h" #include "bcm_bca_leds_dt_bindings.h" #include "bcm_bca_leds.h" #include "dt_access.h" static uintptr_t xrdpled_base; static int xrdpled_probe(dt_device_t *pdev) { int ret; xrdpled_base = dt_dev_remap_resource(pdev, 0); if (IS_ERR(xrdpled_base)) { ret = PTR_ERR(xrdpled_base); xrdpled_base = NULL; dev_err(&pdev->dev, "Missing xrdpled_base entry\n"); goto Exit; } dev_dbg(&pdev->dev, "xrdpled_base=0x%lx\n", xrdpled_base); dev_info(&pdev->dev, "registered\n"); return 0; Exit: return ret; } #ifdef __UBOOT__ static const struct udevice_id xrdpled_ids[] = { { .compatible = "brcm,xrdp-led" }, { /* end of list */ }, }; U_BOOT_DRIVER(brcm_xrdpled) = { .name = "brcm-xrdpled", .id = UCLASS_MISC, .of_match = xrdpled_ids, .probe = xrdpled_probe, }; #else static const struct of_device_id of_platform_table[] = { { .compatible = "brcm,xrdp-led" }, { /* end of list */ }, }; static struct platform_driver of_platform_driver = { .driver = { .name = "brcm-xrdpled", .of_match_table = of_platform_table, }, .probe = xrdpled_probe, }; module_platform_driver(of_platform_driver); #endif typedef union { struct { uint32_t rx_act_en :1 ; // [00:00] uint32_t tx_act_en :1 ; // [01:01] uint32_t spdlnk_led0_act_sel :1 ; // [02:02] uint32_t spdlnk_led1_act_sel :1 ; // [03:03] uint32_t spdlnk_led2_act_sel :1 ; // [04:04] uint32_t act_led_act_sel :1 ; // [05:05] uint32_t spdlnk_led0_act_pol_sel :1 ; // [06:06] uint32_t spdlnk_led1_act_pol_sel :1 ; // [07:07] uint32_t spdlnk_led2_act_pol_sel :1 ; // [08:08] uint32_t act_led_pol_sel :1 ; // [09:09] uint32_t led_spd_ovrd :3 ; // [12:10] uint32_t lnk_status_ovrd :1 ; // [13:13] uint32_t spd_ovrd_en :1 ; // [14:14] uint32_t lnk_ovrd_en :1 ; // [15:15] uint32_t r1 :16; // [31:16] }Bits; uint32_t Reg32; }XRDP_LED_CTRL; typedef union { struct { uint32_t sel_no_link_encode :3 ; // [02:00] uint32_t sel_10m_encode :3 ; // [05:03] uint32_t sel_100m_encode :3 ; // [08:06] uint32_t sel_1000m_encode :3 ; // [11:09] uint32_t sel_2500m_encode :3 ; // [14:12] uint32_t sel_10g_encode :3 ; // [17:15] uint32_t r1 :14; // [31:18] }Bits; uint32_t Reg32; }XRDP_LED_LINK_SPEED_ENC_SEL; typedef union { struct { uint32_t no_link_encode :3 ; // [02:00] uint32_t m10_encode :3 ; // [05:03] uint32_t m100_encode :3 ; // [08:06] uint32_t m1000_encode :3 ; // [11:09] uint32_t m2500_encode :3 ; // [14:12] uint32_t m10g_encode :3 ; // [17:15] uint32_t r1 :14; // [31:18] }Bits; uint32_t Reg32; }XRDP_LED_LINK_SPEED_ENC; typedef union { struct { uint32_t port_en :16; // [15:00] uint32_t act_sel :1 ; // [16:16] uint32_t act_pol_sel :1 ; // [17:17] uint32_t lnk_pol_sel :1 ; // [18:18] uint32_t r1 :13; // [31:19] }Bits; uint32_t Reg32; }XRDP_LED_AGGREGATE_CTRL; typedef struct XrdpLedRegs { XRDP_LED_CTRL led_ctrl[5]; uint32_t reserved0[3]; XRDP_LED_LINK_SPEED_ENC_SEL led_link_speed_enc_sel[5]; uint32_t reserved1[3]; XRDP_LED_LINK_SPEED_ENC led_link_speed_enc[5]; uint32_t reserved2[3]; uint32_t led_blink_rate_ctrl; uint32_t led_pwm_ctrl; uint32_t led_intensity_ctrl; XRDP_LED_AGGREGATE_CTRL led_aggregate_ctrl; uint32_t led_aggregate_blink_rate_ctrl; uint32_t led_aggregate_pwm_ctrl; uint32_t led_aggregate_intensity_ctrl; uint32_t led_sw_init_ctrl; } XrdpLedRegs; #define XRDP_LED_BASE (void *)xrdpled_base #define XRDP_LED ((volatile XrdpLedRegs * const) XRDP_LED_BASE) int xrdp_leds_init(void *_leds_info) { bca_leds_info_t *leds_info = (bca_leds_info_t *)_leds_info; int ret = 0; int j; XRDP_LED_CTRL led_ctrl; XRDP_LED_LINK_SPEED_ENC_SEL spdlnk_sel; XRDP_LED_LINK_SPEED_ENC spdlnk; uint32_t port = leds_info->port_id; XRDP_LED_AGGREGATE_CTRL agg_ctrl; uint8_t activity; if(port == 0xff) { /* No Led info provided */ return 0; } spdlnk_sel.Bits.sel_10g_encode = 0; spdlnk_sel.Bits.sel_1000m_encode = 0; spdlnk_sel.Bits.sel_100m_encode = 0; spdlnk_sel.Bits.sel_2500m_encode = 0; spdlnk_sel.Bits.sel_10m_encode = 0; spdlnk_sel.Bits.sel_no_link_encode = 0; spdlnk.Bits.m10g_encode = 7; spdlnk.Bits.m2500_encode = 7; spdlnk.Bits.m1000_encode = 7; spdlnk.Bits.m100_encode = 7; spdlnk.Bits.m10_encode = 7; spdlnk.Bits.no_link_encode = 7; led_ctrl.Reg32 = XRDP_LED->led_ctrl[port].Reg32; agg_ctrl.Reg32 = XRDP_LED->led_aggregate_ctrl.Reg32; agg_ctrl.Bits.act_sel = 1; agg_ctrl.Bits.act_pol_sel = 0; agg_ctrl.Bits.lnk_pol_sel = 1; if (!leds_info->skip_in_aggregate) agg_ctrl.Bits.port_en |= 1<led_aggregate_ctrl.Reg32 = agg_ctrl.Reg32; if (!leds_info->skip_in_aggregate) XRDP_LED->led_aggregate_ctrl.Bits.port_en |= 1<link[j]; uint32_t led_activity = leds_info->activity[j]; activity = 0; if (led_mux & LED_SPEED_10G) spdlnk.Bits.m10g_encode &= ~(1<activity[3] || leds_info->link[3]) led_ctrl.Bits.act_led_act_sel = leds_info->link[3] ? 0 : 1; XRDP_LED->led_link_speed_enc_sel[port].Reg32 = spdlnk_sel.Reg32; XRDP_LED->led_link_speed_enc[port].Reg32 = spdlnk.Reg32; XRDP_LED->led_ctrl[port].Reg32 = led_ctrl.Reg32; printk("%s Port %d configured \n", __FUNCTION__, port); return ret; }