コード例 #1
4
ファイル: fsl-imx25-tsadc.c プロジェクト: AshishNamdev/linux
static int mx25_tsadc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct mx25_tsadc *tsadc;
	struct resource *res;
	int ret;
	void __iomem *iomem;

	tsadc = devm_kzalloc(dev, sizeof(*tsadc), GFP_KERNEL);
	if (!tsadc)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	iomem = devm_ioremap_resource(dev, res);
	if (IS_ERR(iomem))
		return PTR_ERR(iomem);

	tsadc->regs = devm_regmap_init_mmio(dev, iomem,
					    &mx25_tsadc_regmap_config);
	if (IS_ERR(tsadc->regs)) {
		dev_err(dev, "Failed to initialize regmap\n");
		return PTR_ERR(tsadc->regs);
	}

	tsadc->clk = devm_clk_get(dev, "ipg");
	if (IS_ERR(tsadc->clk)) {
		dev_err(dev, "Failed to get ipg clock\n");
		return PTR_ERR(tsadc->clk);
	}

	/* setup clock according to the datasheet */
	mx25_tsadc_setup_clk(pdev, tsadc);

	/* Enable clock and reset the component */
	regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_CLK_EN,
			   MX25_TGCR_CLK_EN);
	regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_TSC_RST,
			   MX25_TGCR_TSC_RST);

	/* Setup powersaving mode, but enable internal reference voltage */
	regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_POWERMODE_MASK,
			   MX25_TGCR_POWERMODE_SAVE);
	regmap_update_bits(tsadc->regs, MX25_TSC_TGCR, MX25_TGCR_INTREFEN,
			   MX25_TGCR_INTREFEN);

	ret = mx25_tsadc_setup_irq(pdev, tsadc);
	if (ret)
		return ret;

	platform_set_drvdata(pdev, tsadc);

	of_platform_populate(np, NULL, NULL, dev);

	return 0;
}
コード例 #2
0
ファイル: tsens-common.c プロジェクト: AlexShiLucky/linux
int __init init_common(struct tsens_device *tmdev)
{
	void __iomem *tm_base, *srot_base;
	struct resource *res;
	u32 code;
	int ret;
	struct platform_device *op = of_find_device_by_node(tmdev->dev->of_node);
	u16 ctrl_offset = tmdev->reg_offsets[SROT_CTRL_OFFSET];

	if (!op)
		return -EINVAL;

	if (op->num_resources > 1) {
		/* DT with separate SROT and TM address space */
		tmdev->tm_offset = 0;
		res = platform_get_resource(op, IORESOURCE_MEM, 1);
		srot_base = devm_ioremap_resource(&op->dev, res);
		if (IS_ERR(srot_base))
			return PTR_ERR(srot_base);

		tmdev->srot_map = devm_regmap_init_mmio(tmdev->dev, srot_base,
							&tsens_srot_config);
		if (IS_ERR(tmdev->srot_map))
			return PTR_ERR(tmdev->srot_map);

	} else {
		/* old DTs where SROT and TM were in a contiguous 2K block */
		tmdev->tm_offset = 0x1000;
	}

	res = platform_get_resource(op, IORESOURCE_MEM, 0);
	tm_base = devm_ioremap_resource(&op->dev, res);
	if (IS_ERR(tm_base))
		return PTR_ERR(tm_base);

	tmdev->tm_map = devm_regmap_init_mmio(tmdev->dev, tm_base, &tsens_config);
	if (IS_ERR(tmdev->tm_map))
		return PTR_ERR(tmdev->tm_map);

	if (tmdev->srot_map) {
		ret = regmap_read(tmdev->srot_map, ctrl_offset, &code);
		if (ret)
			return ret;
		if (!(code & TSENS_EN)) {
			dev_err(tmdev->dev, "tsens device is not enabled\n");
			return -ENODEV;
		}
	}

	return 0;
}
コード例 #3
0
static int syscon_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct syscon *syscon;
	struct resource *res;

	syscon = devm_kzalloc(dev, sizeof(*syscon), GFP_KERNEL);
	if (!syscon)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENOENT;

	syscon->base = devm_ioremap(dev, res->start, resource_size(res));
	if (!syscon->base)
		return -ENOMEM;

	syscon_regmap_config.max_register = res->end - res->start - 3;
	syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
					&syscon_regmap_config);
	if (IS_ERR(syscon->regmap)) {
		dev_err(dev, "regmap init failed\n");
		return PTR_ERR(syscon->regmap);
	}

	platform_set_drvdata(pdev, syscon);

	dev_info(dev, "regmap %pR registered\n", res);

	return 0;
}
コード例 #4
0
ファイル: jz4740.c プロジェクト: 19Dan01/linux
static int jz4740_codec_probe(struct platform_device *pdev)
{
	int ret;
	struct jz4740_codec *jz4740_codec;
	struct resource *mem;
	void __iomem *base;

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

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, mem);
	if (IS_ERR(base))
		return PTR_ERR(base);

	jz4740_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					    &jz4740_codec_regmap_config);
	if (IS_ERR(jz4740_codec->regmap))
		return PTR_ERR(jz4740_codec->regmap);

	platform_set_drvdata(pdev, jz4740_codec);

	ret = snd_soc_register_codec(&pdev->dev,
			&soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1);
	if (ret)
		dev_err(&pdev->dev, "Failed to register codec\n");

	return ret;
}
コード例 #5
0
static int berlin2_pinctrl_probe(struct platform_device *pdev)
{
	const struct of_device_id *match =
		of_match_device(berlin2_pinctrl_match, &pdev->dev);
	struct regmap_config *rmconfig;
	struct regmap *regmap;
	struct resource *res;
	void __iomem *base;

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

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

	rmconfig->reg_bits = 32,
	rmconfig->val_bits = 32,
	rmconfig->reg_stride = 4,
	rmconfig->max_register = resource_size(res);

	regmap = devm_regmap_init_mmio(&pdev->dev, base, rmconfig);
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	return berlin_pinctrl_probe(pdev, match->data);
}
コード例 #6
0
ファイル: socfpga-a10.c プロジェクト: CCNITSilchar/linux
static int socfpga_a10_fpga_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct a10_fpga_priv *priv;
	void __iomem *reg_base;
	struct fpga_manager *mgr;
	struct resource *res;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	/* First mmio base is for register access */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	reg_base = devm_ioremap_resource(dev, res);
	if (IS_ERR(reg_base))
		return PTR_ERR(reg_base);

	/* Second mmio base is for writing FPGA image data */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	priv->fpga_data_addr = devm_ioremap_resource(dev, res);
	if (IS_ERR(priv->fpga_data_addr))
		return PTR_ERR(priv->fpga_data_addr);

	/* regmap for register access */
	priv->regmap = devm_regmap_init_mmio(dev, reg_base,
					     &socfpga_a10_fpga_regmap_config);
	if (IS_ERR(priv->regmap))
		return -ENODEV;

	priv->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->clk)) {
		dev_err(dev, "no clock specified\n");
		return PTR_ERR(priv->clk);
	}

	ret = clk_prepare_enable(priv->clk);
	if (ret) {
		dev_err(dev, "could not enable clock\n");
		return -EBUSY;
	}

	mgr = fpga_mgr_create(dev, "SoCFPGA Arria10 FPGA Manager",
			      &socfpga_a10_fpga_mgr_ops, priv);
	if (!mgr)
		return -ENOMEM;

	platform_set_drvdata(pdev, mgr);

	ret = fpga_mgr_register(mgr);
	if (ret) {
		fpga_mgr_free(mgr);
		clk_disable_unprepare(priv->clk);
		return ret;
	}

	return 0;
}
コード例 #7
0
ファイル: a53-pll.c プロジェクト: AlexShiLucky/linux
static int qcom_a53pll_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct regmap *regmap;
	struct resource *res;
	struct clk_pll *pll;
	void __iomem *base;
	struct clk_init_data init = { };
	int ret;

	pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL);
	if (!pll)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	regmap = devm_regmap_init_mmio(dev, base, &a53pll_regmap_config);
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	pll->l_reg = 0x04;
	pll->m_reg = 0x08;
	pll->n_reg = 0x0c;
	pll->config_reg = 0x14;
	pll->mode_reg = 0x00;
	pll->status_reg = 0x1c;
	pll->status_bit = 16;
	pll->freq_tbl = a53pll_freq;

	init.name = "a53pll";
	init.parent_names = (const char *[]){ "xo" };
	init.num_parents = 1;
	init.ops = &clk_pll_sr2_ops;
	init.flags = CLK_IS_CRITICAL;
	pll->clkr.hw.init = &init;

	ret = devm_clk_register_regmap(dev, &pll->clkr);
	if (ret) {
		dev_err(dev, "failed to register regmap clock: %d\n", ret);
		return ret;
	}

	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
					  &pll->clkr.hw);
	if (ret) {
		dev_err(dev, "failed to add clock provider: %d\n", ret);
		return ret;
	}

	return 0;
}

