Skip to content

Commit

Permalink
Merge branch 'net-ipa-platform-specific-clock-and-interconnect-rates'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jakub Kicinski committed Nov 21, 2020
2 parents 0a12ad5 + 91d02f9 commit 0ee6de2
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 34 deletions.
47 changes: 26 additions & 21 deletions drivers/net/ipa/ipa_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "ipa.h"
#include "ipa_clock.h"
#include "ipa_modem.h"
#include "ipa_data.h"

/**
* DOC: IPA Clocking
Expand All @@ -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
Expand All @@ -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;
Expand All @@ -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 *
Expand Down Expand Up @@ -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;

Expand All @@ -141,6 +139,7 @@ static int ipa_interconnect_enable(struct ipa *ipa)
/* 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;

Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand All @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ipa/ipa_clock.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
struct device;

struct ipa;
struct ipa_clock_data;

/**
* ipa_clock_rate() - Return the current IPA core clock rate
Expand All @@ -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()
Expand Down
21 changes: 21 additions & 0 deletions drivers/net/ipa/ipa_data-sc7180.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,11 +309,32 @@ 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,
.endpoint_count = ARRAY_SIZE(ipa_gsi_endpoint_data),
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
};
21 changes: 21 additions & 0 deletions drivers/net/ipa/ipa_data-sdm845.c
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,32 @@ 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,
.endpoint_count = ARRAY_SIZE(ipa_gsi_endpoint_data),
.endpoint_data = ipa_gsi_endpoint_data,
.resource_data = &ipa_resource_data,
.mem_data = &ipa_mem_data,
.clock_data = &ipa_clock_data,
};
31 changes: 30 additions & 1 deletion drivers/net/ipa/ipa_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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;
Expand Down
21 changes: 10 additions & 11 deletions drivers/net/ipa/ipa_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down

0 comments on commit 0ee6de2

Please sign in to comment.