Beispiel #1
0
static int da8xx_rproc_remove(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct rproc *rproc = platform_get_drvdata(pdev);
	struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;

	/*
	 * It's important to place the DSP in reset before going away,
	 * since a subsequent insmod of this module may enable the DSP's
	 * clock before its program/boot-address has been loaded and
	 * before this module's probe has had a chance to reset the DSP.
	 * Without the reset, the DSP can lockup permanently when it
	 * begins executing garbage.
	 */
	reset_assert(dev);

	/*
	 * The devm subsystem might end up releasing things before
	 * freeing the irq, thus allowing an interrupt to sneak in while
	 * the device is being removed.  This should prevent that.
	 */
	disable_irq(drproc->irq);

	rproc_del(rproc);
	rproc_put(rproc);

	return 0;
}
static int wkup_m3_rproc_remove(struct platform_device *pdev)
{
	struct rproc *rproc = platform_get_drvdata(pdev);

	rproc_del(rproc);
	rproc_put(rproc);
	pm_runtime_put_sync(&pdev->dev);

	m3_rproc_static = NULL;

	return 0;
}
Beispiel #3
0
static int qproc_remove(struct platform_device *pdev)
{
	struct qproc *qproc = platform_get_drvdata(pdev);
	int i;

	for (i = 0; i < ARRAY_SIZE(qproc_attrs); i++)
		device_remove_file(&pdev->dev, &qproc_attrs[i]);

	rproc_put(qproc->rproc);

	return 0;
}
static int zynqmp_r5_remoteproc_remove(struct platform_device *pdev)
{
	struct zynqmp_r5_rproc_pdata *local = platform_get_drvdata(pdev);

	dev_info(&pdev->dev, "%s\n", __func__);

	rproc_del(local->rproc);
	rproc_put(local->rproc);

	dma_release_declared_memory(&pdev->dev);

	return 0;
}
Beispiel #5
0
static void rproc_exit(void) {
  volatile unsigned int *r = OMAP2_L4_IO_ADDRESS(M3_RSTCTRL);
  printk(KERN_ALERT "rproc leaving\n");

  //Release the system, shutdown remote core.
  if (dummy_rproc != NULL){
    printk(KERN_ALERT "Reset Cortex M3 Core2,%x\n",*r);
    //Before we shutdown the main M3 core, have to turn off
    //the second M3 cores first.
    *r |= 0x2;
    printk(KERN_ALERT "RSTCTRL reg after reset %x\n",*r);
    printk(KERN_ALERT "Put rproc handle\n");
    rproc_put(dummy_rproc);
  }
}
Beispiel #6
0
/* STE modem device is unregistered */
static int sproc_drv_remove(struct platform_device *pdev)
{
	struct ste_modem_device *mdev =
		container_of(pdev, struct ste_modem_device, pdev);
	struct sproc *sproc = mdev->drv_data;

	sproc_dbg(sproc, "remove ste-modem\n");

	/* Reset device callback functions */
	sproc->mdev->ops.setup(sproc->mdev, NULL);

	/* Unregister as remoteproc device */
	rproc_del(sproc->rproc);
	dma_free_coherent(sproc->rproc->dev.parent, SPROC_FW_SIZE,
			  sproc->fw_addr, sproc->fw_dma_addr);
	rproc_put(sproc->rproc);

	mdev->drv_data = NULL;

	return 0;
}
Beispiel #7
0
/* Handle probe of a modem device */
static int sproc_probe(struct platform_device *pdev)
{
	struct ste_modem_device *mdev =
		container_of(pdev, struct ste_modem_device, pdev);
	struct sproc *sproc;
	struct rproc *rproc;
	int err;

	dev_dbg(&mdev->pdev.dev, "probe ste-modem\n");

	if (!mdev->ops.setup || !mdev->ops.kick || !mdev->ops.kick_subscribe ||
	    !mdev->ops.power) {
		dev_err(&mdev->pdev.dev, "invalid mdev ops\n");
		return -EINVAL;
	}

	rproc = rproc_alloc(&mdev->pdev.dev, mdev->pdev.name, &sproc_ops,
			    SPROC_MODEM_FIRMWARE, sizeof(*sproc));
	if (!rproc)
		return -ENOMEM;

	sproc = rproc->priv;
	sproc->mdev = mdev;
	sproc->rproc = rproc;
	mdev->drv_data = sproc;

	/* Provide callback functions to modem device */
	sproc->mdev->ops.setup(sproc->mdev, &sproc_dev_cb);

	/* Set the STE-modem specific firmware handler */
	rproc->fw_ops = &sproc_fw_ops;

	/*
	 * STE-modem requires the firmware to be located
	 * at the start of the shared memory region. So we need to
	 * reserve space for firmware at the start.
	 */
	sproc->fw_addr = dma_alloc_coherent(rproc->dev.parent, SPROC_FW_SIZE,
					    &sproc->fw_dma_addr,
					    GFP_KERNEL);
	if (!sproc->fw_addr) {
		sproc_err(sproc, "Cannot allocate memory for fw\n");
		err = -ENOMEM;
		goto free_rproc;
	}

	/* Register as a remoteproc device */
	err = rproc_add(rproc);
	if (err)
		goto free_mem;

	return 0;

free_mem:
	dma_free_coherent(rproc->dev.parent, SPROC_FW_SIZE,
			  sproc->fw_addr, sproc->fw_dma_addr);
free_rproc:
	/* Reset device data upon error */
	mdev->drv_data = NULL;
	rproc_put(rproc);
	return err;
}
Beispiel #8
0
static int da8xx_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct da8xx_rproc *drproc;
	struct rproc *rproc;
	struct irq_data *irq_data;
	struct resource *bootreg_res;
	struct resource *chipsig_res;
	struct clk *dsp_clk;
	void __iomem *chipsig;
	void __iomem *bootreg;
	int irq;
	int ret;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		dev_err(dev, "platform_get_irq(pdev, 0) error: %d\n", irq);
		return irq;
	}

	irq_data = irq_get_irq_data(irq);
	if (!irq_data) {
		dev_err(dev, "irq_get_irq_data(%d): NULL\n", irq);
		return -EINVAL;
	}

	bootreg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	bootreg = devm_ioremap_resource(dev, bootreg_res);
	if (IS_ERR(bootreg))
		return PTR_ERR(bootreg);

	chipsig_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	chipsig = devm_ioremap_resource(dev, chipsig_res);
	if (IS_ERR(chipsig))
		return PTR_ERR(chipsig);

	dsp_clk = devm_clk_get(dev, NULL);
	if (IS_ERR(dsp_clk)) {
		dev_err(dev, "clk_get error: %ld\n", PTR_ERR(dsp_clk));

		return PTR_ERR(dsp_clk);
	}

	rproc = rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name,
		sizeof(*drproc));
	if (!rproc)
		return -ENOMEM;

	drproc = rproc->priv;
	drproc->rproc = rproc;
	rproc->has_iommu = false;

	platform_set_drvdata(pdev, rproc);

	/* everything the ISR needs is now setup, so hook it up */
	ret = devm_request_threaded_irq(dev, irq, da8xx_rproc_callback,
					handle_event, 0, "da8xx-remoteproc",
					rproc);
	if (ret) {
		dev_err(dev, "devm_request_threaded_irq error: %d\n", ret);
		goto free_rproc;
	}

	/*
	 * rproc_add() can end up enabling the DSP's clk with the DSP
	 * *not* in reset, but da8xx_rproc_start() needs the DSP to be
	 * held in reset at the time it is called.
	 */
	ret = reset_assert(dev);
	if (ret)
		goto free_rproc;

	drproc->chipsig = chipsig;
	drproc->bootreg = bootreg;
	drproc->ack_fxn = irq_data->chip->irq_ack;
	drproc->irq_data = irq_data;
	drproc->irq = irq;
	drproc->dsp_clk = dsp_clk;

	ret = rproc_add(rproc);
	if (ret) {
		dev_err(dev, "rproc_add failed: %d\n", ret);
		goto free_rproc;
	}

	return 0;

