aboutsummaryrefslogtreecommitdiff
path: root/include/linux/msm-bus.h
blob: 5b9a680253f5d772202fe4dd16829190014122b9 (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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/* Copyright (c) 2010-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that 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 _ARCH_ARM_MACH_MSM_BUS_H
#define _ARCH_ARM_MACH_MSM_BUS_H

#include <linux/types.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <soc/qcom/tcs.h>

/*
 * Macros for clients to convert their data to ib and ab
 * Ws : Time window over which to transfer the data in SECONDS
 * Bs : Size of the data block in bytes
 * Per : Recurrence period
 * Tb : Throughput bandwidth to prevent stalling
 * R  : Ratio of actual bandwidth used to Tb
 * Ib : Instantaneous bandwidth
 * Ab : Arbitrated bandwidth
 *
 * IB_RECURRBLOCK and AB_RECURRBLOCK:
 * These are used if the requirement is to transfer a
 * recurring block of data over a known time window.
 *
 * IB_THROUGHPUTBW and AB_THROUGHPUTBW:
 * These are used for CPU style masters. Here the requirement
 * is to have minimum throughput bandwidth available to avoid
 * stalling.
 */
#define IB_RECURRBLOCK(Ws, Bs) ((Ws) == 0 ? 0 : ((Bs)/(Ws)))
#define AB_RECURRBLOCK(Ws, Per) ((Ws) == 0 ? 0 : ((Bs)/(Per)))
#define IB_THROUGHPUTBW(Tb) (Tb)
#define AB_THROUGHPUTBW(Tb, R) ((Tb) * (R))
#define MSM_BUS_MAX_TCS_CMDS 16

struct msm_bus_vectors {
	int src; /* Master */
	int dst; /* Slave */
	uint64_t ab; /* Arbitrated bandwidth */
	uint64_t ib; /* Instantaneous bandwidth */
};

struct msm_bus_paths {
	int num_paths;
	struct msm_bus_vectors *vectors;
};

struct msm_bus_lat_vectors {
	uint64_t fal_ns; /* First Access Latency */
	uint64_t idle_t_ns; /* Idle Time */
};

struct msm_bus_scale_pdata {
	struct msm_bus_paths *usecase;
	struct msm_bus_lat_vectors *usecase_lat;
	int num_usecases;
	const char *name;
	/*
	 * If the active_only flag is set to 1, the BW request is applied
	 * only when at least one CPU is active (powered on). If the flag
	 * is set to 0, then the BW request is always applied irrespective
	 * of the CPU state.
	 */
	unsigned int active_only;
	/*
	 * If the ALC(Active Latency Client) flag is set to 1,
	 * use lat_usecases for latency voting.
	 */
	unsigned int alc;
};

struct msm_bus_client_handle {
	char *name;
	int mas;
	int slv;
	int first_hop;
	struct device *mas_dev;
	u64 cur_act_ib;
	u64 cur_act_ab;
	u64 cur_dual_ib;
	u64 cur_dual_ab;
	bool active_only;
};

struct msm_bus_tcs_usecase {
	int num_cmds;
	struct tcs_cmd cmds[MSM_BUS_MAX_TCS_CMDS];
};

struct msm_bus_tcs_handle {
	int num_usecases;
	struct msm_bus_tcs_usecase *usecases;
};

/* Scaling APIs */

/*
 * This function returns a handle to the client. This should be used to
 * call msm_bus_scale_client_update_request.
 * The function returns 0 if bus driver is unable to register a client
 */

#if (defined(CONFIG_QCOM_BUS_SCALING) ||\
	defined(CONFIG_QCOM_BUS_TOPOLOGY_ADHOC))
int __init msm_bus_fabric_init_driver(void);
uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata);
int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index);
void msm_bus_scale_unregister_client(uint32_t cl);
int msm_bus_scale_client_update_context(uint32_t cl, bool active_only,
							unsigned int ctx_idx);

