1 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) 2 // Copyright(c) 2015-17 Intel Corporation. 3 4 /* 5 * SDW Intel Init Routines 6 * 7 * Initializes and creates SDW devices based on ACPI and Hardware values 8 */ 9 10 #include <linux/acpi.h> 11 #include <linux/export.h> 12 #include <linux/module.h> 13 #include <linux/platform_device.h> 14 #include <linux/soundwire/sdw_intel.h> 15 #include "intel.h" 16 17 #define SDW_LINK_TYPE 4 /* from Intel ACPI documentation */ 18 #define SDW_MAX_LINKS 4 19 #define SDW_SHIM_LCAP 0x0 20 #define SDW_SHIM_BASE 0x2C000 21 #define SDW_ALH_BASE 0x2C800 22 #define SDW_LINK_BASE 0x30000 23 #define SDW_LINK_SIZE 0x10000 24 25 struct sdw_link_data { 26 struct sdw_intel_link_res res; 27 struct platform_device *pdev; 28 }; 29 30 struct sdw_intel_ctx { 31 int count; 32 struct sdw_link_data *links; 33 }; 34 35 static int sdw_intel_cleanup_pdev(struct sdw_intel_ctx *ctx) 36 { 37 struct sdw_link_data *link = ctx->links; 38 int i; 39 40 if (!link) 41 return 0; 42 43 for (i = 0; i < ctx->count; i++) { 44 if (link->pdev) 45 platform_device_unregister(link->pdev); 46 link++; 47 } 48 49 kfree(ctx->links); 50 ctx->links = NULL; 51 52 return 0; 53 } 54 55 static struct sdw_intel_ctx 56 *sdw_intel_add_controller(struct sdw_intel_res *res) 57 { 58 struct platform_device_info pdevinfo; 59 struct platform_device *pdev; 60 struct sdw_link_data *link; 61 struct sdw_intel_ctx *ctx; 62 struct acpi_device *adev; 63 int ret, i; 64 u8 count; 65 u32 caps; 66 67 if (acpi_bus_get_device(res->handle, &adev)) 68 return NULL; 69 70 /* Found controller, find links supported */ 71 count = 0; 72 ret = fwnode_property_read_u8_array(acpi_fwnode_handle(adev), 73 "mipi-sdw-master-count", &count, 1); 74 75 /* Don't fail on error, continue and use hw value */ 76 if (ret) { 77 dev_err(&adev->dev, 78 "Failed to read mipi-sdw-master-count: %d\n", ret); 79 count = SDW_MAX_LINKS; 80 } 81 82 /* Check SNDWLCAP.LCOUNT */ 83 caps = ioread32(res->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP); 84 caps &= GENMASK(2, 0); 85 86 /* Check HW supported vs property value and use min of two */ 87 count = min_t(u8, caps, count); 88 89 /* Check count is within bounds */ 90 if (count > SDW_MAX_LINKS) { 91 dev_err(&adev->dev, "Link count %d exceeds max %d\n", 92 count, SDW_MAX_LINKS); 93 return NULL; 94 } else if (!count) { 95 dev_warn(&adev->dev, "No SoundWire links detected\n"); 96 return NULL; 97 } 98 99 dev_dbg(&adev->dev, "Creating %d SDW Link devices\n", count); 100 101 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 102 if (!ctx) 103 return NULL; 104 105 ctx->count = count; 106 ctx->links = kcalloc(ctx->count, sizeof(*ctx->links), GFP_KERNEL); 107 if (!ctx->links) 108 goto link_err; 109 110 link = ctx->links; 111 112 /* Create SDW Master devices */ 113 for (i = 0; i < count; i++) { 114 link->res.irq = res->irq; 115 link->res.registers = res->mmio_base + SDW_LINK_BASE 116 + (SDW_LINK_SIZE * i); 117 link->res.shim = res->mmio_base + SDW_SHIM_BASE; 118 link->res.alh = res->mmio_base + SDW_ALH_BASE; 119 120 link->res.ops = res->ops; 121 link->res.arg = res->arg; 122 123 memset(&pdevinfo, 0, sizeof(pdevinfo)); 124 125 pdevinfo.parent = res->parent; 126 pdevinfo.name = "int-sdw"; 127 pdevinfo.id = i; 128 pdevinfo.fwnode = acpi_fwnode_handle(adev); 129 pdevinfo.data = &link->res; 130 pdevinfo.size_data = sizeof(link->res); 131 132 pdev = platform_device_register_full(&pdevinfo); 133 if (IS_ERR(pdev)) { 134 dev_err(&adev->dev, 135 "platform device creation failed: %ld\n", 136 PTR_ERR(pdev)); 137 goto pdev_err; 138 } 139 140 link->pdev = pdev; 141 link++; 142 } 143 144 return ctx; 145 146 pdev_err: 147 sdw_intel_cleanup_pdev(ctx); 148 link_err: 149 kfree(ctx); 150 return NULL; 151 } 152 153 static acpi_status sdw_intel_acpi_cb(acpi_handle handle, u32 level, 154 void *cdata, void **return_value) 155 { 156 struct sdw_intel_res *res = cdata; 157 struct acpi_device *adev; 158 acpi_status status; 159 u64 adr; 160 161 status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr); 162 if (ACPI_FAILURE(status)) 163 return AE_OK; /* keep going */ 164 165 if (acpi_bus_get_device(handle, &adev)) { 166 pr_err("%s: Couldn't find ACPI handle\n", __func__); 167 return AE_NOT_FOUND; 168 } 169 170 res->handle = handle; 171 172 /* 173 * On some Intel platforms, multiple children of the HDAS 174 * device can be found, but only one of them is the SoundWire 175 * controller. The SNDW device is always exposed with 176 * Name(_ADR, 0x40000000), with bits 31..28 representing the 177 * SoundWire link so filter accordingly 178 */ 179 if ((adr & GENMASK(31, 28)) >> 28 != SDW_LINK_TYPE) 180 return AE_OK; /* keep going */ 181 182 /* device found, stop namespace walk */ 183 return AE_CTRL_TERMINATE; 184 } 185 186 /** 187 * sdw_intel_init() - SoundWire Intel init routine 188 * @parent_handle: ACPI parent handle 189 * @res: resource data 190 * 191 * This scans the namespace and creates SoundWire link controller devices 192 * based on the info queried. 193 */ 194 void *sdw_intel_init(acpi_handle *parent_handle, struct sdw_intel_res *res) 195 { 196 acpi_status status; 197 198 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, 199 parent_handle, 1, 200 sdw_intel_acpi_cb, 201 NULL, res, NULL); 202 if (ACPI_FAILURE(status)) 203 return NULL; 204 205 return sdw_intel_add_controller(res); 206 } 207 EXPORT_SYMBOL(sdw_intel_init); 208 209 /** 210 * sdw_intel_exit() - SoundWire Intel exit 211 * @arg: callback context 212 * 213 * Delete the controller instances created and cleanup 214 */ 215 void sdw_intel_exit(void *arg) 216 { 217 struct sdw_intel_ctx *ctx = arg; 218 219 sdw_intel_cleanup_pdev(ctx); 220 kfree(ctx); 221 } 222 EXPORT_SYMBOL(sdw_intel_exit); 223 224 MODULE_LICENSE("Dual BSD/GPL"); 225 MODULE_DESCRIPTION("Intel Soundwire Init Library"); 226