コード例 #1
0
ファイル: power_clk.c プロジェクト: FrozenCow/FIRE-ICE
void quadd_power_clk_stop(void)
{
	struct power_clk_source *s;

	if (power_ctx.quadd_ctx->param.power_rate_freq == 0)
		return;

	if (power_ctx.period > 0)
		del_timer_sync(&power_ctx.timer);

	s = &power_ctx.gpu;
	if (atomic_cmpxchg(&s->active, 1, 0)) {
#ifdef CONFIG_COMMON_CLK
		if (s->clkp)
			clk_notifier_unregister(s->clkp, &s->nb);
#endif
	}

	s = &power_ctx.emc;
	if (atomic_cmpxchg(&s->active, 1, 0)) {
#ifdef CONFIG_COMMON_CLK
		if (s->clkp)
			clk_notifier_unregister(s->clkp, &s->nb);
#endif
	}

	s = &power_ctx.cpu;
	if (atomic_cmpxchg(&s->active, 1, 0)) {
		pr_info("power_clk: stop\n");
		unregister_cpu_notifier(&s->nb);
	}
}
コード例 #2
0
ファイル: apcs-msm8916.c プロジェクト: AlexShiLucky/linux
static int qcom_apcs_msm8916_clk_remove(struct platform_device *pdev)
{
	struct clk_regmap_mux_div *a53cc = platform_get_drvdata(pdev);

	clk_notifier_unregister(a53cc->pclk, &a53cc->clk_nb);

	return 0;
}
コード例 #3
0
struct clk *meson_clk_register_cpu(const struct clk_conf *clk_conf,
				   void __iomem *reg_base,
				   spinlock_t *lock)
{
	struct clk *clk;
	struct clk *pclk;
	struct meson_clk_cpu *clk_cpu;
	struct clk_init_data init;
	int ret;

	clk_cpu = kzalloc(sizeof(*clk_cpu), GFP_KERNEL);
	if (!clk_cpu)
		return ERR_PTR(-ENOMEM);

	clk_cpu->base = reg_base;
	clk_cpu->reg_off = clk_conf->reg_off;
	clk_cpu->div_table = clk_conf->conf.div_table;
	clk_cpu->clk_nb.notifier_call = meson_clk_cpu_notifier_cb;

	init.name = clk_conf->clk_name;
	init.ops = &meson_clk_cpu_ops;
	init.flags = clk_conf->flags | CLK_GET_RATE_NOCACHE;
	init.flags |= CLK_SET_RATE_PARENT;
	init.parent_names = clk_conf->clks_parent;
	init.num_parents = 1;

	clk_cpu->hw.init = &init;

	pclk = __clk_lookup(clk_conf->clks_parent[0]);
	if (!pclk) {
		pr_err("%s: could not lookup parent clock %s\n",
				__func__, clk_conf->clks_parent[0]);
		ret = -EINVAL;
		goto free_clk;
	}

	ret = clk_notifier_register(pclk, &clk_cpu->clk_nb);
	if (ret) {
		pr_err("%s: failed to register clock notifier for %s\n",
				__func__, clk_conf->clk_name);
		goto free_clk;
	}

	clk = clk_register(NULL, &clk_cpu->hw);
	if (IS_ERR(clk)) {
		ret = PTR_ERR(clk);
		goto unregister_clk_nb;
	}

	return clk;

unregister_clk_nb:
	clk_notifier_unregister(pclk, &clk_cpu->clk_nb);
free_clk:
	kfree(clk_cpu);

	return ERR_PTR(ret);
}
コード例 #4
0
ファイル: owl_gpu_clk.c プロジェクト: xapp-le/kernel
void owl_gpu_clk_notifier_unregister(struct notifier_block *notifier)
{
	struct clk *clk = NULL;
	int ret = -1;
	
	clk = clk_get(NULL, "GPU3D_CORECLK");
	ret = clk_notifier_unregister(clk, notifier);
	
	clk = clk_get(NULL, "GPU3D_SYSCLK");
	ret = clk_notifier_unregister(clk, notifier);
	
	clk = clk_get(NULL, "GPU3D_HYDCLK");
	ret = clk_notifier_unregister(clk, notifier);
	
	clk = clk_get(NULL, "GPU3D_NIC_MEMCLK");
	ret = clk_notifier_unregister(clk, notifier);

}
コード例 #5
0
ファイル: timer-sun5i.c プロジェクト: 0x000000FF/edison-linux
static int __init sun5i_setup_clocksource(struct device_node *node,
					  void __iomem *base,
					  struct clk *clk, int irq)
{
	struct sun5i_timer_clksrc *cs;
	unsigned long rate;
	int ret;

