/** * print_smd_ch_table - Print the current state of every valid SMD channel in a * specific SMD channel allocation table to a human * readable formatted output. * * @s: the sequential file to print to * @tbl: a valid pointer to the channel allocation table to print from * @num_tbl_entries: total number of entries in the table referenced by @tbl * @ch_base_id: the SMEM item id corresponding to the array of channel * structures for the channels found in @tbl * @fifo_base_id: the SMEM item id corresponding to the array of channel fifos * for the channels found in @tbl * @pid: processor id to use for any SMEM operations * @flags: flags to use for any SMEM operations */ static void print_smd_ch_table(struct seq_file *s, struct smd_alloc_elm *tbl, unsigned num_tbl_entries, unsigned ch_base_id, unsigned fifo_base_id, unsigned pid, unsigned flags) { void *half_ch; unsigned half_ch_size; uint32_t ch_type; void *buffer; unsigned buffer_size; int n; /* * formatted, human readable channel state output, ie: ID|CHANNEL NAME |T|PROC |STATE |FIFO SZ|RDPTR |WRPTR |FLAGS |DATAPEN ------------------------------------------------------------------------------- 00|DS |S|APPS |CLOSED |0x02000|0x00000|0x00000|dcCiwrsb|0x00000 | | |MDMSW|OPENING|0x02000|0x00000|0x00000|dcCiwrsb|0x00000 ------------------------------------------------------------------------------- */ seq_printf(s, "%2s|%-19s|%1s|%-5s|%-7s|%-7s|%-7s|%-7s|%-8s|%-7s\n", "ID", "CHANNEL NAME", "T", "PROC", "STATE", "FIFO SZ", "RDPTR", "WRPTR", "FLAGS", "DATAPEN"); seq_puts(s, "-------------------------------------------------------------------------------\n"); for (n = 0; n < num_tbl_entries; ++n) { if (strlen(tbl[n].name) == 0) continue; seq_printf(s, "%2u|%-19s|%s|", tbl[n].cid, tbl[n].name, smd_xfer_type_to_str(SMD_XFER_TYPE(tbl[n].type))); ch_type = SMD_CHANNEL_TYPE(tbl[n].type); if (is_word_access_ch(ch_type)) half_ch_size = sizeof(struct smd_half_channel_word_access); else half_ch_size = sizeof(struct smd_half_channel); half_ch = smem_find(ch_base_id + n, 2 * half_ch_size, pid, flags); buffer = smem_get_entry(fifo_base_id + n, &buffer_size, pid, flags); if (half_ch && buffer) print_half_ch_state(s, half_ch, get_half_ch_funcs(ch_type), buffer_size / 2, smd_edge_to_local_pid(ch_type)); seq_puts(s, "\n"); seq_printf(s, "%2s|%-19s|%1s|", "", "", ""); if (half_ch && buffer) print_half_ch_state(s, half_ch + half_ch_size, get_half_ch_funcs(ch_type), buffer_size / 2, smd_edge_to_remote_pid(ch_type)); seq_puts(s, "\n"); seq_puts(s, "-------------------------------------------------------------------------------\n"); } }
static int msm_smsm_probe(struct platform_device *pdev) { uint32_t edge; char *key; int ret; uint32_t irq_offset; uint32_t irq_bitmask; uint32_t irq_line; struct interrupt_config_item *private_irq; struct device_node *node; void *irq_out_base; resource_size_t irq_out_size; struct platform_device *parent_pdev; struct resource *r; struct interrupt_config *private_intr_config; uint32_t remote_pid; disable_smsm_reset_handshake = 1; node = pdev->dev.of_node; if (!pdev->dev.parent) { pr_err("%s: missing link to parent device\n", __func__); return -ENODEV; } parent_pdev = to_platform_device(pdev->dev.parent); key = "irq-reg-base"; r = platform_get_resource_byname(parent_pdev, IORESOURCE_MEM, key); if (!r) goto missing_key; irq_out_size = resource_size(r); irq_out_base = ioremap_nocache(r->start, irq_out_size); if (!irq_out_base) { pr_err("%s: ioremap_nocache() of irq_out_base addr:%pr size:%pr\n", __func__, &r->start, &irq_out_size); return -ENOMEM; } SMSM_DBG("%s: %s = %p", __func__, key, irq_out_base); key = "qcom,smsm-edge"; ret = of_property_read_u32(node, key, &edge); if (ret) goto missing_key; SMSM_DBG("%s: %s = %d", __func__, key, edge); key = "qcom,smsm-irq-offset"; ret = of_property_read_u32(node, key, &irq_offset); if (ret) goto missing_key; SMSM_DBG("%s: %s = %x", __func__, key, irq_offset); key = "qcom,smsm-irq-bitmask"; ret = of_property_read_u32(node, key, &irq_bitmask); if (ret) goto missing_key; SMSM_DBG("%s: %s = %x", __func__, key, irq_bitmask); key = "interrupts"; irq_line = irq_of_parse_and_map(node, 0); if (!irq_line) goto missing_key; SMSM_DBG("%s: %s = %d", __func__, key, irq_line); private_intr_config = smd_get_intr_config(edge); if (!private_intr_config) { pr_err("%s: invalid edge\n", __func__); return -ENODEV; } private_irq = &private_intr_config->smsm; private_irq->out_bit_pos = irq_bitmask; private_irq->out_offset = irq_offset; private_irq->out_base = irq_out_base; private_irq->irq_id = irq_line; remote_pid = smd_edge_to_remote_pid(edge); interrupt_stats[remote_pid].smsm_interrupt_id = irq_line; ret = request_irq(irq_line, private_irq->irq_handler, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "smsm_dev", NULL); if (ret < 0) { pr_err("%s: request_irq() failed on %d\n", __func__, irq_line); return ret; } else { ret = enable_irq_wake(irq_line); if (ret < 0) pr_err("%s: enable_irq_wake() failed on %d\n", __func__, irq_line); } ret = smsm_post_init(); if (ret) { pr_err("smd_post_init() failed ret=%d\n", ret); return ret; } return 0; missing_key: pr_err("%s: missing key: %s", __func__, key); return -ENODEV; }