free_rproc:
	rproc_put(rproc);

	return ret;
}
static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
{
	const unsigned char *prop;
	struct resource *res;
	int ret = 0;
	int method = 0;
	struct zynqmp_r5_rproc_pdata *local;

	local = devm_kzalloc(&pdev->dev, sizeof(struct zynqmp_r5_rproc_pdata),
				 GFP_KERNEL);
	if (!local)
		return -ENOMEM;

	platform_set_drvdata(pdev, local);

	/* Declare vring for firmware */
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vring0");
	if (!res) {
		dev_err(&pdev->dev, "invalid address for vring0\n");
		return -ENXIO;
	}

	/* FIXME: it may need to extend to 64/48 bit */
	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
		goto dma_mask_fault;
	}

	prop = of_get_property(pdev->dev.of_node, "core_conf", NULL);
	if (!prop) {
		dev_warn(&pdev->dev, "default core_conf used: lock-step\n");
		prop = "lock-step";
	}

	dev_info(&pdev->dev, "RPU core_conf: %s\n", prop);
	if (!strcmp(prop, "split0")) {
		local->rpu_mode = SPLIT;
		local->rpu_id = 0;
	} else if (!strcmp(prop, "split1")) {
		local->rpu_mode = SPLIT;
		local->rpu_id = 1;
	} else if (!strcmp(prop, "lock-step")) {
		local->rpu_mode = LOCK_STEP;
		local->rpu_id = 0;
	} else {
		dev_err(&pdev->dev, "Invalid core_conf mode provided - %s , %d\n",
			prop, local->rpu_mode);
		goto dma_mask_fault;
	}

	prop = of_get_property(pdev->dev.of_node, "method", NULL);
	if (!prop) {
		dev_warn(&pdev->dev, "default method used: smc\n");
		prop = "smc";
	}

	dev_info(&pdev->dev, "IPI/RPU control method: %s\n", prop);
	if (!strcmp(prop, "direct")) {
		method = HW;
		local->ipi_ops = &ipi_hw_ops;
		local->rpu_ops = &rpu_hw_ops;
	} else if (!strcmp(prop, "hvc")) {
		method = HVC;
		local->ipi_ops = &ipi_hvc_ops;
		local->rpu_ops = &rpu_hvc_ops;
	} else if (!strcmp(prop, "smc")) {
		method = SMC;
		local->ipi_ops = &ipi_smc_ops;
		local->rpu_ops = &rpu_smc_ops;
	} else {
		dev_err(&pdev->dev, "Invalid method provided - %s\n",
			prop);
		goto dma_mask_fault;
	}

	/* Handle direct hardware access */
	/* (TODO: remove once RPU and IPI drivers are ready ) */
	if (method == HW) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"rpu_base");
		local->rpu_base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(local->rpu_base)) {
			dev_err(&pdev->dev, "Unable to map RPU I/O memory\n");
			ret = PTR_ERR(local->rpu_base);
			goto dma_mask_fault;
		}

		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"apb_base");
		local->crl_apb_base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(local->crl_apb_base)) {
			dev_err(&pdev->dev, "Unable to map CRL_APB I/O memory\n");
			ret = PTR_ERR(local->crl_apb_base);
			goto dma_mask_fault;
		}

		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipi");
		local->ipi_base = devm_ioremap_resource(&pdev->dev, res);
		if (IS_ERR(local->ipi_base)) {
			pr_err("%s: Unable to map IPI\n", __func__);
			ret = PTR_ERR(local->ipi_base);
			goto dma_mask_fault;
		}
	}

	prop = of_get_property(pdev->dev.of_node, "bootmem", NULL);
	if (!prop) {
		dev_warn(&pdev->dev, "default bootmem property used: tcm\n");
		prop = "tcm";
	}

	dev_info(&pdev->dev, "RPU bootmem: %s\n", prop);
	if (!strcmp(prop, "tcm")) {
		local->bootmem = TCM;
	} else if (!strcmp(prop, "ocm")) {
		local->bootmem = OCM;
	} else {
		dev_err(&pdev->dev, "Invalid R5 bootmem property - %s\n",
			prop);
		goto dma_mask_fault;
	}

	/* IPI IRQ */
	local->vring0 = platform_get_irq(pdev, 0);
	if (local->vring0 < 0) {
		ret = local->vring0;
		dev_err(&pdev->dev, "unable to find IPI IRQ\n");
		goto dma_mask_fault;
	}
	ret = devm_request_irq(&pdev->dev, local->vring0,
		r5_remoteproc_interrupt, 0, dev_name(&pdev->dev),
		&pdev->dev);
	if (ret) {
		dev_err(&pdev->dev, "IRQ %d already allocated\n",
			local->vring0);
		goto dma_mask_fault;
	}
	dev_dbg(&pdev->dev, "vring0 irq: %d\n", local->vring0);

	ret = of_property_read_u32(pdev->dev.of_node, "ipi_dest_mask",
		&local->ipi_dest_mask);
	if (ret < 0) {
		dev_warn(&pdev->dev, "default ipi_dest_mask used: 0x100\n");
		local->ipi_dest_mask = 0x100;
	}
	dev_info(&pdev->dev, "ipi_dest_mask: 0x%x\n", local->ipi_dest_mask);

	/* Module param firmware first */
	prop = of_get_property(pdev->dev.of_node, "firmware", NULL);
	if (firmware)
		prop = firmware;
	else if (!prop)
		prop = DEFAULT_FIRMWARE_NAME;

	if (prop) {
		dev_dbg(&pdev->dev, "Using firmware: %s\n", prop);
		local->rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev),
			&zynqmp_r5_rproc_ops, prop, sizeof(struct rproc));
		if (!local->rproc) {
			dev_err(&pdev->dev, "rproc allocation failed\n");
			goto rproc_fault;
		}

		ret = rproc_add(local->rproc);
		if (ret) {
			dev_err(&pdev->dev, "rproc registration failed\n");
			goto rproc_fault;
		}
	} else {
		ret = -ENODEV;
	}

	return ret;

