1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/regmap.h> 3 #include <net/dsa.h> 4 5 #include "qca8k.h" 6 #include "qca8k_leds.h" 7 8 static int 9 qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) 10 { 11 switch (port_num) { 12 case 0: 13 reg_info->reg = QCA8K_LED_CTRL_REG(led_num); 14 reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; 15 break; 16 case 1: 17 case 2: 18 case 3: 19 /* Port 123 are controlled on a different reg */ 20 reg_info->reg = QCA8K_LED_CTRL3_REG; 21 reg_info->shift = QCA8K_LED_PHY123_PATTERN_EN_SHIFT(port_num, led_num); 22 break; 23 case 4: 24 reg_info->reg = QCA8K_LED_CTRL_REG(led_num); 25 reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; 26 break; 27 default: 28 return -EINVAL; 29 } 30 31 return 0; 32 } 33 34 static int 35 qca8k_led_brightness_set(struct qca8k_led *led, 36 enum led_brightness brightness) 37 { 38 struct qca8k_led_pattern_en reg_info; 39 struct qca8k_priv *priv = led->priv; 40 u32 mask, val; 41 42 qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); 43 44 val = QCA8K_LED_ALWAYS_OFF; 45 if (brightness) 46 val = QCA8K_LED_ALWAYS_ON; 47 48 /* HW regs to control brightness is special and port 1-2-3 49 * are placed in a different reg. 50 * 51 * To control port 0 brightness: 52 * - the 2 bit (15, 14) of: 53 * - QCA8K_LED_CTRL0_REG for led1 54 * - QCA8K_LED_CTRL1_REG for led2 55 * - QCA8K_LED_CTRL2_REG for led3 56 * 57 * To control port 4: 58 * - the 2 bit (31, 30) of: 59 * - QCA8K_LED_CTRL0_REG for led1 60 * - QCA8K_LED_CTRL1_REG for led2 61 * - QCA8K_LED_CTRL2_REG for led3 62 * 63 * To control port 1: 64 * - the 2 bit at (9, 8) of QCA8K_LED_CTRL3_REG are used for led1 65 * - the 2 bit at (11, 10) of QCA8K_LED_CTRL3_REG are used for led2 66 * - the 2 bit at (13, 12) of QCA8K_LED_CTRL3_REG are used for led3 67 * 68 * To control port 2: 69 * - the 2 bit at (15, 14) of QCA8K_LED_CTRL3_REG are used for led1 70 * - the 2 bit at (17, 16) of QCA8K_LED_CTRL3_REG are used for led2 71 * - the 2 bit at (19, 18) of QCA8K_LED_CTRL3_REG are used for led3 72 * 73 * To control port 3: 74 * - the 2 bit at (21, 20) of QCA8K_LED_CTRL3_REG are used for led1 75 * - the 2 bit at (23, 22) of QCA8K_LED_CTRL3_REG are used for led2 76 * - the 2 bit at (25, 24) of QCA8K_LED_CTRL3_REG are used for led3 77 * 78 * To abstract this and have less code, we use the port and led numm 79 * to calculate the shift and the correct reg due to this problem of 80 * not having a 1:1 map of LED with the regs. 81 */ 82 if (led->port_num == 0 || led->port_num == 4) { 83 mask = QCA8K_LED_PATTERN_EN_MASK; 84 val <<= QCA8K_LED_PATTERN_EN_SHIFT; 85 } else { 86 mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; 87 } 88 89 return regmap_update_bits(priv->regmap, reg_info.reg, 90 mask << reg_info.shift, 91 val << reg_info.shift); 92 } 93 94 static int 95 qca8k_cled_brightness_set_blocking(struct led_classdev *ldev, 96 enum led_brightness brightness) 97 { 98 struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); 99 100 return qca8k_led_brightness_set(led, brightness); 101 } 102 103 static enum led_brightness 104 qca8k_led_brightness_get(struct qca8k_led *led) 105 { 106 struct qca8k_led_pattern_en reg_info; 107 struct qca8k_priv *priv = led->priv; 108 u32 val; 109 int ret; 110 111 qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); 112 113 ret = regmap_read(priv->regmap, reg_info.reg, &val); 114 if (ret) 115 return 0; 116 117 val >>= reg_info.shift; 118 119 if (led->port_num == 0 || led->port_num == 4) { 120 val &= QCA8K_LED_PATTERN_EN_MASK; 121 val >>= QCA8K_LED_PATTERN_EN_SHIFT; 122 } else { 123 val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; 124 } 125 126 /* Assume brightness ON only when the LED is set to always ON */ 127 return val == QCA8K_LED_ALWAYS_ON; 128 } 129 130 static int 131 qca8k_cled_blink_set(struct led_classdev *ldev, 132 unsigned long *delay_on, 133 unsigned long *delay_off) 134 { 135 struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); 136 u32 mask, val = QCA8K_LED_ALWAYS_BLINK_4HZ; 137 struct qca8k_led_pattern_en reg_info; 138 struct qca8k_priv *priv = led->priv; 139 140 if (*delay_on == 0 && *delay_off == 0) { 141 *delay_on = 125; 142 *delay_off = 125; 143 } 144 145 if (*delay_on != 125 || *delay_off != 125) { 146 /* The hardware only supports blinking at 4Hz. Fall back 147 * to software implementation in other cases. 148 */ 149 return -EINVAL; 150 } 151 152 qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); 153 154 if (led->port_num == 0 || led->port_num == 4) { 155 mask = QCA8K_LED_PATTERN_EN_MASK; 156 val <<= QCA8K_LED_PATTERN_EN_SHIFT; 157 } else { 158 mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; 159 } 160 161 regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, 162 val << reg_info.shift); 163 164 return 0; 165 } 166 167 static int 168 qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) 169 { 170 struct fwnode_handle *led = NULL, *leds = NULL; 171 struct led_init_data init_data = { }; 172 struct dsa_switch *ds = priv->ds; 173 enum led_default_state state; 174 struct qca8k_led *port_led; 175 int led_num, led_index; 176 int ret; 177 178 leds = fwnode_get_named_child_node(port, "leds"); 179 if (!leds) { 180 dev_dbg(priv->dev, "No Leds node specified in device tree for port %d!\n", 181 port_num); 182 return 0; 183 } 184 185 fwnode_for_each_child_node(leds, led) { 186 /* Reg represent the led number of the port. 187 * Each port can have at most 3 leds attached 188 * Commonly: 189 * 1. is gigabit led 190 * 2. is mbit led 191 * 3. additional status led 192 */ 193 if (fwnode_property_read_u32(led, "reg", &led_num)) 194 continue; 195 196 if (led_num >= QCA8K_LED_PORT_COUNT) { 197 dev_warn(priv->dev, "Invalid LED reg %d defined for port %d", 198 led_num, port_num); 199 continue; 200 } 201 202 led_index = QCA8K_LED_PORT_INDEX(port_num, led_num); 203 204 port_led = &priv->ports_led[led_index]; 205 port_led->port_num = port_num; 206 port_led->led_num = led_num; 207 port_led->priv = priv; 208 209 state = led_init_default_state_get(led); 210 switch (state) { 211 case LEDS_DEFSTATE_ON: 212 port_led->cdev.brightness = 1; 213 qca8k_led_brightness_set(port_led, 1); 214 break; 215 case LEDS_DEFSTATE_KEEP: 216 port_led->cdev.brightness = 217 qca8k_led_brightness_get(port_led); 218 break; 219 default: 220 port_led->cdev.brightness = 0; 221 qca8k_led_brightness_set(port_led, 0); 222 } 223 224 port_led->cdev.max_brightness = 1; 225 port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; 226 port_led->cdev.blink_set = qca8k_cled_blink_set; 227 init_data.default_label = ":port"; 228 init_data.fwnode = led; 229 init_data.devname_mandatory = true; 230 init_data.devicename = kasprintf(GFP_KERNEL, "%s:0%d", ds->slave_mii_bus->id, 231 port_num); 232 if (!init_data.devicename) 233 return -ENOMEM; 234 235 ret = devm_led_classdev_register_ext(priv->dev, &port_led->cdev, &init_data); 236 if (ret) 237 dev_warn(priv->dev, "Failed to init LED %d for port %d", led_num, port_num); 238 239 kfree(init_data.devicename); 240 } 241 242 return 0; 243 } 244 245 int 246 qca8k_setup_led_ctrl(struct qca8k_priv *priv) 247 { 248 struct fwnode_handle *ports, *port; 249 int port_num; 250 int ret; 251 252 ports = device_get_named_child_node(priv->dev, "ports"); 253 if (!ports) { 254 dev_info(priv->dev, "No ports node specified in device tree!"); 255 return 0; 256 } 257 258 fwnode_for_each_child_node(ports, port) { 259 if (fwnode_property_read_u32(port, "reg", &port_num)) 260 continue; 261 262 /* Skip checking for CPU port 0 and CPU port 6 as not supported */ 263 if (port_num == 0 || port_num == 6) 264 continue; 265 266 /* Each port can have at most 3 different leds attached. 267 * Switch port starts from 0 to 6, but port 0 and 6 are CPU 268 * port. The port index needs to be decreased by one to identify 269 * the correct port for LED setup. 270 */ 271 ret = qca8k_parse_port_leds(priv, port, qca8k_port_to_phy(port_num)); 272 if (ret) 273 return ret; 274 } 275 276 return 0; 277 } 278