int __init omap3_twl_init(void) { struct voltagedomain *voltdm; if (!cpu_is_omap34xx()) return -ENODEV; if (cpu_is_omap3630()) { omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; } /* * The smartreflex bit on twl4030 specifies if the setting of voltage * is done over the I2C_SR path. Since this setting is independent of * the actual usage of smartreflex AVS module, we enable TWL SR bit * by default irrespective of whether smartreflex AVS module is enabled * on the OMAP side or not. This is because without this bit enabled, * the voltage scaling through vp forceupdate/bypass mechanism of * voltage scaling will not function on TWL over I2C_SR. */ if (!twl_sr_enable_autoinit) omap3_twl_set_sr_bit(true); voltdm = omap_voltage_domain_lookup("mpu"); omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); voltdm = omap_voltage_domain_lookup("core"); omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); return 0; }
int __init omap4_twl_init(void) { struct voltagedomain *voltdm; if (!cpu_is_omap44xx()) return -ENODEV; voltdm = omap_voltage_domain_lookup("mpu"); omap_voltage_register_pmic(voltdm, &omap4_mpu_volt_info); voltdm = omap_voltage_domain_lookup("iva"); omap_voltage_register_pmic(voltdm, &omap4_iva_volt_info); voltdm = omap_voltage_domain_lookup("core"); omap_voltage_register_pmic(voltdm, &omap4_core_volt_info); return 0; }
static int sr_dev_init(struct omap_hwmod *oh, void *user) { struct omap_sr_data *sr_data; struct omap_device *od; struct omap_volt_data *volt_data; char *name = "smartreflex"; static int i; sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL); if (!sr_data) { pr_err("%s: Unable to allocate memory for %s sr_data.Error!\n", __func__, oh->name); return -ENOMEM; } if (!oh->vdd_name) { pr_err("%s: No voltage domain specified for %s." "Cannot initialize\n", __func__, oh->name); goto exit; } sr_data->ip_type = oh->class->rev; sr_data->senn_mod = 0x1; sr_data->senp_mod = 0x1; sr_data->voltdm = omap_voltage_domain_lookup(oh->vdd_name); if (IS_ERR(sr_data->voltdm)) { pr_err("%s: Unable to get voltage domain pointer for VDD %s\n", __func__, oh->vdd_name); goto exit; } omap_voltage_get_volttable(sr_data->voltdm, &volt_data); if (!volt_data) { pr_warning("%s: No Voltage table registerd fo VDD%d." "Something really wrong\n\n", __func__, i + 1); goto exit; } sr_set_nvalues(volt_data, sr_data); sr_data->enable_on_init = sr_enable_on_init; od = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data), omap_sr_latency, ARRAY_SIZE(omap_sr_latency), 0); if (IS_ERR(od)) pr_warning("%s: Could not build omap_device for %s: %s.\n\n", __func__, name, oh->name); exit: i++; kfree(sr_data); return 0; }
int __init omap3_twl_init(void) { struct voltagedomain *voltdm; if (!cpu_is_omap34xx()) return -ENODEV; /* * In case of AM3517/AM3505 we should not be going down * further, since SR is not applicable there. */ if (cpu_is_omap3505() || cpu_is_omap3517()) return -ENODEV; if (cpu_is_omap3630()) { omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; } /* * The smartreflex bit on twl4030 needs to be enabled by * default irrespective of whether smartreflex module is * enabled on the OMAP side or not. This is because without * this bit enabled the voltage scaling through * vp forceupdate does not function properly on OMAP3. */ if (twl_sr_enable) omap3_twl_set_sr_bit(1); voltdm = omap_voltage_domain_lookup("mpu"); omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); voltdm = omap_voltage_domain_lookup("core"); omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); return 0; }
/* * This API is to be called during init to put the various voltage * domains to the voltage as per the opp table. Typically we boot up * at the nominal voltage. So this function finds out the rate of * the clock associated with the voltage domain, finds out the correct * opp entry and puts the voltage domain to the voltage specifies * in the opp entry */ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, struct device *dev) { struct voltagedomain *voltdm; struct clk *clk; struct opp *opp; unsigned long freq, bootup_volt; if (!vdd_name || !clk_name || !dev) { printk(KERN_ERR "%s: Invalid parameters!\n", __func__); goto exit; } voltdm = omap_voltage_domain_lookup(vdd_name); if (IS_ERR(voltdm)) { printk(KERN_ERR "%s: Unable to get vdd pointer for vdd_%s\n", __func__, vdd_name); goto exit; } clk = clk_get(NULL, clk_name); if (IS_ERR(clk)) { printk(KERN_ERR "%s: unable to get clk %s\n", __func__, clk_name); goto exit; } freq = clk->rate; clk_put(clk); opp = opp_find_freq_ceil(dev, &freq); if (IS_ERR(opp)) { printk(KERN_ERR "%s: unable to find boot up OPP for vdd_%s\n", __func__, vdd_name); goto exit; } bootup_volt = opp_get_voltage(opp); if (!bootup_volt) { printk(KERN_ERR "%s: unable to find voltage corresponding" "to the bootup OPP for vdd_%s\n", __func__, vdd_name); goto exit; } omap_voltage_scale_vdd(voltdm, bootup_volt); return 0; exit: printk(KERN_ERR "%s: Unable to put vdd_%s to its init voltage\n\n", __func__, vdd_name); return -EINVAL; }
int __init omap3_twl_init(void) { struct voltagedomain *voltdm; if (!cpu_is_omap34xx()) return -ENODEV; if (cpu_is_omap3630()) { omap3_mpu_volt_info.vp_vddmin = OMAP3630_VP1_VLIMITTO_VDDMIN; omap3_mpu_volt_info.vp_vddmax = OMAP3630_VP1_VLIMITTO_VDDMAX; omap3_core_volt_info.vp_vddmin = OMAP3630_VP2_VLIMITTO_VDDMIN; omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX; } voltdm = omap_voltage_domain_lookup("mpu"); omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info); voltdm = omap_voltage_domain_lookup("core"); omap_voltage_register_pmic(voltdm, &omap3_core_volt_info); return 0; }
/** * omap_device_build_ss - build and register 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 * @pm_lats: pointer to a omap_device_pm_latency array for this device * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats * @is_early_device: should the device be registered as an early device or not * * Convenience function for building and registering an omap_device * subsystem record. Subsystem records consist of multiple * omap_hwmods. This function in turn builds and registers a * platform_device record. Returns an ERR_PTR() on error, or passes * along the return value of omap_device_register(). */ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id, struct omap_hwmod **ohs, int oh_cnt, void *pdata, int pdata_len, struct omap_device_pm_latency *pm_lats, int pm_lats_cnt, int is_early_device) { int ret = -ENOMEM; struct omap_device *od; char *pdev_name2; struct resource *res = NULL; int i, res_count; struct omap_hwmod **hwmods; if (!ohs || oh_cnt == 0 || !pdev_name) return ERR_PTR(-EINVAL); if (!pdata && pdata_len > 0) return ERR_PTR(-EINVAL); pr_debug("omap_device: %s: building with %d hwmods\n", pdev_name, oh_cnt); od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); if (!od) return ERR_PTR(-ENOMEM); od->hwmods_cnt = oh_cnt; hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); if (!hwmods) goto odbs_exit1; memcpy(hwmods, ohs, sizeof(struct omap_hwmod *) * oh_cnt); od->hwmods = hwmods; pdev_name2 = kzalloc(strlen(pdev_name) + 1, GFP_KERNEL); if (!pdev_name2) goto odbs_exit2; strcpy(pdev_name2, pdev_name); od->pdev.name = pdev_name2; od->pdev.id = pdev_id; res_count = omap_device_count_resources(od); if (res_count > 0) { res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); if (!res) goto odbs_exit3; } omap_device_fill_resources(od, res); od->pdev.num_resources = res_count; od->pdev.resource = res; ret = platform_device_add_data(&od->pdev, pdata, pdata_len); if (ret) goto odbs_exit4; od->pm_lats = pm_lats; od->pm_lats_cnt = pm_lats_cnt; if (is_early_device) ret = omap_early_device_register(od); else ret = omap_device_register(od); for (i = 0; i < oh_cnt; i++) { hwmods[i]->od = od; _add_optional_clock_alias(od, hwmods[i]); if (hwmods[i]->vdd_name) { struct omap_hwmod *oh = hwmods[i]; struct voltagedomain *voltdm; if (is_early_device) continue; voltdm = omap_voltage_domain_lookup(oh->vdd_name); if (!omap_voltage_add_dev(voltdm, &od->pdev.dev)) oh->voltdm = voltdm; } } if (ret) goto odbs_exit4; return od; odbs_exit4: kfree(res); odbs_exit3: kfree(pdev_name2); odbs_exit2: kfree(hwmods); odbs_exit1: kfree(od); pr_err("omap_device: %s: build failed (%d)\n", pdev_name, ret); return ERR_PTR(ret); }