static const struct of_device_id qcom_a53pll_match_table[] = {
	{ .compatible = "qcom,msm8916-a53pll" },
	{ }
};
コード例 #8
0
ファイル: ccu-sun8i-r40.c プロジェクト: AlexShiLucky/linux
static int sun8i_r40_ccu_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct regmap *regmap;
	void __iomem *reg;
	u32 val;
	int ret;

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

	/* Force the PLL-Audio-1x divider to 4 */
	val = readl(reg + SUN8I_R40_PLL_AUDIO_REG);
	val &= ~GENMASK(19, 16);
	writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG);

	/* Force PLL-MIPI to MIPI mode */
	val = readl(reg + SUN8I_R40_PLL_MIPI_REG);
	val &= ~BIT(16);
	writel(val, reg + SUN8I_R40_PLL_MIPI_REG);

	/* Force OHCI 12M parent to 12M divided from 48M */
	val = readl(reg + SUN8I_R40_USB_CLK_REG);
	val &= ~GENMASK(25, 20);
	writel(val, reg + SUN8I_R40_USB_CLK_REG);

	/*
	 * Force SYS 32k (otherwise known as LOSC throughout the CCU)
	 * clock parent to LOSC output from RTC module instead of the
	 * CCU's internal RC oscillator divided output.
	 */
	writel(SUN8I_R40_SYS_32K_CLK_KEY | BIT(8),
	       reg + SUN8I_R40_SYS_32K_CLK_REG);

	regmap = devm_regmap_init_mmio(&pdev->dev, reg,
				       &sun8i_r40_ccu_regmap_config);
	if (IS_ERR(regmap))
		return PTR_ERR(regmap);

	ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun8i_r40_ccu_desc);
	if (ret)
		return ret;

	/* Gate then ungate PLL CPU after any rate changes */
	ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb);

	/* Reparent CPU during PLL CPU rate changes */
	ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk,
				  &sun8i_r40_cpu_nb);

	return 0;
}
コード例 #9
0
ファイル: tsens-common.c プロジェクト: guanhe0/kernel
int init_common(struct tsens_device *tmdev)
{
	void __iomem *base;

	base = of_iomap(tmdev->dev->of_node, 0);
	if (IS_ERR(base))
		return -EINVAL;

	tmdev->map = devm_regmap_init_mmio(tmdev->dev, base, &tsens_config);
	if (!tmdev->map)
		return -ENODEV;

	return 0;
}
コード例 #10
0
ファイル: common.c プロジェクト: 0x000000FF/edison-linux
struct regmap *
qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
	void __iomem *base;
	struct resource *res;
	struct device *dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base))
		return ERR_CAST(base);

	return devm_regmap_init_mmio(dev, base, desc->config);
}
コード例 #11
0
ファイル: atmel-hlcdc.c プロジェクト: 19Dan01/linux
static int atmel_hlcdc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct atmel_hlcdc *hlcdc;
	struct resource *res;
	void __iomem *regs;

	hlcdc = devm_kzalloc(dev, sizeof(*hlcdc), GFP_KERNEL);
	if (!hlcdc)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(regs))
		return PTR_ERR(regs);

	hlcdc->irq = platform_get_irq(pdev, 0);
	if (hlcdc->irq < 0)
		return hlcdc->irq;

	hlcdc->periph_clk = devm_clk_get(dev, "periph_clk");
	if (IS_ERR(hlcdc->periph_clk)) {
		dev_err(dev, "failed to get peripheral clock\n");
		return PTR_ERR(hlcdc->periph_clk);
	}

	hlcdc->sys_clk = devm_clk_get(dev, "sys_clk");
	if (IS_ERR(hlcdc->sys_clk)) {
		dev_err(dev, "failed to get system clock\n");
		return PTR_ERR(hlcdc->sys_clk);
	}

	hlcdc->slow_clk = devm_clk_get(dev, "slow_clk");
	if (IS_ERR(hlcdc->slow_clk)) {
		dev_err(dev, "failed to get slow clock\n");
		return PTR_ERR(hlcdc->slow_clk);
	}

	hlcdc->regmap = devm_regmap_init_mmio(dev, regs,
					      &atmel_hlcdc_regmap_config);
	if (IS_ERR(hlcdc->regmap))
		return PTR_ERR(hlcdc->regmap);

	dev_set_drvdata(dev, hlcdc);

	return mfd_add_devices(dev, -1, atmel_hlcdc_cells,
			       ARRAY_SIZE(atmel_hlcdc_cells),
			       NULL, 0, NULL);
}
コード例 #12
0
static int msm8916_wcd_digital_probe(struct platform_device *pdev)
{
	struct msm8916_wcd_digital_priv *priv;
	struct device *dev = &pdev->dev;
	void __iomem *base;
	struct resource *mem_res;
	struct regmap *digital_map;
	int ret;

	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, mem_res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	digital_map =
	    devm_regmap_init_mmio(&pdev->dev, base,
				  &msm8916_codec_regmap_config);
	if (IS_ERR(digital_map))
		return PTR_ERR(digital_map);

	ret = msm8916_wcd_digital_get_clks(pdev, priv);
	if (ret < 0)
		return ret;

	ret = clk_prepare_enable(priv->ahbclk);
	if (ret < 0) {
		dev_err(dev, "failed to enable ahbclk %d\n", ret);
		return ret;
	}

	ret = clk_prepare_enable(priv->mclk);
	if (ret < 0) {
		dev_err(dev, "failed to enable mclk %d\n", ret);
		return ret;
	}

	dev_set_drvdata(dev, priv);

	return snd_soc_register_codec(dev, &msm8916_wcd_digital,
				      msm8916_wcd_digital_dai,
				      ARRAY_SIZE(msm8916_wcd_digital_dai));
}
コード例 #13
0
ファイル: sirf-usp.c プロジェクト: AkyZero/wrapfs-latest
static int sirf_usp_pcm_probe(struct platform_device *pdev)
{
	int ret;
	struct sirf_usp *usp;
	void __iomem *base;
	struct resource *mem_res;

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

	platform_set_drvdata(pdev, usp);

	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap(&pdev->dev, mem_res->start,
		resource_size(mem_res));
	if (base == NULL)
		return -ENOMEM;
	usp->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					    &sirf_usp_regmap_config);
	if (IS_ERR(usp->regmap))
		return PTR_ERR(usp->regmap);

	usp->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(usp->clk)) {
		dev_err(&pdev->dev, "Get clock failed.\n");
		return PTR_ERR(usp->clk);
	}

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = sirf_usp_pcm_runtime_resume(&pdev->dev);
		if (ret)
			return ret;
	}

	ret = devm_snd_soc_register_component(&pdev->dev, &sirf_usp_component,
		&sirf_usp_pcm_dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Register Audio SoC dai failed.\n");
		return ret;
	}
	return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
}
コード例 #14
0
static struct regmap *meson_map(struct device *dev,
					 struct device_node *node, char *name)
{
	struct resource res;
	void __iomem *base;
	if (of_address_to_resource(node, 0, &res))
		return ERR_PTR(-ENOENT);