	cs = kzalloc(sizeof(*cs), GFP_KERNEL);
	if (!cs)
		return -ENOMEM;

	ret = clk_prepare_enable(clk);
	if (ret) {
		pr_err("Couldn't enable parent clock\n");
		goto err_free;
	}

	rate = clk_get_rate(clk);

	cs->timer.base = base;
	cs->timer.clk = clk;
	cs->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clksrc;
	cs->timer.clk_rate_cb.next = NULL;

	ret = clk_notifier_register(clk, &cs->timer.clk_rate_cb);
	if (ret) {
		pr_err("Unable to register clock notifier.\n");
		goto err_disable_clk;
	}

	writel(~0, base + TIMER_INTVAL_LO_REG(1));
	writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
	       base + TIMER_CTL_REG(1));

	cs->clksrc.name = node->name;
	cs->clksrc.rating = 340;
	cs->clksrc.read = sun5i_clksrc_read;
	cs->clksrc.mask = CLOCKSOURCE_MASK(32);
	cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;

	ret = clocksource_register_hz(&cs->clksrc, rate);
	if (ret) {
		pr_err("Couldn't register clock source.\n");
		goto err_remove_notifier;
	}

	return 0;

err_remove_notifier:
	clk_notifier_unregister(clk, &cs->timer.clk_rate_cb);
err_disable_clk:
	clk_disable_unprepare(clk);
err_free:
	kfree(cs);
	return ret;
}
コード例 #6
0
ファイル: i2c-cadence.c プロジェクト: LCameron/linux-xlnx
/**
 * cdns_i2c_remove - Unregister the device after releasing the resources
 * @pdev:	Handle to the platform device structure
 *
 * This function frees all the resources allocated to the device.
 *
 * Return: 0 always
 */
static int cdns_i2c_remove(struct platform_device *pdev)
{
	struct cdns_i2c *id = platform_get_drvdata(pdev);

	i2c_del_adapter(&id->adap);
	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
	clk_disable_unprepare(id->clk);

	return 0;
}
コード例 #7
0
static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
{
	dev_t devno;
	bool ret;
	DSP_STATUS dsp_status = DSP_SOK;
	HANDLE hDrvObject = NULL;

	dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_FAILED(dsp_status))
		goto func_cont;

#ifdef CONFIG_BRIDGE_DVFS
	if (clk_notifier_unregister(clk_handle, &iva_clk_notifier))
		pr_err("%s: clk_notifier_unregister failed for iva2_ck\n",
								__func__);
#endif /* #ifdef CONFIG_BRIDGE_DVFS */

	if (driverContext) {
		/* Put the DSP in reset state */
		ret = DSP_Deinit(driverContext);
		driverContext = 0;
		DBC_Assert(ret == true);
	}

#ifdef CONFIG_BRIDGE_DVFS
	clk_put(clk_handle);
	clk_handle = NULL;
#endif

func_cont:

#ifdef CONFIG_PM
	/* The suspend wait queue should not have anything waiting on it
	   since remove won't be called while the file is open */
	DBC_Assert(!waitqueue_active(&bridge_suspend_data.suspend_wq));
#endif
	MEM_ExtPhysPoolRelease();

	SERVICES_Exit();
	GT_exit();

	/* Remove driver sysfs entries */
	bridge_destroy_sysfs();

	devno = MKDEV(driver_major, 0);
	cdev_del(&bridge_cdev);
	unregister_chrdev_region(devno, 1);
	if (bridge_class) {
		/* remove the device from sysfs */
		device_destroy(bridge_class, MKDEV(driver_major, 0));
		class_destroy(bridge_class);

	}
	return 0;
}
コード例 #8
0
ファイル: clk-xlnx-clock-wizard.c プロジェクト: 020gzh/linux
static int clk_wzrd_remove(struct platform_device *pdev)
{
	int i;
	struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev);

	of_clk_del_provider(pdev->dev.of_node);

	for (i = 0; i < WZRD_NUM_OUTPUTS; i++)
		clk_unregister(clk_wzrd->clkout[i]);
	for (i = 0; i < wzrd_clk_int_max; i++)
		clk_unregister(clk_wzrd->clks_internal[i]);

	if (clk_wzrd->speed_grade) {
		clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb);
		clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb);
	}

	clk_disable_unprepare(clk_wzrd->axi_clk);

	return 0;
}
コード例 #9
0
ファイル: clock_cooling.c プロジェクト: 020gzh/linux
/**
 * clock_cooling_unregister - function to remove clock cooling device.
 * @cdev: thermal cooling device pointer.
 *
 * This interface function unregisters the "thermal-clock-%x" cooling device.
 */
