1*aadea887SPeter Maydell// Convert device code using three-phase reset to add a ResetType
2*aadea887SPeter Maydell// argument to implementations of ResettableHoldPhase and
3*aadea887SPeter Maydell// ResettableEnterPhase methods.
4*aadea887SPeter Maydell//
5*aadea887SPeter Maydell// Copyright Linaro Ltd 2024
6*aadea887SPeter Maydell// SPDX-License-Identifier: GPL-2.0-or-later
7*aadea887SPeter Maydell//
8*aadea887SPeter Maydell// for dir in include hw target; do \
9*aadea887SPeter Maydell// spatch --macro-file scripts/cocci-macro-file.h \
10*aadea887SPeter Maydell//        --sp-file scripts/coccinelle/reset-type.cocci \
11*aadea887SPeter Maydell//        --keep-comments --smpl-spacing --in-place --include-headers \
12*aadea887SPeter Maydell//        --dir $dir; done
13*aadea887SPeter Maydell//
14*aadea887SPeter Maydell// This coccinelle script aims to produce a complete change that needs
15*aadea887SPeter Maydell// no human interaction, so as well as the generic "update device
16*aadea887SPeter Maydell// implementations of the hold and exit phase methods" it includes
17*aadea887SPeter Maydell// the special-case transformations needed for the core code and for
18*aadea887SPeter Maydell// one device model that does something a bit nonstandard. Those
19*aadea887SPeter Maydell// special cases are at the end of the file.
20*aadea887SPeter Maydell
21*aadea887SPeter Maydell// Look for where we use a function as a ResettableHoldPhase method,
22*aadea887SPeter Maydell// either by directly assigning it to phases.hold or by calling
23*aadea887SPeter Maydell// resettable_class_set_parent_phases, and remember the function name.
24*aadea887SPeter Maydell@ holdfn_assigned @
25*aadea887SPeter Maydellidentifier enterfn, holdfn, exitfn;
26*aadea887SPeter Maydellidentifier rc;
27*aadea887SPeter Maydellexpression e;
28*aadea887SPeter Maydell@@
29*aadea887SPeter MaydellResettableClass *rc;
30*aadea887SPeter Maydell...
31*aadea887SPeter Maydell(
32*aadea887SPeter Maydell rc->phases.hold = holdfn;
33*aadea887SPeter Maydell|
34*aadea887SPeter Maydell resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
35*aadea887SPeter Maydell)
36*aadea887SPeter Maydell
37*aadea887SPeter Maydell// Look for the definition of the function we found in holdfn_assigned,
38*aadea887SPeter Maydell// and add the new argument. If the function calls a hold function
39*aadea887SPeter Maydell// itself (probably chaining to the parent class reset) then add the
40*aadea887SPeter Maydell// new argument there too.
41*aadea887SPeter Maydell@ holdfn_defined @
42*aadea887SPeter Maydellidentifier holdfn_assigned.holdfn;
43*aadea887SPeter Maydelltypedef Object;
44*aadea887SPeter Maydellidentifier obj;
45*aadea887SPeter Maydellexpression parent;
46*aadea887SPeter Maydell@@
47*aadea887SPeter Maydell-holdfn(Object *obj)
48*aadea887SPeter Maydell+holdfn(Object *obj, ResetType type)
49*aadea887SPeter Maydell{
50*aadea887SPeter Maydell    <...
51*aadea887SPeter Maydell-    parent.hold(obj)
52*aadea887SPeter Maydell+    parent.hold(obj, type)
53*aadea887SPeter Maydell    ...>
54*aadea887SPeter Maydell}
55*aadea887SPeter Maydell
56*aadea887SPeter Maydell// Similarly for ResettableExitPhase.
57*aadea887SPeter Maydell@ exitfn_assigned @
58*aadea887SPeter Maydellidentifier enterfn, holdfn, exitfn;
59*aadea887SPeter Maydellidentifier rc;
60*aadea887SPeter Maydellexpression e;
61*aadea887SPeter Maydell@@
62*aadea887SPeter MaydellResettableClass *rc;
63*aadea887SPeter Maydell...
64*aadea887SPeter Maydell(
65*aadea887SPeter Maydell rc->phases.exit = exitfn;
66*aadea887SPeter Maydell|
67*aadea887SPeter Maydell resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
68*aadea887SPeter Maydell)
69*aadea887SPeter Maydell@ exitfn_defined @
70*aadea887SPeter Maydellidentifier exitfn_assigned.exitfn;
71*aadea887SPeter Maydelltypedef Object;
72*aadea887SPeter Maydellidentifier obj;
73*aadea887SPeter Maydellexpression parent;
74*aadea887SPeter Maydell@@
75*aadea887SPeter Maydell-exitfn(Object *obj)
76*aadea887SPeter Maydell+exitfn(Object *obj, ResetType type)
77*aadea887SPeter Maydell{
78*aadea887SPeter Maydell    <...
79*aadea887SPeter Maydell-    parent.exit(obj)
80*aadea887SPeter Maydell+    parent.exit(obj, type)
81*aadea887SPeter Maydell    ...>
82*aadea887SPeter Maydell}
83*aadea887SPeter Maydell
84*aadea887SPeter Maydell// SPECIAL CASES ONLY BELOW HERE
85*aadea887SPeter Maydell// We use a python scripted constraint on the position of the match
86*aadea887SPeter Maydell// to ensure that they only match in a particular function. See
87*aadea887SPeter Maydell// https://public-inbox.org/git/alpine.DEB.2.21.1808240652370.2344@hadrien/
88*aadea887SPeter Maydell// which recommends this as the way to do "match only in this function".
89*aadea887SPeter Maydell
90*aadea887SPeter Maydell// Special case: isl_pmbus_vr.c has some reset methods calling others directly
91*aadea887SPeter Maydell@ isl_pmbus_vr @
92*aadea887SPeter Maydellidentifier obj;
93*aadea887SPeter Maydell@@
94*aadea887SPeter Maydell- isl_pmbus_vr_exit_reset(obj);
95*aadea887SPeter Maydell+ isl_pmbus_vr_exit_reset(obj, type);
96*aadea887SPeter Maydell
97*aadea887SPeter Maydell// Special case: device_phases_reset() needs to pass RESET_TYPE_COLD
98*aadea887SPeter Maydell@ device_phases_reset_hold @
99*aadea887SPeter Maydellexpression obj;
100*aadea887SPeter Maydellidentifier rc;
101*aadea887SPeter Maydellidentifier phase;
102*aadea887SPeter Maydellposition p : script:python() { p[0].current_element == "device_phases_reset" };
103*aadea887SPeter Maydell@@
104*aadea887SPeter Maydell- rc->phases.phase(obj)@p
105*aadea887SPeter Maydell+ rc->phases.phase(obj, RESET_TYPE_COLD)
106*aadea887SPeter Maydell
107*aadea887SPeter Maydell// Special case: in resettable_phase_hold() and resettable_phase_exit()
108*aadea887SPeter Maydell// we need to pass through the ResetType argument to the method being called
109*aadea887SPeter Maydell@ resettable_phase_hold @
110*aadea887SPeter Maydellexpression obj;
111*aadea887SPeter Maydellidentifier rc;
112*aadea887SPeter Maydellposition p : script:python() { p[0].current_element == "resettable_phase_hold" };
113*aadea887SPeter Maydell@@
114*aadea887SPeter Maydell- rc->phases.hold(obj)@p
115*aadea887SPeter Maydell+ rc->phases.hold(obj, type)
116*aadea887SPeter Maydell@ resettable_phase_exit @
117*aadea887SPeter Maydellexpression obj;
118*aadea887SPeter Maydellidentifier rc;
119*aadea887SPeter Maydellposition p : script:python() { p[0].current_element == "resettable_phase_exit" };
120*aadea887SPeter Maydell@@
121*aadea887SPeter Maydell- rc->phases.exit(obj)@p
122*aadea887SPeter Maydell+ rc->phases.exit(obj, type)
123*aadea887SPeter Maydell// Special case: the typedefs for the methods need to declare the new argument
124*aadea887SPeter Maydell@ phase_typedef_hold @
125*aadea887SPeter Maydellidentifier obj;
126*aadea887SPeter Maydell@@
127*aadea887SPeter Maydell- typedef void (*ResettableHoldPhase)(Object *obj);
128*aadea887SPeter Maydell+ typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
129*aadea887SPeter Maydell@ phase_typedef_exit @
130*aadea887SPeter Maydellidentifier obj;
131*aadea887SPeter Maydell@@
132*aadea887SPeter Maydell- typedef void (*ResettableExitPhase)(Object *obj);
133*aadea887SPeter Maydell+ typedef void (*ResettableExitPhase)(Object *obj, ResetType type);
134