	base = devm_ioremap_resource(dev, &res);
	if (IS_ERR(base))
		return ERR_CAST(base);

	meson_regmap_config.max_register = resource_size(&res) - 4;
	meson_regmap_config.name = kasprintf(GFP_KERNEL,
						  "%s-%s", node->name,
						  name);
	if (!meson_regmap_config.name)
		return ERR_PTR(-ENOMEM);

	return devm_regmap_init_mmio(dev, base, &meson_regmap_config);
}
コード例 #15
0
ファイル: stm32_sai_sub.c プロジェクト: asmalldev/linux
static int stm32_sai_sub_parse_of(struct platform_device *pdev,
				  struct stm32_sai_sub_data *sai)
{
	struct device_node *np = pdev->dev.of_node;
	struct resource *res;
	void __iomem *base;

	if (!np)
		return -ENODEV;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	dev_err(&pdev->dev, "res %pr\n", res);

	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	sai->phys_addr = res->start;
	sai->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					    &stm32_sai_sub_regmap_config);

	/* Get direction property */
	if (of_property_match_string(np, "dma-names", "tx") >= 0) {
		sai->dir = SNDRV_PCM_STREAM_PLAYBACK;
	} else if (of_property_match_string(np, "dma-names", "rx") >= 0) {
		sai->dir = SNDRV_PCM_STREAM_CAPTURE;
	} else {
		dev_err(&pdev->dev, "Unsupported direction\n");
		return -EINVAL;
	}

	sai->sai_ck = devm_clk_get(&pdev->dev, "sai_ck");
	if (IS_ERR(sai->sai_ck)) {
		dev_err(&pdev->dev, "missing kernel clock sai_ck\n");
		return PTR_ERR(sai->sai_ck);
	}

	return 0;
}
コード例 #16
0
static int syscon_probe(struct platform_device *pdev)
{
    struct device *dev = &pdev->dev;
    struct device_node *np = dev->of_node;
    struct syscon *syscon;
    struct resource res;
    int ret;

    if (!np)
        return -ENOENT;

    syscon = devm_kzalloc(dev, sizeof(struct syscon),
                          GFP_KERNEL);
    if (!syscon)
        return -ENOMEM;

    syscon->base = of_iomap(np, 0);
    if (!syscon->base)
        return -EADDRNOTAVAIL;

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

    syscon_regmap_config.max_register = res.end - res.start - 3;
    syscon->regmap = devm_regmap_init_mmio(dev, syscon->base,
                                           &syscon_regmap_config);
    if (IS_ERR(syscon->regmap)) {
        dev_err(dev, "regmap init failed\n");
        return PTR_ERR(syscon->regmap);
    }

    syscon->dev = dev;
    platform_set_drvdata(pdev, syscon);

    dev_info(dev, "syscon regmap start 0x%x end 0x%x registered\n",
             res.start, res.end);

    return 0;
}
コード例 #17
0
ファイル: nvmem-mmio.c プロジェクト: vmayoral/snappy-kernel
int nvmem_mmio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct resource *res;
	const struct nvmem_mmio_data *data;
	struct nvmem_device *nvmem;
	struct regmap *regmap;
	const struct of_device_id *match;
	void __iomem *base;

	if (!dev || !dev->driver)
		return -ENODEV;

	match = of_match_device(dev->driver->of_match_table, dev);
	if (!match || !match->data)
		return -EINVAL;

	data = match->data;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	data->regmap_config->max_register = resource_size(res) - 1;

	regmap = devm_regmap_init_mmio(dev, base, data->regmap_config);
	if (IS_ERR(regmap)) {
		dev_err(dev, "regmap init failed\n");
		return PTR_ERR(regmap);
	}
	data->nvmem_config->dev = dev;
	nvmem = nvmem_register(data->nvmem_config);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	platform_set_drvdata(pdev, nvmem);

	return 0;
}
コード例 #18
0
ファイル: exynos-nocp.c プロジェクト: AngleFork/linux
static int exynos_nocp_parse_dt(struct platform_device *pdev,
				struct exynos_nocp *nocp)
{
	struct device *dev = nocp->dev;
	struct device_node *np = dev->of_node;
	struct resource *res;
	void __iomem *base;

	if (!np) {
		dev_err(dev, "failed to find devicetree node\n");
		return -EINVAL;
	}

	nocp->clk = devm_clk_get(dev, "nocp");
	if (IS_ERR(nocp->clk))
		nocp->clk = NULL;

	/* Maps the memory mapped IO to control nocp register */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (IS_ERR(res))
		return PTR_ERR(res);

	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base))
		return PTR_ERR(base);

	exynos_nocp_regmap_config.max_register = resource_size(res) - 4;

	nocp->regmap = devm_regmap_init_mmio(dev, base,
					&exynos_nocp_regmap_config);
	if (IS_ERR(nocp->regmap)) {
		dev_err(dev, "failed to initialize regmap\n");
		return PTR_ERR(nocp->regmap);
	}

	return 0;
}
コード例 #19
0
ファイル: pinctrl-meson.c プロジェクト: AshishNamdev/linux
static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
					 struct device_node *node, char *name)
{
	struct resource res;
	void __iomem *base;
	int i;

	i = of_property_match_string(node, "reg-names", name);
	if (of_address_to_resource(node, i, &res))
		return ERR_PTR(-ENOENT);

	base = devm_ioremap_resource(pc->dev, &res);
	if (IS_ERR(base))
		return ERR_CAST(base);

