1// SPDX-License-Identifier: GPL-2.0
2/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. */
3
4#include <linux/err.h>
5#include <linux/init.h>
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/mutex.h>
9#include <linux/pm_domain.h>
10#include <linux/of.h>
11#include <linux/platform_device.h>
12#include <linux/pm_opp.h>
13#include <linux/soc/qcom/smd-rpm.h>
14
15#include <dt-bindings/power/qcom-rpmpd.h>
16
17#define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd)
18
19/* Resource types:
20 * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */
21#define RPMPD_SMPA 0x61706d73
22#define RPMPD_LDOA 0x616f646c
23#define RPMPD_SMPB 0x62706d73
24#define RPMPD_LDOB 0x626f646c
25#define RPMPD_RWCX 0x78637772
26#define RPMPD_RWMX 0x786d7772
27#define RPMPD_RWLC 0x636c7772
28#define RPMPD_RWLM 0x6d6c7772
29#define RPMPD_RWSC 0x63737772
30#define RPMPD_RWSM 0x6d737772
31#define RPMPD_RWGX 0x78677772
32
33/* Operation Keys */
34#define KEY_CORNER		0x6e726f63 /* corn */
35#define KEY_ENABLE		0x6e657773 /* swen */
36#define KEY_FLOOR_CORNER	0x636676   /* vfc */
37#define KEY_FLOOR_LEVEL		0x6c6676   /* vfl */
38#define KEY_LEVEL		0x6c766c76 /* vlvl */
39
40#define MAX_CORNER_RPMPD_STATE	6
41
42struct rpmpd_req {
43	__le32 key;
44	__le32 nbytes;
45	__le32 value;
46};
47
48struct rpmpd {
49	struct generic_pm_domain pd;
50	struct generic_pm_domain *parent;
51	struct rpmpd *peer;
52	const bool active_only;
53	unsigned int corner;
54	bool enabled;
55	const int res_type;
56	const int res_id;
57	struct qcom_smd_rpm *rpm;
58	unsigned int max_state;
59	__le32 key;
60	bool state_synced;
61};
62
63struct rpmpd_desc {
64	struct rpmpd **rpmpds;
65	size_t num_pds;
66	unsigned int max_state;
67};
68
69static DEFINE_MUTEX(rpmpd_lock);
70
71/* CX */
72static struct rpmpd cx_rwcx0_lvl_ao;
73static struct rpmpd cx_rwcx0_lvl = {
74	.pd = { .name = "cx", },
75	.peer = &cx_rwcx0_lvl_ao,
76	.res_type = RPMPD_RWCX,
77	.res_id = 0,
78	.key = KEY_LEVEL,
79};
80
81static struct rpmpd cx_rwcx0_lvl_ao = {
82	.pd = { .name = "cx_ao", },
83	.peer = &cx_rwcx0_lvl,
84	.active_only = true,
85	.res_type = RPMPD_RWCX,
86	.res_id = 0,
87	.key = KEY_LEVEL,
88};
89
90static struct rpmpd cx_s1a_corner_ao;
91static struct rpmpd cx_s1a_corner = {
92	.pd = { .name = "cx", },
93	.peer = &cx_s1a_corner_ao,
94	.res_type = RPMPD_SMPA,
95	.res_id = 1,
96	.key = KEY_CORNER,
97};
98
99static struct rpmpd cx_s1a_corner_ao = {
100	.pd = { .name = "cx_ao", },
101	.peer = &cx_s1a_corner,
102	.active_only = true,
103	.res_type = RPMPD_SMPA,
104	.res_id = 1,
105	.key = KEY_CORNER,
106};
107
108static struct rpmpd cx_s2a_corner_ao;
109static struct rpmpd cx_s2a_corner = {
110	.pd = { .name = "cx", },
111	.peer = &cx_s2a_corner_ao,
112	.res_type = RPMPD_SMPA,
113	.res_id = 2,
114	.key = KEY_CORNER,
115};
116
117static struct rpmpd cx_s2a_corner_ao = {
118	.pd = { .name = "cx_ao", },
119	.peer = &cx_s2a_corner,
120	.active_only = true,
121	.res_type = RPMPD_SMPA,
122	.res_id = 2,
123	.key = KEY_CORNER,
124};
125
126static struct rpmpd cx_s2a_lvl_ao;
127static struct rpmpd cx_s2a_lvl = {
128	.pd = { .name = "cx", },
129	.peer = &cx_s2a_lvl_ao,
130	.res_type = RPMPD_SMPA,
131	.res_id = 2,
132	.key = KEY_LEVEL,
133};
134
135static struct rpmpd cx_s2a_lvl_ao = {
136	.pd = { .name = "cx_ao", },
137	.peer = &cx_s2a_lvl,
138	.active_only = true,
139	.res_type = RPMPD_SMPA,
140	.res_id = 2,
141	.key = KEY_LEVEL,
142};
143
144static struct rpmpd cx_s3a_lvl_ao;
145static struct rpmpd cx_s3a_lvl = {
146	.pd = { .name = "cx", },
147	.peer = &cx_s3a_lvl_ao,
148	.res_type = RPMPD_SMPA,
149	.res_id = 3,
150	.key = KEY_LEVEL,
151};
152
153static struct rpmpd cx_s3a_lvl_ao = {
154	.pd = { .name = "cx_ao", },
155	.peer = &cx_s3a_lvl,
156	.active_only = true,
157	.res_type = RPMPD_SMPA,
158	.res_id = 3,
159	.key = KEY_LEVEL,
160};
161
162static struct rpmpd cx_rwcx0_vfl = {
163	.pd = { .name = "cx_vfl", },
164	.res_type = RPMPD_RWCX,
165	.res_id = 0,
166	.key = KEY_FLOOR_LEVEL,
167};
168
169static struct rpmpd cx_rwsc2_vfl = {
170	.pd = { .name = "cx_vfl", },
171	.res_type = RPMPD_RWSC,
172	.res_id = 2,
173	.key = KEY_FLOOR_LEVEL,
174};
175
176static struct rpmpd cx_s1a_vfc = {
177	.pd = { .name = "cx_vfc", },
178	.res_type = RPMPD_SMPA,
179	.res_id = 1,
180	.key = KEY_FLOOR_CORNER,
181};
182
183static struct rpmpd cx_s2a_vfc = {
184	.pd = { .name = "cx_vfc", },
185	.res_type = RPMPD_SMPA,
186	.res_id = 2,
187	.key = KEY_FLOOR_CORNER,
188};
189
190static struct rpmpd cx_s2a_vfl = {
191	.pd = { .name = "cx_vfl", },
192	.res_type = RPMPD_SMPA,
193	.res_id = 2,
194	.key = KEY_FLOOR_LEVEL,
195};
196
197static struct rpmpd cx_s3a_vfl = {
198	.pd = { .name = "cx_vfl", },
199	.res_type = RPMPD_SMPA,
200	.res_id = 3,
201	.key = KEY_FLOOR_LEVEL,
202};
203
204/* G(F)X */
205static struct rpmpd gfx_s2b_corner = {
206	.pd = { .name = "gfx", },
207	.res_type = RPMPD_SMPB,
208	.res_id = 2,
209	.key = KEY_CORNER,
210};
211
212static struct rpmpd gfx_s2b_vfc = {
213	.pd = { .name = "gfx_vfc", },
214	.res_type = RPMPD_SMPB,
215	.res_id = 2,
216	.key = KEY_FLOOR_CORNER,
217};
218
219static struct rpmpd mx_rwmx0_lvl;
220static struct rpmpd gx_rwgx0_lvl_ao;
221static struct rpmpd gx_rwgx0_lvl = {
222	.pd = { .name = "gx", },
223	.peer = &gx_rwgx0_lvl_ao,
224	.res_type = RPMPD_RWGX,
225	.parent = &mx_rwmx0_lvl.pd,
226	.res_id = 0,
227	.key = KEY_LEVEL,
228};
229
230static struct rpmpd mx_rwmx0_lvl_ao;
231static struct rpmpd gx_rwgx0_lvl_ao = {
232	.pd = { .name = "gx_ao", },
233	.peer = &gx_rwgx0_lvl,
234	.parent = &mx_rwmx0_lvl_ao.pd,
235	.active_only = true,
236	.res_type = RPMPD_RWGX,
237	.res_id = 0,
238	.key = KEY_LEVEL,
239};
240
241/* MX */
242static struct rpmpd mx_l3a_corner_ao;
243static struct rpmpd mx_l3a_corner = {
244	.pd = { .name = "mx", },
245	.peer = &mx_l3a_corner_ao,
246	.res_type = RPMPD_LDOA,
247	.res_id = 3,
248	.key = KEY_CORNER,
249};
250
251static struct rpmpd mx_l3a_corner_ao = {
252	.pd = { .name = "mx_ao", },
253	.peer = &mx_l3a_corner,
254	.active_only = true,
255	.res_type = RPMPD_LDOA,
256	.res_id = 3,
257	.key = KEY_CORNER,
258};
259
260static struct rpmpd mx_l12a_lvl_ao;
261static struct rpmpd mx_l12a_lvl = {
262	.pd = { .name = "mx", },
263	.peer = &mx_l12a_lvl_ao,
264	.res_type = RPMPD_LDOA,
265	.res_id = 12,
266	.key = KEY_LEVEL,
267};
268
269static struct rpmpd mx_l12a_lvl_ao = {
270	.pd = { .name = "mx_ao", },
271	.peer = &mx_l12a_lvl,
272	.active_only = true,
273	.res_type = RPMPD_LDOA,
274	.res_id = 12,
275	.key = KEY_LEVEL,
276};
277
278static struct rpmpd mx_s2a_corner_ao;
279static struct rpmpd mx_s2a_corner = {
280	.pd = { .name = "mx", },
281	.peer = &mx_s2a_corner_ao,
282	.res_type = RPMPD_SMPA,
283	.res_id = 2,
284	.key = KEY_CORNER,
285};
286
287static struct rpmpd mx_s2a_corner_ao = {
288	.pd = { .name = "mx_ao", },
289	.peer = &mx_s2a_corner,
290	.active_only = true,
291	.res_type = RPMPD_SMPA,
292	.res_id = 2,
293	.key = KEY_CORNER,
294};
295
296static struct rpmpd mx_rwmx0_lvl_ao;
297static struct rpmpd mx_rwmx0_lvl = {
298	.pd = { .name = "mx", },
299	.peer = &mx_rwmx0_lvl_ao,
300	.res_type = RPMPD_RWMX,
301	.res_id = 0,
302	.key = KEY_LEVEL,
303};
304
305static struct rpmpd mx_rwmx0_lvl_ao = {
306	.pd = { .name = "mx_ao", },
307	.peer = &mx_rwmx0_lvl,
308	.active_only = true,
309	.res_type = RPMPD_RWMX,
310	.res_id = 0,
311	.key = KEY_LEVEL,
312};
313
314static struct rpmpd mx_s6a_lvl_ao;
315static struct rpmpd mx_s6a_lvl = {
316	.pd = { .name = "mx", },
317	.peer = &mx_s6a_lvl_ao,
318	.res_type = RPMPD_SMPA,
319	.res_id = 6,
320	.key = KEY_LEVEL,
321};
322
323static struct rpmpd mx_s6a_lvl_ao = {
324	.pd = { .name = "mx_ao", },
325	.peer = &mx_s6a_lvl,
326	.active_only = true,
327	.res_type = RPMPD_SMPA,
328	.res_id = 6,
329	.key = KEY_LEVEL,
330};
331
332static struct rpmpd mx_s7a_lvl_ao;
333static struct rpmpd mx_s7a_lvl = {
334	.pd = { .name = "mx", },
335	.peer = &mx_s7a_lvl_ao,
336	.res_type = RPMPD_SMPA,
337	.res_id = 7,
338	.key = KEY_LEVEL,
339};
340
341static struct rpmpd mx_s7a_lvl_ao = {
342	.pd = { .name = "mx_ao", },
343	.peer = &mx_s7a_lvl,
344	.active_only = true,
345	.res_type = RPMPD_SMPA,
346	.res_id = 7,
347	.key = KEY_LEVEL,
348};
349
350static struct rpmpd mx_l12a_vfl = {
351	.pd = { .name = "mx_vfl", },
352	.res_type = RPMPD_LDOA,
353	.res_id = 12,
354	.key = KEY_FLOOR_LEVEL,
355};
356
357static struct rpmpd mx_rwmx0_vfl = {
358	.pd = { .name = "mx_vfl", },
359	.res_type = RPMPD_RWMX,
360	.res_id = 0,
361	.key = KEY_FLOOR_LEVEL,
362};
363
364static struct rpmpd mx_rwsm6_vfl = {
365	.pd = { .name = "mx_vfl", },
366	.res_type = RPMPD_RWSM,
367	.res_id = 6,
368	.key = KEY_FLOOR_LEVEL,
369};
370
371/* MD */
372static struct rpmpd md_s1a_corner_ao;
373static struct rpmpd md_s1a_corner = {
374	.pd = { .name = "md", },
375	.peer = &md_s1a_corner_ao,
376	.res_type = RPMPD_SMPA,
377	.res_id = 1,
378	.key = KEY_CORNER,
379};
380
381static struct rpmpd md_s1a_corner_ao = {
382	.pd = { .name = "md_ao", },
383	.peer = &md_s1a_corner,
384	.active_only = true,
385	.res_type = RPMPD_SMPA,
386	.res_id = 1,
387	.key = KEY_CORNER,
388};
389
390static struct rpmpd md_s1a_lvl_ao;
391static struct rpmpd md_s1a_lvl = {
392	.pd = { .name = "md", },
393	.peer = &md_s1a_lvl_ao,
394	.res_type = RPMPD_SMPA,
395	.res_id = 1,
396	.key = KEY_LEVEL,
397};
398
399static struct rpmpd md_s1a_lvl_ao = {
400	.pd = { .name = "md_ao", },
401	.peer = &md_s1a_lvl,
402	.active_only = true,
403	.res_type = RPMPD_SMPA,
404	.res_id = 1,
405	.key = KEY_LEVEL,
406};
407
408static struct rpmpd md_s1a_vfc = {
409	.pd = { .name = "md_vfc", },
410	.res_type = RPMPD_SMPA,
411	.res_id = 1,
412	.key = KEY_FLOOR_CORNER,
413};
414
415/* LPI_CX */
416static struct rpmpd lpi_cx_rwlc0_lvl = {
417	.pd = { .name = "lpi_cx", },
418	.res_type = RPMPD_RWLC,
419	.res_id = 0,
420	.key = KEY_LEVEL,
421};
422
423static struct rpmpd lpi_cx_rwlc0_vfl = {
424	.pd = { .name = "lpi_cx_vfl", },
425	.res_type = RPMPD_RWLC,
426	.res_id = 0,
427	.key = KEY_FLOOR_LEVEL,
428};
429
430/* LPI_MX */
431static struct rpmpd lpi_mx_rwlm0_lvl = {
432	.pd = { .name = "lpi_mx", },
433	.res_type = RPMPD_RWLM,
434	.res_id = 0,
435	.key = KEY_LEVEL,
436};
437
438static struct rpmpd lpi_mx_rwlm0_vfl = {
439	.pd = { .name = "lpi_mx_vfl", },
440	.res_type = RPMPD_RWLM,
441	.res_id = 0,
442	.key = KEY_FLOOR_LEVEL,
443};
444
445/* SSC_CX */
446static struct rpmpd ssc_cx_l26a_corner = {
447	.pd = { .name = "ssc_cx", },
448	.res_type = RPMPD_LDOA,
449	.res_id = 26,
450	.key = KEY_CORNER,
451};
452
453static struct rpmpd ssc_cx_rwlc0_lvl = {
454	.pd = { .name = "ssc_cx", },
455	.res_type = RPMPD_RWLC,
456	.res_id = 0,
457	.key = KEY_LEVEL,
458};
459
460static struct rpmpd ssc_cx_rwsc0_lvl = {
461	.pd = { .name = "ssc_cx", },
462	.res_type = RPMPD_RWSC,
463	.res_id = 0,
464	.key = KEY_LEVEL,
465};
466
467static struct rpmpd ssc_cx_l26a_vfc = {
468	.pd = { .name = "ssc_cx_vfc", },
469	.res_type = RPMPD_LDOA,
470	.res_id = 26,
471	.key = KEY_FLOOR_CORNER,
472};
473
474static struct rpmpd ssc_cx_rwlc0_vfl = {
475	.pd = { .name = "ssc_cx_vfl", },
476	.res_type = RPMPD_RWLC,
477	.res_id = 0,
478	.key = KEY_FLOOR_LEVEL,
479};
480
481static struct rpmpd ssc_cx_rwsc0_vfl = {
482	.pd = { .name = "ssc_cx_vfl", },
483	.res_type = RPMPD_RWSC,
484	.res_id = 0,
485	.key = KEY_FLOOR_LEVEL,
486};
487
488/* SSC_MX */
489static struct rpmpd ssc_mx_rwlm0_lvl = {
490	.pd = { .name = "ssc_mx", },
491	.res_type = RPMPD_RWLM,
492	.res_id = 0,
493	.key = KEY_LEVEL,
494};
495
496static struct rpmpd ssc_mx_rwsm0_lvl = {
497	.pd = { .name = "ssc_mx", },
498	.res_type = RPMPD_RWSM,
499	.res_id = 0,
500	.key = KEY_LEVEL,
501};
502
503static struct rpmpd ssc_mx_rwlm0_vfl = {
504	.pd = { .name = "ssc_mx_vfl", },
505	.res_type = RPMPD_RWLM,
506	.res_id = 0,
507	.key = KEY_FLOOR_LEVEL,
508};
509
510static struct rpmpd ssc_mx_rwsm0_vfl = {
511	.pd = { .name = "ssc_mx_vfl", },
512	.res_type = RPMPD_RWSM,
513	.res_id = 0,
514	.key = KEY_FLOOR_LEVEL,
515};
516
517static struct rpmpd *mdm9607_rpmpds[] = {
518	[MDM9607_VDDCX] =	&cx_s3a_lvl,
519	[MDM9607_VDDCX_AO] =	&cx_s3a_lvl_ao,
520	[MDM9607_VDDCX_VFL] =	&cx_s3a_vfl,
521	[MDM9607_VDDMX] =	&mx_l12a_lvl,
522	[MDM9607_VDDMX_AO] =	&mx_l12a_lvl_ao,
523	[MDM9607_VDDMX_VFL] =	&mx_l12a_vfl,
524};
525
526static const struct rpmpd_desc mdm9607_desc = {
527	.rpmpds = mdm9607_rpmpds,
528	.num_pds = ARRAY_SIZE(mdm9607_rpmpds),
529	.max_state = RPM_SMD_LEVEL_TURBO,
530};
531
532static struct rpmpd *msm8226_rpmpds[] = {
533	[MSM8226_VDDCX] =	&cx_s1a_corner,
534	[MSM8226_VDDCX_AO] =	&cx_s1a_corner_ao,
535	[MSM8226_VDDCX_VFC] =	&cx_s1a_vfc,
536};
537
538static const struct rpmpd_desc msm8226_desc = {
539	.rpmpds = msm8226_rpmpds,
540	.num_pds = ARRAY_SIZE(msm8226_rpmpds),
541	.max_state = MAX_CORNER_RPMPD_STATE,
542};
543
544static struct rpmpd *msm8939_rpmpds[] = {
545	[MSM8939_VDDMDCX] =	&md_s1a_corner,
546	[MSM8939_VDDMDCX_AO] =	&md_s1a_corner_ao,
547	[MSM8939_VDDMDCX_VFC] =	&md_s1a_vfc,
548	[MSM8939_VDDCX] =	&cx_s2a_corner,
549	[MSM8939_VDDCX_AO] =	&cx_s2a_corner_ao,
550	[MSM8939_VDDCX_VFC] =	&cx_s2a_vfc,
551	[MSM8939_VDDMX] =	&mx_l3a_corner,
552	[MSM8939_VDDMX_AO] =	&mx_l3a_corner_ao,
553};
554
555static const struct rpmpd_desc msm8939_desc = {
556	.rpmpds = msm8939_rpmpds,
557	.num_pds = ARRAY_SIZE(msm8939_rpmpds),
558	.max_state = MAX_CORNER_RPMPD_STATE,
559};
560
561static struct rpmpd *msm8916_rpmpds[] = {
562	[MSM8916_VDDCX] =	&cx_s1a_corner,
563	[MSM8916_VDDCX_AO] =	&cx_s1a_corner_ao,
564	[MSM8916_VDDCX_VFC] =	&cx_s1a_vfc,
565	[MSM8916_VDDMX] =	&mx_l3a_corner,
566	[MSM8916_VDDMX_AO] =	&mx_l3a_corner_ao,
567};
568
569static const struct rpmpd_desc msm8916_desc = {
570	.rpmpds = msm8916_rpmpds,
571	.num_pds = ARRAY_SIZE(msm8916_rpmpds),
572	.max_state = MAX_CORNER_RPMPD_STATE,
573};
574
575static struct rpmpd *msm8953_rpmpds[] = {
576	[MSM8953_VDDMD] =	&md_s1a_lvl,
577	[MSM8953_VDDMD_AO] =	&md_s1a_lvl_ao,
578	[MSM8953_VDDCX] =	&cx_s2a_lvl,
579	[MSM8953_VDDCX_AO] =	&cx_s2a_lvl_ao,
580	[MSM8953_VDDCX_VFL] =	&cx_s2a_vfl,
581	[MSM8953_VDDMX] =	&mx_s7a_lvl,
582	[MSM8953_VDDMX_AO] =	&mx_s7a_lvl_ao,
583};
584
585static const struct rpmpd_desc msm8953_desc = {
586	.rpmpds = msm8953_rpmpds,
587	.num_pds = ARRAY_SIZE(msm8953_rpmpds),
588	.max_state = RPM_SMD_LEVEL_TURBO,
589};
590
591static struct rpmpd *msm8976_rpmpds[] = {
592	[MSM8976_VDDCX] =	&cx_s2a_lvl,
593	[MSM8976_VDDCX_AO] =	&cx_s2a_lvl_ao,
594	[MSM8976_VDDCX_VFL] =	&cx_rwsc2_vfl,
595	[MSM8976_VDDMX] =	&mx_s6a_lvl,
596	[MSM8976_VDDMX_AO] =	&mx_s6a_lvl_ao,
597	[MSM8976_VDDMX_VFL] =	&mx_rwsm6_vfl,
598};
599
600static const struct rpmpd_desc msm8976_desc = {
601	.rpmpds = msm8976_rpmpds,
602	.num_pds = ARRAY_SIZE(msm8976_rpmpds),
603	.max_state = RPM_SMD_LEVEL_TURBO_HIGH,
604};
605
606static struct rpmpd *msm8994_rpmpds[] = {
607	[MSM8994_VDDCX] =	&cx_s1a_corner,
608	[MSM8994_VDDCX_AO] =	&cx_s1a_corner_ao,
609	[MSM8994_VDDCX_VFC] =	&cx_s1a_vfc,
610	[MSM8994_VDDMX] =	&mx_s2a_corner,
611	[MSM8994_VDDMX_AO] =	&mx_s2a_corner_ao,
612
613	/* Attention! *Some* 8994 boards with pm8004 may use SMPC here! */
614	[MSM8994_VDDGFX] =	&gfx_s2b_corner,
615	[MSM8994_VDDGFX_VFC] =	&gfx_s2b_vfc,
616};
617
618static const struct rpmpd_desc msm8994_desc = {
619	.rpmpds = msm8994_rpmpds,
620	.num_pds = ARRAY_SIZE(msm8994_rpmpds),
621	.max_state = MAX_CORNER_RPMPD_STATE,
622};
623
624static struct rpmpd *msm8996_rpmpds[] = {
625	[MSM8996_VDDCX] =	&cx_s1a_corner,
626	[MSM8996_VDDCX_AO] =	&cx_s1a_corner_ao,
627	[MSM8996_VDDCX_VFC] =	&cx_s1a_vfc,
628	[MSM8996_VDDMX] =	&mx_s2a_corner,
629	[MSM8996_VDDMX_AO] =	&mx_s2a_corner_ao,
630	[MSM8996_VDDSSCX] =	&ssc_cx_l26a_corner,
631	[MSM8996_VDDSSCX_VFC] =	&ssc_cx_l26a_vfc,
632};
633
634static const struct rpmpd_desc msm8996_desc = {
635	.rpmpds = msm8996_rpmpds,
636	.num_pds = ARRAY_SIZE(msm8996_rpmpds),
637	.max_state = MAX_CORNER_RPMPD_STATE,
638};
639
640static struct rpmpd *msm8998_rpmpds[] = {
641	[MSM8998_VDDCX] =	&cx_rwcx0_lvl,
642	[MSM8998_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
643	[MSM8998_VDDCX_VFL] =	&cx_rwcx0_vfl,
644	[MSM8998_VDDMX] =	&mx_rwmx0_lvl,
645	[MSM8998_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
646	[MSM8998_VDDMX_VFL] =	&mx_rwmx0_vfl,
647	[MSM8998_SSCCX] =	&ssc_cx_rwsc0_lvl,
648	[MSM8998_SSCCX_VFL] =	&ssc_cx_rwsc0_vfl,
649	[MSM8998_SSCMX] =	&ssc_mx_rwsm0_lvl,
650	[MSM8998_SSCMX_VFL] =	&ssc_mx_rwsm0_vfl,
651};
652
653static const struct rpmpd_desc msm8998_desc = {
654	.rpmpds = msm8998_rpmpds,
655	.num_pds = ARRAY_SIZE(msm8998_rpmpds),
656	.max_state = RPM_SMD_LEVEL_BINNING,
657};
658
659static struct rpmpd *qcs404_rpmpds[] = {
660	[QCS404_VDDMX] =	&mx_rwmx0_lvl,
661	[QCS404_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
662	[QCS404_VDDMX_VFL] =	&mx_rwmx0_vfl,
663	[QCS404_LPICX] =	&lpi_cx_rwlc0_lvl,
664	[QCS404_LPICX_VFL] =	&lpi_cx_rwlc0_vfl,
665	[QCS404_LPIMX] =	&lpi_mx_rwlm0_lvl,
666	[QCS404_LPIMX_VFL] =	&lpi_mx_rwlm0_vfl,
667};
668
669static const struct rpmpd_desc qcs404_desc = {
670	.rpmpds = qcs404_rpmpds,
671	.num_pds = ARRAY_SIZE(qcs404_rpmpds),
672	.max_state = RPM_SMD_LEVEL_BINNING,
673};
674
675static struct rpmpd *sdm660_rpmpds[] = {
676	[SDM660_VDDCX] =	&cx_rwcx0_lvl,
677	[SDM660_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
678	[SDM660_VDDCX_VFL] =	&cx_rwcx0_vfl,
679	[SDM660_VDDMX] =	&mx_rwmx0_lvl,
680	[SDM660_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
681	[SDM660_VDDMX_VFL] =	&mx_rwmx0_vfl,
682	[SDM660_SSCCX] =	&ssc_cx_rwlc0_lvl,
683	[SDM660_SSCCX_VFL] =	&ssc_cx_rwlc0_vfl,
684	[SDM660_SSCMX] =	&ssc_mx_rwlm0_lvl,
685	[SDM660_SSCMX_VFL] =	&ssc_mx_rwlm0_vfl,
686};
687
688static const struct rpmpd_desc sdm660_desc = {
689	.rpmpds = sdm660_rpmpds,
690	.num_pds = ARRAY_SIZE(sdm660_rpmpds),
691	.max_state = RPM_SMD_LEVEL_TURBO,
692};
693
694static struct rpmpd *sm6115_rpmpds[] = {
695	[SM6115_VDDCX] =	&cx_rwcx0_lvl,
696	[SM6115_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
697	[SM6115_VDDCX_VFL] =	&cx_rwcx0_vfl,
698	[SM6115_VDDMX] =	&mx_rwmx0_lvl,
699	[SM6115_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
700	[SM6115_VDDMX_VFL] =	&mx_rwmx0_vfl,
701	[SM6115_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
702	[SM6115_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
703};
704
705static const struct rpmpd_desc sm6115_desc = {
706	.rpmpds = sm6115_rpmpds,
707	.num_pds = ARRAY_SIZE(sm6115_rpmpds),
708	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
709};
710
711static struct rpmpd *sm6125_rpmpds[] = {
712	[SM6125_VDDCX] =	&cx_rwcx0_lvl,
713	[SM6125_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
714	[SM6125_VDDCX_VFL] =	&cx_rwcx0_vfl,
715	[SM6125_VDDMX] =	&mx_rwmx0_lvl,
716	[SM6125_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
717	[SM6125_VDDMX_VFL] =	&mx_rwmx0_vfl,
718};
719
720static const struct rpmpd_desc sm6125_desc = {
721	.rpmpds = sm6125_rpmpds,
722	.num_pds = ARRAY_SIZE(sm6125_rpmpds),
723	.max_state = RPM_SMD_LEVEL_BINNING,
724};
725
726static struct rpmpd *sm6375_rpmpds[] = {
727	[SM6375_VDDCX] =	&cx_rwcx0_lvl,
728	[SM6375_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
729	[SM6375_VDDCX_VFL] =	&cx_rwcx0_vfl,
730	[SM6375_VDDMX] =	&mx_rwmx0_lvl,
731	[SM6375_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
732	[SM6375_VDDMX_VFL] =	&mx_rwmx0_vfl,
733	[SM6375_VDDGX] =	&gx_rwgx0_lvl,
734	[SM6375_VDDGX_AO] =	&gx_rwgx0_lvl_ao,
735	[SM6375_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
736	[SM6375_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
737};
738
739static const struct rpmpd_desc sm6375_desc = {
740	.rpmpds = sm6375_rpmpds,
741	.num_pds = ARRAY_SIZE(sm6375_rpmpds),
742	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
743};
744
745static struct rpmpd *qcm2290_rpmpds[] = {
746	[QCM2290_VDDCX] =	&cx_rwcx0_lvl,
747	[QCM2290_VDDCX_AO] =	&cx_rwcx0_lvl_ao,
748	[QCM2290_VDDCX_VFL] =	&cx_rwcx0_vfl,
749	[QCM2290_VDDMX] =	&mx_rwmx0_lvl,
750	[QCM2290_VDDMX_AO] =	&mx_rwmx0_lvl_ao,
751	[QCM2290_VDDMX_VFL] =	&mx_rwmx0_vfl,
752	[QCM2290_VDD_LPI_CX] =	&lpi_cx_rwlc0_lvl,
753	[QCM2290_VDD_LPI_MX] =	&lpi_mx_rwlm0_lvl,
754};
755
756static const struct rpmpd_desc qcm2290_desc = {
757	.rpmpds = qcm2290_rpmpds,
758	.num_pds = ARRAY_SIZE(qcm2290_rpmpds),
759	.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
760};
761
762static const struct of_device_id rpmpd_match_table[] = {
763	{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
764	{ .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc },
765	{ .compatible = "qcom,msm8909-rpmpd", .data = &msm8916_desc },
766	{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
767	{ .compatible = "qcom,msm8939-rpmpd", .data = &msm8939_desc },
768	{ .compatible = "qcom,msm8953-rpmpd", .data = &msm8953_desc },
769	{ .compatible = "qcom,msm8976-rpmpd", .data = &msm8976_desc },
770	{ .compatible = "qcom,msm8994-rpmpd", .data = &msm8994_desc },
771	{ .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc },
772	{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
773	{ .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc },
774	{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
775	{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
776	{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
777	{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
778	{ .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
779	{ }
780};
781MODULE_DEVICE_TABLE(of, rpmpd_match_table);
782
783static int rpmpd_send_enable(struct rpmpd *pd, bool enable)
784{
785	struct rpmpd_req req = {
786		.key = KEY_ENABLE,
787		.nbytes = cpu_to_le32(sizeof(u32)),
788		.value = cpu_to_le32(enable),
789	};
790
791	return qcom_rpm_smd_write(pd->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
792				  pd->res_type, pd->res_id, &req, sizeof(req));
793}
794
795static int rpmpd_send_corner(struct rpmpd *pd, int state, unsigned int corner)
796{
797	struct rpmpd_req req = {
798		.key = pd->key,
799		.nbytes = cpu_to_le32(sizeof(u32)),
800		.value = cpu_to_le32(corner),
801	};
802
803	return qcom_rpm_smd_write(pd->rpm, state, pd->res_type, pd->res_id,
804				  &req, sizeof(req));
805};
806
807static void to_active_sleep(struct rpmpd *pd, unsigned int corner,
808			    unsigned int *active, unsigned int *sleep)
809{
810	*active = corner;
811
812	if (pd->active_only)
813		*sleep = 0;
814	else
815		*sleep = *active;
816}
817
818static int rpmpd_aggregate_corner(struct rpmpd *pd)
819{
820	int ret;
821	struct rpmpd *peer = pd->peer;
822	unsigned int active_corner, sleep_corner;
823	unsigned int this_active_corner = 0, this_sleep_corner = 0;
824	unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
825
826	/* Clamp to the highest corner/level if sync_state isn't done yet */
827	if (!pd->state_synced)
828		this_active_corner = this_sleep_corner = pd->max_state - 1;
829	else
830		to_active_sleep(pd, pd->corner, &this_active_corner, &this_sleep_corner);
831
832	if (peer && peer->enabled)
833		to_active_sleep(peer, peer->corner, &peer_active_corner,
834				&peer_sleep_corner);
835
836	active_corner = max(this_active_corner, peer_active_corner);
837
838	ret = rpmpd_send_corner(pd, QCOM_SMD_RPM_ACTIVE_STATE, active_corner);
839	if (ret)
840		return ret;
841
842	sleep_corner = max(this_sleep_corner, peer_sleep_corner);
843
844	return rpmpd_send_corner(pd, QCOM_SMD_RPM_SLEEP_STATE, sleep_corner);
845}
846
847static int rpmpd_power_on(struct generic_pm_domain *domain)
848{
849	int ret;
850	struct rpmpd *pd = domain_to_rpmpd(domain);
851
852	mutex_lock(&rpmpd_lock);
853
854	ret = rpmpd_send_enable(pd, true);
855	if (ret)
856		goto out;
857
858	pd->enabled = true;
859
860	if (pd->corner)
861		ret = rpmpd_aggregate_corner(pd);
862
863out:
864	mutex_unlock(&rpmpd_lock);
865
866	return ret;
867}
868
869static int rpmpd_power_off(struct generic_pm_domain *domain)
870{
871	int ret;
872	struct rpmpd *pd = domain_to_rpmpd(domain);
873
874	mutex_lock(&rpmpd_lock);
875
876	ret = rpmpd_send_enable(pd, false);
877	if (!ret)
878		pd->enabled = false;
879
880	mutex_unlock(&rpmpd_lock);
881
882	return ret;
883}
884
885static int rpmpd_set_performance(struct generic_pm_domain *domain,
886				 unsigned int state)
887{
888	int ret = 0;
889	struct rpmpd *pd = domain_to_rpmpd(domain);
890
891	if (state > pd->max_state)
892		state = pd->max_state;
893
894	mutex_lock(&rpmpd_lock);
895
896	pd->corner = state;
897
898	/* Always send updates for vfc and vfl */
899	if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
900	    pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
901		goto out;
902
903	ret = rpmpd_aggregate_corner(pd);
904
905out:
906	mutex_unlock(&rpmpd_lock);
907
908	return ret;
909}
910
911static unsigned int rpmpd_get_performance(struct generic_pm_domain *genpd,
912					  struct dev_pm_opp *opp)
913{
914	return dev_pm_opp_get_level(opp);
915}
916
917static int rpmpd_probe(struct platform_device *pdev)
918{
919	int i;
920	size_t num;
921	struct genpd_onecell_data *data;
922	struct qcom_smd_rpm *rpm;
923	struct rpmpd **rpmpds;
924	const struct rpmpd_desc *desc;
925
926	rpm = dev_get_drvdata(pdev->dev.parent);
927	if (!rpm) {
928		dev_err(&pdev->dev, "Unable to retrieve handle to RPM\n");
929		return -ENODEV;
930	}
931
932	desc = of_device_get_match_data(&pdev->dev);
933	if (!desc)
934		return -EINVAL;
935
936	rpmpds = desc->rpmpds;
937	num = desc->num_pds;
938
939	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
940	if (!data)
941		return -ENOMEM;
942
943	data->domains = devm_kcalloc(&pdev->dev, num, sizeof(*data->domains),
944				     GFP_KERNEL);
945	if (!data->domains)
946		return -ENOMEM;
947
948	data->num_domains = num;
949
950	for (i = 0; i < num; i++) {
951		if (!rpmpds[i]) {
952			dev_warn(&pdev->dev, "rpmpds[] with empty entry at index=%d\n",
953				 i);
954			continue;
955		}
956
957		rpmpds[i]->rpm = rpm;
958		rpmpds[i]->max_state = desc->max_state;
959		rpmpds[i]->pd.power_off = rpmpd_power_off;
960		rpmpds[i]->pd.power_on = rpmpd_power_on;
961		rpmpds[i]->pd.set_performance_state = rpmpd_set_performance;
962		rpmpds[i]->pd.opp_to_performance_state = rpmpd_get_performance;
963		pm_genpd_init(&rpmpds[i]->pd, NULL, true);
964
965		data->domains[i] = &rpmpds[i]->pd;
966	}
967
968	/* Add subdomains */
969	for (i = 0; i < num; i++) {
970		if (!rpmpds[i])
971			continue;
972
973		if (rpmpds[i]->parent)
974			pm_genpd_add_subdomain(rpmpds[i]->parent, &rpmpds[i]->pd);
975	}
976
977	return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
978}
979
980static void rpmpd_sync_state(struct device *dev)
981{
982	const struct rpmpd_desc *desc = of_device_get_match_data(dev);
983	struct rpmpd **rpmpds = desc->rpmpds;
984	struct rpmpd *pd;
985	unsigned int i;
986	int ret;
987
988	mutex_lock(&rpmpd_lock);
989	for (i = 0; i < desc->num_pds; i++) {
990		pd = rpmpds[i];
991		if (!pd)
992			continue;
993
994		pd->state_synced = true;
995
996		if (!pd->enabled)
997			pd->corner = 0;
998
999		ret = rpmpd_aggregate_corner(pd);
1000		if (ret)
1001			dev_err(dev, "failed to sync %s: %d\n", pd->pd.name, ret);
1002	}
1003	mutex_unlock(&rpmpd_lock);
1004}
1005
1006static struct platform_driver rpmpd_driver = {
1007	.driver = {
1008		.name = "qcom-rpmpd",
1009		.of_match_table = rpmpd_match_table,
1010		.suppress_bind_attrs = true,
1011		.sync_state = rpmpd_sync_state,
1012	},
1013	.probe = rpmpd_probe,
1014};
1015
1016static int __init rpmpd_init(void)
1017{
1018	return platform_driver_register(&rpmpd_driver);
1019}
1020core_initcall(rpmpd_init);
1021
1022MODULE_DESCRIPTION("Qualcomm Technologies, Inc. RPM Power Domain Driver");
1023MODULE_LICENSE("GPL v2");
1024