summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-11-20 18:45:03 -0800
committerJakub Kicinski <kuba@kernel.org>2020-11-20 18:45:03 -0800
commit0ee6de264b8305d2c55f32a80e00c054736b10f9 (patch)
tree8635737169b7c18d4f9aced6422f33fb4313a1de
parent0a12ad5929556195fbdf1c58a14ec8e5b01b006c (diff)
parent91d02f9551501fe63e2031d7821d0e7fd4ea5a21 (diff)
Merge branch 'net-ipa-platform-specific-clock-and-interconnect-rates'
Alex Elder says: ==================== net: ipa: platform-specific clock and interconnect rates This series changes the way the IPA core clock rate and the bandwidth parameters for interconnects are specified. Previously these were specified with hard-wired constants, with the same values used for the SDM845 and SC7180 platforms. Now these parameters are recorded in platform-specific configuration data. For the SC7180 this means we use an all-new core clock rate and interconnect parameters. Additionally, while developing this I learned that the average bandwidth setting for two of the interconnects is ignored (on both platforms). Zero is now used explicitly as that unused bandwidth value. This means the SDM845 bandwidth settings are also changed by this series. ==================== Link: https://lore.kernel.org/r/20201119224041.16066-1-elder@linaro.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ipa/ipa_clock.c47
-rw-r--r--drivers/net/ipa/ipa_clock.h5
-rw-r--r--drivers/net/ipa/ipa_data-sc7180.c21
-rw-r--r--drivers/net/ipa/ipa_data-sdm845.c21
-rw-r--r--drivers/net/ipa/ipa_data.h31
-rw-r--r--drivers/net/ipa/ipa_main.c21
6 files changed, 112 insertions, 34 deletions
diff --git a/drivers/net/ipa/ipa_clock.c b/drivers/net/ipa/ipa_clock.c
index a2c0fde05819..9dcf16f399b7 100644
--- a/drivers/net/ipa/ipa_clock.c
+++ b/drivers/net/ipa/ipa_clock.c
@@ -13,6 +13,7 @@
#include "ipa.h"
#include "ipa_clock.h"
#include "ipa_modem.h"
+#include "ipa_data.h"
/**
* DOC: IPA Clocking
@@ -29,18 +30,6 @@
* An IPA clock reference must be held for any access to IPA hardware.
*/
-#define IPA_CORE_CLOCK_RATE (75UL * 1000 * 1000) /* Hz */
-
-/* Interconnect path bandwidths (each times 1000 bytes per second) */
-#define IPA_MEMORY_AVG (80 * 1000) /* 80 MBps */
-#define IPA_MEMORY_PEAK (600 * 1000)
-
-#define IPA_IMEM_AVG (80 * 1000)
-#define IPA_IMEM_PEAK (350 * 1000)
-
-#define IPA_CONFIG_AVG (40 * 1000)
-#define IPA_CONFIG_PEAK (40 * 1000)
-
/**
* struct ipa_clock - IPA clocking information
* @count: Clocking reference count
@@ -49,6 +38,7 @@
* @memory_path: Memory interconnect
* @imem_path: Internal memory interconnect
* @config_path: Configuration space interconnect
+ * @interconnect_data: Interconnect configuration data
*/
struct ipa_clock {
refcount_t count;
@@ -57,6 +47,7 @@ struct ipa_clock {
struct icc_path *memory_path;
struct icc_path *imem_path;
struct icc_path *config_path;
+ const struct ipa_interconnect_data *interconnect_data;
};
static struct icc_path *
@@ -113,18 +104,25 @@ static void ipa_interconnect_exit(struct ipa_clock *clock)
/* Currently we only use one bandwidth level, so just "enable" interconnects */
static int ipa_interconnect_enable(struct ipa *ipa)
{
+ const struct ipa_interconnect_data *data;
struct ipa_clock *clock = ipa->clock;
int ret;
- ret = icc_set_bw(clock->memory_path, IPA_MEMORY_AVG, IPA_MEMORY_PEAK);
+ data = &clock->interconnect_data[IPA_INTERCONNECT_MEMORY];
+ ret = icc_set_bw(clock->memory_path, data->average_rate,
+ data->peak_rate);
if (ret)
return ret;
- ret = icc_set_bw(clock->imem_path, IPA_IMEM_AVG, IPA_IMEM_PEAK);
+ data = &clock->interconnect_data[IPA_INTERCONNECT_IMEM];
+ ret = icc_set_bw(clock->memory_path, data->average_rate,
+ data->peak_rate);
if (ret)
goto err_memory_path_disable;
- ret = icc_set_bw(clock->config_path, IPA_CONFIG_AVG, IPA_CONFIG_PEAK);
+ data = &clock->interconnect_data[IPA_INTERCONNECT_CONFIG];
+ ret = icc_set_bw(clock->memory_path, data->average_rate,
+ data->peak_rate);
if (ret)
goto err_imem_path_disable;
@@ -141,6 +139,7 @@ err_memory_path_disable:
/* To disable an interconnect, we just its bandwidth to 0 */
static int ipa_interconnect_disable(struct ipa *ipa)
{
+ const struct ipa_interconnect_data *data;
struct ipa_clock *clock = ipa->clock;
int ret;
@@ -159,9 +158,13 @@ static int ipa_interconnect_disable(struct ipa *ipa)
return 0;
err_imem_path_reenable:
- (void)icc_set_bw(clock->imem_path, IPA_IMEM_AVG, IPA_IMEM_PEAK);
+ data = &clock->interconnect_data[IPA_INTERCONNECT_IMEM];
+ (void)icc_set_bw(clock->imem_path, data->average_rate,
+ data->peak_rate);
err_memory_path_reenable:
- (void)icc_set_bw(clock->memory_path, IPA_MEMORY_AVG, IPA_MEMORY_PEAK);
+ data = &clock->interconnect_data[IPA_INTERCONNECT_MEMORY];
+ (void)icc_set_bw(clock->memory_path, data->average_rate,
+ data->peak_rate);
return ret;
}
@@ -257,7 +260,8 @@ u32 ipa_clock_rate(struct ipa *ipa)
}
/* Initialize IPA clocking */
-struct ipa_clock *ipa_clock_init(struct device *dev)
+struct ipa_clock *
+ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)
{
struct ipa_clock *clock;
struct clk *clk;
@@ -269,10 +273,10 @@ struct ipa_clock *ipa_clock_init(struct device *dev)
return ERR_CAST(clk);
}
- ret = clk_set_rate(clk, IPA_CORE_CLOCK_RATE);
+ ret = clk_set_rate(clk, data->core_clock_rate);
if (ret) {
- dev_err(dev, "error %d setting core clock rate to %lu\n",
- ret, IPA_CORE_CLOCK_RATE);
+ dev_err(dev, "error %d setting core clock rate to %u\n",
+ ret, data->core_clock_rate);
goto err_clk_put;
}
@@ -282,6 +286,7 @@ struct ipa_clock *ipa_clock_init(struct device *dev)
goto err_clk_put;
}
clock->core = clk;
+ clock->interconnect_data = data->interconnect;
ret = ipa_interconnect_init(clock, dev);
if (ret)
diff --git a/drivers/net/ipa/ipa_clock.h b/drivers/net/ipa/ipa_clock.h
index 1d70f1de3875..1fe634760e59 100644
--- a/drivers/net/ipa/ipa_clock.h
+++ b/drivers/net/ipa/ipa_clock.h
@@ -9,6 +9,7 @@
struct device;
struct ipa;
+struct ipa_clock_data;
/**
* ipa_clock_rate() - Return the current IPA core clock rate
@@ -21,10 +22,12 @@ u32 ipa_clock_rate(struct ipa *ipa);
/**
* ipa_clock_init() - Initialize IPA clocking
* @dev: IPA device
+ * @data: Clock configuration data
*
* Return: A pointer to an ipa_clock structure, or a pointer-coded error
*/
-struct ipa_clock *ipa_clock_init(struct device *dev);
+struct ipa_clock *ipa_clock_init(struct device *dev,
+ const struct ipa_clock_data *data);
/**
* ipa_clock_exit() - Inverse of ipa_clock_init()
diff --git a/drivers/net/ipa/ipa_data-sc7180.c b/drivers/net/ipa/ipa_data-sc7180.c
index 37dada4da680..5cc0ed77edb9 100644
--- a/drivers/net/ipa/ipa_data-sc7180.c
+++ b/drivers/net/ipa/ipa_data-sc7180.c
@@ -309,6 +309,26 @@ static struct ipa_mem_data ipa_mem_data = {
.smem_size = 0x00002000,
};
+static struct ipa_clock_data ipa_clock_data = {
+ .core_clock_rate = 100 * 1000 * 1000, /* Hz */
+ /* Interconnect rates are in 1000 byte/second units */
+ .interconnect = {
+ [IPA_INTERCONNECT_MEMORY] = {
+ .peak_rate = 465000, /* 465 MBps */
+ .average_rate = 80000, /* 80 MBps */
+ },
+ /* Average rate is unused for the next two interconnects */
+ [IPA_INTERCONNECT_IMEM] = {
+ .peak_rate = 68570, /* 68.570 MBps */
+ .average_rate = 0, /* unused */
+ },
+ [IPA_INTERCONNECT_CONFIG] = {
+ .peak_rate = 30000, /* 30 MBps */
+ .average_rate = 0, /* unused */
+ },
+ },
+};
+
/* Configuration data for the SC7180 SoC. */
const struct ipa_data ipa_data_sc7180 = {
.version = IPA_VERSION_4_2,
@@ -316,4 +336,5 @@ const struct ipa_data ipa_data_sc7180 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
+ .clock_data = &ipa_clock_data,
};
diff --git a/drivers/net/ipa/ipa_data-sdm845.c b/drivers/net/ipa/ipa_data-sdm845.c
index bd92b619e7fe..f8fee8d3ca42 100644
--- a/drivers/net/ipa/ipa_data-sdm845.c
+++ b/drivers/net/ipa/ipa_data-sdm845.c
@@ -329,6 +329,26 @@ static struct ipa_mem_data ipa_mem_data = {
.smem_size = 0x00002000,
};
+static struct ipa_clock_data ipa_clock_data = {
+ .core_clock_rate = 75 * 1000 * 1000, /* Hz */
+ /* Interconnect rates are in 1000 byte/second units */
+ .interconnect = {
+ [IPA_INTERCONNECT_MEMORY] = {
+ .peak_rate = 600000, /* 600 MBps */
+ .average_rate = 80000, /* 80 MBps */
+ },
+ /* Average rate is unused for the next two interconnects */
+ [IPA_INTERCONNECT_IMEM] = {
+ .peak_rate = 350000, /* 350 MBps */
+ .average_rate = 0, /* unused */
+ },
+ [IPA_INTERCONNECT_CONFIG] = {
+ .peak_rate = 40000, /* 40 MBps */
+ .average_rate = 0, /* unused */
+ },
+ },
+};
+
/* Configuration data for the SDM845 SoC. */
const struct ipa_data ipa_data_sdm845 = {
.version = IPA_VERSION_3_5_1,
@@ -336,4 +356,5 @@ const struct ipa_data ipa_data_sdm845 = {
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
+ .clock_data = &ipa_clock_data,
};
diff --git a/drivers/net/ipa/ipa_data.h b/drivers/net/ipa/ipa_data.h
index 83c4b78373ef..0ed5ffe2b8da 100644
--- a/drivers/net/ipa/ipa_data.h
+++ b/drivers/net/ipa/ipa_data.h
@@ -241,7 +241,7 @@ struct ipa_resource_data {
};
/**
- * struct ipa_mem - description of IPA memory regions
+ * struct ipa_mem_data - description of IPA memory regions
* @local_count: number of regions defined in the local[] array
* @local: array of IPA-local memory region descriptors
* @imem_addr: physical address of IPA region within IMEM
@@ -258,6 +258,34 @@ struct ipa_mem_data {
u32 smem_size;
};
+/** enum ipa_interconnect_id - IPA interconnect identifier */
+enum ipa_interconnect_id {
+ IPA_INTERCONNECT_MEMORY,
+ IPA_INTERCONNECT_IMEM,
+ IPA_INTERCONNECT_CONFIG,
+ IPA_INTERCONNECT_COUNT, /* Last; not an interconnect */
+};
+
+/**
+ * struct ipa_interconnect_data - description of IPA interconnect rates
+ * @peak_rate: Peak interconnect bandwidth (in 1000 byte/sec units)
+ * @average_rate: Average interconnect bandwidth (in 1000 byte/sec units)
+ */
+struct ipa_interconnect_data {
+ u32 peak_rate;
+ u32 average_rate;
+};
+
+/**
+ * struct ipa_clock_data - description of IPA clock and interconnect rates
+ * @core_clock_rate: Core clock rate (Hz)
+ * @interconnect: Array of interconnect bandwidth parameters
+ */
+struct ipa_clock_data {
+ u32 core_clock_rate;
+ struct ipa_interconnect_data interconnect[IPA_INTERCONNECT_COUNT];
+};
+
/**
* struct ipa_data - combined IPA/GSI configuration data
* @version: IPA hardware version
@@ -273,6 +301,7 @@ struct ipa_data {
const struct ipa_gsi_endpoint_data *endpoint_data;
const struct ipa_resource_data *resource_data;
const struct ipa_mem_data *mem_data;
+ const struct ipa_clock_data *clock_data;
};
extern const struct ipa_data ipa_data_sdm845;
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 3fb9c5d90b70..468ab1acc20e 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -728,6 +728,14 @@ static int ipa_probe(struct platform_device *pdev)
ipa_validate_build();
+ /* Get configuration data early; needed for clock initialization */
+ data = of_device_get_match_data(dev);
+ if (!data) {
+ /* This is really IPA_VALIDATE (should never happen) */
+ dev_err(dev, "matched hardware not supported\n");
+ return -ENODEV;
+ }
+
/* If we need Trust Zone, make sure it's available */
modem_init = of_property_read_bool(dev->of_node, "modem-init");
if (!modem_init)
@@ -748,22 +756,13 @@ static int ipa_probe(struct platform_device *pdev)
/* The clock and interconnects might not be ready when we're
* probed, so might return -EPROBE_DEFER.
*/
- clock = ipa_clock_init(dev);
+ clock = ipa_clock_init(dev, data->clock_data);
if (IS_ERR(clock)) {
ret = PTR_ERR(clock);
goto err_rproc_put;
}
- /* No more EPROBE_DEFER. Get our configuration data */
- data = of_device_get_match_data(dev);
- if (!data) {
- /* This is really IPA_VALIDATE (should never happen) */
- dev_err(dev, "matched hardware not supported\n");
- ret = -ENOTSUPP;
- goto err_clock_exit;
- }
-
- /* Allocate and initialize the IPA structure */
+ /* No more EPROBE_DEFER. Allocate and initialize the IPA structure */
ipa = kzalloc(sizeof(*ipa), GFP_KERNEL);
if (!ipa) {
ret = -ENOMEM;