示例#1
0
static int st_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct of_device_id *match;
	struct st_rproc *ddata;
	struct device_node *np = dev->of_node;
	struct rproc *rproc;
	int enabled;
	int ret;

	match = of_match_device(st_rproc_match, dev);
	if (!match || !match->data) {
		dev_err(dev, "No device match found\n");
		return -ENODEV;
	}

	rproc = rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
	if (!rproc)
		return -ENOMEM;

	rproc->has_iommu = false;
	ddata = rproc->priv;
	ddata->config = (struct st_rproc_config *)match->data;

	platform_set_drvdata(pdev, rproc);

	ret = st_rproc_parse_dt(pdev);
	if (ret)
		goto free_rproc;

	enabled = st_rproc_state(pdev);
	if (enabled < 0) {
		ret = enabled;
		goto free_rproc;
	}

	if (enabled) {
		atomic_inc(&rproc->power);
		rproc->state = RPROC_RUNNING;
	} else {
		clk_set_rate(ddata->clk, ddata->clk_rate);
	}

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

	return 0;

free_rproc:
	rproc_free(rproc);
	return ret;
}
示例#2
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;
}
示例#3
0
static int wkup_m3_rproc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct wkup_m3_platform_data *pdata = dev->platform_data;
	/* umem always needs to be processed first */
	const char *mem_names[WKUPM3_MEM_MAX] = { "umem", "dmem" };
	struct wkup_m3_rproc *wkupm3;
	const char *fw_name;
	struct rproc *rproc;
	struct resource *res;
	const __be32 *addrp;
	u32 l4_offset = 0;
	u64 size;
	int ret;
	int i;

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

	ret = of_property_read_string(dev->of_node, "ti,pm-firmware",
				      &fw_name);
	if (ret) {
		dev_err(dev, "No firmware filename given\n");
		return -ENODEV;
	}

	pm_runtime_enable(&pdev->dev);
	ret = pm_runtime_get_sync(&pdev->dev);
	if (ret < 0) {
		dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n");
		goto err;
	}

	rproc = rproc_alloc(dev, "wkup_m3", &wkup_m3_rproc_ops,
			    fw_name, sizeof(*wkupm3));
	if (!rproc) {
		ret = -ENOMEM;
		goto err;
	}

	rproc->auto_boot = false;

	wkupm3 = rproc->priv;
	wkupm3->rproc = rproc;
	wkupm3->pdev = pdev;

	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						   mem_names[i]);
		wkupm3->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
		if (IS_ERR(wkupm3->mem[i].cpu_addr)) {
			dev_err(&pdev->dev, "devm_ioremap_resource failed for resource %d\n",
				i);
			ret = PTR_ERR(wkupm3->mem[i].cpu_addr);
			goto err;
		}
		wkupm3->mem[i].bus_addr = res->start;
		wkupm3->mem[i].size = resource_size(res);
		addrp = of_get_address(dev->of_node, i, &size, NULL);
		/*
		 * The wkupm3 has umem at address 0 in its view, so the device
		 * addresses for each memory region is computed as a relative
		 * offset of the bus address for umem, and therefore needs to be
		 * processed first.
		 */
		if (!strcmp(mem_names[i], "umem"))
			l4_offset = be32_to_cpu(*addrp);
		wkupm3->mem[i].dev_addr = be32_to_cpu(*addrp) - l4_offset;
	}

	dev_set_drvdata(dev, rproc);

	ret = rproc_add(rproc);
	if (ret) {
		dev_err(dev, "rproc_add failed\n");
		goto err_put_rproc;
	}

	return 0;

err_put_rproc:
	rproc_free(rproc);
err:
	pm_runtime_put_noidle(dev);
	pm_runtime_disable(dev);
	return ret;
}
示例#4
0
struct st_slim_rproc *st_slim_rproc_alloc(struct platform_device *pdev,
				char *fw_name)
{
	struct device *dev = &pdev->dev;
	struct st_slim_rproc *slim_rproc;
	struct device_node *np = dev->of_node;
	struct rproc *rproc;
	struct resource *res;
	int err, i;
	const struct rproc_fw_ops *elf_ops;

	if (!fw_name)
		return ERR_PTR(-EINVAL);

	if (!of_device_is_compatible(np, "st,slim-rproc"))
		return ERR_PTR(-EINVAL);

	rproc = rproc_alloc(dev, np->name, &slim_rproc_ops,
			fw_name, sizeof(*slim_rproc));
	if (!rproc)
		return ERR_PTR(-ENOMEM);

	rproc->has_iommu = false;

	slim_rproc = rproc->priv;
	slim_rproc->rproc = rproc;

	elf_ops = rproc->fw_ops;
	/* Use some generic elf ops */
	slim_rproc_fw_ops.load = elf_ops->load;
	slim_rproc_fw_ops.sanity_check = elf_ops->sanity_check;

	rproc->fw_ops = &slim_rproc_fw_ops;

	/* get imem and dmem */
	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						mem_names[i]);

		slim_rproc->mem[i].cpu_addr = devm_ioremap_resource(dev, res);
		if (IS_ERR(slim_rproc->mem[i].cpu_addr)) {
			dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
			err = PTR_ERR(slim_rproc->mem[i].cpu_addr);
			goto err;
		}
		slim_rproc->mem[i].bus_addr = res->start;
		slim_rproc->mem[i].size = resource_size(res);
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimcore");
	slim_rproc->slimcore = devm_ioremap_resource(dev, res);
	if (IS_ERR(slim_rproc->slimcore)) {
		dev_err(&pdev->dev, "failed to ioremap slimcore IO\n");
		err = PTR_ERR(slim_rproc->slimcore);
		goto err;
	}

	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "peripherals");
	slim_rproc->peri = devm_ioremap_resource(dev, res);
	if (IS_ERR(slim_rproc->peri)) {
		dev_err(&pdev->dev, "failed to ioremap peripherals IO\n");
		err = PTR_ERR(slim_rproc->peri);
		goto err;
	}

	err = slim_clk_get(slim_rproc, dev);
	if (err)
		goto err;

	err = slim_clk_enable(slim_rproc);
	if (err) {
		dev_err(dev, "Failed to enable clocks\n");
		goto err_clk_put;
	}

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

	return slim_rproc;