struct msm_bus_client_handle*
msm_bus_scale_register(uint32_t mas, uint32_t slv, char *name,
							bool active_only);
void msm_bus_scale_unregister(struct msm_bus_client_handle *cl);
int msm_bus_scale_update_bw(struct msm_bus_client_handle *cl, u64 ab, u64 ib);
int msm_bus_scale_update_bw_context(struct msm_bus_client_handle *cl,
		u64 act_ab, u64 act_ib, u64 dual_ib, u64 dual_ab);
int msm_bus_scale_query_tcs_cmd(struct msm_bus_tcs_usecase *tcs_usecase,
					uint32_t cl, unsigned int index);
int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle *tcs_handle,
					uint32_t cl);

/* AXI Port configuration APIs */
int msm_bus_axi_porthalt(int master_port);
int msm_bus_axi_portunhalt(int master_port);

#else
static inline int __init msm_bus_fabric_init_driver(void) { return 0; }
static struct msm_bus_client_handle dummy_cl;

static inline uint32_t
msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata)
{
	return 1;
}

static inline int
msm_bus_scale_client_update_request(uint32_t cl, unsigned int index)
{
	return 0;
}

static inline int
msm_bus_scale_client_update_context(uint32_t cl, bool active_only,
							unsigned int ctx_idx)
{
	return 0;
}

static inline void
msm_bus_scale_unregister_client(uint32_t cl)
{
}

static inline int msm_bus_axi_porthalt(int master_port)
{
	return 0;
}

static inline int msm_bus_axi_portunhalt(int master_port)
{
	return 0;
}

static inline struct msm_bus_client_handle*
msm_bus_scale_register(uint32_t mas, uint32_t slv, char *name,
							bool active_only)
{
	return &dummy_cl;
}

static inline void msm_bus_scale_unregister(struct msm_bus_client_handle *cl)
{
}

static inline int
msm_bus_scale_update_bw(struct msm_bus_client_handle *cl, u64 ab, u64 ib)
{
	return 0;
}

static inline int
msm_bus_scale_update_bw_context(struct msm_bus_client_handle *cl, u64 act_ab,
				u64 act_ib, u64 dual_ib, u64 dual_ab)

{
	return 0;
}

static inline int msm_bus_scale_query_tcs_cmd(struct msm_bus_tcs_usecase
						*tcs_usecase, uint32_t cl,
						unsigned int index)
{
	return 0;
}

static inline int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle
						*tcs_handle, uint32_t cl)
{
	return 0;
}

#endif

#if defined(CONFIG_OF) && defined(CONFIG_QCOM_BUS_SCALING)
struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
		struct platform_device *pdev, struct device_node *of_node);
struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
struct msm_bus_scale_pdata *msm_bus_cl_get_pdata_from_dev(struct device *dev);
void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
#else
static inline struct msm_bus_scale_pdata
*msm_bus_cl_get_pdata(struct platform_device *pdev)
{
	return NULL;
}

static inline struct msm_bus_scale_pdata
*msm_bus_cl_get_pdata_from_dev(struct device *dev)
{
	return NULL;
}

static inline struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
		struct platform_device *pdev, struct device_node *of_node)
{
	return NULL;
}

static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
{
}
#endif

#ifdef CONFIG_DEBUG_BUS_VOTER
int msm_bus_floor_vote_context(const char *name, u64 floor_hz,
						bool active_only);
int msm_bus_floor_vote(const char *name, u64 floor_hz);
#else
static inline int msm_bus_floor_vote(const char *name, u64 floor_hz)
{
	return -EINVAL;
}

static inline int msm_bus_floor_vote_context(const char *name, u64 floor_hz,
						bool active_only)
{
	return -EINVAL;
}
#endif /*defined(CONFIG_DEBUG_BUS_VOTER) && defined(CONFIG_BUS_TOPOLOGY_ADHOC)*/
#endif /*_ARCH_ARM_MACH_MSM_BUS_H*/