1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020-21 Intel Corporation.
6 #include <linux/pm_runtime.h>
8 #include "iosm_ipc_chnl_cfg.h"
9 #include "iosm_ipc_imem_ops.h"
10 #include "iosm_ipc_port.h"
12 /* open logical channel for control communication */
13 static int ipc_port_ctrl_start(struct wwan_port *port)
15 struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
18 pm_runtime_get_sync(ipc_port->ipc_imem->dev);
19 ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem,
22 if (!ipc_port->channel)
25 pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
26 pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
31 /* close logical channel */
32 static void ipc_port_ctrl_stop(struct wwan_port *port)
34 struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
36 pm_runtime_get_sync(ipc_port->ipc_imem->dev);
37 ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel);
38 pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
39 pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
42 /* transfer control data to modem */
43 static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)
45 struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port);
48 pm_runtime_get_sync(ipc_port->ipc_imem->dev);
49 ret = ipc_imem_sys_cdev_write(ipc_port, skb);
50 pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev);
51 pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev);
56 static const struct wwan_port_ops ipc_wwan_ctrl_ops = {
57 .start = ipc_port_ctrl_start,
58 .stop = ipc_port_ctrl_stop,
59 .tx = ipc_port_ctrl_tx,
63 struct iosm_cdev *ipc_port_init(struct iosm_imem *ipc_imem,
64 struct ipc_chnl_cfg ipc_port_cfg)
66 struct iosm_cdev *ipc_port = kzalloc(sizeof(*ipc_port), GFP_KERNEL);
67 enum wwan_port_type port_type = ipc_port_cfg.wwan_port_type;
68 enum ipc_channel_id chl_id = ipc_port_cfg.id;
73 ipc_port->dev = ipc_imem->dev;
74 ipc_port->pcie = ipc_imem->pcie;
76 ipc_port->port_type = port_type;
77 ipc_port->chl_id = chl_id;
78 ipc_port->ipc_imem = ipc_imem;
80 ipc_port->iosm_port = wwan_create_port(ipc_port->dev, port_type,
81 &ipc_wwan_ctrl_ops, NULL,
87 /* Port deinit func */
88 void ipc_port_deinit(struct iosm_cdev *port[])
90 struct iosm_cdev *ipc_port;
93 for (ctrl_chl_nr = 0; ctrl_chl_nr < IPC_MEM_MAX_CHANNELS;
95 if (port[ctrl_chl_nr]) {
96 ipc_port = port[ctrl_chl_nr];
97 wwan_remove_port(ipc_port->iosm_port);