void clock_cooling_unregister(struct thermal_cooling_device *cdev)
{
	struct clock_cooling_device *ccdev;

	if (!cdev)
		return;

	ccdev = cdev->devdata;

	clk_notifier_unregister(ccdev->clk, &ccdev->clk_rate_change_nb);
	dev_pm_opp_free_cpufreq_table(ccdev->dev, &ccdev->freq_table);

	thermal_cooling_device_unregister(ccdev->cdev);
	release_idr(ccdev->id);
}
コード例 #10
0
/**
 * cdns_i2c_remove - Unregister the device after releasing the resources
 * @pdev:	Handle to the platform device structure
 *
 * This function frees all the resources allocated to the device.
 *
 * Return: 0 always
 */
static int cdns_i2c_remove(struct platform_device *pdev)
{
	struct cdns_i2c *id = platform_get_drvdata(pdev);

	pm_runtime_disable(&pdev->dev);
	pm_runtime_set_suspended(&pdev->dev);
	pm_runtime_dont_use_autosuspend(&pdev->dev);

	i2c_del_adapter(&id->adap);
	clk_notifier_unregister(id->clk, &id->clk_rate_change_nb);
	clk_disable_unprepare(id->clk);
	pm_runtime_disable(&pdev->dev);

	return 0;
}
コード例 #11
0
static int sdhci_zynq_remove(struct platform_device *pdev)
{
	struct sdhci_host *host = platform_get_drvdata(pdev);
	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
	struct xsdhcips *xsdhcips = pltfm_host->priv;

	clk_notifier_unregister(xsdhcips->devclk,
			&xsdhcips->clk_rate_change_nb);
	clk_disable_unprepare(xsdhcips->devclk);
	clk_disable_unprepare(xsdhcips->aperclk);
	clk_put(xsdhcips->devclk);
	clk_put(xsdhcips->aperclk);
	kfree(xsdhcips);

	return sdhci_pltfm_unregister(pdev);
}
コード例 #12
0
ファイル: xilinx_uartps.c プロジェクト: mikemvk/linux-at91
/**
 * cdns_uart_remove - called when the platform driver is unregistered
 * @pdev: Pointer to the platform device structure
 *
 * Return: 0 on success, negative errno otherwise
 */
static int cdns_uart_remove(struct platform_device *pdev)
{
    struct uart_port *port = platform_get_drvdata(pdev);
    struct cdns_uart *cdns_uart_data = port->private_data;
    int rc;

    /* Remove the cdns_uart port from the serial core */
#ifdef CONFIG_COMMON_CLK
    clk_notifier_unregister(cdns_uart_data->uartclk,
                            &cdns_uart_data->clk_rate_change_nb);
#endif
    rc = uart_remove_one_port(&cdns_uart_uart_driver, port);
    port->mapbase = 0;
    clk_disable_unprepare(cdns_uart_data->uartclk);
    clk_disable_unprepare(cdns_uart_data->pclk);
    return rc;
}
コード例 #13
0
ファイル: omap_hsi.c プロジェクト: egonalter/R-Link_kernel
static int hsi_clk_notifier_unregister(struct clk *clk,
						struct notifier_block *nb)
{
#ifdef OMAP_HSI_EXAMPLE_PWR_CODE
	struct hsi_internal_clk *hsi_clk;

	if (!clk || !nb)
		return -EINVAL;

	hsi_clk = container_of(clk, struct hsi_internal_clk, clk);
	hsi_clk->drv_nb = NULL;

	return clk_notifier_unregister(hsi_clk->childs[1], &hsi_clk->nb);

#endif
	pr_debug(KERN_DEBUG "%s called", __func__);
	return 0;
}
コード例 #14
0
ファイル: xilinx_uartps.c プロジェクト: Analias/SNOWLeo-SDR-1
/**
 * xuartps_remove - called when the platform driver is unregistered
 * @pdev: Pointer to the platform device structure
 *
 * Returns 0 on success, negative error otherwise
 */
