162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * GNSS receiver support
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2018 Johan Hovold <johan@kernel.org>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef _LINUX_GNSS_H
962306a36Sopenharmony_ci#define _LINUX_GNSS_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/cdev.h>
1262306a36Sopenharmony_ci#include <linux/device.h>
1362306a36Sopenharmony_ci#include <linux/kfifo.h>
1462306a36Sopenharmony_ci#include <linux/mutex.h>
1562306a36Sopenharmony_ci#include <linux/rwsem.h>
1662306a36Sopenharmony_ci#include <linux/types.h>
1762306a36Sopenharmony_ci#include <linux/wait.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cistruct gnss_device;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cienum gnss_type {
2262306a36Sopenharmony_ci	GNSS_TYPE_NMEA = 0,
2362306a36Sopenharmony_ci	GNSS_TYPE_SIRF,
2462306a36Sopenharmony_ci	GNSS_TYPE_UBX,
2562306a36Sopenharmony_ci	GNSS_TYPE_MTK,
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	GNSS_TYPE_COUNT
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct gnss_operations {
3162306a36Sopenharmony_ci	int (*open)(struct gnss_device *gdev);
3262306a36Sopenharmony_ci	void (*close)(struct gnss_device *gdev);
3362306a36Sopenharmony_ci	int (*write_raw)(struct gnss_device *gdev, const unsigned char *buf,
3462306a36Sopenharmony_ci				size_t count);
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistruct gnss_device {
3862306a36Sopenharmony_ci	struct device dev;
3962306a36Sopenharmony_ci	struct cdev cdev;
4062306a36Sopenharmony_ci	int id;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	enum gnss_type type;
4362306a36Sopenharmony_ci	unsigned long flags;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	struct rw_semaphore rwsem;
4662306a36Sopenharmony_ci	const struct gnss_operations *ops;
4762306a36Sopenharmony_ci	unsigned int count;
4862306a36Sopenharmony_ci	unsigned int disconnected:1;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	struct mutex read_mutex;
5162306a36Sopenharmony_ci	struct kfifo read_fifo;
5262306a36Sopenharmony_ci	wait_queue_head_t read_queue;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	struct mutex write_mutex;
5562306a36Sopenharmony_ci	char *write_buf;
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct gnss_device *gnss_allocate_device(struct device *parent);
5962306a36Sopenharmony_civoid gnss_put_device(struct gnss_device *gdev);
6062306a36Sopenharmony_ciint gnss_register_device(struct gnss_device *gdev);
6162306a36Sopenharmony_civoid gnss_deregister_device(struct gnss_device *gdev);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciint gnss_insert_raw(struct gnss_device *gdev, const unsigned char *buf,
6462306a36Sopenharmony_ci			size_t count);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic inline void gnss_set_drvdata(struct gnss_device *gdev, void *data)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	dev_set_drvdata(&gdev->dev, data);
6962306a36Sopenharmony_ci}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic inline void *gnss_get_drvdata(struct gnss_device *gdev)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	return dev_get_drvdata(&gdev->dev);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci#endif /* _LINUX_GNSS_H */
77