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