diff options
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-cmd.h | 1 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-driver.c | 41 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio-service.c | 41 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio.c | 23 | ||||
-rw-r--r-- | drivers/soc/fsl/dpio/dpio.h | 4 | ||||
-rw-r--r-- | drivers/soc/fsl/qbman/qman.c | 9 | ||||
-rw-r--r-- | drivers/soc/fsl/qe/qe_tdm.c | 55 | ||||
-rw-r--r-- | drivers/soc/lantiq/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/lantiq/gphy.c | 224 |
9 files changed, 95 insertions, 304 deletions
diff --git a/drivers/soc/fsl/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h index ab8f82ee7ee5..5814d2f395a4 100644 --- a/drivers/soc/fsl/dpio/dpio-cmd.h +++ b/drivers/soc/fsl/dpio/dpio-cmd.h @@ -25,6 +25,7 @@ #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) struct dpio_cmd_open { __le32 dpio_id; diff --git a/drivers/soc/fsl/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c index e58fcc9096e8..2d4af32a0dec 100644 --- a/drivers/soc/fsl/dpio/dpio-driver.c +++ b/drivers/soc/fsl/dpio/dpio-driver.c @@ -30,6 +30,8 @@ struct dpio_priv { struct dpaa2_io *io; }; +static cpumask_var_t cpus_unused_mask; + static irqreturn_t dpio_irq_handler(int irq_num, void *arg) { struct device *dev = (struct device *)arg; @@ -86,7 +88,7 @@ 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; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -108,6 +110,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 +136,14 @@ 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); /* * Set the CENA regs to be the cache inhibited area of the portal to @@ -171,7 +176,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 +187,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 +197,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,7 +216,7 @@ 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); @@ -220,11 +225,8 @@ static int dpaa2_dpio_remove(struct fsl_mc_device *dpio_dev) 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; - } + cpu = dpaa2_io_get_cpu(priv->io); + 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 +245,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 +269,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..bc801934602a 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); diff --git a/drivers/soc/fsl/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c index ff37c80e11a0..521bc6946317 100644 --- a/drivers/soc/fsl/dpio/dpio.c +++ b/drivers/soc/fsl/dpio/dpio.c @@ -196,3 +196,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..b2ac4ba4fb8e 100644 --- a/drivers/soc/fsl/dpio/dpio.h +++ b/drivers/soc/fsl/dpio/dpio.h @@ -80,4 +80,8 @@ int dpio_get_api_version(struct fsl_mc_io *mc_io, 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/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); diff --git a/drivers/soc/lantiq/Makefile b/drivers/soc/lantiq/Makefile index be9e866d53e5..35aa86bd1023 100644 --- a/drivers/soc/lantiq/Makefile +++ b/drivers/soc/lantiq/Makefile @@ -1,2 +1 @@ obj-y += fpi-bus.o -obj-$(CONFIG_XRX200_PHY_FW) += gphy.o diff --git a/drivers/soc/lantiq/gphy.c b/drivers/soc/lantiq/gphy.c deleted file mode 100644 index feeb17cebc25..000000000000 --- a/drivers/soc/lantiq/gphy.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2012 John Crispin <blogic@phrozen.org> - * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com> - * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de> - */ - -#include <linux/clk.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/firmware.h> -#include <linux/mfd/syscon.h> -#include <linux/module.h> -#include <linux/reboot.h> -#include <linux/regmap.h> -#include <linux/reset.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#include <linux/property.h> -#include <dt-bindings/mips/lantiq_rcu_gphy.h> - -#include <lantiq_soc.h> - -#define XRX200_GPHY_FW_ALIGN (16 * 1024) - -struct xway_gphy_priv { - struct clk *gphy_clk_gate; - struct reset_control *gphy_reset; - struct reset_control *gphy_reset2; - void __iomem *membase; - char *fw_name; -}; - -struct xway_gphy_match_data { - char *fe_firmware_name; - char *ge_firmware_name; -}; - -static const struct xway_gphy_match_data xrx200a1x_gphy_data = { - .fe_firmware_name = "lantiq/xrx200_phy22f_a14.bin", - .ge_firmware_name = "lantiq/xrx200_phy11g_a14.bin", -}; - -static const struct xway_gphy_match_data xrx200a2x_gphy_data = { - .fe_firmware_name = "lantiq/xrx200_phy22f_a22.bin", - .ge_firmware_name = "lantiq/xrx200_phy11g_a22.bin", -}; - -static const struct xway_gphy_match_data xrx300_gphy_data = { - .fe_firmware_name = "lantiq/xrx300_phy22f_a21.bin", - .ge_firmware_name = "lantiq/xrx300_phy11g_a21.bin", -}; - -static const struct of_device_id xway_gphy_match[] = { - { .compatible = "lantiq,xrx200a1x-gphy", .data = &xrx200a1x_gphy_data }, - { .compatible = "lantiq,xrx200a2x-gphy", .data = &xrx200a2x_gphy_data }, - { .compatible = "lantiq,xrx300-gphy", .data = &xrx300_gphy_data }, - { .compatible = "lantiq,xrx330-gphy", .data = &xrx300_gphy_data }, - {}, -}; -MODULE_DEVICE_TABLE(of, xway_gphy_match); - -static int xway_gphy_load(struct device *dev, struct xway_gphy_priv *priv, - dma_addr_t *dev_addr) -{ - const struct firmware *fw; - void *fw_addr; - dma_addr_t dma_addr; - size_t size; - int ret; - - ret = request_firmware(&fw, priv->fw_name, dev); - if (ret) { - dev_err(dev, "failed to load firmware: %s, error: %i\n", - priv->fw_name, ret); - return ret; - } - - /* - * GPHY cores need the firmware code in a persistent and contiguous - * memory area with a 16 kB boundary aligned start address. - */ - size = fw->size + XRX200_GPHY_FW_ALIGN; - - fw_addr = dmam_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL); - if (fw_addr) { - fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN); - *dev_addr = ALIGN(dma_addr, XRX200_GPHY_FW_ALIGN); - memcpy(fw_addr, fw->data, fw->size); - } else { - dev_err(dev, "failed to alloc firmware memory\n"); - ret = -ENOMEM; - } - - release_firmware(fw); - - return ret; -} - -static int xway_gphy_of_probe(struct platform_device *pdev, - struct xway_gphy_priv *priv) -{ - struct device *dev = &pdev->dev; - const struct xway_gphy_match_data *gphy_fw_name_cfg; - u32 gphy_mode; - int ret; - struct resource *res_gphy; - - gphy_fw_name_cfg = of_device_get_match_data(dev); - - priv->gphy_clk_gate = devm_clk_get(dev, NULL); - if (IS_ERR(priv->gphy_clk_gate)) { - dev_err(dev, "Failed to lookup gate clock\n"); - return PTR_ERR(priv->gphy_clk_gate); - } - - res_gphy = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->membase = devm_ioremap_resource(dev, res_gphy); - if (IS_ERR(priv->membase)) - return PTR_ERR(priv->membase); - - priv->gphy_reset = devm_reset_control_get(dev, "gphy"); - if (IS_ERR(priv->gphy_reset)) { - if (PTR_ERR(priv->gphy_reset) != -EPROBE_DEFER) - dev_err(dev, "Failed to lookup gphy reset\n"); - return PTR_ERR(priv->gphy_reset); - } - - priv->gphy_reset2 = devm_reset_control_get_optional(dev, "gphy2"); - if (IS_ERR(priv->gphy_reset2)) - return PTR_ERR(priv->gphy_reset2); - - ret = device_property_read_u32(dev, "lantiq,gphy-mode", &gphy_mode); - /* Default to GE mode */ - if (ret) - gphy_mode = GPHY_MODE_GE; - - switch (gphy_mode) { - case GPHY_MODE_FE: - priv->fw_name = gphy_fw_name_cfg->fe_firmware_name; - break; - case GPHY_MODE_GE: - priv->fw_name = gphy_fw_name_cfg->ge_firmware_name; - break; - default: - dev_err(dev, "Unknown GPHY mode %d\n", gphy_mode); - return -EINVAL; - } - - return 0; -} - -static int xway_gphy_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct xway_gphy_priv *priv; - dma_addr_t fw_addr = 0; - int ret; - - priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - ret = xway_gphy_of_probe(pdev, priv); - if (ret) - return ret; - - ret = clk_prepare_enable(priv->gphy_clk_gate); - if (ret) - return ret; - - ret = xway_gphy_load(dev, priv, &fw_addr); - if (ret) { - clk_disable_unprepare(priv->gphy_clk_gate); - return ret; - } - - reset_control_assert(priv->gphy_reset); - reset_control_assert(priv->gphy_reset2); - - iowrite32be(fw_addr, priv->membase); - - reset_control_deassert(priv->gphy_reset); - reset_control_deassert(priv->gphy_reset2); - - platform_set_drvdata(pdev, priv); - - return ret; -} - -static int xway_gphy_remove(struct platform_device *pdev) -{ - struct xway_gphy_priv *priv = platform_get_drvdata(pdev); - - iowrite32be(0, priv->membase); - - clk_disable_unprepare(priv->gphy_clk_gate); - - return 0; -} - -static struct platform_driver xway_gphy_driver = { - .probe = xway_gphy_probe, - .remove = xway_gphy_remove, - .driver = { - .name = "xway-rcu-gphy", - .of_match_table = xway_gphy_match, - }, -}; - -module_platform_driver(xway_gphy_driver); - -MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin"); -MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin"); -MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin"); -MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin"); -MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin"); -MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin"); -MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); -MODULE_DESCRIPTION("Lantiq XWAY GPHY Firmware Loader"); -MODULE_LICENSE("GPL"); |