rproc_fault:
	rproc_put(local->rproc);

dma_mask_fault:
	dma_release_declared_memory(&pdev->dev);

err_exit:
	return 0;
}
static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
{
	const unsigned char *prop;
	struct resource *res;
	int ret = 0;
	int method = 0;
	char *rproc_firmware = 0;
	struct zynqmp_r5_rproc_pdata *local;

	local = devm_kzalloc(&pdev->dev, sizeof(struct zynqmp_r5_rproc_pdata),
				 GFP_KERNEL);
	if (!local)
		return -ENOMEM;

	platform_set_drvdata(pdev, local);

	/* FIXME: it may need to extend to 64/48 bit */
	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
		goto dma_mask_fault;
	}

	prop = of_get_property(pdev->dev.of_node, "core_conf", NULL);
	if (!prop) {
		dev_warn(&pdev->dev, "default core_conf used: lock-step\n");
		prop = "lock-step";
	}

	dev_info(&pdev->dev, "RPU core_conf: %s\n", prop);
	if (!strcmp(prop, "split0")) {
		local->rpu_mode = SPLIT;
		local->rpu_id = 0;
	} else if (!strcmp(prop, "split1")) {
		local->rpu_mode = SPLIT;
		local->rpu_id = 1;
	} else if (!strcmp(prop, "lock-step")) {
		local->rpu_mode = LOCK_STEP;
		local->rpu_id = 0;
	} else {
		dev_err(&pdev->dev, "Invalid core_conf mode provided - %s , %d\n",
			prop, local->rpu_mode);
		ret = -EINVAL;
		goto dma_mask_fault;
	}

	prop = of_get_property(pdev->dev.of_node, "method", NULL);
	if (!prop) {
		dev_warn(&pdev->dev, "default method used: smc\n");
		prop = "direct";
	}

	dev_info(&pdev->dev, "IPI/RPU control method: %s\n", prop);
	if (!strcmp(prop, "direct")) {
		method = HW;
		local->ipi_ops = &ipi_hw_ops;
		local->rpu_ops = &rpu_hw_ops;
	} else if (!strcmp(prop, "hvc")) {
		method = HVC;
		local->ipi_ops = &ipi_hvc_ops;
		local->rpu_ops = &rpu_hvc_ops;
	} else if (!strcmp(prop, "smc")) {
		method = SMC;
		local->ipi_ops = &ipi_smc_ops;
		local->rpu_ops = &rpu_smc_ops;
	} else {
		dev_err(&pdev->dev, "Invalid method provided - %s\n",
			prop);
		ret = -EINVAL;
		goto dma_mask_fault;
	}

	/* Handle direct hardware access */
	/* (TODO: remove once RPU and IPI drivers are ready ) */
	if (method == HW) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"rpu_base");
		local->rpu_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
		if (IS_ERR(local->rpu_base)) {
			dev_err(&pdev->dev, "Unable to map RPU I/O memory\n");
			ret = PTR_ERR(local->rpu_base);
			goto dma_mask_fault;
		}

		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
			"apb_base");
		local->crl_apb_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
		if (IS_ERR(local->crl_apb_base)) {
			dev_err(&pdev->dev, "Unable to map CRL_APB I/O memory\n");
			ret = PTR_ERR(local->crl_apb_base);
			goto dma_mask_fault;
		}

		res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipi");
		local->ipi_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
		if (IS_ERR(local->ipi_base)) {
			pr_err("%s: Unable to map IPI\n", __func__);
			ret = PTR_ERR(local->ipi_base);
			goto dma_mask_fault;
		}
	}

	/* IPI IRQ */
	local->vring0 = platform_get_irq(pdev, 0);
	if (local->vring0 < 0) {
		ret = local->vring0;
		dev_err(&pdev->dev, "unable to find IPI IRQ\n");
		goto dma_mask_fault;
	}
	ret = devm_request_irq(&pdev->dev, local->vring0,
		r5_remoteproc_interrupt, IRQF_SHARED, dev_name(&pdev->dev),
		&pdev->dev);
	if (ret) {
		dev_err(&pdev->dev, "IRQ %d already allocated\n",
			local->vring0);
		goto dma_mask_fault;
	}
	dev_dbg(&pdev->dev, "vring0 irq: %d\n", local->vring0);

	if (local->rpu_id == 0) {
		local->ipi_dest_mask = RPU_0_IPI_MASK;
		rproc_firmware = firmware;
	} else {
		local->ipi_dest_mask = RPU_1_IPI_MASK;
		rproc_firmware = firmware1;
	}

	dev_dbg(&pdev->dev, "Using firmware: %s\n", rproc_firmware);
	local->rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev),
		&zynqmp_r5_rproc_ops, rproc_firmware, sizeof(struct rproc));
	if (!local->rproc) {
		dev_err(&pdev->dev, "rproc allocation failed\n");
		goto rproc_fault;
	}

	zynqmp_r5_rproc_init(local->rproc);
	ret = rproc_add(local->rproc);
	if (ret) {
		dev_err(&pdev->dev, "rproc registration failed\n");
		goto rproc_fault;
	}

	return ret;

