Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soundwire: Add Master registration

A Master adds a SoundWire bus instance which scans the firmware
provided for device description.

In this patch we scan ACPI namespaces and create SoundWire
Slave devices based on ACPI description

Signed-off-by: Sanyog Kale <sanyog.r.kale@intel.com>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Acked-By: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vinod Koul and committed by
Greg Kroah-Hartman
7c3cd189 9251345d

+276 -1
+1 -1
drivers/soundwire/Makefile
··· 3 3 # 4 4 5 5 #Bus Objs 6 - soundwire-bus-objs := bus_type.o 6 + soundwire-bus-objs := bus_type.o bus.o slave.o 7 7 obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
+124
drivers/soundwire/bus.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/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 + 28 + /* 29 + * Device numbers in SoundWire are 0 thru 15. Enumeration device 30 + * number (0), Broadcast device number (15), Group numbers (12 and 31 + * 13) and Master device number (14) are not used for assignment so 32 + * mask these and other higher bits. 33 + */ 34 + 35 + /* Set higher order bits */ 36 + *bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM); 37 + 38 + /* Set enumuration device number and broadcast device number */ 39 + set_bit(SDW_ENUM_DEV_NUM, bus->assigned); 40 + set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned); 41 + 42 + /* Set group device numbers and master device number */ 43 + set_bit(SDW_GROUP12_DEV_NUM, bus->assigned); 44 + set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); 45 + set_bit(SDW_MASTER_DEV_NUM, bus->assigned); 46 + 47 + /* 48 + * SDW is an enumerable bus, but devices can be powered off. So, 49 + * they won't be able to report as present. 50 + * 51 + * Create Slave devices based on Slaves described in 52 + * the respective firmware (ACPI/DT) 53 + */ 54 + if (IS_ENABLED(CONFIG_ACPI) && ACPI_HANDLE(bus->dev)) 55 + ret = sdw_acpi_find_slaves(bus); 56 + else 57 + ret = -ENOTSUPP; /* No ACPI/DT so error out */ 58 + 59 + if (ret) { 60 + dev_err(bus->dev, "Finding slaves failed:%d\n", ret); 61 + return ret; 62 + } 63 + 64 + return 0; 65 + } 66 + EXPORT_SYMBOL(sdw_add_bus_master); 67 + 68 + static int sdw_delete_slave(struct device *dev, void *data) 69 + { 70 + struct sdw_slave *slave = dev_to_sdw_dev(dev); 71 + struct sdw_bus *bus = slave->bus; 72 + 73 + mutex_lock(&bus->bus_lock); 74 + 75 + if (slave->dev_num) /* clear dev_num if assigned */ 76 + clear_bit(slave->dev_num, bus->assigned); 77 + 78 + list_del_init(&slave->node); 79 + mutex_unlock(&bus->bus_lock); 80 + 81 + device_unregister(dev); 82 + return 0; 83 + } 84 + 85 + /** 86 + * sdw_delete_bus_master() - delete the bus master instance 87 + * @bus: bus to be deleted 88 + * 89 + * Remove the instance, delete the child devices. 90 + */ 91 + void sdw_delete_bus_master(struct sdw_bus *bus) 92 + { 93 + device_for_each_child(bus->dev, NULL, sdw_delete_slave); 94 + } 95 + EXPORT_SYMBOL(sdw_delete_bus_master); 96 + 97 + void sdw_extract_slave_id(struct sdw_bus *bus, 98 + u64 addr, struct sdw_slave_id *id) 99 + { 100 + dev_dbg(bus->dev, "SDW Slave Addr: %llx", addr); 101 + 102 + /* 103 + * Spec definition 104 + * Register Bit Contents 105 + * DevId_0 [7:4] 47:44 sdw_version 106 + * DevId_0 [3:0] 43:40 unique_id 107 + * DevId_1 39:32 mfg_id [15:8] 108 + * DevId_2 31:24 mfg_id [7:0] 109 + * DevId_3 23:16 part_id [15:8] 110 + * DevId_4 15:08 part_id [7:0] 111 + * DevId_5 07:00 class_id 112 + */ 113 + id->sdw_version = (addr >> 44) & GENMASK(3, 0); 114 + id->unique_id = (addr >> 40) & GENMASK(3, 0); 115 + id->mfg_id = (addr >> 24) & GENMASK(15, 0); 116 + id->part_id = (addr >> 8) & GENMASK(15, 0); 117 + id->class_id = addr & GENMASK(7, 0); 118 + 119 + dev_dbg(bus->dev, 120 + "SDW Slave class_id %x, part_id %x, mfg_id %x, unique_id %x, version %x", 121 + id->class_id, id->part_id, id->mfg_id, 122 + id->unique_id, id->sdw_version); 123 + 124 + }
+19
drivers/soundwire/bus.h
··· 1 + // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2 + // Copyright(c) 2015-17 Intel Corporation. 3 + 4 + #ifndef __SDW_BUS_H 5 + #define __SDW_BUS_H 6 + 7 + #if IS_ENABLED(CONFIG_ACPI) 8 + int sdw_acpi_find_slaves(struct sdw_bus *bus); 9 + #else 10 + static inline int sdw_acpi_find_slaves(struct sdw_bus *bus) 11 + { 12 + return -ENOTSUPP; 13 + } 14 + #endif 15 + 16 + void sdw_extract_slave_id(struct sdw_bus *bus, 17 + u64 addr, struct sdw_slave_id *id); 18 + 19 + #endif /* __SDW_BUS_H */
+114
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/soundwire/sdw.h> 6 + #include <linux/soundwire/sdw_type.h> 7 + #include "bus.h" 8 + 9 + static void sdw_slave_release(struct device *dev) 10 + { 11 + struct sdw_slave *slave = dev_to_sdw_dev(dev); 12 + 13 + kfree(slave); 14 + } 15 + 16 + static int sdw_slave_add(struct sdw_bus *bus, 17 + struct sdw_slave_id *id, struct fwnode_handle *fwnode) 18 + { 19 + struct sdw_slave *slave; 20 + int ret; 21 + 22 + slave = kzalloc(sizeof(*slave), GFP_KERNEL); 23 + if (!slave) 24 + return -ENOMEM; 25 + 26 + /* Initialize data structure */ 27 + memcpy(&slave->id, id, sizeof(*id)); 28 + slave->dev.parent = bus->dev; 29 + slave->dev.fwnode = fwnode; 30 + 31 + /* name shall be sdw:link:mfg:part:class:unique */ 32 + dev_set_name(&slave->dev, "sdw:%x:%x:%x:%x:%x", 33 + bus->link_id, id->mfg_id, id->part_id, 34 + id->class_id, id->unique_id); 35 + 36 + slave->dev.release = sdw_slave_release; 37 + slave->dev.bus = &sdw_bus_type; 38 + slave->bus = bus; 39 + slave->status = SDW_SLAVE_UNATTACHED; 40 + slave->dev_num = 0; 41 + 42 + mutex_lock(&bus->bus_lock); 43 + list_add_tail(&slave->node, &bus->slaves); 44 + mutex_unlock(&bus->bus_lock); 45 + 46 + ret = device_register(&slave->dev); 47 + if (ret) { 48 + dev_err(bus->dev, "Failed to add slave: ret %d\n", ret); 49 + 50 + /* 51 + * On err, don't free but drop ref as this will be freed 52 + * when release method is invoked. 53 + */ 54 + mutex_lock(&bus->bus_lock); 55 + list_del(&slave->node); 56 + mutex_unlock(&bus->bus_lock); 57 + put_device(&slave->dev); 58 + } 59 + 60 + return ret; 61 + } 62 + 63 + #if IS_ENABLED(CONFIG_ACPI) 64 + /* 65 + * sdw_acpi_find_slaves() - Find Slave devices in Master ACPI node 66 + * @bus: SDW bus instance 67 + * 68 + * Scans Master ACPI node for SDW child Slave devices and registers it. 69 + */ 70 + int sdw_acpi_find_slaves(struct sdw_bus *bus) 71 + { 72 + struct acpi_device *adev, *parent; 73 + 74 + parent = ACPI_COMPANION(bus->dev); 75 + if (!parent) { 76 + dev_err(bus->dev, "Can't find parent for acpi bind\n"); 77 + return -ENODEV; 78 + } 79 + 80 + list_for_each_entry(adev, &parent->children, node) { 81 + unsigned long long addr; 82 + struct sdw_slave_id id; 83 + unsigned int link_id; 84 + acpi_status status; 85 + 86 + status = acpi_evaluate_integer(adev->handle, 87 + METHOD_NAME__ADR, NULL, &addr); 88 + 89 + if (ACPI_FAILURE(status)) { 90 + dev_err(bus->dev, "_ADR resolution failed: %x\n", 91 + status); 92 + return status; 93 + } 94 + 95 + /* Extract link id from ADR, Bit 51 to 48 (included) */ 96 + link_id = (addr >> 48) & GENMASK(3, 0); 97 + 98 + /* Check for link_id match */ 99 + if (link_id != bus->link_id) 100 + continue; 101 + 102 + sdw_extract_slave_id(bus, addr, &id); 103 + 104 + /* 105 + * don't error check for sdw_slave_add as we want to continue 106 + * adding Slaves 107 + */ 108 + sdw_slave_add(bus, &id, acpi_fwnode_handle(adev)); 109 + } 110 + 111 + return 0; 112 + } 113 + 114 + #endif
+18
include/linux/soundwire/sdw.h
··· 7 7 struct sdw_bus; 8 8 struct sdw_slave; 9 9 10 + /* SDW spec defines and enums, as defined by MIPI 1.1. Spec */ 11 + 12 + /* SDW Broadcast Device Number */ 13 + #define SDW_BROADCAST_DEV_NUM 15 14 + 15 + /* SDW Enumeration Device Number */ 16 + #define SDW_ENUM_DEV_NUM 0 17 + 18 + /* SDW Group Device Numbers */ 19 + #define SDW_GROUP12_DEV_NUM 12 20 + #define SDW_GROUP13_DEV_NUM 13 21 + 22 + /* SDW Master Device Number, not supported yet */ 23 + #define SDW_MASTER_DEV_NUM 14 24 + 10 25 #define SDW_MAX_DEVICES 11 11 26 12 27 /** ··· 119 104 DECLARE_BITMAP(assigned, SDW_MAX_DEVICES); 120 105 struct mutex bus_lock; 121 106 }; 107 + 108 + int sdw_add_bus_master(struct sdw_bus *bus); 109 + void sdw_delete_bus_master(struct sdw_bus *bus); 122 110 123 111 #endif /* __SOUNDWIRE_H */