1 | // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) |
2 | // Copyright(c) 2015-17 Intel Corporation. |
3 | |
4 | #include <linux/acpi.h> |
5 | #include <linux/of.h> |
6 | #include <linux/soundwire/sdw.h> |
7 | #include <linux/soundwire/sdw_type.h> |
8 | #include "bus.h" |
9 | #include "sysfs_local.h" |
10 | |
11 | static void sdw_slave_release(struct device *dev) |
12 | { |
13 | struct sdw_slave *slave = dev_to_sdw_dev(dev); |
14 | |
15 | mutex_destroy(lock: &slave->sdw_dev_lock); |
16 | kfree(objp: slave); |
17 | } |
18 | |
19 | const struct device_type sdw_slave_type = { |
20 | .name = "sdw_slave" , |
21 | .release = sdw_slave_release, |
22 | .uevent = sdw_slave_uevent, |
23 | }; |
24 | |
25 | int sdw_slave_add(struct sdw_bus *bus, |
26 | struct sdw_slave_id *id, struct fwnode_handle *fwnode) |
27 | { |
28 | struct sdw_slave *slave; |
29 | int ret; |
30 | int i; |
31 | |
32 | slave = kzalloc(size: sizeof(*slave), GFP_KERNEL); |
33 | if (!slave) |
34 | return -ENOMEM; |
35 | |
36 | /* Initialize data structure */ |
37 | memcpy(&slave->id, id, sizeof(*id)); |
38 | slave->dev.parent = bus->dev; |
39 | slave->dev.fwnode = fwnode; |
40 | |
41 | if (id->unique_id == SDW_IGNORED_UNIQUE_ID) { |
42 | /* name shall be sdw:ctrl:link:mfg:part:class */ |
43 | dev_set_name(dev: &slave->dev, name: "sdw:%01x:%01x:%04x:%04x:%02x" , |
44 | bus->controller_id, bus->link_id, id->mfg_id, id->part_id, |
45 | id->class_id); |
46 | } else { |
47 | /* name shall be sdw:ctrl:link:mfg:part:class:unique */ |
48 | dev_set_name(dev: &slave->dev, name: "sdw:%01x:%01x:%04x:%04x:%02x:%01x" , |
49 | bus->controller_id, bus->link_id, id->mfg_id, id->part_id, |
50 | id->class_id, id->unique_id); |
51 | } |
52 | |
53 | slave->dev.bus = &sdw_bus_type; |
54 | slave->dev.of_node = of_node_get(to_of_node(fwnode)); |
55 | slave->dev.type = &sdw_slave_type; |
56 | slave->dev.groups = sdw_slave_status_attr_groups; |
57 | slave->bus = bus; |
58 | slave->status = SDW_SLAVE_UNATTACHED; |
59 | init_completion(x: &slave->enumeration_complete); |
60 | init_completion(x: &slave->initialization_complete); |
61 | slave->dev_num = 0; |
62 | slave->probed = false; |
63 | slave->first_interrupt_done = false; |
64 | mutex_init(&slave->sdw_dev_lock); |
65 | |
66 | for (i = 0; i < SDW_MAX_PORTS; i++) |
67 | init_completion(x: &slave->port_ready[i]); |
68 | |
69 | mutex_lock(&bus->bus_lock); |
70 | list_add_tail(new: &slave->node, head: &bus->slaves); |
71 | mutex_unlock(lock: &bus->bus_lock); |
72 | |
73 | ret = device_register(dev: &slave->dev); |
74 | if (ret) { |
75 | dev_err(bus->dev, "Failed to add slave: ret %d\n" , ret); |
76 | |
77 | /* |
78 | * On err, don't free but drop ref as this will be freed |
79 | * when release method is invoked. |
80 | */ |
81 | mutex_lock(&bus->bus_lock); |
82 | list_del(entry: &slave->node); |
83 | mutex_unlock(lock: &bus->bus_lock); |
84 | put_device(dev: &slave->dev); |
85 | |
86 | return ret; |
87 | } |
88 | sdw_slave_debugfs_init(slave); |
89 | |
90 | return ret; |
91 | } |
92 | EXPORT_SYMBOL(sdw_slave_add); |
93 | |
94 | #if IS_ENABLED(CONFIG_ACPI) |
95 | |
96 | static bool find_slave(struct sdw_bus *bus, |
97 | struct acpi_device *adev, |
98 | struct sdw_slave_id *id) |
99 | { |
100 | u64 addr; |
101 | unsigned int link_id; |
102 | acpi_status status; |
103 | |
104 | status = acpi_evaluate_integer(handle: adev->handle, |
105 | METHOD_NAME__ADR, NULL, data: &addr); |
106 | |
107 | if (ACPI_FAILURE(status)) { |
108 | dev_err(bus->dev, "_ADR resolution failed: %x\n" , |
109 | status); |
110 | return false; |
111 | } |
112 | |
113 | if (bus->ops->override_adr) |
114 | addr = bus->ops->override_adr(bus, addr); |
115 | |
116 | if (!addr) |
117 | return false; |
118 | |
119 | /* Extract link id from ADR, Bit 51 to 48 (included) */ |
120 | link_id = SDW_DISCO_LINK_ID(addr); |
121 | |
122 | /* Check for link_id match */ |
123 | if (link_id != bus->link_id) |
124 | return false; |
125 | |
126 | sdw_extract_slave_id(bus, addr, id); |
127 | |
128 | return true; |
129 | } |
130 | |
131 | struct sdw_acpi_child_walk_data { |
132 | struct sdw_bus *bus; |
133 | struct acpi_device *adev; |
134 | struct sdw_slave_id id; |
135 | bool ignore_unique_id; |
136 | }; |
137 | |
138 | static int sdw_acpi_check_duplicate(struct acpi_device *adev, void *data) |
139 | { |
140 | struct sdw_acpi_child_walk_data *cwd = data; |
141 | struct sdw_bus *bus = cwd->bus; |
142 | struct sdw_slave_id id; |
143 | |
144 | if (adev == cwd->adev) |
145 | return 0; |
146 | |
147 | if (!find_slave(bus, adev, id: &id)) |
148 | return 0; |
149 | |
150 | if (cwd->id.sdw_version != id.sdw_version || cwd->id.mfg_id != id.mfg_id || |
151 | cwd->id.part_id != id.part_id || cwd->id.class_id != id.class_id) |
152 | return 0; |
153 | |
154 | if (cwd->id.unique_id != id.unique_id) { |
155 | dev_dbg(bus->dev, |
156 | "Valid unique IDs 0x%x 0x%x for Slave mfg_id 0x%04x, part_id 0x%04x\n" , |
157 | cwd->id.unique_id, id.unique_id, cwd->id.mfg_id, |
158 | cwd->id.part_id); |
159 | cwd->ignore_unique_id = false; |
160 | return 0; |
161 | } |
162 | |
163 | dev_err(bus->dev, |
164 | "Invalid unique IDs 0x%x 0x%x for Slave mfg_id 0x%04x, part_id 0x%04x\n" , |
165 | cwd->id.unique_id, id.unique_id, cwd->id.mfg_id, cwd->id.part_id); |
166 | return -ENODEV; |
167 | } |
168 | |
169 | static int sdw_acpi_find_one(struct acpi_device *adev, void *data) |
170 | { |
171 | struct sdw_bus *bus = data; |
172 | struct sdw_acpi_child_walk_data cwd = { |
173 | .bus = bus, |
174 | .adev = adev, |
175 | .ignore_unique_id = true, |
176 | }; |
177 | int ret; |
178 | |
179 | if (!find_slave(bus, adev, id: &cwd.id)) |
180 | return 0; |
181 | |
182 | /* Brute-force O(N^2) search for duplicates. */ |
183 | ret = acpi_dev_for_each_child(ACPI_COMPANION(bus->dev), |
184 | fn: sdw_acpi_check_duplicate, data: &cwd); |
185 | if (ret) |
186 | return ret; |
187 | |
188 | if (cwd.ignore_unique_id) |
189 | cwd.id.unique_id = SDW_IGNORED_UNIQUE_ID; |
190 | |
191 | /* Ignore errors and continue. */ |
192 | sdw_slave_add(bus, &cwd.id, acpi_fwnode_handle(adev)); |
193 | return 0; |
194 | } |
195 | |
196 | /* |
197 | * sdw_acpi_find_slaves() - Find Slave devices in Master ACPI node |
198 | * @bus: SDW bus instance |
199 | * |
200 | * Scans Master ACPI node for SDW child Slave devices and registers it. |
201 | */ |
202 | int sdw_acpi_find_slaves(struct sdw_bus *bus) |
203 | { |
204 | struct acpi_device *parent; |
205 | |
206 | parent = ACPI_COMPANION(bus->dev); |
207 | if (!parent) { |
208 | dev_err(bus->dev, "Can't find parent for acpi bind\n" ); |
209 | return -ENODEV; |
210 | } |
211 | |
212 | return acpi_dev_for_each_child(adev: parent, fn: sdw_acpi_find_one, data: bus); |
213 | } |
214 | |
215 | #endif |
216 | |
217 | /* |
218 | * sdw_of_find_slaves() - Find Slave devices in master device tree node |
219 | * @bus: SDW bus instance |
220 | * |
221 | * Scans Master DT node for SDW child Slave devices and registers it. |
222 | */ |
223 | int sdw_of_find_slaves(struct sdw_bus *bus) |
224 | { |
225 | struct device *dev = bus->dev; |
226 | struct device_node *node; |
227 | |
228 | for_each_child_of_node(bus->dev->of_node, node) { |
229 | int link_id, ret, len; |
230 | unsigned int sdw_version; |
231 | const char *compat = NULL; |
232 | struct sdw_slave_id id; |
233 | const __be32 *addr; |
234 | |
235 | compat = of_get_property(node, name: "compatible" , NULL); |
236 | if (!compat) |
237 | continue; |
238 | |
239 | ret = sscanf(compat, "sdw%01x%04hx%04hx%02hhx" , &sdw_version, |
240 | &id.mfg_id, &id.part_id, &id.class_id); |
241 | |
242 | if (ret != 4) { |
243 | dev_err(dev, "Invalid compatible string found %s\n" , |
244 | compat); |
245 | continue; |
246 | } |
247 | |
248 | addr = of_get_property(node, name: "reg" , lenp: &len); |
249 | if (!addr || (len < 2 * sizeof(u32))) { |
250 | dev_err(dev, "Invalid Link and Instance ID\n" ); |
251 | continue; |
252 | } |
253 | |
254 | link_id = be32_to_cpup(p: addr++); |
255 | id.unique_id = be32_to_cpup(p: addr); |
256 | id.sdw_version = sdw_version; |
257 | |
258 | /* Check for link_id match */ |
259 | if (link_id != bus->link_id) |
260 | continue; |
261 | |
262 | sdw_slave_add(bus, &id, of_fwnode_handle(node)); |
263 | } |
264 | |
265 | return 0; |
266 | } |
267 | |