rproc_fault:
	rproc_put(local->rproc);

dma_mask_fault:
	dma_release_declared_memory(&pdev->dev);

	return ret;
}
static int wkup_m3_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct wkup_m3_platform_data *pdata = dev->platform_data;
	struct wkup_m3_rproc *m3_rproc;
	struct rproc *rproc;
	int irq, ret;
	struct resource *res;
	struct task_struct *task;

	if (!wkup_m3_pm_ops)
		return -EPROBE_DEFER;

	pm_runtime_enable(&pdev->dev);

	ret = pm_runtime_get_sync(&pdev->dev);
	if (IS_ERR_VALUE(ret)) {
		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
		return ret;
	}

	rproc = rproc_alloc(dev, "wkup_m3", &wkup_m3_rproc_ops,
			    "am335x-pm-firmware.elf", sizeof(*m3_rproc));
	if (!rproc)
		return -ENOMEM;

	m3_rproc = rproc->priv;
	m3_rproc->rproc = rproc;
	m3_rproc->pdev = pdev;

	m3_rproc_static = m3_rproc;

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipc_regs");
	m3_rproc->ipc_mem_base = devm_ioremap_resource(dev, res);
	if (!m3_rproc->ipc_mem_base) {
		dev_err(dev, "could not ioremap ipc_mem\n");
		ret = -EADDRNOTAVAIL;
		goto err;
	}

	irq = platform_get_irq(pdev, 0);
	if (!irq) {
		dev_err(&pdev->dev, "no irq resource\n");
		ret = -ENXIO;
		goto err;
	}

	ret = devm_request_irq(dev, irq, wkup_m3_txev_handler,
			       IRQF_DISABLED, "wkup_m3_txev", m3_rproc);
	if (ret) {
		dev_err(dev, "request_irq failed\n");
		goto err;
	}

	if (!(pdata && pdata->deassert_reset)) {
		dev_err(dev, "Platform data missing deassert_reset!\n");
		ret = -ENODEV;
	}

	/* Register as a remoteproc device */
	ret = rproc_add(rproc);
	if (ret) {
		dev_err(dev, "rproc_add failed\n");
		goto err;
	}

	/*
	 * Wait for firmware loading completion in a thread so we
	 * can boot the wkup_m3 as soon as it's ready without holding
	 * up kernel boot
	 */
	task = kthread_run((void *)wkup_m3_rproc_loader_thread, rproc,
			   "wkup_m3_rproc_loader");

	if (IS_ERR(task)) {
		dev_err(dev, "can't create rproc_loader thread\n");
		goto err;
	}

	return 0;

