1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/device/devres.h> 4 #include <linux/netlink.h> 5 #include <linux/sprintf.h> 6 #include <linux/types.h> 7 #include <net/devlink.h> 8 9 #include "core.h" 10 #include "devlink.h" 11 #include "dpll.h" 12 #include "flash.h" 13 #include "fw.h" 14 #include "regs.h" 15 16 /** 17 * zl3073x_devlink_info_get - Devlink device info callback 18 * @devlink: devlink structure pointer 19 * @req: devlink request pointer to store information 20 * @extack: netlink extack pointer to report errors 21 * 22 * Return: 0 on success, <0 on error 23 */ 24 static int 25 zl3073x_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, 26 struct netlink_ext_ack *extack) 27 { 28 struct zl3073x_dev *zldev = devlink_priv(devlink); 29 u16 id, revision, fw_ver; 30 char buf[16]; 31 u32 cfg_ver; 32 int rc; 33 34 rc = zl3073x_read_u16(zldev, ZL_REG_ID, &id); 35 if (rc) 36 return rc; 37 38 snprintf(buf, sizeof(buf), "%X", id); 39 rc = devlink_info_version_fixed_put(req, 40 DEVLINK_INFO_VERSION_GENERIC_ASIC_ID, 41 buf); 42 if (rc) 43 return rc; 44 45 rc = zl3073x_read_u16(zldev, ZL_REG_REVISION, &revision); 46 if (rc) 47 return rc; 48 49 snprintf(buf, sizeof(buf), "%X", revision); 50 rc = devlink_info_version_fixed_put(req, 51 DEVLINK_INFO_VERSION_GENERIC_ASIC_REV, 52 buf); 53 if (rc) 54 return rc; 55 56 rc = zl3073x_read_u16(zldev, ZL_REG_FW_VER, &fw_ver); 57 if (rc) 58 return rc; 59 60 snprintf(buf, sizeof(buf), "%u", fw_ver); 61 rc = devlink_info_version_running_put(req, 62 DEVLINK_INFO_VERSION_GENERIC_FW, 63 buf); 64 if (rc) 65 return rc; 66 67 rc = zl3073x_read_u32(zldev, ZL_REG_CUSTOM_CONFIG_VER, &cfg_ver); 68 if (rc) 69 return rc; 70 71 /* No custom config version */ 72 if (cfg_ver == U32_MAX) 73 return 0; 74 75 snprintf(buf, sizeof(buf), "%lu.%lu.%lu.%lu", 76 FIELD_GET(GENMASK(31, 24), cfg_ver), 77 FIELD_GET(GENMASK(23, 16), cfg_ver), 78 FIELD_GET(GENMASK(15, 8), cfg_ver), 79 FIELD_GET(GENMASK(7, 0), cfg_ver)); 80 81 return devlink_info_version_running_put(req, "custom_cfg", buf); 82 } 83 84 static int 85 zl3073x_devlink_reload_down(struct devlink *devlink, bool netns_change, 86 enum devlink_reload_action action, 87 enum devlink_reload_limit limit, 88 struct netlink_ext_ack *extack) 89 { 90 struct zl3073x_dev *zldev = devlink_priv(devlink); 91 92 if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 93 return -EOPNOTSUPP; 94 95 /* Stop normal operation */ 96 zl3073x_dev_stop(zldev); 97 98 return 0; 99 } 100 101 static int 102 zl3073x_devlink_reload_up(struct devlink *devlink, 103 enum devlink_reload_action action, 104 enum devlink_reload_limit limit, 105 u32 *actions_performed, 106 struct netlink_ext_ack *extack) 107 { 108 struct zl3073x_dev *zldev = devlink_priv(devlink); 109 union devlink_param_value val; 110 int rc; 111 112 if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 113 return -EOPNOTSUPP; 114 115 rc = devl_param_driverinit_value_get(devlink, 116 DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 117 &val); 118 if (rc) 119 return rc; 120 121 if (zldev->clock_id != val.vu64) { 122 dev_dbg(zldev->dev, 123 "'clock_id' changed to %016llx\n", val.vu64); 124 zldev->clock_id = val.vu64; 125 } 126 127 /* Restart normal operation */ 128 rc = zl3073x_dev_start(zldev, false); 129 if (rc) 130 dev_warn(zldev->dev, "Failed to re-start normal operation\n"); 131 132 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 133 134 return 0; 135 } 136 137 void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg, 138 const char *component, u32 done, u32 total) 139 { 140 struct devlink *devlink = priv_to_devlink(zldev); 141 142 devlink_flash_update_status_notify(devlink, msg, component, done, 143 total); 144 } 145 146 /** 147 * zl3073x_devlink_flash_prepare - Prepare and enter flash mode 148 * @zldev: zl3073x device pointer 149 * @zlfw: pointer to loaded firmware 150 * @extack: netlink extack pointer to report errors 151 * 152 * The function stops normal operation and switches the device to flash mode. 153 * If an error occurs the normal operation is resumed. 154 * 155 * Return: 0 on success, <0 on error 156 */ 157 static int 158 zl3073x_devlink_flash_prepare(struct zl3073x_dev *zldev, 159 struct zl3073x_fw *zlfw, 160 struct netlink_ext_ack *extack) 161 { 162 struct zl3073x_fw_component *util; 163 int rc; 164 165 util = zlfw->component[ZL_FW_COMPONENT_UTIL]; 166 if (!util) { 167 zl3073x_devlink_flash_notify(zldev, 168 "Utility is missing in firmware", 169 NULL, 0, 0); 170 zl3073x_fw_free(zlfw); 171 return -ENOEXEC; 172 } 173 174 /* Stop normal operation prior entering flash mode */ 175 zl3073x_dev_stop(zldev); 176 177 rc = zl3073x_flash_mode_enter(zldev, util->data, util->size, extack); 178 if (rc) { 179 zl3073x_devlink_flash_notify(zldev, 180 "Failed to enter flash mode", 181 NULL, 0, 0); 182 183 /* Resume normal operation */ 184 zl3073x_dev_start(zldev, true); 185 186 return rc; 187 } 188 189 return 0; 190 } 191 192 /** 193 * zl3073x_devlink_flash_finish - Leave flash mode and resume normal operation 194 * @zldev: zl3073x device pointer 195 * @extack: netlink extack pointer to report errors 196 * 197 * The function switches the device back to standard mode and resumes normal 198 * operation. 199 * 200 * Return: 0 on success, <0 on error 201 */ 202 static int 203 zl3073x_devlink_flash_finish(struct zl3073x_dev *zldev, 204 struct netlink_ext_ack *extack) 205 { 206 int rc; 207 208 /* Reset device CPU to normal mode */ 209 zl3073x_flash_mode_leave(zldev, extack); 210 211 /* Resume normal operation */ 212 rc = zl3073x_dev_start(zldev, true); 213 if (rc) 214 zl3073x_devlink_flash_notify(zldev, 215 "Failed to start normal operation", 216 NULL, 0, 0); 217 218 return rc; 219 } 220 221 /** 222 * zl3073x_devlink_flash_update - Devlink flash update callback 223 * @devlink: devlink structure pointer 224 * @params: flashing parameters pointer 225 * @extack: netlink extack pointer to report errors 226 * 227 * Return: 0 on success, <0 on error 228 */ 229 static int 230 zl3073x_devlink_flash_update(struct devlink *devlink, 231 struct devlink_flash_update_params *params, 232 struct netlink_ext_ack *extack) 233 { 234 struct zl3073x_dev *zldev = devlink_priv(devlink); 235 struct zl3073x_fw *zlfw; 236 int rc = 0; 237 238 zlfw = zl3073x_fw_load(zldev, params->fw->data, params->fw->size, 239 extack); 240 if (IS_ERR(zlfw)) { 241 zl3073x_devlink_flash_notify(zldev, "Failed to load firmware", 242 NULL, 0, 0); 243 rc = PTR_ERR(zlfw); 244 goto finish; 245 } 246 247 /* Stop normal operation and enter flash mode */ 248 rc = zl3073x_devlink_flash_prepare(zldev, zlfw, extack); 249 if (rc) 250 goto finish; 251 252 rc = zl3073x_fw_flash(zldev, zlfw, extack); 253 if (rc) { 254 zl3073x_devlink_flash_finish(zldev, extack); 255 goto finish; 256 } 257 258 /* Resume normal mode */ 259 rc = zl3073x_devlink_flash_finish(zldev, extack); 260 261 finish: 262 if (!IS_ERR(zlfw)) 263 zl3073x_fw_free(zlfw); 264 265 zl3073x_devlink_flash_notify(zldev, 266 rc ? "Flashing failed" : "Flashing done", 267 NULL, 0, 0); 268 269 return rc; 270 } 271 272 static const struct devlink_ops zl3073x_devlink_ops = { 273 .info_get = zl3073x_devlink_info_get, 274 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), 275 .reload_down = zl3073x_devlink_reload_down, 276 .reload_up = zl3073x_devlink_reload_up, 277 .flash_update = zl3073x_devlink_flash_update, 278 }; 279 280 static void 281 zl3073x_devlink_free(void *ptr) 282 { 283 devlink_free(ptr); 284 } 285 286 /** 287 * zl3073x_devm_alloc - allocates zl3073x device structure 288 * @dev: pointer to device structure 289 * 290 * Allocates zl3073x device structure as device resource. 291 * 292 * Return: pointer to zl3073x device on success, error pointer on error 293 */ 294 struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev) 295 { 296 struct zl3073x_dev *zldev; 297 struct devlink *devlink; 298 int rc; 299 300 devlink = devlink_alloc(&zl3073x_devlink_ops, sizeof(*zldev), dev); 301 if (!devlink) 302 return ERR_PTR(-ENOMEM); 303 304 /* Add devres action to free devlink device */ 305 rc = devm_add_action_or_reset(dev, zl3073x_devlink_free, devlink); 306 if (rc) 307 return ERR_PTR(rc); 308 309 zldev = devlink_priv(devlink); 310 zldev->dev = dev; 311 dev_set_drvdata(zldev->dev, zldev); 312 313 return zldev; 314 } 315 EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, "ZL3073X"); 316 317 static int 318 zl3073x_devlink_param_clock_id_validate(struct devlink *devlink, u32 id, 319 union devlink_param_value val, 320 struct netlink_ext_ack *extack) 321 { 322 if (!val.vu64) { 323 NL_SET_ERR_MSG_MOD(extack, "'clock_id' must be non-zero"); 324 return -EINVAL; 325 } 326 327 return 0; 328 } 329 330 static const struct devlink_param zl3073x_devlink_params[] = { 331 DEVLINK_PARAM_GENERIC(CLOCK_ID, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 332 NULL, NULL, 333 zl3073x_devlink_param_clock_id_validate), 334 }; 335 336 static void 337 zl3073x_devlink_unregister(void *ptr) 338 { 339 struct devlink *devlink = priv_to_devlink(ptr); 340 341 devl_lock(devlink); 342 343 /* Unregister devlink params */ 344 devl_params_unregister(devlink, zl3073x_devlink_params, 345 ARRAY_SIZE(zl3073x_devlink_params)); 346 347 /* Unregister devlink instance */ 348 devl_unregister(devlink); 349 350 devl_unlock(devlink); 351 } 352 353 /** 354 * zl3073x_devlink_register - register devlink instance and params 355 * @zldev: zl3073x device to register the devlink for 356 * 357 * Register the devlink instance and parameters associated with the device. 358 * 359 * Return: 0 on success, <0 on error 360 */ 361 int zl3073x_devlink_register(struct zl3073x_dev *zldev) 362 { 363 struct devlink *devlink = priv_to_devlink(zldev); 364 union devlink_param_value value; 365 int rc; 366 367 devl_lock(devlink); 368 369 /* Register devlink params */ 370 rc = devl_params_register(devlink, zl3073x_devlink_params, 371 ARRAY_SIZE(zl3073x_devlink_params)); 372 if (rc) { 373 devl_unlock(devlink); 374 375 return rc; 376 } 377 378 value.vu64 = zldev->clock_id; 379 devl_param_driverinit_value_set(devlink, 380 DEVLINK_PARAM_GENERIC_ID_CLOCK_ID, 381 value); 382 383 /* Register devlink instance */ 384 devl_register(devlink); 385 386 devl_unlock(devlink); 387 388 /* Add devres action to unregister devlink device */ 389 return devm_add_action_or_reset(zldev->dev, zl3073x_devlink_unregister, 390 zldev); 391 } 392