// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016, Linaro Ltd. * Copyright (c) 2015, Sony Mobile Communications Inc. */ #include <linux/cleanup.h> #include <linux/firmware.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/rpmsg.h> #include <linux/soc/qcom/wcnss_ctrl.h> #define WCNSS_REQUEST_TIMEOUT … #define WCNSS_CBC_TIMEOUT … #define WCNSS_ACK_DONE_BOOTING … #define WCNSS_ACK_COLD_BOOTING … #define NV_FRAGMENT_SIZE … #define NVBIN_FILE … /** * struct wcnss_ctrl - driver context * @dev: device handle * @channel: SMD channel handle * @ack: completion for outstanding requests * @cbc: completion for cbc complete indication * @ack_status: status of the outstanding request * @probe_work: worker for uploading nv binary */ struct wcnss_ctrl { … }; /* message types */ enum { … }; /** * struct wcnss_msg_hdr - common packet header for requests and responses * @type: packet message type * @len: total length of the packet, including this header */ struct wcnss_msg_hdr { … } __packed; /* * struct wcnss_version_resp - version request response */ struct wcnss_version_resp { … } __packed; /** * struct wcnss_download_nv_req - firmware fragment request * @hdr: common packet wcnss_msg_hdr header * @seq: sequence number of this fragment * @last: boolean indicator of this being the last fragment of the binary * @frag_size: length of this fragment * @fragment: fragment data */ struct wcnss_download_nv_req { … } __packed; /** * struct wcnss_download_nv_resp - firmware download response * @hdr: common packet wcnss_msg_hdr header * @status: boolean to indicate success of the download */ struct wcnss_download_nv_resp { … } __packed; /** * wcnss_ctrl_smd_callback() - handler from SMD responses * @rpdev: remote processor message device pointer * @data: pointer to the incoming data packet * @count: size of the incoming data packet * @priv: unused * @addr: unused * * Handles any incoming packets from the remote WCNSS_CTRL service. */ static int wcnss_ctrl_smd_callback(struct rpmsg_device *rpdev, void *data, int count, void *priv, u32 addr) { … } /** * wcnss_request_version() - send a version request to WCNSS * @wcnss: wcnss ctrl driver context */ static int wcnss_request_version(struct wcnss_ctrl *wcnss) { … } /** * wcnss_download_nv() - send nv binary to WCNSS * @wcnss: wcnss_ctrl state handle * @expect_cbc: indicator to caller that an cbc event is expected * * Returns 0 on success. Negative errno on failure. */ static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc) { … } /** * qcom_wcnss_open_channel() - open additional SMD channel to WCNSS * @wcnss: wcnss handle, retrieved from drvdata * @name: SMD channel name * @cb: callback to handle incoming data on the channel * @priv: private data for use in the call-back */ struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name, rpmsg_rx_cb_t cb, void *priv) { … } EXPORT_SYMBOL_GPL(…); static void wcnss_async_probe(struct work_struct *work) { … } static int wcnss_ctrl_probe(struct rpmsg_device *rpdev) { … } static void wcnss_ctrl_remove(struct rpmsg_device *rpdev) { … } static const struct of_device_id wcnss_ctrl_of_match[] = …; MODULE_DEVICE_TABLE(of, wcnss_ctrl_of_match); static struct rpmsg_driver wcnss_ctrl_driver = …; module_rpmsg_driver(…) …; MODULE_DESCRIPTION(…) …; MODULE_LICENSE(…) …;