diff --git a/Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml b/Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml index dada28b47ea0..2900224aac74 100644 --- a/Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml +++ b/Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml @@ -15,6 +15,9 @@ description: | represented by CTRLMMR_xxx_JTAGID register which contains information about SoC id and revision. + On some SoCs like AM62P, the silicon revision is determined by reading + alternative registers via NVMEM cells. + properties: $nodename: pattern: "^chipid@[0-9a-f]+$" @@ -26,6 +29,14 @@ properties: reg: maxItems: 1 + nvmem-cells: + items: + - description: Alternate silicon revision register + + nvmem-cell-names: + items: + - const: gpsw1 + required: - compatible - reg diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 9d5071223f4c..7c0f7b3e89e0 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -47,6 +47,8 @@ struct sci_clk_provider { * @node: Link for handling clocks probed via DT * @cached_req: Cached requested freq for determine rate calls * @cached_res: Cached result freq for determine rate calls + * @parent_id: Parent index for this clock + * @rate: Clock rate */ struct sci_clk { struct clk_hw hw; @@ -58,6 +60,8 @@ struct sci_clk { struct list_head node; unsigned long cached_req; unsigned long cached_res; + int parent_id; + unsigned long rate; }; #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw) @@ -150,6 +154,8 @@ static unsigned long sci_clk_recalc_rate(struct clk_hw *hw, return 0; } + clk->rate = freq; + return freq; } @@ -210,10 +216,15 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct sci_clk *clk = to_sci_clk(hw); + int ret; - return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, - clk->clk_id, rate / 10 * 9, rate, - rate / 10 * 11); + ret = clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, + clk->clk_id, rate / 10 * 9, rate, + rate / 10 * 11); + if (!ret) + clk->rate = rate; + + return ret; } /** @@ -234,12 +245,13 @@ static u8 sci_clk_get_parent(struct clk_hw *hw) dev_err(clk->provider->dev, "get-parent failed for dev=%d, clk=%d, ret=%d\n", clk->dev_id, clk->clk_id, ret); + clk->parent_id = ret; return 0; } - parent_id = parent_id - clk->clk_id - 1; + clk->parent_id = parent_id - clk->clk_id - 1; - return (u8)parent_id; + return (u8)clk->parent_id; } /** @@ -252,12 +264,28 @@ static u8 sci_clk_get_parent(struct clk_hw *hw) static int sci_clk_set_parent(struct clk_hw *hw, u8 index) { struct sci_clk *clk = to_sci_clk(hw); + int ret; clk->cached_req = 0; - return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, - clk->clk_id, - index + 1 + clk->clk_id); + ret = clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, + clk->clk_id, + index + 1 + clk->clk_id); + if (!ret) + clk->parent_id = index; + + return ret; +} + +static void sci_clk_restore_context(struct clk_hw *hw) +{ + struct sci_clk *clk = to_sci_clk(hw); + + if (clk->num_parents > 1 && clk->parent_id >= 0) + sci_clk_set_parent(hw, (u8)clk->parent_id); + + if (clk->rate) + sci_clk_set_rate(hw, clk->rate, 0); } static const struct clk_ops sci_clk_ops = { @@ -269,6 +297,7 @@ static const struct clk_ops sci_clk_ops = { .set_rate = sci_clk_set_rate, .get_parent = sci_clk_get_parent, .set_parent = sci_clk_set_parent, + .restore_context = sci_clk_restore_context, }; /** diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index e027a2bd8f26..590a464403c5 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -9,14 +9,17 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include +#include #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -87,6 +90,16 @@ struct ti_sci_desc { int max_msg_size; }; +/** + * struct ti_sci_irq - Description of allocated irqs + * @node: Link to hash table + * @desc: Description of the irq + */ +struct ti_sci_irq { + struct hlist_node node; + struct ti_sci_msg_req_manage_irq desc; +}; + /** * struct ti_sci_info - Structure representing a TI SCI instance * @dev: Device pointer @@ -101,6 +114,8 @@ struct ti_sci_desc { * @chan_rx: Receive mailbox channel * @minfo: Message info * @node: list head + * @irqs: List of allocated irqs + * @irq_lock: Protection for irq hash list * @host_id: Host ID * @fw_caps: FW/SoC low power capabilities * @users: Number of users of this instance @@ -118,6 +133,8 @@ struct ti_sci_info { struct mbox_chan *chan_rx; struct ti_sci_xfers_info minfo; struct list_head node; + DECLARE_HASHTABLE(irqs, 8); + struct mutex irq_lock; u8 host_id; u64 fw_caps; /* protected by ti_sci_list_mutex */ @@ -2299,6 +2316,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle, return ret; } +/** + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table. + * @irq: irq to hash + * + * Return: the computed hash value. + */ +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq) +{ + return irq->src_id ^ irq->src_index; +} + +/** + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not + * compared) + * @irq_a: irq_a to compare + * @irq_b: irq_b to compare + * + * Return: true if the two irqs are equal, else false. + */ +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a, + struct ti_sci_msg_req_manage_irq *irq_b) +{ + return !memcmp(&irq_a->valid_params, &irq_b->valid_params, + sizeof(*irq_a) - sizeof(irq_a->hdr)); +} + /** * ti_sci_set_irq() - Helper api to configure the irq route between the * requested source and destination @@ -2322,15 +2365,53 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params, u16 dst_host_irq, u16 ia_id, u16 vint, u16 global_event, u8 vint_status_bit, u8 s_host) { + struct ti_sci_info *info = handle_to_ti_sci_info(handle); + struct ti_sci_msg_req_manage_irq *desc; + struct ti_sci_irq *irq; + int ret; + + /* Lock for set_irq() and free_irq() to keep the IRQ hash list consistent */ + guard(mutex)(&info->irq_lock); + pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", __func__, valid_params, src_id, src_index, dst_id, dst_host_irq, ia_id, vint, global_event, vint_status_bit); - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, - dst_id, dst_host_irq, ia_id, vint, - global_event, vint_status_bit, s_host, - TI_SCI_MSG_SET_IRQ); + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_SET_IRQ); + + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) + goto end; + + irq = kzalloc_obj(*irq, GFP_KERNEL); + if (!irq) { + ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_FREE_IRQ); + ret = -ENOMEM; + goto end; + } + + desc = &irq->desc; + desc->valid_params = valid_params; + desc->src_id = src_id; + desc->src_index = src_index; + desc->dst_id = dst_id; + desc->dst_host_irq = dst_host_irq; + desc->ia_id = ia_id; + desc->vint = vint; + desc->global_event = global_event; + desc->vint_status_bit = vint_status_bit; + desc->secondary_host = s_host; + + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc)); + +end: + return ret; } /** @@ -2356,15 +2437,53 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params, u16 dst_host_irq, u16 ia_id, u16 vint, u16 global_event, u8 vint_status_bit, u8 s_host) { + struct ti_sci_info *info = handle_to_ti_sci_info(handle); + struct ti_sci_msg_req_manage_irq irq_desc; + struct device *dev = info->dev; + struct ti_sci_irq *this_irq; + struct hlist_node *tmp_node; + int ret; + + guard(mutex)(&info->irq_lock); + pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", __func__, valid_params, src_id, src_index, dst_id, dst_host_irq, ia_id, vint, global_event, vint_status_bit); - return ti_sci_manage_irq(handle, valid_params, src_id, src_index, - dst_id, dst_host_irq, ia_id, vint, - global_event, vint_status_bit, s_host, - TI_SCI_MSG_FREE_IRQ); + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index, + dst_id, dst_host_irq, ia_id, vint, + global_event, vint_status_bit, s_host, + TI_SCI_MSG_FREE_IRQ); + + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)) + goto end; + + irq_desc.valid_params = valid_params; + irq_desc.src_id = src_id; + irq_desc.src_index = src_index; + irq_desc.dst_id = dst_id; + irq_desc.dst_host_irq = dst_host_irq; + irq_desc.ia_id = ia_id; + irq_desc.vint = vint; + irq_desc.global_event = global_event; + irq_desc.vint_status_bit = vint_status_bit; + irq_desc.secondary_host = s_host; + + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node, + ti_sci_irq_hash(&irq_desc)) { + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) { + hlist_del(&this_irq->node); + kfree(this_irq); + goto end; + } + } + + dev_warn(dev, "%s: should not be here, IRQ was not found in hash list\n", + __func__); + +end: + return ret; } /** @@ -3770,8 +3889,11 @@ static int ti_sci_prepare_system_suspend(struct ti_sci_info *info) return ti_sci_cmd_prepare_sleep(&info->handle, TISCI_MSG_VALUE_SLEEP_MODE_DM_MANAGED, 0, 0, 0); + } else if (info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED) { + /* Nothing to do in the BOARDCFG_MANAGED mode */ + return 0; } else { - /* DM Managed is not supported by the firmware. */ + /* DM Managed and BoardCfg Managed are not supported by the firmware. */ dev_err(info->dev, "Suspend to memory is not supported by the firmware\n"); return -EOPNOTSUPP; } @@ -3842,7 +3964,10 @@ static int ti_sci_suspend_noirq(struct device *dev) static int ti_sci_resume_noirq(struct device *dev) { struct ti_sci_info *info = dev_get_drvdata(dev); - int ret = 0; + struct ti_sci_msg_req_manage_irq *irq_desc; + struct ti_sci_irq *irq; + struct hlist_node *tmp_node; + int ret = 0, err = 0, i; u32 source; u64 time; u8 pin; @@ -3854,13 +3979,53 @@ static int ti_sci_resume_noirq(struct device *dev) return ret; } + switch (pm_suspend_target_state) { + case PM_SUSPEND_MEM: + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) { + hash_for_each_safe(info->irqs, i, tmp_node, irq, node) { + irq_desc = &irq->desc; + ret = ti_sci_manage_irq(&info->handle, + irq_desc->valid_params, + irq_desc->src_id, + irq_desc->src_index, + irq_desc->dst_id, + irq_desc->dst_host_irq, + irq_desc->ia_id, + irq_desc->vint, + irq_desc->global_event, + irq_desc->vint_status_bit, + irq_desc->secondary_host, + TI_SCI_MSG_SET_IRQ); + if (ret) { + dev_err(dev, "failed to restore IRQ with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d, via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n", + irq_desc->valid_params, + irq_desc->src_id, + irq_desc->src_index, + irq_desc->dst_id, + irq_desc->dst_host_irq, + irq_desc->ia_id, + irq_desc->vint, + irq_desc->global_event, + irq_desc->vint_status_bit); + err = ret; + } + } + } + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST) + clk_restore_context(); + break; + default: + break; + } + ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode); /* Do not fail to resume on error as the wake reason is not critical */ if (!ret) dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n", source, pin, mode); - return 0; + return err; } static void ti_sci_pm_complete(struct device *dev) @@ -4009,12 +4174,15 @@ static int ti_sci_probe(struct platform_device *pdev) } ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps); - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s\n", + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s%s\n", info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "", info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "", - info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "" + info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : "", + info->fw_caps & MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST ? " Clk-Context-Lost" : "" ); ti_sci_setup_ops(info); @@ -4047,6 +4215,13 @@ static int ti_sci_probe(struct platform_device *pdev) list_add_tail(&info->node, &ti_sci_list); mutex_unlock(&ti_sci_list_mutex); + ret = devm_mutex_init(dev, &info->irq_lock); + if (ret) + goto out; + + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) + hash_init(info->irqs); + ret = of_platform_populate(dev->of_node, NULL, NULL, dev); if (ret) { dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret)); diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h index 4616127e33ff..8fccbcd1c9a2 100644 --- a/drivers/firmware/ti_sci.h +++ b/drivers/firmware/ti_sci.h @@ -150,6 +150,12 @@ struct ti_sci_msg_req_reboot { * MSG_FLAG_CAPS_LPM_DM_MANAGED: LPM can be managed by DM * MSG_FLAG_CAPS_LPM_ABORT: Abort entry to LPM * MSG_FLAG_CAPS_IO_ISOLATION: IO Isolation support + * MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED: LPM config done statically + * for the DM via boardcfg + * MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST: DM is not able to restore IRQ + * context + * MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST: DM is not able to restore + * Clock context * * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS * providing currently available SOC/firmware capabilities. SoC that don't @@ -162,6 +168,9 @@ struct ti_sci_msg_resp_query_fw_caps { #define MSG_FLAG_CAPS_LPM_DM_MANAGED TI_SCI_MSG_FLAG(5) #define MSG_FLAG_CAPS_LPM_ABORT TI_SCI_MSG_FLAG(9) #define MSG_FLAG_CAPS_IO_ISOLATION TI_SCI_MSG_FLAG(7) +#define MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED TI_SCI_MSG_FLAG(12) +#define MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST TI_SCI_MSG_FLAG(14) +#define MSG_FLAG_CAPS_LPM_CLK_CONTEXT_LOST TI_SCI_MSG_FLAG(15) #define MSG_MASK_CAPS_LPM GENMASK_ULL(4, 1) u64 fw_caps; } __packed; diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index 7602b8a909b0..5966db4327b1 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1012,7 +1013,7 @@ static int k3_ringacc_ring_pop_head_proxy(struct k3_ring *ring, void *elem) static int k3_ringacc_ring_pop_tail_proxy(struct k3_ring *ring, void *elem) { return k3_ringacc_ring_access_proxy(ring, elem, - K3_RINGACC_ACCESS_MODE_POP_HEAD); + K3_RINGACC_ACCESS_MODE_POP_TAIL); } static int k3_ringacc_ring_access_io(struct k3_ring *ring, void *elem, @@ -1083,7 +1084,7 @@ static int k3_ringacc_ring_pop_io(struct k3_ring *ring, void *elem) static int k3_ringacc_ring_pop_tail_io(struct k3_ring *ring, void *elem) { return k3_ringacc_ring_access_io(ring, elem, - K3_RINGACC_ACCESS_MODE_POP_HEAD); + K3_RINGACC_ACCESS_MODE_POP_TAIL); } /* @@ -1436,7 +1437,7 @@ static int k3_ringacc_init(struct platform_device *pdev, ringacc->rm_gp_range->desc[0].num, ringacc->tisci_dev_id); dev_info(dev, "dma-ring-reset-quirk: %s\n", - ringacc->dma_ring_reset_quirk ? "enabled" : "disabled"); + str_enabled_disabled(ringacc->dma_ring_reset_quirk)); dev_info(dev, "RA Proxy rev. %08x, num_proxies:%u\n", readl(&ringacc->proxy_gcfg->revision), ringacc->num_proxies); diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index 676041879eca..48dbef3acceb 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -6,6 +6,7 @@ */ #include +#include #include #include #include @@ -25,6 +26,8 @@ #define CTRLMMR_WKUP_JTAGID_VARIANT_SHIFT (28) #define CTRLMMR_WKUP_JTAGID_VARIANT_MASK GENMASK(31, 28) +#define GP_SW1_ADR_MASK GENMASK(3, 0) + #define CTRLMMR_WKUP_JTAGID_PARTNO_SHIFT (12) #define CTRLMMR_WKUP_JTAGID_PARTNO_MASK GENMASK(27, 12) @@ -70,6 +73,23 @@ static const char * const am62lx_rev_string_map[] = { "1.0", "1.1", }; +static const char * const am62p_gpsw_rev_string_map[] = { + "1.0", "1.1", "1.2", +}; + +static int +k3_chipinfo_get_gpsw_variant(struct device *dev) +{ + u32 gpsw_val = 0; + int ret; + + ret = nvmem_cell_read_u32(dev, "gpsw1", &gpsw_val); + if (ret) + return ret; + + return gpsw_val & GP_SW1_ADR_MASK; +} + static int k3_chipinfo_partno_to_names(unsigned int partno, struct soc_device_attribute *soc_dev_attr) @@ -86,9 +106,11 @@ k3_chipinfo_partno_to_names(unsigned int partno, } static int -k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, - struct soc_device_attribute *soc_dev_attr) +k3_chipinfo_variant_to_sr(struct device *dev, unsigned int partno, + unsigned int variant, struct soc_device_attribute *soc_dev_attr) { + int gpsw_variant = 0; + switch (partno) { case JTAG_ID_PARTNO_J721E: if (variant >= ARRAY_SIZE(j721e_rev_string_map)) @@ -102,6 +124,19 @@ k3_chipinfo_variant_to_sr(unsigned int partno, unsigned int variant, soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s", am62lx_rev_string_map[variant]); break; + case JTAG_ID_PARTNO_AM62PX: + /* Check GP_SW1 for silicon revision */ + gpsw_variant = k3_chipinfo_get_gpsw_variant(dev); + if (gpsw_variant == -EPROBE_DEFER) + return gpsw_variant; + if (gpsw_variant < 0 || gpsw_variant >= ARRAY_SIZE(am62p_gpsw_rev_string_map)) { + dev_warn(dev, "Failed to get silicon variant (%d), set SR1.0\n", + gpsw_variant); + gpsw_variant = 0; + } + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%s", + am62p_gpsw_rev_string_map[gpsw_variant]); + break; default: variant++; soc_dev_attr->revision = kasprintf(GFP_KERNEL, "SR%x.0", @@ -173,7 +208,7 @@ static int k3_chipinfo_probe(struct platform_device *pdev) goto err; } - ret = k3_chipinfo_variant_to_sr(partno_id, variant, soc_dev_attr); + ret = k3_chipinfo_variant_to_sr(dev, partno_id, variant, soc_dev_attr); if (ret) { dev_err(dev, "Unknown SoC SR[0x%08X]: %d\n", jtag_id, ret); goto err; diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index e5f5e3142fc4..96df3982e47b 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -29,7 +29,6 @@ #define DMA_TX_FILT_EINFO BIT(30) #define DMA_TX_PRIO_SHIFT 0 #define DMA_RX_PRIO_SHIFT 16 -#define DMA_PRIO_MASK GENMASK(3, 0) #define DMA_PRIO_DEFAULT 0 #define DMA_RX_TIMEOUT_DEFAULT 17500 /* cycles */ #define DMA_RX_TIMEOUT_MASK GENMASK(16, 0) @@ -388,11 +387,6 @@ static int of_channel_match_helper(struct device_node *np, const char *name, return -ENODEV; } - if (args.args[0] < 0) { - dev_err(kdev->dev, "Missing args for %s\n", name); - return -ENODEV; - } - return args.args[0]; } @@ -526,7 +520,7 @@ static void __iomem *pktdma_get_regs(struct knav_dma_device *dma, if (ret) { dev_err(dev, "Can't translate of node(%pOFn) address for index(%d)\n", node, index); - return ERR_PTR(ret); + return IOMEM_ERR_PTR(ret); } regs = devm_ioremap_resource(kdev->dev, &res); diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h index 9325e8ce2e25..037dc1b36645 100644 --- a/drivers/soc/ti/knav_qmss.h +++ b/drivers/soc/ti/knav_qmss.h @@ -123,7 +123,7 @@ struct knav_pdsp_info { const char *name; struct knav_reg_pdsp_regs __iomem *regs; union { - void __iomem *command; + u32 __iomem *command; struct knav_reg_acc_command __iomem *acc_command; u32 __iomem *qos_command; }; diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c index 269b4e75ae40..1f8b5acdd462 100644 --- a/drivers/soc/ti/knav_qmss_acc.c +++ b/drivers/soc/ti/knav_qmss_acc.c @@ -466,7 +466,7 @@ static const struct knav_range_ops knav_acc_range_ops = { * @node: device node * @range: qmms range information * - * Return 0 on success or error + * Return: 0 on success, errno otherwise. */ int knav_init_acc_range(struct knav_device *kdev, struct device_node *node, diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 86d7a9c9ae01..7410b63af0e6 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -25,11 +25,8 @@ #include "knav_qmss.h" -static struct knav_device *kdev; +static struct knav_device *knav_qdev; static DEFINE_MUTEX(knav_dev_lock); -#define knav_dev_lock_held() \ - lockdep_is_held(&knav_dev_lock) - /* Queue manager register indices in DTS */ #define KNAV_QUEUE_PEEK_REG_INDEX 0 #define KNAV_QUEUE_STATUS_REG_INDEX 1 @@ -58,7 +55,7 @@ static DEFINE_MUTEX(knav_dev_lock); #define for_each_handle_rcu(qh, inst) \ list_for_each_entry_rcu(qh, &inst->handles, list, \ - knav_dev_lock_held()) + lockdep_is_held(&knav_dev_lock)) #define for_each_instance(idx, inst, kdev) \ for (idx = 0, inst = kdev->instances; \ @@ -205,10 +202,10 @@ knav_queue_match_id_to_inst(struct knav_device *kdev, unsigned id) static inline struct knav_queue_inst *knav_queue_find_by_id(int id) { - if (kdev->base_id <= id && - kdev->base_id + kdev->num_queues > id) { - id -= kdev->base_id; - return knav_queue_match_id_to_inst(kdev, id); + if (knav_qdev->base_id <= id && + knav_qdev->base_id + knav_qdev->num_queues > id) { + id -= knav_qdev->base_id; + return knav_queue_match_id_to_inst(knav_qdev, id); } return NULL; } @@ -296,7 +293,7 @@ static struct knav_queue *knav_queue_open_by_type(const char *name, mutex_lock(&knav_dev_lock); - for_each_instance(idx, inst, kdev) { + for_each_instance(idx, inst, knav_qdev) { if (knav_queue_is_reserved(inst)) continue; if (!knav_queue_match_type(inst, type)) @@ -469,9 +466,9 @@ static int knav_queue_debug_show(struct seq_file *s, void *v) mutex_lock(&knav_dev_lock); seq_printf(s, "%s: %u-%u\n", - dev_name(kdev->dev), kdev->base_id, - kdev->base_id + kdev->num_queues - 1); - for_each_instance(idx, inst, kdev) + dev_name(knav_qdev->dev), knav_qdev->base_id, + knav_qdev->base_id + knav_qdev->num_queues - 1); + for_each_instance(idx, inst, knav_qdev) knav_queue_debug_show_instance(s, inst); mutex_unlock(&knav_dev_lock); @@ -480,8 +477,8 @@ static int knav_queue_debug_show(struct seq_file *s, void *v) DEFINE_SHOW_ATTRIBUTE(knav_queue_debug); -static inline int knav_queue_pdsp_wait(u32 * __iomem addr, unsigned timeout, - u32 flags) +static inline int knav_queue_pdsp_wait(u32 __iomem *addr, unsigned int timeout, + u32 flags) { unsigned long end; u32 val = 0; @@ -520,7 +517,7 @@ static int knav_queue_flush(struct knav_queue *qh) * Subsequent attempts to open a shared queue should * also have this flag. * - * Returns a handle to the open hardware queue if successful. Use IS_ERR() + * Return: handle to the open hardware queue on success. Use IS_ERR() * to check the returned value for error codes. */ void *knav_queue_open(const char *name, unsigned id, @@ -576,7 +573,7 @@ EXPORT_SYMBOL_GPL(knav_queue_close); * @cmd: - control commands * @arg: - command argument * - * Returns 0 on success, errno otherwise. + * Return: 0 on success, errno otherwise. */ int knav_queue_device_control(void *qhandle, enum knav_queue_ctrl_cmd cmd, unsigned long arg) @@ -628,7 +625,7 @@ EXPORT_SYMBOL_GPL(knav_queue_device_control); * @size: - size of data to push * @flags: - can be used to pass additional information * - * Returns 0 on success, errno otherwise. + * Return: 0 on success, errno otherwise. */ int knav_queue_push(void *qhandle, dma_addr_t dma, unsigned size, unsigned flags) @@ -649,7 +646,7 @@ EXPORT_SYMBOL_GPL(knav_queue_push); * @qhandle: - hardware queue handle * @size: - (optional) size of the data pop'ed. * - * Returns a DMA address on success, 0 on failure. + * Return: DMA address on success, 0 on failure. */ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size) { @@ -750,8 +747,8 @@ EXPORT_SYMBOL_GPL(knav_pool_desc_dma_to_virt); * @region_id: - QMSS region id from which the descriptors are to be * allocated. * - * Returns a pool handle on success. - * Use IS_ERR_OR_NULL() to identify error values on return. + * Return: pool handle on success. Use IS_ERR_OR_NULL() to identify + * error values on return. */ void *knav_pool_create(const char *name, int num_desc, int region_id) @@ -762,19 +759,17 @@ void *knav_pool_create(const char *name, unsigned last_offset; int ret; - if (!kdev) + if (!knav_qdev) return ERR_PTR(-EPROBE_DEFER); - if (!kdev->dev) + if (!knav_qdev->dev) return ERR_PTR(-ENODEV); - pool = devm_kzalloc(kdev->dev, sizeof(*pool), GFP_KERNEL); - if (!pool) { - dev_err(kdev->dev, "out of memory allocating pool\n"); + pool = devm_kzalloc(knav_qdev->dev, sizeof(*pool), GFP_KERNEL); + if (!pool) return ERR_PTR(-ENOMEM); - } - for_each_region(kdev, reg_itr) { + for_each_region(knav_qdev, reg_itr) { if (reg_itr->id != region_id) continue; region = reg_itr; @@ -782,28 +777,28 @@ void *knav_pool_create(const char *name, } if (!region) { - dev_err(kdev->dev, "region-id(%d) not found\n", region_id); + dev_err(knav_qdev->dev, "region-id(%d) not found\n", region_id); ret = -EINVAL; goto err; } pool->queue = knav_queue_open(name, KNAV_QUEUE_GP, 0); if (IS_ERR(pool->queue)) { - dev_err(kdev->dev, - "failed to open queue for pool(%s), error %ld\n", - name, PTR_ERR(pool->queue)); + dev_err(knav_qdev->dev, + "failed to open queue for pool(%s), error %pe\n", + name, pool->queue); ret = PTR_ERR(pool->queue); goto err; } pool->name = kstrndup(name, KNAV_NAME_SIZE - 1, GFP_KERNEL); - pool->kdev = kdev; - pool->dev = kdev->dev; + pool->kdev = knav_qdev; + pool->dev = knav_qdev->dev; mutex_lock(&knav_dev_lock); if (num_desc > (region->num_desc - region->used_desc)) { - dev_err(kdev->dev, "out of descs in region(%d) for pool(%s)\n", + dev_err(knav_qdev->dev, "out of descs in region(%d) for pool(%s)\n", region_id, name); ret = -ENOMEM; goto err_unlock; @@ -829,10 +824,10 @@ void *knav_pool_create(const char *name, pool->num_desc = num_desc; pool->region_offset = last_offset; region->used_desc += num_desc; - list_add_tail(&pool->list, &kdev->pools); + list_add_tail(&pool->list, &knav_qdev->pools); list_add_tail(&pool->region_inst, node); } else { - dev_err(kdev->dev, "pool(%s) create failed: fragmented desc pool in region(%d)\n", + dev_err(knav_qdev->dev, "pool(%s) create failed: fragmented desc pool in region(%d)\n", name, region_id); ret = -ENOMEM; goto err_unlock; @@ -846,7 +841,7 @@ void *knav_pool_create(const char *name, mutex_unlock(&knav_dev_lock); err: kfree(pool->name); - devm_kfree(kdev->dev, pool); + devm_kfree(knav_qdev->dev, pool); return ERR_PTR(ret); } EXPORT_SYMBOL_GPL(knav_pool_create); @@ -874,7 +869,7 @@ void knav_pool_destroy(void *ph) mutex_unlock(&knav_dev_lock); kfree(pool->name); - devm_kfree(kdev->dev, pool); + devm_kfree(knav_qdev->dev, pool); } EXPORT_SYMBOL_GPL(knav_pool_destroy); @@ -883,7 +878,7 @@ EXPORT_SYMBOL_GPL(knav_pool_destroy); * knav_pool_desc_get() - Get a descriptor from the pool * @ph: - pool handle * - * Returns descriptor from the pool. + * Return: descriptor from the pool on success, error pointer otherwise. */ void *knav_pool_desc_get(void *ph) { @@ -922,7 +917,7 @@ EXPORT_SYMBOL_GPL(knav_pool_desc_put); * @dma: - DMA address return pointer * @dma_sz: - adjusted return pointer * - * Returns 0 on success, errno otherwise. + * Return: 0 on success, errno otherwise. */ int knav_pool_desc_map(void *ph, void *desc, unsigned size, dma_addr_t *dma, unsigned *dma_sz) @@ -947,7 +942,7 @@ EXPORT_SYMBOL_GPL(knav_pool_desc_map); * @dma: - DMA address of descriptor to unmap * @dma_sz: - size of descriptor to unmap * - * Returns descriptor address on success, Use IS_ERR_OR_NULL() to identify + * Return: descriptor address on success. Use IS_ERR_OR_NULL() to identify * error values on return. */ void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz) @@ -967,7 +962,8 @@ EXPORT_SYMBOL_GPL(knav_pool_desc_unmap); /** * knav_pool_count() - Get the number of descriptors in pool. * @ph: - pool handle - * Returns number of elements in the pool. + * + * Return: number of elements in the pool. */ int knav_pool_count(void *ph) { @@ -1025,10 +1021,8 @@ static void knav_queue_setup_region(struct knav_device *kdev, region->dma_end = region->dma_start + size; pool = devm_kzalloc(kdev->dev, sizeof(*pool), GFP_KERNEL); - if (!pool) { - dev_err(kdev->dev, "out of memory allocating dummy pool\n"); + if (!pool) goto fail; - } pool->num_desc = 0; pool->region_offset = region->num_desc; list_add(&pool->region_inst, ®ion->pools); @@ -1211,10 +1205,8 @@ static int knav_setup_queue_range(struct knav_device *kdev, int ret, i; range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL); - if (!range) { - dev_err(dev, "out of memory allocating range\n"); + if (!range) return -ENOMEM; - } range->kdev = kdev; range->name = knav_queue_find_name(node); @@ -1376,7 +1368,7 @@ static void __iomem *knav_queue_map_reg(struct knav_device *kdev, if (ret) { dev_err(kdev->dev, "Can't translate of node(%pOFn) address for index(%d)\n", node, index); - return ERR_PTR(ret); + return IOMEM_ERR_PTR(ret); } regs = devm_ioremap_resource(kdev->dev, &res); @@ -1564,7 +1556,7 @@ static int knav_queue_load_pdsp(struct knav_device *kdev, int i, ret, fwlen; const struct firmware *fw; bool found = false; - u32 *fwdata; + const __be32 *fwdata; for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) { if (knav_acc_firmwares[i]) { @@ -1586,9 +1578,9 @@ static int knav_queue_load_pdsp(struct knav_device *kdev, dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n", knav_acc_firmwares[i]); - writel_relaxed(pdsp->id + 1, pdsp->command + 0x18); + writel_relaxed(pdsp->id + 1, pdsp->command + 0x6); /* download the firmware */ - fwdata = (u32 *)fw->data; + fwdata = (const __be32 *)fw->data; fwlen = (fw->size + sizeof(u32) - 1) / sizeof(u32); for (i = 0; i < fwlen; i++) writel_relaxed(be32_to_cpu(fwdata[i]), pdsp->iram + i); @@ -1689,7 +1681,7 @@ static inline struct knav_qmgr_info *knav_find_qmgr(unsigned id) { struct knav_qmgr_info *qmgr; - for_each_qmgr(kdev, qmgr) { + for_each_qmgr(knav_qdev, qmgr) { if ((id >= qmgr->start_queue) && (id < qmgr->start_queue + qmgr->num_queues)) return qmgr; @@ -1781,22 +1773,22 @@ static int knav_queue_probe(struct platform_device *pdev) return -ENODEV; } - kdev = devm_kzalloc(dev, sizeof(struct knav_device), GFP_KERNEL); - if (!kdev) { + knav_qdev = devm_kzalloc(dev, sizeof(struct knav_device), GFP_KERNEL); + if (!knav_qdev) { dev_err(dev, "memory allocation failed\n"); return -ENOMEM; } if (device_get_match_data(dev)) - kdev->version = QMSS_66AK2G; + knav_qdev->version = QMSS_66AK2G; - platform_set_drvdata(pdev, kdev); - kdev->dev = dev; - INIT_LIST_HEAD(&kdev->queue_ranges); - INIT_LIST_HEAD(&kdev->qmgrs); - INIT_LIST_HEAD(&kdev->pools); - INIT_LIST_HEAD(&kdev->regions); - INIT_LIST_HEAD(&kdev->pdsps); + platform_set_drvdata(pdev, knav_qdev); + knav_qdev->dev = dev; + INIT_LIST_HEAD(&knav_qdev->queue_ranges); + INIT_LIST_HEAD(&knav_qdev->qmgrs); + INIT_LIST_HEAD(&knav_qdev->pools); + INIT_LIST_HEAD(&knav_qdev->regions); + INIT_LIST_HEAD(&knav_qdev->pdsps); pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev); @@ -1811,31 +1803,31 @@ static int knav_queue_probe(struct platform_device *pdev) ret = -ENODEV; goto err; } - kdev->base_id = temp[0]; - kdev->num_queues = temp[1]; + knav_qdev->base_id = temp[0]; + knav_qdev->num_queues = temp[1]; /* Initialize queue managers using device tree configuration */ - ret = knav_queue_init_qmgrs(kdev, node); + ret = knav_queue_init_qmgrs(knav_qdev, node); if (ret) goto err; /* get pdsp configuration values from device tree */ - ret = knav_queue_setup_pdsps(kdev, node); + ret = knav_queue_setup_pdsps(knav_qdev, node); if (ret) goto err; /* get usable queue range values from device tree */ - ret = knav_setup_queue_pools(kdev, node); + ret = knav_setup_queue_pools(knav_qdev, node); if (ret) goto err; - ret = knav_get_link_ram(kdev, "linkram0", &kdev->link_rams[0]); + ret = knav_get_link_ram(knav_qdev, "linkram0", &knav_qdev->link_rams[0]); if (ret) { - dev_err(kdev->dev, "could not setup linking ram\n"); + dev_err(knav_qdev->dev, "could not setup linking ram\n"); goto err; } - ret = knav_get_link_ram(kdev, "linkram1", &kdev->link_rams[1]); + ret = knav_get_link_ram(knav_qdev, "linkram1", &knav_qdev->link_rams[1]); if (ret) { /* * nothing really, we have one linking ram already, so we just @@ -1843,15 +1835,15 @@ static int knav_queue_probe(struct platform_device *pdev) */ } - ret = knav_queue_setup_link_ram(kdev); + ret = knav_queue_setup_link_ram(knav_qdev); if (ret) goto err; - ret = knav_queue_setup_regions(kdev, node); + ret = knav_queue_setup_regions(knav_qdev, node); if (ret) goto err; - ret = knav_queue_init_queues(kdev); + ret = knav_queue_init_queues(knav_qdev); if (ret < 0) { dev_err(dev, "hwqueue initialization failed\n"); goto err; @@ -1863,9 +1855,9 @@ static int knav_queue_probe(struct platform_device *pdev) return 0; err: - knav_queue_stop_pdsps(kdev); - knav_queue_free_regions(kdev); - knav_free_queue_ranges(kdev); + knav_queue_stop_pdsps(knav_qdev); + knav_queue_free_regions(knav_qdev); + knav_free_queue_ranges(knav_qdev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); return ret; @@ -1873,7 +1865,12 @@ static int knav_queue_probe(struct platform_device *pdev) static void knav_queue_remove(struct platform_device *pdev) { - /* TODO: Free resources */ + struct knav_device *kdev = platform_get_drvdata(pdev); + + device_ready = false; + knav_queue_stop_pdsps(kdev); + knav_queue_free_regions(kdev); + knav_free_queue_ranges(kdev); pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); } diff --git a/include/linux/soc/ti/knav_dma.h b/include/linux/soc/ti/knav_dma.h index 18d806a8e52c..eb1e6b014eaf 100644 --- a/include/linux/soc/ti/knav_dma.h +++ b/include/linux/soc/ti/knav_dma.h @@ -75,7 +75,7 @@ enum knav_dma_desc_type { * struct knav_dma_tx_cfg: Tx channel configuration * @filt_einfo: Filter extended packet info * @filt_pswords: Filter PS words present - * @knav_dma_tx_priority: Tx channel scheduling priority + * @priority: Tx channel scheduling priority */ struct knav_dma_tx_cfg { bool filt_einfo; @@ -87,13 +87,13 @@ struct knav_dma_tx_cfg { * struct knav_dma_rx_cfg: Rx flow configuration * @einfo_present: Extended packet info present * @psinfo_present: PS words present - * @knav_dma_rx_err_mode: Error during buffer starvation - * @knav_dma_desc_type: Host or Monolithic desc + * @err_mode: Error during buffer starvation + * @desc_type: Host or Monolithic desc * @psinfo_at_sop: PS word located at start of packet * @sop_offset: Start of packet offset * @dst_q: Destination queue for a given flow * @thresh: Rx flow size threshold - * @fdq[]: Free desc Queue array + * @fdq: Free desc Queue array * @sz_thresh0: RX packet size threshold 0 * @sz_thresh1: RX packet size threshold 1 * @sz_thresh2: RX packet size threshold 2 @@ -115,7 +115,8 @@ struct knav_dma_rx_cfg { /** * struct knav_dma_cfg: Pktdma channel configuration - * @sl_cfg: Slave configuration + * @direction: DMA transfer mode and direction + * @u: union containing @tx or @rx * @tx: Tx channel configuration * @rx: Rx flow configuration */