	meson_regmap_config.max_register = resource_size(&res) - 4;
	meson_regmap_config.name = devm_kasprintf(pc->dev, GFP_KERNEL,
						  "%s-%s", node->name,
						  name);
	if (!meson_regmap_config.name)
		return ERR_PTR(-ENOMEM);

	return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
}
コード例 #20
0
ファイル: tegra20_das.c プロジェクト: FrozenCow/FIRE-ICE
static int tegra20_das_probe(struct platform_device *pdev)
{
	struct resource *res, *region;
	void __iomem *regs;
	int ret = 0;

	if (das)
		return -ENODEV;

	das = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_das), GFP_KERNEL);
	if (!das) {
		dev_err(&pdev->dev, "Can't allocate tegra20_das\n");
		ret = -ENOMEM;
		goto err;
	}
	das->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "No memory resource\n");
		ret = -ENODEV;
		goto err;
	}

	region = devm_request_mem_region(&pdev->dev, res->start,
					 resource_size(res), pdev->name);
	if (!region) {
		dev_err(&pdev->dev, "Memory region already claimed\n");
		ret = -EBUSY;
		goto err;
	}

	regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
	if (!regs) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err;
	}

	das->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
					    &tegra20_das_regmap_config);
	if (IS_ERR(das->regmap)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		ret = PTR_ERR(das->regmap);
		goto err;
	}

	ret = tegra20_das_connect_dap_to_dac(TEGRA20_DAS_DAP_ID_1,
					     TEGRA20_DAS_DAP_SEL_DAC1);
	if (ret) {
		dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
		goto err;
	}
	ret = tegra20_das_connect_dac_to_dap(TEGRA20_DAS_DAC_ID_1,
					     TEGRA20_DAS_DAC_SEL_DAP1);
	if (ret) {
		dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
		goto err;
	}

	platform_set_drvdata(pdev, das);

	return 0;

err:
	das = NULL;
	return ret;
}
コード例 #21
0
ファイル: axi-i2s.c プロジェクト: 3null/linux
static int axi_i2s_probe(struct platform_device *pdev)
{
	struct resource *res;
	struct axi_i2s *i2s;
	void __iomem *base;
	int ret;

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

	platform_set_drvdata(pdev, i2s);

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

	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, base,
		&axi_i2s_regmap_config);
	if (IS_ERR(i2s->regmap))
		return PTR_ERR(i2s->regmap);

	i2s->clk = devm_clk_get(&pdev->dev, "axi");
	if (IS_ERR(i2s->clk))
		return PTR_ERR(i2s->clk);

	i2s->clk_ref = devm_clk_get(&pdev->dev, "ref");
	if (IS_ERR(i2s->clk_ref))
		return PTR_ERR(i2s->clk_ref);

	ret = clk_prepare_enable(i2s->clk);
	if (ret)
		return ret;

	i2s->playback_dma_data.addr = res->start + AXI_I2S_REG_TX_FIFO;
	i2s->playback_dma_data.addr_width = 4;
	i2s->playback_dma_data.maxburst = 1;

	i2s->capture_dma_data.addr = res->start + AXI_I2S_REG_RX_FIFO;
	i2s->capture_dma_data.addr_width = 4;
	i2s->capture_dma_data.maxburst = 1;

	i2s->ratnum.num = clk_get_rate(i2s->clk_ref) / 2 / AXI_I2S_BITS_PER_FRAME;
	i2s->ratnum.den_step = 1;
	i2s->ratnum.den_min = 1;
	i2s->ratnum.den_max = 64;

	i2s->rate_constraints.rats = &i2s->ratnum;
	i2s->rate_constraints.nrats = 1;

	regmap_write(i2s->regmap, AXI_I2S_REG_RESET, AXI_I2S_RESET_GLOBAL);

	ret = devm_snd_soc_register_component(&pdev->dev, &axi_i2s_component,
					 &axi_i2s_dai, 1);
	if (ret)
		goto err_clk_disable;

	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
	if (ret)
		goto err_clk_disable;

err_clk_disable:
	clk_disable_unprepare(i2s->clk);
	return ret;
}
コード例 #22
0
static int tegra30_ahub_probe(struct platform_device *pdev)
{
	const struct of_device_id *match;
	const struct tegra30_ahub_soc_data *soc_data;
	struct clk *clk;
	int i;
	struct resource *res0, *res1, *region;
	u32 of_dma[2];
	void __iomem *regs_apbif, *regs_ahub;
	int ret = 0;

	if (ahub)
		return -ENODEV;

	match = of_match_device(tegra30_ahub_of_match, &pdev->dev);
	if (!match)
		return -EINVAL;
	soc_data = match->data;

	/*
	 * The AHUB hosts a register bus: the "configlink". For this to
	 * operate correctly, all devices on this bus must be out of reset.
	 * Ensure that here.
	 */
	for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
		if (!(configlink_clocks[i].clk_list_mask &
					soc_data->clk_list_mask))
			continue;
		clk = clk_get(&pdev->dev, configlink_clocks[i].clk_name);
		if (IS_ERR(clk)) {
			dev_err(&pdev->dev, "Can't get clock %s\n",
				configlink_clocks[i].clk_name);
			ret = PTR_ERR(clk);
			goto err;
		}
		tegra_periph_reset_deassert(clk);
		clk_put(clk);
	}

	ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub),
			    GFP_KERNEL);
	if (!ahub) {
		dev_err(&pdev->dev, "Can't allocate tegra30_ahub\n");
		ret = -ENOMEM;
		goto err;
	}
	dev_set_drvdata(&pdev->dev, ahub);

	ahub->dev = &pdev->dev;

	ahub->clk_d_audio = clk_get(&pdev->dev, "d_audio");
	if (IS_ERR(ahub->clk_d_audio)) {
		dev_err(&pdev->dev, "Can't retrieve ahub d_audio clock\n");
		ret = PTR_ERR(ahub->clk_d_audio);
		goto err;
	}

	ahub->clk_apbif = clk_get(&pdev->dev, "apbif");
	if (IS_ERR(ahub->clk_apbif)) {
		dev_err(&pdev->dev, "Can't retrieve ahub apbif clock\n");
		ret = PTR_ERR(ahub->clk_apbif);
		goto err_clk_put_d_audio;
	}

	if (of_property_read_u32_array(pdev->dev.of_node,
				"nvidia,dma-request-selector",
				of_dma, 2) < 0) {
		dev_err(&pdev->dev,
			"Missing property nvidia,dma-request-selector\n");
		ret = -ENODEV;
		goto err_clk_put_d_audio;
	}
	ahub->dma_sel = of_dma[1];

	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res0) {
		dev_err(&pdev->dev, "No apbif memory resource\n");
		ret = -ENODEV;
		goto err_clk_put_apbif;
	}

	region = devm_request_mem_region(&pdev->dev, res0->start,
					 resource_size(res0), DRV_NAME);
	if (!region) {
		dev_err(&pdev->dev, "request region apbif failed\n");
		ret = -EBUSY;
		goto err_clk_put_apbif;
	}
	ahub->apbif_addr = res0->start;

	regs_apbif = devm_ioremap(&pdev->dev, res0->start,
				  resource_size(res0));
	if (!regs_apbif) {
		dev_err(&pdev->dev, "ioremap apbif failed\n");
		ret = -ENOMEM;
		goto err_clk_put_apbif;
	}

	ahub->regmap_apbif = devm_regmap_init_mmio(&pdev->dev, regs_apbif,
					&tegra30_ahub_apbif_regmap_config);
	if (IS_ERR(ahub->regmap_apbif)) {
		dev_err(&pdev->dev, "apbif regmap init failed\n");
		ret = PTR_ERR(ahub->regmap_apbif);
		goto err_clk_put_apbif;
	}
	regcache_cache_only(ahub->regmap_apbif, true);

	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res1) {
		dev_err(&pdev->dev, "No ahub memory resource\n");
		ret = -ENODEV;
		goto err_clk_put_apbif;
	}

	region = devm_request_mem_region(&pdev->dev, res1->start,
					 resource_size(res1), DRV_NAME);
	if (!region) {
		dev_err(&pdev->dev, "request region ahub failed\n");
		ret = -EBUSY;
		goto err_clk_put_apbif;
	}

	regs_ahub = devm_ioremap(&pdev->dev, res1->start,
				 resource_size(res1));
	if (!regs_ahub) {
		dev_err(&pdev->dev, "ioremap ahub failed\n");
		ret = -ENOMEM;
		goto err_clk_put_apbif;
	}

	ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub,
					&tegra30_ahub_ahub_regmap_config);
	if (IS_ERR(ahub->regmap_ahub)) {
		dev_err(&pdev->dev, "ahub regmap init failed\n");
		ret = PTR_ERR(ahub->regmap_ahub);
		goto err_clk_put_apbif;
	}
	regcache_cache_only(ahub->regmap_ahub, true);

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = tegra30_ahub_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);

	return 0;