static int __devexit xuartps_remove(struct platform_device *pdev)
{
	struct uart_port *port = dev_get_drvdata(&pdev->dev);
	int rc = 0;
	struct xuartps *xuartps;

	/* Remove the xuartps port from the serial core */
	if (port) {
		xuartps = port->private_data;
		clk_notifier_unregister(xuartps->devclk,
				&xuartps->clk_rate_change_nb);
		xuartps->port = NULL;
		port->private_data = NULL;
		rc = uart_remove_one_port(&xuartps_uart_driver, port);
		dev_set_drvdata(&pdev->dev, NULL);
		port->mapbase = 0;
		clk_disable_unprepare(xuartps->devclk);
		clk_put(xuartps->devclk);
		clk_disable_unprepare(xuartps->aperclk);
		clk_put(xuartps->aperclk);
		kfree(xuartps);
	}
	return rc;
}
コード例 #15
0
ファイル: timer-sun5i.c プロジェクト: 0x000000FF/edison-linux
static int __init sun5i_setup_clockevent(struct device_node *node, void __iomem *base,
					 struct clk *clk, int irq)
{
	struct sun5i_timer_clkevt *ce;
	unsigned long rate;
	int ret;
	u32 val;

	ce = kzalloc(sizeof(*ce), GFP_KERNEL);
	if (!ce)
		return -ENOMEM;

	ret = clk_prepare_enable(clk);
	if (ret) {
		pr_err("Couldn't enable parent clock\n");
		goto err_free;
	}

	rate = clk_get_rate(clk);

	ce->timer.base = base;
	ce->timer.ticks_per_jiffy = DIV_ROUND_UP(rate, HZ);
	ce->timer.clk = clk;
	ce->timer.clk_rate_cb.notifier_call = sun5i_rate_cb_clkevt;
	ce->timer.clk_rate_cb.next = NULL;

	ret = clk_notifier_register(clk, &ce->timer.clk_rate_cb);
	if (ret) {
		pr_err("Unable to register clock notifier.\n");
		goto err_disable_clk;
	}

	ce->clkevt.name = node->name;
	ce->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
	ce->clkevt.set_next_event = sun5i_clkevt_next_event;
	ce->clkevt.set_mode = sun5i_clkevt_mode;
	ce->clkevt.rating = 340;
	ce->clkevt.irq = irq;
	ce->clkevt.cpumask = cpu_possible_mask;

	/* Enable timer0 interrupt */
	val = readl(base + TIMER_IRQ_EN_REG);
	writel(val | TIMER_IRQ_EN(0), base + TIMER_IRQ_EN_REG);

	clockevents_config_and_register(&ce->clkevt, rate,
					TIMER_SYNC_TICKS, 0xffffffff);

	ret = request_irq(irq, sun5i_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
			  "sun5i_timer0", ce);
	if (ret) {
		pr_err("Unable to register interrupt\n");
		goto err_remove_notifier;
	}

	return 0;

err_remove_notifier:
	clk_notifier_unregister(clk, &ce->timer.clk_rate_cb);
err_disable_clk:
	clk_disable_unprepare(clk);
err_free:
	kfree(ce);
	return ret;
}
コード例 #16
0
ファイル: xilinx_uartps.c プロジェクト: Analias/SNOWLeo-SDR-1
/**
 * xuartps_probe - Platform driver probe
 * @pdev: Pointer to the platform device structure
 *
 * Returns 0 on success, negative error otherwise
 */
