Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'dpll-zl3073x-add-support-for-devlink-flash'

Ivan Vecera says:

====================
dpll: zl3073x: Add support for devlink flash

Add functionality for accessing device hardware registers, loading
firmware bundles, and accessing the device's internal flash memory,
and use it to implement the devlink flash functionality.
====================

Link: https://patch.msgid.link/20250909091532.11790-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1722 -117
+14
Documentation/networking/devlink/zl3073x.rst
··· 49 49 - running 50 50 - 1.3.0.1 51 51 - Device configuration version customized by OEM 52 + 53 + Flash Update 54 + ============ 55 + 56 + The ``zl3073x`` driver implements support for flash update using the 57 + ``devlink-flash`` interface. It supports updating the device flash using a 58 + combined flash image ("bundle") that contains multiple components (firmware 59 + parts and configurations). 60 + 61 + During the flash procedure, the standard firmware interface is not available, 62 + so the driver unregisters all DPLLs and associated pins, and re-registers them 63 + once the flash procedure is complete. 64 + 65 + The driver does not support any overwrite mask flags.
+1 -1
drivers/dpll/zl3073x/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 3 3 obj-$(CONFIG_ZL3073X) += zl3073x.o 4 - zl3073x-objs := core.o devlink.o dpll.o prop.o 4 + zl3073x-objs := core.o devlink.o dpll.o flash.o fw.o prop.o 5 5 6 6 obj-$(CONFIG_ZL3073X_I2C) += zl3073x_i2c.o 7 7 zl3073x_i2c-objs := i2c.o
+310 -104
drivers/dpll/zl3073x/core.c
··· 95 95 96 96 #define ZL_RANGE_OFFSET 0x80 97 97 #define ZL_PAGE_SIZE 0x80 98 - #define ZL_NUM_PAGES 15 98 + #define ZL_NUM_PAGES 256 99 99 #define ZL_PAGE_SEL 0x7F 100 - #define ZL_PAGE_SEL_MASK GENMASK(3, 0) 100 + #define ZL_PAGE_SEL_MASK GENMASK(7, 0) 101 101 #define ZL_NUM_REGS (ZL_NUM_PAGES * ZL_PAGE_SIZE) 102 102 103 103 /* Regmap range configuration */ ··· 174 174 zl3073x_check_reg(struct zl3073x_dev *zldev, unsigned int reg, size_t size) 175 175 { 176 176 /* Check that multiop lock is held when accessing registers 177 - * from page 10 and above. 177 + * from page 10 and above except the page 255 that does not 178 + * need this protection. 178 179 */ 179 - if (ZL_REG_PAGE(reg) >= 10) 180 + if (ZL_REG_PAGE(reg) >= 10 && ZL_REG_PAGE(reg) < 255) 180 181 lockdep_assert_held(&zldev->multiop_lock); 181 182 182 183 /* Check the index is in valid range for indexed register */ ··· 445 444 446 445 /* Wait for the operation to actually finish */ 447 446 return zl3073x_poll_zero_u8(zldev, op_reg, op_val); 447 + } 448 + 449 + /** 450 + * zl3073x_do_hwreg_op - Perform HW register read/write operation 451 + * @zldev: zl3073x device pointer 452 + * @op: operation to perform 453 + * 454 + * Performs requested operation and waits for its completion. 455 + * 456 + * Return: 0 on success, <0 on error 457 + */ 458 + static int 459 + zl3073x_do_hwreg_op(struct zl3073x_dev *zldev, u8 op) 460 + { 461 + int rc; 462 + 463 + /* Set requested operation and set pending bit */ 464 + rc = zl3073x_write_u8(zldev, ZL_REG_HWREG_OP, op | ZL_HWREG_OP_PENDING); 465 + if (rc) 466 + return rc; 467 + 468 + /* Poll for completion - pending bit cleared */ 469 + return zl3073x_poll_zero_u8(zldev, ZL_REG_HWREG_OP, 470 + ZL_HWREG_OP_PENDING); 471 + } 472 + 473 + /** 474 + * zl3073x_read_hwreg - Read HW register 475 + * @zldev: zl3073x device pointer 476 + * @addr: HW register address 477 + * @value: Value of the HW register 478 + * 479 + * Reads HW register value and stores it into @value. 480 + * 481 + * Return: 0 on success, <0 on error 482 + */ 483 + int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value) 484 + { 485 + int rc; 486 + 487 + /* Set address to read data from */ 488 + rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_ADDR, addr); 489 + if (rc) 490 + return rc; 491 + 492 + /* Perform the read operation */ 493 + rc = zl3073x_do_hwreg_op(zldev, ZL_HWREG_OP_READ); 494 + if (rc) 495 + return rc; 496 + 497 + /* Read the received data */ 498 + return zl3073x_read_u32(zldev, ZL_REG_HWREG_READ_DATA, value); 499 + } 500 + 501 + /** 502 + * zl3073x_write_hwreg - Write value to HW register 503 + * @zldev: zl3073x device pointer 504 + * @addr: HW registers address 505 + * @value: Value to be written to HW register 506 + * 507 + * Stores the requested value into HW register. 508 + * 509 + * Return: 0 on success, <0 on error 510 + */ 511 + int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value) 512 + { 513 + int rc; 514 + 515 + /* Set address to write data to */ 516 + rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_ADDR, addr); 517 + if (rc) 518 + return rc; 519 + 520 + /* Set data to be written */ 521 + rc = zl3073x_write_u32(zldev, ZL_REG_HWREG_WRITE_DATA, value); 522 + if (rc) 523 + return rc; 524 + 525 + /* Perform the write operation */ 526 + return zl3073x_do_hwreg_op(zldev, ZL_HWREG_OP_WRITE); 527 + } 528 + 529 + /** 530 + * zl3073x_update_hwreg - Update certain bits in HW register 531 + * @zldev: zl3073x device pointer 532 + * @addr: HW register address 533 + * @value: Value to be written into HW register 534 + * @mask: Bitmask indicating bits to be updated 535 + * 536 + * Reads given HW register, updates requested bits specified by value and 537 + * mask and writes result back to HW register. 538 + * 539 + * Return: 0 on success, <0 on error 540 + */ 541 + int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value, 542 + u32 mask) 543 + { 544 + u32 tmp; 545 + int rc; 546 + 547 + rc = zl3073x_read_hwreg(zldev, addr, &tmp); 548 + if (rc) 549 + return rc; 550 + 551 + tmp &= ~mask; 552 + tmp |= value & mask; 553 + 554 + return zl3073x_write_hwreg(zldev, addr, tmp); 555 + } 556 + 557 + /** 558 + * zl3073x_write_hwreg_seq - Write HW registers sequence 559 + * @zldev: pointer to device structure 560 + * @seq: pointer to first sequence item 561 + * @num_items: number of items in sequence 562 + * 563 + * Writes given HW registers sequence. 564 + * 565 + * Return: 0 on success, <0 on error 566 + */ 567 + int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev, 568 + const struct zl3073x_hwreg_seq_item *seq, 569 + size_t num_items) 570 + { 571 + int i, rc = 0; 572 + 573 + for (i = 0; i < num_items; i++) { 574 + dev_dbg(zldev->dev, "Write 0x%0x [0x%0x] to 0x%0x", 575 + seq[i].value, seq[i].mask, seq[i].addr); 576 + 577 + if (seq[i].mask == U32_MAX) 578 + /* Write value directly */ 579 + rc = zl3073x_write_hwreg(zldev, seq[i].addr, 580 + seq[i].value); 581 + else 582 + /* Update only bits specified by the mask */ 583 + rc = zl3073x_update_hwreg(zldev, seq[i].addr, 584 + seq[i].value, seq[i].mask); 585 + if (rc) 586 + return rc; 587 + 588 + if (seq->wait) 589 + msleep(seq->wait); 590 + } 591 + 592 + return rc; 448 593 } 449 594 450 595 /** ··· 956 809 msecs_to_jiffies(500)); 957 810 } 958 811 959 - static void zl3073x_dev_dpll_fini(void *ptr) 960 - { 961 - struct zl3073x_dpll *zldpll, *next; 962 - struct zl3073x_dev *zldev = ptr; 963 - 964 - /* Stop monitoring thread */ 965 - if (zldev->kworker) { 966 - kthread_cancel_delayed_work_sync(&zldev->work); 967 - kthread_destroy_worker(zldev->kworker); 968 - zldev->kworker = NULL; 969 - } 970 - 971 - /* Release DPLLs */ 972 - list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { 973 - zl3073x_dpll_unregister(zldpll); 974 - list_del(&zldpll->list); 975 - zl3073x_dpll_free(zldpll); 976 - } 977 - } 978 - 979 - static int 980 - zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls) 981 - { 982 - struct kthread_worker *kworker; 983 - struct zl3073x_dpll *zldpll; 984 - unsigned int i; 985 - int rc; 986 - 987 - INIT_LIST_HEAD(&zldev->dplls); 988 - 989 - /* Initialize all DPLLs */ 990 - for (i = 0; i < num_dplls; i++) { 991 - zldpll = zl3073x_dpll_alloc(zldev, i); 992 - if (IS_ERR(zldpll)) { 993 - dev_err_probe(zldev->dev, PTR_ERR(zldpll), 994 - "Failed to alloc DPLL%u\n", i); 995 - rc = PTR_ERR(zldpll); 996 - goto error; 997 - } 998 - 999 - rc = zl3073x_dpll_register(zldpll); 1000 - if (rc) { 1001 - dev_err_probe(zldev->dev, rc, 1002 - "Failed to register DPLL%u\n", i); 1003 - zl3073x_dpll_free(zldpll); 1004 - goto error; 1005 - } 1006 - 1007 - list_add_tail(&zldpll->list, &zldev->dplls); 1008 - } 1009 - 1010 - /* Perform initial firmware fine phase correction */ 1011 - rc = zl3073x_dpll_init_fine_phase_adjust(zldev); 1012 - if (rc) { 1013 - dev_err_probe(zldev->dev, rc, 1014 - "Failed to init fine phase correction\n"); 1015 - goto error; 1016 - } 1017 - 1018 - /* Initialize monitoring thread */ 1019 - kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); 1020 - kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); 1021 - if (IS_ERR(kworker)) { 1022 - rc = PTR_ERR(kworker); 1023 - goto error; 1024 - } 1025 - 1026 - zldev->kworker = kworker; 1027 - kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); 1028 - 1029 - /* Add devres action to release DPLL related resources */ 1030 - rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev); 1031 - if (rc) 1032 - goto error; 1033 - 1034 - return 0; 1035 - 1036 - error: 1037 - zl3073x_dev_dpll_fini(zldev); 1038 - 1039 - return rc; 1040 - } 1041 - 1042 812 /** 1043 813 * zl3073x_dev_phase_meas_setup - setup phase offset measurement 1044 814 * @zldev: pointer to zl3073x_dev structure 1045 - * @num_channels: number of DPLL channels 1046 815 * 1047 816 * Enable phase offset measurement block, set measurement averaging factor 1048 817 * and enable DPLL-to-its-ref phase measurement for all DPLLs. ··· 966 903 * Returns: 0 on success, <0 on error 967 904 */ 968 905 static int 969 - zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev, int num_channels) 906 + zl3073x_dev_phase_meas_setup(struct zl3073x_dev *zldev) 970 907 { 971 - u8 dpll_meas_ctrl, mask; 972 - int i, rc; 908 + struct zl3073x_dpll *zldpll; 909 + u8 dpll_meas_ctrl, mask = 0; 910 + int rc; 973 911 974 912 /* Read DPLL phase measurement control register */ 975 913 rc = zl3073x_read_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, &dpll_meas_ctrl); ··· 990 926 return rc; 991 927 992 928 /* Enable DPLL-to-connected-ref measurement for each channel */ 993 - for (i = 0, mask = 0; i < num_channels; i++) 994 - mask |= BIT(i); 929 + list_for_each_entry(zldpll, &zldev->dplls, list) 930 + mask |= BIT(zldpll->id); 995 931 996 932 return zl3073x_write_u8(zldev, ZL_REG_DPLL_PHASE_ERR_READ_MASK, mask); 933 + } 934 + 935 + /** 936 + * zl3073x_dev_start - Start normal operation 937 + * @zldev: zl3073x device pointer 938 + * @full: perform full initialization 939 + * 940 + * The function starts normal operation, which means registering all DPLLs and 941 + * their pins, and starting monitoring. If full initialization is requested, 942 + * the function additionally initializes the phase offset measurement block and 943 + * fetches hardware-invariant parameters. 944 + * 945 + * Return: 0 on success, <0 on error 946 + */ 947 + int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full) 948 + { 949 + struct zl3073x_dpll *zldpll; 950 + int rc; 951 + 952 + if (full) { 953 + /* Fetch device state */ 954 + rc = zl3073x_dev_state_fetch(zldev); 955 + if (rc) 956 + return rc; 957 + 958 + /* Setup phase offset measurement block */ 959 + rc = zl3073x_dev_phase_meas_setup(zldev); 960 + if (rc) { 961 + dev_err(zldev->dev, 962 + "Failed to setup phase measurement\n"); 963 + return rc; 964 + } 965 + } 966 + 967 + /* Register all DPLLs */ 968 + list_for_each_entry(zldpll, &zldev->dplls, list) { 969 + rc = zl3073x_dpll_register(zldpll); 970 + if (rc) { 971 + dev_err_probe(zldev->dev, rc, 972 + "Failed to register DPLL%u\n", 973 + zldpll->id); 974 + return rc; 975 + } 976 + } 977 + 978 + /* Perform initial firmware fine phase correction */ 979 + rc = zl3073x_dpll_init_fine_phase_adjust(zldev); 980 + if (rc) { 981 + dev_err_probe(zldev->dev, rc, 982 + "Failed to init fine phase correction\n"); 983 + return rc; 984 + } 985 + 986 + /* Start monitoring */ 987 + kthread_queue_delayed_work(zldev->kworker, &zldev->work, 0); 988 + 989 + return 0; 990 + } 991 + 992 + /** 993 + * zl3073x_dev_stop - Stop normal operation 994 + * @zldev: zl3073x device pointer 995 + * 996 + * The function stops the normal operation that mean deregistration of all 997 + * DPLLs and their pins and stop monitoring. 998 + * 999 + * Return: 0 on success, <0 on error 1000 + */ 1001 + void zl3073x_dev_stop(struct zl3073x_dev *zldev) 1002 + { 1003 + struct zl3073x_dpll *zldpll; 1004 + 1005 + /* Stop monitoring */ 1006 + kthread_cancel_delayed_work_sync(&zldev->work); 1007 + 1008 + /* Unregister all DPLLs */ 1009 + list_for_each_entry(zldpll, &zldev->dplls, list) { 1010 + if (zldpll->dpll_dev) 1011 + zl3073x_dpll_unregister(zldpll); 1012 + } 1013 + } 1014 + 1015 + static void zl3073x_dev_dpll_fini(void *ptr) 1016 + { 1017 + struct zl3073x_dpll *zldpll, *next; 1018 + struct zl3073x_dev *zldev = ptr; 1019 + 1020 + /* Stop monitoring and unregister DPLLs */ 1021 + zl3073x_dev_stop(zldev); 1022 + 1023 + /* Destroy monitoring thread */ 1024 + if (zldev->kworker) { 1025 + kthread_destroy_worker(zldev->kworker); 1026 + zldev->kworker = NULL; 1027 + } 1028 + 1029 + /* Free all DPLLs */ 1030 + list_for_each_entry_safe(zldpll, next, &zldev->dplls, list) { 1031 + list_del(&zldpll->list); 1032 + zl3073x_dpll_free(zldpll); 1033 + } 1034 + } 1035 + 1036 + static int 1037 + zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls) 1038 + { 1039 + struct kthread_worker *kworker; 1040 + struct zl3073x_dpll *zldpll; 1041 + unsigned int i; 1042 + int rc; 1043 + 1044 + INIT_LIST_HEAD(&zldev->dplls); 1045 + 1046 + /* Allocate all DPLLs */ 1047 + for (i = 0; i < num_dplls; i++) { 1048 + zldpll = zl3073x_dpll_alloc(zldev, i); 1049 + if (IS_ERR(zldpll)) { 1050 + dev_err_probe(zldev->dev, PTR_ERR(zldpll), 1051 + "Failed to alloc DPLL%u\n", i); 1052 + rc = PTR_ERR(zldpll); 1053 + goto error; 1054 + } 1055 + 1056 + list_add_tail(&zldpll->list, &zldev->dplls); 1057 + } 1058 + 1059 + /* Initialize monitoring thread */ 1060 + kthread_init_delayed_work(&zldev->work, zl3073x_dev_periodic_work); 1061 + kworker = kthread_run_worker(0, "zl3073x-%s", dev_name(zldev->dev)); 1062 + if (IS_ERR(kworker)) { 1063 + rc = PTR_ERR(kworker); 1064 + goto error; 1065 + } 1066 + zldev->kworker = kworker; 1067 + 1068 + /* Start normal operation */ 1069 + rc = zl3073x_dev_start(zldev, true); 1070 + if (rc) { 1071 + dev_err_probe(zldev->dev, rc, "Failed to start device\n"); 1072 + goto error; 1073 + } 1074 + 1075 + /* Add devres action to release DPLL related resources */ 1076 + rc = devm_add_action_or_reset(zldev->dev, zl3073x_dev_dpll_fini, zldev); 1077 + if (rc) 1078 + goto error; 1079 + 1080 + return 0; 1081 + 1082 + error: 1083 + zl3073x_dev_dpll_fini(zldev); 1084 + 1085 + return rc; 997 1086 } 998 1087 999 1088 /** ··· 1215 998 if (rc) 1216 999 return dev_err_probe(zldev->dev, rc, 1217 1000 "Failed to initialize mutex\n"); 1218 - 1219 - /* Fetch device state */ 1220 - rc = zl3073x_dev_state_fetch(zldev); 1221 - if (rc) 1222 - return rc; 1223 - 1224 - /* Setup phase offset measurement block */ 1225 - rc = zl3073x_dev_phase_meas_setup(zldev, chip_info->num_channels); 1226 - if (rc) 1227 - return dev_err_probe(zldev->dev, rc, 1228 - "Failed to setup phase measurement\n"); 1229 1001 1230 1002 /* Register DPLL channels */ 1231 1003 rc = zl3073x_devm_dpll_init(zldev, chip_info->num_channels);
+33
drivers/dpll/zl3073x/core.h
··· 3 3 #ifndef _ZL3073X_CORE_H 4 4 #define _ZL3073X_CORE_H 5 5 6 + #include <linux/bitfield.h> 6 7 #include <linux/kthread.h> 7 8 #include <linux/list.h> 8 9 #include <linux/mutex.h> ··· 112 111 int zl3073x_dev_probe(struct zl3073x_dev *zldev, 113 112 const struct zl3073x_chip_info *chip_info); 114 113 114 + int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full); 115 + void zl3073x_dev_stop(struct zl3073x_dev *zldev); 116 + 115 117 /********************** 116 118 * Registers operations 117 119 **********************/ 120 + 121 + /** 122 + * struct zl3073x_hwreg_seq_item - HW register write sequence item 123 + * @addr: HW register to be written 124 + * @value: value to be written to HW register 125 + * @mask: bitmask indicating bits to be updated 126 + * @wait: number of ms to wait after register write 127 + */ 128 + struct zl3073x_hwreg_seq_item { 129 + u32 addr; 130 + u32 value; 131 + u32 mask; 132 + u32 wait; 133 + }; 134 + 135 + #define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \ 136 + { \ 137 + .addr = _addr, \ 138 + .value = FIELD_PREP_CONST(_mask, _value), \ 139 + .mask = _mask, \ 140 + .wait = _wait, \ 141 + } 118 142 119 143 int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val, 120 144 unsigned int mask_reg, u16 mask_val); ··· 152 126 int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val); 153 127 int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val); 154 128 int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val); 129 + int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value); 130 + int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value); 131 + int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value, 132 + u32 mask); 133 + int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev, 134 + const struct zl3073x_hwreg_seq_item *seq, 135 + size_t num_items); 155 136 156 137 /***************** 157 138 * Misc operations
+144 -12
drivers/dpll/zl3073x/devlink.c
··· 9 9 #include "core.h" 10 10 #include "devlink.h" 11 11 #include "dpll.h" 12 + #include "flash.h" 13 + #include "fw.h" 12 14 #include "regs.h" 13 15 14 16 /** ··· 88 86 struct netlink_ext_ack *extack) 89 87 { 90 88 struct zl3073x_dev *zldev = devlink_priv(devlink); 91 - struct zl3073x_dpll *zldpll; 92 89 93 90 if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) 94 91 return -EOPNOTSUPP; 95 92 96 - /* Unregister all DPLLs */ 97 - list_for_each_entry(zldpll, &zldev->dplls, list) 98 - zl3073x_dpll_unregister(zldpll); 93 + /* Stop normal operation */ 94 + zl3073x_dev_stop(zldev); 99 95 100 96 return 0; 101 97 } ··· 107 107 { 108 108 struct zl3073x_dev *zldev = devlink_priv(devlink); 109 109 union devlink_param_value val; 110 - struct zl3073x_dpll *zldpll; 111 110 int rc; 112 111 113 112 if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) ··· 124 125 zldev->clock_id = val.vu64; 125 126 } 126 127 127 - /* Re-register all DPLLs */ 128 - list_for_each_entry(zldpll, &zldev->dplls, list) { 129 - rc = zl3073x_dpll_register(zldpll); 130 - if (rc) 131 - dev_warn(zldev->dev, 132 - "Failed to re-register DPLL%u\n", zldpll->id); 133 - } 128 + /* Restart normal operation */ 129 + rc = zl3073x_dev_start(zldev, false); 130 + if (rc) 131 + dev_warn(zldev->dev, "Failed to re-start normal operation\n"); 134 132 135 133 *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT); 136 134 137 135 return 0; 136 + } 137 + 138 + void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg, 139 + const char *component, u32 done, u32 total) 140 + { 141 + struct devlink *devlink = priv_to_devlink(zldev); 142 + 143 + devlink_flash_update_status_notify(devlink, msg, component, done, 144 + total); 145 + } 146 + 147 + /** 148 + * zl3073x_devlink_flash_prepare - Prepare and enter flash mode 149 + * @zldev: zl3073x device pointer 150 + * @zlfw: pointer to loaded firmware 151 + * @extack: netlink extack pointer to report errors 152 + * 153 + * The function stops normal operation and switches the device to flash mode. 154 + * If an error occurs the normal operation is resumed. 155 + * 156 + * Return: 0 on success, <0 on error 157 + */ 158 + static int 159 + zl3073x_devlink_flash_prepare(struct zl3073x_dev *zldev, 160 + struct zl3073x_fw *zlfw, 161 + struct netlink_ext_ack *extack) 162 + { 163 + struct zl3073x_fw_component *util; 164 + int rc; 165 + 166 + util = zlfw->component[ZL_FW_COMPONENT_UTIL]; 167 + if (!util) { 168 + zl3073x_devlink_flash_notify(zldev, 169 + "Utility is missing in firmware", 170 + NULL, 0, 0); 171 + zl3073x_fw_free(zlfw); 172 + return -ENOEXEC; 173 + } 174 + 175 + /* Stop normal operation prior entering flash mode */ 176 + zl3073x_dev_stop(zldev); 177 + 178 + rc = zl3073x_flash_mode_enter(zldev, util->data, util->size, extack); 179 + if (rc) { 180 + zl3073x_devlink_flash_notify(zldev, 181 + "Failed to enter flash mode", 182 + NULL, 0, 0); 183 + 184 + /* Resume normal operation */ 185 + zl3073x_dev_start(zldev, true); 186 + 187 + return rc; 188 + } 189 + 190 + return 0; 191 + } 192 + 193 + /** 194 + * zl3073x_devlink_flash_finish - Leave flash mode and resume normal operation 195 + * @zldev: zl3073x device pointer 196 + * @extack: netlink extack pointer to report errors 197 + * 198 + * The function switches the device back to standard mode and resumes normal 199 + * operation. 200 + * 201 + * Return: 0 on success, <0 on error 202 + */ 203 + static int 204 + zl3073x_devlink_flash_finish(struct zl3073x_dev *zldev, 205 + struct netlink_ext_ack *extack) 206 + { 207 + int rc; 208 + 209 + /* Reset device CPU to normal mode */ 210 + zl3073x_flash_mode_leave(zldev, extack); 211 + 212 + /* Resume normal operation */ 213 + rc = zl3073x_dev_start(zldev, true); 214 + if (rc) 215 + zl3073x_devlink_flash_notify(zldev, 216 + "Failed to start normal operation", 217 + NULL, 0, 0); 218 + 219 + return rc; 220 + } 221 + 222 + /** 223 + * zl3073x_devlink_flash_update - Devlink flash update callback 224 + * @devlink: devlink structure pointer 225 + * @params: flashing parameters pointer 226 + * @extack: netlink extack pointer to report errors 227 + * 228 + * Return: 0 on success, <0 on error 229 + */ 230 + static int 231 + zl3073x_devlink_flash_update(struct devlink *devlink, 232 + struct devlink_flash_update_params *params, 233 + struct netlink_ext_ack *extack) 234 + { 235 + struct zl3073x_dev *zldev = devlink_priv(devlink); 236 + struct zl3073x_fw *zlfw; 237 + int rc = 0; 238 + 239 + zlfw = zl3073x_fw_load(zldev, params->fw->data, params->fw->size, 240 + extack); 241 + if (IS_ERR(zlfw)) { 242 + zl3073x_devlink_flash_notify(zldev, "Failed to load firmware", 243 + NULL, 0, 0); 244 + rc = PTR_ERR(zlfw); 245 + goto finish; 246 + } 247 + 248 + /* Stop normal operation and enter flash mode */ 249 + rc = zl3073x_devlink_flash_prepare(zldev, zlfw, extack); 250 + if (rc) 251 + goto finish; 252 + 253 + rc = zl3073x_fw_flash(zldev, zlfw, extack); 254 + if (rc) { 255 + zl3073x_devlink_flash_finish(zldev, extack); 256 + goto finish; 257 + } 258 + 259 + /* Resume normal mode */ 260 + rc = zl3073x_devlink_flash_finish(zldev, extack); 261 + 262 + finish: 263 + if (!IS_ERR(zlfw)) 264 + zl3073x_fw_free(zlfw); 265 + 266 + zl3073x_devlink_flash_notify(zldev, 267 + rc ? "Flashing failed" : "Flashing done", 268 + NULL, 0, 0); 269 + 270 + return rc; 138 271 } 139 272 140 273 static const struct devlink_ops zl3073x_devlink_ops = { ··· 274 143 .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), 275 144 .reload_down = zl3073x_devlink_reload_down, 276 145 .reload_up = zl3073x_devlink_reload_up, 146 + .flash_update = zl3073x_devlink_flash_update, 277 147 }; 278 148 279 149 static void
+3
drivers/dpll/zl3073x/devlink.h
··· 9 9 10 10 int zl3073x_devlink_register(struct zl3073x_dev *zldev); 11 11 12 + void zl3073x_devlink_flash_notify(struct zl3073x_dev *zldev, const char *msg, 13 + const char *component, u32 done, u32 total); 14 + 12 15 #endif /* _ZL3073X_DEVLINK_H */
+666
drivers/dpll/zl3073x/flash.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <linux/array_size.h> 4 + #include <linux/bitfield.h> 5 + #include <linux/bits.h> 6 + #include <linux/delay.h> 7 + #include <linux/dev_printk.h> 8 + #include <linux/errno.h> 9 + #include <linux/jiffies.h> 10 + #include <linux/minmax.h> 11 + #include <linux/netlink.h> 12 + #include <linux/sched/signal.h> 13 + #include <linux/sizes.h> 14 + #include <linux/sprintf.h> 15 + #include <linux/string.h> 16 + #include <linux/types.h> 17 + #include <linux/unaligned.h> 18 + #include <net/devlink.h> 19 + 20 + #include "core.h" 21 + #include "devlink.h" 22 + #include "flash.h" 23 + 24 + #define ZL_FLASH_ERR_PFX "FW update failed: " 25 + #define ZL_FLASH_ERR_MSG(_extack, _msg, ...) \ 26 + NL_SET_ERR_MSG_FMT_MOD((_extack), ZL_FLASH_ERR_PFX _msg, \ 27 + ## __VA_ARGS__) 28 + 29 + /** 30 + * zl3073x_flash_download - Download image block to device memory 31 + * @zldev: zl3073x device structure 32 + * @component: name of the component to be downloaded 33 + * @addr: device memory target address 34 + * @data: pointer to data to download 35 + * @size: size of data to download 36 + * @extack: netlink extack pointer to report errors 37 + * 38 + * Return: 0 on success, <0 on error 39 + */ 40 + static int 41 + zl3073x_flash_download(struct zl3073x_dev *zldev, const char *component, 42 + u32 addr, const void *data, size_t size, 43 + struct netlink_ext_ack *extack) 44 + { 45 + #define ZL_CHECK_DELAY 5000 /* Check for interrupt each 5 seconds */ 46 + unsigned long check_time; 47 + const void *ptr, *end; 48 + int rc = 0; 49 + 50 + dev_dbg(zldev->dev, "Downloading %zu bytes to device memory at 0x%0x\n", 51 + size, addr); 52 + 53 + check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY); 54 + 55 + for (ptr = data, end = data + size; ptr < end; ptr += 4, addr += 4) { 56 + /* Write current word to HW memory */ 57 + rc = zl3073x_write_hwreg(zldev, addr, 58 + get_unaligned((u32 *)ptr)); 59 + if (rc) { 60 + ZL_FLASH_ERR_MSG(extack, 61 + "failed to write to memory at 0x%0x", 62 + addr); 63 + return rc; 64 + } 65 + 66 + if (time_is_before_jiffies(check_time)) { 67 + if (signal_pending(current)) { 68 + ZL_FLASH_ERR_MSG(extack, 69 + "Flashing interrupted"); 70 + return -EINTR; 71 + } 72 + 73 + check_time = jiffies + msecs_to_jiffies(ZL_CHECK_DELAY); 74 + } 75 + 76 + /* Report status each 1 kB block */ 77 + if ((ptr - data) % 1024 == 0) 78 + zl3073x_devlink_flash_notify(zldev, "Downloading image", 79 + component, ptr - data, 80 + size); 81 + } 82 + 83 + zl3073x_devlink_flash_notify(zldev, "Downloading image", component, 84 + ptr - data, size); 85 + 86 + dev_dbg(zldev->dev, "%zu bytes downloaded to device memory\n", size); 87 + 88 + return rc; 89 + } 90 + 91 + /** 92 + * zl3073x_flash_error_check - Check for flash utility errors 93 + * @zldev: zl3073x device structure 94 + * @extack: netlink extack pointer to report errors 95 + * 96 + * The function checks for errors detected by the flash utility and 97 + * reports them if any were found. 98 + * 99 + * Return: 0 on success, -EIO when errors are detected 100 + */ 101 + static int 102 + zl3073x_flash_error_check(struct zl3073x_dev *zldev, 103 + struct netlink_ext_ack *extack) 104 + { 105 + u32 count, cause; 106 + int rc; 107 + 108 + rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_COUNT, &count); 109 + if (rc) 110 + return rc; 111 + else if (!count) 112 + return 0; /* No error */ 113 + 114 + rc = zl3073x_read_u32(zldev, ZL_REG_ERROR_CAUSE, &cause); 115 + if (rc) 116 + return rc; 117 + 118 + /* Report errors */ 119 + ZL_FLASH_ERR_MSG(extack, 120 + "utility error occurred: count=%u cause=0x%x", count, 121 + cause); 122 + 123 + return -EIO; 124 + } 125 + 126 + /** 127 + * zl3073x_flash_wait_ready - Check or wait for utility to be ready to flash 128 + * @zldev: zl3073x device structure 129 + * @timeout_ms: timeout for the waiting 130 + * 131 + * Return: 0 on success, <0 on error 132 + */ 133 + static int 134 + zl3073x_flash_wait_ready(struct zl3073x_dev *zldev, unsigned int timeout_ms) 135 + { 136 + #define ZL_FLASH_POLL_DELAY_MS 100 137 + unsigned long timeout; 138 + int rc, i; 139 + 140 + dev_dbg(zldev->dev, "Waiting for flashing to be ready\n"); 141 + 142 + timeout = jiffies + msecs_to_jiffies(timeout_ms); 143 + 144 + for (i = 0; time_is_after_jiffies(timeout); i++) { 145 + u8 value; 146 + 147 + /* Check for interrupt each 1s */ 148 + if (i > 9) { 149 + if (signal_pending(current)) 150 + return -EINTR; 151 + i = 0; 152 + } 153 + 154 + rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value); 155 + if (rc) 156 + return rc; 157 + 158 + value = FIELD_GET(ZL_WRITE_FLASH_OP, value); 159 + 160 + if (value == ZL_WRITE_FLASH_OP_DONE) 161 + return 0; /* Successfully done */ 162 + 163 + msleep(ZL_FLASH_POLL_DELAY_MS); 164 + } 165 + 166 + return -ETIMEDOUT; 167 + } 168 + 169 + /** 170 + * zl3073x_flash_cmd_wait - Perform flash operation and wait for finish 171 + * @zldev: zl3073x device structure 172 + * @operation: operation to perform 173 + * @extack: netlink extack pointer to report errors 174 + * 175 + * Return: 0 on success, <0 on error 176 + */ 177 + static int 178 + zl3073x_flash_cmd_wait(struct zl3073x_dev *zldev, u32 operation, 179 + struct netlink_ext_ack *extack) 180 + { 181 + #define ZL_FLASH_PHASE1_TIMEOUT_MS 60000 /* up to 1 minute */ 182 + #define ZL_FLASH_PHASE2_TIMEOUT_MS 120000 /* up to 2 minutes */ 183 + u8 value; 184 + int rc; 185 + 186 + dev_dbg(zldev->dev, "Sending flash command: 0x%x\n", operation); 187 + 188 + rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE1_TIMEOUT_MS); 189 + if (rc) 190 + return rc; 191 + 192 + /* Issue the requested operation */ 193 + rc = zl3073x_read_u8(zldev, ZL_REG_WRITE_FLASH, &value); 194 + if (rc) 195 + return rc; 196 + 197 + value &= ~ZL_WRITE_FLASH_OP; 198 + value |= FIELD_PREP(ZL_WRITE_FLASH_OP, operation); 199 + 200 + rc = zl3073x_write_u8(zldev, ZL_REG_WRITE_FLASH, value); 201 + if (rc) 202 + return rc; 203 + 204 + /* Wait for command completion */ 205 + rc = zl3073x_flash_wait_ready(zldev, ZL_FLASH_PHASE2_TIMEOUT_MS); 206 + if (rc) 207 + return rc; 208 + 209 + return zl3073x_flash_error_check(zldev, extack); 210 + } 211 + 212 + /** 213 + * zl3073x_flash_get_sector_size - Get flash sector size 214 + * @zldev: zl3073x device structure 215 + * @sector_size: sector size returned by the function 216 + * 217 + * The function reads the flash sector size detected by flash utility and 218 + * stores it into @sector_size. 219 + * 220 + * Return: 0 on success, <0 on error 221 + */ 222 + static int 223 + zl3073x_flash_get_sector_size(struct zl3073x_dev *zldev, size_t *sector_size) 224 + { 225 + u8 flash_info; 226 + int rc; 227 + 228 + rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_INFO, &flash_info); 229 + if (rc) 230 + return rc; 231 + 232 + switch (FIELD_GET(ZL_FLASH_INFO_SECTOR_SIZE, flash_info)) { 233 + case ZL_FLASH_INFO_SECTOR_4K: 234 + *sector_size = SZ_4K; 235 + break; 236 + case ZL_FLASH_INFO_SECTOR_64K: 237 + *sector_size = SZ_64K; 238 + break; 239 + default: 240 + rc = -EINVAL; 241 + break; 242 + } 243 + 244 + return rc; 245 + } 246 + 247 + /** 248 + * zl3073x_flash_block - Download and flash memory block 249 + * @zldev: zl3073x device structure 250 + * @component: component name 251 + * @operation: flash operation to perform 252 + * @page: destination flash page 253 + * @addr: device memory address to load data 254 + * @data: pointer to data to be flashed 255 + * @size: size of data 256 + * @extack: netlink extack pointer to report errors 257 + * 258 + * The function downloads the memory block given by the @data pointer and 259 + * the size @size and flashes it into internal memory on flash page @page. 260 + * The internal flash operation performed by the firmware is specified by 261 + * the @operation parameter. 262 + * 263 + * Return: 0 on success, <0 on error 264 + */ 265 + static int 266 + zl3073x_flash_block(struct zl3073x_dev *zldev, const char *component, 267 + u32 operation, u32 page, u32 addr, const void *data, 268 + size_t size, struct netlink_ext_ack *extack) 269 + { 270 + int rc; 271 + 272 + /* Download block to device memory */ 273 + rc = zl3073x_flash_download(zldev, component, addr, data, size, extack); 274 + if (rc) 275 + return rc; 276 + 277 + /* Set address to flash from */ 278 + rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_START_ADDR, addr); 279 + if (rc) 280 + return rc; 281 + 282 + /* Set size of block to flash */ 283 + rc = zl3073x_write_u32(zldev, ZL_REG_IMAGE_SIZE, size); 284 + if (rc) 285 + return rc; 286 + 287 + /* Set destination page to flash */ 288 + rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, page); 289 + if (rc) 290 + return rc; 291 + 292 + /* Set filling pattern */ 293 + rc = zl3073x_write_u32(zldev, ZL_REG_FILL_PATTERN, U32_MAX); 294 + if (rc) 295 + return rc; 296 + 297 + zl3073x_devlink_flash_notify(zldev, "Flashing image", component, 0, 298 + size); 299 + 300 + dev_dbg(zldev->dev, "Flashing %zu bytes to page %u\n", size, page); 301 + 302 + /* Execute sectors flash operation */ 303 + rc = zl3073x_flash_cmd_wait(zldev, operation, extack); 304 + if (rc) 305 + return rc; 306 + 307 + zl3073x_devlink_flash_notify(zldev, "Flashing image", component, size, 308 + size); 309 + 310 + return 0; 311 + } 312 + 313 + /** 314 + * zl3073x_flash_sectors - Flash sectors 315 + * @zldev: zl3073x device structure 316 + * @component: component name 317 + * @page: destination flash page 318 + * @addr: device memory address to load data 319 + * @data: pointer to data to be flashed 320 + * @size: size of data 321 + * @extack: netlink extack pointer to report errors 322 + * 323 + * The function flashes given @data with size of @size to the internal flash 324 + * memory block starting from page @page. The function uses sector flash 325 + * method and has to take into account the flash sector size reported by 326 + * flashing utility. Input data are spliced into blocks according this 327 + * sector size and each block is flashed separately. 328 + * 329 + * Return: 0 on success, <0 on error 330 + */ 331 + int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component, 332 + u32 page, u32 addr, const void *data, size_t size, 333 + struct netlink_ext_ack *extack) 334 + { 335 + #define ZL_FLASH_MAX_BLOCK_SIZE 0x0001E000 336 + #define ZL_FLASH_PAGE_SIZE 256 337 + size_t max_block_size, block_size, sector_size; 338 + const void *ptr, *end; 339 + int rc; 340 + 341 + /* Get flash sector size */ 342 + rc = zl3073x_flash_get_sector_size(zldev, &sector_size); 343 + if (rc) { 344 + ZL_FLASH_ERR_MSG(extack, "Failed to get flash sector size"); 345 + return rc; 346 + } 347 + 348 + /* Determine max block size depending on sector size */ 349 + max_block_size = ALIGN_DOWN(ZL_FLASH_MAX_BLOCK_SIZE, sector_size); 350 + 351 + for (ptr = data, end = data + size; ptr < end; ptr += block_size) { 352 + char comp_str[32]; 353 + 354 + block_size = min_t(size_t, max_block_size, end - ptr); 355 + 356 + /* Add suffix '-partN' if the requested component size is 357 + * greater than max_block_size. 358 + */ 359 + if (max_block_size < size) 360 + snprintf(comp_str, sizeof(comp_str), "%s-part%zu", 361 + component, (ptr - data) / max_block_size + 1); 362 + else 363 + strscpy(comp_str, component); 364 + 365 + /* Flash the memory block */ 366 + rc = zl3073x_flash_block(zldev, comp_str, 367 + ZL_WRITE_FLASH_OP_SECTORS, page, addr, 368 + ptr, block_size, extack); 369 + if (rc) 370 + goto finish; 371 + 372 + /* Move to next page */ 373 + page += block_size / ZL_FLASH_PAGE_SIZE; 374 + } 375 + 376 + finish: 377 + zl3073x_devlink_flash_notify(zldev, 378 + rc ? "Flashing failed" : "Flashing done", 379 + component, 0, 0); 380 + 381 + return rc; 382 + } 383 + 384 + /** 385 + * zl3073x_flash_page - Flash page 386 + * @zldev: zl3073x device structure 387 + * @component: component name 388 + * @page: destination flash page 389 + * @addr: device memory address to load data 390 + * @data: pointer to data to be flashed 391 + * @size: size of data 392 + * @extack: netlink extack pointer to report errors 393 + * 394 + * The function flashes given @data with size of @size to the internal flash 395 + * memory block starting with page @page. 396 + * 397 + * Return: 0 on success, <0 on error 398 + */ 399 + int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component, 400 + u32 page, u32 addr, const void *data, size_t size, 401 + struct netlink_ext_ack *extack) 402 + { 403 + int rc; 404 + 405 + /* Flash the memory block */ 406 + rc = zl3073x_flash_block(zldev, component, ZL_WRITE_FLASH_OP_PAGE, page, 407 + addr, data, size, extack); 408 + 409 + zl3073x_devlink_flash_notify(zldev, 410 + rc ? "Flashing failed" : "Flashing done", 411 + component, 0, 0); 412 + 413 + return rc; 414 + } 415 + 416 + /** 417 + * zl3073x_flash_page_copy - Copy flash page 418 + * @zldev: zl3073x device structure 419 + * @component: component name 420 + * @src_page: source page to copy 421 + * @dst_page: destination page 422 + * @extack: netlink extack pointer to report errors 423 + * 424 + * The function copies one flash page specified by @src_page into the flash 425 + * page specified by @dst_page. 426 + * 427 + * Return: 0 on success, <0 on error 428 + */ 429 + int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component, 430 + u32 src_page, u32 dst_page, 431 + struct netlink_ext_ack *extack) 432 + { 433 + int rc; 434 + 435 + /* Set source page to be copied */ 436 + rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_READ, src_page); 437 + if (rc) 438 + return rc; 439 + 440 + /* Set destination page for the copy */ 441 + rc = zl3073x_write_u32(zldev, ZL_REG_FLASH_INDEX_WRITE, dst_page); 442 + if (rc) 443 + return rc; 444 + 445 + /* Perform copy operation */ 446 + rc = zl3073x_flash_cmd_wait(zldev, ZL_WRITE_FLASH_OP_COPY_PAGE, extack); 447 + if (rc) 448 + ZL_FLASH_ERR_MSG(extack, "Failed to copy page %u to page %u", 449 + src_page, dst_page); 450 + 451 + return rc; 452 + } 453 + 454 + /** 455 + * zl3073x_flash_mode_verify - Check flash utility 456 + * @zldev: zl3073x device structure 457 + * 458 + * Return: 0 if the flash utility is ready, <0 on error 459 + */ 460 + static int 461 + zl3073x_flash_mode_verify(struct zl3073x_dev *zldev) 462 + { 463 + u8 family, release; 464 + u32 hash; 465 + int rc; 466 + 467 + rc = zl3073x_read_u32(zldev, ZL_REG_FLASH_HASH, &hash); 468 + if (rc) 469 + return rc; 470 + 471 + rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_FAMILY, &family); 472 + if (rc) 473 + return rc; 474 + 475 + rc = zl3073x_read_u8(zldev, ZL_REG_FLASH_RELEASE, &release); 476 + if (rc) 477 + return rc; 478 + 479 + dev_dbg(zldev->dev, 480 + "Flash utility check: hash 0x%08x, fam 0x%02x, rel 0x%02x\n", 481 + hash, family, release); 482 + 483 + /* Return success for correct family */ 484 + return (family == 0x21) ? 0 : -ENODEV; 485 + } 486 + 487 + static int 488 + zl3073x_flash_host_ctrl_enable(struct zl3073x_dev *zldev) 489 + { 490 + u8 host_ctrl; 491 + int rc; 492 + 493 + /* Enable host control */ 494 + rc = zl3073x_read_u8(zldev, ZL_REG_HOST_CONTROL, &host_ctrl); 495 + if (rc) 496 + return rc; 497 + 498 + host_ctrl |= ZL_HOST_CONTROL_ENABLE; 499 + 500 + return zl3073x_write_u8(zldev, ZL_REG_HOST_CONTROL, host_ctrl); 501 + } 502 + 503 + /** 504 + * zl3073x_flash_mode_enter - Switch the device to flash mode 505 + * @zldev: zl3073x device structure 506 + * @util_ptr: buffer with flash utility 507 + * @util_size: size of buffer with flash utility 508 + * @extack: netlink extack pointer to report errors 509 + * 510 + * The function prepares and switches the device into flash mode. 511 + * 512 + * The procedure: 513 + * 1) Stop device CPU by specific HW register sequence 514 + * 2) Download flash utility to device memory 515 + * 3) Resume device CPU by specific HW register sequence 516 + * 4) Check communication with flash utility 517 + * 5) Enable host control necessary to access flash API 518 + * 6) Check for potential error detected by the utility 519 + * 520 + * The API provided by normal firmware is not available in flash mode 521 + * so the caller has to ensure that this API is not used in this mode. 522 + * 523 + * After performing flash operation the caller should call 524 + * @zl3073x_flash_mode_leave to return back to normal operation. 525 + * 526 + * Return: 0 on success, <0 on error. 527 + */ 528 + int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr, 529 + size_t util_size, struct netlink_ext_ack *extack) 530 + { 531 + /* Sequence to be written prior utility download */ 532 + static const struct zl3073x_hwreg_seq_item pre_seq[] = { 533 + HWREG_SEQ_ITEM(0x80000400, 1, BIT(0), 0), 534 + HWREG_SEQ_ITEM(0x80206340, 1, BIT(4), 0), 535 + HWREG_SEQ_ITEM(0x10000000, 1, BIT(2), 0), 536 + HWREG_SEQ_ITEM(0x10000024, 0x00000001, U32_MAX, 0), 537 + HWREG_SEQ_ITEM(0x10000020, 0x00000001, U32_MAX, 0), 538 + HWREG_SEQ_ITEM(0x10000000, 1, BIT(10), 1000), 539 + }; 540 + /* Sequence to be written after utility download */ 541 + static const struct zl3073x_hwreg_seq_item post_seq[] = { 542 + HWREG_SEQ_ITEM(0x10400004, 0x000000C0, U32_MAX, 0), 543 + HWREG_SEQ_ITEM(0x10400008, 0x00000000, U32_MAX, 0), 544 + HWREG_SEQ_ITEM(0x10400010, 0x20000000, U32_MAX, 0), 545 + HWREG_SEQ_ITEM(0x10400014, 0x20000004, U32_MAX, 0), 546 + HWREG_SEQ_ITEM(0x10000000, 1, GENMASK(10, 9), 0), 547 + HWREG_SEQ_ITEM(0x10000020, 0x00000000, U32_MAX, 0), 548 + HWREG_SEQ_ITEM(0x10000000, 0, BIT(0), 1000), 549 + }; 550 + int rc; 551 + 552 + zl3073x_devlink_flash_notify(zldev, "Prepare flash mode", "utility", 553 + 0, 0); 554 + 555 + /* Execure pre-load sequence */ 556 + rc = zl3073x_write_hwreg_seq(zldev, pre_seq, ARRAY_SIZE(pre_seq)); 557 + if (rc) { 558 + ZL_FLASH_ERR_MSG(extack, "cannot execute pre-load sequence"); 559 + goto error; 560 + } 561 + 562 + /* Download utility image to device memory */ 563 + rc = zl3073x_flash_download(zldev, "utility", 0x20000000, util_ptr, 564 + util_size, extack); 565 + if (rc) { 566 + ZL_FLASH_ERR_MSG(extack, "cannot download flash utility"); 567 + goto error; 568 + } 569 + 570 + /* Execute post-load sequence */ 571 + rc = zl3073x_write_hwreg_seq(zldev, post_seq, ARRAY_SIZE(post_seq)); 572 + if (rc) { 573 + ZL_FLASH_ERR_MSG(extack, "cannot execute post-load sequence"); 574 + goto error; 575 + } 576 + 577 + /* Check that utility identifies itself correctly */ 578 + rc = zl3073x_flash_mode_verify(zldev); 579 + if (rc) { 580 + ZL_FLASH_ERR_MSG(extack, "flash utility check failed"); 581 + goto error; 582 + } 583 + 584 + /* Enable host control */ 585 + rc = zl3073x_flash_host_ctrl_enable(zldev); 586 + if (rc) { 587 + ZL_FLASH_ERR_MSG(extack, "cannot enable host control"); 588 + goto error; 589 + } 590 + 591 + zl3073x_devlink_flash_notify(zldev, "Flash mode enabled", "utility", 592 + 0, 0); 593 + 594 + return 0; 595 + 596 + error: 597 + zl3073x_flash_mode_leave(zldev, extack); 598 + 599 + return rc; 600 + } 601 + 602 + /** 603 + * zl3073x_flash_mode_leave - Leave flash mode 604 + * @zldev: zl3073x device structure 605 + * @extack: netlink extack pointer to report errors 606 + * 607 + * The function instructs the device to leave the flash mode and 608 + * to return back to normal operation. 609 + * 610 + * The procedure: 611 + * 1) Set reset flag 612 + * 2) Reset the device CPU by specific HW register sequence 613 + * 3) Wait for the device to be ready 614 + * 4) Check the reset flag was cleared 615 + * 616 + * Return: 0 on success, <0 on error 617 + */ 618 + int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev, 619 + struct netlink_ext_ack *extack) 620 + { 621 + /* Sequence to be written after flash */ 622 + static const struct zl3073x_hwreg_seq_item fw_reset_seq[] = { 623 + HWREG_SEQ_ITEM(0x80000404, 1, BIT(0), 0), 624 + HWREG_SEQ_ITEM(0x80000410, 1, BIT(0), 0), 625 + }; 626 + u8 reset_status; 627 + int rc; 628 + 629 + zl3073x_devlink_flash_notify(zldev, "Leaving flash mode", "utility", 630 + 0, 0); 631 + 632 + /* Read reset status register */ 633 + rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status); 634 + if (rc) 635 + return rc; 636 + 637 + /* Set reset bit */ 638 + reset_status |= ZL_REG_RESET_STATUS_RESET; 639 + 640 + /* Update reset status register */ 641 + rc = zl3073x_write_u8(zldev, ZL_REG_RESET_STATUS, reset_status); 642 + if (rc) 643 + return rc; 644 + 645 + /* We do not check the return value here as the sequence resets 646 + * the device CPU and the last write always return an error. 647 + */ 648 + zl3073x_write_hwreg_seq(zldev, fw_reset_seq, ARRAY_SIZE(fw_reset_seq)); 649 + 650 + /* Wait for the device to be ready */ 651 + msleep(500); 652 + 653 + /* Read again the reset status register */ 654 + rc = zl3073x_read_u8(zldev, ZL_REG_RESET_STATUS, &reset_status); 655 + if (rc) 656 + return rc; 657 + 658 + /* Check the reset bit was cleared */ 659 + if (reset_status & ZL_REG_RESET_STATUS_RESET) { 660 + dev_err(zldev->dev, 661 + "Reset not confirmed after switch to normal mode\n"); 662 + return -EINVAL; 663 + } 664 + 665 + return 0; 666 + }
+29
drivers/dpll/zl3073x/flash.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + 3 + #ifndef __ZL3073X_FLASH_H 4 + #define __ZL3073X_FLASH_H 5 + 6 + #include <linux/types.h> 7 + 8 + struct netlink_ext_ack; 9 + struct zl3073x_dev; 10 + 11 + int zl3073x_flash_mode_enter(struct zl3073x_dev *zldev, const void *util_ptr, 12 + size_t util_size, struct netlink_ext_ack *extack); 13 + 14 + int zl3073x_flash_mode_leave(struct zl3073x_dev *zldev, 15 + struct netlink_ext_ack *extack); 16 + 17 + int zl3073x_flash_page(struct zl3073x_dev *zldev, const char *component, 18 + u32 page, u32 addr, const void *data, size_t size, 19 + struct netlink_ext_ack *extack); 20 + 21 + int zl3073x_flash_page_copy(struct zl3073x_dev *zldev, const char *component, 22 + u32 src_page, u32 dst_page, 23 + struct netlink_ext_ack *extack); 24 + 25 + int zl3073x_flash_sectors(struct zl3073x_dev *zldev, const char *component, 26 + u32 page, u32 addr, const void *data, size_t size, 27 + struct netlink_ext_ack *extack); 28 + 29 + #endif /* __ZL3073X_FLASH_H */
+419
drivers/dpll/zl3073x/fw.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <linux/array_size.h> 4 + #include <linux/build_bug.h> 5 + #include <linux/dev_printk.h> 6 + #include <linux/err.h> 7 + #include <linux/errno.h> 8 + #include <linux/netlink.h> 9 + #include <linux/slab.h> 10 + #include <linux/string.h> 11 + 12 + #include "core.h" 13 + #include "flash.h" 14 + #include "fw.h" 15 + 16 + #define ZL3073X_FW_ERR_PFX "FW load failed: " 17 + #define ZL3073X_FW_ERR_MSG(_extack, _msg, ...) \ 18 + NL_SET_ERR_MSG_FMT_MOD((_extack), ZL3073X_FW_ERR_PFX _msg, \ 19 + ## __VA_ARGS__) 20 + 21 + enum zl3073x_flash_type { 22 + ZL3073X_FLASH_TYPE_NONE = 0, 23 + ZL3073X_FLASH_TYPE_SECTORS, 24 + ZL3073X_FLASH_TYPE_PAGE, 25 + ZL3073X_FLASH_TYPE_PAGE_AND_COPY, 26 + }; 27 + 28 + struct zl3073x_fw_component_info { 29 + const char *name; 30 + size_t max_size; 31 + enum zl3073x_flash_type flash_type; 32 + u32 load_addr; 33 + u32 dest_page; 34 + u32 copy_page; 35 + }; 36 + 37 + static const struct zl3073x_fw_component_info component_info[] = { 38 + [ZL_FW_COMPONENT_UTIL] = { 39 + .name = "utility", 40 + .max_size = 0x2300, 41 + .load_addr = 0x20000000, 42 + .flash_type = ZL3073X_FLASH_TYPE_NONE, 43 + }, 44 + [ZL_FW_COMPONENT_FW1] = { 45 + .name = "firmware1", 46 + .max_size = 0x35000, 47 + .load_addr = 0x20002000, 48 + .flash_type = ZL3073X_FLASH_TYPE_SECTORS, 49 + .dest_page = 0x020, 50 + }, 51 + [ZL_FW_COMPONENT_FW2] = { 52 + .name = "firmware2", 53 + .max_size = 0x0040, 54 + .load_addr = 0x20000000, 55 + .flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY, 56 + .dest_page = 0x3e0, 57 + .copy_page = 0x000, 58 + }, 59 + [ZL_FW_COMPONENT_FW3] = { 60 + .name = "firmware3", 61 + .max_size = 0x0248, 62 + .load_addr = 0x20000400, 63 + .flash_type = ZL3073X_FLASH_TYPE_PAGE_AND_COPY, 64 + .dest_page = 0x3e4, 65 + .copy_page = 0x004, 66 + }, 67 + [ZL_FW_COMPONENT_CFG0] = { 68 + .name = "config0", 69 + .max_size = 0x1000, 70 + .load_addr = 0x20000000, 71 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 72 + .dest_page = 0x3d0, 73 + }, 74 + [ZL_FW_COMPONENT_CFG1] = { 75 + .name = "config1", 76 + .max_size = 0x1000, 77 + .load_addr = 0x20000000, 78 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 79 + .dest_page = 0x3c0, 80 + }, 81 + [ZL_FW_COMPONENT_CFG2] = { 82 + .name = "config2", 83 + .max_size = 0x1000, 84 + .load_addr = 0x20000000, 85 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 86 + .dest_page = 0x3b0, 87 + }, 88 + [ZL_FW_COMPONENT_CFG3] = { 89 + .name = "config3", 90 + .max_size = 0x1000, 91 + .load_addr = 0x20000000, 92 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 93 + .dest_page = 0x3a0, 94 + }, 95 + [ZL_FW_COMPONENT_CFG4] = { 96 + .name = "config4", 97 + .max_size = 0x1000, 98 + .load_addr = 0x20000000, 99 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 100 + .dest_page = 0x390, 101 + }, 102 + [ZL_FW_COMPONENT_CFG5] = { 103 + .name = "config5", 104 + .max_size = 0x1000, 105 + .load_addr = 0x20000000, 106 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 107 + .dest_page = 0x380, 108 + }, 109 + [ZL_FW_COMPONENT_CFG6] = { 110 + .name = "config6", 111 + .max_size = 0x1000, 112 + .load_addr = 0x20000000, 113 + .flash_type = ZL3073X_FLASH_TYPE_PAGE, 114 + .dest_page = 0x370, 115 + }, 116 + }; 117 + 118 + /* Sanity check */ 119 + static_assert(ARRAY_SIZE(component_info) == ZL_FW_NUM_COMPONENTS); 120 + 121 + /** 122 + * zl3073x_fw_component_alloc - Alloc structure to hold firmware component 123 + * @size: size of buffer to store data 124 + * 125 + * Return: pointer to allocated component structure or NULL on error. 126 + */ 127 + static struct zl3073x_fw_component * 128 + zl3073x_fw_component_alloc(size_t size) 129 + { 130 + struct zl3073x_fw_component *comp; 131 + 132 + comp = kzalloc(sizeof(*comp), GFP_KERNEL); 133 + if (!comp) 134 + return NULL; 135 + 136 + comp->size = size; 137 + comp->data = kzalloc(size, GFP_KERNEL); 138 + if (!comp->data) { 139 + kfree(comp); 140 + return NULL; 141 + } 142 + 143 + return comp; 144 + } 145 + 146 + /** 147 + * zl3073x_fw_component_free - Free allocated component structure 148 + * @comp: pointer to allocated component 149 + */ 150 + static void 151 + zl3073x_fw_component_free(struct zl3073x_fw_component *comp) 152 + { 153 + if (comp) 154 + kfree(comp->data); 155 + 156 + kfree(comp); 157 + } 158 + 159 + /** 160 + * zl3073x_fw_component_id_get - Get ID for firmware component name 161 + * @name: input firmware component name 162 + * 163 + * Return: 164 + * - ZL3073X_FW_COMPONENT_* ID for known component name 165 + * - ZL3073X_FW_COMPONENT_INVALID if the given name is unknown 166 + */ 167 + static enum zl3073x_fw_component_id 168 + zl3073x_fw_component_id_get(const char *name) 169 + { 170 + enum zl3073x_fw_component_id id; 171 + 172 + for (id = 0; id < ZL_FW_NUM_COMPONENTS; id++) 173 + if (!strcasecmp(name, component_info[id].name)) 174 + return id; 175 + 176 + return ZL_FW_COMPONENT_INVALID; 177 + } 178 + 179 + /** 180 + * zl3073x_fw_component_load - Load component from firmware source 181 + * @zldev: zl3073x device structure 182 + * @pcomp: pointer to loaded component 183 + * @psrc: data pointer to load component from 184 + * @psize: remaining bytes in buffer 185 + * @extack: netlink extack pointer to report errors 186 + * 187 + * The function allocates single firmware component and loads the data from 188 + * the buffer specified by @psrc and @psize. Pointer to allocated component 189 + * is stored in output @pcomp. Source data pointer @psrc and remaining bytes 190 + * @psize are updated accordingly. 191 + * 192 + * Return: 193 + * * 1 when component was allocated and loaded 194 + * * 0 when there is no component to load 195 + * * <0 on error 196 + */ 197 + static ssize_t 198 + zl3073x_fw_component_load(struct zl3073x_dev *zldev, 199 + struct zl3073x_fw_component **pcomp, 200 + const char **psrc, size_t *psize, 201 + struct netlink_ext_ack *extack) 202 + { 203 + const struct zl3073x_fw_component_info *info; 204 + struct zl3073x_fw_component *comp = NULL; 205 + struct device *dev = zldev->dev; 206 + enum zl3073x_fw_component_id id; 207 + char buf[32], name[16]; 208 + u32 count, size, *dest; 209 + int pos, rc; 210 + 211 + /* Fetch image name and size from input */ 212 + strscpy(buf, *psrc, min(sizeof(buf), *psize)); 213 + rc = sscanf(buf, "%15s %u %n", name, &count, &pos); 214 + if (!rc) { 215 + /* No more data */ 216 + return 0; 217 + } else if (rc == 1 || count > U32_MAX / sizeof(u32)) { 218 + ZL3073X_FW_ERR_MSG(extack, "invalid component size"); 219 + return -EINVAL; 220 + } 221 + *psrc += pos; 222 + *psize -= pos; 223 + 224 + dev_dbg(dev, "Firmware component '%s' found\n", name); 225 + 226 + id = zl3073x_fw_component_id_get(name); 227 + if (id == ZL_FW_COMPONENT_INVALID) { 228 + ZL3073X_FW_ERR_MSG(extack, "unknown component type '%s'", name); 229 + return -EINVAL; 230 + } 231 + 232 + info = &component_info[id]; 233 + size = count * sizeof(u32); /* get size in bytes */ 234 + 235 + /* Check image size validity */ 236 + if (size > component_info[id].max_size) { 237 + ZL3073X_FW_ERR_MSG(extack, 238 + "[%s] component is too big (%u bytes)\n", 239 + info->name, size); 240 + return -EINVAL; 241 + } 242 + 243 + dev_dbg(dev, "Indicated component image size: %u bytes\n", size); 244 + 245 + /* Alloc component */ 246 + comp = zl3073x_fw_component_alloc(size); 247 + if (!comp) { 248 + ZL3073X_FW_ERR_MSG(extack, "failed to alloc memory"); 249 + return -ENOMEM; 250 + } 251 + comp->id = id; 252 + 253 + /* Load component data from firmware source */ 254 + for (dest = comp->data; count; count--, dest++) { 255 + strscpy(buf, *psrc, min(sizeof(buf), *psize)); 256 + rc = sscanf(buf, "%x %n", dest, &pos); 257 + if (!rc) 258 + goto err_data; 259 + 260 + *psrc += pos; 261 + *psize -= pos; 262 + } 263 + 264 + *pcomp = comp; 265 + 266 + return 1; 267 + 268 + err_data: 269 + ZL3073X_FW_ERR_MSG(extack, "[%s] invalid or missing data", info->name); 270 + 271 + zl3073x_fw_component_free(comp); 272 + 273 + return -ENODATA; 274 + } 275 + 276 + /** 277 + * zl3073x_fw_free - Free allocated firmware 278 + * @fw: firmware pointer 279 + * 280 + * The function frees existing firmware allocated by @zl3073x_fw_load. 281 + */ 282 + void zl3073x_fw_free(struct zl3073x_fw *fw) 283 + { 284 + size_t i; 285 + 286 + if (!fw) 287 + return; 288 + 289 + for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++) 290 + zl3073x_fw_component_free(fw->component[i]); 291 + 292 + kfree(fw); 293 + } 294 + 295 + /** 296 + * zl3073x_fw_load - Load all components from source 297 + * @zldev: zl3073x device structure 298 + * @data: source buffer pointer 299 + * @size: size of source buffer 300 + * @extack: netlink extack pointer to report errors 301 + * 302 + * The functions allocate firmware structure and loads all components from 303 + * the given buffer specified by @data and @size. 304 + * 305 + * Return: pointer to firmware on success, error pointer on error 306 + */ 307 + struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data, 308 + size_t size, struct netlink_ext_ack *extack) 309 + { 310 + struct zl3073x_fw_component *comp; 311 + enum zl3073x_fw_component_id id; 312 + struct zl3073x_fw *fw; 313 + ssize_t rc; 314 + 315 + /* Allocate firmware structure */ 316 + fw = kzalloc(sizeof(*fw), GFP_KERNEL); 317 + if (!fw) 318 + return ERR_PTR(-ENOMEM); 319 + 320 + do { 321 + /* Load single component */ 322 + rc = zl3073x_fw_component_load(zldev, &comp, &data, &size, 323 + extack); 324 + if (rc <= 0) 325 + /* Everything was read or error occurred */ 326 + break; 327 + 328 + id = comp->id; 329 + 330 + /* Report error if the given component is present twice 331 + * or more. 332 + */ 333 + if (fw->component[id]) { 334 + ZL3073X_FW_ERR_MSG(extack, 335 + "duplicate component '%s' detected", 336 + component_info[id].name); 337 + zl3073x_fw_component_free(comp); 338 + rc = -EINVAL; 339 + break; 340 + } 341 + 342 + fw->component[id] = comp; 343 + } while (true); 344 + 345 + if (rc) { 346 + /* Free allocated firmware in case of error */ 347 + zl3073x_fw_free(fw); 348 + return ERR_PTR(rc); 349 + } 350 + 351 + return fw; 352 + } 353 + 354 + /** 355 + * zl3073x_flash_bundle_flash - Flash all components 356 + * @zldev: zl3073x device structure 357 + * @components: pointer to components array 358 + * @extack: netlink extack pointer to report errors 359 + * 360 + * Returns 0 in case of success or negative number otherwise. 361 + */ 362 + static int 363 + zl3073x_fw_component_flash(struct zl3073x_dev *zldev, 364 + struct zl3073x_fw_component *comp, 365 + struct netlink_ext_ack *extack) 366 + { 367 + const struct zl3073x_fw_component_info *info; 368 + int rc; 369 + 370 + info = &component_info[comp->id]; 371 + 372 + switch (info->flash_type) { 373 + case ZL3073X_FLASH_TYPE_NONE: 374 + /* Non-flashable component - used for utility */ 375 + return 0; 376 + case ZL3073X_FLASH_TYPE_SECTORS: 377 + rc = zl3073x_flash_sectors(zldev, info->name, info->dest_page, 378 + info->load_addr, comp->data, 379 + comp->size, extack); 380 + break; 381 + case ZL3073X_FLASH_TYPE_PAGE: 382 + rc = zl3073x_flash_page(zldev, info->name, info->dest_page, 383 + info->load_addr, comp->data, comp->size, 384 + extack); 385 + break; 386 + case ZL3073X_FLASH_TYPE_PAGE_AND_COPY: 387 + rc = zl3073x_flash_page(zldev, info->name, info->dest_page, 388 + info->load_addr, comp->data, comp->size, 389 + extack); 390 + if (!rc) 391 + rc = zl3073x_flash_page_copy(zldev, info->name, 392 + info->dest_page, 393 + info->copy_page, extack); 394 + break; 395 + } 396 + if (rc) 397 + ZL3073X_FW_ERR_MSG(extack, "Failed to flash component '%s'", 398 + info->name); 399 + 400 + return rc; 401 + } 402 + 403 + int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw, 404 + struct netlink_ext_ack *extack) 405 + { 406 + int i, rc = 0; 407 + 408 + for (i = 0; i < ZL_FW_NUM_COMPONENTS; i++) { 409 + if (!zlfw->component[i]) 410 + continue; /* Component is not present */ 411 + 412 + rc = zl3073x_fw_component_flash(zldev, zlfw->component[i], 413 + extack); 414 + if (rc) 415 + break; 416 + } 417 + 418 + return rc; 419 + }
+52
drivers/dpll/zl3073x/fw.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + 3 + #ifndef _ZL3073X_FW_H 4 + #define _ZL3073X_FW_H 5 + 6 + /* 7 + * enum zl3073x_fw_component_id - Identifiers for possible flash components 8 + */ 9 + enum zl3073x_fw_component_id { 10 + ZL_FW_COMPONENT_INVALID = -1, 11 + ZL_FW_COMPONENT_UTIL = 0, 12 + ZL_FW_COMPONENT_FW1, 13 + ZL_FW_COMPONENT_FW2, 14 + ZL_FW_COMPONENT_FW3, 15 + ZL_FW_COMPONENT_CFG0, 16 + ZL_FW_COMPONENT_CFG1, 17 + ZL_FW_COMPONENT_CFG2, 18 + ZL_FW_COMPONENT_CFG3, 19 + ZL_FW_COMPONENT_CFG4, 20 + ZL_FW_COMPONENT_CFG5, 21 + ZL_FW_COMPONENT_CFG6, 22 + ZL_FW_NUM_COMPONENTS 23 + }; 24 + 25 + /** 26 + * struct zl3073x_fw_component - Firmware component 27 + * @id: Flash component ID 28 + * @size: Size of the buffer 29 + * @data: Pointer to buffer with component data 30 + */ 31 + struct zl3073x_fw_component { 32 + enum zl3073x_fw_component_id id; 33 + size_t size; 34 + void *data; 35 + }; 36 + 37 + /** 38 + * struct zl3073x_fw - Firmware bundle 39 + * @component: firmware components array 40 + */ 41 + struct zl3073x_fw { 42 + struct zl3073x_fw_component *component[ZL_FW_NUM_COMPONENTS]; 43 + }; 44 + 45 + struct zl3073x_fw *zl3073x_fw_load(struct zl3073x_dev *zldev, const char *data, 46 + size_t size, struct netlink_ext_ack *extack); 47 + void zl3073x_fw_free(struct zl3073x_fw *fw); 48 + 49 + int zl3073x_fw_flash(struct zl3073x_dev *zldev, struct zl3073x_fw *zlfw, 50 + struct netlink_ext_ack *extack); 51 + 52 + #endif /* _ZL3073X_FW_H */
+51
drivers/dpll/zl3073x/regs.h
··· 72 72 #define ZL_REG_FW_VER ZL_REG(0, 0x05, 2) 73 73 #define ZL_REG_CUSTOM_CONFIG_VER ZL_REG(0, 0x07, 4) 74 74 75 + #define ZL_REG_RESET_STATUS ZL_REG(0, 0x18, 1) 76 + #define ZL_REG_RESET_STATUS_RESET BIT(0) 77 + 75 78 /************************* 76 79 * Register Page 2, Status 77 80 *************************/ ··· 262 259 #define ZL_REG_OUTPUT_ESYNC_PERIOD ZL_REG(14, 0x14, 4) 263 260 #define ZL_REG_OUTPUT_ESYNC_WIDTH ZL_REG(14, 0x18, 4) 264 261 #define ZL_REG_OUTPUT_PHASE_COMP ZL_REG(14, 0x20, 4) 262 + 263 + /* 264 + * Register Page 255 - HW registers access 265 + */ 266 + #define ZL_REG_HWREG_OP ZL_REG(0xff, 0x00, 1) 267 + #define ZL_HWREG_OP_WRITE 0x28 268 + #define ZL_HWREG_OP_READ 0x29 269 + #define ZL_HWREG_OP_PENDING BIT(1) 270 + 271 + #define ZL_REG_HWREG_ADDR ZL_REG(0xff, 0x04, 4) 272 + #define ZL_REG_HWREG_WRITE_DATA ZL_REG(0xff, 0x08, 4) 273 + #define ZL_REG_HWREG_READ_DATA ZL_REG(0xff, 0x0c, 4) 274 + 275 + /* 276 + * Registers available in flash mode 277 + */ 278 + #define ZL_REG_FLASH_HASH ZL_REG(0, 0x78, 4) 279 + #define ZL_REG_FLASH_FAMILY ZL_REG(0, 0x7c, 1) 280 + #define ZL_REG_FLASH_RELEASE ZL_REG(0, 0x7d, 1) 281 + 282 + #define ZL_REG_HOST_CONTROL ZL_REG(1, 0x02, 1) 283 + #define ZL_HOST_CONTROL_ENABLE BIT(0) 284 + 285 + #define ZL_REG_IMAGE_START_ADDR ZL_REG(1, 0x04, 4) 286 + #define ZL_REG_IMAGE_SIZE ZL_REG(1, 0x08, 4) 287 + #define ZL_REG_FLASH_INDEX_READ ZL_REG(1, 0x0c, 4) 288 + #define ZL_REG_FLASH_INDEX_WRITE ZL_REG(1, 0x10, 4) 289 + #define ZL_REG_FILL_PATTERN ZL_REG(1, 0x14, 4) 290 + 291 + #define ZL_REG_WRITE_FLASH ZL_REG(1, 0x18, 1) 292 + #define ZL_WRITE_FLASH_OP GENMASK(2, 0) 293 + #define ZL_WRITE_FLASH_OP_DONE 0x0 294 + #define ZL_WRITE_FLASH_OP_SECTORS 0x2 295 + #define ZL_WRITE_FLASH_OP_PAGE 0x3 296 + #define ZL_WRITE_FLASH_OP_COPY_PAGE 0x4 297 + 298 + #define ZL_REG_FLASH_INFO ZL_REG(2, 0x00, 1) 299 + #define ZL_FLASH_INFO_SECTOR_SIZE GENMASK(3, 0) 300 + #define ZL_FLASH_INFO_SECTOR_4K 0 301 + #define ZL_FLASH_INFO_SECTOR_64K 1 302 + 303 + #define ZL_REG_ERROR_COUNT ZL_REG(2, 0x04, 4) 304 + #define ZL_REG_ERROR_CAUSE ZL_REG(2, 0x08, 4) 305 + 306 + #define ZL_REG_OP_STATE ZL_REG(2, 0x14, 1) 307 + #define ZL_OP_STATE_NO_COMMAND 0 308 + #define ZL_OP_STATE_PENDING 1 309 + #define ZL_OP_STATE_DONE 2 265 310 266 311 #endif /* _ZL3073X_REGS_H */