err:
	rproc_put(rproc);
	pm_runtime_put_sync(&pdev->dev);
	return ret;
}
Beispiel #12
0
static int mb_remoteproc_probe(struct platform_device *pdev)
{
	const unsigned char *prop;
	struct platform_device *bram_pdev;
	struct device_node *bram_dev;
	struct resource *res; /* IO mem resources */
	int ret = 0;
	int count = 0;
	struct mb_rproc_pdata *local;

	local = devm_kzalloc(&pdev->dev, sizeof(*local), GFP_KERNEL);
	if (!local)
		return -ENOMEM;

	platform_set_drvdata(pdev, local);

	/* Declare memory for firmware */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "invalid address\n");
		return -ENODEV;
	}

	local->mem_start = res->start;
	local->mem_end = res->end;

	/* Alloc phys addr from 0 to max_addr for firmware */
	ret = dma_declare_coherent_memory(&pdev->dev, local->mem_start,
		local->mem_start, local->mem_end - local->mem_start + 1,
		DMA_MEMORY_IO);
	if (!ret) {
		dev_err(&pdev->dev, "dma_declare_coherent_memory failed\n");
		return -ENOMEM;
	}

	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret);
		goto dma_mask_fault;
	}

	/* Alloc IRQ based on DTS to be sure that no other driver will use it */
	while (1) {
		int irq;
		/* Allocating shared IRQs will ensure that any module will
		 * use these IRQs */
		irq = platform_get_irq(pdev, count++);
		if (irq == -ENXIO || irq == -EINVAL)
			break;
		ret = devm_request_irq(&pdev->dev, irq, mb_remoteproc_interrupt,
				       0, dev_name(&pdev->dev), &pdev->dev);
		if (ret) {
			dev_err(&pdev->dev, "IRQ %d already allocated\n", irq);
			goto dma_mask_fault;
		}

		dev_info(&pdev->dev, "%d: Alloc irq: %d\n", count, irq);
	}

	/* Find out reset gpio and keep microblaze in reset */
	local->reset_gpio = of_get_named_gpio(pdev->dev.of_node, "reset", 0);
	if (local->reset_gpio < 0) {
		dev_err(&pdev->dev, "reset-gpio property not found\n");
		ret = local->reset_gpio;
		goto dma_mask_fault;
	}
	ret = devm_gpio_request_one(&pdev->dev, local->reset_gpio,
				    GPIOF_OUT_INIT_HIGH, "mb_reset");
	if (ret) {
		dev_err(&pdev->dev, "Please specify gpio reset addr\n");
		goto dma_mask_fault;
	}

	/* Find out reset gpio and keep microblaze in reset */
	local->mb_debug_gpio = of_get_named_gpio(pdev->dev.of_node, "debug", 0);
	if (local->mb_debug_gpio < 0) {
		dev_err(&pdev->dev, "mb-debug-gpio property not found\n");
		ret = local->mb_debug_gpio;
		goto dma_mask_fault;
	}
	ret = devm_gpio_request_one(&pdev->dev, local->mb_debug_gpio,
				    GPIOF_OUT_INIT_LOW, "mb_debug");
	if (ret) {
		dev_err(&pdev->dev, "Please specify gpio debug pin\n");
		goto dma_mask_fault;
	}

	/* IPI number for getting irq from firmware */
	local->ipi = of_get_named_gpio(pdev->dev.of_node, "ipino", 0);
	if (local->ipi < 0) {
		dev_err(&pdev->dev, "ipi-gpio property not found\n");
		ret = local->ipi;
		goto dma_mask_fault;
	}
	ret = devm_gpio_request_one(&pdev->dev, local->ipi, GPIOF_IN, "mb_ipi");
	if (ret) {
		dev_err(&pdev->dev, "Please specify gpio reset addr\n");
		goto dma_mask_fault;
	}
	ret = devm_request_irq(&pdev->dev, gpio_to_irq(local->ipi),
			       ipi_kick, IRQF_SHARED|IRQF_TRIGGER_RISING,
			       dev_name(&pdev->dev), local);
	if (ret) {
		dev_err(&pdev->dev, "IRQ %d already allocated\n", local->ipi);
		goto dma_mask_fault;
	}

	/* Find out vring0 pin */
	local->vring0 = of_get_named_gpio(pdev->dev.of_node, "vring0", 0);
	if (local->vring0 < 0) {
		dev_err(&pdev->dev, "reset-gpio property not found\n");
		ret = local->vring0;
		goto dma_mask_fault;
	}
	ret = devm_gpio_request_one(&pdev->dev, local->vring0,
				    GPIOF_DIR_OUT, "mb_vring0");
	if (ret) {
		dev_err(&pdev->dev, "Please specify gpio reset addr\n");
		goto dma_mask_fault;
	}

	/* Find out vring1 pin */
	local->vring1 = of_get_named_gpio(pdev->dev.of_node, "vring1", 0);
	if (local->vring1 < 0) {
		dev_err(&pdev->dev, "reset-gpio property not found\n");
		ret = local->vring1;
		goto dma_mask_fault;
	}
	ret = devm_gpio_request_one(&pdev->dev, local->vring1,
				    GPIOF_DIR_OUT, "mb_vring1");
	if (ret) {
		dev_err(&pdev->dev, "Please specify gpio reset addr\n");
		goto dma_mask_fault;
	}

	/* Allocate bram device */
	bram_dev = of_parse_phandle(pdev->dev.of_node, "bram", 0);
	if (!bram_dev) {
		dev_err(&pdev->dev, "Please specify bram connection\n");
		ret = -ENODEV;
		goto dma_mask_fault;
	}
	bram_pdev = of_find_device_by_node(bram_dev);
	if (!bram_pdev) {
		dev_err(&pdev->dev, "BRAM device hasn't found\n");
		ret = -ENODEV;
		goto dma_mask_fault;
	}
	res = platform_get_resource(bram_pdev, IORESOURCE_MEM, 0);
	local->vbase = devm_ioremap_resource(&pdev->dev, res);
	if (!local->vbase) {
		ret = -ENODEV;
		goto dma_mask_fault;
	}

	/* Load simple bootloader to bram */
	local->bootloader = of_get_property(pdev->dev.of_node,
					    "bram-firmware", NULL);
	if (!local->bootloader) {
		dev_err(&pdev->dev, "Please specify BRAM firmware\n");
		ret = -ENODEV;
		goto dma_mask_fault;
	}

	dev_info(&pdev->dev, "Using microblaze BRAM bootloader: %s\n",
		 local->bootloader);

	/* Module param firmware first */
	if (firmware)
		prop = firmware;
	else
		prop = of_get_property(pdev->dev.of_node, "firmware", NULL);

	if (prop) {
		dev_info(&pdev->dev, "Using firmware: %s\n", prop);
		local->rproc = rproc_alloc(&pdev->dev, dev_name(&pdev->dev),
				&mb_rproc_ops, prop, sizeof(struct rproc));
		if (!local->rproc) {
			dev_err(&pdev->dev, "rproc allocation failed\n");
			ret = -ENODEV;
			goto dma_mask_fault;
		}

		ret = rproc_add(local->rproc);
		if (ret) {
			dev_err(&pdev->dev, "rproc registration failed\n");
			rproc_put(local->rproc);
			goto dma_mask_fault;
		}
		return 0;
	} else {
		ret = -ENODEV;
	}

