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
164
|
/*
* Copyright (c) 2015-2017 NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#ifndef _LINUX_TEGRA_IVC_BUS_H
#define _LINUX_TEGRA_IVC_BUS_H
#include <linux/tegra-ivc-instance.h>
#include <linux/types.h>
extern struct bus_type tegra_ivc_bus_type;
struct tegra_ivc_bus;
struct tegra_hsp_ops;
struct tegra_ivc_rpc_data;
struct tegra_ivc_bus *tegra_ivc_bus_create(struct device *);
void tegra_ivc_bus_ready(struct tegra_ivc_bus *bus, bool online);
void tegra_ivc_bus_destroy(struct tegra_ivc_bus *bus);
int tegra_ivc_bus_boot_sync(struct tegra_ivc_bus *bus);
struct tegra_ivc_driver {
struct device_driver driver;
struct device_type *dev_type;
union {
const struct tegra_hsp_ops *hsp;
const struct tegra_ivc_channel_ops *channel;
} ops;
};
static inline struct tegra_ivc_driver *to_tegra_ivc_driver(
struct device_driver *drv)
{
if (drv == NULL)
return NULL;
return container_of(drv, struct tegra_ivc_driver, driver);
}
int tegra_ivc_driver_register(struct tegra_ivc_driver *drv);
void tegra_ivc_driver_unregister(struct tegra_ivc_driver *drv);
#define tegra_ivc_module_driver(drv) \
module_driver(drv, tegra_ivc_driver_register, \
tegra_ivc_driver_unregister)
#define tegra_ivc_subsys_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
return __register(&(__driver) , ##__VA_ARGS__); \
} \
subsys_initcall_sync(__driver##_init);
#define tegra_ivc_subsys_driver_default(__driver) \
tegra_ivc_subsys_driver(__driver, \
tegra_ivc_driver_register, \
tegra_ivc_driver_unregister)
/* Tegra HSP driver support */
extern struct device_type tegra_hsp_type;
struct tegra_hsp_ops {
int (*probe)(struct device *);
void (*remove)(struct device *);
void (*ring)(struct device *);
};
void tegra_hsp_notify(struct device *);
static inline const struct tegra_hsp_ops *tegra_hsp_dev_ops(struct device *dev)
{
struct tegra_ivc_driver *drv = to_tegra_ivc_driver(dev->driver);
const struct tegra_hsp_ops *ops = NULL;
if (drv != NULL && drv->dev_type == &tegra_hsp_type)
ops = drv->ops.hsp;
return ops;
}
/* IVC channel driver support */
extern struct device_type tegra_ivc_channel_type;
struct tegra_ivc_channel {
struct ivc ivc;
struct device dev;
const struct tegra_ivc_channel_ops __rcu *ops;
struct tegra_ivc_channel *next;
struct mutex ivc_wr_lock;
struct tegra_ivc_rpc_data *rpc_priv;
atomic_t bus_resets;
bool is_ready;
};
static inline bool tegra_ivc_channel_online_check(
struct tegra_ivc_channel *chan)
{
atomic_set(&chan->bus_resets, 0);
smp_wmb();
smp_rmb();
return chan->is_ready;
}
static inline bool tegra_ivc_channel_has_been_reset(
struct tegra_ivc_channel *chan)
{
smp_rmb();
return atomic_read(&chan->bus_resets) != 0;
}
static inline void *tegra_ivc_channel_get_drvdata(
struct tegra_ivc_channel *chan)
{
return dev_get_drvdata(&chan->dev);
}
static inline void tegra_ivc_channel_set_drvdata(
struct tegra_ivc_channel *chan, void *data)
{
dev_set_drvdata(&chan->dev, data);
}
static inline struct tegra_ivc_channel *to_tegra_ivc_channel(
struct device *dev)
{
return container_of(dev, struct tegra_ivc_channel, dev);
}
static inline struct device *tegra_ivc_channel_to_camrtc_dev(
struct tegra_ivc_channel *ch)
{
if (unlikely(ch == NULL))
return NULL;
BUG_ON(ch->dev.parent == NULL);
BUG_ON(ch->dev.parent->parent == NULL);
return ch->dev.parent->parent;
}
int tegra_ivc_channel_runtime_get(struct tegra_ivc_channel *chan);
void tegra_ivc_channel_runtime_put(struct tegra_ivc_channel *chan);
struct tegra_ivc_channel_ops {
int (*probe)(struct tegra_ivc_channel *);
void (*ready)(struct tegra_ivc_channel *, bool online);
void (*remove)(struct tegra_ivc_channel *);
void (*notify)(struct tegra_ivc_channel *);
};
/* Legacy mailbox support */
struct tegra_ivc_mbox_msg {
int length;
void *data;
};
#endif
|