static int __devinit xuartps_probe(struct platform_device *pdev)
{
	int rc;
	struct uart_port *port;
	struct resource *res, *res2;
	unsigned int clk = 0;
	int ret = 0;
	int id = 0;

	struct xuartps *xuartps;

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

	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res2)
		return -ENODEV;

	/* Look for a serialN alias */
	id = of_alias_get_id(pdev->dev.of_node, "serial");
	if (id < 0) {
		dev_warn(&pdev->dev, "failed to get alias id, errno %d\n", id);
		id = 0;
	}

	port = xuartps_get_port(id);
	xuartps = kmalloc(sizeof(*xuartps), GFP_KERNEL);
	if (res2->start == 59)
		xuartps->uartnum = 0;
	else
		xuartps->uartnum = 1;

	if (xuartps->uartnum)
		xuartps->aperclk = clk_get_sys("UART1_APER", NULL);
	else
		xuartps->aperclk = clk_get_sys("UART0_APER", NULL);
	if (IS_ERR(xuartps->aperclk)) {
		dev_err(&pdev->dev, "APER clock not found.\n");
		ret = PTR_ERR(xuartps->aperclk);
		goto err_out_free;
	}
	if (xuartps->uartnum)
		xuartps->devclk = clk_get_sys("UART1", NULL);
	else
		xuartps->devclk = clk_get_sys("UART0", NULL);
	if (IS_ERR(xuartps->devclk)) {
		dev_err(&pdev->dev, "Device clock not found.\n");
		ret = PTR_ERR(xuartps->devclk);
		goto err_out_clk_put_aper;
	}

	ret = clk_prepare_enable(xuartps->aperclk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable APER clock.\n");
		goto err_out_clk_put;
	}
	ret = clk_prepare_enable(xuartps->devclk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable device clock.\n");
		goto err_out_clk_dis_aper;
	}

	clk = (unsigned int)clk_get_rate(xuartps->devclk);
	xuartps->clk_rate_change_nb.notifier_call = xuartps_clk_notifier_cb;
	xuartps->clk_rate_change_nb.next = NULL;
	if (clk_notifier_register(xuartps->devclk,
				&xuartps->clk_rate_change_nb))
		dev_warn(&pdev->dev, "Unable to register clock notifier.\n");

	/* Initialize the port structure */
	if (!port) {
		dev_err(&pdev->dev, "Cannot get uart_port structure\n");
		ret = -ENODEV;
		goto err_out_clk_dis;
	} else {
		/* Register the port.
		 * This function also registers this device with the tty layer
		 * and triggers invocation of the config_port() entry point.
		 */
		port->mapbase = res->start;
		port->irq = res2->start;
		port->dev = &pdev->dev;
		port->uartclk = clk;
		port->private_data = xuartps;
		xuartps->port = port;
		dev_set_drvdata(&pdev->dev, port);
		rc = uart_add_one_port(&xuartps_uart_driver, port);
		if (rc) {
			dev_err(&pdev->dev,
				"uart_add_one_port() failed; err=%i\n", rc);
			dev_set_drvdata(&pdev->dev, NULL);
			port->private_data = NULL;
			xuartps->port = NULL;
			ret = rc;
			goto err_out_clk_dis;
		}
		return 0;
	}
err_out_clk_dis:
	clk_notifier_unregister(xuartps->devclk, &xuartps->clk_rate_change_nb);
	clk_disable_unprepare(xuartps->devclk);
err_out_clk_dis_aper:
	clk_disable_unprepare(xuartps->aperclk);
err_out_clk_put:
	clk_put(xuartps->devclk);
err_out_clk_put_aper:
	clk_put(xuartps->aperclk);
err_out_free:
	kfree(xuartps);

	return ret;
}
コード例 #17
0
ファイル: xilinx_uartps.c プロジェクト: mikemvk/linux-at91
/**
 * cdns_uart_probe - Platform driver probe
 * @pdev: Pointer to the platform device structure
 *
 * Return: 0 on success, negative errno otherwise
 */
static int cdns_uart_probe(struct platform_device *pdev)
{
    int rc, id;
    struct uart_port *port;
    struct resource *res, *res2;
    struct cdns_uart *cdns_uart_data;

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

    cdns_uart_data->pclk = devm_clk_get(&pdev->dev, "pclk");
    if (IS_ERR(cdns_uart_data->pclk)) {
        cdns_uart_data->pclk = devm_clk_get(&pdev->dev, "aper_clk");
        if (!IS_ERR(cdns_uart_data->pclk))
            dev_err(&pdev->dev, "clock name 'aper_clk' is deprecated.\n");
    }
    if (IS_ERR(cdns_uart_data->pclk)) {
        dev_err(&pdev->dev, "pclk clock not found.\n");
        return PTR_ERR(cdns_uart_data->pclk);
    }

    cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "uart_clk");
    if (IS_ERR(cdns_uart_data->uartclk)) {
        cdns_uart_data->uartclk = devm_clk_get(&pdev->dev, "ref_clk");
        if (!IS_ERR(cdns_uart_data->uartclk))
            dev_err(&pdev->dev, "clock name 'ref_clk' is deprecated.\n");
    }
    if (IS_ERR(cdns_uart_data->uartclk)) {
        dev_err(&pdev->dev, "uart_clk clock not found.\n");
        return PTR_ERR(cdns_uart_data->uartclk);
    }

    rc = clk_prepare_enable(cdns_uart_data->pclk);
    if (rc) {
        dev_err(&pdev->dev, "Unable to enable pclk clock.\n");
        return rc;
    }
    rc = clk_prepare_enable(cdns_uart_data->uartclk);
    if (rc) {
        dev_err(&pdev->dev, "Unable to enable device clock.\n");
        goto err_out_clk_dis_pclk;
    }

    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!res) {
        rc = -ENODEV;
        goto err_out_clk_disable;
    }

    res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (!res2) {
        rc = -ENODEV;
        goto err_out_clk_disable;
    }

