Commit | Line | Data |
---|---|---|
7c3cd189 VK |
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/mod_devicetable.h> | |
6 | #include <linux/soundwire/sdw.h> | |
7 | #include "bus.h" | |
8 | ||
9 | /** | |
10 | * sdw_add_bus_master() - add a bus Master instance | |
11 | * @bus: bus instance | |
12 | * | |
13 | * Initializes the bus instance, read properties and create child | |
14 | * devices. | |
15 | */ | |
16 | int sdw_add_bus_master(struct sdw_bus *bus) | |
17 | { | |
18 | int ret; | |
19 | ||
20 | if (!bus->dev) { | |
21 | pr_err("SoundWire bus has no device"); | |
22 | return -ENODEV; | |
23 | } | |
24 | ||
25 | mutex_init(&bus->bus_lock); | |
26 | INIT_LIST_HEAD(&bus->slaves); | |
27 | ||
56d4fe31 VK |
28 | if (bus->ops->read_prop) { |
29 | ret = bus->ops->read_prop(bus); | |
30 | if (ret < 0) { | |
31 | dev_err(bus->dev, "Bus read properties failed:%d", ret); | |
32 | return ret; | |
33 | } | |
34 | } | |
35 | ||
7c3cd189 VK |
36 | /* |
37 | * Device numbers in SoundWire are 0 thru 15. Enumeration device | |
38 | * number (0), Broadcast device number (15), Group numbers (12 and | |
39 | * 13) and Master device number (14) are not used for assignment so | |
40 | * mask these and other higher bits. | |
41 | */ | |
42 | ||
43 | /* Set higher order bits */ | |
44 | *bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM); | |
45 | ||
46 | /* Set enumuration device number and broadcast device number */ | |
47 | set_bit(SDW_ENUM_DEV_NUM, bus->assigned); | |
48 | set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned); | |
49 | ||
50 | /* Set group device numbers and master device number */ | |
51 | set_bit(SDW_GROUP12_DEV_NUM, bus->assigned); | |
52 | set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); | |
53 | set_bit(SDW_MASTER_DEV_NUM, bus->assigned); | |
54 | ||
55 | /* | |
56 | * SDW is an enumerable bus, but devices can be powered off. So, | |
57 | * they won't be able to report as present. | |
58 | * | |
59 | * Create Slave devices based on Slaves described in | |
60 | * the respective firmware (ACPI/DT) | |
61 | */ | |
62 | if (IS_ENABLED(CONFIG_ACPI) && ACPI_HANDLE(bus->dev)) | |
63 | ret = sdw_acpi_find_slaves(bus); | |
64 | else | |
65 | ret = -ENOTSUPP; /* No ACPI/DT so error out */ | |
66 | ||
67 | if (ret) { | |
68 | dev_err(bus->dev, "Finding slaves failed:%d\n", ret); | |
69 | return ret; | |
70 | } | |
71 | ||
72 | return 0; | |
73 | } | |
74 | EXPORT_SYMBOL(sdw_add_bus_master); | |
75 | ||
76 | static int sdw_delete_slave(struct device *dev, void *data) | |
77 | { | |
78 | struct sdw_slave *slave = dev_to_sdw_dev(dev); | |
79 | struct sdw_bus *bus = slave->bus; | |
80 | ||
81 | mutex_lock(&bus->bus_lock); | |
82 | ||
83 | if (slave->dev_num) /* clear dev_num if assigned */ | |
84 | clear_bit(slave->dev_num, bus->assigned); | |
85 | ||
86 | list_del_init(&slave->node); | |
87 | mutex_unlock(&bus->bus_lock); | |
88 | ||
89 | device_unregister(dev); | |
90 | return 0; | |
91 | } | |
92 | ||
93 | /** | |
94 | * sdw_delete_bus_master() - delete the bus master instance | |
95 | * @bus: bus to be deleted | |
96 | * | |
97 | * Remove the instance, delete the child devices. | |
98 | */ | |
99 | void sdw_delete_bus_master(struct sdw_bus *bus) | |
100 | { | |
101 | device_for_each_child(bus->dev, NULL, sdw_delete_slave); | |
102 | } | |
103 | EXPORT_SYMBOL(sdw_delete_bus_master); | |
104 | ||
105 | void sdw_extract_slave_id(struct sdw_bus *bus, | |
106 | u64 addr, struct sdw_slave_id *id) | |
107 | { | |
108 | dev_dbg(bus->dev, "SDW Slave Addr: %llx", addr); | |
109 | ||
110 | /* | |
111 | * Spec definition | |
112 | * Register Bit Contents | |
113 | * DevId_0 [7:4] 47:44 sdw_version | |
114 | * DevId_0 [3:0] 43:40 unique_id | |
115 | * DevId_1 39:32 mfg_id [15:8] | |
116 | * DevId_2 31:24 mfg_id [7:0] | |
117 | * DevId_3 23:16 part_id [15:8] | |
118 | * DevId_4 15:08 part_id [7:0] | |
119 | * DevId_5 07:00 class_id | |
120 | */ | |
121 | id->sdw_version = (addr >> 44) & GENMASK(3, 0); | |
122 | id->unique_id = (addr >> 40) & GENMASK(3, 0); | |
123 | id->mfg_id = (addr >> 24) & GENMASK(15, 0); | |
124 | id->part_id = (addr >> 8) & GENMASK(15, 0); | |
125 | id->class_id = addr & GENMASK(7, 0); | |
126 | ||
127 | dev_dbg(bus->dev, | |
128 | "SDW Slave class_id %x, part_id %x, mfg_id %x, unique_id %x, version %x", | |
129 | id->class_id, id->part_id, id->mfg_id, | |
130 | id->unique_id, id->sdw_version); | |
131 | ||
132 | } |