Files
linux-nv-oot/drivers/platform/tegra/mce/mce.c
Jon Hunter 876a3cd09d platform: tegra: mce: Combine drivers
The Tegra MCE driver is currently built as two kernel modules which are
tegra-mce.ko and tegra23x-mce.ko. The tegra-mce.ko module simply exports
functions that other drivers can use and the tegra23x-mce.ko modules is
dependent upon this. Instead of building these as two separate kernel
modules we should build as one. Even in the future, if support for other
SoCs is added we can still have a single driver that supports all SoCs.

Rename the file tegra-mce.c to mce.c and update the Makefile so that the
single kernel module produced is called tegra-mce.ko.

Bug 4078818

Change-Id: I5cd7d09f9defb77de4109a89adf1c1384f6b076c
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2890818
Reviewed-by: Laxman Dewangan <ldewangan@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2023-04-21 11:29:39 -07:00

462 lines
10 KiB
C

// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#include <linux/debugfs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform/tegra/tegra-mce.h>
#include <asm/smp_plat.h>
static struct tegra_mce_ops *mce_ops;
void tegra_mce_set_ops(struct tegra_mce_ops *tegra_mce_plat_ops)
{
mce_ops = tegra_mce_plat_ops;
}
EXPORT_SYMBOL_GPL(tegra_mce_set_ops);
/**
* Specify power state and wake time for entering upon STANDBYWFI
*
* @state: requested core power state
* @wake_time: wake time in TSC ticks
*
* Returns 0 if success.
*/
int tegra_mce_enter_cstate(u32 state, u32 wake_time)
{
if (mce_ops && mce_ops->enter_cstate)
return mce_ops->enter_cstate(state, wake_time);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_enter_cstate);
/**
* Specify deepest cluster/ccplex/system states allowed.
*
* @cluster: deepest cluster-wide state
* @ccplex: deepest ccplex-wide state
* @system: deepest system-wide state
* @force: forced system state
* @wake_mask: wake mask to be updated
* @valid: is wake_mask applicable?
*
* Returns 0 if success.
*/
int tegra_mce_update_cstate_info(u32 cluster, u32 ccplex, u32 system,
u8 force, u32 wake_mask, bool valid)
{
if (mce_ops && mce_ops->update_cstate_info)
return mce_ops->update_cstate_info(cluster, ccplex, system,
force, wake_mask, valid);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_update_cstate_info);
/**
* Update threshold for one specific c-state crossover
*
* @type: type of state crossover.
* @time: idle time threshold.
*
* Returns 0 if success.
*/
int tegra_mce_update_crossover_time(u32 type, u32 time)
{
if (mce_ops && mce_ops->update_crossover_time)
return mce_ops->update_crossover_time(type, time);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_update_crossover_time);
/**
* Query the runtime stats of a specific cstate
*
* @state: c-state of the stats.
* @stats: output integer to hold the stats.
*
* Returns 0 if success.
*/
int tegra_mce_read_cstate_stats(u32 state, u64 *stats)
{
if (mce_ops && mce_ops->read_cstate_stats)
return mce_ops->read_cstate_stats(state, stats);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_cstate_stats);
/**
* Overwrite the runtime stats of a specific c-state
*
* @state: c-state of the stats.
* @stats: integer represents the new stats.
*
* Returns 0 if success.
*/
int tegra_mce_write_cstate_stats(u32 state, u32 stats)
{
if (mce_ops && mce_ops->write_cstate_stats)
return mce_ops->write_cstate_stats(state, stats);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_cstate_stats);
/**
* Query MCE to determine if SC7 is allowed
* given a target core's C-state and wake time
*
* @state: c-state of the stats.
* @stats: integer represents the new stats.
* @allowed: pointer to result
*
* Returns 0 if success.
*/
int tegra_mce_is_sc7_allowed(u32 state, u32 wake, u32 *allowed)
{
if (mce_ops && mce_ops->is_sc7_allowed)
return mce_ops->is_sc7_allowed(state, wake, allowed);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_is_sc7_allowed);
/**
* Bring another offlined core back online to C0 state.
*
* @cpu: logical cpuid from smp_processor_id()
*
* Returns 0 if success.
*/
int tegra_mce_online_core(int cpu)
{
if (mce_ops && mce_ops->online_core)
return mce_ops->online_core(cpu);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_online_core);
/**
* Program Auto-CC3 feature.
*
* @ndiv: ndiv of IDLE voltage/freq register
* @vindex: vindex of IDLE voltage/freq register
* (Not used on tegra19x)
* @enable: enable bit for Auto-CC3
*
* Returns 0 if success.
*/
int tegra_mce_cc3_ctrl(u32 ndiv, u32 vindex, u8 enable)
{
if (mce_ops && mce_ops->cc3_ctrl)
return mce_ops->cc3_ctrl(ndiv, vindex, enable);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_cc3_ctrl);
/**
* Send data to MCE which echoes it back.
*
* @data: data to be sent to MCE.
* @out: output data to hold the response.
* @matched: pointer to matching result
*
* Returns 0 if success.
*/
int tegra_mce_echo_data(u64 data, u64 *matched)
{
if (mce_ops && mce_ops->echo_data)
return mce_ops->echo_data(data, matched);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_echo_data);
/**
* Read out MCE API major/minor versions
*
* @major: output for major number.
* @minor: output for minor number.
*
* Returns 0 if success.
*/
int tegra_mce_read_versions(u32 *major, u32 *minor)
{
if (mce_ops && mce_ops->read_versions)
return mce_ops->read_versions(major, minor);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_versions);
/**
* Read out RT Safe Mask
*
* @rt_safe_mask: output for rt safe mask.
*
* Returns 0 if success.
*/
int tegra_mce_read_rt_safe_mask(u64 *rt_safe_mask)
{
if (mce_ops && mce_ops->read_rt_safe_mask)
return mce_ops->read_rt_safe_mask(rt_safe_mask);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_rt_safe_mask);
/**
* Write RT Safe Mask
*
* @rt_safe_mask: rt safe mask value to be written
*
* Returns 0 if success.
*/
int tegra_mce_write_rt_safe_mask(u64 rt_safe_mask)
{
if (mce_ops && mce_ops->write_rt_safe_mask)
return mce_ops->write_rt_safe_mask(rt_safe_mask);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_rt_safe_mask);
/**
* Read out RT Window US
*
* @rt_window_us: output for rt window us
*
* Returns 0 if success.
*/
int tegra_mce_read_rt_window_us(u64 *rt_window_us)
{
if (mce_ops && mce_ops->read_rt_window_us)
return mce_ops->read_rt_window_us(rt_window_us);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_rt_window_us);
/**
* Write RT Window US
*
* @rt_window_us: rt window us value to be written
*
* Returns 0 if success.
*/
int tegra_mce_write_rt_window_us(u64 rt_window_us)
{
if (mce_ops && mce_ops->write_rt_window_us)
return mce_ops->write_rt_window_us(rt_window_us);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_rt_window_us);
/**
* Read out RT Fwd Progress US
*
* @rt_fwd_progress_us: output for rt fwd progress us
*
* Returns 0 if success.
*/
int tegra_mce_read_rt_fwd_progress_us(u64 *rt_fwd_progress_us)
{
if (mce_ops && mce_ops->read_rt_fwd_progress_us)
return mce_ops->read_rt_fwd_progress_us(rt_fwd_progress_us);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_rt_fwd_progress_us);
/**
* Write RT Fwd Progress US
*
* @rt_fwd_progress_us: rt fwd progress us value to be written
*
* Returns 0 if success.
*/
int tegra_mce_write_rt_fwd_progress_us(u64 rt_fwd_progress_us)
{
if (mce_ops && mce_ops->write_rt_fwd_progress_us)
return mce_ops->write_rt_fwd_progress_us(rt_fwd_progress_us);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_rt_fwd_progress_us);
/**
* Enumerate MCE API features
*
* @features: output feature vector (4bits each)
*
* Returns 0 if success.
*/
int tegra_mce_enum_features(u64 *features)
{
if (mce_ops && mce_ops->enum_features)
return mce_ops->enum_features(features);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_enum_features);
/**
* Read uncore MCA errors.
*
* @cmd: MCA command
* @data: output data for the command
* @error: error from MCA
*
* Returns 0 if success.
*/
int tegra_mce_read_uncore_mca(mca_cmd_t cmd, u64 *data, u32 *error)
{
if (mce_ops && mce_ops->read_uncore_mca)
return mce_ops->read_uncore_mca(cmd, data, error);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_uncore_mca);
/**
* Write uncore MCA errors.
*
* @cmd: MCA command
* @data: input data for the command
* @error: error from MCA
*
* Returns 0 if success.
*/
int tegra_mce_write_uncore_mca(mca_cmd_t cmd, u64 data, u32 *error)
{
if (mce_ops && mce_ops->write_uncore_mca)
return mce_ops->write_uncore_mca(cmd, data, error);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_uncore_mca);
/**
* Query PMU for uncore perfmon counter
*
* @req input command and counter index
* @data output counter value
*
* Returns status of read request.
*/
int tegra_mce_read_uncore_perfmon(u32 req, u32 *data)
{
if (mce_ops && mce_ops->read_uncore_perfmon)
return mce_ops->read_uncore_perfmon(req, data);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_uncore_perfmon);
/**
* Write PMU reg for uncore perfmon counter
*
* @req input command and counter index
* @data data to be written
*
* Returns status of write request.
*/
int tegra_mce_write_uncore_perfmon(u32 req, u32 data)
{
if (mce_ops && mce_ops->write_uncore_perfmon)
return mce_ops->write_uncore_perfmon(req, data);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_uncore_perfmon);
int tegra_mce_enable_latic(void)
{
if (mce_ops && mce_ops->enable_latic)
return mce_ops->enable_latic();
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_enable_latic);
/**
* Write to NVG DDA registers
*
* @index: NVG communication channel id
* @value: Register value to be written
*
* Returns 0 on success
*/
int tegra_mce_write_dda_ctrl(u32 index, u64 value)
{
if(mce_ops && mce_ops->write_dda_ctrl)
return mce_ops->write_dda_ctrl(index, value);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_dda_ctrl);
/**
* Read NVG DDA registers
*
* @index: NVG communication channel id
* @value: Associated register value read
*
* Returns 0 on success
*/
int tegra_mce_read_dda_ctrl(u32 index, u64 *value)
{
if(mce_ops && mce_ops->read_dda_ctrl)
return mce_ops->read_dda_ctrl(index, value);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_dda_ctrl);
/**
* Read NVG L3 cache control register
*
* @value: Fill L3 cache ways
*
* Returns 0 on success
*/
int tegra_mce_read_l3_cache_ways(u64 *value)
{
if (mce_ops && mce_ops->read_l3_cache_ways)
return mce_ops->read_l3_cache_ways(value);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_read_l3_cache_ways);
/**
* Write L3 cache ways and read back the l3 cache ways written
*
* @data: L3 cache ways to be writtein
* @value: L3 cache ways returrned back
*
* Returns 0 on success
*/
int tegra_mce_write_l3_cache_ways(u64 data, u64 *value)
{
if (mce_ops && mce_ops->write_l3_cache_ways)
return mce_ops->write_l3_cache_ways(data, value);
else
return -ENOTSUPP;
}
EXPORT_SYMBOL_GPL(tegra_mce_write_l3_cache_ways);
MODULE_AUTHOR("NVIDIA Corporation");
MODULE_LICENSE("GPL v2");