Skip to content

Commit b53a234

Browse files
pantoniouglikely
authored andcommitted
of/reconfig: Add of_reconfig_get_state_change() of notifier helper.
Introduce of_reconfig_get_state_change() which allows an of notifier to query about device state changes. Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com> Signed-off-by: Grant Likely <grant.likely@linaro.org>
1 parent da56d04 commit b53a234

File tree

2 files changed

+103
-0
lines changed

2 files changed

+103
-0
lines changed

drivers/of/dynamic.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,102 @@ int of_reconfig_notify(unsigned long action, void *p)
8585
return notifier_to_errno(rc);
8686
}
8787

88+
/*
89+
* of_reconfig_get_state_change() - Returns new state of device
90+
* @action - action of the of notifier
91+
* @arg - argument of the of notifier
92+
*
93+
* Returns the new state of a device based on the notifier used.
94+
* Returns 0 on device going from enabled to disabled, 1 on device
95+
* going from disabled to enabled and -1 on no change.
96+
*/
97+
int of_reconfig_get_state_change(unsigned long action, void *arg)
98+
{
99+
struct device_node *dn;
100+
struct property *prop, *old_prop;
101+
struct of_prop_reconfig *pr;
102+
int is_status, status_state, old_status_state, prev_state, new_state;
103+
104+
/* figure out if a device should be created or destroyed */
105+
dn = NULL;
106+
prop = old_prop = NULL;
107+
switch (action) {
108+
case OF_RECONFIG_ATTACH_NODE:
109+
case OF_RECONFIG_DETACH_NODE:
110+
dn = arg;
111+
prop = of_find_property(dn, "status", NULL);
112+
break;
113+
case OF_RECONFIG_ADD_PROPERTY:
114+
case OF_RECONFIG_REMOVE_PROPERTY:
115+
pr = arg;
116+
dn = pr->dn;
117+
prop = pr->prop;
118+
break;
119+
case OF_RECONFIG_UPDATE_PROPERTY:
120+
pr = arg;
121+
dn = pr->dn;
122+
prop = pr->prop;
123+
old_prop = pr->old_prop;
124+
break;
125+
default:
126+
return OF_RECONFIG_NO_CHANGE;
127+
}
128+
129+
is_status = 0;
130+
status_state = -1;
131+
old_status_state = -1;
132+
prev_state = -1;
133+
new_state = -1;
134+
135+
if (prop && !strcmp(prop->name, "status")) {
136+
is_status = 1;
137+
status_state = !strcmp(prop->value, "okay") ||
138+
!strcmp(prop->value, "ok");
139+
if (old_prop)
140+
old_status_state = !strcmp(old_prop->value, "okay") ||
141+
!strcmp(old_prop->value, "ok");
142+
}
143+
144+
switch (action) {
145+
case OF_RECONFIG_ATTACH_NODE:
146+
prev_state = 0;
147+
/* -1 & 0 status either missing or okay */
148+
new_state = status_state != 0;
149+
break;
150+
case OF_RECONFIG_DETACH_NODE:
151+
/* -1 & 0 status either missing or okay */
152+
prev_state = status_state != 0;
153+
new_state = 0;
154+
break;
155+
case OF_RECONFIG_ADD_PROPERTY:
156+
if (is_status) {
157+
/* no status property -> enabled (legacy) */
158+
prev_state = 1;
159+
new_state = status_state;
160+
}
161+
break;
162+
case OF_RECONFIG_REMOVE_PROPERTY:
163+
if (is_status) {
164+
prev_state = status_state;
165+
/* no status property -> enabled (legacy) */
166+
new_state = 1;
167+
}
168+
break;
169+
case OF_RECONFIG_UPDATE_PROPERTY:
170+
if (is_status) {
171+
prev_state = old_status_state != 0;
172+
new_state = status_state != 0;
173+
}
174+
break;
175+
}
176+
177+
if (prev_state == new_state)
178+
return OF_RECONFIG_NO_CHANGE;
179+
180+
return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
181+
}
182+
EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
183+
88184
int of_property_notify(int action, struct device_node *np,
89185
struct property *prop, struct property *oldprop)
90186
{

include/linux/of.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ struct of_prop_reconfig {
327327
extern int of_reconfig_notifier_register(struct notifier_block *);
328328
extern int of_reconfig_notifier_unregister(struct notifier_block *);
329329
extern int of_reconfig_notify(unsigned long, void *);
330+
extern int of_reconfig_get_state_change(unsigned long action, void *arg);
330331

331332
extern int of_attach_node(struct device_node *);
332333
extern int of_detach_node(struct device_node *);
@@ -887,6 +888,12 @@ struct of_changeset {
887888
struct list_head entries;
888889
};
889890

891+
enum of_reconfig_change {
892+
OF_RECONFIG_NO_CHANGE = 0,
893+
OF_RECONFIG_CHANGE_ADD,
894+
OF_RECONFIG_CHANGE_REMOVE,
895+
};
896+
890897
#ifdef CONFIG_OF_DYNAMIC
891898
extern void of_changeset_init(struct of_changeset *ocs);
892899
extern void of_changeset_destroy(struct of_changeset *ocs);

0 commit comments

Comments
 (0)