1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015, Sony Mobile Communications Inc. 4 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 5 */ 6 7 #include <linux/interrupt.h> 8 #include <linux/mailbox_client.h> 9 #include <linux/mfd/syscon.h> 10 #include <linux/module.h> 11 #include <linux/of_irq.h> 12 #include <linux/platform_device.h> 13 #include <linux/spinlock.h> 14 #include <linux/regmap.h> 15 #include <linux/soc/qcom/smem.h> 16 #include <linux/soc/qcom/smem_state.h> 17 18 /* 19 * This driver implements the Qualcomm Shared Memory State Machine, a mechanism 20 * for communicating single bit state information to remote processors. 21 * 22 * The implementation is based on two sections of shared memory; the first 23 * holding the state bits and the second holding a matrix of subscription bits. 24 * 25 * The state bits are structured in entries of 32 bits, each belonging to one 26 * system in the SoC. The entry belonging to the local system is considered 27 * read-write, while the rest should be considered read-only. 28 * 29 * The subscription matrix consists of N bitmaps per entry, denoting interest 30 * in updates of the entry for each of the N hosts. Upon updating a state bit 31 * each host's subscription bitmap should be queried and the remote system 32 * should be interrupted if they request so. 33 * 34 * The subscription matrix is laid out in entry-major order: 35 * entry0: [host0 ... hostN] 36 * . 37 * . 38 * entryM: [host0 ... hostN] 39 * 40 * A third, optional, shared memory region might contain information regarding 41 * the number of entries in the state bitmap as well as number of columns in 42 * the subscription matrix. 43 */ 44 45 /* 46 * Shared memory identifiers, used to acquire handles to respective memory 47 * region. 48 */ 49 #define SMEM_SMSM_SHARED_STATE 85 50 #define SMEM_SMSM_CPU_INTR_MASK 333 51 #define SMEM_SMSM_SIZE_INFO 419 52 53 /* 54 * Default sizes, in case SMEM_SMSM_SIZE_INFO is not found. 55 */ 56 #define SMSM_DEFAULT_NUM_ENTRIES 8 57 #define SMSM_DEFAULT_NUM_HOSTS 3 58 59 struct smsm_entry; 60 struct smsm_host; 61 62 /** 63 * struct qcom_smsm - smsm driver context 64 * @dev: smsm device pointer 65 * @local_host: column in the subscription matrix representing this system 66 * @num_hosts: number of columns in the subscription matrix 67 * @num_entries: number of entries in the state map and rows in the subscription 68 * matrix 69 * @local_state: pointer to the local processor's state bits 70 * @subscription: pointer to local processor's row in subscription matrix 71 * @state: smem state handle 72 * @lock: spinlock for read-modify-write of the outgoing state 73 * @entries: context for each of the entries 74 * @hosts: context for each of the hosts 75 * @mbox_client: mailbox client handle 76 */ 77 struct qcom_smsm { 78 struct device *dev; 79 80 u32 local_host; 81 82 u32 num_hosts; 83 u32 num_entries; 84 85 u32 __iomem *local_state; 86 u32 __iomem *subscription; 87 struct qcom_smem_state *state; 88 89 spinlock_t lock; 90 91 struct smsm_entry *entries; 92 struct smsm_host *hosts; 93 94 struct mbox_client mbox_client; 95 }; 96 97 /** 98 * struct smsm_entry - per remote processor entry context 99 * @smsm: back-reference to driver context 100 * @domain: IRQ domain for this entry, if representing a remote system 101 * @irq_enabled: bitmap of which state bits IRQs are enabled 102 * @irq_rising: bitmap tracking if rising bits should be propagated 103 * @irq_falling: bitmap tracking if falling bits should be propagated 104 * @last_value: snapshot of state bits last time the interrupts where propagated 105 * @remote_state: pointer to this entry's state bits 106 * @subscription: pointer to a row in the subscription matrix representing this 107 * entry 108 */ 109 struct smsm_entry { 110 struct qcom_smsm *smsm; 111 112 struct irq_domain *domain; 113 DECLARE_BITMAP(irq_enabled, 32); 114 DECLARE_BITMAP(irq_rising, 32); 115 DECLARE_BITMAP(irq_falling, 32); 116 unsigned long last_value; 117 118 u32 __iomem *remote_state; 119 u32 __iomem *subscription; 120 }; 121 122 /** 123 * struct smsm_host - representation of a remote host 124 * @ipc_regmap: regmap for outgoing interrupt 125 * @ipc_offset: offset in @ipc_regmap for outgoing interrupt 126 * @ipc_bit: bit in @ipc_regmap + @ipc_offset for outgoing interrupt 127 * @mbox_chan: apcs ipc mailbox channel handle 128 */ 129 struct smsm_host { 130 struct regmap *ipc_regmap; 131 int ipc_offset; 132 int ipc_bit; 133 134 struct mbox_chan *mbox_chan; 135 }; 136 137 /** 138 * smsm_update_bits() - change bit in outgoing entry and inform subscribers 139 * @data: smsm context pointer 140 * @mask: value mask 141 * @value: new value 142 * 143 * Used to set and clear the bits in the outgoing/local entry and inform 144 * subscribers about the change. 145 */ 146 static int smsm_update_bits(void *data, u32 mask, u32 value) 147 { 148 struct qcom_smsm *smsm = data; 149 struct smsm_host *hostp; 150 unsigned long flags; 151 u32 changes; 152 u32 host; 153 u32 orig; 154 u32 val; 155 156 spin_lock_irqsave(&smsm->lock, flags); 157 158 /* Update the entry */ 159 val = orig = readl(smsm->local_state); 160 val &= ~mask; 161 val |= value; 162 163 /* Don't signal if we didn't change the value */ 164 changes = val ^ orig; 165 if (!changes) { 166 spin_unlock_irqrestore(&smsm->lock, flags); 167 goto done; 168 } 169 170 /* Write out the new value */ 171 writel(val, smsm->local_state); 172 spin_unlock_irqrestore(&smsm->lock, flags); 173 174 /* Make sure the value update is ordered before any kicks */ 175 wmb(); 176 177 /* Iterate over all hosts to check whom wants a kick */ 178 for (host = 0; host < smsm->num_hosts; host++) { 179 hostp = &smsm->hosts[host]; 180 181 val = readl(smsm->subscription + host); 182 if (!(val & changes)) 183 continue; 184 185 if (hostp->mbox_chan) { 186 mbox_send_message(hostp->mbox_chan, NULL); 187 mbox_client_txdone(hostp->mbox_chan, 0); 188 } else if (hostp->ipc_regmap) { 189 regmap_write(hostp->ipc_regmap, 190 hostp->ipc_offset, 191 BIT(hostp->ipc_bit)); 192 } 193 } 194 195 done: 196 return 0; 197 } 198 199 static const struct qcom_smem_state_ops smsm_state_ops = { 200 .update_bits = smsm_update_bits, 201 }; 202 203 /** 204 * smsm_intr() - cascading IRQ handler for SMSM 205 * @irq: unused 206 * @data: entry related to this IRQ 207 * 208 * This function cascades an incoming interrupt from a remote system, based on 209 * the state bits and configuration. 210 */ 211 static irqreturn_t smsm_intr(int irq, void *data) 212 { 213 struct smsm_entry *entry = data; 214 unsigned i; 215 int irq_pin; 216 u32 changed; 217 u32 val; 218 219 val = readl(entry->remote_state); 220 changed = val ^ xchg(&entry->last_value, val); 221 222 for_each_set_bit(i, entry->irq_enabled, 32) { 223 if (!(changed & BIT(i))) 224 continue; 225 226 if (val & BIT(i)) { 227 if (test_bit(i, entry->irq_rising)) { 228 irq_pin = irq_find_mapping(entry->domain, i); 229 handle_nested_irq(irq_pin); 230 } 231 } else { 232 if (test_bit(i, entry->irq_falling)) { 233 irq_pin = irq_find_mapping(entry->domain, i); 234 handle_nested_irq(irq_pin); 235 } 236 } 237 } 238 239 return IRQ_HANDLED; 240 } 241 242 /** 243 * smsm_mask_irq() - un-subscribe from cascades of IRQs of a certain staus bit 244 * @irqd: IRQ handle to be masked 245 * 246 * This un-subscribes the local CPU from interrupts upon changes to the defines 247 * status bit. The bit is also cleared from cascading. 248 */ 249 static void smsm_mask_irq(struct irq_data *irqd) 250 { 251 struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); 252 irq_hw_number_t irq = irqd_to_hwirq(irqd); 253 struct qcom_smsm *smsm = entry->smsm; 254 u32 val; 255 256 if (entry->subscription) { 257 val = readl(entry->subscription + smsm->local_host); 258 val &= ~BIT(irq); 259 writel(val, entry->subscription + smsm->local_host); 260 } 261 262 clear_bit(irq, entry->irq_enabled); 263 } 264 265 /** 266 * smsm_unmask_irq() - subscribe to cascades of IRQs of a certain status bit 267 * @irqd: IRQ handle to be unmasked 268 * 269 * This subscribes the local CPU to interrupts upon changes to the defined 270 * status bit. The bit is also marked for cascading. 271 */ 272 static void smsm_unmask_irq(struct irq_data *irqd) 273 { 274 struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); 275 irq_hw_number_t irq = irqd_to_hwirq(irqd); 276 struct qcom_smsm *smsm = entry->smsm; 277 u32 val; 278 279 /* Make sure our last cached state is up-to-date */ 280 assign_bit(irq, &entry->last_value, 281 readl(entry->remote_state) & BIT(irq)); 282 283 set_bit(irq, entry->irq_enabled); 284 285 if (entry->subscription) { 286 val = readl(entry->subscription + smsm->local_host); 287 val |= BIT(irq); 288 writel(val, entry->subscription + smsm->local_host); 289 } 290 } 291 292 /** 293 * smsm_set_irq_type() - updates the requested IRQ type for the cascading 294 * @irqd: consumer interrupt handle 295 * @type: requested flags 296 */ 297 static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type) 298 { 299 struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); 300 irq_hw_number_t irq = irqd_to_hwirq(irqd); 301 302 if (!(type & IRQ_TYPE_EDGE_BOTH)) 303 return -EINVAL; 304 305 assign_bit(irq, entry->irq_rising, type & IRQ_TYPE_EDGE_RISING); 306 307 assign_bit(irq, entry->irq_falling, type & IRQ_TYPE_EDGE_FALLING); 308 309 return 0; 310 } 311 312 static int smsm_get_irqchip_state(struct irq_data *irqd, 313 enum irqchip_irq_state which, bool *state) 314 { 315 struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd); 316 irq_hw_number_t irq = irqd_to_hwirq(irqd); 317 u32 val; 318 319 if (which != IRQCHIP_STATE_LINE_LEVEL) 320 return -EINVAL; 321 322 val = readl(entry->remote_state); 323 *state = !!(val & BIT(irq)); 324 325 return 0; 326 } 327 328 static struct irq_chip smsm_irq_chip = { 329 .name = "smsm", 330 .irq_mask = smsm_mask_irq, 331 .irq_unmask = smsm_unmask_irq, 332 .irq_set_type = smsm_set_irq_type, 333 .irq_get_irqchip_state = smsm_get_irqchip_state, 334 }; 335 336 /** 337 * smsm_irq_map() - sets up a mapping for a cascaded IRQ 338 * @d: IRQ domain representing an entry 339 * @irq: IRQ to set up 340 * @hw: unused 341 */ 342 static int smsm_irq_map(struct irq_domain *d, 343 unsigned int irq, 344 irq_hw_number_t hw) 345 { 346 struct smsm_entry *entry = d->host_data; 347 348 irq_set_chip_and_handler(irq, &smsm_irq_chip, handle_level_irq); 349 irq_set_chip_data(irq, entry); 350 irq_set_nested_thread(irq, 1); 351 352 return 0; 353 } 354 355 static const struct irq_domain_ops smsm_irq_ops = { 356 .map = smsm_irq_map, 357 .xlate = irq_domain_xlate_twocell, 358 }; 359 360 /** 361 * smsm_parse_mbox() - requests an mbox channel 362 * @smsm: smsm driver context 363 * @host_id: index of the remote host to be resolved 364 * 365 * Requests the desired channel using the mbox interface which is needed for 366 * sending the outgoing interrupts to a remove hosts - identified by @host_id. 367 */ 368 static int smsm_parse_mbox(struct qcom_smsm *smsm, unsigned int host_id) 369 { 370 struct smsm_host *host = &smsm->hosts[host_id]; 371 int ret = 0; 372 373 host->mbox_chan = mbox_request_channel(&smsm->mbox_client, host_id); 374 if (IS_ERR(host->mbox_chan)) { 375 ret = PTR_ERR(host->mbox_chan); 376 host->mbox_chan = NULL; 377 } 378 379 return ret; 380 } 381 382 /** 383 * smsm_parse_ipc() - parses a qcom,ipc-%d device tree property 384 * @smsm: smsm driver context 385 * @host_id: index of the remote host to be resolved 386 * 387 * Parses device tree to acquire the information needed for sending the 388 * outgoing interrupts to a remote host - identified by @host_id. 389 */ 390 static int smsm_parse_ipc(struct qcom_smsm *smsm, unsigned host_id) 391 { 392 struct device_node *syscon; 393 struct device_node *node = smsm->dev->of_node; 394 struct smsm_host *host = &smsm->hosts[host_id]; 395 char key[16]; 396 int ret; 397 398 snprintf(key, sizeof(key), "qcom,ipc-%d", host_id); 399 syscon = of_parse_phandle(node, key, 0); 400 if (!syscon) 401 return 0; 402 403 host->ipc_regmap = syscon_node_to_regmap(syscon); 404 of_node_put(syscon); 405 if (IS_ERR(host->ipc_regmap)) 406 return PTR_ERR(host->ipc_regmap); 407 408 ret = of_property_read_u32_index(node, key, 1, &host->ipc_offset); 409 if (ret < 0) { 410 dev_err(smsm->dev, "no offset in %s\n", key); 411 return -EINVAL; 412 } 413 414 ret = of_property_read_u32_index(node, key, 2, &host->ipc_bit); 415 if (ret < 0) { 416 dev_err(smsm->dev, "no bit in %s\n", key); 417 return -EINVAL; 418 } 419 420 return 0; 421 } 422 423 /** 424 * smsm_inbound_entry() - parse DT and set up an entry representing a remote system 425 * @smsm: smsm driver context 426 * @entry: entry context to be set up 427 * @node: dt node containing the entry's properties 428 */ 429 static int smsm_inbound_entry(struct qcom_smsm *smsm, 430 struct smsm_entry *entry, 431 struct device_node *node) 432 { 433 int ret; 434 int irq; 435 436 irq = irq_of_parse_and_map(node, 0); 437 if (!irq) { 438 dev_err(smsm->dev, "failed to parse smsm interrupt\n"); 439 return -EINVAL; 440 } 441 442 ret = devm_request_threaded_irq(smsm->dev, irq, 443 NULL, smsm_intr, 444 IRQF_ONESHOT, 445 "smsm", (void *)entry); 446 if (ret) 447 return ret; 448 449 entry->domain = irq_domain_create_linear(of_fwnode_handle(node), 32, &smsm_irq_ops, entry); 450 if (!entry->domain) { 451 dev_err(smsm->dev, "failed to add irq_domain\n"); 452 return -ENOMEM; 453 } 454 455 return 0; 456 } 457 458 /** 459 * smsm_get_size_info() - parse the optional memory segment for sizes 460 * @smsm: smsm driver context 461 * 462 * Attempt to acquire the number of hosts and entries from the optional shared 463 * memory location. Not being able to find this segment should indicate that 464 * we're on a older system where these values was hard coded to 465 * SMSM_DEFAULT_NUM_ENTRIES and SMSM_DEFAULT_NUM_HOSTS. 466 * 467 * Returns 0 on success, negative errno on failure. 468 */ 469 static int smsm_get_size_info(struct qcom_smsm *smsm) 470 { 471 size_t size; 472 struct { 473 u32 num_hosts; 474 u32 num_entries; 475 u32 reserved0; 476 u32 reserved1; 477 } *info; 478 479 info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SIZE_INFO, &size); 480 if (IS_ERR(info) && PTR_ERR(info) != -ENOENT) 481 return dev_err_probe(smsm->dev, PTR_ERR(info), 482 "unable to retrieve smsm size info\n"); 483 else if (IS_ERR(info) || size != sizeof(*info)) { 484 dev_warn(smsm->dev, "no smsm size info, using defaults\n"); 485 smsm->num_entries = SMSM_DEFAULT_NUM_ENTRIES; 486 smsm->num_hosts = SMSM_DEFAULT_NUM_HOSTS; 487 return 0; 488 } 489 490 smsm->num_entries = info->num_entries; 491 smsm->num_hosts = info->num_hosts; 492 493 dev_dbg(smsm->dev, 494 "found custom size of smsm: %d entries %d hosts\n", 495 smsm->num_entries, smsm->num_hosts); 496 497 return 0; 498 } 499 500 static int qcom_smsm_probe(struct platform_device *pdev) 501 { 502 struct device_node *local_node; 503 struct device_node *node; 504 struct smsm_entry *entry; 505 struct qcom_smsm *smsm; 506 u32 __iomem *intr_mask; 507 size_t size; 508 u32 __iomem *states; 509 u32 id; 510 int ret; 511 512 smsm = devm_kzalloc(&pdev->dev, sizeof(*smsm), GFP_KERNEL); 513 if (!smsm) 514 return -ENOMEM; 515 smsm->dev = &pdev->dev; 516 spin_lock_init(&smsm->lock); 517 518 ret = smsm_get_size_info(smsm); 519 if (ret) 520 return ret; 521 522 smsm->entries = devm_kcalloc(&pdev->dev, 523 smsm->num_entries, 524 sizeof(struct smsm_entry), 525 GFP_KERNEL); 526 if (!smsm->entries) 527 return -ENOMEM; 528 529 smsm->hosts = devm_kcalloc(&pdev->dev, 530 smsm->num_hosts, 531 sizeof(struct smsm_host), 532 GFP_KERNEL); 533 if (!smsm->hosts) 534 return -ENOMEM; 535 536 for_each_child_of_node(pdev->dev.of_node, local_node) { 537 if (of_property_present(local_node, "#qcom,smem-state-cells")) 538 break; 539 } 540 if (!local_node) { 541 dev_err(&pdev->dev, "no state entry\n"); 542 return -EINVAL; 543 } 544 545 of_property_read_u32(pdev->dev.of_node, 546 "qcom,local-host", 547 &smsm->local_host); 548 549 smsm->mbox_client.dev = &pdev->dev; 550 smsm->mbox_client.knows_txdone = true; 551 552 /* Parse the host properties */ 553 for (id = 0; id < smsm->num_hosts; id++) { 554 /* Try using mbox interface first, otherwise fall back to syscon */ 555 ret = smsm_parse_mbox(smsm, id); 556 if (!ret) 557 continue; 558 559 ret = smsm_parse_ipc(smsm, id); 560 if (ret < 0) 561 goto out_put; 562 } 563 564 /* Acquire the main SMSM state vector */ 565 ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, 566 smsm->num_entries * sizeof(u32)); 567 if (ret < 0 && ret != -EEXIST) { 568 dev_err(&pdev->dev, "unable to allocate shared state entry\n"); 569 goto out_put; 570 } 571 572 states = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL); 573 if (IS_ERR(states)) { 574 dev_err(&pdev->dev, "Unable to acquire shared state entry\n"); 575 ret = PTR_ERR(states); 576 goto out_put; 577 } 578 579 /* Acquire the list of interrupt mask vectors */ 580 size = smsm->num_entries * smsm->num_hosts * sizeof(u32); 581 ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size); 582 if (ret < 0 && ret != -EEXIST) { 583 dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n"); 584 goto out_put; 585 } 586 587 intr_mask = (u32 __iomem *)qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL); 588 if (IS_ERR(intr_mask)) { 589 dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n"); 590 ret = PTR_ERR(intr_mask); 591 goto out_put; 592 } 593 594 /* Setup the reference to the local state bits */ 595 smsm->local_state = states + smsm->local_host; 596 smsm->subscription = intr_mask + smsm->local_host * smsm->num_hosts; 597 598 /* Register the outgoing state */ 599 smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm); 600 if (IS_ERR(smsm->state)) { 601 dev_err(smsm->dev, "failed to register qcom_smem_state\n"); 602 ret = PTR_ERR(smsm->state); 603 goto out_put; 604 } 605 606 /* Register handlers for remote processor entries of interest. */ 607 for_each_available_child_of_node(pdev->dev.of_node, node) { 608 if (!of_property_read_bool(node, "interrupt-controller")) 609 continue; 610 611 ret = of_property_read_u32(node, "reg", &id); 612 if (ret || id >= smsm->num_entries) { 613 dev_err(&pdev->dev, "invalid reg of entry\n"); 614 if (!ret) 615 ret = -EINVAL; 616 goto unwind_interfaces; 617 } 618 entry = &smsm->entries[id]; 619 620 entry->smsm = smsm; 621 entry->remote_state = states + id; 622 623 /* Setup subscription pointers and unsubscribe to any kicks */ 624 entry->subscription = intr_mask + id * smsm->num_hosts; 625 writel(0, entry->subscription + smsm->local_host); 626 627 ret = smsm_inbound_entry(smsm, entry, node); 628 if (ret < 0) 629 goto unwind_interfaces; 630 } 631 632 platform_set_drvdata(pdev, smsm); 633 of_node_put(local_node); 634 635 return 0; 636 637 unwind_interfaces: 638 of_node_put(node); 639 for (id = 0; id < smsm->num_entries; id++) 640 if (smsm->entries[id].domain) 641 irq_domain_remove(smsm->entries[id].domain); 642 643 qcom_smem_state_unregister(smsm->state); 644 out_put: 645 for (id = 0; id < smsm->num_hosts; id++) 646 mbox_free_channel(smsm->hosts[id].mbox_chan); 647 648 of_node_put(local_node); 649 return ret; 650 } 651 652 static void qcom_smsm_remove(struct platform_device *pdev) 653 { 654 struct qcom_smsm *smsm = platform_get_drvdata(pdev); 655 unsigned id; 656 657 for (id = 0; id < smsm->num_entries; id++) 658 if (smsm->entries[id].domain) 659 irq_domain_remove(smsm->entries[id].domain); 660 661 for (id = 0; id < smsm->num_hosts; id++) 662 mbox_free_channel(smsm->hosts[id].mbox_chan); 663 664 qcom_smem_state_unregister(smsm->state); 665 } 666 667 static const struct of_device_id qcom_smsm_of_match[] = { 668 { .compatible = "qcom,smsm" }, 669 {} 670 }; 671 MODULE_DEVICE_TABLE(of, qcom_smsm_of_match); 672 673 static struct platform_driver qcom_smsm_driver = { 674 .probe = qcom_smsm_probe, 675 .remove = qcom_smsm_remove, 676 .driver = { 677 .name = "qcom-smsm", 678 .of_match_table = qcom_smsm_of_match, 679 }, 680 }; 681 module_platform_driver(qcom_smsm_driver); 682 683 MODULE_DESCRIPTION("Qualcomm Shared Memory State Machine driver"); 684 MODULE_LICENSE("GPL v2"); 685