err_clk_dis:
	slim_clk_disable(slim_rproc);
err_clk_put:
	for (i = 0; i < ST_SLIM_MAX_CLK && slim_rproc->clks[i]; i++)
		clk_put(slim_rproc->clks[i]);
err:
	rproc_free(rproc);
	return ERR_PTR(err);
}
示例#5
0
static int adsp_probe(struct platform_device *pdev)
{
	const struct adsp_pil_data *desc;
	struct qcom_adsp *adsp;
	struct rproc *rproc;
	int ret;

	desc = of_device_get_match_data(&pdev->dev);
	if (!desc)
		return -EINVAL;

	rproc = rproc_alloc(&pdev->dev, pdev->name, &adsp_ops,
			    desc->firmware_name, sizeof(*adsp));
	if (!rproc) {
		dev_err(&pdev->dev, "unable to allocate remoteproc\n");
		return -ENOMEM;
	}

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

	ret = adsp_alloc_memory_region(adsp);
	if (ret)
		goto free_rproc;

	ret = adsp_init_clock(adsp);
	if (ret)
		goto free_rproc;

	pm_runtime_enable(adsp->dev);

	ret = adsp_init_reset(adsp);
	if (ret)
		goto disable_pm;

	ret = adsp_init_mmio(adsp, pdev);
	if (ret)
		goto disable_pm;

	ret = qcom_q6v5_init(&adsp->q6v5, pdev, rproc, desc->crash_reason_smem,
			     qcom_adsp_pil_handover);
	if (ret)
		goto disable_pm;

	qcom_add_glink_subdev(rproc, &adsp->glink_subdev);
	qcom_add_ssr_subdev(rproc, &adsp->ssr_subdev, desc->ssr_name);
	adsp->sysmon = qcom_add_sysmon_subdev(rproc,
					      desc->sysmon_name,
					      desc->ssctl_id);

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

	return 0;

disable_pm:
	pm_runtime_disable(adsp->dev);
free_rproc:
	rproc_free(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;
}
示例#7
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;
	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;
}
示例#9
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;
	struct reset_control *dsp_reset;
	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_byname(pdev, IORESOURCE_MEM,
						   "host1cfg");
	bootreg = devm_ioremap_resource(dev, bootreg_res);
	if (IS_ERR(bootreg))
		return PTR_ERR(bootreg);

	chipsig_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
						   "chipsig");
	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);
	}

	dsp_reset = devm_reset_control_get_exclusive(dev, NULL);
	if (IS_ERR(dsp_reset)) {
		if (PTR_ERR(dsp_reset) != -EPROBE_DEFER)
			dev_err(dev, "unable to get reset control: %ld\n",
				PTR_ERR(dsp_reset));

		return PTR_ERR(dsp_reset);
	}

	if (dev->of_node) {
		ret = of_reserved_mem_device_init(dev);
		if (ret) {
			dev_err(dev, "device does not have specific CMA pool: %d\n",
				ret);
			return ret;
		}
	}

	rproc = rproc_alloc(dev, "dsp", &da8xx_rproc_ops, da8xx_fw_name,
		sizeof(*drproc));
	if (!rproc) {
		ret = -ENOMEM;
		goto free_mem;
	}

	/* error recovery is not supported at present */
	rproc->recovery_disabled = true;

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

	ret = da8xx_rproc_get_internal_memories(pdev, drproc);
	if (ret)
		goto free_rproc;

	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_control_assert(dsp_reset);
	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;

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

	return 0;

free_rproc:
	rproc_free(rproc);
free_mem:
	if (dev->of_node)
		of_reserved_mem_device_release(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;
}
示例#11
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;
}
示例#12
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;
}