summaryrefslogtreecommitdiff
path: root/drivers/net/ipa/ipa_clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ipa/ipa_clock.c')
-rw-r--r--drivers/net/ipa/ipa_clock.c117
1 files changed, 51 insertions, 66 deletions
diff --git a/drivers/net/ipa/ipa_clock.c b/drivers/net/ipa/ipa_clock.c
index fbe42106fc2a..354675a643db 100644
--- a/drivers/net/ipa/ipa_clock.c
+++ b/drivers/net/ipa/ipa_clock.c
@@ -47,13 +47,15 @@ struct ipa_interconnect {
* @count: Clocking reference count
* @mutex: Protects clock enable/disable
* @core: IPA core clock
+ * @interconnect_count: Number of elements in interconnect[]
* @interconnect: Interconnect array
*/
struct ipa_clock {
refcount_t count;
struct mutex mutex; /* protects clock enable/disable */
struct clk *core;
- struct ipa_interconnect interconnect[IPA_INTERCONNECT_COUNT];
+ u32 interconnect_count;
+ struct ipa_interconnect *interconnect;
};
static int ipa_interconnect_init_one(struct device *dev,
@@ -90,31 +92,29 @@ static int ipa_interconnect_init(struct ipa_clock *clock, struct device *dev,
const struct ipa_interconnect_data *data)
{
struct ipa_interconnect *interconnect;
+ u32 count;
int ret;
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- ret = ipa_interconnect_init_one(dev, interconnect, data++);
- if (ret)
- return ret;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ret = ipa_interconnect_init_one(dev, interconnect, data++);
- if (ret)
- goto err_memory_path_put;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ret = ipa_interconnect_init_one(dev, interconnect, data++);
- if (ret)
- goto err_imem_path_put;
+ count = clock->interconnect_count;
+ interconnect = kcalloc(count, sizeof(*interconnect), GFP_KERNEL);
+ if (!interconnect)
+ return -ENOMEM;
+ clock->interconnect = interconnect;
+
+ while (count--) {
+ ret = ipa_interconnect_init_one(dev, interconnect, data++);
+ if (ret)
+ goto out_unwind;
+ interconnect++;
+ }
return 0;
-err_imem_path_put:
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ipa_interconnect_exit_one(interconnect);
-err_memory_path_put:
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- ipa_interconnect_exit_one(interconnect);
+out_unwind:
+ while (interconnect-- > clock->interconnect)
+ ipa_interconnect_exit_one(interconnect);
+ kfree(clock->interconnect);
+ clock->interconnect = NULL;
return ret;
}
@@ -124,12 +124,11 @@ static void ipa_interconnect_exit(struct ipa_clock *clock)
{
struct ipa_interconnect *interconnect;
- interconnect = &clock->interconnect[IPA_INTERCONNECT_CONFIG];
- ipa_interconnect_exit_one(interconnect);
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ipa_interconnect_exit_one(interconnect);
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- ipa_interconnect_exit_one(interconnect);
+ interconnect = clock->interconnect + clock->interconnect_count;
+ while (interconnect-- > clock->interconnect)
+ ipa_interconnect_exit_one(interconnect);
+ kfree(clock->interconnect);
+ clock->interconnect = NULL;
}
/* Currently we only use one bandwidth level, so just "enable" interconnects */
@@ -138,33 +137,23 @@ static int ipa_interconnect_enable(struct ipa *ipa)
struct ipa_interconnect *interconnect;
struct ipa_clock *clock = ipa->clock;
int ret;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
- interconnect->peak_bandwidth);
- if (ret)
- return ret;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
- interconnect->peak_bandwidth);
- if (ret)
- goto err_memory_path_disable;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_CONFIG];
- ret = icc_set_bw(interconnect->path, interconnect->average_bandwidth,
- interconnect->peak_bandwidth);
- if (ret)
- goto err_imem_path_disable;
+ u32 i;
+
+ interconnect = clock->interconnect;
+ for (i = 0; i < clock->interconnect_count; i++) {
+ ret = icc_set_bw(interconnect->path,
+ interconnect->average_bandwidth,
+ interconnect->peak_bandwidth);
+ if (ret)
+ goto out_unwind;
+ interconnect++;
+ }
return 0;
-err_imem_path_disable:
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- (void)icc_set_bw(interconnect->path, 0, 0);
-err_memory_path_disable:
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- (void)icc_set_bw(interconnect->path, 0, 0);
+out_unwind:
+ while (interconnect-- > clock->interconnect)
+ (void)icc_set_bw(interconnect->path, 0, 0);
return ret;
}
@@ -175,22 +164,17 @@ static void ipa_interconnect_disable(struct ipa *ipa)
struct ipa_interconnect *interconnect;
struct ipa_clock *clock = ipa->clock;
int result = 0;
+ u32 count;
int ret;
- interconnect = &clock->interconnect[IPA_INTERCONNECT_MEMORY];
- ret = icc_set_bw(interconnect->path, 0, 0);
- if (ret)
- result = ret;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ret = icc_set_bw(interconnect->path, 0, 0);
- if (ret && !result)
- result = ret;
-
- interconnect = &clock->interconnect[IPA_INTERCONNECT_IMEM];
- ret = icc_set_bw(interconnect->path, 0, 0);
- if (ret && !result)
- result = ret;
+ count = clock->interconnect_count;
+ interconnect = clock->interconnect + count;
+ while (count--) {
+ interconnect--;
+ ret = icc_set_bw(interconnect->path, 0, 0);
+ if (ret && !result)
+ result = ret;
+ }
if (result)
dev_err(&ipa->pdev->dev,
@@ -314,8 +298,9 @@ ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)
goto err_clk_put;
}
clock->core = clk;
+ clock->interconnect_count = data->interconnect_count;
- ret = ipa_interconnect_init(clock, dev, data->interconnect);
+ ret = ipa_interconnect_init(clock, dev, data->interconnect_data);
if (ret)
goto err_kfree;