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); } }
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; }
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); }
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); }
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; }
/** * 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; }
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; }
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; }
/** * 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); }
/** * 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; }
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); }
/** * 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; }
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; }
/** * 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; }
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; }
/** * 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; }
/** * 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; }
/** * 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; }
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; }
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); }
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; }