1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * drivers/mfd/mfd-core.c 4 * 5 * core MFD support 6 * Copyright (c) 2006 Ian Molton 7 * Copyright (c) 2007,2008 Dmitry Baryshkov 8 */ 9 10 #include <linux/kernel.h> 11 #include <linux/platform_device.h> 12 #include <linux/acpi.h> 13 #include <linux/property.h> 14 #include <linux/mfd/core.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/slab.h> 17 #include <linux/module.h> 18 #include <linux/irqdomain.h> 19 #include <linux/of.h> 20 #include <linux/regulator/consumer.h> 21 22 static struct device_type mfd_dev_type = { 23 .name = "mfd_device", 24 }; 25 26 int mfd_cell_enable(struct platform_device *pdev) 27 { 28 const struct mfd_cell *cell = mfd_get_cell(pdev); 29 int err = 0; 30 31 if (!cell->enable) { 32 dev_dbg(&pdev->dev, "No .enable() call-back registered\n"); 33 return 0; 34 } 35 36 /* only call enable hook if the cell wasn't previously enabled */ 37 if (atomic_inc_return(cell->usage_count) == 1) 38 err = cell->enable(pdev); 39 40 /* if the enable hook failed, decrement counter to allow retries */ 41 if (err) 42 atomic_dec(cell->usage_count); 43 44 return err; 45 } 46 EXPORT_SYMBOL(mfd_cell_enable); 47 48 int mfd_cell_disable(struct platform_device *pdev) 49 { 50 const struct mfd_cell *cell = mfd_get_cell(pdev); 51 int err = 0; 52 53 if (!cell->disable) { 54 dev_dbg(&pdev->dev, "No .disable() call-back registered\n"); 55 return 0; 56 } 57 58 /* only disable if no other clients are using it */ 59 if (atomic_dec_return(cell->usage_count) == 0) 60 err = cell->disable(pdev); 61 62 /* if the disable hook failed, increment to allow retries */ 63 if (err) 64 atomic_inc(cell->usage_count); 65 66 /* sanity check; did someone call disable too many times? */ 67 WARN_ON(atomic_read(cell->usage_count) < 0); 68 69 return err; 70 } 71 EXPORT_SYMBOL(mfd_cell_disable); 72 73 static int mfd_platform_add_cell(struct platform_device *pdev, 74 const struct mfd_cell *cell, 75 atomic_t *usage_count) 76 { 77 if (!cell) 78 return 0; 79 80 pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL); 81 if (!pdev->mfd_cell) 82 return -ENOMEM; 83 84 pdev->mfd_cell->usage_count = usage_count; 85 return 0; 86 } 87 88 #if IS_ENABLED(CONFIG_ACPI) 89 static void mfd_acpi_add_device(const struct mfd_cell *cell, 90 struct platform_device *pdev) 91 { 92 const struct mfd_cell_acpi_match *match = cell->acpi_match; 93 struct acpi_device *parent, *child; 94 struct acpi_device *adev; 95 96 parent = ACPI_COMPANION(pdev->dev.parent); 97 if (!parent) 98 return; 99 100 /* 101 * MFD child device gets its ACPI handle either from the ACPI device 102 * directly under the parent that matches the either _HID or _CID, or 103 * _ADR or it will use the parent handle if is no ID is given. 104 * 105 * Note that use of _ADR is a grey area in the ACPI specification, 106 * though Intel Galileo Gen2 is using it to distinguish the children 107 * devices. 108 */ 109 adev = parent; 110 if (match) { 111 if (match->pnpid) { 112 struct acpi_device_id ids[2] = {}; 113 114 strlcpy(ids[0].id, match->pnpid, sizeof(ids[0].id)); 115 list_for_each_entry(child, &parent->children, node) { 116 if (!acpi_match_device_ids(child, ids)) { 117 adev = child; 118 break; 119 } 120 } 121 } else { 122 unsigned long long adr; 123 acpi_status status; 124 125 list_for_each_entry(child, &parent->children, node) { 126 status = acpi_evaluate_integer(child->handle, 127 "_ADR", NULL, 128 &adr); 129 if (ACPI_SUCCESS(status) && match->adr == adr) { 130 adev = child; 131 break; 132 } 133 } 134 } 135 } 136 137 ACPI_COMPANION_SET(&pdev->dev, adev); 138 } 139 #else 140 static inline void mfd_acpi_add_device(const struct mfd_cell *cell, 141 struct platform_device *pdev) 142 { 143 } 144 #endif 145 146 static int mfd_add_device(struct device *parent, int id, 147 const struct mfd_cell *cell, atomic_t *usage_count, 148 struct resource *mem_base, 149 int irq_base, struct irq_domain *domain) 150 { 151 struct resource *res; 152 struct platform_device *pdev; 153 struct device_node *np = NULL; 154 int ret = -ENOMEM; 155 int platform_id; 156 int r; 157 158 if (id == PLATFORM_DEVID_AUTO) 159 platform_id = id; 160 else 161 platform_id = id + cell->id; 162 163 pdev = platform_device_alloc(cell->name, platform_id); 164 if (!pdev) 165 goto fail_alloc; 166 167 res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL); 168 if (!res) 169 goto fail_device; 170 171 pdev->dev.parent = parent; 172 pdev->dev.type = &mfd_dev_type; 173 pdev->dev.dma_mask = parent->dma_mask; 174 pdev->dev.dma_parms = parent->dma_parms; 175 pdev->dev.coherent_dma_mask = parent->coherent_dma_mask; 176 177 ret = regulator_bulk_register_supply_alias( 178 &pdev->dev, cell->parent_supplies, 179 parent, cell->parent_supplies, 180 cell->num_parent_supplies); 181 if (ret < 0) 182 goto fail_res; 183 184 if (parent->of_node && cell->of_compatible) { 185 for_each_child_of_node(parent->of_node, np) { 186 if (of_device_is_compatible(np, cell->of_compatible)) { 187 pdev->dev.of_node = np; 188 pdev->dev.fwnode = &np->fwnode; 189 break; 190 } 191 } 192 } 193 194 mfd_acpi_add_device(cell, pdev); 195 196 if (cell->pdata_size) { 197 ret = platform_device_add_data(pdev, 198 cell->platform_data, cell->pdata_size); 199 if (ret) 200 goto fail_alias; 201 } 202 203 if (cell->properties) { 204 ret = platform_device_add_properties(pdev, cell->properties); 205 if (ret) 206 goto fail_alias; 207 } 208 209 ret = mfd_platform_add_cell(pdev, cell, usage_count); 210 if (ret) 211 goto fail_alias; 212 213 for (r = 0; r < cell->num_resources; r++) { 214 res[r].name = cell->resources[r].name; 215 res[r].flags = cell->resources[r].flags; 216 217 /* Find out base to use */ 218 if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) { 219 res[r].parent = mem_base; 220 res[r].start = mem_base->start + 221 cell->resources[r].start; 222 res[r].end = mem_base->start + 223 cell->resources[r].end; 224 } else if (cell->resources[r].flags & IORESOURCE_IRQ) { 225 if (domain) { 226 /* Unable to create mappings for IRQ ranges. */ 227 WARN_ON(cell->resources[r].start != 228 cell->resources[r].end); 229 res[r].start = res[r].end = irq_create_mapping( 230 domain, cell->resources[r].start); 231 } else { 232 res[r].start = irq_base + 233 cell->resources[r].start; 234 res[r].end = irq_base + 235 cell->resources[r].end; 236 } 237 } else { 238 res[r].parent = cell->resources[r].parent; 239 res[r].start = cell->resources[r].start; 240 res[r].end = cell->resources[r].end; 241 } 242 243 if (!cell->ignore_resource_conflicts) { 244 if (has_acpi_companion(&pdev->dev)) { 245 ret = acpi_check_resource_conflict(&res[r]); 246 if (ret) 247 goto fail_alias; 248 } 249 } 250 } 251 252 ret = platform_device_add_resources(pdev, res, cell->num_resources); 253 if (ret) 254 goto fail_alias; 255 256 ret = platform_device_add(pdev); 257 if (ret) 258 goto fail_alias; 259 260 if (cell->pm_runtime_no_callbacks) 261 pm_runtime_no_callbacks(&pdev->dev); 262 263 kfree(res); 264 265 return 0; 266 267 fail_alias: 268 regulator_bulk_unregister_supply_alias(&pdev->dev, 269 cell->parent_supplies, 270 cell->num_parent_supplies); 271 fail_res: 272 kfree(res); 273 fail_device: 274 platform_device_put(pdev); 275 fail_alloc: 276 return ret; 277 } 278 279 /** 280 * mfd_add_devices - register child devices 281 * 282 * @parent: Pointer to parent device. 283 * @id: Can be PLATFORM_DEVID_AUTO to let the Platform API take care 284 * of device numbering, or will be added to a device's cell_id. 285 * @cells: Array of (struct mfd_cell)s describing child devices. 286 * @n_devs: Number of child devices to register. 287 * @mem_base: Parent register range resource for child devices. 288 * @irq_base: Base of the range of virtual interrupt numbers allocated for 289 * this MFD device. Unused if @domain is specified. 290 * @domain: Interrupt domain to create mappings for hardware interrupts. 291 */ 292 int mfd_add_devices(struct device *parent, int id, 293 const struct mfd_cell *cells, int n_devs, 294 struct resource *mem_base, 295 int irq_base, struct irq_domain *domain) 296 { 297 int i; 298 int ret; 299 atomic_t *cnts; 300 301 /* initialize reference counting for all cells */ 302 cnts = kcalloc(n_devs, sizeof(*cnts), GFP_KERNEL); 303 if (!cnts) 304 return -ENOMEM; 305 306 for (i = 0; i < n_devs; i++) { 307 atomic_set(&cnts[i], 0); 308 ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, 309 irq_base, domain); 310 if (ret) 311 goto fail; 312 } 313 314 return 0; 315 316 fail: 317 if (i) 318 mfd_remove_devices(parent); 319 else 320 kfree(cnts); 321 return ret; 322 } 323 EXPORT_SYMBOL(mfd_add_devices); 324 325 static int mfd_remove_devices_fn(struct device *dev, void *c) 326 { 327 struct platform_device *pdev; 328 const struct mfd_cell *cell; 329 atomic_t **usage_count = c; 330 331 if (dev->type != &mfd_dev_type) 332 return 0; 333 334 pdev = to_platform_device(dev); 335 cell = mfd_get_cell(pdev); 336 337 regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, 338 cell->num_parent_supplies); 339 340 /* find the base address of usage_count pointers (for freeing) */ 341 if (!*usage_count || (cell->usage_count < *usage_count)) 342 *usage_count = cell->usage_count; 343 344 platform_device_unregister(pdev); 345 return 0; 346 } 347 348 void mfd_remove_devices(struct device *parent) 349 { 350 atomic_t *cnts = NULL; 351 352 device_for_each_child_reverse(parent, &cnts, mfd_remove_devices_fn); 353 kfree(cnts); 354 } 355 EXPORT_SYMBOL(mfd_remove_devices); 356 357 static void devm_mfd_dev_release(struct device *dev, void *res) 358 { 359 mfd_remove_devices(dev); 360 } 361 362 /** 363 * devm_mfd_add_devices - Resource managed version of mfd_add_devices() 364 * 365 * Returns 0 on success or an appropriate negative error number on failure. 366 * All child-devices of the MFD will automatically be removed when it gets 367 * unbinded. 368 */ 369 int devm_mfd_add_devices(struct device *dev, int id, 370 const struct mfd_cell *cells, int n_devs, 371 struct resource *mem_base, 372 int irq_base, struct irq_domain *domain) 373 { 374 struct device **ptr; 375 int ret; 376 377 ptr = devres_alloc(devm_mfd_dev_release, sizeof(*ptr), GFP_KERNEL); 378 if (!ptr) 379 return -ENOMEM; 380 381 ret = mfd_add_devices(dev, id, cells, n_devs, mem_base, 382 irq_base, domain); 383 if (ret < 0) { 384 devres_free(ptr); 385 return ret; 386 } 387 388 *ptr = dev; 389 devres_add(dev, ptr); 390 391 return ret; 392 } 393 EXPORT_SYMBOL(devm_mfd_add_devices); 394 395 int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) 396 { 397 struct mfd_cell cell_entry; 398 struct device *dev; 399 struct platform_device *pdev; 400 int i; 401 402 /* fetch the parent cell's device (should already be registered!) */ 403 dev = bus_find_device_by_name(&platform_bus_type, NULL, cell); 404 if (!dev) { 405 printk(KERN_ERR "failed to find device for cell %s\n", cell); 406 return -ENODEV; 407 } 408 pdev = to_platform_device(dev); 409 memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry)); 410 411 WARN_ON(!cell_entry.enable); 412 413 for (i = 0; i < n_clones; i++) { 414 cell_entry.name = clones[i]; 415 /* don't give up if a single call fails; just report error */ 416 if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, 417 cell_entry.usage_count, NULL, 0, NULL)) 418 dev_err(dev, "failed to create platform device '%s'\n", 419 clones[i]); 420 } 421 422 put_device(dev); 423 424 return 0; 425 } 426 EXPORT_SYMBOL(mfd_clone_cell); 427 428 MODULE_LICENSE("GPL"); 429 MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov"); 430