// SPDX-License-Identifier: GPL-2.0+ /* * Texas Instruments' BIST (Built-In Self-Test) driver * * Copyright (C) 2025 Texas Instruments Incorporated - https://www.ti.com/ * Neha Malcom Francis * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "k3_bist_static_data.h" /* PBIST Timeout Value */ #define PBIST_MAX_TIMEOUT_VALUE 100000000 /** * struct k3_bist_privdata - K3 BIST structure * @dev: device pointer * @pbist_base: base of register set for PBIST * @instance: PBIST instance number * @intr_num: corresponding interrupt ID of the PBIST instance * @lbist_ctrl_mmr: base of CTRL MMR register set for LBIST */ struct k3_bist_privdata { struct udevice *dev; void *pbist_base; u32 instance; u32 intr_num; void *lbist_ctrl_mmr; struct pbist_inst_info *pbist_info; struct lbist_inst_info *lbist_info; }; static struct k3_bist_privdata *k3_bist_priv; /** * check_post_pbist_result() - Check POST results * * Function to check whether HW Power-On Self Test, i.e. POST has run * successfully on the MCU domain. * * Return: 0 if all went fine, else corresponding error. */ static int check_post_pbist_result(void) { bool is_done, timed_out; u32 mask; u32 post_reg_val, shift; /* Read HW POST status register */ post_reg_val = readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT); /* Check if HW POST PBIST was performed */ shift = WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT_POST_MCU_PBIST_DONE_SHIFT; is_done = (((post_reg_val >> shift) & 0x1u) == 0x1u) ? (bool)true : (bool)false; if (!is_done) { /* HW POST: PBIST not completed, check if it timed out */ shift = WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT_POST_MCU_PBIST_TIMEOUT_SHIFT; timed_out = (((post_reg_val >> shift) & 0x1u) == 0x1u) ? (bool)true : (bool)false; if (!timed_out) { printf("%s: PBIST was not performed at all on this device for this core\n", __func__); return -EINVAL; } printf("%s: PBIST was attempted but timed out for this section\n", __func__); return -ETIMEDOUT; } else { /* HW POST: PBIST was completed on this device, check the result */ mask = WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT_POST_MCU_PBIST_FAIL_MASK; if ((post_reg_val & mask) != 0) { printf("%s: PBIST was completed, but the test failed\n", __func__); return -EINVAL; } debug("%s: HW POST PBIST completed, test passed\n", __func__); } return 0; } /** * check_post_lbist_result() - Check POST results * * Function to check whether HW Power-On Self Test, i.e. POST has run * successfully on the MCU domain. * * Return: 0 if all went fine, else corresponding error. */ static int check_post_lbist_result(void) { bool is_done, timed_out; u32 post_reg_val, shift; u32 calculated_misr, expected_misr; /* Read HW POST status register */ post_reg_val = readl(WKUP_CTRL_MMR0_BASE + WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT); /* Check if HW POST LBIST was performed */ shift = WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT_POST_MCU_LBIST_DONE_SHIFT; is_done = (((post_reg_val >> shift) & 0x1u) == 0x1u) ? (bool)true : (bool)false; if (!is_done) { /* HW POST: PBIST not completed, check if it timed out */ shift = WKUP_CTRL_MMR_CFG0_WKUP_POST_STAT_POST_MCU_LBIST_TIMEOUT_SHIFT; timed_out = (((post_reg_val >> shift) & 0x1u) == 0x1u) ? (bool)true : (bool)false; if (!timed_out) { printf("%s: PBIST was not performed at all on this device for this core\n", __func__); return -EINVAL; } printf("%s: PBIST was attempted but timed out for this section\n", __func__); return -ETIMEDOUT; } else { /* Get the output MISR and the expected MISR which 0 for MCU domain */ lbist_get_misr((void *)MCU_LBIST_BASE, &calculated_misr); expected_misr = readl(MCU_CTRL_MMR0_CFG0_BASE + MCU_CTRL_MMR_CFG0_MCU_LBIST_SIG); if (calculated_misr != expected_misr) { /* HW POST: LBIST was completed, but the test failed for this core */ printf("%s: calculated MISR != expected MISR\n", __func__); debug("%s: calculated MISR = %x\n", __func__, calculated_misr); debug("%s: expected MISR = %x\n", __func__, expected_misr); return -EINVAL; } debug("%s: HW POST LBIST completed, test passed\n", __func__); } return 0; } /** * pbist_self_test() - Run PBIST_TEST on specified cores * @config: pbist_config structure for PBIST test * * Function to run PBIST_TEST * * Return: 0 if all went fine, else corresponding error. */ static int pbist_self_test(struct pbist_config *config) { void *base = k3_bist_priv->pbist_base; /* Turns on PBIST clock in PBIST ACTivate register */ writel(PBIST_PACT_PACT_MASK, base + PBIST_PACT); /* Set Margin mode register for Test mode */ writel(PBIST_TEST_MODE, base + PBIST_MARGIN_MODE); /* Zero out Loop counter 0 */ writel(0x0, base + PBIST_L0); /* Set algorithm bitmap */ writel(config->algorithms_bit_map, base + PBIST_ALGO); /* Set Memory group bitmap */ writel(config->memory_groups_bit_map, base + PBIST_RINFO); /* Zero out override register */ writel(config->override, base + PBIST_OVER); /* Set Scramble value - 64 bit*/ writel(config->scramble_value_lo, base + PBIST_SCR_LO); writel(config->scramble_value_hi, base + PBIST_SCR_HI); /* Set DLR register for ROM based testing and Config Access */ writel(PBIST_DLR_DLR0_ROM_MASK | PBIST_DLR_DLR0_CAM_MASK, base + PBIST_DLR); /* Allow time for completion of test*/ udelay(1000); if (readl(base + PBIST_FSRF)) { printf("%s: test failed\n", __func__); return -EINVAL; } return 0; } /** * pbist_neg_self_test() - Run PBIST_negTEST on specified cores * @config: pbist_config_neg structure for PBIST negative test * * Function to run PBIST failure insertion test * * Return: 0 if all went fine, else corresponding error. */ static int pbist_neg_self_test(struct pbist_config_neg *config) { void *base = k3_bist_priv->pbist_base; /* Turns on PBIST clock in PBIST ACTivate register */ writel(PBIST_PACT_PACT_MASK, base + PBIST_PACT); /* Set Margin mode register for Test mode */ writel(PBIST_FAILURE_INSERTION_TEST_MODE, base + PBIST_MARGIN_MODE); /* Zero out Loop counter 0 */ writel(0x0, base + PBIST_L0); /* Set DLR register */ writel(0x10, base + PBIST_DLR); /* Set Registers*/ writel(0x00000001, base + PBIST_RF0L); writel(0x00003123, base + PBIST_RF0U); writel(0x0513FC02, base + PBIST_RF1L); writel(0x00000002, base + PBIST_RF1U); writel(0x00000003, base + PBIST_RF2L); writel(0x00000000, base + PBIST_RF2U); writel(0x00000004, base + PBIST_RF3L); writel(0x00000028, base + PBIST_RF3U); writel(0x64000044, base + PBIST_RF4L); writel(0x00000000, base + PBIST_RF4U); writel(0x0006A006, base + PBIST_RF5L); writel(0x00000000, base + PBIST_RF5U); writel(0x00000007, base + PBIST_RF6L); writel(0x0000A0A0, base + PBIST_RF6U); writel(0x00000008, base + PBIST_RF7L); writel(0x00000064, base + PBIST_RF7U); writel(0x00000009, base + PBIST_RF8L); writel(0x0000A5A5, base + PBIST_RF8U); writel(0x0000000A, base + PBIST_RF9L); writel(0x00000079, base + PBIST_RF9U); writel(0x00000000, base + PBIST_RF10L); writel(0x00000001, base + PBIST_RF10U); writel(0xAAAAAAAA, base + PBIST_D); writel(0xAAAAAAAA, base + PBIST_E); writel(config->CA2, base + PBIST_CA2); writel(config->CL0, base + PBIST_CL0); writel(config->CA3, base + PBIST_CA3); writel(config->I0, base + PBIST_I0); writel(config->CL1, base + PBIST_CL1); writel(config->I3, base + PBIST_I3); writel(config->I2, base + PBIST_I2); writel(config->CL2, base + PBIST_CL2); writel(config->CA1, base + PBIST_CA1); writel(config->CA0, base + PBIST_CA0); writel(config->CL3, base + PBIST_CL3); writel(config->I1, base + PBIST_I1); writel(config->RAMT, base + PBIST_RAMT); writel(config->CSR, base + PBIST_CSR); writel(config->CMS, base + PBIST_CMS); writel(0x00000009, base + PBIST_STR); /* Start PBIST */ writel(0x00000001, base + PBIST_STR); /* Allow time for completion of test*/ udelay(1000); if (readl(base + PBIST_FSRF) == 0) { printf("%s: test failed\n", __func__); return -EINVAL; } return 0; } /** * pbist_rom_self_test() - Run PBIST_ROM_TEST on specified cores * @config: pbist_config_rom structure for PBIST negative test * * Function to run PBIST test of ROM * * Return: 0 if all went fine, else corresponding error. */ static int pbist_rom_self_test(struct pbist_config_rom *config) { void *base = k3_bist_priv->pbist_base; /* Turns on PBIST clock in PBIST ACTivate register */ writel(0x1, base + PBIST_PACT); /* Set Margin mode register for Test mode */ writel(0xf, base + PBIST_MARGIN_MODE); /* Zero out Loop counter 0 */ writel(0x0, base + PBIST_L0); /* Set DLR register */ writel(0x310, base + PBIST_DLR); /* Set Registers*/ writel(0x00000001, base + PBIST_RF0L); writel(0x00003123, base + PBIST_RF0U); writel(0x7A400183, base + PBIST_RF1L); writel(0x00000060, base + PBIST_RF1U); writel(0x00000184, base + PBIST_RF2L); writel(0x00000000, base + PBIST_RF2U); writel(0x7B600181, base + PBIST_RF3L); writel(0x00000061, base + PBIST_RF3U); writel(0x00000000, base + PBIST_RF4L); writel(0x00000000, base + PBIST_RF4U); writel(config->D, base + PBIST_D); writel(config->E, base + PBIST_E); writel(config->CA2, base + PBIST_CA2); writel(config->CL0, base + PBIST_CL0); writel(config->CA3, base + PBIST_CA3); writel(config->I0, base + PBIST_I0); writel(config->CL1, base + PBIST_CL1); writel(config->I3, base + PBIST_I3); writel(config->I2, base + PBIST_I2); writel(config->CL2, base + PBIST_CL2); writel(config->CA1, base + PBIST_CA1); writel(config->CA0, base + PBIST_CA0); writel(config->CL3, base + PBIST_CL3); writel(config->I1, base + PBIST_I1); writel(config->RAMT, base + PBIST_RAMT); writel(config->CSR, base + PBIST_CSR); writel(config->CMS, base + PBIST_CMS); writel(0x00000009, base + PBIST_STR); /* Start PBIST */ writel(0x00000001, base + PBIST_STR); /* Allow time for completion of test*/ udelay(1000); if (readl(base + PBIST_FSRF)) { printf("%s: test failed\n", __func__); return -EINVAL; } return 0; } /** * lbist_program_config() - Program LBIST config * @config: lbist_config structure for LBIST test */ static void lbist_program_config(struct lbist_config *config) { void *base = k3_bist_priv->lbist_ctrl_mmr; lbist_set_clock_delay(base, config->dc_def); lbist_set_divide_ratio(base, config->divide_ratio); lbist_clear_load_div(base); lbist_set_load_div(base); lbist_set_num_stuck_at_patterns(base, config->static_pc_def); lbist_set_num_set_patterns(base, config->set_pc_def); lbist_set_num_reset_patterns(base, config->reset_pc_def); lbist_set_num_chain_test_patterns(base, config->scan_pc_def); lbist_set_seed(base, config->prpg_def_l, config->prpg_def_u); } /** * lbist_enable_isolation() - LBIST Enable Isolation * @config: lbist_config structure for LBIST test */ void lbist_enable_isolation(void) { void *base = k3_bist_priv->lbist_ctrl_mmr; u32 reg_val; reg_val = readl(base + LBIST_SPARE0); writel(reg_val | (LBIST_SPARE0_LBIST_SELFTEST_EN_MASK), base + LBIST_SPARE0); } /** * lbist_disable_isolation() - LBIST Disable Isolation * @config: lbist_config structure for LBIST test */ void lbist_disable_isolation(void) { void *base = k3_bist_priv->lbist_ctrl_mmr; u32 reg_val; reg_val = readl(base + LBIST_SPARE0); writel(reg_val & (~(LBIST_SPARE0_LBIST_SELFTEST_EN_MASK)), base + LBIST_SPARE0); } /** * lbist_enable_run_bist_mode() - LBIST Enable run BIST mode * @config: lbist_config structure for LBIST test */ static void lbist_enable_run_bist_mode(struct lbist_config *config) { void *base = k3_bist_priv->lbist_ctrl_mmr; u32 reg_val; reg_val = readl(base + LBIST_CTRL); writel(reg_val | (LBIST_CTRL_RUNBIST_MODE_MAX << LBIST_CTRL_RUNBIST_MODE_SHIFT), base + LBIST_CTRL); } /** * lbist_start() - Start LBIST test * @config: lbist_config structure for LBIST test */ static void lbist_start(struct lbist_config *config) { struct udevice *dev = k3_bist_priv->dev; void *base = k3_bist_priv->lbist_ctrl_mmr; u32 reg_val; u32 timeout_count = 0; reg_val = readl(base + LBIST_CTRL); writel(reg_val | (LBIST_CTRL_BIST_RESET_MAX << LBIST_CTRL_BIST_RESET_SHIFT), base + LBIST_CTRL); reg_val = readl(base + LBIST_CTRL); writel(reg_val | (LBIST_CTRL_BIST_RUN_MAX << LBIST_CTRL_BIST_RUN_SHIFT), base + LBIST_CTRL); reg_val = readl(base + LBIST_STAT); if ((reg_val & LBIST_STAT_BIST_RUNNING_MASK) != 0) debug("%s(dev=%p): LBIST is running\n", __func__, dev); while (((!(readl(base + LBIST_STAT) & LBIST_STAT_BIST_DONE_MASK))) && (timeout_count++ < PBIST_MAX_TIMEOUT_VALUE)) { } if (!(readl(base + LBIST_STAT) & LBIST_STAT_BIST_DONE_MASK)) printf("%s(dev=%p): test failed\n", __func__, dev); } /** * lbist_check_result() - Check LBIST test result * @config: lbist_config structure for LBIST test * * Return: 0 if all went fine, else corresponding error. */ static int lbist_check_result(struct lbist_config *config) { void *base = k3_bist_priv->lbist_ctrl_mmr; struct lbist_inst_info *info = k3_bist_priv->lbist_info; u32 calculated_misr; u32 expected_misr; lbist_get_misr(base, &calculated_misr); expected_misr = info->expected_misr; lbist_clear_run_bist_mode(base); lbist_stop(base); lbist_reset(base); if (calculated_misr != expected_misr) { printf("calculated_misr != expected_misr\n %x %x\n", calculated_misr, expected_misr); return -EINVAL; } return 0; } static int k3_run_lbist(void) { /* Check whether HW POST successfully completely LBIST on the MCU domain */ struct lbist_inst_info *info_lbist = k3_bist_priv->lbist_info; lbist_program_config(&info_lbist->lbist_conf); lbist_enable_isolation(); lbist_reset(&info_lbist->lbist_conf); lbist_enable_run_bist_mode(&info_lbist->lbist_conf); lbist_start(&info_lbist->lbist_conf); if (lbist_check_result(&info_lbist->lbist_conf)) { printf("%s: test failed\n", __func__); return -EINVAL; } return 0; } static int k3_run_lbist_post(void) { if (check_post_lbist_result()) { printf("HW POST LBIST failed to run successfully\n"); return -EINVAL; } return 0; } static int k3_run_pbist_post(void) { /* Check whether HW POST successfully completely PBIST on the MCU domain */ if (check_post_pbist_result()) { printf("HW POST failed to run successfully\n"); return -EINVAL; } return 0; } static int k3_run_pbist(void) { /* Run PBIST test */ struct pbist_inst_info *info = k3_bist_priv->pbist_info; int num_runs = info->num_pbist_runs; for (int j = 0; j < num_runs; j++) { if (pbist_self_test(&info->pbist_config_run[j])) { printf("failed to run PBIST test\n"); return -EINVAL; } } return 0; } static int k3_run_pbist_neg(void) { /* Run PBIST failure insertion test */ struct pbist_inst_info *info = k3_bist_priv->pbist_info; if (pbist_neg_self_test(&info->pbist_neg_config_run)) { printf("failed to run PBIST negative test\n"); return -EINVAL; } return 0; } static int k3_run_pbist_rom(void) { /* Run PBIST test on ROM */ struct pbist_inst_info *info = k3_bist_priv->pbist_info; int num_runs = info->num_pbist_rom_test_runs; for (int j = 0; j < num_runs; j++) { if (pbist_rom_self_test(&info->pbist_rom_test_config_run[j])) { printf("failed to run ROM PBIST test\n"); return -EINVAL; } } return 0; } int prepare_pbist(struct ti_sci_handle *handle) { struct ti_sci_proc_ops *proc_ops = &handle->ops.proc_ops; struct ti_sci_dev_ops *dev_ops = &handle->ops.dev_ops; struct pbist_inst_info *info_pbist = k3_bist_priv->pbist_info; struct core_under_test *cut = info_pbist->cut; if (proc_ops->proc_request(handle, cut[0].proc_id)) { printf("%s: requesting primary core failed\n", __func__); return -EINVAL; } if (proc_ops->proc_request(handle, cut[1].proc_id)) { printf("%s: requesting secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut[0].dev_id, 0x1)) { printf("%s: local reset primary core failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut[1].dev_id, 0x1)) { printf("%s: local reset secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->get_device(handle, cut[0].dev_id)) { printf("%s: power on primary core failed\n", __func__); return -EINVAL; } if (dev_ops->get_device(handle, cut[1].dev_id)) { printf("%s: power on secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->get_device(handle, info_pbist->dev_id)) { printf("%s: power on PBIST failed\n", __func__); return -EINVAL; } return 0; } int deprepare_pbist(struct ti_sci_handle *handle) { struct ti_sci_proc_ops *proc_ops = &handle->ops.proc_ops; struct ti_sci_dev_ops *dev_ops = &handle->ops.dev_ops; struct pbist_inst_info *info_pbist = k3_bist_priv->pbist_info; struct core_under_test *cut = info_pbist->cut; if (dev_ops->put_device(handle, info_pbist->dev_id)) { printf("%s: power off PBIST failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut[1].dev_id)) { printf("%s: power off secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut[0].dev_id)) { printf("%s: power off primary core failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut[0].dev_id, 0)) { printf("%s: putting primary core out of local reset failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut[1].dev_id, 0)) { printf("%s: putting secondary core out of local reset failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut[0].dev_id)) { printf("%s: power off primary core failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut[1].dev_id)) { printf("%s: power off secondary core failed\n", __func__); return -EINVAL; } if (proc_ops->proc_release(handle, cut[0].proc_id)) { printf("%s: release primary core failed\n", __func__); return -EINVAL; } if (proc_ops->proc_release(handle, cut[1].proc_id)) { printf("%s: release secondary core failed\n", __func__); return -EINVAL; } return 0; } int prepare_lbist(struct ti_sci_handle *handle) { struct ti_sci_proc_ops *proc_ops = &handle->ops.proc_ops; struct ti_sci_dev_ops *dev_ops = &handle->ops.dev_ops; struct lbist_inst_info *info_lbist = k3_bist_priv->lbist_info; struct core_under_test *cut = &info_lbist->cut; if (proc_ops->proc_request(handle, cut->proc_id)) { printf("%s: requesting primary core failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut->dev_id, 0x3)) { printf("%s: module and local reset primary core failed\n", __func__); return -EINVAL; } if (dev_ops->idle_device(handle, cut->dev_id)) { printf("%s: putting primary core into retention failed\n", __func__); return -EINVAL; } return 0; } int deprepare_lbist(struct ti_sci_handle *handle) { struct ti_sci_proc_ops *proc_ops = &handle->ops.proc_ops; struct ti_sci_dev_ops *dev_ops = &handle->ops.dev_ops; struct lbist_inst_info *info_lbist = k3_bist_priv->lbist_info; struct core_under_test *cut = &info_lbist->cut; if (dev_ops->put_device(handle, 0)) { printf("%s: power off secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut->dev_id)) { printf("%s: power off primary core failed\n", __func__); return -EINVAL; } lbist_disable_isolation(); if (dev_ops->idle_device(handle, cut->dev_id)) { printf("%s: retention primary core failed\n", __func__); return -EINVAL; } if (dev_ops->idle_device(handle, 0)) { printf("%s: retention secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, 0)) { printf("%s: power off secondary core failed\n", __func__); return -EINVAL; } if (dev_ops->put_device(handle, cut->dev_id)) { printf("%s: power off primary core failed\n", __func__); return -EINVAL; } if (dev_ops->set_device_resets(handle, cut->dev_id, 0)) { printf("%s: putting primary core out of local reset failed\n", __func__); return -EINVAL; } if (proc_ops->proc_release(handle, cut->proc_id)) { printf("%s: release primary core failed\n", __func__); return -EINVAL; } return 0; } /** * k3_bist_probe() - Basic probe * @dev: corresponding BIST device * * Parses BIST info from device tree, and configures the module accordingly. * Return: 0 if all goes good, else appropriate error message. */ static int k3_bist_probe(struct udevice *dev) { int ret = 0; struct k3_bist_privdata *priv = dev_get_priv(dev); struct pbist_inst_info *info; struct lbist_inst_info *info_lbist; void *reg; debug("%s(dev=%p)\n", __func__, dev); priv = dev_get_priv(dev); priv->dev = dev; k3_bist_priv = priv; reg = dev_read_addr_name_ptr(dev, "cfg"); if (!reg) { dev_err(dev, "No reg property for BIST\n"); return -EINVAL; } priv->pbist_base = reg; reg = dev_read_addr_name_ptr(dev, "ctrl_mmr"); if (!reg) { dev_err(dev, "No reg property for CTRL MMR\n"); return -EINVAL; } priv->lbist_ctrl_mmr = reg; ret = dev_read_u32(dev, "ti,sci-dev-id", &priv->instance); if (!priv->instance) return -ENODEV; switch (priv->instance) { case PBIST14_DEV_ID: priv->pbist_info = &pbist14_inst_info; priv->lbist_info = &lbist_inst_info_main_r5f2_x; info = priv->pbist_info; info_lbist = priv->lbist_info; priv->intr_num = info->intr_num; break; default: dev_err(dev, "%s: PBIST instance %d not supported\n", __func__, priv->instance); return -ENODEV; }; return 0; } static const struct bist_ops k3_bist_ops = { .run_lbist = k3_run_lbist, .run_lbist_post = k3_run_lbist_post, .run_pbist = k3_run_pbist, .run_pbist_post = k3_run_pbist_post, .run_pbist_neg = k3_run_pbist_neg, .run_pbist_rom = k3_run_pbist_rom, }; static const struct udevice_id k3_bist_ids[] = { { .compatible = "ti,j784s4-bist" }, {} }; U_BOOT_DRIVER(k3_bist) = { .name = "k3_bist", .of_match = k3_bist_ids, .id = UCLASS_MISC, .ops = &k3_bist_ops, .probe = k3_bist_probe, .priv_auto = sizeof(struct k3_bist_privdata), };