162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Greybus connections
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2014 Google Inc.
662306a36Sopenharmony_ci * Copyright 2014 Linaro Ltd.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __CONNECTION_H
1062306a36Sopenharmony_ci#define __CONNECTION_H
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/bits.h>
1362306a36Sopenharmony_ci#include <linux/list.h>
1462306a36Sopenharmony_ci#include <linux/kfifo.h>
1562306a36Sopenharmony_ci#include <linux/kref.h>
1662306a36Sopenharmony_ci#include <linux/workqueue.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_CSD		BIT(0)
1962306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_NO_FLOWCTRL	BIT(1)
2062306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_OFFLOADED	BIT(2)
2162306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_CDSI1	BIT(3)
2262306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_CONTROL	BIT(4)
2362306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_HIGH_PRIO	BIT(5)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define GB_CONNECTION_FLAG_CORE_MASK	GB_CONNECTION_FLAG_CONTROL
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cienum gb_connection_state {
2862306a36Sopenharmony_ci	GB_CONNECTION_STATE_DISABLED		= 0,
2962306a36Sopenharmony_ci	GB_CONNECTION_STATE_ENABLED_TX		= 1,
3062306a36Sopenharmony_ci	GB_CONNECTION_STATE_ENABLED		= 2,
3162306a36Sopenharmony_ci	GB_CONNECTION_STATE_DISCONNECTING	= 3,
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct gb_operation;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_citypedef int (*gb_request_handler_t)(struct gb_operation *);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct gb_connection {
3962306a36Sopenharmony_ci	struct gb_host_device		*hd;
4062306a36Sopenharmony_ci	struct gb_interface		*intf;
4162306a36Sopenharmony_ci	struct gb_bundle		*bundle;
4262306a36Sopenharmony_ci	struct kref			kref;
4362306a36Sopenharmony_ci	u16				hd_cport_id;
4462306a36Sopenharmony_ci	u16				intf_cport_id;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	struct list_head		hd_links;
4762306a36Sopenharmony_ci	struct list_head		bundle_links;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	gb_request_handler_t		handler;
5062306a36Sopenharmony_ci	unsigned long			flags;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	struct mutex			mutex;
5362306a36Sopenharmony_ci	spinlock_t			lock;
5462306a36Sopenharmony_ci	enum gb_connection_state	state;
5562306a36Sopenharmony_ci	struct list_head		operations;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	char				name[16];
5862306a36Sopenharmony_ci	struct workqueue_struct		*wq;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	atomic_t			op_cycle;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	void				*private;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	bool				mode_switch;
6562306a36Sopenharmony_ci};
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistruct gb_connection *gb_connection_create_static(struct gb_host_device *hd,
6862306a36Sopenharmony_ci				u16 hd_cport_id, gb_request_handler_t handler);
6962306a36Sopenharmony_cistruct gb_connection *gb_connection_create_control(struct gb_interface *intf);
7062306a36Sopenharmony_cistruct gb_connection *gb_connection_create(struct gb_bundle *bundle,
7162306a36Sopenharmony_ci				u16 cport_id, gb_request_handler_t handler);
7262306a36Sopenharmony_cistruct gb_connection *gb_connection_create_flags(struct gb_bundle *bundle,
7362306a36Sopenharmony_ci				u16 cport_id, gb_request_handler_t handler,
7462306a36Sopenharmony_ci				unsigned long flags);
7562306a36Sopenharmony_cistruct gb_connection *gb_connection_create_offloaded(struct gb_bundle *bundle,
7662306a36Sopenharmony_ci				u16 cport_id, unsigned long flags);
7762306a36Sopenharmony_civoid gb_connection_destroy(struct gb_connection *connection);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistatic inline bool gb_connection_is_static(struct gb_connection *connection)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	return !connection->intf;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciint gb_connection_enable(struct gb_connection *connection);
8562306a36Sopenharmony_ciint gb_connection_enable_tx(struct gb_connection *connection);
8662306a36Sopenharmony_civoid gb_connection_disable_rx(struct gb_connection *connection);
8762306a36Sopenharmony_civoid gb_connection_disable(struct gb_connection *connection);
8862306a36Sopenharmony_civoid gb_connection_disable_forced(struct gb_connection *connection);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_civoid gb_connection_mode_switch_prepare(struct gb_connection *connection);
9162306a36Sopenharmony_civoid gb_connection_mode_switch_complete(struct gb_connection *connection);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_civoid greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
9462306a36Sopenharmony_ci		       u8 *data, size_t length);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_civoid gb_connection_latency_tag_enable(struct gb_connection *connection);
9762306a36Sopenharmony_civoid gb_connection_latency_tag_disable(struct gb_connection *connection);
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline bool gb_connection_e2efc_enabled(struct gb_connection *connection)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	return !(connection->flags & GB_CONNECTION_FLAG_CSD);
10262306a36Sopenharmony_ci}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic inline bool
10562306a36Sopenharmony_cigb_connection_flow_control_disabled(struct gb_connection *connection)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	return connection->flags & GB_CONNECTION_FLAG_NO_FLOWCTRL;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic inline bool gb_connection_is_offloaded(struct gb_connection *connection)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	return connection->flags & GB_CONNECTION_FLAG_OFFLOADED;
11362306a36Sopenharmony_ci}
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic inline bool gb_connection_is_control(struct gb_connection *connection)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	return connection->flags & GB_CONNECTION_FLAG_CONTROL;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic inline void *gb_connection_get_data(struct gb_connection *connection)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	return connection->private;
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline void gb_connection_set_data(struct gb_connection *connection,
12662306a36Sopenharmony_ci					  void *data)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	connection->private = data;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#endif /* __CONNECTION_H */
132