diff --git a/recipes-kernel/linux/linux-yocto/0001-memory-tegra-Add-Tegra234-clients-for-RCE-and-VI.patch b/recipes-kernel/linux/linux-yocto/0001-memory-tegra-Add-Tegra234-clients-for-RCE-and-VI.patch new file mode 100644 index 00000000..2e95771a --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0001-memory-tegra-Add-Tegra234-clients-for-RCE-and-VI.patch @@ -0,0 +1,105 @@ +From 26ffd973703ca765fce04d644a78de8e0b180725 Mon Sep 17 00:00:00 2001 +From: Jon Hunter +Date: Thu, 12 Oct 2023 11:49:09 +0100 +Subject: [PATCH 1/9] memory: tegra: Add Tegra234 clients for RCE and VI + +Add the Tegra234 memory client entries for the Real-time Camera Engine +(RCE) and Video Input (VI) devices. + +Upstream-Status: Pending +Signed-off-by: Jon Hunter +Acked-by: Thierry Reding +Link: https://lore.kernel.org/r/20231012104909.48518-1-jonathanh@nvidia.com +Signed-off-by: Krzysztof Kozlowski +--- + drivers/memory/tegra/tegra234.c | 60 +++++++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +diff --git a/drivers/memory/tegra/tegra234.c b/drivers/memory/tegra/tegra234.c +index fa40c49b070d..b8a7af2d36c1 100644 +--- a/drivers/memory/tegra/tegra234.c ++++ b/drivers/memory/tegra/tegra234.c +@@ -449,6 +449,18 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { + .security = 0x38c, + }, + }, ++ }, { ++ .id = TEGRA234_MEMORY_CLIENT_VIW, ++ .name = "viw", ++ .bpmp_id = TEGRA_ICC_BPMP_VI, ++ .type = TEGRA_ICC_ISO_VI, ++ .sid = TEGRA234_SID_ISO_VI, ++ .regs = { ++ .sid = { ++ .override = 0x390, ++ .security = 0x394, ++ }, ++ }, + }, { + .id = TEGRA234_MEMORY_CLIENT_NVDECSRD, + .name = "nvdecsrd", +@@ -621,6 +633,30 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { + .security = 0x50c, + }, + }, ++ }, { ++ .id = TEGRA234_MEMORY_CLIENT_VIFALR, ++ .name = "vifalr", ++ .bpmp_id = TEGRA_ICC_BPMP_VIFAL, ++ .type = TEGRA_ICC_ISO_VIFAL, ++ .sid = TEGRA234_SID_ISO_VIFALC, ++ .regs = { ++ .sid = { ++ .override = 0x5e0, ++ .security = 0x5e4, ++ }, ++ }, ++ }, { ++ .id = TEGRA234_MEMORY_CLIENT_VIFALW, ++ .name = "vifalw", ++ .bpmp_id = TEGRA_ICC_BPMP_VIFAL, ++ .type = TEGRA_ICC_ISO_VIFAL, ++ .sid = TEGRA234_SID_ISO_VIFALC, ++ .regs = { ++ .sid = { ++ .override = 0x5e8, ++ .security = 0x5ec, ++ }, ++ }, + }, { + .id = TEGRA234_MEMORY_CLIENT_DLA0RDA, + .name = "dla0rda", +@@ -701,6 +737,30 @@ static const struct tegra_mc_client tegra234_mc_clients[] = { + .security = 0x62c, + }, + }, ++ }, { ++ .id = TEGRA234_MEMORY_CLIENT_RCER, ++ .name = "rcer", ++ .bpmp_id = TEGRA_ICC_BPMP_RCE, ++ .type = TEGRA_ICC_NISO, ++ .sid = TEGRA234_SID_RCE, ++ .regs = { ++ .sid = { ++ .override = 0x690, ++ .security = 0x694, ++ }, ++ }, ++ }, { ++ .id = TEGRA234_MEMORY_CLIENT_RCEW, ++ .name = "rcew", ++ .bpmp_id = TEGRA_ICC_BPMP_RCE, ++ .type = TEGRA_ICC_NISO, ++ .sid = TEGRA234_SID_RCE, ++ .regs = { ++ .sid = { ++ .override = 0x698, ++ .security = 0x69c, ++ }, ++ }, + }, { + .id = TEGRA234_MEMORY_CLIENT_PCIE0R, + .name = "pcie0r", +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0002-hwmon-ina3221-Add-support-for-channel-summation-disa.patch b/recipes-kernel/linux/linux-yocto/0002-hwmon-ina3221-Add-support-for-channel-summation-disa.patch new file mode 100644 index 00000000..01ec72f1 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0002-hwmon-ina3221-Add-support-for-channel-summation-disa.patch @@ -0,0 +1,188 @@ +From ab5e670e06c3385fd9ec1f6809b4742495558151 Mon Sep 17 00:00:00 2001 +From: Ninad Malwade +Date: Fri, 29 Sep 2023 11:36:49 +0100 +Subject: [PATCH 2/9] hwmon: (ina3221) Add support for channel summation + disable + +The INA3221 allows the Critical alert pin to be controlled by the +summation control function. This function adds the single +shunt-voltage conversions for the desired channels in order to compare +the combined sum to the programmed limit. The Shunt-Voltage Sum Limit +register contains the programmed value that is compared to the value in +the Shunt-Voltage Sum register in order to determine if the total summed +limit is exceeded. If the shunt-voltage sum limit value is exceeded, the +Critical alert pin pulls low. + +For the summation limit to have a meaningful value, we have to use the +same shunt-resistor value on all included channels. Unless equal +shunt-resistor values are used for each channel, the summation control +function cannot be used and it is not enabled by the driver. + +To address this, add support to disable the summation of specific +channels via device tree property "ti,summation-disable". The channel +which has this property would be excluded from the calculation of +summation control function. + +For example, summation control function calculates Shunt-Voltage Sum as: + +- input_shunt_voltage_summation = input_shunt_voltage_channel1 + + input_shunt_voltage_channel2 + + input_shunt_voltage_channel3 + +If we want the summation to only use channel1 and channel3, we can add +'ti,summation-disable' property in device tree node for channel2. Then +the calculation will skip channel2. + +- input_shunt_voltage_summation = input_shunt_voltage_channel1 + + input_shunt_voltage_channel3 + +Note that we only want the channel to be skipped for summation control +function rather than completely disabled. Therefore, even if we add the +property 'ti,summation-disable', the channel is still enabled and +functional. + +Finally, create debugfs entries that display if summation is disabled +for each of the channels. + +Upstream-Status: Pending +Signed-off-by: Rajkumar Kasirajan +Signed-off-by: Ninad Malwade +Co-developed-by: Jon Hunter +Signed-off-by: Jon Hunter +Link: https://lore.kernel.org/r/20230929103650.86074-4-jonathanh@nvidia.com +Signed-off-by: Guenter Roeck +--- + drivers/hwmon/ina3221.c | 33 ++++++++++++++++++++++++++++++--- + 1 file changed, 30 insertions(+), 3 deletions(-) + +diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c +index 5ab944056ec0..5ffdc94db436 100644 +--- a/drivers/hwmon/ina3221.c ++++ b/drivers/hwmon/ina3221.c +@@ -6,6 +6,7 @@ + * Andrew F. Davis + */ + ++#include + #include + #include + #include +@@ -99,11 +100,13 @@ enum ina3221_channels { + * @label: label of channel input source + * @shunt_resistor: shunt resistor value of channel input source + * @disconnected: connection status of channel input source ++ * @summation_disable: channel summation status of input source + */ + struct ina3221_input { + const char *label; + int shunt_resistor; + bool disconnected; ++ bool summation_disable; + }; + + /** +@@ -113,8 +116,10 @@ struct ina3221_input { + * @fields: Register fields of the device + * @inputs: Array of channel input source specific structures + * @lock: mutex lock to serialize sysfs attribute accesses ++ * @debugfs: Pointer to debugfs entry for device + * @reg_config: Register value of INA3221_CONFIG + * @summation_shunt_resistor: equivalent shunt resistor value for summation ++ * @summation_channel_control: Value written to SCC field in INA3221_MASK_ENABLE + * @single_shot: running in single-shot operating mode + */ + struct ina3221_data { +@@ -123,8 +128,10 @@ struct ina3221_data { + struct regmap_field *fields[F_MAX_FIELDS]; + struct ina3221_input inputs[INA3221_NUM_CHANNELS]; + struct mutex lock; ++ struct dentry *debugfs; + u32 reg_config; + int summation_shunt_resistor; ++ u32 summation_channel_control; + + bool single_shot; + }; +@@ -154,7 +161,8 @@ static inline int ina3221_summation_shunt_resistor(struct ina3221_data *ina) + int i, shunt_resistor = 0; + + for (i = 0; i < INA3221_NUM_CHANNELS; i++) { +- if (input[i].disconnected || !input[i].shunt_resistor) ++ if (input[i].disconnected || !input[i].shunt_resistor || ++ input[i].summation_disable) + continue; + if (!shunt_resistor) { + /* Found the reference shunt resistor value */ +@@ -786,6 +794,9 @@ static int ina3221_probe_child_from_dt(struct device *dev, + /* Save the connected input label if available */ + of_property_read_string(child, "label", &input->label); + ++ /* summation channel control */ ++ input->summation_disable = of_property_read_bool(child, "ti,summation-disable"); ++ + /* Overwrite default shunt resistor value optionally */ + if (!of_property_read_u32(child, "shunt-resistor-micro-ohms", &val)) { + if (val < 1 || val > INT_MAX) { +@@ -827,6 +838,7 @@ static int ina3221_probe(struct i2c_client *client) + struct device *dev = &client->dev; + struct ina3221_data *ina; + struct device *hwmon_dev; ++ char name[32]; + int i, ret; + + ina = devm_kzalloc(dev, sizeof(*ina), GFP_KERNEL); +@@ -873,6 +885,10 @@ static int ina3221_probe(struct i2c_client *client) + + /* Initialize summation_shunt_resistor for summation channel control */ + ina->summation_shunt_resistor = ina3221_summation_shunt_resistor(ina); ++ for (i = 0; i < INA3221_NUM_CHANNELS; i++) { ++ if (!ina->inputs[i].summation_disable) ++ ina->summation_channel_control |= BIT(14 - i); ++ } + + ina->pm_dev = dev; + mutex_init(&ina->lock); +@@ -900,6 +916,15 @@ static int ina3221_probe(struct i2c_client *client) + goto fail; + } + ++ scnprintf(name, sizeof(name), "%s-%s", INA3221_DRIVER_NAME, dev_name(dev)); ++ ina->debugfs = debugfs_create_dir(name, NULL); ++ ++ for (i = 0; i < INA3221_NUM_CHANNELS; i++) { ++ scnprintf(name, sizeof(name), "in%d_summation_disable", i); ++ debugfs_create_bool(name, 0400, ina->debugfs, ++ &ina->inputs[i].summation_disable); ++ } ++ + return 0; + + fail: +@@ -918,6 +943,8 @@ static void ina3221_remove(struct i2c_client *client) + struct ina3221_data *ina = dev_get_drvdata(&client->dev); + int i; + ++ debugfs_remove_recursive(ina->debugfs); ++ + pm_runtime_disable(ina->pm_dev); + pm_runtime_set_suspended(ina->pm_dev); + +@@ -978,13 +1005,13 @@ static int ina3221_resume(struct device *dev) + /* Initialize summation channel control */ + if (ina->summation_shunt_resistor) { + /* +- * Take all three channels into summation by default ++ * Sum only channels that are not disabled for summation. + * Shunt measurements of disconnected channels should + * be 0, so it does not matter for summation. + */ + ret = regmap_update_bits(ina->regmap, INA3221_MASK_ENABLE, + INA3221_MASK_ENABLE_SCC_MASK, +- INA3221_MASK_ENABLE_SCC_MASK); ++ ina->summation_channel_control); + if (ret) { + dev_err(dev, "Unable to control summation channel\n"); + return ret; +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0003-cpufreq-tegra194-save-CPU-data-to-avoid-repeated-SMP.patch b/recipes-kernel/linux/linux-yocto/0003-cpufreq-tegra194-save-CPU-data-to-avoid-repeated-SMP.patch new file mode 100644 index 00000000..c0458653 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0003-cpufreq-tegra194-save-CPU-data-to-avoid-repeated-SMP.patch @@ -0,0 +1,201 @@ +From 72159b110a95f50887784dbb7771cbbcefde7576 Mon Sep 17 00:00:00 2001 +From: Sumit Gupta +Date: Wed, 4 Oct 2023 19:35:36 +0530 +Subject: [PATCH 3/9] cpufreq: tegra194: save CPU data to avoid repeated SMP + calls + +Currently, we make SMP call on every frequency set request to get the +physical 'CPU ID' and 'CLUSTER ID' for the target CPU. This change +optimizes the repeated calls by storing the physical IDs and the per +core frequency register offset for all CPUs during boot. Later this +info is used directly when required to set the frequency or read it +from ACTMON counters. + +Upstream-Status: Pending +Signed-off-by: Sumit Gupta +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/tegra194-cpufreq.c | 79 +++++++++++++++++++----------- + 1 file changed, 51 insertions(+), 28 deletions(-) + +diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c +index 386aed3637b4..f6a8e6cf6d94 100644 +--- a/drivers/cpufreq/tegra194-cpufreq.c ++++ b/drivers/cpufreq/tegra194-cpufreq.c +@@ -39,6 +39,12 @@ + /* cpufreq transisition latency */ + #define TEGRA_CPUFREQ_TRANSITION_LATENCY (300 * 1000) /* unit in nanoseconds */ + ++struct tegra_cpu_data { ++ u32 cpuid; ++ u32 clusterid; ++ void __iomem *freq_core_reg; ++}; ++ + struct tegra_cpu_ctr { + u32 cpu; + u32 coreclk_cnt, last_coreclk_cnt; +@@ -69,6 +75,7 @@ struct tegra194_cpufreq_data { + struct cpufreq_frequency_table **bpmp_luts; + const struct tegra_cpufreq_soc *soc; + bool icc_dram_bw_scaling; ++ struct tegra_cpu_data *cpu_data; + }; + + static struct workqueue_struct *read_counters_wq; +@@ -116,14 +123,8 @@ static void tegra234_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) + static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); +- void __iomem *freq_core_reg; +- u64 mpidr_id; +- +- /* use physical id to get address of per core frequency register */ +- mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; +- freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); + +- *ndiv = readl(freq_core_reg) & NDIV_MASK; ++ *ndiv = readl(data->cpu_data[cpu].freq_core_reg) & NDIV_MASK; + + return 0; + } +@@ -131,19 +132,10 @@ static int tegra234_get_cpu_ndiv(u32 cpu, u32 cpuid, u32 clusterid, u64 *ndiv) + static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); +- void __iomem *freq_core_reg; +- u32 cpu, cpuid, clusterid; +- u64 mpidr_id; +- +- for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) { +- data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); +- +- /* use physical id to get address of per core frequency register */ +- mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; +- freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); ++ u32 cpu; + +- writel(ndiv, freq_core_reg); +- } ++ for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) ++ writel(ndiv, data->cpu_data[cpu].freq_core_reg); + } + + /* +@@ -157,11 +149,10 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + void __iomem *actmon_reg; +- u32 cpuid, clusterid; + u64 val; + +- data->soc->ops->get_cpu_cluster_id(c->cpu, &cpuid, &clusterid); +- actmon_reg = CORE_ACTMON_CNTR_REG(data, clusterid, cpuid); ++ actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid, ++ data->cpu_data[c->cpu].cpuid); + + val = readq(actmon_reg); + c->last_refclk_cnt = upper_32_bits(val); +@@ -357,19 +348,17 @@ static void tegra194_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) + static unsigned int tegra194_get_speed(u32 cpu) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); ++ u32 clusterid = data->cpu_data[cpu].clusterid; + struct cpufreq_frequency_table *pos; +- u32 cpuid, clusterid; + unsigned int rate; + u64 ndiv; + int ret; + +- data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); +- + /* reconstruct actual cpu freq using counters */ + rate = tegra194_calculate_speed(cpu); + + /* get last written ndiv value */ +- ret = data->soc->ops->get_cpu_ndiv(cpu, cpuid, clusterid, &ndiv); ++ ret = data->soc->ops->get_cpu_ndiv(cpu, data->cpu_data[cpu].cpuid, clusterid, &ndiv); + if (WARN_ON_ONCE(ret)) + return rate; + +@@ -475,13 +464,12 @@ static int tegra194_cpufreq_init(struct cpufreq_policy *policy) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + int maxcpus_per_cluster = data->soc->maxcpus_per_cluster; ++ u32 clusterid = data->cpu_data[policy->cpu].clusterid; + struct cpufreq_frequency_table *freq_table; + struct cpufreq_frequency_table *bpmp_lut; + u32 start_cpu, cpu; +- u32 clusterid; + int ret; + +- data->soc->ops->get_cpu_cluster_id(policy->cpu, NULL, &clusterid); + if (clusterid >= data->soc->num_clusters || !data->bpmp_luts[clusterid]) + return -EINVAL; + +@@ -659,6 +647,28 @@ tegra_cpufreq_bpmp_read_lut(struct platform_device *pdev, struct tegra_bpmp *bpm + return freq_table; + } + ++static int tegra194_cpufreq_store_physids(unsigned int cpu, struct tegra194_cpufreq_data *data) ++{ ++ int num_cpus = data->soc->maxcpus_per_cluster * data->soc->num_clusters; ++ u32 cpuid, clusterid; ++ u64 mpidr_id; ++ ++ if (cpu > (num_cpus - 1)) { ++ pr_err("cpufreq: wrong num of cpus or clusters in soc data\n"); ++ return -EINVAL; ++ } ++ ++ data->soc->ops->get_cpu_cluster_id(cpu, &cpuid, &clusterid); ++ ++ mpidr_id = (clusterid * data->soc->maxcpus_per_cluster) + cpuid; ++ ++ data->cpu_data[cpu].cpuid = cpuid; ++ data->cpu_data[cpu].clusterid = clusterid; ++ data->cpu_data[cpu].freq_core_reg = SCRATCH_FREQ_CORE_REG(data, mpidr_id); ++ ++ return 0; ++} ++ + static int tegra194_cpufreq_probe(struct platform_device *pdev) + { + const struct tegra_cpufreq_soc *soc; +@@ -666,6 +676,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) + struct tegra_bpmp *bpmp; + struct device *cpu_dev; + int err, i; ++ u32 cpu; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) +@@ -692,6 +703,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) + return PTR_ERR(data->regs); + } + ++ data->cpu_data = devm_kcalloc(&pdev->dev, data->soc->num_clusters * ++ data->soc->maxcpus_per_cluster, ++ sizeof(*data->cpu_data), GFP_KERNEL); ++ if (!data->cpu_data) ++ return -ENOMEM; ++ + platform_set_drvdata(pdev, data); + + bpmp = tegra_bpmp_get(&pdev->dev); +@@ -713,6 +730,12 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) + } + } + ++ for_each_possible_cpu(cpu) { ++ err = tegra194_cpufreq_store_physids(cpu, data); ++ if (err) ++ goto err_free_res; ++ } ++ + tegra194_cpufreq_driver.driver_data = data; + + /* Check for optional OPPv2 and interconnect paths on CPU0 to enable ICC scaling */ +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0004-cpufreq-tegra194-use-refclk-delta-based-loop-instead.patch b/recipes-kernel/linux/linux-yocto/0004-cpufreq-tegra194-use-refclk-delta-based-loop-instead.patch new file mode 100644 index 00000000..236bf5f3 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0004-cpufreq-tegra194-use-refclk-delta-based-loop-instead.patch @@ -0,0 +1,195 @@ +From 417688bed63554f235fdc4b03c078a8ee2efcbc8 Mon Sep 17 00:00:00 2001 +From: Sumit Gupta +Date: Wed, 4 Oct 2023 19:35:37 +0530 +Subject: [PATCH 4/9] cpufreq: tegra194: use refclk delta based loop instead of + udelay + +Use reference clock count based loop instead of "udelay()" for +sampling of counters to improve the accuracy of re-generated CPU +frequency. "udelay()" internally calls "WFE" which stops the +counters and results in bigger delta between the last set freq +and the re-generated value from counters. The counter sampling +window used in loop is the minimum number of reference clock +cycles which is known to give a stable value of CPU frequency. +The change also helps to reduce the sampling window from "500us" +to "<50us". + +Upstream-Status: Pending +Suggested-by: Antti Miettinen +Signed-off-by: Sumit Gupta +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/tegra194-cpufreq.c | 72 +++++++++++++++++++++++------- + 1 file changed, 55 insertions(+), 17 deletions(-) + +diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c +index f6a8e6cf6d94..9dae6195e0e7 100644 +--- a/drivers/cpufreq/tegra194-cpufreq.c ++++ b/drivers/cpufreq/tegra194-cpufreq.c +@@ -5,7 +5,6 @@ + + #include + #include +-#include + #include + #include + #include +@@ -21,10 +20,11 @@ + + #define KHZ 1000 + #define REF_CLK_MHZ 408 /* 408 MHz */ +-#define US_DELAY 500 + #define CPUFREQ_TBL_STEP_HZ (50 * KHZ * KHZ) + #define MAX_CNT ~0U + ++#define MAX_DELTA_KHZ 115200 ++ + #define NDIV_MASK 0x1FF + + #define CORE_OFFSET(cpu) (cpu * 8) +@@ -68,6 +68,7 @@ struct tegra_cpufreq_soc { + int maxcpus_per_cluster; + unsigned int num_clusters; + phys_addr_t actmon_cntr_base; ++ u32 refclk_delta_min; + }; + + struct tegra194_cpufreq_data { +@@ -149,6 +150,8 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c) + { + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + void __iomem *actmon_reg; ++ u32 delta_refcnt; ++ int cnt = 0; + u64 val; + + actmon_reg = CORE_ACTMON_CNTR_REG(data, data->cpu_data[c->cpu].clusterid, +@@ -157,10 +160,25 @@ static void tegra234_read_counters(struct tegra_cpu_ctr *c) + val = readq(actmon_reg); + c->last_refclk_cnt = upper_32_bits(val); + c->last_coreclk_cnt = lower_32_bits(val); +- udelay(US_DELAY); +- val = readq(actmon_reg); +- c->refclk_cnt = upper_32_bits(val); +- c->coreclk_cnt = lower_32_bits(val); ++ ++ /* ++ * The sampling window is based on the minimum number of reference ++ * clock cycles which is known to give a stable value of CPU frequency. ++ */ ++ do { ++ val = readq(actmon_reg); ++ c->refclk_cnt = upper_32_bits(val); ++ c->coreclk_cnt = lower_32_bits(val); ++ if (c->refclk_cnt < c->last_refclk_cnt) ++ delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt); ++ else ++ delta_refcnt = c->refclk_cnt - c->last_refclk_cnt; ++ if (++cnt >= 0xFFFF) { ++ pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n", ++ c->cpu, delta_refcnt, cnt); ++ break; ++ } ++ } while (delta_refcnt < data->soc->refclk_delta_min); + } + + static struct tegra_cpufreq_ops tegra234_cpufreq_ops = { +@@ -175,6 +193,7 @@ static const struct tegra_cpufreq_soc tegra234_cpufreq_soc = { + .actmon_cntr_base = 0x9000, + .maxcpus_per_cluster = 4, + .num_clusters = 3, ++ .refclk_delta_min = 16000, + }; + + static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = { +@@ -182,6 +201,7 @@ static const struct tegra_cpufreq_soc tegra239_cpufreq_soc = { + .actmon_cntr_base = 0x4000, + .maxcpus_per_cluster = 8, + .num_clusters = 1, ++ .refclk_delta_min = 16000, + }; + + static void tegra194_get_cpu_cluster_id(u32 cpu, u32 *cpuid, u32 *clusterid) +@@ -222,15 +242,33 @@ static inline u32 map_ndiv_to_freq(struct mrq_cpu_ndiv_limits_response + + static void tegra194_read_counters(struct tegra_cpu_ctr *c) + { ++ struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); ++ u32 delta_refcnt; ++ int cnt = 0; + u64 val; + + val = read_freq_feedback(); + c->last_refclk_cnt = lower_32_bits(val); + c->last_coreclk_cnt = upper_32_bits(val); +- udelay(US_DELAY); +- val = read_freq_feedback(); +- c->refclk_cnt = lower_32_bits(val); +- c->coreclk_cnt = upper_32_bits(val); ++ ++ /* ++ * The sampling window is based on the minimum number of reference ++ * clock cycles which is known to give a stable value of CPU frequency. ++ */ ++ do { ++ val = read_freq_feedback(); ++ c->refclk_cnt = lower_32_bits(val); ++ c->coreclk_cnt = upper_32_bits(val); ++ if (c->refclk_cnt < c->last_refclk_cnt) ++ delta_refcnt = c->refclk_cnt + (MAX_CNT - c->last_refclk_cnt); ++ else ++ delta_refcnt = c->refclk_cnt - c->last_refclk_cnt; ++ if (++cnt >= 0xFFFF) { ++ pr_warn("cpufreq: problem with refclk on cpu:%d, delta_refcnt:%u, cnt:%d\n", ++ c->cpu, delta_refcnt, cnt); ++ break; ++ } ++ } while (delta_refcnt < data->soc->refclk_delta_min); + } + + static void tegra_read_counters(struct work_struct *work) +@@ -288,9 +326,8 @@ static unsigned int tegra194_calculate_speed(u32 cpu) + u32 rate_mhz; + + /* +- * udelay() is required to reconstruct cpu frequency over an +- * observation window. Using workqueue to call udelay() with +- * interrupts enabled. ++ * Reconstruct cpu frequency over an observation/sampling window. ++ * Using workqueue to keep interrupts enabled during the interval. + */ + read_counters_work.c.cpu = cpu; + INIT_WORK_ONSTACK(&read_counters_work.work, tegra_read_counters); +@@ -372,9 +409,9 @@ static unsigned int tegra194_get_speed(u32 cpu) + if (pos->driver_data != ndiv) + continue; + +- if (abs(pos->frequency - rate) > 115200) { +- pr_warn("cpufreq: cpu%d,cur:%u,set:%u,set ndiv:%llu\n", +- cpu, rate, pos->frequency, ndiv); ++ if (abs(pos->frequency - rate) > MAX_DELTA_KHZ) { ++ pr_warn("cpufreq: cpu%d,cur:%u,set:%u,delta:%d,set ndiv:%llu\n", ++ cpu, rate, pos->frequency, abs(rate - pos->frequency), ndiv); + } else { + rate = pos->frequency; + } +@@ -568,6 +605,7 @@ static const struct tegra_cpufreq_soc tegra194_cpufreq_soc = { + .ops = &tegra194_cpufreq_ops, + .maxcpus_per_cluster = 2, + .num_clusters = 4, ++ .refclk_delta_min = 16000, + }; + + static void tegra194_cpufreq_free_resources(void) +@@ -684,7 +722,7 @@ static int tegra194_cpufreq_probe(struct platform_device *pdev) + + soc = of_device_get_match_data(&pdev->dev); + +- if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters) { ++ if (soc->ops && soc->maxcpus_per_cluster && soc->num_clusters && soc->refclk_delta_min) { + data->soc = soc; + } else { + dev_err(&pdev->dev, "soc data missing\n"); +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0005-cpufreq-tegra194-remove-redundant-AND-with-cpu_onlin.patch b/recipes-kernel/linux/linux-yocto/0005-cpufreq-tegra194-remove-redundant-AND-with-cpu_onlin.patch new file mode 100644 index 00000000..ee2de108 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0005-cpufreq-tegra194-remove-redundant-AND-with-cpu_onlin.patch @@ -0,0 +1,35 @@ +From 43194c25943acd2588aff56cce80485dd31238d6 Mon Sep 17 00:00:00 2001 +From: Sumit Gupta +Date: Mon, 9 Oct 2023 13:54:23 +0530 +Subject: [PATCH 5/9] cpufreq: tegra194: remove redundant AND with + cpu_online_mask + +Remove redundant 'AND' with cpu_online_mask as the policy->cpus always +contains only the currently online CPUs. + +Upstream-Status: Pending +Suggested-by: Viresh Kumar +Link: https://lore.kernel.org/lkml/20231003050019.a6mcchw2o2z2wkrh@vireshk-i7/ +Signed-off-by: Sumit Gupta +[ Viresh: Fix rebase conflict ] +Signed-off-by: Viresh Kumar +--- + drivers/cpufreq/tegra194-cpufreq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/cpufreq/tegra194-cpufreq.c b/drivers/cpufreq/tegra194-cpufreq.c +index 9dae6195e0e7..59865ea455a8 100644 +--- a/drivers/cpufreq/tegra194-cpufreq.c ++++ b/drivers/cpufreq/tegra194-cpufreq.c +@@ -135,7 +135,7 @@ static void tegra234_set_cpu_ndiv(struct cpufreq_policy *policy, u64 ndiv) + struct tegra194_cpufreq_data *data = cpufreq_get_driver_data(); + u32 cpu; + +- for_each_cpu_and(cpu, policy->cpus, cpu_online_mask) ++ for_each_cpu(cpu, policy->cpus) + writel(ndiv, data->cpu_data[cpu].freq_core_reg); + } + +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0006-fbdev-simplefb-Support-memory-region-property.patch b/recipes-kernel/linux/linux-yocto/0006-fbdev-simplefb-Support-memory-region-property.patch new file mode 100644 index 00000000..b3177935 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0006-fbdev-simplefb-Support-memory-region-property.patch @@ -0,0 +1,101 @@ +From e9d717f5991936ee8207e5ca65c2b3dc5c13c989 Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Wed, 1 Nov 2023 18:20:16 +0100 +Subject: [PATCH 6/9] fbdev/simplefb: Support memory-region property + +The simple-framebuffer bindings specify that the "memory-region" +property can be used as an alternative to the "reg" property to define +the framebuffer memory used by the display hardware. Implement support +for this in the simplefb driver. + +Upstream-Status: Pending +Reviewed-by: Hans de Goede +Signed-off-by: Thierry Reding +Signed-off-by: Hans de Goede +Link: https://patchwork.freedesktop.org/patch/msgid/20231101172017.3872242-2-thierry.reding@gmail.com +--- + drivers/video/fbdev/simplefb.c | 35 +++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c +index 62f99f6fccd3..18025f34fde7 100644 +--- a/drivers/video/fbdev/simplefb.c ++++ b/drivers/video/fbdev/simplefb.c +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -121,12 +122,13 @@ struct simplefb_params { + u32 height; + u32 stride; + struct simplefb_format *format; ++ struct resource memory; + }; + + static int simplefb_parse_dt(struct platform_device *pdev, + struct simplefb_params *params) + { +- struct device_node *np = pdev->dev.of_node; ++ struct device_node *np = pdev->dev.of_node, *mem; + int ret; + const char *format; + int i; +@@ -166,6 +168,23 @@ static int simplefb_parse_dt(struct platform_device *pdev, + return -EINVAL; + } + ++ mem = of_parse_phandle(np, "memory-region", 0); ++ if (mem) { ++ ret = of_address_to_resource(mem, 0, ¶ms->memory); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to parse memory-region\n"); ++ of_node_put(mem); ++ return ret; ++ } ++ ++ if (of_property_present(np, "reg")) ++ dev_warn(&pdev->dev, "preferring \"memory-region\" over \"reg\" property\n"); ++ ++ of_node_put(mem); ++ } else { ++ memset(¶ms->memory, 0, sizeof(params->memory)); ++ } ++ + return 0; + } + +@@ -193,6 +212,8 @@ static int simplefb_parse_pd(struct platform_device *pdev, + return -EINVAL; + } + ++ memset(¶ms->memory, 0, sizeof(params->memory)); ++ + return 0; + } + +@@ -431,10 +452,14 @@ static int simplefb_probe(struct platform_device *pdev) + if (ret) + return ret; + +- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +- if (!res) { +- dev_err(&pdev->dev, "No memory resource\n"); +- return -EINVAL; ++ if (params.memory.start == 0 && params.memory.end == 0) { ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "No memory resource\n"); ++ return -EINVAL; ++ } ++ } else { ++ res = ¶ms.memory; + } + + mem = request_mem_region(res->start, resource_size(res), "simplefb"); +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0007-fbdev-simplefb-Add-support-for-generic-power-domains.patch b/recipes-kernel/linux/linux-yocto/0007-fbdev-simplefb-Add-support-for-generic-power-domains.patch new file mode 100644 index 00000000..f0ede312 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0007-fbdev-simplefb-Add-support-for-generic-power-domains.patch @@ -0,0 +1,150 @@ +From a0be355e6802345084fbca28646ce9e3c7defddf Mon Sep 17 00:00:00 2001 +From: Thierry Reding +Date: Wed, 1 Nov 2023 18:20:17 +0100 +Subject: [PATCH 7/9] fbdev/simplefb: Add support for generic power-domains + +The simple-framebuffer device tree bindings document the power-domains +property, so make sure that simplefb supports it. This ensures that the +power domains remain enabled as long as simplefb is active. + +v2: - remove unnecessary call to simplefb_detach_genpds() since that's + already done automatically by devres + - fix crash if power-domains property is missing in DT + +Upstream-Status: Pending +Signed-off-by: Thierry Reding +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Link: https://patchwork.freedesktop.org/patch/msgid/20231101172017.3872242-3-thierry.reding@gmail.com +--- + drivers/video/fbdev/simplefb.c | 93 ++++++++++++++++++++++++++++++++++ + 1 file changed, 93 insertions(+) + +diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c +index 18025f34fde7..fe682af63827 100644 +--- a/drivers/video/fbdev/simplefb.c ++++ b/drivers/video/fbdev/simplefb.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + + static const struct fb_fix_screeninfo simplefb_fix = { +@@ -78,6 +79,11 @@ struct simplefb_par { + unsigned int clk_count; + struct clk **clks; + #endif ++#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS ++ unsigned int num_genpds; ++ struct device **genpds; ++ struct device_link **genpd_links; ++#endif + #if defined CONFIG_OF && defined CONFIG_REGULATOR + bool regulators_enabled; + u32 regulator_count; +@@ -432,6 +438,89 @@ static void simplefb_regulators_enable(struct simplefb_par *par, + static void simplefb_regulators_destroy(struct simplefb_par *par) { } + #endif + ++#if defined CONFIG_OF && defined CONFIG_PM_GENERIC_DOMAINS ++static void simplefb_detach_genpds(void *res) ++{ ++ struct simplefb_par *par = res; ++ unsigned int i = par->num_genpds; ++ ++ if (par->num_genpds <= 1) ++ return; ++ ++ while (i--) { ++ if (par->genpd_links[i]) ++ device_link_del(par->genpd_links[i]); ++ ++ if (!IS_ERR_OR_NULL(par->genpds[i])) ++ dev_pm_domain_detach(par->genpds[i], true); ++ } ++} ++ ++static int simplefb_attach_genpds(struct simplefb_par *par, ++ struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ unsigned int i; ++ int err; ++ ++ err = of_count_phandle_with_args(dev->of_node, "power-domains", ++ "#power-domain-cells"); ++ if (err < 0) { ++ dev_info(dev, "failed to parse power-domains: %d\n", err); ++ return err; ++ } ++ ++ par->num_genpds = err; ++ ++ /* ++ * Single power-domain devices are handled by the driver core, so ++ * nothing to do here. ++ */ ++ if (par->num_genpds <= 1) ++ return 0; ++ ++ par->genpds = devm_kcalloc(dev, par->num_genpds, sizeof(*par->genpds), ++ GFP_KERNEL); ++ if (!par->genpds) ++ return -ENOMEM; ++ ++ par->genpd_links = devm_kcalloc(dev, par->num_genpds, ++ sizeof(*par->genpd_links), ++ GFP_KERNEL); ++ if (!par->genpd_links) ++ return -ENOMEM; ++ ++ for (i = 0; i < par->num_genpds; i++) { ++ par->genpds[i] = dev_pm_domain_attach_by_id(dev, i); ++ if (IS_ERR(par->genpds[i])) { ++ err = PTR_ERR(par->genpds[i]); ++ if (err == -EPROBE_DEFER) { ++ simplefb_detach_genpds(par); ++ return err; ++ } ++ ++ dev_warn(dev, "failed to attach domain %u: %d\n", i, err); ++ continue; ++ } ++ ++ par->genpd_links[i] = device_link_add(dev, par->genpds[i], ++ DL_FLAG_STATELESS | ++ DL_FLAG_PM_RUNTIME | ++ DL_FLAG_RPM_ACTIVE); ++ if (!par->genpd_links[i]) ++ dev_warn(dev, "failed to link power-domain %u\n", i); ++ } ++ ++ return devm_add_action_or_reset(dev, simplefb_detach_genpds, par); ++} ++#else ++static int simplefb_attach_genpds(struct simplefb_par *par, ++ struct platform_device *pdev) ++{ ++ return 0; ++} ++#endif ++ + static int simplefb_probe(struct platform_device *pdev) + { + int ret; +@@ -518,6 +607,10 @@ static int simplefb_probe(struct platform_device *pdev) + if (ret < 0) + goto error_clocks; + ++ ret = simplefb_attach_genpds(par, pdev); ++ if (ret < 0) ++ goto error_regulators; ++ + simplefb_clocks_enable(par, pdev); + simplefb_regulators_enable(par, pdev); + +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/0008-UBUNTU-SAUCE-PCI-endpoint-Add-core_deinit-callback-s.patch b/recipes-kernel/linux/linux-yocto/0008-UBUNTU-SAUCE-PCI-endpoint-Add-core_deinit-callback-s.patch new file mode 100644 index 00000000..ca61690b --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/0008-UBUNTU-SAUCE-PCI-endpoint-Add-core_deinit-callback-s.patch @@ -0,0 +1,98 @@ +From 30e70a4c2fec54bce91fa1fc53cca7c9ee9390ca Mon Sep 17 00:00:00 2001 +From: Vidya Sagar +Date: Thu, 13 Oct 2022 23:48:12 +0530 +Subject: [PATCH 8/9] UBUNTU: SAUCE: PCI: endpoint: Add core_deinit() callback + support + +BugLink: https://bugs.launchpad.net/bugs/2001557 + +The endpoint function driver should undo the things done in core_init() +and stop hardware access before deinitializing the controller. Add +core_deinit() callback support for function driver to do this cleanup. +This core_deinit() callback should be invoked by the controller driver +before deinitializing the controller. + +Upstream-Status: Pending +Signed-off-by: Vidya Sagar +Signed-off-by: Kartik +Acked-by: Brad Figg +Acked-by: Jacob Martin +Acked-by: Ian May +Signed-off-by: Brad Figg +--- + drivers/pci/endpoint/pci-epc-core.c | 26 ++++++++++++++++++++++++++ + include/linux/pci-epc.h | 1 + + include/linux/pci-epf.h | 2 ++ + 3 files changed, 29 insertions(+) + +diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c +index a7d3a92391a4..94e61baedef7 100644 +--- a/drivers/pci/endpoint/pci-epc-core.c ++++ b/drivers/pci/endpoint/pci-epc-core.c +@@ -757,6 +757,32 @@ void pci_epc_init_notify(struct pci_epc *epc) + } + EXPORT_SYMBOL_GPL(pci_epc_init_notify); + ++/** ++ * pci_epc_deinit_notify() - Notify the EPF device that EPC device's core ++ * deinitialization is scheduled. ++ * @epc: the EPC device whose core deinitialization is scheduled ++ * ++ * Invoke to Notify the EPF device that the EPC device's deinitialization ++ * is scheduled. ++ */ ++void pci_epc_deinit_notify(struct pci_epc *epc) ++{ ++ struct pci_epf *epf; ++ ++ if (!epc || IS_ERR(epc)) ++ return; ++ ++ mutex_lock(&epc->list_lock); ++ list_for_each_entry(epf, &epc->pci_epf, list) { ++ mutex_lock(&epf->lock); ++ if (epf->event_ops->core_deinit) ++ epf->event_ops->core_deinit(epf); ++ mutex_unlock(&epf->lock); ++ } ++ mutex_unlock(&epc->list_lock); ++} ++EXPORT_SYMBOL_GPL(pci_epc_deinit_notify); ++ + /** + * pci_epc_bme_notify() - Notify the EPF device that the EPC device has received + * the BME event from the Root complex +diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h +index 5cb694031072..907f69b51ee0 100644 +--- a/include/linux/pci-epc.h ++++ b/include/linux/pci-epc.h +@@ -205,6 +205,7 @@ int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf, + void pci_epc_linkup(struct pci_epc *epc); + void pci_epc_linkdown(struct pci_epc *epc); + void pci_epc_init_notify(struct pci_epc *epc); ++void pci_epc_deinit_notify(struct pci_epc *epc); + void pci_epc_bme_notify(struct pci_epc *epc); + void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf, + enum pci_epc_interface_type type); +diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h +index 3f44b6aec477..27b2a7f63ceb 100644 +--- a/include/linux/pci-epf.h ++++ b/include/linux/pci-epf.h +@@ -70,12 +70,14 @@ struct pci_epf_ops { + /** + * struct pci_epf_event_ops - Callbacks for capturing the EPC events + * @core_init: Callback for the EPC initialization complete event ++ * @core_deinit: Callback for the EPC deinitialization schedule event + * @link_up: Callback for the EPC link up event + * @link_down: Callback for the EPC link down event + * @bme: Callback for the EPC BME (Bus Master Enable) event + */ + struct pci_epc_event_ops { + int (*core_init)(struct pci_epf *epf); ++ int (*core_deinit)(struct pci_epf *epf); + int (*link_up)(struct pci_epf *epf); + int (*link_down)(struct pci_epf *epf); + int (*bme)(struct pci_epf *epf); +-- +2.25.1 + diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-drm.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-drm.cfg new file mode 100644 index 00000000..29d5839f --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-drm.cfg @@ -0,0 +1,57 @@ +CONFIG_DRM=m +CONFIG_DRM_MIPI_DSI=y +CONFIG_DRM_KMS_HELPER=m +CONFIG_DRM_FBDEV_EMULATION=y +CONFIG_DRM_FBDEV_OVERALLOC=100 +# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set +CONFIG_DRM_DISPLAY_HELPER=m +CONFIG_DRM_DISPLAY_DP_HELPER=y +CONFIG_DRM_DISPLAY_HDMI_HELPER=y +CONFIG_DRM_TTM=m +CONFIG_DRM_EXEC=m +CONFIG_DRM_VRAM_HELPER=m +CONFIG_DRM_TTM_HELPER=m +CONFIG_DRM_GEM_DMA_HELPER=m +CONFIG_DRM_GEM_SHMEM_HELPER=m +CONFIG_DRM_SCHED=m + +CONFIG_DRM_TEGRA=m +# CONFIG_DRM_TEGRA_DEBUG is not set +CONFIG_DRM_TEGRA_STAGING=y +CONFIG_DRM_PANEL=y + +# +# Display Panels +# +CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m +CONFIG_DRM_PANEL_DSI_CM=m +CONFIG_DRM_PANEL_LVDS=m +CONFIG_DRM_PANEL_SIMPLE=m +CONFIG_DRM_PANEL_EDP=m +CONFIG_DRM_PANEL_MANTIX_MLAF057WE51=m +CONFIG_DRM_PANEL_RAYDIUM_RM67191=m +CONFIG_DRM_PANEL_SITRONIX_ST7703=m +CONFIG_DRM_PANEL_TRULY_NT35597_WQXGA=m +# end of Display Panels + +CONFIG_DRM_BRIDGE=y +CONFIG_DRM_PANEL_BRIDGE=y + +# +# Display Interface Bridges +# +CONFIG_DRM_DISPLAY_CONNECTOR=m +CONFIG_DRM_SIMPLE_BRIDGE=m +CONFIG_DRM_DW_HDMI=m +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_I2S_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=m +CONFIG_DRM_DW_MIPI_DSI=m + +CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_SIMPLE=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_PWM=m +CONFIG_BACKLIGHT_LP855X=m +CONFIG_VIDEOMODE_HELPERS=y diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-extra.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-extra.cfg new file mode 100644 index 00000000..08a2a35b --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-extra.cfg @@ -0,0 +1,16 @@ + +CONFIG_I2C_HID_ACPI=m +CONFIG_I2C_HID_OF=m +CONFIG_I2C_HID_CORE=m +CONFIG_HIDRAW=y + +CONFIG_USB_XHCI_PLATFORM=y + +CONFIG_SENSORS_ARM_SCMI=y +CONFIG_SENSORS_ARM_SCPI=y +CONFIG_ARM_SCMI_CPUFREQ=y +CONFIG_ARM_SMMU_V3_PMU=m +CONFIG_ARM_SBSA_WATCHDOG=y +CONFIG_ARM_SP805_WATCHDOG=y +CONFIG_ARM_SMC_WATCHDOG=y +CONFIG_ARM_CCI_PMU=m diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-governors.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-governors.cfg new file mode 100644 index 00000000..64d5599b --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-governors.cfg @@ -0,0 +1,18 @@ +CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_FREQ_GOV_ATTR_SET=y +CONFIG_CPU_FREQ_GOV_COMMON=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=m +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y +CONFIG_CPU_THERMAL=y +CONFIG_CPU_FREQ_THERMAL=y +CONFIG_DEVFREQ_THERMAL=y +CONFIG_DEVFREQ_GOV_PERFORMANCE=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y +CONFIG_DEVFREQ_GOV_USERSPACE=m diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-pcie.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-pcie.cfg new file mode 100644 index 00000000..9f7c0791 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-pcie.cfg @@ -0,0 +1,15 @@ +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_ENDPOINT_CONFIGFS=y +CONFIG_PCI_EPF_TEST=m +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCI_TEGRA=y + +CONFIG_PCIE_TEGRA194=m +CONFIG_PCIE_TEGRA194_HOST=m +CONFIG_PCIE_TEGRA194_EP=m +CONFIG_PCIEAER=y + +CONFIG_NVME_CORE=m +CONFIG_BLK_DEV_NVME=m +CONFIG_NVME_FABRICS=m +CONFIG_NVME_TARGET=m diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-scsi-ufs.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-scsi-ufs.cfg new file mode 100644 index 00000000..0890bf30 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-scsi-ufs.cfg @@ -0,0 +1,2 @@ +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-sound.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-sound.cfg new file mode 100644 index 00000000..083dedc8 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-sound.cfg @@ -0,0 +1,38 @@ +CONFIG_SOUND=y + +CONFIG_SND=y +CONFIG_SND_AUDIO_GRAPH_CARD=m +CONFIG_SND_DMAENGINE_PCM=y +CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_HWDEP=y +CONFIG_SND_PCM=y +CONFIG_SND_SOC=y +CONFIG_SND_SOC_I2C_AND_SPI=y +CONFIG_SND_TIMER=y +CONFIG_SND_USB_AUDIO=y + +CONFIG_SND_HDA=m +CONFIG_SND_HDA_TEGRA=m +CONFIG_SND_HDA_POWER_SAVE_DEFAULT=0 +CONFIG_SND_HDA_CORE=m +CONFIG_SND_HDA_ALIGNED_MMIO=y + +CONFIG_SND_SOC_DMIC=m +CONFIG_SND_SOC_HDMI_CODEC=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SIMPLE_MUX=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_TEGRA=m +CONFIG_SND_SOC_TEGRA210_AHUB=m +CONFIG_SND_SOC_TEGRA210_DMIC=m +CONFIG_SND_SOC_TEGRA210_I2S=m +CONFIG_SND_SOC_TEGRA210_OPE=m +CONFIG_SND_SOC_TEGRA186_ASRC=m +CONFIG_SND_SOC_TEGRA186_DSPK=m +CONFIG_SND_SOC_TEGRA210_ADMAIF=m +CONFIG_SND_SOC_TEGRA210_MVC=m +CONFIG_SND_SOC_TEGRA210_SFC=m +CONFIG_SND_SOC_TEGRA210_AMX=m +CONFIG_SND_SOC_TEGRA210_ADX=m +CONFIG_SND_SOC_TEGRA210_MIXER=m +CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-usb.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-usb.cfg new file mode 100644 index 00000000..b0a478cd --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-usb.cfg @@ -0,0 +1,40 @@ +CONFIG_EXTCON_USB_GPIO=y + +CONFIG_PHY_TEGRA_XUSB=y +CONFIG_PHY_TEGRA194_P2U=m + +CONFIG_TYPEC=m +CONFIG_TYPEC_TCPM=m +CONFIG_TYPEC_TCPCI=m + +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_TEGRA=y + +CONFIG_USB_GADGET=y +CONFIG_USB_TEGRA_XUDC=m +CONFIG_USB_XHCI_TEGRA=y + +CONFIG_USB_LIBCOMPOSITE=m +CONFIG_USB_F_ACM=m +CONFIG_USB_U_SERIAL=m +CONFIG_USB_U_ETHER=m +CONFIG_USB_F_SERIAL=m +CONFIG_USB_F_OBEX=m +CONFIG_USB_F_NCM=m +CONFIG_USB_F_ECM=m +CONFIG_USB_F_EEM=m +CONFIG_USB_F_SUBSET=m +CONFIG_USB_F_RNDIS=m +CONFIG_USB_F_MASS_STORAGE=m +CONFIG_USB_F_FS=m +CONFIG_USB_CONFIGFS=m +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-v4l2.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-v4l2.cfg new file mode 100644 index 00000000..d0e2de77 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-v4l2.cfg @@ -0,0 +1,8 @@ +CONFIG_MEDIA_PLATFORM_DRIVERS=y +CONFIG_V4L2_H264=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_VIDEO_TEGRA_VDE=m +CONFIG_VIDEOBUF2_V4L2=m +CONFIG_VIDEO_V4L2_I2C=y +CONFIG_STAGING_MEDIA=y +CONFIG_VIDEO_MUX=y diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra-virtualization.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra-virtualization.cfg new file mode 100644 index 00000000..4eb54fd1 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra-virtualization.cfg @@ -0,0 +1,24 @@ +CONFIG_GUEST_PERF_EVENTS=y +CONFIG_ARM64_ERRATUM_834220=y +CONFIG_IRQ_BYPASS_MANAGER=y +CONFIG_HAVE_KVM_IRQCHIP=y +CONFIG_HAVE_KVM_IRQ_ROUTING=y +CONFIG_HAVE_KVM_DIRTY_RING=y +CONFIG_HAVE_KVM_DIRTY_RING_ACQ_REL=y +CONFIG_NEED_KVM_DIRTY_RING_WITH_BITMAP=y +CONFIG_KVM_MMIO=y +CONFIG_HAVE_KVM_MSI=y +CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y +CONFIG_KVM_VFIO=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_HAVE_KVM_IRQ_BYPASS=y +CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y +CONFIG_KVM_XFER_TO_GUEST_WORK=y +CONFIG_KVM_GENERIC_HARDWARE_ENABLING=y +CONFIG_VIRTUALIZATION=y +CONFIG_KVM=y +CONFIG_PREEMPT_NOTIFIERS=y +CONFIG_MMU_NOTIFIER=y +CONFIG_INTERVAL_TREE=y +CONFIG_SCHED_INFO=y +CONFIG_PARAVIRT=y diff --git a/recipes-kernel/linux/linux-yocto/tegra/tegra.cfg b/recipes-kernel/linux/linux-yocto/tegra/tegra.cfg new file mode 100644 index 00000000..8ecf787e --- /dev/null +++ b/recipes-kernel/linux/linux-yocto/tegra/tegra.cfg @@ -0,0 +1,84 @@ +CONFIG_ARM64_PMEM=y +# CONFIG_SHADOW_CALL_STACK is not set +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_GPIO=y +CONFIG_SRAM=y + +CONFIG_ARM_DSU_PMU=y +CONFIG_ARM_TEGRA186_CPUFREQ=y +CONFIG_ARM_TEGRA194_CPUFREQ=y + +CONFIG_TEGRA_ACONNECT=m +CONFIG_TEGRA_IVC=y +CONFIG_TEGRA_BPMP=y + +CONFIG_DMA_RESTRICTED_POOL=y +CONFIG_DMA_CMA=y +CONFIG_DMA_NUMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=32 +CONFIG_CMA_SIZE_SEL_MBYTES=y +CONFIG_CMA_ALIGNMENT=8 + +CONFIG_DTC=y +CONFIG_OF=y +CONFIG_OF_FLATTREE=y +CONFIG_OF_EARLY_FLATTREE=y +CONFIG_OF_KOBJ=y +CONFIG_OF_DYNAMIC=y +CONFIG_OF_ADDRESS=y +CONFIG_OF_IRQ=y +CONFIG_OF_RESERVED_MEM=y +CONFIG_OF_RESOLVE=y +CONFIG_OF_OVERLAY=y +CONFIG_OF_NUMA=y + +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_INA3221=m +CONFIG_SERIAL_TEGRA=y +CONFIG_SERIAL_TEGRA_TCU=y +CONFIG_SERIAL_TEGRA_TCU_CONSOLE=y +CONFIG_I2C_TEGRA=y +CONFIG_I2C_TEGRA_BPMP=y +CONFIG_SPI_TEGRA114=m +CONFIG_PINCTRL_TEGRA=y +CONFIG_PINCTRL_TEGRA124=y +CONFIG_PINCTRL_TEGRA210=y +CONFIG_PINCTRL_TEGRA194=y +CONFIG_PINCTRL_TEGRA234=y +CONFIG_GPIO_TEGRA186=y +CONFIG_TEGRA_SOCTHERM=m +CONFIG_TEGRA_BPMP_THERMAL=m + +CONFIG_TEGRA_HOST1X_CONTEXT_BUS=y +CONFIG_TEGRA_HOST1X=m +CONFIG_TEGRA_HOST1X_FIREWALL=y + +CONFIG_MMC_SDHCI_TEGRA=y +CONFIG_RTC_DRV_TEGRA=y +CONFIG_DMA_VIRTUAL_CHANNELS=y +CONFIG_TEGRA186_GPC_DMA=y +CONFIG_TEGRA20_APB_DMA=y +CONFIG_TEGRA210_ADMA=m +CONFIG_STAGING=y +CONFIG_CLK_TEGRA_BPMP=y +CONFIG_TEGRA_CLK_DFLL=y +CONFIG_TEGRA_TIMER=y +CONFIG_TEGRA186_TIMER=y +CONFIG_TEGRA_HSP_MBOX=y +CONFIG_ARCH_TEGRA_132_SOC=y +CONFIG_ARCH_TEGRA_210_SOC=y +CONFIG_ARCH_TEGRA_186_SOC=y +CONFIG_ARCH_TEGRA_194_SOC=y +CONFIG_ARCH_TEGRA_234_SOC=y +CONFIG_SOC_TEGRA_FLOWCTRL=y +CONFIG_SOC_TEGRA_PMC=y +CONFIG_SOC_TEGRA_POWERGATE_BPMP=y +CONFIG_SOC_TEGRA_CBB=y +CONFIG_RESET_TEGRA_BPMP=y +CONFIG_HTE=y +CONFIG_HTE_TEGRA194=y +CONFIG_HTE_TEGRA194_TEST=m +CONFIG_CONFIGFS_FS=y + +CONFIG_AQUANTIA_PHY=y +CONFIG_DWMAC_TEGRA=m diff --git a/recipes-kernel/linux/linux-yocto_6.6.bbappend b/recipes-kernel/linux/linux-yocto_6.6.bbappend new file mode 100644 index 00000000..8dc05559 --- /dev/null +++ b/recipes-kernel/linux/linux-yocto_6.6.bbappend @@ -0,0 +1,143 @@ +FILESEXTRAPATHS:prepend:tegra := "${THISDIR}/${PN}:" + +TEGRA_UEFI_SIGNING_CLASS ??= "tegra-uefi-signing" + +INHERIT_DEPS = "" +INHERIT_DEPS:tegra = "${TEGRA_UEFI_SIGNING_CLASS}" +inherit ${INHERIT_DEPS} + +SRC_URI:append:tegra = " \ + file://0001-memory-tegra-Add-Tegra234-clients-for-RCE-and-VI.patch \ + file://0002-hwmon-ina3221-Add-support-for-channel-summation-disa.patch \ + file://0003-cpufreq-tegra194-save-CPU-data-to-avoid-repeated-SMP.patch \ + file://0004-cpufreq-tegra194-use-refclk-delta-based-loop-instead.patch \ + file://0005-cpufreq-tegra194-remove-redundant-AND-with-cpu_onlin.patch \ + file://0006-fbdev-simplefb-Support-memory-region-property.patch \ + file://0007-fbdev-simplefb-Add-support-for-generic-power-domains.patch \ + file://0008-UBUNTU-SAUCE-PCI-endpoint-Add-core_deinit-callback-s.patch \ + file://tegra.cfg \ + file://tegra-drm.cfg \ + file://tegra-governors.cfg \ + file://tegra-pcie.cfg \ + file://tegra-scsi-ufs.cfg \ + file://tegra-sound.cfg \ + file://tegra-usb.cfg \ + file://tegra-v4l2.cfg \ + file://tegra-virtualization.cfg \ + file://rtw8822ce-wifi.cfg \ +" + +COMPATIBLE_MACHINE:tegra = "(tegra)" +KMACHINE:tegra = "genericarm64" + +KERNEL_FEATURES:append:tegra = " \ + features/bluetooth/bluetooth.scc \ + features/bluetooth/bluetooth-usb.scc \ + features/i2c/i2c.scc \ + features/input/touchscreen.scc \ + features/media/media.scc \ + features/media/media-platform.scc \ + features/media/media-usb-webcams.scc \ + features/usb/serial.scc \ + features/usb/usb-raw-gadget.scc \ + features/usb/xhci-hcd.scc \ +" + +# All of our device trees are out-of-tree +KERNEL_DEVICETREE:forcevariable:tegra = "" + +sign_kernel_image() { + tegra_uefi_sbsign "$1" + shift + while [ $# -gt 0 ]; do + tegra_uefi_attach_sign "$1" + shift + done +} + +SIGNING_DEPS ?= "" +SIGNING_DEPS:tegra ?= "${TEGRA_UEFI_SIGNING_TASKDEPS}" + +do_sign_kernel() { + # do nothing by default +} +do_sign_kernel:tegra() { + sign_kernel_image ${KERNEL_OUTPUT_DIR}/${KERNEL_IMAGETYPE} +} +do_sign_kernel[dirs] = "${B}" +do_sign_kernel[depends] += "${SIGNING_DEPS}" + +addtask sign_kernel after do_compile before do_install + +sign_bootimg() { + tegra_uefi_attach_sign "$1" +} + +bootimg_from_bundled_initramfs() { + if [ ! -z "${INITRAMFS_IMAGE}" -a "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then + rm -f ${WORKDIR}/initrd + touch ${WORKDIR}/initrd + for imageType in ${KERNEL_IMAGETYPES} ; do + if [ "$imageType" = "fitImage" ] ; then + continue + fi + initramfs_base_name=${imageType}-${INITRAMFS_NAME} + initramfs_symlink_name=${imageType}-${INITRAMFS_LINK_NAME} + ${STAGING_BINDIR_NATIVE}/tegra-flash/mkbootimg \ + --kernel $deployDir/${initramfs_base_name}.bin \ + --ramdisk ${WORKDIR}/initrd \ + --cmdline "${KERNEL_ARGS}" \ + --output $deployDir/${initramfs_base_name}.cboot + sign_bootimg $deployDir/${initramfs_base_name}.cboot + chmod 0644 $deployDir/${initramfs_base_name}.cboot + ln -sf ${initramfs_base_name}.cboot $deployDir/${initramfs_symlink_name}.cboot + done + elif [ -z "${INITRAMFS_IMAGE}" ]; then + rm -f ${WORKDIR}/initrd + touch ${WORKDIR}/initrd + for imageType in ${KERNEL_IMAGETYPES} ; do + if [ "$imageType" = "fitImage" ] ; then + continue + fi + baseName=$imageType-${KERNEL_IMAGE_NAME} + ${STAGING_BINDIR_NATIVE}/tegra-flash/mkbootimg \ + --kernel $deployDir/${baseName}.bin \ + --ramdisk ${WORKDIR}/initrd \ + --cmdline "${KERNEL_ARGS}" \ + --output $deployDir/${baseName}.cboot + sign_bootimg $deployDir/${baseName}.cboot + chmod 0644 $deployDir/${baseName}.cboot + ln -sf ${baseName}.cboot $deployDir/$imageType-${KERNEL_IMAGE_LINK_NAME}.cboot + ln -sf ${baseName}.cboot $deployDir/$imageType.cboot + done + fi +} +do_deploy:append:tegra() { + bootimg_from_bundled_initramfs +} + +DEPLOY_DEPS ?= "" +DEPLOY_DEPS:tegra ?= "tegra-flashtools-native:do_populate_sysroot ${TEGRA_UEFI_SIGNING_TASKDEPS}" +do_deploy[depends] += "${DEPLOY_DEPS}" + +# RRECOMMENDS:${KERNEL_PACKAGE_NAME}-base:tegra = "" + +# kernel.bbclass automatically adds a dependency on the intramfs image +# even if INITRAMFS_IMAGE_BUNDLE is disabled. This creates a circular +# dependency for tegra builds, where we need to combine initramfs (as an +# initrd) and kernel artifacts into a bootable image, so break that +# dependency here. +python () { + mach_overrides = d.getVar('MACHINEOVERRIDES') + mach_overrides = frozenset(mach_overrides.split(':')) + + if 'tegra' in mach_overrides and d.getVar('INITRAMFS_IMAGE') and not bb.utils.to_boolean(d.getVar('INITRAMFS_IMAGE_BUNDLE')): + flags = d.getVarFlag('do_bundle_initramfs', 'depends', False).split() + try: + i = flags.index('${INITRAMFS_IMAGE}:do_image_complete') + del flags[i] + d.setVarFlag('do_bundle_initramfs', 'depends', ' '.join(flags)) + except ValueError: + bb.warn('did not find it in %s' % ','.join(flags)) + pass +}