Commit 3cb5b035 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'memory-controller-drv-6.6' of...

Merge tag 'memory-controller-drv-6.6' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into soc/drivers

Memory controller drivers for v6.6

1. Tegra:
 - Extend support for Tegra234 SoC Memory Controllers with DRM and GPU
   clients.
 - Tegra186: Skip MRQ DVFS where it is not supported and do not fail
   probe.
2. Wide cleanup of DT includes.
3. Devicetree bindings:
 - Reference common peripheral (client) properties in Ingenic NEMC and
   TI GPMC.
 - Convert Davicom DM9000 to DT schema.

* tag 'memory-controller-drv-6.6' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
  memory: tegra: add MC client for Tegra234 GPU
  dt-bindings: net: davicom,dm9000: convert to DT schema
  dt-bindings: memory-controllers: reference TI GPMC peripheral properties
  dt-bindings: memory-controllers: ingenic,nemc: reference peripheral properties
  memory: Explicitly include correct DT includes
  memory: tegra: Prefer octal over symbolic permissions
  memory: tegra: add check if MRQ_EMC_DVFS_LATENCY is supported
  memory: tegra: Add clients used by DRM in Tegra234
  memory: tegra: sort tegra234_mc_clients table as per register offsets
  memory: tegra: make icc_set_bw return zero if BWMGR not supported
  memory: tegra: Add dummy implementation on Tegra194

