blob: b1c6c0fcb654f69e363af2e497a0d75fe87a02b2 [file] [log] [blame]
Alex Elderba764c42020-03-05 22:28:19 -06001// SPDX-License-Identifier: GPL-2.0
2
3/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
Alex Elder4c7ccfc2021-02-12 08:33:59 -06004 * Copyright (C) 2018-2021 Linaro Ltd.
Alex Elderba764c42020-03-05 22:28:19 -06005 */
6
Alex Elderba764c42020-03-05 22:28:19 -06007#include <linux/clk.h>
8#include <linux/device.h>
9#include <linux/interconnect.h>
Alex Elder73ff3162021-08-04 10:36:24 -050010#include <linux/pm.h>
Alex Elder2abb0c72021-08-10 14:27:00 -050011#include <linux/pm_runtime.h>
Alex Elder73ff3162021-08-04 10:36:24 -050012#include <linux/bitops.h>
Alex Elderba764c42020-03-05 22:28:19 -060013
14#include "ipa.h"
Alex Elder2775cbc2021-08-20 11:01:29 -050015#include "ipa_power.h"
Alex Elder73ff3162021-08-04 10:36:24 -050016#include "ipa_endpoint.h"
Alex Elderba764c42020-03-05 22:28:19 -060017#include "ipa_modem.h"
Alex Elderdfccb8b2020-11-19 16:40:39 -060018#include "ipa_data.h"
Alex Elderba764c42020-03-05 22:28:19 -060019
20/**
Alex Elder7aa0e8b2021-08-20 11:01:28 -050021 * DOC: IPA Power Management
Alex Elderba764c42020-03-05 22:28:19 -060022 *
Alex Elder7aa0e8b2021-08-20 11:01:28 -050023 * The IPA hardware is enabled when the IPA core clock and all the
24 * interconnects (buses) it depends on are enabled. Runtime power
25 * management is used to determine whether the core clock and
26 * interconnects are enabled, and if not in use to be suspended
27 * automatically.
Alex Elderba764c42020-03-05 22:28:19 -060028 *
Alex Elder7aa0e8b2021-08-20 11:01:28 -050029 * The core clock currently runs at a fixed clock rate when enabled,
30 * an all interconnects use a fixed average and peak bandwidth.
Alex Elderba764c42020-03-05 22:28:19 -060031 */
32
Alex Elder1aac3092021-08-20 11:01:27 -050033#define IPA_AUTOSUSPEND_DELAY 500 /* milliseconds */
34
Alex Elderba764c42020-03-05 22:28:19 -060035/**
Alex Elder5b408102021-01-15 06:50:46 -060036 * struct ipa_interconnect - IPA interconnect information
37 * @path: Interconnect path
Alex Elderdb6cd512021-01-15 06:50:47 -060038 * @average_bandwidth: Average interconnect bandwidth (KB/second)
39 * @peak_bandwidth: Peak interconnect bandwidth (KB/second)
Alex Elder5b408102021-01-15 06:50:46 -060040 */
41struct ipa_interconnect {
42 struct icc_path *path;
Alex Elderdb6cd512021-01-15 06:50:47 -060043 u32 average_bandwidth;
44 u32 peak_bandwidth;
Alex Elder5b408102021-01-15 06:50:46 -060045};
46
47/**
Alex Elderafb08b72021-08-04 10:36:26 -050048 * enum ipa_power_flag - IPA power flags
49 * @IPA_POWER_FLAG_RESUMED: Whether resume from suspend has been signaled
Alex Elderb9c532c2021-08-12 14:50:31 -050050 * @IPA_POWER_FLAG_SYSTEM: Hardware is system (not runtime) suspended
Alex Elderb8e36e12021-08-19 16:12:28 -050051 * @IPA_POWER_FLAG_STOPPED: Modem TX is disabled by ipa_start_xmit()
52 * @IPA_POWER_FLAG_STARTED: Modem TX was enabled by ipa_runtime_resume()
Alex Elderafb08b72021-08-04 10:36:26 -050053 * @IPA_POWER_FLAG_COUNT: Number of defined power flags
54 */
55enum ipa_power_flag {
56 IPA_POWER_FLAG_RESUMED,
Alex Elderb9c532c2021-08-12 14:50:31 -050057 IPA_POWER_FLAG_SYSTEM,
Alex Elderb8e36e12021-08-19 16:12:28 -050058 IPA_POWER_FLAG_STOPPED,
59 IPA_POWER_FLAG_STARTED,
Alex Elderafb08b72021-08-04 10:36:26 -050060 IPA_POWER_FLAG_COUNT, /* Last; not a flag */
61};
62
63/**
Alex Elder7aa0e8b2021-08-20 11:01:28 -050064 * struct ipa_power - IPA power management information
Alex Elder63de79f2021-08-10 14:27:01 -050065 * @dev: IPA device pointer
Alex Elderba764c42020-03-05 22:28:19 -060066 * @core: IPA core clock
Alex Elderb8e36e12021-08-19 16:12:28 -050067 * @spinlock: Protects modem TX queue enable/disable
Alex Elderafb08b72021-08-04 10:36:26 -050068 * @flags: Boolean state flags
Alex Elderea151e12021-01-15 06:50:50 -060069 * @interconnect_count: Number of elements in interconnect[]
Alex Elder5b408102021-01-15 06:50:46 -060070 * @interconnect: Interconnect array
Alex Elderba764c42020-03-05 22:28:19 -060071 */
Alex Elder7aa0e8b2021-08-20 11:01:28 -050072struct ipa_power {
Alex Elder63de79f2021-08-10 14:27:01 -050073 struct device *dev;
Alex Elderba764c42020-03-05 22:28:19 -060074 struct clk *core;
Alex Elderb8e36e12021-08-19 16:12:28 -050075 spinlock_t spinlock; /* used with STOPPED/STARTED power flags */
Alex Elderafb08b72021-08-04 10:36:26 -050076 DECLARE_BITMAP(flags, IPA_POWER_FLAG_COUNT);
Alex Elderea151e12021-01-15 06:50:50 -060077 u32 interconnect_count;
78 struct ipa_interconnect *interconnect;
Alex Elderba764c42020-03-05 22:28:19 -060079};
80
Alex Elder10d0d392021-01-15 06:50:49 -060081static int ipa_interconnect_init_one(struct device *dev,
82 struct ipa_interconnect *interconnect,
83 const struct ipa_interconnect_data *data)
Alex Elderba764c42020-03-05 22:28:19 -060084{
85 struct icc_path *path;
86
Alex Elder10d0d392021-01-15 06:50:49 -060087 path = of_icc_get(dev, data->name);
88 if (IS_ERR(path)) {
89 int ret = PTR_ERR(path);
Alex Elderba764c42020-03-05 22:28:19 -060090
Alex Elder4c7ccfc2021-02-12 08:33:59 -060091 dev_err_probe(dev, ret, "error getting %s interconnect\n",
92 data->name);
Alex Elder10d0d392021-01-15 06:50:49 -060093
94 return ret;
95 }
96
97 interconnect->path = path;
98 interconnect->average_bandwidth = data->average_bandwidth;
99 interconnect->peak_bandwidth = data->peak_bandwidth;
100
101 return 0;
102}
103
104static void ipa_interconnect_exit_one(struct ipa_interconnect *interconnect)
105{
106 icc_put(interconnect->path);
107 memset(interconnect, 0, sizeof(*interconnect));
Alex Elderba764c42020-03-05 22:28:19 -0600108}
109
110/* Initialize interconnects required for IPA operation */
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500111static int ipa_interconnect_init(struct ipa_power *power, struct device *dev,
Alex Elderdb6cd512021-01-15 06:50:47 -0600112 const struct ipa_interconnect_data *data)
Alex Elderba764c42020-03-05 22:28:19 -0600113{
Alex Elderdb6cd512021-01-15 06:50:47 -0600114 struct ipa_interconnect *interconnect;
Alex Elderea151e12021-01-15 06:50:50 -0600115 u32 count;
Alex Elder10d0d392021-01-15 06:50:49 -0600116 int ret;
Alex Elderba764c42020-03-05 22:28:19 -0600117
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500118 count = power->interconnect_count;
Alex Elderea151e12021-01-15 06:50:50 -0600119 interconnect = kcalloc(count, sizeof(*interconnect), GFP_KERNEL);
120 if (!interconnect)
121 return -ENOMEM;
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500122 power->interconnect = interconnect;
Alex Elderba764c42020-03-05 22:28:19 -0600123
Alex Elderea151e12021-01-15 06:50:50 -0600124 while (count--) {
125 ret = ipa_interconnect_init_one(dev, interconnect, data++);
126 if (ret)
127 goto out_unwind;
128 interconnect++;
129 }
Alex Elderba764c42020-03-05 22:28:19 -0600130
131 return 0;
132
Alex Elderea151e12021-01-15 06:50:50 -0600133out_unwind:
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500134 while (interconnect-- > power->interconnect)
Alex Elderea151e12021-01-15 06:50:50 -0600135 ipa_interconnect_exit_one(interconnect);
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500136 kfree(power->interconnect);
137 power->interconnect = NULL;
Alex Elder10d0d392021-01-15 06:50:49 -0600138
139 return ret;
Alex Elderba764c42020-03-05 22:28:19 -0600140}
141
142/* Inverse of ipa_interconnect_init() */
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500143static void ipa_interconnect_exit(struct ipa_power *power)
Alex Elderba764c42020-03-05 22:28:19 -0600144{
Alex Elder10d0d392021-01-15 06:50:49 -0600145 struct ipa_interconnect *interconnect;
146
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500147 interconnect = power->interconnect + power->interconnect_count;
148 while (interconnect-- > power->interconnect)
Alex Elderea151e12021-01-15 06:50:50 -0600149 ipa_interconnect_exit_one(interconnect);
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500150 kfree(power->interconnect);
151 power->interconnect = NULL;
Alex Elderba764c42020-03-05 22:28:19 -0600152}
153
154/* Currently we only use one bandwidth level, so just "enable" interconnects */
155static int ipa_interconnect_enable(struct ipa *ipa)
156{
Alex Elderdb6cd512021-01-15 06:50:47 -0600157 struct ipa_interconnect *interconnect;
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500158 struct ipa_power *power = ipa->power;
Alex Elderba764c42020-03-05 22:28:19 -0600159 int ret;
Alex Elderea151e12021-01-15 06:50:50 -0600160 u32 i;
Alex Elderba764c42020-03-05 22:28:19 -0600161
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500162 interconnect = power->interconnect;
163 for (i = 0; i < power->interconnect_count; i++) {
Alex Elderea151e12021-01-15 06:50:50 -0600164 ret = icc_set_bw(interconnect->path,
165 interconnect->average_bandwidth,
166 interconnect->peak_bandwidth);
Alex Elder8ee7c402021-08-04 10:36:23 -0500167 if (ret) {
168 dev_err(&ipa->pdev->dev,
169 "error %d enabling %s interconnect\n",
170 ret, icc_get_name(interconnect->path));
Alex Elderea151e12021-01-15 06:50:50 -0600171 goto out_unwind;
Alex Elder8ee7c402021-08-04 10:36:23 -0500172 }
Alex Elderea151e12021-01-15 06:50:50 -0600173 interconnect++;
174 }
Alex Elderba764c42020-03-05 22:28:19 -0600175
176 return 0;
177
Alex Elderea151e12021-01-15 06:50:50 -0600178out_unwind:
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500179 while (interconnect-- > power->interconnect)
Alex Elderea151e12021-01-15 06:50:50 -0600180 (void)icc_set_bw(interconnect->path, 0, 0);
Alex Elderba764c42020-03-05 22:28:19 -0600181
182 return ret;
183}
184
185/* To disable an interconnect, we just its bandwidth to 0 */
Alex Elder8ee7c402021-08-04 10:36:23 -0500186static int ipa_interconnect_disable(struct ipa *ipa)
Alex Elderba764c42020-03-05 22:28:19 -0600187{
Alex Elderdb6cd512021-01-15 06:50:47 -0600188 struct ipa_interconnect *interconnect;
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500189 struct ipa_power *power = ipa->power;
Alex Elder8ee7c402021-08-04 10:36:23 -0500190 struct device *dev = &ipa->pdev->dev;
Alex Elderec0ef6d2021-01-15 06:50:45 -0600191 int result = 0;
Alex Elderea151e12021-01-15 06:50:50 -0600192 u32 count;
Alex Elderba764c42020-03-05 22:28:19 -0600193 int ret;
194
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500195 count = power->interconnect_count;
196 interconnect = power->interconnect + count;
Alex Elderea151e12021-01-15 06:50:50 -0600197 while (count--) {
198 interconnect--;
199 ret = icc_set_bw(interconnect->path, 0, 0);
Alex Elder8ee7c402021-08-04 10:36:23 -0500200 if (ret) {
201 dev_err(dev, "error %d disabling %s interconnect\n",
202 ret, icc_get_name(interconnect->path));
203 /* Try to disable all; record only the first error */
204 if (!result)
205 result = ret;
206 }
Alex Elderea151e12021-01-15 06:50:50 -0600207 }
Alex Elderba764c42020-03-05 22:28:19 -0600208
Alex Elder8ee7c402021-08-04 10:36:23 -0500209 return result;
Alex Elderba764c42020-03-05 22:28:19 -0600210}
211
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500212/* Enable IPA power, enabling interconnects and the core clock */
213static int ipa_power_enable(struct ipa *ipa)
Alex Elderba764c42020-03-05 22:28:19 -0600214{
215 int ret;
216
217 ret = ipa_interconnect_enable(ipa);
218 if (ret)
219 return ret;
220
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500221 ret = clk_prepare_enable(ipa->power->core);
Alex Elder8ee7c402021-08-04 10:36:23 -0500222 if (ret) {
223 dev_err(&ipa->pdev->dev, "error %d enabling core clock\n", ret);
224 (void)ipa_interconnect_disable(ipa);
225 }
Alex Elderba764c42020-03-05 22:28:19 -0600226
227 return ret;
228}
229
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500230/* Inverse of ipa_power_enable() */
231static int ipa_power_disable(struct ipa *ipa)
Alex Elderba764c42020-03-05 22:28:19 -0600232{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500233 clk_disable_unprepare(ipa->power->core);
Alex Elder7ebd1682021-08-10 14:26:58 -0500234
235 return ipa_interconnect_disable(ipa);
Alex Elderba764c42020-03-05 22:28:19 -0600236}
237
Alex Elder2abb0c72021-08-10 14:27:00 -0500238static int ipa_runtime_suspend(struct device *dev)
239{
240 struct ipa *ipa = dev_get_drvdata(dev);
241
242 /* Endpoints aren't usable until setup is complete */
243 if (ipa->setup_complete) {
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500244 __clear_bit(IPA_POWER_FLAG_RESUMED, ipa->power->flags);
Alex Elder2abb0c72021-08-10 14:27:00 -0500245 ipa_endpoint_suspend(ipa);
246 gsi_suspend(&ipa->gsi);
247 }
248
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500249 return ipa_power_disable(ipa);
Alex Elder2abb0c72021-08-10 14:27:00 -0500250}
251
252static int ipa_runtime_resume(struct device *dev)
253{
254 struct ipa *ipa = dev_get_drvdata(dev);
255 int ret;
256
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500257 ret = ipa_power_enable(ipa);
Alex Elder2abb0c72021-08-10 14:27:00 -0500258 if (WARN_ON(ret < 0))
259 return ret;
260
261 /* Endpoints aren't usable until setup is complete */
262 if (ipa->setup_complete) {
263 gsi_resume(&ipa->gsi);
264 ipa_endpoint_resume(ipa);
265 }
266
267 return 0;
268}
269
Alex Elderb9c532c2021-08-12 14:50:31 -0500270static int ipa_suspend(struct device *dev)
271{
272 struct ipa *ipa = dev_get_drvdata(dev);
273
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500274 __set_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
Alex Elderb9c532c2021-08-12 14:50:31 -0500275
276 return pm_runtime_force_suspend(dev);
277}
278
279static int ipa_resume(struct device *dev)
280{
281 struct ipa *ipa = dev_get_drvdata(dev);
282 int ret;
283
284 ret = pm_runtime_force_resume(dev);
285
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500286 __clear_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags);
Alex Elderb9c532c2021-08-12 14:50:31 -0500287
288 return ret;
289}
290
Alex Elder78b348f2020-07-03 16:23:34 -0500291/* Return the current IPA core clock rate */
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500292u32 ipa_core_clock_rate(struct ipa *ipa)
Alex Elder78b348f2020-07-03 16:23:34 -0500293{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500294 return ipa->power ? (u32)clk_get_rate(ipa->power->core) : 0;
Alex Elder78b348f2020-07-03 16:23:34 -0500295}
296
Alex Elderafe1baa2021-08-04 10:36:25 -0500297/**
298 * ipa_suspend_handler() - Handle the suspend IPA interrupt
299 * @ipa: IPA pointer
300 * @irq_id: IPA interrupt type (unused)
301 *
302 * If an RX endpoint is suspended, and the IPA has a packet destined for
303 * that endpoint, the IPA generates a SUSPEND interrupt to inform the AP
304 * that it should resume the endpoint. If we get one of these interrupts
305 * we just wake up the system.
306 */
307static void ipa_suspend_handler(struct ipa *ipa, enum ipa_irq_id irq_id)
308{
Alex Elderb9c532c2021-08-12 14:50:31 -0500309 /* To handle an IPA interrupt we will have resumed the hardware
310 * just to handle the interrupt, so we're done. If we are in a
311 * system suspend, trigger a system resume.
Alex Elderafe1baa2021-08-04 10:36:25 -0500312 */
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500313 if (!__test_and_set_bit(IPA_POWER_FLAG_RESUMED, ipa->power->flags))
314 if (test_bit(IPA_POWER_FLAG_SYSTEM, ipa->power->flags))
Alex Elderb9c532c2021-08-12 14:50:31 -0500315 pm_wakeup_dev_event(&ipa->pdev->dev, 0, true);
Alex Elderafe1baa2021-08-04 10:36:25 -0500316
317 /* Acknowledge/clear the suspend interrupt on all endpoints */
318 ipa_interrupt_suspend_clear_all(ipa->interrupt);
319}
320
Alex Elderb8e36e12021-08-19 16:12:28 -0500321/* The next few functions coordinate stopping and starting the modem
322 * network device transmit queue.
323 *
324 * Transmit can be running concurrent with power resume, and there's a
325 * chance the resume completes before the transmit path stops the queue,
326 * leaving the queue in a stopped state. The next two functions are used
327 * to avoid this: ipa_power_modem_queue_stop() is used by ipa_start_xmit()
328 * to conditionally stop the TX queue; and ipa_power_modem_queue_start()
329 * is used by ipa_runtime_resume() to conditionally restart it.
330 *
331 * Two flags and a spinlock are used. If the queue is stopped, the STOPPED
332 * power flag is set. And if the queue is started, the STARTED flag is set.
333 * The queue is only started on resume if the STOPPED flag is set. And the
334 * queue is only started in ipa_start_xmit() if the STARTED flag is *not*
335 * set. As a result, the queue remains operational if the two activites
336 * happen concurrently regardless of the order they complete. The spinlock
337 * ensures the flag and TX queue operations are done atomically.
338 *
339 * The first function stops the modem netdev transmit queue, but only if
340 * the STARTED flag is *not* set. That flag is cleared if it was set.
341 * If the queue is stopped, the STOPPED flag is set. This is called only
342 * from the power ->runtime_resume operation.
343 */
344void ipa_power_modem_queue_stop(struct ipa *ipa)
345{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500346 struct ipa_power *power = ipa->power;
Alex Elderb8e36e12021-08-19 16:12:28 -0500347 unsigned long flags;
348
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500349 spin_lock_irqsave(&power->spinlock, flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500350
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500351 if (!__test_and_clear_bit(IPA_POWER_FLAG_STARTED, power->flags)) {
Alex Elderb8e36e12021-08-19 16:12:28 -0500352 netif_stop_queue(ipa->modem_netdev);
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500353 __set_bit(IPA_POWER_FLAG_STOPPED, power->flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500354 }
355
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500356 spin_unlock_irqrestore(&power->spinlock, flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500357}
358
359/* This function starts the modem netdev transmit queue, but only if the
360 * STOPPED flag is set. That flag is cleared if it was set. If the queue
361 * was restarted, the STARTED flag is set; this allows ipa_start_xmit()
362 * to skip stopping the queue in the event of a race.
363 */
364void ipa_power_modem_queue_wake(struct ipa *ipa)
365{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500366 struct ipa_power *power = ipa->power;
Alex Elderb8e36e12021-08-19 16:12:28 -0500367 unsigned long flags;
368
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500369 spin_lock_irqsave(&power->spinlock, flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500370
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500371 if (__test_and_clear_bit(IPA_POWER_FLAG_STOPPED, power->flags)) {
372 __set_bit(IPA_POWER_FLAG_STARTED, power->flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500373 netif_wake_queue(ipa->modem_netdev);
374 }
375
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500376 spin_unlock_irqrestore(&power->spinlock, flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500377}
378
379/* This function clears the STARTED flag once the TX queue is operating */
380void ipa_power_modem_queue_active(struct ipa *ipa)
381{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500382 clear_bit(IPA_POWER_FLAG_STARTED, ipa->power->flags);
Alex Elderb8e36e12021-08-19 16:12:28 -0500383}
384
Alex Elderd430fe42021-08-12 14:50:30 -0500385int ipa_power_setup(struct ipa *ipa)
Alex Elderafe1baa2021-08-04 10:36:25 -0500386{
Alex Elderd430fe42021-08-12 14:50:30 -0500387 int ret;
388
Alex Elderafe1baa2021-08-04 10:36:25 -0500389 ipa_interrupt_add(ipa->interrupt, IPA_IRQ_TX_SUSPEND,
390 ipa_suspend_handler);
Alex Elderd430fe42021-08-12 14:50:30 -0500391
392 ret = device_init_wakeup(&ipa->pdev->dev, true);
393 if (ret)
394 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_TX_SUSPEND);
395
396 return ret;
Alex Elderafe1baa2021-08-04 10:36:25 -0500397}
398
399void ipa_power_teardown(struct ipa *ipa)
400{
Alex Elderd430fe42021-08-12 14:50:30 -0500401 (void)device_init_wakeup(&ipa->pdev->dev, false);
Alex Elderafe1baa2021-08-04 10:36:25 -0500402 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_TX_SUSPEND);
403}
404
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500405/* Initialize IPA power management */
406struct ipa_power *
407ipa_power_init(struct device *dev, const struct ipa_power_data *data)
Alex Elderba764c42020-03-05 22:28:19 -0600408{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500409 struct ipa_power *power;
Alex Elderba764c42020-03-05 22:28:19 -0600410 struct clk *clk;
411 int ret;
412
413 clk = clk_get(dev, "core");
414 if (IS_ERR(clk)) {
Alex Elder4c7ccfc2021-02-12 08:33:59 -0600415 dev_err_probe(dev, PTR_ERR(clk), "error getting core clock\n");
416
Alex Elderba764c42020-03-05 22:28:19 -0600417 return ERR_CAST(clk);
418 }
419
Alex Elder91d02f92020-11-19 16:40:41 -0600420 ret = clk_set_rate(clk, data->core_clock_rate);
Alex Elderba764c42020-03-05 22:28:19 -0600421 if (ret) {
Alex Elder91d02f92020-11-19 16:40:41 -0600422 dev_err(dev, "error %d setting core clock rate to %u\n",
423 ret, data->core_clock_rate);
Alex Elderba764c42020-03-05 22:28:19 -0600424 goto err_clk_put;
425 }
426
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500427 power = kzalloc(sizeof(*power), GFP_KERNEL);
428 if (!power) {
Alex Elderba764c42020-03-05 22:28:19 -0600429 ret = -ENOMEM;
430 goto err_clk_put;
431 }
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500432 power->dev = dev;
433 power->core = clk;
434 spin_lock_init(&power->spinlock);
435 power->interconnect_count = data->interconnect_count;
Alex Elderba764c42020-03-05 22:28:19 -0600436
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500437 ret = ipa_interconnect_init(power, dev, data->interconnect_data);
Alex Elderba764c42020-03-05 22:28:19 -0600438 if (ret)
439 goto err_kfree;
440
Alex Elder1aac3092021-08-20 11:01:27 -0500441 pm_runtime_set_autosuspend_delay(dev, IPA_AUTOSUSPEND_DELAY);
442 pm_runtime_use_autosuspend(dev);
Alex Elder63de79f2021-08-10 14:27:01 -0500443 pm_runtime_enable(dev);
444
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500445 return power;
Alex Elderba764c42020-03-05 22:28:19 -0600446
447err_kfree:
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500448 kfree(power);
Alex Elderba764c42020-03-05 22:28:19 -0600449err_clk_put:
450 clk_put(clk);
451
452 return ERR_PTR(ret);
453}
454
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500455/* Inverse of ipa_power_init() */
456void ipa_power_exit(struct ipa_power *power)
Alex Elderba764c42020-03-05 22:28:19 -0600457{
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500458 struct device *dev = power->dev;
459 struct clk *clk = power->core;
Alex Elderba764c42020-03-05 22:28:19 -0600460
Alex Elder1aac3092021-08-20 11:01:27 -0500461 pm_runtime_disable(dev);
462 pm_runtime_dont_use_autosuspend(dev);
Alex Elder7aa0e8b2021-08-20 11:01:28 -0500463 ipa_interconnect_exit(power);
464 kfree(power);
Alex Elderba764c42020-03-05 22:28:19 -0600465 clk_put(clk);
466}
Alex Elder73ff3162021-08-04 10:36:24 -0500467
Alex Elder73ff3162021-08-04 10:36:24 -0500468const struct dev_pm_ops ipa_pm_ops = {
Alex Elderb9c532c2021-08-12 14:50:31 -0500469 .suspend = ipa_suspend,
470 .resume = ipa_resume,
Alex Elder63de79f2021-08-10 14:27:01 -0500471 .runtime_suspend = ipa_runtime_suspend,
472 .runtime_resume = ipa_runtime_resume,
Alex Elder73ff3162021-08-04 10:36:24 -0500473};