err_pm_disable:
	pm_runtime_disable(&pdev->dev);
err_clk_put_apbif:
	clk_put(ahub->clk_apbif);
err_clk_put_d_audio:
	clk_put(ahub->clk_d_audio);
	ahub = NULL;
err:
	return ret;
}
コード例 #23
0
ファイル: tegra20_i2s.c プロジェクト: AlexShiLucky/linux
static int tegra20_i2s_platform_probe(struct platform_device *pdev)
{
	struct tegra20_i2s *i2s;
	struct resource *mem;
	void __iomem *regs;
	int ret;

	i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_i2s), GFP_KERNEL);
	if (!i2s) {
		ret = -ENOMEM;
		goto err;
	}
	dev_set_drvdata(&pdev->dev, i2s);

	i2s->dai = tegra20_i2s_dai_template;
	i2s->dai.name = dev_name(&pdev->dev);

	i2s->clk_i2s = clk_get(&pdev->dev, NULL);
	if (IS_ERR(i2s->clk_i2s)) {
		dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
		ret = PTR_ERR(i2s->clk_i2s);
		goto err;
	}

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	regs = devm_ioremap_resource(&pdev->dev, mem);
	if (IS_ERR(regs)) {
		ret = PTR_ERR(regs);
		goto err_clk_put;
	}

	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
					    &tegra20_i2s_regmap_config);
	if (IS_ERR(i2s->regmap)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		ret = PTR_ERR(i2s->regmap);
		goto err_clk_put;
	}

	i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
	i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	i2s->capture_dma_data.maxburst = 4;

	i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
	i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	i2s->playback_dma_data.maxburst = 4;

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = tegra20_i2s_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

	ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component,
					 &i2s->dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
		ret = -ENOMEM;
		goto err_suspend;
	}

	ret = tegra_pcm_platform_register(&pdev->dev);
	if (ret) {
		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
		goto err_unregister_component;
	}

	return 0;

err_unregister_component:
	snd_soc_unregister_component(&pdev->dev);
err_suspend:
	if (!pm_runtime_status_suspended(&pdev->dev))
		tegra20_i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
	pm_runtime_disable(&pdev->dev);
err_clk_put:
	clk_put(i2s->clk_i2s);
err:
	return ret;
}
コード例 #24
0
ファイル: rockchip_i2s.c プロジェクト: a2hojsjsjs/linux
static int rockchip_i2s_probe(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
	struct rk_i2s_dev *i2s;
	struct snd_soc_dai_driver *soc_dai;
	struct resource *res;
	void __iomem *regs;
	int ret;
	int val;

	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
	if (!i2s) {
		dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
		return -ENOMEM;
	}

	/* try to prepare related clocks */
	i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
	if (IS_ERR(i2s->hclk)) {
		dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
		return PTR_ERR(i2s->hclk);
	}
	ret = clk_prepare_enable(i2s->hclk);
	if (ret) {
		dev_err(i2s->dev, "hclock enable failed %d\n", ret);
		return ret;
	}

	i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
	if (IS_ERR(i2s->mclk)) {
		dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
		return PTR_ERR(i2s->mclk);
	}

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

	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
					    &rockchip_i2s_regmap_config);
	if (IS_ERR(i2s->regmap)) {
		dev_err(&pdev->dev,
			"Failed to initialise managed register map\n");
		return PTR_ERR(i2s->regmap);
	}

	i2s->playback_dma_data.addr = res->start + I2S_TXDR;
	i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	i2s->playback_dma_data.maxburst = 4;

	i2s->capture_dma_data.addr = res->start + I2S_RXDR;
	i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
	i2s->capture_dma_data.maxburst = 4;

	i2s->dev = &pdev->dev;
	dev_set_drvdata(&pdev->dev, i2s);

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = i2s_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

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

	memcpy(soc_dai, &rockchip_i2s_dai, sizeof(*soc_dai));
	if (!of_property_read_u32(node, "rockchip,playback-channels", &val)) {
		if (val >= 2 && val <= 8)
			soc_dai->playback.channels_max = val;
	}

	if (!of_property_read_u32(node, "rockchip,capture-channels", &val)) {
		if (val >= 2 && val <= 8)
			soc_dai->capture.channels_max = val;
	}

	ret = devm_snd_soc_register_component(&pdev->dev,
					      &rockchip_i2s_component,
					      soc_dai, 1);

	if (ret) {
		dev_err(&pdev->dev, "Could not register DAI\n");
		goto err_suspend;
	}

	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
	if (ret) {
		dev_err(&pdev->dev, "Could not register PCM\n");
		return ret;
	}

	return 0;

