Commit 0ee6de26 authored by Jakub Kicinski's avatar Jakub Kicinski

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.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 0a12ad59 91d02f95
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "ipa.h" #include "ipa.h"
#include "ipa_clock.h" #include "ipa_clock.h"
#include "ipa_modem.h" #include "ipa_modem.h"
#include "ipa_data.h"
/** /**
* DOC: IPA Clocking * DOC: IPA Clocking
...@@ -29,18 +30,6 @@ ...@@ -29,18 +30,6 @@
* An IPA clock reference must be held for any access to IPA hardware. * 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 * struct ipa_clock - IPA clocking information
* @count: Clocking reference count * @count: Clocking reference count
...@@ -49,6 +38,7 @@ ...@@ -49,6 +38,7 @@
* @memory_path: Memory interconnect * @memory_path: Memory interconnect
* @imem_path: Internal memory interconnect * @imem_path: Internal memory interconnect
* @config_path: Configuration space interconnect * @config_path: Configuration space interconnect
* @interconnect_data: Interconnect configuration data
*/ */
struct ipa_clock { struct ipa_clock {
refcount_t count; refcount_t count;
...@@ -57,6 +47,7 @@ struct ipa_clock { ...@@ -57,6 +47,7 @@ struct ipa_clock {
struct icc_path *memory_path; struct icc_path *memory_path;
struct icc_path *imem_path; struct icc_path *imem_path;
struct icc_path *config_path; struct icc_path *config_path;
const struct ipa_interconnect_data *interconnect_data;
}; };
static struct icc_path * static struct icc_path *
...@@ -113,18 +104,25 @@ static void ipa_interconnect_exit(struct ipa_clock *clock) ...@@ -113,18 +104,25 @@ static void ipa_interconnect_exit(struct ipa_clock *clock)
/* Currently we only use one bandwidth level, so just "enable" interconnects */ /* Currently we only use one bandwidth level, so just "enable" interconnects */
static int ipa_interconnect_enable(struct ipa *ipa) static int ipa_interconnect_enable(struct ipa *ipa)
{ {
const struct ipa_interconnect_data *data;
struct ipa_clock *clock = ipa->clock; struct ipa_clock *clock = ipa->clock;
int ret; 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) if (ret)
return 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) if (ret)
goto err_memory_path_disable; 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) if (ret)
goto err_imem_path_disable; goto err_imem_path_disable;
...@@ -141,6 +139,7 @@ static int ipa_interconnect_enable(struct ipa *ipa) ...@@ -141,6 +139,7 @@ static int ipa_interconnect_enable(struct ipa *ipa)
/* To disable an interconnect, we just its bandwidth to 0 */ /* To disable an interconnect, we just its bandwidth to 0 */
static int ipa_interconnect_disable(struct ipa *ipa) static int ipa_interconnect_disable(struct ipa *ipa)
{ {
const struct ipa_interconnect_data *data;
struct ipa_clock *clock = ipa->clock; struct ipa_clock *clock = ipa->clock;
int ret; int ret;
...@@ -159,9 +158,13 @@ static int ipa_interconnect_disable(struct ipa *ipa) ...@@ -159,9 +158,13 @@ static int ipa_interconnect_disable(struct ipa *ipa)
return 0; return 0;
err_imem_path_reenable: 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: 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; return ret;
} }
...@@ -257,7 +260,8 @@ u32 ipa_clock_rate(struct ipa *ipa) ...@@ -257,7 +260,8 @@ u32 ipa_clock_rate(struct ipa *ipa)
} }
/* Initialize IPA clocking */ /* 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 ipa_clock *clock;
struct clk *clk; struct clk *clk;
...@@ -269,10 +273,10 @@ struct ipa_clock *ipa_clock_init(struct device *dev) ...@@ -269,10 +273,10 @@ struct ipa_clock *ipa_clock_init(struct device *dev)
return ERR_CAST(clk); return ERR_CAST(clk);
} }
ret = clk_set_rate(clk, IPA_CORE_CLOCK_RATE); ret = clk_set_rate(clk, data->core_clock_rate);
if (ret) { if (ret) {
dev_err(dev, "error %d setting core clock rate to %lu\n", dev_err(dev, "error %d setting core clock rate to %u\n",
ret, IPA_CORE_CLOCK_RATE); ret, data->core_clock_rate);
goto err_clk_put; goto err_clk_put;
} }
...@@ -282,6 +286,7 @@ struct ipa_clock *ipa_clock_init(struct device *dev) ...@@ -282,6 +286,7 @@ struct ipa_clock *ipa_clock_init(struct device *dev)
goto err_clk_put; goto err_clk_put;
} }
clock->core = clk; clock->core = clk;
clock->interconnect_data = data->interconnect;
ret = ipa_interconnect_init(clock, dev); ret = ipa_interconnect_init(clock, dev);
if (ret) if (ret)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
struct device; struct device;
struct ipa; struct ipa;
struct ipa_clock_data;
/** /**
* ipa_clock_rate() - Return the current IPA core clock rate * ipa_clock_rate() - Return the current IPA core clock rate
...@@ -21,10 +22,12 @@ u32 ipa_clock_rate(struct ipa *ipa); ...@@ -21,10 +22,12 @@ u32 ipa_clock_rate(struct ipa *ipa);
/** /**
* ipa_clock_init() - Initialize IPA clocking * ipa_clock_init() - Initialize IPA clocking
* @dev: IPA device * @dev: IPA device
* @data: Clock configuration data
* *
* Return: A pointer to an ipa_clock structure, or a pointer-coded error * 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() * ipa_clock_exit() - Inverse of ipa_clock_init()
......
...@@ -309,6 +309,26 @@ static struct ipa_mem_data ipa_mem_data = { ...@@ -309,6 +309,26 @@ static struct ipa_mem_data ipa_mem_data = {
.smem_size = 0x00002000, .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. */ /* Configuration data for the SC7180 SoC. */
const struct ipa_data ipa_data_sc7180 = { const struct ipa_data ipa_data_sc7180 = {
.version = IPA_VERSION_4_2, .version = IPA_VERSION_4_2,
...@@ -316,4 +336,5 @@ const struct ipa_data ipa_data_sc7180 = { ...@@ -316,4 +336,5 @@ const struct ipa_data ipa_data_sc7180 = {
.endpoint_data = ipa_gsi_endpoint_data, .endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data, .resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data, .mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
}; };
...@@ -329,6 +329,26 @@ static struct ipa_mem_data ipa_mem_data = { ...@@ -329,6 +329,26 @@ static struct ipa_mem_data ipa_mem_data = {
.smem_size = 0x00002000, .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. */ /* Configuration data for the SDM845 SoC. */
const struct ipa_data ipa_data_sdm845 = { const struct ipa_data ipa_data_sdm845 = {
.version = IPA_VERSION_3_5_1, .version = IPA_VERSION_3_5_1,
...@@ -336,4 +356,5 @@ const struct ipa_data ipa_data_sdm845 = { ...@@ -336,4 +356,5 @@ const struct ipa_data ipa_data_sdm845 = {
.endpoint_data = ipa_gsi_endpoint_data, .endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data, .resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data, .mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
}; };
...@@ -241,7 +241,7 @@ struct ipa_resource_data { ...@@ -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_count: number of regions defined in the local[] array
* @local: array of IPA-local memory region descriptors * @local: array of IPA-local memory region descriptors
* @imem_addr: physical address of IPA region within IMEM * @imem_addr: physical address of IPA region within IMEM
...@@ -258,6 +258,34 @@ struct ipa_mem_data { ...@@ -258,6 +258,34 @@ struct ipa_mem_data {
u32 smem_size; 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 * struct ipa_data - combined IPA/GSI configuration data
* @version: IPA hardware version * @version: IPA hardware version
...@@ -273,6 +301,7 @@ struct ipa_data { ...@@ -273,6 +301,7 @@ struct ipa_data {
const struct ipa_gsi_endpoint_data *endpoint_data; const struct ipa_gsi_endpoint_data *endpoint_data;
const struct ipa_resource_data *resource_data; const struct ipa_resource_data *resource_data;
const struct ipa_mem_data *mem_data; const struct ipa_mem_data *mem_data;
const struct ipa_clock_data *clock_data;
}; };
extern const struct ipa_data ipa_data_sdm845; extern const struct ipa_data ipa_data_sdm845;
......
...@@ -728,6 +728,14 @@ static int ipa_probe(struct platform_device *pdev) ...@@ -728,6 +728,14 @@ static int ipa_probe(struct platform_device *pdev)
ipa_validate_build(); 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 */ /* If we need Trust Zone, make sure it's available */
modem_init = of_property_read_bool(dev->of_node, "modem-init"); modem_init = of_property_read_bool(dev->of_node, "modem-init");
if (!modem_init) if (!modem_init)
...@@ -748,22 +756,13 @@ static int ipa_probe(struct platform_device *pdev) ...@@ -748,22 +756,13 @@ static int ipa_probe(struct platform_device *pdev)
/* The clock and interconnects might not be ready when we're /* The clock and interconnects might not be ready when we're
* probed, so might return -EPROBE_DEFER. * probed, so might return -EPROBE_DEFER.
*/ */
clock = ipa_clock_init(dev); clock = ipa_clock_init(dev, data->clock_data);
if (IS_ERR(clock)) { if (IS_ERR(clock)) {
ret = PTR_ERR(clock); ret = PTR_ERR(clock);
goto err_rproc_put; goto err_rproc_put;
} }
/* No more EPROBE_DEFER. Get our configuration data */ /* No more EPROBE_DEFER. Allocate and initialize the IPA structure */
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 */
ipa = kzalloc(sizeof(*ipa), GFP_KERNEL); ipa = kzalloc(sizeof(*ipa), GFP_KERNEL);
if (!ipa) { if (!ipa) {
ret = -ENOMEM; ret = -ENOMEM;
......
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