Example #1
0
/*
 * Probe for the NAND device.
 */
static int oxnas_nand_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct device_node *nand_np;
	struct oxnas_nand_ctrl *oxnas;
	struct nand_chip *chip;
	struct mtd_info *mtd;
	struct resource *res;
	int nchips = 0;
	int count = 0;
	int err = 0;

	/* Allocate memory for the device structure (and zero it) */
	oxnas = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
			     GFP_KERNEL);
	if (!oxnas)
		return -ENOMEM;

	nand_hw_control_init(&oxnas->base);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	oxnas->io_base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(oxnas->io_base))
		return PTR_ERR(oxnas->io_base);

	oxnas->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(oxnas->clk))
		oxnas->clk = NULL;

	/* Only a single chip node is supported */
	count = of_get_child_count(np);
	if (count > 1)
		return -EINVAL;

	clk_prepare_enable(oxnas->clk);
	device_reset_optional(&pdev->dev);

	for_each_child_of_node(np, nand_np) {
		chip = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
				    GFP_KERNEL);
		if (!chip)
			return -ENOMEM;

		chip->controller = &oxnas->base;

		nand_set_flash_node(chip, nand_np);
		nand_set_controller_data(chip, oxnas);

		mtd = nand_to_mtd(chip);
		mtd->dev.parent = &pdev->dev;
		mtd->priv = chip;

		chip->cmd_ctrl = oxnas_nand_cmd_ctrl;
		chip->read_buf = oxnas_nand_read_buf;
		chip->read_byte = oxnas_nand_read_byte;
		chip->write_buf = oxnas_nand_write_buf;
		chip->chip_delay = 30;

		/* Scan to find existence of the device */
		err = nand_scan(mtd, 1);
		if (err)
			return err;

		err = mtd_device_register(mtd, NULL, 0);
		if (err) {
			nand_release(mtd);
			return err;
		}

		oxnas->chips[nchips] = chip;
		++nchips;
	}
Example #2
0
static int meson_ao_cec_probe(struct platform_device *pdev)
{
	struct meson_ao_cec_device *ao_cec;
	struct device *hdmi_dev;
	struct resource *res;
	int ret, irq;

	hdmi_dev = cec_notifier_parse_hdmi_phandle(&pdev->dev);

	if (IS_ERR(hdmi_dev))
		return PTR_ERR(hdmi_dev);

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

	spin_lock_init(&ao_cec->cec_reg_lock);

	ao_cec->notify = cec_notifier_get(hdmi_dev);
	if (!ao_cec->notify)
		return -ENOMEM;

	ao_cec->adap = cec_allocate_adapter(&meson_ao_cec_ops, ao_cec,
					    "meson_ao_cec",
					    CEC_CAP_LOG_ADDRS |
					    CEC_CAP_TRANSMIT |
					    CEC_CAP_RC |
					    CEC_CAP_PASSTHROUGH,
					    1); /* Use 1 for now */
	if (IS_ERR(ao_cec->adap)) {
		ret = PTR_ERR(ao_cec->adap);
		goto out_probe_notify;
	}

	ao_cec->adap->owner = THIS_MODULE;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	ao_cec->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(ao_cec->base)) {
		ret = PTR_ERR(ao_cec->base);
		goto out_probe_adapter;
	}

	irq = platform_get_irq(pdev, 0);
	ret = devm_request_threaded_irq(&pdev->dev, irq,
					meson_ao_cec_irq,
					meson_ao_cec_irq_thread,
					0, NULL, ao_cec);
	if (ret) {
		dev_err(&pdev->dev, "irq request failed\n");
		goto out_probe_adapter;
	}

	ao_cec->core = devm_clk_get(&pdev->dev, "core");
	if (IS_ERR(ao_cec->core)) {
		dev_err(&pdev->dev, "core clock request failed\n");
		ret = PTR_ERR(ao_cec->core);
		goto out_probe_adapter;
	}

	ret = clk_prepare_enable(ao_cec->core);
	if (ret) {
		dev_err(&pdev->dev, "core clock enable failed\n");
		goto out_probe_adapter;
	}

	ret = clk_set_rate(ao_cec->core, CEC_CLK_RATE);
	if (ret) {
		dev_err(&pdev->dev, "core clock set rate failed\n");
		goto out_probe_clk;
	}

	device_reset_optional(&pdev->dev);

	ao_cec->pdev = pdev;
	platform_set_drvdata(pdev, ao_cec);

	ret = cec_register_adapter(ao_cec->adap, &pdev->dev);
	if (ret < 0) {
		cec_notifier_put(ao_cec->notify);
		goto out_probe_clk;
	}

	/* Setup Hardware */
	writel_relaxed(CEC_GEN_CNTL_RESET,
		       ao_cec->base + CEC_GEN_CNTL_REG);

	cec_register_cec_notifier(ao_cec->adap, ao_cec->notify);

	return 0;

out_probe_clk:
	clk_disable_unprepare(ao_cec->core);

out_probe_adapter:
	cec_delete_adapter(ao_cec->adap);

out_probe_notify:
	cec_notifier_put(ao_cec->notify);

	dev_err(&pdev->dev, "CEC controller registration failed\n");

	return ret;
}