#ifdef CONFIG_COMMON_CLK
    cdns_uart_data->clk_rate_change_nb.notifier_call =
        cdns_uart_clk_notifier_cb;
    if (clk_notifier_register(cdns_uart_data->uartclk,
                              &cdns_uart_data->clk_rate_change_nb))
        dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
#endif
    /* Look for a serialN alias */
    id = of_alias_get_id(pdev->dev.of_node, "serial");
    if (id < 0)
        id = 0;

    /* Initialize the port structure */
    port = cdns_uart_get_port(id);

    if (!port) {
        dev_err(&pdev->dev, "Cannot get uart_port structure\n");
        rc = -ENODEV;
        goto err_out_notif_unreg;
    } else {
        /* Register the port.
         * This function also registers this device with the tty layer
         * and triggers invocation of the config_port() entry point.
         */
        port->mapbase = res->start;
        port->irq = res2->start;
        port->dev = &pdev->dev;
        port->uartclk = clk_get_rate(cdns_uart_data->uartclk);
        port->private_data = cdns_uart_data;
        cdns_uart_data->port = port;
        platform_set_drvdata(pdev, port);
        rc = uart_add_one_port(&cdns_uart_uart_driver, port);
        if (rc) {
            dev_err(&pdev->dev,
                    "uart_add_one_port() failed; err=%i\n", rc);
            goto err_out_notif_unreg;
        }
        return 0;
    }

err_out_notif_unreg:
#ifdef CONFIG_COMMON_CLK
    clk_notifier_unregister(cdns_uart_data->uartclk,
                            &cdns_uart_data->clk_rate_change_nb);
#endif
err_out_clk_disable:
    clk_disable_unprepare(cdns_uart_data->uartclk);
err_out_clk_dis_pclk:
    clk_disable_unprepare(cdns_uart_data->pclk);

    return rc;
}
コード例 #18
0
ファイル: xilinx_uartps.c プロジェクト: 7799/linux
/**
 * xuartps_probe - Platform driver probe
 * @pdev: Pointer to the platform device structure
 *
 * Returns 0 on success, negative error otherwise
 **/
static int xuartps_probe(struct platform_device *pdev)
{
	int rc;
	struct uart_port *port;
	struct resource *res, *res2;
	struct xuartps *xuartps_data;

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

	xuartps_data->aperclk = devm_clk_get(&pdev->dev, "aper_clk");
	if (IS_ERR(xuartps_data->aperclk)) {
		dev_err(&pdev->dev, "aper_clk clock not found.\n");
		return PTR_ERR(xuartps_data->aperclk);
	}
	xuartps_data->refclk = devm_clk_get(&pdev->dev, "ref_clk");
	if (IS_ERR(xuartps_data->refclk)) {
		dev_err(&pdev->dev, "ref_clk clock not found.\n");
		return PTR_ERR(xuartps_data->refclk);
	}

	rc = clk_prepare_enable(xuartps_data->aperclk);
	if (rc) {
		dev_err(&pdev->dev, "Unable to enable APER clock.\n");
		return rc;
	}
	rc = clk_prepare_enable(xuartps_data->refclk);
	if (rc) {
		dev_err(&pdev->dev, "Unable to enable device clock.\n");
		goto err_out_clk_dis_aper;
	}

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		rc = -ENODEV;
		goto err_out_clk_disable;
	}

	res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res2) {
		rc = -ENODEV;
		goto err_out_clk_disable;
	}

#ifdef CONFIG_COMMON_CLK
	xuartps_data->clk_rate_change_nb.notifier_call =
			xuartps_clk_notifier_cb;
	if (clk_notifier_register(xuartps_data->refclk,
				&xuartps_data->clk_rate_change_nb))
		dev_warn(&pdev->dev, "Unable to register clock notifier.\n");
#endif

	/* Initialize the port structure */
	port = xuartps_get_port();

	if (!port) {
		dev_err(&pdev->dev, "Cannot get uart_port structure\n");
		rc = -ENODEV;
		goto err_out_notif_unreg;
	} else {
		/* Register the port.
		 * This function also registers this device with the tty layer
		 * and triggers invocation of the config_port() entry point.
		 */
		port->mapbase = res->start;
		port->irq = res2->start;
		port->dev = &pdev->dev;
		port->uartclk = clk_get_rate(xuartps_data->refclk);
		port->private_data = xuartps_data;
		xuartps_data->port = port;
		platform_set_drvdata(pdev, port);
		rc = uart_add_one_port(&xuartps_uart_driver, port);
		if (rc) {
			dev_err(&pdev->dev,
				"uart_add_one_port() failed; err=%i\n", rc);
			goto err_out_notif_unreg;
		}
		return 0;
	}

