static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, const char *fck_source, const char *property, const char **timer_name, int posted) { char name[10]; /* 10 = sizeof("gptXX_Xck0") */ const char *oh_name; struct device_node *np; struct omap_hwmod *oh; struct resource irq, mem; struct clk *src; int r = 0; if (of_have_populated_dt()) { np = omap_get_timer_dt(omap_timer_match, property); if (!np) return -ENODEV; of_property_read_string_index(np, "ti,hwmods", 0, &oh_name); if (!oh_name) return -ENODEV; timer->irq = irq_of_parse_and_map(np, 0); if (!timer->irq) return -ENXIO; timer->io_base = of_iomap(np, 0); of_node_put(np); } else { if (omap_dm_timer_reserve_systimer(timer->id)) return -ENODEV; sprintf(name, "timer%d", timer->id); oh_name = name; } oh = omap_hwmod_lookup(oh_name); if (!oh) return -ENODEV; *timer_name = oh->name; if (!of_have_populated_dt()) { r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, &irq); if (r) return -ENXIO; timer->irq = irq.start; r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, &mem); if (r) return -ENXIO; /* Static mapping, never released */ timer->io_base = ioremap(mem.start, mem.end - mem.start); } if (!timer->io_base) return -ENXIO; /* After the dmtimer is using hwmod these clocks won't be needed */ timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); if (IS_ERR(timer->fclk)) return PTR_ERR(timer->fclk); src = clk_get(NULL, fck_source); if (IS_ERR(src)) return PTR_ERR(src); if (clk_get_parent(timer->fclk) != src) { r = clk_set_parent(timer->fclk, src); if (r < 0) { pr_warn("%s: %s cannot set source\n", __func__, oh->name); clk_put(src); return r; } } clk_put(src); omap_hwmod_setup_one(oh_name); omap_hwmod_enable(oh); __omap_dm_timer_init_regs(timer); if (posted) __omap_dm_timer_enable_posted(timer); /* Check that the intended posted configuration matches the actual */ if (posted != timer->posted) return -EINVAL; timer->rate = clk_get_rate(timer->fclk); timer->reserved = 1; return r; }
static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer, int gptimer_id, const char *fck_source) { char name[10]; /* 10 = sizeof("gptXX_Xck0") */ struct omap_hwmod *oh; struct resource irq_rsrc, mem_rsrc; size_t size; int res = 0; int r; sprintf(name, "timer%d", gptimer_id); omap_hwmod_setup_one(name); oh = omap_hwmod_lookup(name); if (!oh) return -ENODEV; r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL, &irq_rsrc); if (r) return -ENXIO; timer->irq = irq_rsrc.start; r = omap_hwmod_get_resource_byname(oh, IORESOURCE_MEM, NULL, &mem_rsrc); if (r) return -ENXIO; timer->phys_base = mem_rsrc.start; size = mem_rsrc.end - mem_rsrc.start; /* Static mapping, never released */ timer->io_base = ioremap(timer->phys_base, size); if (!timer->io_base) return -ENXIO; /* After the dmtimer is using hwmod these clocks won't be needed */ timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh)); if (IS_ERR(timer->fclk)) return -ENODEV; omap_hwmod_enable(oh); if (omap_dm_timer_reserve_systimer(gptimer_id)) return -ENODEV; if (gptimer_id != 12) { struct clk *src; src = clk_get(NULL, fck_source); if (IS_ERR(src)) { res = -EINVAL; } else { res = __omap_dm_timer_set_source(timer->fclk, src); if (IS_ERR_VALUE(res)) pr_warning("%s: timer%i cannot set source\n", __func__, gptimer_id); clk_put(src); } } __omap_dm_timer_init_regs(timer); __omap_dm_timer_reset(timer, 1, 1); timer->posted = 1; timer->rate = clk_get_rate(timer->fclk); timer->reserved = 1; return res; }
static int hdmi_probe(struct snd_soc_codec *codec) { struct platform_device *pdev = to_platform_device(codec->dev); struct resource *hdmi_rsrc; int ret = 0; snd_soc_codec_set_drvdata(codec, &hdmi_data); hdmi_rsrc = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!hdmi_rsrc) { dev_err(&pdev->dev, "Cannot obtain IORESOURCE_MEM HDMI\n"); ret = -EINVAL; goto res_err; } hdmi_data.oh = omap_hwmod_lookup("dss_hdmi"); if (!hdmi_data.oh) { dev_err(&pdev->dev, "can't find omap_hwmod for hdmi\n"); ret = -ENODEV; goto res_err; } /* Base address taken from platform */ hdmi_data.ip_data.base_wp = ioremap(hdmi_rsrc->start, resource_size(hdmi_rsrc)); if (!hdmi_data.ip_data.base_wp) { dev_err(&pdev->dev, "can't ioremap WP\n"); ret = -ENOMEM; goto res_err; } hdmi_data.ip_data.hdmi_core_sys_offset = HDMI_CORE_SYS; hdmi_data.ip_data.hdmi_core_av_offset = HDMI_CORE_AV; hdmi_data.ip_data.hdmi_pll_offset = HDMI_PLLCTRL; hdmi_data.ip_data.hdmi_phy_offset = HDMI_PHY; hdmi_data.dssdev = omap_dss_find_device(NULL, hdmi_audio_match); if (!hdmi_data.dssdev) { dev_err(&pdev->dev, "can't find HDMI device\n"); ret = -ENODEV; goto dssdev_err; } hdmi_data.notifier.notifier_call = hdmi_audio_notifier_callback; blocking_notifier_chain_register(&hdmi_data.dssdev->state_notifiers, &hdmi_data.notifier); hdmi_data.workqueue = create_singlethread_workqueue("hdmi-codec"); INIT_DELAYED_WORK(&hdmi_data.delayed_work, hdmi_audio_work); return 0; dssdev_err: iounmap(hdmi_data.ip_data.base_wp); res_err: return ret; }
void __init usbhs_init(const struct usbhs_omap_board_data *pdata) { struct omap_hwmod *uhh_hwm, *tll_hwm; struct platform_device *pdev; int bus_id = -1; int i; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { usbhs_data.port_mode[i] = pdata->port_mode[i]; usbtll_data.port_mode[i] = pdata->port_mode[i]; ohci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i]; ehci_data.regulator[i] = pdata->regulator[i]; } ehci_data.phy_reset = pdata->phy_reset; ehci_data.phy_clk = pdata->phy_clk; ohci_data.es2_compatibility = pdata->es2_compatibility; ehci_data.usbhs_update_sar = &usbhs_update_sar; ohci_data.usbhs_update_sar = &usbhs_update_sar; usbhs_data.ehci_data = &ehci_data; usbhs_data.ohci_data = &ohci_data; uhh_hwm = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); if (!uhh_hwm) { pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); return; } tll_hwm = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); if (!tll_hwm) { pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); return; } l3init_clkdm = clkdm_lookup("l3_init_clkdm"); if (!l3init_clkdm) { pr_err("Failed to get l3_init_clkdm\n"); } pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm, (void *)&usbtll_data, sizeof(usbtll_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(pdev)) { pr_err("Could not build hwmod device %s\n", USBHS_TLL_HWMODNAME); return; } pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm, (void *)&usbhs_data, sizeof(usbhs_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(pdev)) { pr_err("Could not build hwmod devices %s\n", USBHS_UHH_HWMODNAME); return; } pdev_usbhs = pdev; if (cpu_is_omap34xx()) { setup_ehci_io_mux(pdata->port_mode); setup_ohci_io_mux(pdata->port_mode); } else if (cpu_is_omap44xx() || cpu_is_omap54xx()) uhh_hwm->mux = setup_4430_usbhs_io_mux(pdev, pdata->port_mode); }
void __init usb_musb_init(struct omap_musb_board_data *board_data) { char oh_name[MAX_OMAP_MUSB_HWMOD_NAME_LEN]; struct omap_hwmod *oh; struct omap_device *od; struct platform_device *pdev = NULL; struct device *dev; int l, bus_id = -1; struct musb_hdrc_platform_data *pdata; void __iomem *otg_base; if (!board_data) { pr_err("Board data is required for hdrc device register\n"); return; } l = snprintf(oh_name, MAX_OMAP_MUSB_HWMOD_NAME_LEN, "usb_otg_hs"); WARN(l >= MAX_OMAP_MUSB_HWMOD_NAME_LEN, "String buffer overflow in MUSB device setup\n"); oh = omap_hwmod_lookup(oh_name); if (!oh) { pr_err("Could not look up %s\n", oh_name); } else { /* * REVISIT: This line can be removed once all the platforms * using musb_core.c have been converted to use use clkdev. */ musb_plat.clock = "ick"; musb_plat.board_data = board_data; musb_plat.power = board_data->power >> 1; musb_plat.mode = board_data->mode; musb_plat.device_enable = omap_device_enable; musb_plat.device_idle = omap_device_idle; musb_plat.enable_wakeup = omap_device_enable_wakeup; musb_plat.disable_wakeup = omap_device_disable_wakeup; #ifdef CONFIG_PM musb_plat.set_min_bus_tput = omap_pm_set_min_bus_tput; #endif /* * Errata 1.166 idle_req/ack is broken in omap3430 * workaround is to disable the autodile bit for omap3430. */ if (cpu_is_omap3430() || cpu_is_omap3630()) oh->flags |= HWMOD_NO_OCP_AUTOIDLE; musb_plat.oh = oh; oh_p = oh; pdata = &musb_plat; od = omap_device_build(name, bus_id, oh, pdata, sizeof(struct musb_hdrc_platform_data), omap_musb_latency, ARRAY_SIZE(omap_musb_latency), false); if (IS_ERR(od)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); } else { pdev = &od->pdev; dev = &pdev->dev; get_device(dev); dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); } /*powerdown the phy*/ if (omap_rev() > OMAP3630_REV_ES1_1) { otg_base = ioremap(OMAP34XX_HSUSB_OTG_BASE, SZ_4K); if (WARN_ON(!otg_base)) return; /* Reset OTG controller. After reset, it will be in * force-idle, force-standby mode. */ __raw_writel(OTG_SYSC_SOFTRESET, otg_base + OTG_SYSCONFIG); iounmap(otg_base); } if (board_data->interface_type == MUSB_INTERFACE_UTMI) omap_writel(PHY_PD, DIE_ID_REG_BASE + CONTROL_DEV_CONF); usb_gadget_init(); #ifdef CONFIG_ARCH_OMAP3 if(pdev){ musb_plat.device_enable(pdev); musb_module_reset(); musb_plat.device_idle(pdev); }else{ pr_err("Could not reset musb module.\n"); } #endif } }
void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) { struct omap_hwmod *oh; struct omap_device *od; struct platform_device *pdev; struct device *dev = NULL; int bus_id = -1; const char *oh_name, *name; struct omap_musb_board_data *board_data; if (musb_board_data) board_data = musb_board_data; else board_data = &musb_default_board_data; /* * REVISIT: This line can be removed once all the platforms using * musb_core.c have been converted to use use clkdev. */ musb_plat.clock = "ick"; musb_plat.board_data = board_data; musb_plat.power = board_data->power >> 1; musb_plat.mode = board_data->mode; musb_plat.extvbus = board_data->extvbus; if (cpu_is_omap44xx()) omap4430_phy_init(dev); /* power down the phy */ if (cpu_is_omap3517() || cpu_is_omap3505()) { oh_name = "am35x_otg_hs"; name = "musb-am35x"; } else { oh_name = "usb_otg_hs"; name = "musb-omap2430"; } oh = omap_hwmod_lookup(oh_name); if (!oh) { pr_err("Could not look up %s\n", oh_name); return; } od = omap_device_build(name, bus_id, oh, &musb_plat, sizeof(musb_plat), omap_musb_latency, ARRAY_SIZE(omap_musb_latency), false); if (IS_ERR(od)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); return; } pdev = &od->pdev; dev = &pdev->dev; get_device(dev); dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); if (cpu_is_omap44xx()) omap4430_phy_init(dev); #ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE platform_device_register(&android_usb_device); #endif }
static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) { struct omap_hwmod *oh; struct omap_hwmod *ohs[1]; struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; struct omap_hsmmc_platform_data *mmc_data; struct omap_hsmmc_dev_attr *mmc_dev_attr; char *name; int res; mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); if (!mmc_data) return; res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data); if (res < 0) goto free_mmc; name = "omap_hsmmc"; res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN, "mmc%d", ctrl_nr); WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN, "String buffer overflow in MMC%d device setup\n", ctrl_nr); oh = omap_hwmod_lookup(oh_name); if (!oh) { pr_err("Could not look up %s\n", oh_name); goto free_name; } ohs[0] = oh; if (oh->dev_attr != NULL) { mmc_dev_attr = oh->dev_attr; mmc_data->controller_flags = mmc_dev_attr->flags; } pdev = platform_device_alloc(name, ctrl_nr - 1); if (!pdev) { pr_err("Could not allocate pdev for %s\n", name); goto free_name; } dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); od = omap_device_alloc(pdev, ohs, 1); if (IS_ERR(od)) { pr_err("Could not allocate od for %s\n", name); goto put_pdev; } res = platform_device_add_data(pdev, mmc_data, sizeof(struct omap_hsmmc_platform_data)); if (res) { pr_err("Could not add pdata for %s\n", name); goto put_pdev; } hsmmcinfo->pdev = pdev; res = omap_device_register(pdev); if (res) { pr_err("Could not register od for %s\n", name); goto free_od; } goto free_mmc; free_od: omap_device_delete(od); put_pdev: platform_device_put(pdev); free_name: kfree(mmc_data->name); free_mmc: kfree(mmc_data); }
static int am33xx_pm_suspend(void) { int state, ret = 0; struct omap_hwmod *gpmc_oh, *usb_oh, *gpio1_oh; usb_oh = omap_hwmod_lookup("usb_otg_hs"); gpmc_oh = omap_hwmod_lookup("gpmc"); gpio1_oh = omap_hwmod_lookup("gpio1"); /* WKUP domain GPIO */ omap_hwmod_enable(usb_oh); omap_hwmod_enable(gpmc_oh); /* * Keep USB module enabled during standby * to enable USB remote wakeup * Note: This will result in hard-coding USB state * during standby */ if (suspend_state != PM_SUSPEND_STANDBY) omap_hwmod_idle(usb_oh); omap_hwmod_idle(gpmc_oh); /* * Disable the GPIO module. This ensure that * only sWAKEUP interrupts to Cortex-M3 get generated * * XXX: EVM_SK uses a GPIO0 pin for VTP control * in suspend and hence we can't do this for EVM_SK * alone. The side-effect of this is that GPIO wakeup * might have issues. Refer to commit 672639b for the * details */ /* * Keep GPIO0 module enabled during standby to * support wakeup via GPIO0 keys. */ if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) && (suspend_state != PM_SUSPEND_STANDBY)) omap_hwmod_idle(gpio1_oh); /* * Update Suspend_State value to be used in sleep33xx.S to keep * GPIO0 module enabled during standby for EVM-SK */ if (suspend_state == PM_SUSPEND_STANDBY) suspend_cfg_param_list[SUSPEND_STATE] = PM_STANDBY; else suspend_cfg_param_list[SUSPEND_STATE] = PM_DS0; /* * Keep Touchscreen module enabled during standby * to enable wakeup from standby. */ if (suspend_state == PM_SUSPEND_STANDBY) writel(0x2, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL); if (gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_sleep(gfx_l3_clkdm); clkdm_sleep(gfx_l4ls_clkdm); } /* Try to put GFX to sleep */ if (gfx_pwrdm) pwrdm_set_next_pwrst(gfx_pwrdm, PWRDM_POWER_OFF); else pr_err("Could not program GFX to low power state\n"); omap3_intc_suspend(); writel(0x0, AM33XX_CM_MPU_MPU_CLKCTRL); ret = cpu_suspend(0, am33xx_do_sram_idle); writel(0x2, AM33XX_CM_MPU_MPU_CLKCTRL); if (gfx_pwrdm) { state = pwrdm_read_pwrst(gfx_pwrdm); if (state != PWRDM_POWER_OFF) pr_err("GFX domain did not transition to low power state\n"); else pr_info("GFX domain entered low power state\n"); } /* XXX: Why do we need to wakeup the clockdomains? */ if(gfx_l3_clkdm && gfx_l4ls_clkdm) { clkdm_wakeup(gfx_l3_clkdm); clkdm_wakeup(gfx_l4ls_clkdm); } /* * Touchscreen module was enabled during standby * Disable it here. */ if (suspend_state == PM_SUSPEND_STANDBY) writel(0x0, AM33XX_CM_WKUP_ADC_TSC_CLKCTRL); /* * Put USB module to idle on resume from standby */ if (suspend_state == PM_SUSPEND_STANDBY) omap_hwmod_idle(usb_oh); ret = am33xx_verify_lp_state(ret); /* * Enable the GPIO module. Once the driver is * fully adapted to runtime PM this will go away */ /* * During standby, GPIO was not disabled. Hence no * need to enable it here. */ if ((suspend_cfg_param_list[EVM_ID] != EVM_SK) && (suspend_state != PM_SUSPEND_STANDBY)) omap_hwmod_enable(gpio1_oh); return ret; }
/* * Initialise the wakeupgen module. */ int __init omap_wakeupgen_init(void) { int i; unsigned int boot_cpu = smp_processor_id(); unsigned int max_spi_reg; /* Not supported on OMAP4 ES1.0 silicon */ if (omap_rev() == OMAP4430_REV_ES1_0) { WARN(1, "WakeupGen: Not supported on OMAP4430 ES1.0\n"); return -EPERM; } /* Static mapping, never released */ wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K); if (WARN_ON(!wakeupgen_base)) return -ENOMEM; if (cpu_is_omap44xx()) { irq_banks = OMAP4_NR_BANKS; max_irqs = OMAP4_NR_IRQS; secure_api_index = OMAP4_HAL_SAVEGIC_INDEX; secure_hw_api_index = OMAP4_HAL_SAVEHW_INDEX; secure_hal_save_all_api_index = OMAP4_HAL_SAVEALL_INDEX; secure_ram_api_index = OMAP4_HAL_SAVESECURERAM_INDEX; } else if (cpu_is_omap54xx()) { secure_api_index = OMAP5_HAL_SAVEGIC_INDEX; secure_hw_api_index = OMAP5_HAL_SAVEHW_INDEX; secure_hal_save_all_api_index = OMAP5_HAL_SAVEALL_INDEX; secure_ram_api_index = OMAP5_HAL_SAVESECURERAM_INDEX; } /* Clear all IRQ bitmasks at wakeupGen level */ for (i = 0; i < irq_banks; i++) { wakeupgen_writel(0, i, CPU0_ID); wakeupgen_writel(0, i, CPU1_ID); } /* * Override GIC architecture specific functions to add * OMAP WakeupGen interrupt controller along with GIC */ gic_arch_extn.irq_mask = wakeupgen_mask; gic_arch_extn.irq_unmask = wakeupgen_unmask; gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE; /* * FIXME: Add support to set_smp_affinity() once the core * GIC code has necessary hooks in place. */ /* Associate all the IRQs to boot CPU like GIC init does. */ for (i = 0; i < max_irqs; i++) irq_target_cpu[i] = boot_cpu; /* * Find out how many interrupts are supported. * OMAP4 supports max of 128 SPIs where as GIC can support * up to 1020 interrupt sources. On OMAP4, maximum SPIs are * fused in DIST_CTR bit-fields as 128. Hence the code is safe * from reserved register writes since its well within 1020. */ max_spi_reg = gic_readl(GIC_DIST_CTR, 0) & 0x1f; spi_irq_banks = min(max_spi_reg, irq_banks); /* * Set CPU0 GIC backup flag permanently for omap4460 GP, * this is needed because of the ROM code bug that breaks * GIC during wakeup from device off. This errata fix also * clears the GIC save area during init to prevent restoring * garbage to the GIC. */ if (cpu_is_omap446x() && omap_type() == OMAP2_DEVICE_TYPE_GP) pm44xx_errata |= PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx; if (cpu_is_omap44xx() && (omap_type() == OMAP2_DEVICE_TYPE_GP)) { sar_base = omap4_get_sar_ram_base(); if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx)) for (i = SAR_BACKUP_STATUS_OFFSET; i < WAKEUPGENENB_OFFSET_CPU0; i += 4) sar_writel(0, i, 0); sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU0_OFFSET, 0); sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_CPU1_OFFSET, 0); for (i = 0; i < max_spi_reg; i++) sar_writel(GIC_ISR_NON_SECURE, SAR_ICDISR_SPI_OFFSET, i); if (IS_PM44XX_ERRATUM(PM_OMAP4_ROM_CPU1_BACKUP_ERRATUM_xxx)) __raw_writel(SAR_BACKUP_STATUS_GIC_CPU0, sar_base + SAR_BACKUP_STATUS_OFFSET); } else { l3_main_3_oh = omap_hwmod_lookup("l3_main_3"); if (!l3_main_3_oh) pr_err("%s: failed to get l3_main_3_oh\n", __func__); } irq_hotplug_init(); irq_pm_init(); return 0; }
/** * omap_device_build_from_dt - build an omap_device with multiple hwmods * @pdev_name: name of the platform_device driver to use * @pdev_id: this platform_device's connection ID * @oh: ptr to the single omap_hwmod that backs this omap_device * @pdata: platform_data ptr to associate with the platform_device * @pdata_len: amount of memory pointed to by @pdata * * Function for building an omap_device already registered from device-tree * * Returns 0 or PTR_ERR() on error. */ static int omap_device_build_from_dt(struct platform_device *pdev) { struct omap_hwmod **hwmods; struct omap_device *od; struct omap_hwmod *oh; struct device_node *node = pdev->dev.of_node; const char *oh_name; int oh_cnt, i, ret = 0; bool device_active = false; oh_cnt = of_property_count_strings(node, "ti,hwmods"); if (oh_cnt <= 0) { dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n"); return -ENODEV; } hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); if (!hwmods) { ret = -ENOMEM; goto odbfd_exit; } for (i = 0; i < oh_cnt; i++) { of_property_read_string_index(node, "ti,hwmods", i, &oh_name); oh = omap_hwmod_lookup(oh_name); if (!oh) { dev_err(&pdev->dev, "Cannot lookup hwmod '%s'\n", oh_name); ret = -EINVAL; goto odbfd_exit1; } hwmods[i] = oh; if (oh->flags & HWMOD_INIT_NO_IDLE) device_active = true; } od = omap_device_alloc(pdev, hwmods, oh_cnt); if (IS_ERR(od)) { dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n", oh_name); ret = PTR_ERR(od); goto odbfd_exit1; } /* Fix up missing resource names */ for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; if (r->name == NULL) r->name = dev_name(&pdev->dev); } pdev->dev.pm_domain = &omap_device_pm_domain; if (device_active) { omap_device_enable(pdev); pm_runtime_set_active(&pdev->dev); } odbfd_exit1: kfree(hwmods); odbfd_exit: /* if data/we are at fault.. load up a fail handler */ if (ret) pdev->dev.pm_domain = &omap_device_fail_pm_domain; return ret; }
/* Initiliaze WKUP_M3, load the binary blob and let it run */ static int wkup_m3_init(void) { struct clk *m3_clk; struct omap_hwmod *wkup_m3_oh; const struct firmware *firmware; int ret = 0; wkup_m3_oh = omap_hwmod_lookup("wkup_m3"); if (!wkup_m3_oh) { pr_err("%s: could not find omap_hwmod\n", __func__); ret = -ENODEV; goto exit; } ipc_regs = ioremap(A8_M3_IPC_REGS, 0x4*8); if (!ipc_regs) { pr_err("Could not ioremap the IPC area\b"); ret = -ENOMEM; goto exit; } m3_eoi = ioremap(M3_TXEV_EOI, 0x4); if (!m3_eoi) { pr_err("Could not ioremap the EOI register\n"); ret = -ENOMEM; goto err1; } /* Reserve the MBOX for sending messages to M3 */ m3_mbox = omap_mbox_get("wkup_m3", &wkup_m3_mbox_notifier); if (IS_ERR(m3_mbox)) { pr_err("Could not reserve mailbox for A8->M3 IPC\n"); ret = -ENODEV; goto err2; } /* Enable access to the M3 code and data area from A8 */ m3_clk = clk_get(NULL, "wkup_m3_fck"); if (IS_ERR(m3_clk)) { pr_err("%s failed to enable WKUP_M3 clock\n", __func__); goto err3; } if (clk_enable(m3_clk)) { pr_err("%s WKUP_M3: clock enable Failed\n", __func__); goto err4; } m3_code = ioremap(M3_UMEM, SZ_16K); if (!m3_code) { pr_err("%s Could not ioremap M3 code space\n", __func__); ret = -ENOMEM; goto err5; } pr_info("Trying to load am335x-pm-firmware.bin (60 secs timeout)\n"); ret = request_firmware(&firmware, "am335x-pm-firmware.bin", mpu_dev); if (ret < 0) { dev_err(mpu_dev, "request_firmware failed\n"); goto err6; } else { memcpy(m3_code, firmware->data, firmware->size); pr_info("Copied the M3 firmware to UMEM\n"); } ret = request_irq(AM33XX_IRQ_M3_M3SP_TXEV, wkup_m3_txev_handler, IRQF_DISABLED, "wkup_m3_txev", NULL); if (ret) { pr_err("%s request_irq failed for 0x%x\n", __func__, AM33XX_IRQ_M3_M3SP_TXEV); goto err6; } m3_state = M3_STATE_RESET; ret = omap_hwmod_deassert_hardreset(wkup_m3_oh, "wkup_m3"); if (ret) { pr_err("Could not deassert the reset for WKUP_M3\n"); goto err6; } else { return 0; } err6: release_firmware(firmware); iounmap(m3_code); err5: clk_disable(m3_clk); err4: clk_put(m3_clk); err3: omap_mbox_put(m3_mbox, &wkup_m3_mbox_notifier); err2: iounmap(m3_eoi); err1: iounmap(ipc_regs); exit: return ret; }
/** * omap_init_opp_table() - Initialize opp table as per the CPU type * @opp_def: opp default list for this silicon * @opp_def_size: number of opp entries for this silicon * * Register the initial OPP table with the OPP library based on the CPU * type. This is meant to be used only by SoC specific registration. */ int __init omap_init_opp_table(struct omap_opp_def *opp_def, u32 opp_def_size) { int i, r; struct clk *clk; long round_rate; if (!opp_def || !opp_def_size) { pr_err("%s: invalid params!\n", __func__); return -EINVAL; } /* * Initialize only if not already initialized even if the previous * call failed, because, no reason we'd succeed again. */ if (omap_table_init) return -EEXIST; omap_table_init = 1; /* Lets now register with OPP library */ for (i = 0; i < opp_def_size; i++) { struct omap_hwmod *oh; struct device *dev; if (!opp_def->hwmod_name) { WARN(1, "%s: NULL name of omap_hwmod, failing" " [%d].\n", __func__, i); goto next; } oh = omap_hwmod_lookup(opp_def->hwmod_name); if (!oh || !oh->od) { WARN(1, "%s: no hwmod or odev for %s, [%d] " "cannot add OPPs.\n", __func__, opp_def->hwmod_name, i); goto next; } dev = &oh->od->pdev->dev; clk = omap_clk_get_by_name(opp_def->clk_name); if (clk) { round_rate = clk_round_rate(clk, opp_def->freq); if (round_rate > 0) { opp_def->freq = round_rate; } else { WARN(1, "%s: round_rate for clock %s failed\n", __func__, opp_def->clk_name); goto next; /* skip Bad OPP */ } } else { WARN(1, "%s: No clock by name %s found\n", __func__, opp_def->clk_name); goto next; /* skip Bad OPP */ } r = opp_add(dev, opp_def->freq, opp_def->u_volt); if (r) { dev_err(dev, "%s: add OPP %ld failed for %s [%d] " "result=%d\n", __func__, opp_def->freq, opp_def->hwmod_name, i, r); } else { if (!opp_def->default_available) r = opp_disable(dev, opp_def->freq); if (r) dev_err(dev, "%s: disable %ld failed for %s " "[%d] result=%d\n", __func__, opp_def->freq, opp_def->hwmod_name, i, r); r = omap_dvfs_register_device(dev, opp_def->voltdm_name, opp_def->clk_name); if (r) dev_err(dev, "%s:%s:err dvfs register %d %d\n", __func__, opp_def->hwmod_name, r, i); } next: opp_def++; } return 0; }
void __init usbhs_init(const struct usbhs_omap_board_data *pdata) { struct omap_hwmod *oh[4]; struct omap_device *od; int bus_id = -1; int i; for (i = 0; i < OMAP3_HS_USB_PORTS; i++) { usbhs_data.port_mode[i] = pdata->port_mode[i]; ohci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.port_mode[i] = pdata->port_mode[i]; ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i]; ehci_data.regulator[i] = pdata->regulator[i]; ehci_data.transceiver_clk[i] = pdata->transceiver_clk[i]; } ehci_data.phy_reset = pdata->phy_reset; ohci_data.es2_compatibility = pdata->es2_compatibility; usbhs_data.ehci_data = &ehci_data; usbhs_data.ohci_data = &ohci_data; oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME); if (!oh[0]) { pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME); return; } oh[1] = omap_hwmod_lookup(USBHS_OHCI_HWMODNAME); if (!oh[1]) { pr_err("Could not look up %s\n", USBHS_OHCI_HWMODNAME); return; } oh[2] = omap_hwmod_lookup(USBHS_EHCI_HWMODNAME); if (!oh[2]) { pr_err("Could not look up %s\n", USBHS_EHCI_HWMODNAME); return; } oh[3] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME); if (!oh[3]) { pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME); return; } if (cpu_is_omap34xx()) { setup_ehci_io_mux(pdata->port_mode); setup_ohci_io_mux(pdata->port_mode); } else if (cpu_is_omap44xx()) { oh[2]->mux = setup_4430ehci_io_mux(pdata->port_mode); oh[1]->mux = setup_4430ohci_io_mux(pdata->port_mode); } od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 4, (void *)&usbhs_data, sizeof(usbhs_data), omap_uhhtll_latency, ARRAY_SIZE(omap_uhhtll_latency), false); if (IS_ERR(od)) { pr_err("Could not build hwmod devices %s, %s\n", USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME); return; } usbhs_wake = kmalloc(sizeof(*usbhs_wake), GFP_KERNEL); if (!usbhs_wake) { pr_err("Could not allocate usbhs_wake\n"); return; } INIT_WORK(&usbhs_wake->wakeup_work, usbhs_resume_work); usbhs_wake->oh_ehci = oh[2]; usbhs_wake->oh_ohci = oh[1]; usbhs_wake->dev = &od->pdev.dev; }
static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) { struct omap_hwmod *oh; struct omap_hwmod *ohs[1]; struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; struct omap_mmc_platform_data *mmc_data; struct omap_mmc_dev_attr *mmc_dev_attr; char *name; int res; mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); if (!mmc_data) { pr_err("Cannot allocate memory for mmc device!\n"); return; } res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data); if (res < 0) goto free_mmc; omap_hsmmc_mux(mmc_data, (ctrl_nr - 1)); name = "omap_hsmmc"; res = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN, "mmc%d", ctrl_nr); WARN(res >= MAX_OMAP_MMC_HWMOD_NAME_LEN, "String buffer overflow in MMC%d device setup\n", ctrl_nr); oh = omap_hwmod_lookup(oh_name); if (!oh) { pr_err("Could not look up %s\n", oh_name); goto free_name; } ohs[0] = oh; if (oh->dev_attr != NULL) { mmc_dev_attr = oh->dev_attr; mmc_data->controller_flags = mmc_dev_attr->flags; /* * erratum 2.1.1.128 doesn't apply if board has * a transceiver is attached */ if (hsmmcinfo->transceiver) mmc_data->controller_flags &= ~OMAP_HSMMC_BROKEN_MULTIBLOCK_READ; } pdev = platform_device_alloc(name, ctrl_nr - 1); if (!pdev) { pr_err("Could not allocate pdev for %s\n", name); goto free_name; } dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); od = omap_device_alloc(pdev, ohs, 1, NULL, 0); if (!od) { pr_err("Could not allocate od for %s\n", name); goto put_pdev; } res = platform_device_add_data(pdev, mmc_data, sizeof(struct omap_mmc_platform_data)); if (res) { pr_err("Could not add pdata for %s\n", name); goto put_pdev; } hsmmcinfo->pdev = pdev; if (hsmmcinfo->deferred) goto free_mmc; res = omap_device_register(pdev); if (res) { pr_err("Could not register od for %s\n", name); goto free_od; } goto free_mmc; free_od: omap_device_delete(od); put_pdev: platform_device_put(pdev); free_name: kfree(mmc_data->slots[0].name); free_mmc: kfree(mmc_data); }
void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) { struct omap_hwmod *oh; struct platform_device *pdev; struct device *dev; int bus_id = -1; const char *oh_name, *name; struct omap_musb_board_data *board_data; if (musb_board_data) board_data = musb_board_data; else board_data = &musb_default_board_data; /* * REVISIT: This line can be removed once all the platforms using * musb_core.c have been converted to use use clkdev. */ musb_plat[0].clock = "ick"; musb_plat[0].board_data = board_data; musb_plat[0].power = board_data->power >> 1; musb_plat[0].mode = board_data->mode; musb_plat[0].extvbus = board_data->extvbus; /* * OMAP3630/AM35x platform has MUSB RTL-1.8 which has the fix for the * issue restricting active endpoints to use first 8K of FIFO space. * This issue restricts OMAP35x platform to use fifo_mode '5'. */ if (cpu_is_omap3430()) musb_config.fifo_mode = 5; if (cpu_is_omap3517() || cpu_is_omap3505()) { oh_name = "am35x_otg_hs"; name = "musb-am35x"; } else if (cpu_is_ti816x() || cpu_is_am33xx()) { musb_config.fifo_mode = 4; /* only usb0 port enabled in peripheral mode*/ if (board_data->mode == MUSB_PERIPHERAL) { board_data->instances = 0; musb_config.fifo_mode = 6; } board_data->set_phy_power = ti81xx_musb_phy_power; oh_name = "usb_otg_hs"; name = "ti81xx-usbss"; } else { oh_name = "usb_otg_hs"; name = "musb-omap2430"; } oh = omap_hwmod_lookup(oh_name); if (WARN(!oh, "%s: could not find omap_hwmod for %s\n", __func__, oh_name)) return; pdev = omap_device_build(name, bus_id, oh, &musb_plat, sizeof(musb_plat), NULL, 0, false); if (IS_ERR(pdev)) { pr_err("Could not build omap_device for %s %s\n", name, oh_name); return; } dev = &pdev->dev; get_device(dev); dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); if (cpu_is_omap44xx()) omap4430_phy_init(dev); }
int am33xx_cpsw_init(enum am33xx_cpsw_mac_mode mode, unsigned char *phy_id0, unsigned char *phy_id1) { struct omap_hwmod *oh; struct platform_device *pdev; u32 mac_lo, mac_hi, gmii_sel; u32 i; mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_LO); mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_HI); am33xx_cpsw_slaves[0].mac_addr[0] = mac_hi & 0xFF; am33xx_cpsw_slaves[0].mac_addr[1] = (mac_hi & 0xFF00) >> 8; am33xx_cpsw_slaves[0].mac_addr[2] = (mac_hi & 0xFF0000) >> 16; am33xx_cpsw_slaves[0].mac_addr[3] = (mac_hi & 0xFF000000) >> 24; am33xx_cpsw_slaves[0].mac_addr[4] = mac_lo & 0xFF; am33xx_cpsw_slaves[0].mac_addr[5] = (mac_lo & 0xFF00) >> 8; /* Read MACID0 from eeprom if eFuse MACID is invalid */ if (!is_valid_ether_addr(am33xx_cpsw_slaves[0].mac_addr)) { for (i = 0; i < ETH_ALEN; i++) am33xx_cpsw_slaves[0].mac_addr[i] = am33xx_macid0[i]; } mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_LO); mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_HI); am33xx_cpsw_slaves[1].mac_addr[0] = mac_hi & 0xFF; am33xx_cpsw_slaves[1].mac_addr[1] = (mac_hi & 0xFF00) >> 8; am33xx_cpsw_slaves[1].mac_addr[2] = (mac_hi & 0xFF0000) >> 16; am33xx_cpsw_slaves[1].mac_addr[3] = (mac_hi & 0xFF000000) >> 24; am33xx_cpsw_slaves[1].mac_addr[4] = mac_lo & 0xFF; am33xx_cpsw_slaves[1].mac_addr[5] = (mac_lo & 0xFF00) >> 8; /* Read MACID1 from eeprom if eFuse MACID is invalid */ if (!is_valid_ether_addr(am33xx_cpsw_slaves[1].mac_addr)) { for (i = 0; i < ETH_ALEN; i++) am33xx_cpsw_slaves[1].mac_addr[i] = am33xx_macid1[i]; } switch (mode) { case AM33XX_CPSW_MODE_MII: gmii_sel = AM33XX_MII_MODE_EN; break; case AM33XX_CPSW_MODE_RMII: gmii_sel = AM33XX_RMII_MODE_EN; break; case AM33XX_CPSW_MODE_RGMII: gmii_sel = AM33XX_RGMII_MODE_EN; am33xx_cpsw_slaves[0].phy_if = PHY_INTERFACE_MODE_RGMII; am33xx_cpsw_slaves[1].phy_if = PHY_INTERFACE_MODE_RGMII; break; case CALIXTO_EVM_ETHERNET_INTERFACE: gmii_sel = CALIXTO_EVM_ETHERNET_MODE_EN; break; default: return -EINVAL; } writel(gmii_sel, AM33XX_CTRL_REGADDR(AM33XX_CONTROL_GMII_SEL_OFFSET)); if (phy_id0 != NULL) am33xx_cpsw_slaves[0].phy_id = phy_id0; if (phy_id1 != NULL) am33xx_cpsw_slaves[1].phy_id = phy_id1; memcpy(am33xx_cpsw_pdata.mac_addr, am33xx_cpsw_slaves[0].mac_addr, ETH_ALEN); oh = omap_hwmod_lookup("mdio"); if (!oh) { pr_err("could not find cpgmac0 hwmod data\n"); return -ENODEV; } pdev = omap_device_build("davinci_mdio", 0, oh, &am33xx_cpsw_mdiopdata, sizeof(am33xx_cpsw_mdiopdata), NULL, 0, 0); if (IS_ERR(pdev)) pr_err("could not build omap_device for cpsw\n"); oh = omap_hwmod_lookup("cpgmac0"); if (!oh) { pr_err("could not find cpgmac0 hwmod data\n"); return -ENODEV; } pdev = omap_device_build("cpsw", -1, oh, &am33xx_cpsw_pdata, sizeof(am33xx_cpsw_pdata), NULL, 0, 0); if (IS_ERR(pdev)) pr_err("could not build omap_device for cpsw\n"); return 0; }
void __init omap_display_init(struct omap_dss_board_info *board_data) { struct omap_hwmod *oh; char oh_name_omap4[7][MAX_OMAP_DSS_HWMOD_NAME_LEN] = {"dss", "dss_dispc", "dss_dsi1", "dss_dsi2", "dss_hdmi", "dss_rfbi", "dss_venc"}; char oh_name_omap3[5][MAX_OMAP_DSS_HWMOD_NAME_LEN] = {"dss", "dss_dispc", "dss_dsi1", "dss_rfbi", "dss_venc" }; char (*oh_name)[MAX_OMAP_DSS_HWMOD_NAME_LEN]; int l, i, idx = 0, count = 0; struct omap_display_platform_data pdata; idx = 1; if (cpu_is_omap44xx()) { oh_name = &oh_name_omap4[0]; count = 7; } else { oh_name = &oh_name_omap3[0]; count = 5; } for (i = 0; i < count; i++) { l = snprintf(oh_name[i], MAX_OMAP_DSS_HWMOD_NAME_LEN, oh_name[i]); WARN(l >= MAX_OMAP_DSS_HWMOD_NAME_LEN, "String buffer overflow in DSS device setup\n"); oh = omap_hwmod_lookup(oh_name[i]); if (!oh) { pr_err("Could not look up %s\n", oh_name[i]); return; } strcpy(pdata.name, oh_name[i]); pdata.hwmod_count = 2; pdata.board_data = board_data; pdata.board_data->get_last_off_on_transaction_id = NULL; pdata.device_enable = omap_device_enable; pdata.device_idle = omap_device_idle; pdata.device_shutdown = omap_device_shutdown; od = omap_device_build(oh_name[i], -1, oh, &pdata, sizeof(struct omap_display_platform_data), omap_dss_latency, ARRAY_SIZE(omap_dss_latency), 0); WARN((IS_ERR(od)), "Could not build omap_device for %s %s\n", dssname, oh_name[i]); } omap_display_device.dev.platform_data = board_data; if (platform_device_register(&omap_display_device) < 0) printk(KERN_ERR "Unable to register OMAP-Display device\n"); return; }