diff options
Diffstat (limited to 'drivers/soc/fsl')
-rw-r--r-- | drivers/soc/fsl/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-cmd.h | 6 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-driver.c | 93 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-service.c | 46 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio.c | 39 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio.h | 9 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/qbman-portal.c | 5 | ||||
-rw-r--r-- | drivers/soc/fsl/guts.c | 10 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/dpaa_sys.c | 2 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/qman.c | 9 | ||||
-rw-r--r-- | drivers/soc/fsl/qe/qe_tdm.c | 55 |
11 files changed, 186 insertions, 89 deletions
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig index 8f80e8bbf29e..61f8e1433d0a 100644 --- a/drivers/soc/fsl/Kconfig +++ b/drivers/soc/fsl/Kconfig @@ -22,6 +22,7 @@ config FSL_GUTS config FSL_MC_DPIO tristate "QorIQ DPAA2 DPIO driver" depends on FSL_MC_BUS + select SOC_BUS help Driver for the DPAA2 DPIO object. A DPIO provides queue and buffer management facilities for software to interact with diff --git a/drivers/soc/fsl/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h index ab8f82ee7ee5..e13fd3ac1939 100644 --- a/drivers/soc/fsl/dpio/dpio-cmd.h +++ b/drivers/soc/fsl/dpio/dpio-cmd.h @@ -25,6 +25,8 @@ #define DPIO_CMDID_ENABLE DPIO_CMD(0x002) #define DPIO_CMDID_DISABLE DPIO_CMD(0x003) #define DPIO_CMDID_GET_ATTR DPIO_CMD(0x004) +#define DPIO_CMDID_RESET DPIO_CMD(0x005) +#define DPIO_CMDID_SET_STASHING_DEST DPIO_CMD(0x120) struct dpio_cmd_open { __le32 dpio_id; @@ -46,4 +48,8 @@ struct dpio_rsp_get_attr { __le32 qbman_version; }; +struct dpio_stashing_dest { + u8 sdest; +}; + #endif /* _FSL_DPIO_CMD_H */ diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index e58fcc9096e8..c0cdc8946031 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -14,6 +14,7 @@ #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/sys_soc.h> #include <linux/fsl/mc.h> #include <soc/fsl/dpaa2-io.h> @@ -30,6 +31,48 @@ struct dpio_priv { struct dpaa2_io *io; }; +static cpumask_var_t cpus_unused_mask; + +static const struct soc_device_attribute ls1088a_soc[] = { + {.family = "QorIQ LS1088A"}, + { /* sentinel */ } +}; + +static const struct soc_device_attribute ls2080a_soc[] = { + {.family = "QorIQ LS2080A"}, + { /* sentinel */ } +}; + +static const struct soc_device_attribute ls2088a_soc[] = { + {.family = "QorIQ LS2088A"}, + { /* sentinel */ } +}; + +static const struct soc_device_attribute lx2160a_soc[] = { + {.family = "QorIQ LX2160A"}, + { /* sentinel */ } +}; + +static int dpaa2_dpio_get_cluster_sdest(struct fsl_mc_device *dpio_dev, int cpu) +{ + int cluster_base, cluster_size; + + if (soc_device_match(ls1088a_soc)) { + cluster_base = 2; + cluster_size = 4; + } else if (soc_device_match(ls2080a_soc) || + soc_device_match(ls2088a_soc) || + soc_device_match(lx2160a_soc)) { + cluster_base = 0; + cluster_size = 2; + } else { + dev_err(&dpio_dev->dev, "unknown SoC version\n"); + return -1; + } + + return cluster_base + cpu / cluster_size; +} + static irqreturn_t dpio_irq_handler(int irq_num, void *arg) { struct device *dev = (struct device *)arg; @@ -86,7 +129,8 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) struct dpio_priv *priv; int err = -ENOMEM; struct device *dev = &dpio_dev->dev; - static int next_cpu = -1; + int possible_next_cpu; + int sdest; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -108,6 +152,12 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) goto err_open; } + err = dpio_reset(dpio_dev->mc_io, 0, dpio_dev->mc_handle); + if (err) { + dev_err(dev, "dpio_reset() failed\n"); + goto err_reset; + } + err = dpio_get_attributes(dpio_dev->mc_io, 0, dpio_dev->mc_handle, &dpio_attrs); if (err) { @@ -128,17 +178,24 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) desc.dpio_id = dpio_dev->obj_desc.id; /* get the cpu to use for the affinity hint */ - if (next_cpu == -1) - next_cpu = cpumask_first(cpu_online_mask); - else - next_cpu = cpumask_next(next_cpu, cpu_online_mask); - - if (!cpu_possible(next_cpu)) { + possible_next_cpu = cpumask_first(cpus_unused_mask); + if (possible_next_cpu >= nr_cpu_ids) { dev_err(dev, "probe failed. Number of DPIOs exceeds NR_CPUS.\n"); err = -ERANGE; goto err_allocate_irqs; } - desc.cpu = next_cpu; + desc.cpu = possible_next_cpu; + cpumask_clear_cpu(possible_next_cpu, cpus_unused_mask); + + sdest = dpaa2_dpio_get_cluster_sdest(dpio_dev, desc.cpu); + if (sdest >= 0) { + err = dpio_set_stashing_destination(dpio_dev->mc_io, 0, + dpio_dev->mc_handle, + sdest); + if (err) + dev_err(dev, "dpio_set_stashing_destination failed for cpu%d\n", + desc.cpu); + } /* * Set the CENA regs to be the cache inhibited area of the portal to @@ -171,7 +228,7 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) if (err) goto err_register_dpio_irq; - priv->io = dpaa2_io_create(&desc); + priv->io = dpaa2_io_create(&desc, dev); if (!priv->io) { dev_err(dev, "dpaa2_io_create failed\n"); err = -ENOMEM; @@ -182,7 +239,6 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) dev_dbg(dev, " receives_notifications = %d\n", desc.receives_notifications); dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); - fsl_mc_portal_free(dpio_dev->mc_io); return 0; @@ -193,6 +249,7 @@ err_register_dpio_irq: err_allocate_irqs: dpio_disable(dpio_dev->mc_io, 0, dpio_dev->mc_handle); err_get_attr: +err_reset: dpio_close(dpio_dev->mc_io, 0, dpio_dev->mc_handle); err_open: fsl_mc_portal_free(dpio_dev->mc_io); @@ -211,20 +268,17 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) { struct device *dev; struct dpio_priv *priv; - int err; + int err = 0, cpu; dev = &dpio_dev->dev; priv = dev_get_drvdata(dev); + cpu = dpaa2_io_get_cpu(priv->io); dpaa2_io_down(priv->io); dpio_teardown_irqs(dpio_dev); - err = fsl_mc_portal_allocate(dpio_dev, 0, &dpio_dev->mc_io); - if (err) { - dev_err(dev, "MC portal allocation failed\n"); - goto err_mcportal; - } + cpumask_set_cpu(cpu, cpus_unused_mask); err = dpio_open(dpio_dev->mc_io, 0, dpio_dev->obj_desc.id, &dpio_dev->mc_handle); @@ -243,7 +297,7 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) err_open: fsl_mc_portal_free(dpio_dev->mc_io); -err_mcportal: + return err; } @@ -267,11 +321,16 @@ static struct fsl_mc_driver dpaa2_dpio_driver = { static int dpio_driver_init(void) { + if (!zalloc_cpumask_var(&cpus_unused_mask, GFP_KERNEL)) + return -ENOMEM; + cpumask_copy(cpus_unused_mask, cpu_online_mask); + return fsl_mc_driver_register(&dpaa2_dpio_driver); } static void dpio_driver_exit(void) { + free_cpumask_var(cpus_unused_mask); fsl_mc_driver_unregister(&dpaa2_dpio_driver); } module_init(dpio_driver_init); diff --git a/drivers/soc/fsl/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c index ec0837ff039a..b9539ef2c3cd 100644 --- a/drivers/soc/fsl/dpio/dpio-service.c +++ b/drivers/soc/fsl/dpio/dpio-service.c @@ -27,6 +27,7 @@ struct dpaa2_io { /* protect notifications list */ spinlock_t lock_notifications; struct list_head notifications; + struct device *dev; }; struct dpaa2_io_store { @@ -98,13 +99,15 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_select); /** * dpaa2_io_create() - create a dpaa2_io object. * @desc: the dpaa2_io descriptor + * @dev: the actual DPIO device * * Activates a "struct dpaa2_io" corresponding to the given config of an actual * DPIO object. * * Return a valid dpaa2_io object for success, or NULL for failure. */ -struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) +struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc, + struct device *dev) { struct dpaa2_io *obj = kmalloc(sizeof(*obj), GFP_KERNEL); @@ -146,6 +149,8 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) dpio_by_cpu[desc->cpu] = obj; spin_unlock(&dpio_list_lock); + obj->dev = dev; + return obj; } @@ -160,6 +165,11 @@ struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc) */ void dpaa2_io_down(struct dpaa2_io *d) { + spin_lock(&dpio_list_lock); + dpio_by_cpu[d->dpio_desc.cpu] = NULL; + list_del(&d->node); + spin_unlock(&dpio_list_lock); + kfree(d); } @@ -210,10 +220,24 @@ done: } /** + * dpaa2_io_get_cpu() - get the cpu associated with a given DPIO object + * + * @d: the given DPIO object. + * + * Return the cpu associated with the DPIO object + */ +int dpaa2_io_get_cpu(struct dpaa2_io *d) +{ + return d->dpio_desc.cpu; +} +EXPORT_SYMBOL(dpaa2_io_get_cpu); + +/** * dpaa2_io_service_register() - Prepare for servicing of FQDAN or CDAN * notifications on the given DPIO service. * @d: the given DPIO service. * @ctx: the notification context. + * @dev: the device that requests the register * * The caller should make the MC command to attach a DPAA2 object to * a DPIO after this function completes successfully. In that way: @@ -228,14 +252,20 @@ done: * Return 0 for success, or -ENODEV for failure. */ int dpaa2_io_service_register(struct dpaa2_io *d, - struct dpaa2_io_notification_ctx *ctx) + struct dpaa2_io_notification_ctx *ctx, + struct device *dev) { + struct device_link *link; unsigned long irqflags; d = service_select_by_cpu(d, ctx->desired_cpu); if (!d) return -ENODEV; + link = device_link_add(dev, d->dev, DL_FLAG_AUTOREMOVE_CONSUMER); + if (!link) + return -EINVAL; + ctx->dpio_id = d->dpio_desc.dpio_id; ctx->qman64 = (u64)(uintptr_t)ctx; ctx->dpio_private = d; @@ -256,12 +286,14 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_register); * dpaa2_io_service_deregister - The opposite of 'register'. * @service: the given DPIO service. * @ctx: the notification context. + * @dev: the device that requests to be deregistered * * This function should be called only after sending the MC command to * to detach the notification-producing device from the DPIO. */ void dpaa2_io_service_deregister(struct dpaa2_io *service, - struct dpaa2_io_notification_ctx *ctx) + struct dpaa2_io_notification_ctx *ctx, + struct device *dev) { struct dpaa2_io *d = ctx->dpio_private; unsigned long irqflags; @@ -272,6 +304,9 @@ void dpaa2_io_service_deregister(struct dpaa2_io *service, spin_lock_irqsave(&d->lock_notifications, irqflags); list_del(&ctx->node); spin_unlock_irqrestore(&d->lock_notifications, irqflags); + + if (dev) + device_link_remove(dev, d->dev); } EXPORT_SYMBOL_GPL(dpaa2_io_service_deregister); @@ -438,7 +473,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_enqueue_qd); * Return 0 for success, and negative error code for failure. */ int dpaa2_io_service_release(struct dpaa2_io *d, - u32 bpid, + u16 bpid, const u64 *buffers, unsigned int num_buffers) { @@ -467,7 +502,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_release); * Eg. if the buffer pool is empty, this will return zero. */ int dpaa2_io_service_acquire(struct dpaa2_io *d, - u32 bpid, + u16 bpid, u64 *buffers, unsigned int num_buffers) { @@ -595,6 +630,7 @@ struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last) if (!(dpaa2_dq_flags(ret) & DPAA2_DQ_STAT_VALIDFRAME)) ret = NULL; } else { + prefetch(&s->vaddr[s->idx]); *is_last = 0; } diff --git a/drivers/soc/fsl/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c index ff37c80e11a0..af74c597a675 100644 --- a/drivers/soc/fsl/dpio/dpio.c +++ b/drivers/soc/fsl/dpio/dpio.c @@ -166,6 +166,22 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, return 0; } +int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 sdest) +{ + struct fsl_mc_command cmd = { 0 }; + struct dpio_stashing_dest *dpio_cmd; + + cmd.header = mc_encode_cmd_header(DPIO_CMDID_SET_STASHING_DEST, + cmd_flags, token); + dpio_cmd = (struct dpio_stashing_dest *)cmd.params; + dpio_cmd->sdest = sdest; + + return mc_send_command(mc_io, &cmd); +} + /** * dpio_get_api_version - Get Data Path I/O API version * @mc_io: Pointer to MC portal's DPIO object @@ -196,3 +212,26 @@ int dpio_get_api_version(struct fsl_mc_io *mc_io, return 0; } + +/** + * dpio_reset() - Reset the DPIO, returns the object to initial state. + * @mc_io: Pointer to MC portal's I/O object + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' + * @token: Token of DPIO object + * + * Return: '0' on Success; Error code otherwise. + */ +int dpio_reset(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token) +{ + struct fsl_mc_command cmd = { 0 }; + + /* prepare command */ + cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET, + cmd_flags, + token); + + /* send command to mc*/ + return mc_send_command(mc_io, &cmd); +} diff --git a/drivers/soc/fsl/dpio/dpio.h b/drivers/soc/fsl/dpio/dpio.h index 49194c8e45f1..da06f7258098 100644 --- a/drivers/soc/fsl/dpio/dpio.h +++ b/drivers/soc/fsl/dpio/dpio.h @@ -75,9 +75,18 @@ int dpio_get_attributes(struct fsl_mc_io *mc_io, u16 token, struct dpio_attr *attr); +int dpio_set_stashing_destination(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token, + u8 dest); + int dpio_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 *major_ver, u16 *minor_ver); +int dpio_reset(struct fsl_mc_io *mc_io, + u32 cmd_flags, + u16 token); + #endif /* __FSL_DPIO_H */ diff --git a/drivers/soc/fsl/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c index 0bddb85c0ae5..d02013556a1b 100644 --- a/drivers/soc/fsl/dpio/qbman-portal.c +++ b/drivers/soc/fsl/dpio/qbman-portal.c @@ -169,9 +169,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) 3, /* RPM: Valid bit mode, RCR in array mode */ 2, /* DCM: Discrete consumption ack mode */ 3, /* EPM: Valid bit mode, EQCR in array mode */ - 0, /* mem stashing drop enable == FALSE */ + 1, /* mem stashing drop enable == TRUE */ 1, /* mem stashing priority == TRUE */ - 0, /* mem stashing enable == FALSE */ + 1, /* mem stashing enable == TRUE */ 1, /* dequeue stashing priority == TRUE */ 0, /* dequeue stashing enable == FALSE */ 0); /* EQCR_CI stashing priority == FALSE */ @@ -180,6 +180,7 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); if (!reg) { pr_err("qbman: the portal is not enabled!\n"); + kfree(p); return NULL; } diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c index 302e0c8d69d9..63f6df86f9e5 100644 --- a/drivers/soc/fsl/guts.c +++ b/drivers/soc/fsl/guts.c @@ -32,6 +32,7 @@ struct fsl_soc_die_attr { static struct guts *guts; static struct soc_device_attribute soc_dev_attr; static struct soc_device *soc_dev; +static struct device_node *root; /* SoC die attribute definition for QorIQ platform */ @@ -114,7 +115,7 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match( return NULL; } -u32 fsl_guts_get_svr(void) +static u32 fsl_guts_get_svr(void) { u32 svr = 0; @@ -128,11 +129,10 @@ u32 fsl_guts_get_svr(void) return svr; } -EXPORT_SYMBOL(fsl_guts_get_svr); static int fsl_guts_probe(struct platform_device *pdev) { - struct device_node *root, *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.of_node; struct device *dev = &pdev->dev; struct resource *res; const struct fsl_soc_die_attr *soc_die; @@ -155,9 +155,8 @@ static int fsl_guts_probe(struct platform_device *pdev) root = of_find_node_by_path("/"); if (of_property_read_string(root, "model", &machine)) of_property_read_string_index(root, "compatible", 0, &machine); - of_node_put(root); if (machine) - soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); + soc_dev_attr.machine = machine; svr = fsl_guts_get_svr(); soc_die = fsl_soc_die_match(svr, fsl_soc_die); @@ -192,6 +191,7 @@ static int fsl_guts_probe(struct platform_device *pdev) static int fsl_guts_remove(struct platform_device *dev) { soc_device_unregister(soc_dev); + of_node_put(root); return 0; } diff --git a/drivers/soc/fsl/qbman/dpaa_sys.c b/drivers/soc/fsl/qbman/dpaa_sys.c index 9436aa83ff1b..e6d48dccb8d5 100644 --- a/drivers/soc/fsl/qbman/dpaa_sys.c +++ b/drivers/soc/fsl/qbman/dpaa_sys.c @@ -62,7 +62,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr, return -ENODEV; } - if (!dma_zalloc_coherent(dev, *size, addr, 0)) { + if (!dma_alloc_coherent(dev, *size, addr, 0)) { dev_err(dev, "DMA Alloc memory failed\n"); return -ENODEV; } diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 52c153cd795a..636f83f781f5 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work); static irqreturn_t portal_isr(int irq, void *ptr) { struct qman_portal *p = ptr; - - u32 clear = QM_DQAVAIL_MASK | p->irq_sources; u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources; + u32 clear = 0; if (unlikely(!is)) return IRQ_NONE; /* DQRR-handling if it's interrupt-driven */ - if (is & QM_PIRQ_DQRI) + if (is & QM_PIRQ_DQRI) { __poll_portal_fast(p, QMAN_POLL_LIMIT); + clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI; + } /* Handling of anything else that's interrupt-driven */ - clear |= __poll_portal_slow(p, is); + clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW; qm_out(&p->p, QM_REG_ISR, clear); return IRQ_HANDLED; } diff --git a/drivers/soc/fsl/qe/qe_tdm.c b/drivers/soc/fsl/qe/qe_tdm.c index f78c34647ca2..76480df195a8 100644 --- a/drivers/soc/fsl/qe/qe_tdm.c +++ b/drivers/soc/fsl/qe/qe_tdm.c @@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, const char *sprop; int ret = 0; u32 val; - struct resource *res; - struct device_node *np2; - static int siram_init_flag; - struct platform_device *pdev; sprop = of_get_property(np, "fsl,rx-sync-clock", NULL); if (sprop) { @@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm, utdm->siram_entry_id = val; set_si_param(utdm, ut_info); - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si"); - if (!np2) - return -EINVAL; - - pdev = of_find_device_by_node(np2); - if (!pdev) { - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - return -EINVAL; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->si_regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->si_regs)) { - ret = PTR_ERR(utdm->si_regs); - goto err_miss_siram_property; - } - - np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram"); - if (!np2) { - ret = -EINVAL; - goto err_miss_siram_property; - } - - pdev = of_find_device_by_node(np2); - if (!pdev) { - ret = -EINVAL; - pr_err("%pOFn: failed to lookup pdev\n", np2); - of_node_put(np2); - goto err_miss_siram_property; - } - - of_node_put(np2); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - utdm->siram = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(utdm->siram)) { - ret = PTR_ERR(utdm->siram); - goto err_miss_siram_property; - } - - if (siram_init_flag == 0) { - memset_io(utdm->siram, 0, resource_size(res)); - siram_init_flag = 1; - } - - return ret; - -err_miss_siram_property: - devm_iounmap(&pdev->dev, utdm->si_regs); return ret; } EXPORT_SYMBOL(ucc_of_parse_tdm); |