err_suspend:
	if (!pm_runtime_status_suspended(&pdev->dev))
		i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
	pm_runtime_disable(&pdev->dev);

	return ret;
}
コード例 #25
0
ファイル: sun4i-codec.c プロジェクト: 020gzh/linux
static int sun4i_codec_probe(struct platform_device *pdev)
{
	struct snd_soc_card *card;
	struct sun4i_codec *scodec;
	struct resource *res;
	void __iomem *base;
	int ret;

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

	scodec->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(base)) {
		dev_err(&pdev->dev, "Failed to map the registers\n");
		return PTR_ERR(base);
	}

	scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
					     &sun4i_codec_regmap_config);
	if (IS_ERR(scodec->regmap)) {
		dev_err(&pdev->dev, "Failed to create our regmap\n");
		return PTR_ERR(scodec->regmap);
	}

	/* Get the clocks from the DT */
	scodec->clk_apb = devm_clk_get(&pdev->dev, "apb");
	if (IS_ERR(scodec->clk_apb)) {
		dev_err(&pdev->dev, "Failed to get the APB clock\n");
		return PTR_ERR(scodec->clk_apb);
	}

	scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
	if (IS_ERR(scodec->clk_module)) {
		dev_err(&pdev->dev, "Failed to get the module clock\n");
		return PTR_ERR(scodec->clk_module);
	}

	/* Enable the bus clock */
	if (clk_prepare_enable(scodec->clk_apb)) {
		dev_err(&pdev->dev, "Failed to enable the APB clock\n");
		return -EINVAL;
	}

	scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
						  GPIOD_OUT_LOW);
	if (IS_ERR(scodec->gpio_pa)) {
		ret = PTR_ERR(scodec->gpio_pa);
		if (ret != -EPROBE_DEFER)
			dev_err(&pdev->dev, "Failed to get pa gpio: %d\n", ret);
		return ret;
	}

	/* DMA configuration for TX FIFO */
	scodec->playback_dma_data.addr = res->start + SUN4I_CODEC_DAC_TXDATA;
	scodec->playback_dma_data.maxburst = 4;
	scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;

	/* DMA configuration for RX FIFO */
	scodec->capture_dma_data.addr = res->start + SUN4I_CODEC_ADC_RXDATA;
	scodec->capture_dma_data.maxburst = 4;
	scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;

	ret = snd_soc_register_codec(&pdev->dev, &sun4i_codec_codec,
				     &sun4i_codec_dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our codec\n");
		goto err_clk_disable;
	}

	ret = devm_snd_soc_register_component(&pdev->dev,
					      &sun4i_codec_component,
					      &dummy_cpu_dai, 1);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our DAI\n");
		goto err_unregister_codec;
	}

	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
		goto err_unregister_codec;
	}

	card = sun4i_codec_create_card(&pdev->dev);
	if (!card) {
		dev_err(&pdev->dev, "Failed to create our card\n");
		goto err_unregister_codec;
	}

	platform_set_drvdata(pdev, card);
	snd_soc_card_set_drvdata(card, scodec);

	ret = snd_soc_register_card(card);
	if (ret) {
		dev_err(&pdev->dev, "Failed to register our card\n");
		goto err_unregister_codec;
	}

	return 0;

err_unregister_codec:
	snd_soc_unregister_codec(&pdev->dev);
err_clk_disable:
	clk_disable_unprepare(scodec->clk_apb);
	return ret;
}
コード例 #26
0
ファイル: axg-audio.c プロジェクト: avagin/linux
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct audioclk_data *data;
	struct regmap *map;
	struct resource *res;
	void __iomem *regs;
	struct clk_hw *hw;
	int ret, i;

	data = of_device_get_match_data(dev);
	if (!data)
		return -EINVAL;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(regs))
		return PTR_ERR(regs);

	map = devm_regmap_init_mmio(dev, regs, &axg_audio_regmap_cfg);
	if (IS_ERR(map)) {
		dev_err(dev, "failed to init regmap: %ld\n", PTR_ERR(map));
		return PTR_ERR(map);
	}

	/* Get the mandatory peripheral clock */
	ret = devm_clk_get_enable(dev, "pclk");
	if (ret)
		return ret;

	ret = device_reset(dev);
	if (ret) {
		dev_err(dev, "failed to reset device\n");
		return ret;
	}

	/* Register the peripheral input clock */
	hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
	if (IS_ERR(hw))
		return PTR_ERR(hw);

	/* Register optional input master clocks */
	ret = axg_register_clk_hw_inputs(dev, "mst_in",
					 AUD_MST_IN_COUNT);
	if (ret)
		return ret;

	/* Register optional input slave sclks */
	ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
					 AUD_SLV_SCLK_COUNT);
	if (ret)
		return ret;

	/* Register optional input slave lrclks */
	ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
					 AUD_SLV_LRCLK_COUNT);
	if (ret)
		return ret;

	/* Populate regmap for the regmap backed clocks */
	for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
		aud_clk_regmaps[i]->map = map;

	/* Take care to skip the registered input clocks */
	for (i = AUD_CLKID_DDR_ARB; i < data->hw_onecell_data->num; i++) {
		hw = data->hw_onecell_data->hws[i];
		/* array might be sparse */
		if (!hw)
			continue;

		ret = devm_clk_hw_register(dev, hw);
		if (ret) {
			dev_err(dev, "failed to register clock %s\n",
				hw->init->name);
			return ret;
		}
	}

	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
					   data->hw_onecell_data);
}
コード例 #27
0
ファイル: sun8i_mixer.c プロジェクト: Anjali05/linux
static int sun8i_mixer_bind(struct device *dev, struct device *master,
			      void *data)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct drm_device *drm = data;
	struct sun4i_drv *drv = drm->dev_private;
	struct sun8i_mixer *mixer;
	struct resource *res;
	void __iomem *regs;
	unsigned int base;
	int plane_cnt;
	int i, ret;

	/*
	 * The mixer uses single 32-bit register to store memory
	 * addresses, so that it cannot deal with 64-bit memory
	 * addresses.
	 * Restrict the DMA mask so that the mixer won't be
	 * allocated some memory that is too high.
	 */
	ret = dma_set_mask(dev, DMA_BIT_MASK(32));
	if (ret) {
		dev_err(dev, "Cannot do 32-bit DMA.\n");
		return ret;
	}

	mixer = devm_kzalloc(dev, sizeof(*mixer), GFP_KERNEL);
	if (!mixer)
		return -ENOMEM;
	dev_set_drvdata(dev, mixer);
	mixer->engine.ops = &sun8i_engine_ops;
	mixer->engine.node = dev->of_node;

	/*
	 * While this function can fail, we shouldn't do anything
	 * if this happens. Some early DE2 DT entries don't provide
	 * mixer id but work nevertheless because matching between
	 * TCON and mixer is done by comparing node pointers (old
	 * way) instead comparing ids. If this function fails and
	 * id is needed, it will fail during id matching anyway.
	 */
	mixer->engine.id = sun8i_mixer_of_get_id(dev->of_node);

	mixer->cfg = of_device_get_match_data(dev);
	if (!mixer->cfg)
		return -EINVAL;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	regs = devm_ioremap_resource(dev, res);
	if (IS_ERR(regs))
		return PTR_ERR(regs);

	mixer->engine.regs = devm_regmap_init_mmio(dev, regs,
						   &sun8i_mixer_regmap_config);
	if (IS_ERR(mixer->engine.regs)) {
		dev_err(dev, "Couldn't create the mixer regmap\n");
		return PTR_ERR(mixer->engine.regs);
	}

	mixer->reset = devm_reset_control_get(dev, NULL);
	if (IS_ERR(mixer->reset)) {
		dev_err(dev, "Couldn't get our reset line\n");
		return PTR_ERR(mixer->reset);
	}

	ret = reset_control_deassert(mixer->reset);
	if (ret) {
		dev_err(dev, "Couldn't deassert our reset line\n");
		return ret;
	}

	mixer->bus_clk = devm_clk_get(dev, "bus");
	if (IS_ERR(mixer->bus_clk)) {
		dev_err(dev, "Couldn't get the mixer bus clock\n");
		ret = PTR_ERR(mixer->bus_clk);
		goto err_assert_reset;
	}
	clk_prepare_enable(mixer->bus_clk);

	mixer->mod_clk = devm_clk_get(dev, "mod");
	if (IS_ERR(mixer->mod_clk)) {
		dev_err(dev, "Couldn't get the mixer module clock\n");
		ret = PTR_ERR(mixer->mod_clk);
		goto err_disable_bus_clk;
	}

	/*
	 * It seems that we need to enforce that rate for whatever
	 * reason for the mixer to be functional. Make sure it's the
	 * case.
	 */
	if (mixer->cfg->mod_rate)
		clk_set_rate(mixer->mod_clk, mixer->cfg->mod_rate);

	clk_prepare_enable(mixer->mod_clk);

	list_add_tail(&mixer->engine.list, &drv->engine_list);

	base = sun8i_blender_base(mixer);

	/* Reset registers and disable unused sub-engines */
	if (mixer->cfg->is_de3) {
		for (i = 0; i < DE3_MIXER_UNIT_SIZE; i += 4)
			regmap_write(mixer->engine.regs, i, 0);

		regmap_write(mixer->engine.regs, SUN50I_MIXER_FCE_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_PEAK_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_LCTI_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_BLS_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_FCC_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_DNS_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_DRC_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_FMT_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC0_EN, 0);
		regmap_write(mixer->engine.regs, SUN50I_MIXER_CDC1_EN, 0);
	} else {
		for (i = 0; i < DE2_MIXER_UNIT_SIZE; i += 4)
			regmap_write(mixer->engine.regs, i, 0);

		regmap_write(mixer->engine.regs, SUN8I_MIXER_FCE_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_BWS_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_LTI_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_PEAK_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_ASE_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_FCC_EN, 0);
		regmap_write(mixer->engine.regs, SUN8I_MIXER_DCSC_EN, 0);
	}

	/* Enable the mixer */
	regmap_write(mixer->engine.regs, SUN8I_MIXER_GLOBAL_CTL,
		     SUN8I_MIXER_GLOBAL_CTL_RT_EN);

	/* Set background color to black */
	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_BKCOLOR(base),
		     SUN8I_MIXER_BLEND_COLOR_BLACK);

	/*
	 * Set fill color of bottom plane to black. Generally not needed
	 * except when VI plane is at bottom (zpos = 0) and enabled.
	 */
	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
		     SUN8I_MIXER_BLEND_PIPE_CTL_FC_EN(0));
	regmap_write(mixer->engine.regs, SUN8I_MIXER_BLEND_ATTR_FCOLOR(base, 0),
		     SUN8I_MIXER_BLEND_COLOR_BLACK);

	plane_cnt = mixer->cfg->vi_num + mixer->cfg->ui_num;
	for (i = 0; i < plane_cnt; i++)
		regmap_write(mixer->engine.regs,
			     SUN8I_MIXER_BLEND_MODE(base, i),
			     SUN8I_MIXER_BLEND_MODE_DEF);

	regmap_update_bits(mixer->engine.regs, SUN8I_MIXER_BLEND_PIPE_CTL(base),
			   SUN8I_MIXER_BLEND_PIPE_CTL_EN_MSK, 0);

	return 0;