Link: https://lore.kernel.org/r/20230814120052.27485-1-krzysztof.kozlowski@linaro.orgSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 93e0acae 35bd78cf
......@@ -39,6 +39,7 @@ properties:
patternProperties:
".*@[0-9]+$":
type: object
$ref: mc-peripheral-props.yaml#
required:
- compatible
......
......@@ -34,6 +34,8 @@ required:
# The controller specific properties go here.
allOf:
- $ref: st,stm32-fmc2-ebi-props.yaml#
- $ref: ingenic,nemc-peripherals.yaml#
- $ref: intel,ixp4xx-expansion-peripheral-props.yaml#
- $ref: ti,gpmc-child.yaml#
additionalProperties: true
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/davicom,dm9000.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Davicom DM9000 Fast Ethernet Controller
maintainers:
- Paul Cercueil <paul@crapouillou.net>
properties:
compatible:
const: davicom,dm9000
reg:
items:
- description: Address registers
- description: Data registers
interrupts:
maxItems: 1
davicom,no-eeprom:
type: boolean
description: Configuration EEPROM is not available
davicom,ext-phy:
type: boolean
description: Use external PHY
reset-gpios:
maxItems: 1
vcc-supply: true
required:
- compatible
- reg
- interrupts
allOf:
- $ref: /schemas/memory-controllers/mc-peripheral-props.yaml#
- $ref: /schemas/net/ethernet-controller.yaml#
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
ethernet@a8000000 {
compatible = "davicom,dm9000";
reg = <0xa8000000 0x2>, <0xa8000002 0x2>;
interrupt-parent = <&gph1>;
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
local-mac-address = [00 00 de ad be ef];
davicom,no-eeprom;
};
Davicom DM9000 Fast Ethernet controller
Required properties:
- compatible = "davicom,dm9000";
- reg : physical addresses and sizes of registers, must contain 2 entries:
first entry : address register,
second entry : data register.
- interrupts : interrupt specifier specific to interrupt controller
Optional properties:
- davicom,no-eeprom : Configuration EEPROM is not available
- davicom,ext-phy : Use external PHY
- reset-gpios : phandle of gpio that will be used to reset chip during probe
- vcc-supply : phandle of regulator that will be used to enable power to chip
Example:
ethernet@18000000 {
compatible = "davicom,dm9000";
reg = <0x18000000 0x2 0x18000004 0x2>;
interrupt-parent = <&gpn>;
interrupts = <7 4>;
local-mac-address = [00 00 de ad be ef];
davicom,no-eeprom;
reset-gpios = <&gpf 12 GPIO_ACTIVE_LOW>;
vcc-supply = <&eth0_power>;
};
......@@ -32,8 +32,7 @@
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#define DRVNAME "brcmstb-dpfe"
......
......@@ -10,7 +10,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
......
......@@ -15,7 +15,7 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/fsl_ifc.h>
#include <linux/irqdomain.h>
......
......@@ -12,7 +12,6 @@
#include <linux/math64.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
......
......@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/amba/bus.h>
......
......@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
......
......@@ -13,7 +13,7 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_opp.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
......
......@@ -7,8 +7,10 @@
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
......
......@@ -11,7 +11,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sort.h>
......@@ -755,6 +755,43 @@ const char *const tegra_mc_error_names[8] = {
[6] = "SMMU translation error",
};
struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data)
{
struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
struct icc_node *node;
list_for_each_entry(node, &mc->provider.nodes, node_list) {
if (node->id == spec->args[0])
return node;
}
/*
* If a client driver calls devm_of_icc_get() before the MC driver
* is probed, then return EPROBE_DEFER to the client driver.
*/
return ERR_PTR(-EPROBE_DEFER);
}
static int tegra_mc_icc_get(struct icc_node *node, u32 *average, u32 *peak)
{
*average = 0;
*peak = 0;
return 0;
}
static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
{
return 0;
}
const struct tegra_mc_icc_ops tegra_mc_icc_ops = {
.xlate = tegra_mc_icc_xlate,
.aggregate = icc_std_aggregate,
.get_bw = tegra_mc_icc_get,
.set = tegra_mc_icc_set,
};
/*
* Memory Controller (MC) has few Memory Clients that are issuing memory
* bandwidth allocation requests to the MC interconnect provider. The MC
......
......@@ -4,7 +4,7 @@
*/
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <dt-bindings/memory/tegra124-mc.h>
......
......@@ -155,6 +155,73 @@ DEFINE_DEBUGFS_ATTRIBUTE(tegra186_emc_debug_max_rate_fops,
tegra186_emc_debug_max_rate_get,
tegra186_emc_debug_max_rate_set, "%llu\n");
static int tegra186_emc_get_emc_dvfs_latency(struct tegra186_emc *emc)
{
struct mrq_emc_dvfs_latency_response response;
struct tegra_bpmp_message msg;
unsigned int i;
int err;
memset(&msg, 0, sizeof(msg));
msg.mrq = MRQ_EMC_DVFS_LATENCY;
msg.tx.data = NULL;
msg.tx.size = 0;
msg.rx.data = &response;
msg.rx.size = sizeof(response);
err = tegra_bpmp_transfer(emc->bpmp, &msg);
if (err < 0) {
dev_err(emc->dev, "failed to EMC DVFS pairs: %d\n", err);
return err;
}
if (msg.rx.ret < 0) {
dev_err(emc->dev, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg.rx.ret);
return -EINVAL;
}
emc->debugfs.min_rate = ULONG_MAX;
emc->debugfs.max_rate = 0;
emc->num_dvfs = response.num_pairs;
emc->dvfs = devm_kmalloc_array(emc->dev, emc->num_dvfs, sizeof(*emc->dvfs), GFP_KERNEL);
if (!emc->dvfs)
return -ENOMEM;
dev_dbg(emc->dev, "%u DVFS pairs:\n", emc->num_dvfs);
for (i = 0; i < emc->num_dvfs; i++) {
emc->dvfs[i].rate = response.pairs[i].freq * 1000;
emc->dvfs[i].latency = response.pairs[i].latency;
if (emc->dvfs[i].rate < emc->debugfs.min_rate)
emc->debugfs.min_rate = emc->dvfs[i].rate;
if (emc->dvfs[i].rate > emc->debugfs.max_rate)
emc->debugfs.max_rate = emc->dvfs[i].rate;
dev_dbg(emc->dev, " %2u: %lu Hz -> %lu us\n", i,
emc->dvfs[i].rate, emc->dvfs[i].latency);
}
err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate, emc->debugfs.max_rate);
if (err < 0) {
dev_err(emc->dev, "failed to set rate range [%lu-%lu] for %pC\n",
emc->debugfs.min_rate, emc->debugfs.max_rate, emc->clk);
return err;
}
emc->debugfs.root = debugfs_create_dir("emc", NULL);
debugfs_create_file("available_rates", 0444, emc->debugfs.root, emc,
&tegra186_emc_debug_available_rates_fops);
debugfs_create_file("min_rate", 0644, emc->debugfs.root, emc,
&tegra186_emc_debug_min_rate_fops);
debugfs_create_file("max_rate", 0644, emc->debugfs.root, emc,
&tegra186_emc_debug_max_rate_fops);
return 0;
}
/*
* tegra_emc_icc_set_bw() - Set BW api for EMC provider
* @src: ICC node for External Memory Controller (EMC)
......@@ -251,10 +318,7 @@ static int tegra_emc_interconnect_init(struct tegra186_emc *emc)
static int tegra186_emc_probe(struct platform_device *pdev)
{
struct tegra_mc *mc = dev_get_drvdata(pdev->dev.parent);
struct mrq_emc_dvfs_latency_response response;
struct tegra_bpmp_message msg;
struct tegra186_emc *emc;
unsigned int i;
int err;
emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
......@@ -275,70 +339,12 @@ static int tegra186_emc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, emc);
emc->dev = &pdev->dev;
memset(&msg, 0, sizeof(msg));
msg.mrq = MRQ_EMC_DVFS_LATENCY;
msg.tx.data = NULL;
msg.tx.size = 0;
msg.rx.data = &response;
msg.rx.size = sizeof(response);
err = tegra_bpmp_transfer(emc->bpmp, &msg);
if (err < 0) {
dev_err(&pdev->dev, "failed to EMC DVFS pairs: %d\n", err);
goto put_bpmp;
}
if (msg.rx.ret < 0) {
err = -EINVAL;
dev_err(&pdev->dev, "EMC DVFS MRQ failed: %d (BPMP error code)\n", msg.rx.ret);
goto put_bpmp;
}
emc->debugfs.min_rate = ULONG_MAX;
emc->debugfs.max_rate = 0;
emc->num_dvfs = response.num_pairs;
emc->dvfs = devm_kmalloc_array(&pdev->dev, emc->num_dvfs,
sizeof(*emc->dvfs), GFP_KERNEL);
if (!emc->dvfs) {
err = -ENOMEM;
goto put_bpmp;
}
dev_dbg(&pdev->dev, "%u DVFS pairs:\n", emc->num_dvfs);
for (i = 0; i < emc->num_dvfs; i++) {
emc->dvfs[i].rate = response.pairs[i].freq * 1000;
emc->dvfs[i].latency = response.pairs[i].latency;
if (emc->dvfs[i].rate < emc->debugfs.min_rate)
emc->debugfs.min_rate = emc->dvfs[i].rate;
if (emc->dvfs[i].rate > emc->debugfs.max_rate)
emc->debugfs.max_rate = emc->dvfs[i].rate;
dev_dbg(&pdev->dev, " %2u: %lu Hz -> %lu us\n", i,
emc->dvfs[i].rate, emc->dvfs[i].latency);
}
err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,
emc->debugfs.max_rate);
if (err < 0) {
dev_err(&pdev->dev,
"failed to set rate range [%lu-%lu] for %pC\n",
emc->debugfs.min_rate, emc->debugfs.max_rate,
emc->clk);
goto put_bpmp;
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_EMC_DVFS_LATENCY)) {
err = tegra186_emc_get_emc_dvfs_latency(emc);
if (err)
goto put_bpmp;
}
emc->debugfs.root = debugfs_create_dir("emc", NULL);
debugfs_create_file("available_rates", S_IRUGO, emc->debugfs.root,
emc, &tegra186_emc_debug_available_rates_fops);
debugfs_create_file("min_rate", S_IRUGO | S_IWUSR, emc->debugfs.root,
emc, &tegra186_emc_debug_min_rate_fops);
debugfs_create_file("max_rate", S_IRUGO | S_IWUSR, emc->debugfs.root,
emc, &tegra186_emc_debug_max_rate_fops);
if (mc && mc->soc->icc_ops) {
if (tegra_bpmp_mrq_is_supported(emc->bpmp, MRQ_BWMGR_INT)) {
mc->bwmgr_mrq_supported = true;
......
......@@ -7,7 +7,8 @@
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <soc/tegra/mc.h>
......
......@@ -1355,6 +1355,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
.has_addr_hi_reg = true,
.ops = &tegra186_mc_ops,
.icc_ops = &tegra_mc_icc_ops,
.ch_intmask = 0x00000f00,
.global_intstatus_channel_shift = 8,
};
......@@ -5,8 +5,9 @@
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/string.h>
......
......@@ -9,10 +9,10 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/thermal.h>
#include <soc/tegra/fuse.h>
......
This diff is collapsed.
......@@ -22,7 +22,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_platform.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/slab.h>
......
......@@ -3,8 +3,8 @@
* Copyright (C) 2014 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <dt-bindings/memory/tegra30-mc.h>
......
......@@ -175,6 +175,9 @@ struct tegra_mc_icc_ops {
int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
};
struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data);
extern const struct tegra_mc_icc_ops tegra_mc_icc_ops;
struct tegra_mc_ops {
/*
* @probe: Callback to set up SoC-specific bits of the memory controller. This is called
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment