mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 13:41:48 -04:00
i2c: tegra: Introduce tegra_i2c_variant to identify DVC and VI
Replace the per-instance DVC/VI boolean flags with a tegra_i2c_variant enum and move the variant field into tegra_i2c_hw_feature so it is populated via SoC match data. Add dedicated SoC data entries for the "nvidia,tegra20-i2c-dvc" and "nvidia,tegra210-i2c-vi" compatibles and drop compatible-string checks from tegra_i2c_parse_dt. Suggested-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Kartik Rajput <kkartik@nvidia.com> Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Tested-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://lore.kernel.org/r/20260324055843.549808-2-kkartik@nvidia.com
This commit is contained in:
committed by
Andi Shyti
parent
4f1e5c9672
commit
4eeb19aaff
@@ -171,6 +171,18 @@ enum msg_end_type {
|
||||
MSG_END_CONTINUE,
|
||||
};
|
||||
|
||||
/*
|
||||
* tegra_i2c_variant: Identifies the variant of I2C controller.
|
||||
* @TEGRA_I2C_VARIANT_DEFAULT: Identifies the default I2C controller.
|
||||
* @TEGRA_I2C_VARIANT_DVC: Identifies the DVC I2C controller, has a different register layout.
|
||||
* @TEGRA_I2C_VARIANT_VI: Identifies the VI I2C controller, has a different register layout.
|
||||
*/
|
||||
enum tegra_i2c_variant {
|
||||
TEGRA_I2C_VARIANT_DEFAULT,
|
||||
TEGRA_I2C_VARIANT_DVC,
|
||||
TEGRA_I2C_VARIANT_VI,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tegra_i2c_hw_feature : per hardware generation features
|
||||
* @has_continue_xfer_support: continue-transfer supported
|
||||
@@ -223,6 +235,7 @@ enum msg_end_type {
|
||||
* timing settings.
|
||||
* @enable_hs_mode_support: Enable support for high speed (HS) mode transfers.
|
||||
* @has_mutex: Has mutex register for mutual exclusion with other firmwares or VMs.
|
||||
* @variant: This represents the I2C controller variant.
|
||||
*/
|
||||
struct tegra_i2c_hw_feature {
|
||||
bool has_continue_xfer_support;
|
||||
@@ -254,6 +267,7 @@ struct tegra_i2c_hw_feature {
|
||||
bool has_interface_timing_reg;
|
||||
bool enable_hs_mode_support;
|
||||
bool has_mutex;
|
||||
enum tegra_i2c_variant variant;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -268,8 +282,6 @@ struct tegra_i2c_hw_feature {
|
||||
* @base_phys: physical base address of the I2C controller
|
||||
* @cont_id: I2C controller ID, used for packet header
|
||||
* @irq: IRQ number of transfer complete interrupt
|
||||
* @is_dvc: identifies the DVC I2C controller, has a different register layout
|
||||
* @is_vi: identifies the VI I2C controller, has a different register layout
|
||||
* @msg_complete: transfer completion notifier
|
||||
* @msg_buf_remaining: size of unsent data in the message buffer
|
||||
* @msg_len: length of message in current transfer
|
||||
@@ -321,12 +333,12 @@ struct tegra_i2c_dev {
|
||||
bool atomic_mode;
|
||||
bool dma_mode;
|
||||
bool msg_read;
|
||||
bool is_dvc;
|
||||
bool is_vi;
|
||||
};
|
||||
|
||||
#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && (dev)->is_dvc)
|
||||
#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && (dev)->is_vi)
|
||||
#define IS_DVC(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && \
|
||||
(dev)->hw->variant == TEGRA_I2C_VARIANT_DVC)
|
||||
#define IS_VI(dev) (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) && \
|
||||
(dev)->hw->variant == TEGRA_I2C_VARIANT_VI)
|
||||
|
||||
static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
|
||||
unsigned int reg)
|
||||
@@ -1635,8 +1647,42 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
|
||||
.has_interface_timing_reg = false,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
|
||||
static const struct tegra_i2c_hw_feature tegra20_dvc_i2c_hw = {
|
||||
.has_continue_xfer_support = false,
|
||||
.has_per_pkt_xfer_complete_irq = false,
|
||||
.clk_divisor_hs_mode = 3,
|
||||
.clk_divisor_std_mode = 0,
|
||||
.clk_divisor_fast_mode = 0,
|
||||
.clk_divisor_fast_plus_mode = 0,
|
||||
.has_config_load_reg = false,
|
||||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = false,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = false,
|
||||
.has_apb_dma = true,
|
||||
.tlow_std_mode = 0x4,
|
||||
.thigh_std_mode = 0x2,
|
||||
.tlow_fast_mode = 0x4,
|
||||
.thigh_fast_mode = 0x2,
|
||||
.tlow_fastplus_mode = 0x4,
|
||||
.thigh_fastplus_mode = 0x2,
|
||||
.setup_hold_time_std_mode = 0x0,
|
||||
.setup_hold_time_fast_mode = 0x0,
|
||||
.setup_hold_time_fastplus_mode = 0x0,
|
||||
.setup_hold_time_hs_mode = 0x0,
|
||||
.has_interface_timing_reg = false,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DVC,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
|
||||
.has_continue_xfer_support = true,
|
||||
.has_per_pkt_xfer_complete_irq = false,
|
||||
@@ -1665,6 +1711,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
|
||||
.has_interface_timing_reg = false,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
|
||||
@@ -1695,6 +1742,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
|
||||
.has_interface_timing_reg = false,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
|
||||
@@ -1725,6 +1773,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
|
||||
@@ -1755,8 +1804,42 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
static const struct tegra_i2c_hw_feature tegra210_vi_i2c_hw = {
|
||||
.has_continue_xfer_support = true,
|
||||
.has_per_pkt_xfer_complete_irq = true,
|
||||
.clk_divisor_hs_mode = 1,
|
||||
.clk_divisor_std_mode = 0x19,
|
||||
.clk_divisor_fast_mode = 0x19,
|
||||
.clk_divisor_fast_plus_mode = 0x10,
|
||||
.has_config_load_reg = true,
|
||||
.has_multi_master_mode = false,
|
||||
.has_slcg_override_reg = true,
|
||||
.has_mst_fifo = false,
|
||||
.has_mst_reset = false,
|
||||
.quirks = &tegra_i2c_quirks,
|
||||
.supports_bus_clear = true,
|
||||
.has_apb_dma = true,
|
||||
.tlow_std_mode = 0x4,
|
||||
.thigh_std_mode = 0x2,
|
||||
.tlow_fast_mode = 0x4,
|
||||
.thigh_fast_mode = 0x2,
|
||||
.tlow_fastplus_mode = 0x4,
|
||||
.thigh_fastplus_mode = 0x2,
|
||||
.setup_hold_time_std_mode = 0,
|
||||
.setup_hold_time_fast_mode = 0,
|
||||
.setup_hold_time_fastplus_mode = 0,
|
||||
.setup_hold_time_hs_mode = 0,
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_VI,
|
||||
};
|
||||
#endif
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
|
||||
.has_continue_xfer_support = true,
|
||||
.has_per_pkt_xfer_complete_irq = true,
|
||||
@@ -1785,6 +1868,7 @@ static const struct tegra_i2c_hw_feature tegra186_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = false,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
|
||||
@@ -1817,6 +1901,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = true,
|
||||
.has_mutex = false,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
|
||||
@@ -1849,6 +1934,7 @@ static const struct tegra_i2c_hw_feature tegra256_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = true,
|
||||
.has_mutex = true,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
|
||||
@@ -1881,6 +1967,7 @@ static const struct tegra_i2c_hw_feature tegra264_i2c_hw = {
|
||||
.has_interface_timing_reg = true,
|
||||
.enable_hs_mode_support = true,
|
||||
.has_mutex = true,
|
||||
.variant = TEGRA_I2C_VARIANT_DEFAULT,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_i2c_of_match[] = {
|
||||
@@ -1889,7 +1976,7 @@ static const struct of_device_id tegra_i2c_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra194-i2c", .data = &tegra194_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra186-i2c", .data = &tegra186_i2c_hw, },
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra210-i2c-vi", .data = &tegra210_vi_i2c_hw, },
|
||||
#endif
|
||||
{ .compatible = "nvidia,tegra210-i2c", .data = &tegra210_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra124-i2c", .data = &tegra124_i2c_hw, },
|
||||
@@ -1897,7 +1984,7 @@ static const struct of_device_id tegra_i2c_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra30-i2c", .data = &tegra30_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra20-i2c", .data = &tegra20_i2c_hw, },
|
||||
#if IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC)
|
||||
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_i2c_hw, },
|
||||
{ .compatible = "nvidia,tegra20-i2c-dvc", .data = &tegra20_dvc_i2c_hw, },
|
||||
#endif
|
||||
{},
|
||||
};
|
||||
@@ -1905,21 +1992,12 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match);
|
||||
|
||||
static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
|
||||
{
|
||||
struct device_node *np = i2c_dev->dev->of_node;
|
||||
bool multi_mode;
|
||||
|
||||
i2c_parse_fw_timings(i2c_dev->dev, &i2c_dev->timings, true);
|
||||
|
||||
multi_mode = device_property_read_bool(i2c_dev->dev, "multi-master");
|
||||
i2c_dev->multimaster_mode = multi_mode;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
|
||||
of_device_is_compatible(np, "nvidia,tegra20-i2c-dvc"))
|
||||
i2c_dev->is_dvc = true;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) &&
|
||||
of_device_is_compatible(np, "nvidia,tegra210-i2c-vi"))
|
||||
i2c_dev->is_vi = true;
|
||||
}
|
||||
|
||||
static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
|
||||
|
||||
Reference in New Issue
Block a user