err_out_notif_unreg:
#ifdef CONFIG_COMMON_CLK
	clk_notifier_unregister(xuartps_data->refclk,
			&xuartps_data->clk_rate_change_nb);
#endif
err_out_clk_disable:
	clk_disable_unprepare(xuartps_data->refclk);
err_out_clk_dis_aper:
	clk_disable_unprepare(xuartps_data->aperclk);

	return rc;
}
コード例 #19
0
ファイル: apcs-msm8916.c プロジェクト: AlexShiLucky/linux
static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct device *parent = dev->parent;
	struct clk_regmap_mux_div *a53cc;
	struct regmap *regmap;
	struct clk_init_data init = { };
	int ret = -ENODEV;

	regmap = dev_get_regmap(parent, NULL);
	if (!regmap) {
		dev_err(dev, "failed to get regmap: %d\n", ret);
		return ret;
	}

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

	init.name = "a53mux";
	init.parent_names = gpll0_a53cc;
	init.num_parents = ARRAY_SIZE(gpll0_a53cc);
	init.ops = &clk_regmap_mux_div_ops;
	init.flags = CLK_SET_RATE_PARENT;

	a53cc->clkr.hw.init = &init;
	a53cc->clkr.regmap = regmap;
	a53cc->reg_offset = 0x50;
	a53cc->hid_width = 5;
	a53cc->hid_shift = 0;
	a53cc->src_width = 3;
	a53cc->src_shift = 8;
	a53cc->parent_map = gpll0_a53cc_map;

	a53cc->pclk = devm_clk_get(parent, NULL);
	if (IS_ERR(a53cc->pclk)) {
		ret = PTR_ERR(a53cc->pclk);
		dev_err(dev, "failed to get clk: %d\n", ret);
		return ret;
	}

	a53cc->clk_nb.notifier_call = a53cc_notifier_cb;
	ret = clk_notifier_register(a53cc->pclk, &a53cc->clk_nb);
	if (ret) {
		dev_err(dev, "failed to register clock notifier: %d\n", ret);
		return ret;
	}

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

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

	platform_set_drvdata(pdev, a53cc);

	return 0;

err:
	clk_notifier_unregister(a53cc->pclk, &a53cc->clk_nb);
	return ret;
}
コード例 #20
0
ファイル: clk-cpu.c プロジェクト: 513855417/linux
struct clk *rockchip_clk_register_cpuclk(const char *name,
			const char *const *parent_names, u8 num_parents,
			const struct rockchip_cpuclk_reg_data *reg_data,
			const struct rockchip_cpuclk_rate_table *rates,
			int nrates, void __iomem *reg_base, spinlock_t *lock)
{
	struct rockchip_cpuclk *cpuclk;
	struct clk_init_data init;
	struct clk *clk, *cclk;
	int ret;

	if (num_parents < 2) {
		pr_err("%s: needs at least two parent clocks\n", __func__);
		return ERR_PTR(-EINVAL);
	}

	cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL);
	if (!cpuclk)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.parent_names = &parent_names[reg_data->mux_core_main];
	init.num_parents = 1;
	init.ops = &rockchip_cpuclk_ops;

	/* only allow rate changes when we have a rate table */
	init.flags = (nrates > 0) ? CLK_SET_RATE_PARENT : 0;

	/* disallow automatic parent changes by ccf */
	init.flags |= CLK_SET_RATE_NO_REPARENT;

	init.flags |= CLK_GET_RATE_NOCACHE;

	cpuclk->reg_base = reg_base;
	cpuclk->lock = lock;
	cpuclk->reg_data = reg_data;
	cpuclk->clk_nb.notifier_call = rockchip_cpuclk_notifier_cb;
	cpuclk->hw.init = &init;

	cpuclk->alt_parent = __clk_lookup(parent_names[reg_data->mux_core_alt]);
	if (!cpuclk->alt_parent) {
		pr_err("%s: could not lookup alternate parent: (%d)\n",
		       __func__, reg_data->mux_core_alt);
		ret = -EINVAL;
		goto free_cpuclk;
	}

	ret = clk_prepare_enable(cpuclk->alt_parent);
	if (ret) {
		pr_err("%s: could not enable alternate parent\n",
		       __func__);
		goto free_cpuclk;
	}

	clk = __clk_lookup(parent_names[reg_data->mux_core_main]);
	if (!clk) {
		pr_err("%s: could not lookup parent clock: (%d) %s\n",
		       __func__, reg_data->mux_core_main,
		       parent_names[reg_data->mux_core_main]);
		ret = -EINVAL;
		goto free_alt_parent;
	}

	ret = clk_notifier_register(clk, &cpuclk->clk_nb);
	if (ret) {
		pr_err("%s: failed to register clock notifier for %s\n",
				__func__, name);
		goto free_alt_parent;
	}

	if (nrates > 0) {
		cpuclk->rate_count = nrates;
		cpuclk->rate_table = kmemdup(rates,
					     sizeof(*rates) * nrates,
					     GFP_KERNEL);
		if (!cpuclk->rate_table) {
			pr_err("%s: could not allocate memory for cpuclk rates\n",
			       __func__);
			ret = -ENOMEM;
			goto unregister_notifier;
		}
	}

	cclk = clk_register(NULL, &cpuclk->hw);
	if (IS_ERR(cclk)) {
		pr_err("%s: could not register cpuclk %s\n", __func__,	name);
		ret = PTR_ERR(cclk);
		goto free_rate_table;
	}

	return cclk;

