blob: b47c4a7c2da403ed3d249930c6730f69eadcb8a5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2023-2026 Intel Corporation */
#ifndef _ISSEI_DEV_H_
#define _ISSEI_DEV_H_
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/time64.h>
#include <linux/types.h>
#include <linux/wait.h>
#include "dma.h"
struct cdev;
struct kset;
struct issei_device;
struct issei_host_client;
extern struct class *issei_class;
#define ISSEI_HOST_CLIENTS_MAX 255
#define ISSEI_SUPPORTED_PROTOCOL_VER 1
#define ISSEI_MAX_CONSEC_RESET 3
#define ISSEI_RST_HW_READY_TIMEOUT_MSEC (2 * MSEC_PER_SEC)
#define ISSEI_RST_STEP_TIMEOUT_MSEC (2 * MSEC_PER_SEC)
#define ISSEI_STOP_TIMEOUT_MSEC 500
#define ISSEI_WRITE_TIMEOUT_MSEC (MSEC_PER_SEC)
/**
* struct issei_write_buf - write buffer object
* @list: linked list pointer
* @cl: host client that requested this write
* @data: data to write
* @data_size: data size
*/
struct issei_write_buf {
struct list_head list;
struct issei_host_client *cl;
const u8 *data;
size_t data_size;
};
/**
* struct issei_hw_ops - callbacks for hardware operations
* @irq_clear: clear irq
* @irq_enable: enable irq
* @irq_disable: disable irq
* @irq_sync: sync irq
* @hw_reset: initiate hardware reset
* @hw_config: initial hardware config
* @hw_is_ready: check if hardware is ready
* @hw_reset_release: release hardware from reset
* @host_set_ready: set host ready indicator
* @setup_message_send: send setup message
* @setup_message_recv: receive setup message
* @irq_write_generate: generate interrupt on write complete
*/
struct issei_hw_ops {
void (*irq_clear)(struct issei_device *idev);
void (*irq_enable)(struct issei_device *idev);
void (*irq_disable)(struct issei_device *idev);
void (*irq_sync)(struct issei_device *idev);
int (*hw_reset)(struct issei_device *idev, bool enable);
int (*hw_config)(struct issei_device *idev);
bool (*hw_is_ready)(struct issei_device *idev);
void (*hw_reset_release)(struct issei_device *idev);
void (*host_set_ready)(struct issei_device *idev);
int (*setup_message_send)(struct issei_device *idev);
int (*setup_message_recv)(struct issei_device *idev);
int (*irq_write_generate)(struct issei_device *idev);
};
/**
* enum issei_rst_state: driver reset flow states
* @ISSEI_RST_STATE_INIT: initial state
* @ISSEI_RST_STATE_HW_READY: waiting for HW to be ready
* @ISSEI_RST_STATE_SETUP: waiting for channel setup completion
* @ISSEI_RST_STATE_START: waiting for start handshake completion
* @ISSEI_RST_STATE_CLIENT_ENUM: waiting for client enumeration
* @ISSEI_RST_STATE_DONE: reset flow is done
* @ISSEI_RST_STATE_DISABLED: flow is disabled
*/
enum issei_rst_state {
ISSEI_RST_STATE_INIT,
ISSEI_RST_STATE_HW_READY,
ISSEI_RST_STATE_SETUP,
ISSEI_RST_STATE_START,
ISSEI_RST_STATE_CLIENT_ENUM,
ISSEI_RST_STATE_DONE,
ISSEI_RST_STATE_DISABLED,
};
/**
* struct issei_device - issei device
* @parent: parent device object
* @dev: associated device object
* @cdev: character device
* @minor: allocated minor number
* @wait_has_data: wait queue for data
* @has_data: there are data to process
* @power_down: device is powering down
* @wait_rst_state: waitqueue for reset state processing
* @rst_state: reset state
* @fw_protocol_ver: protocol version
* @fw_version: firmware version
* @process_thread: worker thread
* @reset_count: number of consecutive link reset attempts
* @all_reset_count: cumilative number of link reset attempts
* @client_lock: mutex to protect client lists and write queue
* @host_client_list: host clients list
* @host_client_last_id: last allocated host client id
* @host_client_count: number of active host clients
* @fw_client_list: firmware clients list
* @write_queue: write queue
* @last_write_ts: last write timestamp
* @dma: DMA memory configuration
* @ops: hardware operations
* @hw: hw-specific data
*/
struct issei_device {
struct device *parent;
struct device dev;
struct cdev *cdev;
u32 minor;
wait_queue_head_t wait_has_data;
bool has_data;
bool power_down;
wait_queue_head_t wait_rst_state;
enum issei_rst_state rst_state;
u16 fw_protocol_ver;
u16 fw_version[4];
/* reset flow */
struct task_struct *process_thread;
u8 reset_count;
u8 all_reset_count;
/* clients */
struct mutex client_lock;
struct list_head host_client_list;
u16 host_client_last_id;
u8 host_client_count;
struct kset *fw_clients;
struct list_head fw_client_list;
struct list_head write_queue;
ktime_t last_write_ts;
struct issei_dma dma;
const struct issei_hw_ops *ops;
char hw[];
};
static inline void issei_poke_process_thread(struct issei_device *idev)
{
WRITE_ONCE(idev->has_data, true);
wake_up_interruptible(&idev->wait_has_data);
}
int issei_start(struct issei_device *idev);
void issei_stop(struct issei_device *idev);
#endif /* _ISSEI_DEV_H_ */
|