diff --git a/drivers/gpu/nvgpu/common/pmu/pmu.c b/drivers/gpu/nvgpu/common/pmu/pmu.c index 0e87cd5c1..2fd71b6a4 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -42,7 +42,34 @@ void nvgpu_pmu_report_bar0_pri_err_status(struct gk20a *g, u32 bar0_status, "error_type(0x%x)", bar0_status, error_type); } -/* PMU engine reset functions */ +/** + * @brief Enable/Disable PMU hardware + * + * @param pmu [in] The PMU unit struct. This function does + * not perform any validation of this input parameter. + * @param enable [in] boolean parameter to enable/disable. This function does + * not perform any validation of this input parameter. + * + * Assign g = pmu->g. + * This function is used to enable the PMU by doing engine reset, configuring + * PMU Engine clock gating and waiting for IMEM/DMEM memory scrubbing for reset + * request. This function can also be used to disable PMU by keeping the engine + * in reset state. The parameter \a enable will be used to decide the path. + * + If parameter \a enable is true do the following + * + Reset PMU engine by calling \ref gops_pmu.reset_engine + * "g->ops.pmu.reset_engine(g, true)". + * + Call \ref nvgpu_cg_slcg_pmu_load_enable "nvgpu_cg_slcg_pmu_load_enable(g)" + * + Call \ref nvgpu_cg_blcg_pmu_load_enable "nvgpu_cg_blcg_pmu_load_enable(g)" + * + Call \ref nvgpu_falcon_mem_scrub_wait "nvgpu_falcon_mem_scrub_wait(pmu->flcn)". + * if return value is not equal to zero then keep the PMU engine in reset by + * calling \ref gops_pmu.reset_engine "g->ops.pmu.reset_engine(g, false))" + * and return -ETIMEDOUT. + * + If parameter \a enable is false then keep the PMU engine in reset by calling + * \ref gops_pmu.reset_engine "g->ops.pmu.reset_engine(g, false))". + * + *@return 0 in case of success. <0 in case of failure. + *@retval -ETIMEDOUT in case of memory scrub failure. + */ static int pmu_enable_hw(struct nvgpu_pmu *pmu, bool enable) { struct gk20a *g = pmu->g; @@ -85,6 +112,29 @@ void nvgpu_pmu_enable_irq(struct gk20a *g, bool enable) } } +/** + * @brief Enable/Disable PMU + * + * @param pmu [in] The PMU unit struct. This function does + * not perform any validation of this input parameter. + * @param enable [in] boolean parameter to enable/disable. This function does + * not perform any validation of this input parameter. + * + * Assign g = pmu->g. + * This function is used to enable/disable the PMU engine and configuring the + * PMU ECC interrupts. + * + If parameter \a enable is true do the following, in case of failure return error. + * + Call \ref pmu_enable_hw "pmu_enable_hw(pmu, true)". + * + Call \ref nvgpu_falcon_wait_idle "nvgpu_falcon_wait_idle(pmu->flcn)". + * + Call \ref nvgpu_pmu_enable_irq "nvgpu_pmu_enable_irq(g, true)". + * + If parameter \a enable is false do the following, in case of failure return error. + * + Check if PMU engine is in reset by calling \ref gops_pmu.is_engine_in_reset() + * and proceed only if engine not in reset, else return. + * + Call \ref nvgpu_pmu_enable_irq "nvgpu_pmu_enable_irq(g, false)". + * + Call \ref pmu_enable_hw "pmu_enable_hw(pmu, false)". + * + *@return 0 in case of success, < 0 in case of failure. + */ static int pmu_enable(struct nvgpu_pmu *pmu, bool enable) { struct gk20a *g = pmu->g; diff --git a/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h index 0a574cffd..fc2dd30ca 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/gops/pmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2019-2023, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -44,10 +44,17 @@ struct gops_pmu { /** * @brief Initialize PMU unit ECC support. * - * @param g [in] Pointer to GPU driver struct. + * @param g [in] Pointer to GPU driver struct. This function does + * not perform any validation of this input parameter. * * This function allocates memory to track the ecc error counts * for PMU unit. + * + Call \ref nvgpu_ecc_counter_init + * "nvgpu_ecc_counter_init(g, &g->ecc.pmu.stat, pmu_ecc_uncorrected_err_count)" + * and return if failed. + * + Call \ref nvgpu_ecc_counter_init + * "nvgpu_ecc_counter_init(g, &g->ecc.pmu.stat, pmu_ecc_corrected_err_count)" + * and return if failed. * * @return 0 in case of success, < 0 in case of failure. * @retval -ENOMEM if memory allocation for ecc stats fails. @@ -57,53 +64,236 @@ struct gops_pmu { /** * @brief Free PMU unit ECC support. * - * @param g [in] Pointer to GPU driver struct. + * @param g [in] Pointer to GPU driver struct. This function does + * not perform any validation of this input parameter. * * This function deallocates memory allocated for ecc error counts * for PMU unit. + * + Assign *ecc = &g->ecc. + * + Free \a pmu_ecc_corrected_err_count by calling \ref + * nvgpu_kfree(g, ecc->pmu.pmu_ecc_corrected_err_count). + * + Free \a pmu_ecc_uncorrected_err_count by calling \ref + * nvgpu_kfree(g, ecc->pmu.pmu_ecc_uncorrected_err_count); */ void (*ecc_free)(struct gk20a *g); /** * @brief Interrupt handler for PMU interrupts. * - * @param g [in] The GPU driver struct. + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. * - * Steps: - * + Acquire mutex g->pmu->isr_mutex. - * + If PMU interrupts are not enabled release isr_mutex and return. - * + Prepare mask by AND'ing registers pwr_falcon_irqmask_r and - * pwr_falcon_irqdest_r. - * + Read interrupts status register pwr_falcon_irqstat_r. - * + Determine interrupts to be handled by AND'ing value read in - * the previous step with the mask computed earlier. - * + If no interrupts are to be handled release isr_mutex and return. - * + Handle ECC interrupt if it is pending. - * + Clear the pending interrupts to be handled by writing the - * pending interrupt mask to the register pwr_falcon_irqsclr_r. - * + Release mutex g->pmu->isr_mutex. + * This function is responsible for handling all PMU interrupts enabled by + * \ref gpos_pmu.pmu_enable_irq "g->ops.pmu.pmu_enable_irq() + * + Assign *pmu = g->pmu. + * + Acquire mutex \a &g->pmu->isr_mutex by calling \ref nvgpu_mutex_acquire(). + * + Check if \a pmu->isr_enabled is false which implies PMU interrupts are not + * enabled, release \a &g->pmu->isr_mutex by calling + * \ref nvgpu_mutex_release() and return. + * + Prepare mask by AND'ing values obtained by reading registers + * pwr_falcon_irqmask_r() and pwr_falcon_irqdest_r(). + * + Read interrupt status register pwr_falcon_irqstat_r() and assign the + * value to intr. + * + Determine interrupts to be handled by AND'ing intr and mask obtained in + * previous steps and assign the value to intr. + * + If no interrupts are to be handled release \a &g->pmu->isr_mutex by calling + * \ref nvgpu_mutex_release() and return. + * + Handle ECC interrupt by calling \ref gops_pmu.handle_ext_irq + * "g->ops.pmu.handle_ext_irq(g, intr)". Before calling check this + * function pointer is not NULL. + * + Clear the pending interrupts to be handled by writing the value of + * intr to the register pwr_falcon_irqsclr_r(). + * + Release \a &g->pmu->isr_mutex by calling \ref nvgpu_mutex_release(). */ void (*pmu_isr)(struct gk20a *g); /** - * @brief PMU early initialization to allocate memory for PMU unit, - * set PMU Engine h/w properties and set supporting data structs. + * @brief PMU early initialization to allocate memory for PMU unit & set PMU + * Engine h/w properties, data structs, sub-unit's data structs based + * on the detected chip * - * @param g [in] The GPU driver struct. + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. * - * Initializes PMU unit data structs in the GPU driver based on detected - * chip. - * + Allocate memory for #nvgpu_pmu data struct. - * + set PMU Engine h/w properties. - * + set PMU RTOS supporting data structs. - * + set sub-unit's data structs. - * + ops of the PMU unit. - * - * @return 0 in case of success, < 0 in case of failure. - * @retval -ENOMEM if memory allocation fail for any unit. + * This is gops function pointer to \ref nvgpu_pmu_early_init + * "nvgpu_pmu_early_init()" public function. */ int (*pmu_early_init)(struct gk20a *g); + /** + * @brief Enable/Disable PMU ECC interrupts. + * + * @param pmu [in] The PMU unit struct. This function does + * not perform any validation of this input parameter. + * @param enable [in] boolean parameter to enable/disable. This function does + * not perform any validation of this input parameter. + * + * + Disable stall interrupts at the master level by calling + * \ref nvgpu_mc_intr_stall_unit_config + * "nvgpu_mc_intr_stall_unit_config(pmu->g, MC_INTR_UNIT_PMU, MC_INTR_DISABLE)" + * + Disable PMU ECC interrupt by calling \ref nvgpu_falcon_set_irq + * "nvgpu_falcon_set_irq(pmu->flcn, false, 0x0, 0x0)" + * + If enable parameter is set to true then do the following + * + get intr_dest by calling \ref gops_pmu.get_irqdest "gops_pmu.get_irqdest(pmu->g)". + * + Enable stall interrupts at the master level by calling + * \ref nvgpu_mc_intr_stall_unit_config + * "nvgpu_mc_intr_stall_unit_config(pmu->g, MC_INTR_UNIT_PMU, MC_INTR_ENABLE)" + * + Assign intr_mask = pwr_falcon_irqmset_ext_ecc_parity_f(1). + * + Enable PMU ECC interrupt by calling \ref nvgpu_falcon_set_irq + * "nvgpu_falcon_set_irq(pmu->flcn, true, intr_mask, intr_dest)" + */ + void (*pmu_enable_irq)(struct nvgpu_pmu *pmu, bool enable); + + /** + * @brief Provide ECC interrupt destination fields + * + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * + * Provide ECC interrupt destination fields + * + Assign intr_dest to the value obtained by OR'ing + * pwr_falcon_irqdest_host_ext_ecc_parity_f(1) and + * pwr_falcon_irqdest_target_ext_ecc_parity_f(0). + * + Return intr_dest. + */ + u32 (*get_irqdest)(struct gk20a *g); + + /** + * @brief Change the PMU Engine reset state. + * + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * @param do_reset [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * + * PMU Engine reset state change as per input parameter do_reset. + * If do_reset is + * + True - Bring PMU engine out of reset by writing false to + * pwr_falcon_engine_r() register + * + False - Keep PMU falcon/engine in reset by writing true to + * pwr_falcon_engine_r() register + */ + void (*reset_engine)(struct gk20a *g, bool do_reset); + + /** + * @brief Query the PMU Engine reset state. + * + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * + * PMU Engine reset state is read and return as below, + * + True - If PMU engine in reset. + * + False - If PMU engine is out of reset. + * + * @return True if in reset else False. + */ + bool (*is_engine_in_reset)(struct gk20a *g); + + /** + * @brief Setup the normal PMU apertures for standardized access. + * + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * + * Creates a memory aperture that the PMU may use to access memory in + * a specific address-space or mapped into the PMU's virtual-address + * space. The aperture is identified using a unique index that will + * correspond to a single dmaidx in the PMU framebuffer interface. + * + Assign *mm = &g->mm + * + Assign *inst_block = &mm->pmu.inst_block + * + Get ret_mask by calling \ref nvgpu_aperture_mask + * "nvgpu_aperture_mask (g, inst_block, + * pwr_fbif_transcfg_target_noncoherent_sysmem_f(), + * pwr_fbif_transcfg_target_coherent_sysmem_f(), + * pwr_fbif_transcfg_target_local_fb_f()))" + * + Write value (pwr_fbif_transcfg_mem_type_physical_f() | ret_mask) to + * pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_UCODE) register. + * + Write value pwr_fbif_transcfg_mem_type_virtual_f() to register + * pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_VIRT) + * + Write value (pwr_fbif_transcfg_mem_type_physical_f() | ret_mask) to + * pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_VID) register. + * + Write value (pwr_fbif_transcfg_mem_type_physical_f() | + * pwr_fbif_transcfg_target_coherent_sysmem_f()) to + * pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_COH) register. + * + Write value (pwr_fbif_transcfg_mem_type_physical_f() | + * pwr_fbif_transcfg_target_noncoherent_sysmem_f()) to + * pwr_fbif_transcfg_r(GK20A_PMU_DMAIDX_PHYS_SYS_NCOH) register. + */ + void (*setup_apertures)(struct gk20a *g); + + /** + * @brief Handle PMU ECC errors. + * + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * + * This function handles PMU ECC corrected and un-corrected errors. + * + Check and proceed only if pwr_falcon_irqstat_ext_ecc_parity_true_f() bit + * inside parameter \a intr is set to true. + * + Assign \a intr1 to the value obtained by reading interrupt stats register + * pwr_pmu_ecc_intr_status_r(). + * + Check if any corrected and un-corrected ecc errors present in interrupt status + * by AND'ing \a intr1 with (pwr_pmu_ecc_intr_status_corrected_m() | + * pwr_pmu_ecc_intr_status_uncorrected_m()). If no interrupt present return. + * + Assign \a ecc_status to the value obtained by reading register + * pwr_pmu_falcon_ecc_status_r(). + * + Assign \a ecc_addr to the value obtained by reading register + * pwr_pmu_falcon_ecc_address_r(). + * + Assign \a corrected_cnt to the value obtained by reading register + * pwr_pmu_falcon_ecc_corrected_err_count_r. + * + Assign \a uncorrected_cnt to the value obtained by reading register + * pwr_pmu_falcon_ecc_uncorrected_err_count_r. + * + Assign corrected_delta = (corrected_cnt & 0xffffU). + * + Assign uncorrected_delta = (uncorrected_cnt & 0xffffU). + * + Assign \a corrected_overflow to the value obtained by AND'ing ecc_status + * with (U32(0x1U) << 16U) + * + Assign \a uncorrected_overflow to the value obtained by AND'ing ecc_status + * with (U32(0x1U) << 18U) + * + if \a corrected_overflow is not zero OR pwr_pmu_ecc_intr_status_corrected_m + * bit in \a intr1 is enabled then clear the interrupt by writing to zero to + * pwr_pmu_falcon_ecc_corrected_err_count_r() register. + * + if \a uncorrected_overflow is not zero OR pwr_pmu_ecc_intr_status_uncorrected_m + * bit in \a intr1 is enabled then clear the interrupt by writing to zero to + * pwr_pmu_falcon_ecc_uncorrected_err_count_r() register. + * + Write pwr_pmu_falcon_ecc_status_r() register with value + * pwr_pmu_falcon_ecc_status_reset_task_f. + * + If \a corrected_overflow is not zero then update the counters per slice by + * adding pwr_pmu_falcon_ecc_corrected_err_count_total_s value to + * \a corrected_delta and updating it to the new value. + * + If \a uncorrected_overflow is not zero then update the counters per slice + * by adding pwr_pmu_falcon_ecc_uncorrected_err_count_total_s value to + * \a uncorrected_delta and updating it to the new value. + * + Add \a corrected_overflow value to \a + * g->ecc.pmu.pmu_ecc_corrected_err_count[0].counter and updating it to + * the new value. + * + Add \a uncorrected_overflow value to \a + * g->ecc.pmu.pmu_ecc_uncorrected_err_count[0].counter and updating it to + * the new value. + * + Check the corresponding bit in \a ecc_status and if enabled do the + * following + * + bit pwr_pmu_falcon_ecc_status_corrected_err_imem_m() then report + * error by calling \ref nvgpu_report_ecc_err + * "nvgpu_report_ecc_err(g, NVGPU_ERR_MODULE_PMU, 0, + * GPU_PMU_FALCON_IMEM_ECC_CORRECTED, ecc_addr, + * g->ecc.pmu.pmu_ecc_corrected_err_count[0].counter)". + * + bit pwr_pmu_falcon_ecc_status_uncorrected_err_imem_m() then report + * error by calling \ref nvgpu_report_ecc_err "nvgpu_report_ecc_err (g, + * NVGPU_ERR_MODULE_PMU, 0, GPU_PMU_FALCON_IMEM_ECC_UNCORRECTED, ecc_addr, + * g->ecc.pmu.pmu_ecc_uncorrected_err_count[0].counter)" and return -EFAULT. + * + bit pwr_pmu_falcon_ecc_status_corrected_err_dmem_m(), as this is + * not expected and considered as fatal error, release the mutex + * \a &g->pmu->isr_mutex by calling \ref nvgpu_mutex_release() and then + * call BUG(). + * + bit pwr_pmu_falcon_ecc_status_uncorrected_err_dmem_m() the report error + * by calling \ref nvgpu_report_ecc_err "nvgpu_report_ecc_err (g, + * NVGPU_ERR_MODULE_PMU, 0, GPU_PMU_FALCON_DMEM_ECC_UNCORRECTED, ecc_addr, + * g->ecc.pmu.pmu_ecc_uncorrected_err_count[0].counter)" and return -EFAULT. + * + *@retval -EFAULT in case of uncorrected ecc err. + *@return 0 in case of success. + */ + void (*handle_ext_irq)(struct gk20a *g, u32 intr); + #ifdef CONFIG_NVGPU_POWER_PG int (*pmu_restore_golden_img_state)(struct gk20a *g); #endif @@ -155,42 +345,6 @@ struct gops_pmu { */ int (*pmu_reset)(struct gk20a *g); - /** - * @brief Change the PMU Engine reset state. - * - * @param g [in] The GPU driver struct. - * - * PMU Engine reset state change as per input parameter. - * + True - Bring PMU engine out of reset. - * + False - Keep PMU falcon/engine in reset. - */ - void (*reset_engine)(struct gk20a *g, bool do_reset); - - /** - * @brief Query the PMU Engine reset state. - * - * @param g [in] The GPU driver struct. - * - * PMU Engine reset state is read and return as below, - * + True - If PMU engine in reset. - * + False - If PMU engine is out of reset. - * - * @return True if in reset else False. - */ - bool (*is_engine_in_reset)(struct gk20a *g); - - /** - * @brief Setup the normal PMU apertures for standardized access. - * - * @param g [in] The GPU driver struct. - * - * Creates a memory aperture that the PMU may use to access memory in - * a specific address-space or mapped into the PMU's virtual-address - * space. The aperture is identified using a unique index that will - * correspond to a single dmaidx in the PMU framebuffer interface. - */ - void (*setup_apertures)(struct gk20a *g); - /** * @brief Clears the PMU BAR0 error status. * @@ -314,11 +468,7 @@ struct gops_pmu { bool (*validate_mem_integrity)(struct gk20a *g); /** @cond DOXYGEN_SHOULD_SKIP_THIS */ - void (*handle_ext_irq)(struct gk20a *g, u32 intr); void (*handle_swgen1_irq)(struct gk20a *g, u32 intr); - - void (*pmu_enable_irq)(struct nvgpu_pmu *pmu, bool enable); - u32 (*get_irqdest)(struct gk20a *g); u32 (*get_irqmask)(struct gk20a *g); #ifdef CONFIG_NVGPU_LS_PMU diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmu.h index 44a84dc36..4a72788f6 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-2023, NVIDIA CORPORATION. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -459,12 +459,20 @@ s32 nvgpu_pmu_next_core_rtos_args_allocate(struct gk20a *g, /** * @brief Report PMU BAR0 error to 3LSS. * - * @param g [in] The GPU driver struct. - * @param bar0_status [in] bar0 error status value. - * @param err_type [in] Error type. - * - * This function reports PMU BAR0 error to 3LSS. + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * @param bar0_status [in] bar0 error status value. This function does + * not perform any validation of this input parameter. + * @param err_type [in] Error type. This function does + * not perform any validation of this input parameter. * + * This function reports PMU BAR0 error to 3LSS by calling + * \ref nvgpu_report_pmu_err() with following parameters + * + g: The GPU driver struct + * + hw_unit: \ref #NVGPU_ERR_MODULE_PMU + * + err_id: \ref #GPU_PMU_BAR0_ERROR_TIMEOUT + * + sub_err_type: err_type + * + status: bar0_status */ void nvgpu_pmu_report_bar0_pri_err_status(struct gk20a *g, u32 bar0_status, u32 error_type); @@ -472,27 +480,36 @@ void nvgpu_pmu_report_bar0_pri_err_status(struct gk20a *g, u32 bar0_status, /** * @brief Enable/Disable PMU ECC interrupt. * - * @param g [in] The GPU driver struct. - * @param enable [in] boolean parameter to enable/disable. + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. + * @param enable [in] boolean parameter to enable/disable. This function does + * not perform any validation of this input parameter. * - * Enable/Disable PMU ECC interrupt. - * + Check that g->pmu and g->ops.pmu.pmu_enable_irq are not null. - * + Acquire the mutex g->pmu->isr_mutex. - * + Disable the PMU interrupts at MC and PMU level. - * + If enabling, enable ECC interrupt in PMU interrupt configuration - * registers and enable PMU interrupts at MC level. - * + Release the mutex g->pmu->isr_mutex. + * + Check that \ref gk20a.pmu "g->pmu" and \a g->ops.pmu.pmu_enable_irq are + * not null. + * + Acquire the mutex \a &g->pmu->isr_mutex by calling + * \ref nvgpu_mutex_acquire(). + * + Disable and Enable the PMU interrupts at MC and PMU level by calling + * \ref gops_pmu.pmu_enable_irq "gops_pmu.pmu_enable_irq(g->pmu, enable)" + * + Assign g->pmu->isr_enabled = enable. + * + Release the mutex \a &g->pmu->isr_mutex by calling + * \ref nvgpu_mutex_release(). */ void nvgpu_pmu_enable_irq(struct gk20a *g, bool enable); /** * @brief Reset the PMU Engine. * - * @param g [in] The GPU driver struct. + * @param g [in] The GPU driver struct. This function does + * not perform any validation of this input parameter. * * Does the PMU Engine reset to bring into good known state. The reset sequence * also configures PMU Engine clock gating & interrupts if interrupt support is * enabled. + * + Assign pmu = g->pmu. + * + Call \ref pmu_enable "pmu_enable(pmu, false)" to keep PMU engine in reset. + * + Call \ref pmu_enable "pmu_enable(pmu, true)" to reset PMU engine and + * configure PMU Engine clock gating & interrupts. * * @return 0 in case of success, < 0 in case of failure. * @retval -ETIMEDOUT if PMU engine reset times out. @@ -505,25 +522,43 @@ int nvgpu_pmu_reset(struct gk20a *g); * data structs & ops of the PMU unit by populating data based on the * detected chip, * - * @param g [in] The GPU driver struct. + * @param g [in] The GPU driver struct. This function does not + * perform any validation of this parameter. * - * Initializes PMU unit data struct in the GPU driver based on detected chip. - * Allocate memory for #nvgpu_pmu data struct & set PMU Engine h/w properties, - * PMU RTOS supporting data structs & ops of the PMU unit by populating data - * based on the detected chip. Allocates memory for ECC counters for PMU - * unit. Initializes the isr_mutex. + * + Allocate memory for pmu unit software state pmu(\ref nvgpu_pmu) by calling + * \ref nvgpu_kzalloc(g, sizeof(struct nvgpu_pmu)). Skip allocation for + * unrailgate sequence. Return -ENOMEM if allocation fails. + * + Assign \ref gk20a.pmu "g->pmu" = pmu. + * + Assign pmu->g = g. + * + Assign Engine software state pmu->flcn = g->pmu_flcn. + * + Allocates memory for ECC counters to track ecc error counts for PMU unit by + * calling \ref gops_pmu.ecc_init "g->ops.pmu.ecc_init(g)" function. If memory + * allocation fails then free pmu unit software state(\ref gk20a.pmu "g->pmu") + * by calling \ref nvgpu_kfree(g, pmu) and return. \ref gops_pmu.ecc_init + * "g->ops.pmu.ecc_init(g)" function should be called only if the following is + * true + * + \ref gops_pmu.ecc_init "g->ops.pmu.ecc_init" function pointer is not NULL + * + ECC intialization not completed which can be checked by reading + * initialized parameter(\a g->ecc.initialized) in \ref #nvgpu_ecc. + * + Initialize \a pmu->isr_mutex by calling \ref #nvgpu_mutex_init + * "nvgpu_mutex_init(&pmu->isr_mutex)". * * @return 0 in case of success, < 0 in case of failure. - * @retval -ENOMEM if memory allocation for struct #nvgpu_pmu fails. + * @retval -ENOMEM if memory allocation fails. */ int nvgpu_pmu_early_init(struct gk20a *g); /** * @brief PMU remove to free space allocted for PMU unit * - * @param g [in] The GPU - * @param nvgpu_pmu [in] The PMU unit. + * @param g [in] The GPU driver struct. This function does not + * perform any validation of this parameter. + * @param nvgpu_pmu [in] The PMU unit. This function does not + * perform any validation of this parameter. * + * + Destroy mutex \a &pmu->isr_mutex by calling \ref #nvgpu_mutex_destroy(). + * + Free pmu unit software state(\ref gk20a.pmu "g->pmu") by calling + * \ref nvgpu_kfree(g, pmu). */ void nvgpu_pmu_remove_support(struct gk20a *g, struct nvgpu_pmu *pmu);