free_rate_table:
	kfree(cpuclk->rate_table);
unregister_notifier:
	clk_notifier_unregister(clk, &cpuclk->clk_nb);
free_alt_parent:
	clk_disable_unprepare(cpuclk->alt_parent);
free_cpuclk:
	kfree(cpuclk);
	return ERR_PTR(ret);
}
コード例 #21
0
static int sdhci_zynq_probe(struct platform_device *pdev)
{
	int ret;
	int irq = platform_get_irq(pdev, 0);
	const void *prop;
	struct device_node *np = pdev->dev.of_node;
	struct sdhci_host *host;
	struct sdhci_pltfm_host *pltfm_host;
	struct xsdhcips *xsdhcips;

	xsdhcips = kmalloc(sizeof(*xsdhcips), GFP_KERNEL);
	if (!xsdhcips) {
		dev_err(&pdev->dev, "unable to allocate memory\n");
		return -ENOMEM;
	}

	if (irq == 56)
		xsdhcips->aperclk = clk_get_sys("SDIO0_APER", NULL);
	else
		xsdhcips->aperclk = clk_get_sys("SDIO1_APER", NULL);

	if (IS_ERR(xsdhcips->aperclk)) {
		dev_err(&pdev->dev, "APER clock not found.\n");
		ret = PTR_ERR(xsdhcips->aperclk);
		goto err_free;
	}

	if (irq == 56)
		xsdhcips->devclk = clk_get_sys("SDIO0", NULL);
	else
		xsdhcips->devclk = clk_get_sys("SDIO1", NULL);

	if (IS_ERR(xsdhcips->devclk)) {
		dev_err(&pdev->dev, "Device clock not found.\n");
		ret = PTR_ERR(xsdhcips->devclk);
		goto clk_put_aper;
	}

	ret = clk_prepare_enable(xsdhcips->aperclk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable APER clock.\n");
		goto clk_put;
	}

	ret = clk_prepare_enable(xsdhcips->devclk);
	if (ret) {
		dev_err(&pdev->dev, "Unable to enable device clock.\n");
		goto clk_dis_aper;
	}

	xsdhcips->clk_rate_change_nb.notifier_call = xsdhcips_clk_notifier_cb;
	xsdhcips->clk_rate_change_nb.next = NULL;
	if (clk_notifier_register(xsdhcips->devclk,
				&xsdhcips->clk_rate_change_nb))
		dev_warn(&pdev->dev, "Unable to register clock notifier.\n");


	ret = sdhci_pltfm_register(pdev, &sdhci_zynq_pdata);
	if (ret) {
		dev_err(&pdev->dev, "Platform registration failed\n");
		goto clk_notif_unreg;
	}

	host = platform_get_drvdata(pdev);
	pltfm_host = sdhci_priv(host);
	pltfm_host->priv = xsdhcips;

	prop = of_get_property(np, "xlnx,has-cd", NULL);
	if (prop == NULL || (!(u32) be32_to_cpup(prop)))
		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;

	return 0;

clk_notif_unreg:
	clk_notifier_unregister(xsdhcips->devclk,
			&xsdhcips->clk_rate_change_nb);
	clk_disable_unprepare(xsdhcips->devclk);
clk_dis_aper:
	clk_disable_unprepare(xsdhcips->aperclk);
clk_put:
	clk_put(xsdhcips->devclk);
clk_put_aper:
	clk_put(xsdhcips->aperclk);
err_free:
	kfree(xsdhcips);

	return ret;
}