dma_mask_fault:
	dma_release_declared_memory(&pdev->dev);

	return ret;
}
Beispiel #13
0
static int qproc_probe(struct platform_device *pdev)
{
	struct qproc *qproc;
	struct rproc *rproc;
	int ret;
	int i;
	struct device_node *np;
	struct resource r;

	rproc = rproc_alloc(&pdev->dev, pdev->name, &qproc_ops,
			    "mba.mbn", sizeof(*qproc));
	if (!rproc)
		return -ENOMEM;

	rproc->fw_ops = &qproc_fw_ops;

	qproc = (struct qproc *)rproc->priv;
	qproc->dev = &pdev->dev;
	qproc->rproc = rproc;
	platform_set_drvdata(pdev, qproc);

	init_completion(&qproc->start_done);

	ret = qproc_init_mem(qproc, pdev);
	if (ret)
		goto free_rproc;

	ret = qproc_init_clocks(qproc);
	if (ret)
		goto free_rproc;

	ret = qproc_init_regulators(qproc);
	if (ret)
		goto free_rproc;

	//FIXME need to convert this to a proper reset... 
//	ret = qproc_init_reset(qproc);
//	if (ret)
//		goto free_rproc;

	ret = qproc_request_irq(qproc, pdev, "wdog", qproc_wdog_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->wdog_irq = ret;

	ret = qproc_request_irq(qproc, pdev, "fatal", qproc_fatal_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->fatal_irq = ret;

	ret = qproc_request_irq(qproc, pdev, "ready", qproc_ready_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->ready_irq = ret;

	ret = qproc_request_irq(qproc, pdev, "handover", qproc_handover_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->handover_irq = ret;

	ret = qproc_request_irq(qproc, pdev, "stop-ack", qproc_stop_ack_interrupt);
	if (ret < 0)
		goto free_rproc;
	qproc->stop_ack_irq = ret;

	qproc->stop_gpio = devm_gpiod_get(&pdev->dev, "qcom,stop", GPIOD_OUT_LOW);
	if (IS_ERR(qproc->stop_gpio)) {
		dev_err(&pdev->dev, "failed to acquire stop gpio\n");
		return PTR_ERR(qproc->stop_gpio);
	}

	for (i = 0; i < ARRAY_SIZE(qproc_attrs); i++) {
		ret = device_create_file(&pdev->dev, &qproc_attrs[i]);
		if (ret) {
			dev_err(&pdev->dev, "unable to create sysfs file\n");
			goto remove_device_files;
		}
	}

	np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
	if (!np) {
		dev_err(&pdev->dev, "No memory region specified\n");
	} else {

		ret = of_address_to_resource(np, 0, &r);
		of_node_put(np);
		if (ret)
			return ret;

		qproc->reloc_phys = r.start;
		qproc->reloc_size = resource_size(&r);

		dev_info(&pdev->dev, "Found relocation area %lu@%pad\n",
				qproc->reloc_size, &qproc->reloc_phys);
	}


	ret = rproc_add(rproc);
	if (ret)
		goto remove_device_files;

	return 0;

remove_device_files:
	for (i--; i >= 0; i--)
		device_remove_file(&pdev->dev, &qproc_attrs[i]);

free_rproc:
	rproc_put(rproc);

	return ret;
}