/* * Fill a struct uart_port for a given device node */ static int of_platform_serial_setup(struct platform_device *ofdev, int type, struct uart_port *port, struct of_serial_info *info) { struct resource resource; struct device_node *np = ofdev->dev.of_node; u32 clk, spd, prop; int ret; memset(port, 0, sizeof *port); if (of_property_read_u32(np, "clock-frequency", &clk)) { /* Get clk rate through clk driver if present */ info->clk = devm_clk_get(&ofdev->dev, NULL); if (IS_ERR(info->clk)) { dev_warn(&ofdev->dev, "clk or clock-frequency not defined\n"); return PTR_ERR(info->clk); } ret = clk_prepare_enable(info->clk); if (ret < 0) return ret; clk = clk_get_rate(info->clk); } /* If current-speed was set, then try not to change it. */ if (of_property_read_u32(np, "current-speed", &spd) == 0) port->custom_divisor = clk / (16 * spd); ret = of_address_to_resource(np, 0, &resource); if (ret) { dev_warn(&ofdev->dev, "invalid address\n"); goto out; } spin_lock_init(&port->lock); port->mapbase = resource.start; port->mapsize = resource_size(&resource); /* Check for shifted address mapping */ if (of_property_read_u32(np, "reg-offset", &prop) == 0) port->mapbase += prop; /* Check for registers offset within the devices address range */ if (of_property_read_u32(np, "reg-shift", &prop) == 0) port->regshift = prop; /* Check for fifo size */ if (of_property_read_u32(np, "fifo-size", &prop) == 0) port->fifosize = prop; /* Check for a fixed line number */ ret = of_alias_get_id(np, "serial"); if (ret >= 0) port->line = ret; port->irq = irq_of_parse_and_map(np, 0); port->iotype = UPIO_MEM; if (of_property_read_u32(np, "reg-io-width", &prop) == 0) { switch (prop) { case 1: port->iotype = UPIO_MEM; break; case 2: port->iotype = UPIO_MEM16; break; case 4: port->iotype = of_device_is_big_endian(np) ? UPIO_MEM32BE : UPIO_MEM32; break; default: dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n", prop); ret = -EINVAL; goto out; } } info->rst = devm_reset_control_get_optional_shared(&ofdev->dev, NULL); if (IS_ERR(info->rst)) goto out; ret = reset_control_deassert(info->rst); if (ret) goto out; port->type = type; port->uartclk = clk; port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_FIXED_PORT | UPF_FIXED_TYPE; if (of_find_property(np, "no-loopback-test", NULL)) port->flags |= UPF_SKIP_TEST; port->dev = &ofdev->dev; switch (type) { case PORT_TEGRA: port->handle_break = tegra_serial_handle_break; break; case PORT_RT2880: port->iotype = UPIO_AU; break; } if (IS_ENABLED(CONFIG_SERIAL_8250_FSL) && (of_device_is_compatible(np, "fsl,ns16550") || of_device_is_compatible(np, "fsl,16550-FIFO64"))) port->handle_irq = fsl8250_handle_irq; return 0; out: if (info->clk) clk_disable_unprepare(info->clk); return ret; }
static int dwc3_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res, dwc_res; struct dwc3 *dwc; int ret; u32 mdwidth; void __iomem *regs; dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL); if (!dwc) return -ENOMEM; dwc->clks = devm_kmemdup(dev, dwc3_core_clks, sizeof(dwc3_core_clks), GFP_KERNEL); if (!dwc->clks) return -ENOMEM; dwc->dev = dev; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "missing memory resource\n"); return -ENODEV; } dwc->xhci_resources[0].start = res->start; dwc->xhci_resources[0].end = dwc->xhci_resources[0].start + DWC3_XHCI_REGS_END; dwc->xhci_resources[0].flags = res->flags; dwc->xhci_resources[0].name = res->name; /* * Request memory region but exclude xHCI regs, * since it will be requested by the xhci-plat driver. */ dwc_res = *res; dwc_res.start += DWC3_GLOBALS_REGS_START; regs = devm_ioremap_resource(dev, &dwc_res); if (IS_ERR(regs)) return PTR_ERR(regs); dwc->regs = regs; dwc->regs_size = resource_size(&dwc_res); dwc3_get_properties(dwc); dwc->reset = devm_reset_control_get_optional_shared(dev, NULL); if (IS_ERR(dwc->reset)) return PTR_ERR(dwc->reset); if (dev->of_node) { dwc->num_clks = ARRAY_SIZE(dwc3_core_clks); ret = clk_bulk_get(dev, dwc->num_clks, dwc->clks); if (ret == -EPROBE_DEFER) return ret; /* * Clocks are optional, but new DT platforms should support all * clocks as required by the DT-binding. */ if (ret) dwc->num_clks = 0; } ret = reset_control_deassert(dwc->reset); if (ret) goto put_clks; ret = clk_bulk_prepare(dwc->num_clks, dwc->clks); if (ret) goto assert_reset; ret = clk_bulk_enable(dwc->num_clks, dwc->clks); if (ret) goto unprepare_clks; platform_set_drvdata(pdev, dwc); dwc3_cache_hwparams(dwc); spin_lock_init(&dwc->lock); /* Set dma coherent mask to DMA BUS data width */ mdwidth = DWC3_GHWPARAMS0_MDWIDTH(dwc->hwparams.hwparams0); dev_dbg(dev, "Enabling %d-bit DMA addresses.\n", mdwidth); dma_set_coherent_mask(dev, DMA_BIT_MASK(mdwidth)); pm_runtime_set_active(dev); pm_runtime_use_autosuspend(dev); pm_runtime_set_autosuspend_delay(dev, DWC3_DEFAULT_AUTOSUSPEND_DELAY); pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) goto err1; pm_runtime_forbid(dev); ret = dwc3_alloc_event_buffers(dwc, DWC3_EVENT_BUFFERS_SIZE); if (ret) { dev_err(dwc->dev, "failed to allocate event buffers\n"); ret = -ENOMEM; goto err2; } ret = dwc3_get_dr_mode(dwc); if (ret) goto err3; ret = dwc3_core_init(dwc); if (ret) { dev_err(dev, "failed to initialize core\n"); goto err4; } dwc3_check_params(dwc); ret = dwc3_core_init_mode(dwc); if (ret) goto err5; dwc3_debugfs_init(dwc); pm_runtime_put(dev); return 0; err5: dwc3_event_buffers_cleanup(dwc); err4: dwc3_free_scratch_buffers(dwc); err3: dwc3_free_event_buffers(dwc); err2: pm_runtime_allow(&pdev->dev); err1: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); clk_bulk_disable(dwc->num_clks, dwc->clks); unprepare_clks: clk_bulk_unprepare(dwc->num_clks, dwc->clks); assert_reset: reset_control_assert(dwc->reset); put_clks: clk_bulk_put(dwc->num_clks, dwc->clks); return ret; }
static int st_ehci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; struct usb_ehci_pdata *pdata = &ehci_platform_defaults; struct st_ehci_platform_priv *priv; struct ehci_hcd *ehci; int err, irq, clk = 0; if (usb_disabled()) return -ENODEV; irq = platform_get_irq(dev, 0); if (irq < 0) { dev_err(&dev->dev, "no irq provided"); return irq; } res_mem = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res_mem) { dev_err(&dev->dev, "no memory resource provided"); return -ENXIO; } hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); if (!hcd) return -ENOMEM; platform_set_drvdata(dev, hcd); dev->dev.platform_data = pdata; priv = hcd_to_ehci_priv(hcd); ehci = hcd_to_ehci(hcd); priv->phy = devm_phy_get(&dev->dev, "usb"); if (IS_ERR(priv->phy)) { err = PTR_ERR(priv->phy); goto err_put_hcd; } for (clk = 0; clk < USB_MAX_CLKS; clk++) { priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); if (IS_ERR(priv->clks[clk])) { err = PTR_ERR(priv->clks[clk]); if (err == -EPROBE_DEFER) goto err_put_clks; priv->clks[clk] = NULL; break; } } /* some SoCs don't have a dedicated 48Mhz clock, but those that do need the rate to be explicitly set */ priv->clk48 = devm_clk_get(&dev->dev, "clk48"); if (IS_ERR(priv->clk48)) { dev_info(&dev->dev, "48MHz clk not found\n"); priv->clk48 = NULL; } priv->pwr = devm_reset_control_get_optional_shared(&dev->dev, "power"); if (IS_ERR(priv->pwr)) { err = PTR_ERR(priv->pwr); if (err == -EPROBE_DEFER) goto err_put_clks; priv->pwr = NULL; } priv->rst = devm_reset_control_get_optional_shared(&dev->dev, "softreset"); if (IS_ERR(priv->rst)) { err = PTR_ERR(priv->rst); if (err == -EPROBE_DEFER) goto err_put_clks; priv->rst = NULL; } if (pdata->power_on) { err = pdata->power_on(dev); if (err < 0) goto err_put_clks; } hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); hcd->regs = devm_ioremap_resource(&dev->dev, res_mem); if (IS_ERR(hcd->regs)) { err = PTR_ERR(hcd->regs); goto err_put_clks; } err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) goto err_put_clks; device_wakeup_enable(hcd->self.controller); platform_set_drvdata(dev, hcd); return err; err_put_clks: while (--clk >= 0) clk_put(priv->clks[clk]); err_put_hcd: if (pdata == &ehci_platform_defaults) dev->dev.platform_data = NULL; usb_put_hcd(hcd); return err; }
static int dw_wdt_drv_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct watchdog_device *wdd; struct dw_wdt *dw_wdt; struct resource *mem; int ret; dw_wdt = devm_kzalloc(dev, sizeof(*dw_wdt), GFP_KERNEL); if (!dw_wdt) return -ENOMEM; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dw_wdt->regs = devm_ioremap_resource(dev, mem); if (IS_ERR(dw_wdt->regs)) return PTR_ERR(dw_wdt->regs); dw_wdt->clk = devm_clk_get(dev, NULL); if (IS_ERR(dw_wdt->clk)) return PTR_ERR(dw_wdt->clk); ret = clk_prepare_enable(dw_wdt->clk); if (ret) return ret; dw_wdt->rate = clk_get_rate(dw_wdt->clk); if (dw_wdt->rate == 0) { ret = -EINVAL; goto out_disable_clk; } dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); if (IS_ERR(dw_wdt->rst)) { ret = PTR_ERR(dw_wdt->rst); goto out_disable_clk; } reset_control_deassert(dw_wdt->rst); wdd = &dw_wdt->wdd; wdd->info = &dw_wdt_ident; wdd->ops = &dw_wdt_ops; wdd->min_timeout = 1; wdd->max_hw_heartbeat_ms = dw_wdt_top_in_seconds(dw_wdt, DW_WDT_MAX_TOP) * 1000; wdd->parent = dev; watchdog_set_drvdata(wdd, dw_wdt); watchdog_set_nowayout(wdd, nowayout); watchdog_init_timeout(wdd, 0, dev); /* * If the watchdog is already running, use its already configured * timeout. Otherwise use the default or the value provided through * devicetree. */ if (dw_wdt_is_enabled(dw_wdt)) { wdd->timeout = dw_wdt_get_top(dw_wdt); set_bit(WDOG_HW_RUNNING, &wdd->status); } else { wdd->timeout = DW_WDT_DEFAULT_SECONDS; watchdog_init_timeout(wdd, 0, dev); } platform_set_drvdata(pdev, dw_wdt); watchdog_set_restart_priority(wdd, 128); ret = watchdog_register_device(wdd); if (ret) goto out_disable_clk; return 0; out_disable_clk: clk_disable_unprepare(dw_wdt->clk); return ret; }