#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/math64.h>
#include <linux/mhi.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/time64.h>
#include <linux/timer.h>
#include "qaic.h"
#include "qaic_timesync.h"
#define QTIMER_REG_OFFSET …
#define QAIC_TIMESYNC_SIGNATURE …
#define QAIC_CONV_QTIMER_TO_US(qtimer) …
static unsigned int timesync_delay_ms = …;
module_param(timesync_delay_ms, uint, 0600);
MODULE_PARM_DESC(…) …;
enum qts_msg_type { … };
struct qts_hdr { … } __packed;
struct qts_timeval { … } __packed;
struct qts_host_time_sync_msg_data { … } __packed;
struct mqts_dev { … };
struct qts_resp_msg { … } __packed;
struct qts_resp { … };
#ifdef readq
static u64 read_qtimer(const volatile void __iomem *addr)
{ … }
#else
static u64 read_qtimer(const volatile void __iomem *addr)
{
u64 low, high;
low = readl(addr);
high = readl(addr + sizeof(u32));
return low | (high << 32);
}
#endif
static void qaic_timesync_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
{ … }
static void qaic_timesync_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
{ … }
static void qaic_timesync_timer(struct timer_list *t)
{ … }
static int qaic_timesync_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
{
struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev));
struct mqts_dev *mqtsdev;
struct timer_list *timer;
int ret;
mqtsdev = kzalloc(sizeof(*mqtsdev), GFP_KERNEL);
if (!mqtsdev) {
ret = -ENOMEM;
goto out;
}
timer = &mqtsdev->timer;
mqtsdev->mhi_dev = mhi_dev;
mqtsdev->qdev = qdev;
mqtsdev->dev = &qdev->pdev->dev;
mqtsdev->sync_msg = kzalloc(sizeof(*mqtsdev->sync_msg), GFP_KERNEL);
if (!mqtsdev->sync_msg) {
ret = -ENOMEM;
goto free_mqts_dev;
}
atomic_set(&mqtsdev->buff_in_use, 0);
ret = mhi_prepare_for_transfer(mhi_dev);
if (ret)
goto free_sync_msg;
mqtsdev->qtimer_addr = qdev->bar_0 + QTIMER_REG_OFFSET;
timer_setup(timer, qaic_timesync_timer, 0);
timer->expires = jiffies + msecs_to_jiffies(timesync_delay_ms);
add_timer(timer);
dev_set_drvdata(&mhi_dev->dev, mqtsdev);
return 0;
free_sync_msg:
kfree(mqtsdev->sync_msg);
free_mqts_dev:
kfree(mqtsdev);
out:
return ret;
};
static void qaic_timesync_remove(struct mhi_device *mhi_dev)
{ … }
static const struct mhi_device_id qaic_timesync_match_table[] = …;
MODULE_DEVICE_TABLE(mhi, qaic_timesync_match_table);
static struct mhi_driver qaic_timesync_driver = …;
static void qaic_boot_timesync_worker(struct work_struct *work)
{ … }
static int qaic_boot_timesync_queue_resp(struct mhi_device *mhi_dev, struct qaic_device *qdev)
{ … }
static void qaic_boot_timesync_remove(struct mhi_device *mhi_dev)
{ … }
static int qaic_boot_timesync_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id)
{ … }
static void qaic_boot_timesync_ul_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
{ … }
static void qaic_boot_timesync_dl_xfer_cb(struct mhi_device *mhi_dev, struct mhi_result *mhi_result)
{ … }
static const struct mhi_device_id qaic_boot_timesync_match_table[] = …;
static struct mhi_driver qaic_boot_timesync_driver = …;
int qaic_timesync_init(void)
{ … }
void qaic_timesync_deinit(void)
{ … }