err_disable_bus_clk:
	clk_disable_unprepare(mixer->bus_clk);
err_assert_reset:
	reset_control_assert(mixer->reset);
	return ret;
}
コード例 #28
0
ファイル: mt6797-afe-pcm.c プロジェクト: Lyude/linux
static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev)
{
	struct mtk_base_afe *afe;
	struct mt6797_afe_private *afe_priv;
	struct resource *res;
	struct device *dev;
	int i, irq_id, ret;

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

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

	afe_priv = afe->platform_priv;
	afe->dev = &pdev->dev;
	dev = afe->dev;

	/* initial audio related clock */
	ret = mt6797_init_clock(afe);
	if (ret) {
		dev_err(dev, "init clock error\n");
		return ret;
	}

	/* regmap init */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

	afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(afe->base_addr))
		return PTR_ERR(afe->base_addr);

	afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
					    &mt6797_afe_regmap_config);
	if (IS_ERR(afe->regmap))
		return PTR_ERR(afe->regmap);

	/* init memif */
	afe->memif_size = MT6797_MEMIF_NUM;
	afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
				  GFP_KERNEL);
	if (!afe->memif)
		return -ENOMEM;

	for (i = 0; i < afe->memif_size; i++) {
		afe->memif[i].data = &memif_data[i];
		afe->memif[i].irq_usage = -1;
	}

	mutex_init(&afe->irq_alloc_lock);

	/* irq initialize */
	afe->irqs_size = MT6797_IRQ_NUM;
	afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
				 GFP_KERNEL);
	if (!afe->irqs)
		return -ENOMEM;

	for (i = 0; i < afe->irqs_size; i++)
		afe->irqs[i].irq_data = &irq_data[i];

	/* request irq */
	irq_id = platform_get_irq(pdev, 0);
	if (!irq_id) {
		dev_err(dev, "%s no irq found\n", dev->of_node->name);
		return -ENXIO;
	}
	ret = devm_request_irq(dev, irq_id, mt6797_afe_irq_handler,
			       IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
	if (ret) {
		dev_err(dev, "could not request_irq for asys-isr\n");
		return ret;
	}

	/* init sub_dais */
	INIT_LIST_HEAD(&afe->sub_dais);

	for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
		ret = dai_register_cbs[i](afe);
		if (ret) {
			dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
				 i, ret);
			return ret;
		}
	}

	/* init dai_driver and component_driver */
	ret = mtk_afe_combine_sub_dai(afe);
	if (ret) {
		dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
			 ret);
		return ret;
	}

	afe->mtk_afe_hardware = &mt6797_afe_hardware;
	afe->memif_fs = mt6797_memif_fs;
	afe->irq_fs = mt6797_irq_fs;

	afe->runtime_resume = mt6797_afe_runtime_resume;
	afe->runtime_suspend = mt6797_afe_runtime_suspend;

	platform_set_drvdata(pdev, afe);

	pm_runtime_enable(dev);
	if (!pm_runtime_enabled(dev))
		goto err_pm_disable;
	pm_runtime_get_sync(&pdev->dev);

	/* register component */
	ret = devm_snd_soc_register_component(dev, &mt6797_afe_component,
					      NULL, 0);
	if (ret) {
		dev_warn(dev, "err_platform\n");
		goto err_pm_disable;
	}

	ret = devm_snd_soc_register_component(afe->dev,
				     &mt6797_afe_pcm_dai_component,
				     afe->dai_drivers,
				     afe->num_dai_drivers);
	if (ret) {
		dev_warn(dev, "err_dai_component\n");
		goto err_pm_disable;
	}

	return 0;

err_pm_disable:
	pm_runtime_disable(dev);

	return ret;
}
コード例 #29
0
ファイル: fsl_dcu_drm_drv.c プロジェクト: AshishNamdev/linux
static int fsl_dcu_drm_probe(struct platform_device *pdev)
{
	struct fsl_dcu_drm_device *fsl_dev;
	struct drm_device *drm;
	struct device *dev = &pdev->dev;
	struct resource *res;
	void __iomem *base;
	struct drm_driver *driver = &fsl_dcu_drm_driver;
	struct clk *pix_clk_in;
	char pix_clk_name[32];
	const char *pix_clk_in_name;
	const struct of_device_id *id;
	int ret;
	u8 div_ratio_shift = 0;

	fsl_dev = devm_kzalloc(dev, sizeof(*fsl_dev), GFP_KERNEL);
	if (!fsl_dev)
		return -ENOMEM;

	id = of_match_node(fsl_dcu_of_match, pdev->dev.of_node);
	if (!id)
		return -ENODEV;
	fsl_dev->soc = id->data;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	base = devm_ioremap_resource(dev, res);
	if (IS_ERR(base)) {
		ret = PTR_ERR(base);
		return ret;
	}

	fsl_dev->irq = platform_get_irq(pdev, 0);
	if (fsl_dev->irq < 0) {
		dev_err(dev, "failed to get irq\n");
		return fsl_dev->irq;
	}

	fsl_dev->regmap = devm_regmap_init_mmio(dev, base,
			&fsl_dcu_regmap_config);
	if (IS_ERR(fsl_dev->regmap)) {
		dev_err(dev, "regmap init failed\n");
		return PTR_ERR(fsl_dev->regmap);
	}

	fsl_dev->clk = devm_clk_get(dev, "dcu");
	if (IS_ERR(fsl_dev->clk)) {
		dev_err(dev, "failed to get dcu clock\n");
		return PTR_ERR(fsl_dev->clk);
	}
	ret = clk_prepare_enable(fsl_dev->clk);
	if (ret < 0) {
		dev_err(dev, "failed to enable dcu clk\n");
		return ret;
	}

	pix_clk_in = devm_clk_get(dev, "pix");
	if (IS_ERR(pix_clk_in)) {
		/* legancy binding, use dcu clock as pixel clock input */
		pix_clk_in = fsl_dev->clk;
	}

	if (of_property_read_bool(dev->of_node, "big-endian"))
		div_ratio_shift = 24;

	pix_clk_in_name = __clk_get_name(pix_clk_in);
	snprintf(pix_clk_name, sizeof(pix_clk_name), "%s_pix", pix_clk_in_name);
	fsl_dev->pix_clk = clk_register_divider(dev, pix_clk_name,
			pix_clk_in_name, 0, base + DCU_DIV_RATIO,
			div_ratio_shift, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL);
	if (IS_ERR(fsl_dev->pix_clk)) {
		dev_err(dev, "failed to register pix clk\n");
		ret = PTR_ERR(fsl_dev->pix_clk);
		goto disable_clk;
	}

	fsl_dev->tcon = fsl_tcon_init(dev);

	drm = drm_dev_alloc(driver, dev);
	if (IS_ERR(drm)) {
		ret = PTR_ERR(drm);
		goto unregister_pix_clk;
	}

	fsl_dev->dev = dev;
	fsl_dev->drm = drm;
	fsl_dev->np = dev->of_node;
	drm->dev_private = fsl_dev;
	dev_set_drvdata(dev, fsl_dev);

	ret = drm_dev_register(drm, 0);
	if (ret < 0)
		goto unref;

	return 0;

unref:
	drm_dev_unref(drm);
unregister_pix_clk:
	clk_unregister(fsl_dev->pix_clk);
disable_clk:
	clk_disable_unprepare(fsl_dev->clk);
	return ret;
}
コード例 #30
0
ファイル: tegra20_i2s.c プロジェクト: AllenWeb/linux
static __devinit int tegra20_i2s_platform_probe(struct platform_device *pdev)
{
	struct tegra20_i2s *i2s;
	struct resource *mem, *memregion, *dmareq;
	u32 of_dma[2];
	u32 dma_ch;
	void __iomem *regs;
	int ret;

	i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra20_i2s), GFP_KERNEL);
	if (!i2s) {
		dev_err(&pdev->dev, "Can't allocate tegra20_i2s\n");
		ret = -ENOMEM;
		goto err;
	}
	dev_set_drvdata(&pdev->dev, i2s);

	i2s->dai = tegra20_i2s_dai_template;
	i2s->dai.name = dev_name(&pdev->dev);

	i2s->clk_i2s = clk_get(&pdev->dev, NULL);
	if (IS_ERR(i2s->clk_i2s)) {
		dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
		ret = PTR_ERR(i2s->clk_i2s);
		goto err;
	}

	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem) {
		dev_err(&pdev->dev, "No memory resource\n");
		ret = -ENODEV;
		goto err_clk_put;
	}

	dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
	if (!dmareq) {
		if (of_property_read_u32_array(pdev->dev.of_node,
					"nvidia,dma-request-selector",
					of_dma, 2) < 0) {
			dev_err(&pdev->dev, "No DMA resource\n");
			ret = -ENODEV;
			goto err_clk_put;
		}
		dma_ch = of_dma[1];
	} else {
		dma_ch = dmareq->start;
	}

	memregion = devm_request_mem_region(&pdev->dev, mem->start,
					    resource_size(mem), DRV_NAME);
	if (!memregion) {
		dev_err(&pdev->dev, "Memory region already claimed\n");
		ret = -EBUSY;
		goto err_clk_put;
	}

	regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
	if (!regs) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err_clk_put;
	}

	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
					    &tegra20_i2s_regmap_config);
	if (IS_ERR(i2s->regmap)) {
		dev_err(&pdev->dev, "regmap init failed\n");
		ret = PTR_ERR(i2s->regmap);
		goto err_clk_put;
	}

	i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2;
	i2s->capture_dma_data.wrap = 4;
	i2s->capture_dma_data.width = 32;
	i2s->capture_dma_data.req_sel = dma_ch;

	i2s->playback_dma_data.addr = mem->start + TEGRA20_I2S_FIFO1;
	i2s->playback_dma_data.wrap = 4;
	i2s->playback_dma_data.width = 32;
	i2s->playback_dma_data.req_sel = dma_ch;

	i2s->reg_ctrl = TEGRA20_I2S_CTRL_FIFO_FORMAT_PACKED;

	pm_runtime_enable(&pdev->dev);
	if (!pm_runtime_enabled(&pdev->dev)) {
		ret = tegra20_i2s_runtime_resume(&pdev->dev);
		if (ret)
			goto err_pm_disable;
	}

	ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
	if (ret) {
		dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
		ret = -ENOMEM;
		goto err_suspend;
	}

	ret = tegra_pcm_platform_register(&pdev->dev);
	if (ret) {
		dev_err(&pdev->dev, "Could not register PCM: %d\n", ret);
		goto err_unregister_dai;
	}

	return 0;

err_unregister_dai:
	snd_soc_unregister_dai(&pdev->dev);
err_suspend:
	if (!pm_runtime_status_suspended(&pdev->dev))
		tegra20_i2s_runtime_suspend(&pdev->dev);
err_pm_disable:
	pm_runtime_disable(&pdev->dev);
err_clk_put:
	clk_put(i2s->clk_i2s);
err:
	return ret;
}