/* CPU table initialization */ static int __init rm696_opp_init(void) { int r = 0; struct device *mpu_dev; r = omap3_opp_init(); if (IS_ERR_VALUE(r) && (r != -EEXIST)) { pr_err("opp default init failed\n"); return r; } mpu_dev = omap_device_get_by_hwmod_name("mpu"); if (IS_ERR(mpu_dev)) { pr_err("no mpu_dev error\n"); return -ENODEV; } /* Enable MPU 800MHz and lower opps */ r = opp_enable(mpu_dev, 800000000); if (r) pr_err("failed to enable higher (800MHz) opp\n"); /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 1000000000); if (r) pr_err("failed to enable higher (1GHz) opp\n"); return 0; }
static void __init overo_opp_init(void) { int r = 0; /* Initialize the omap3 opp table */ if (omap3_opp_init()) { pr_err("%s: opp default init failed\n", __func__); return; } /* Custom OPP enabled for 36/3730 */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; mpu_dev = omap_device_get_by_hwmod_name("mpu"); if (omap3_has_iva()) iva_dev = omap_device_get_by_hwmod_name("iva"); if (!mpu_dev) { pr_err("%s: Aiee.. no mpu device? %p\n", __func__, mpu_dev); return; } /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 800000000); r |= opp_enable(mpu_dev, 1000000000); if (omap3_has_iva()) { /* Enable IVA 800MHz and lower opps */ r |= opp_enable(iva_dev, 660000000); r |= opp_enable(iva_dev, 800000000); } if (r) { pr_err("%s: failed to enable higher opp %d\n", __func__, r); opp_disable(mpu_dev, 800000000); opp_disable(mpu_dev, 1000000000); if (omap3_has_iva()) { opp_disable(iva_dev, 660000000); opp_disable(iva_dev, 800000000); } } } return; }
/* * This API is to be called during init to set 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 sets the voltage domain to the voltage specified * in the opp entry */ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, const char *oh_name) { struct voltagedomain *voltdm; struct clk *clk; struct opp *opp; unsigned long freq, bootup_volt; struct device *dev; if (!vdd_name || !clk_name || !oh_name) { pr_err("%s: invalid parameters\n", __func__); goto exit; } dev = omap_device_get_by_hwmod_name(oh_name); if (IS_ERR(dev)) { pr_err("%s: Unable to get dev pointer for hwmod %s\n", __func__, oh_name); goto exit; } voltdm = voltdm_lookup(vdd_name); if (IS_ERR(voltdm)) { pr_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)) { pr_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)) { pr_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) { pr_err("%s: unable to find voltage corresponding " "to the bootup OPP for vdd_%s\n", __func__, vdd_name); goto exit; } voltdm_scale(voltdm, bootup_volt); return 0; exit: pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name); return -EINVAL; }
static int __init am33xx_pm_init(void) { int ret; if (!cpu_is_am33xx()) return -ENODEV; pr_info("Power Management for AM33XX family\n"); #ifdef CONFIG_SUSPEND #ifdef CONFIG_TI_PM_DISABLE_VT_SWITCH pm_set_vt_switch(0); #endif (void) clkdm_for_each(clkdms_setup, NULL); /* CEFUSE domain should be turned off post bootup */ cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm"); if (cefuse_pwrdm == NULL) printk(KERN_ERR "Failed to get cefuse_pwrdm\n"); else pwrdm_set_next_pwrst(cefuse_pwrdm, PWRDM_POWER_OFF); gfx_pwrdm = pwrdm_lookup("gfx_pwrdm"); if (gfx_pwrdm == NULL) printk(KERN_ERR "Failed to get gfx_pwrdm\n"); gfx_l3_clkdm = clkdm_lookup("gfx_l3_clkdm"); if (gfx_l3_clkdm == NULL) printk(KERN_ERR "Failed to get gfx_l3_clkdm\n"); gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm"); if (gfx_l4ls_clkdm == NULL) printk(KERN_ERR "Failed to get gfx_l4ls_gfx_clkdm\n"); mpu_dev = omap_device_get_by_hwmod_name("mpu"); if (!mpu_dev) { pr_warning("%s: unable to get the mpu device\n", __func__); return -EINVAL; } ret = wkup_m3_init(); if (ret) { pr_err("Could not initialise WKUP_M3. " "Power management will be compromised\n"); enable_deep_sleep = false; } if (enable_deep_sleep) suspend_set_ops(&am33xx_pm_ops); #endif /* CONFIG_SUSPEND */ return ret; }
static int __init am33xx_setup_sleep_sequence(void) { int ret; int sz; const void *prop; struct device *dev; u32 freq_hz = 100000; unsigned short freq_khz; /* * We put the device tree node in the I2C controller that will * be sending the sequence. i2c1 is the only controller that can * be accessed by the firmware as it is the only controller in the * WKUP domain. */ dev = omap_device_get_by_hwmod_name("i2c1"); if (IS_ERR(dev)) return PTR_ERR(dev); of_property_read_u32(dev->of_node, "clock-frequency", &freq_hz); freq_khz = freq_hz / 1000; prop = of_get_property(dev->of_node, "sleep-sequence", &sz); if (prop) { /* * Length is sequence length + 2 bytes for freq_khz, and 1 * byte for terminator. */ am33xx_i2c_sleep_sequence = kzalloc(sz + 3, GFP_KERNEL); if (!am33xx_i2c_sleep_sequence) return -ENOMEM; put_unaligned_le16(freq_khz, am33xx_i2c_sleep_sequence); memcpy(am33xx_i2c_sleep_sequence + 2, prop, sz); i2c_sleep_sequence_sz = sz + 3; } prop = of_get_property(dev->of_node, "wake-sequence", &sz); if (prop) { am33xx_i2c_wake_sequence = kzalloc(sz + 3, GFP_KERNEL); if (!am33xx_i2c_wake_sequence) { ret = -ENOMEM; goto cleanup_sleep; } put_unaligned_le16(freq_khz, am33xx_i2c_wake_sequence); memcpy(am33xx_i2c_wake_sequence + 2, prop, sz); i2c_wake_sequence_sz = sz + 3; } return 0; cleanup_sleep: kfree(am33xx_i2c_sleep_sequence); am33xx_i2c_sleep_sequence = NULL; return ret; }
static void __init beagle_opp_init(void) { int r = 0; /* Initialize the omap3 opp table */ if (omap3_opp_init()) { pr_err("%s: opp default init failed\n", __func__); return; } /* Custom OPP enabled for all xM versions */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; mpu_dev = omap_device_get_by_hwmod_name("mpu"); iva_dev = omap_device_get_by_hwmod_name("iva"); if (!mpu_dev || !iva_dev) { pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", __func__, mpu_dev, iva_dev); return; } /* Enable MPU 1GHz and lower opps */ r = opp_enable(mpu_dev, 800000000); /* TODO: MPU 1GHz needs SR and ABB */ /* Enable IVA 800MHz and lower opps */ r |= opp_enable(iva_dev, 660000000); /* TODO: DSP 800MHz needs SR and ABB */ if (r) { pr_err("%s: failed to enable higher opp %d\n", __func__, r); /* * Cleanup - disable the higher freqs - we dont care * about the results */ opp_disable(mpu_dev, 800000000); opp_disable(iva_dev, 660000000); } } return; }
static int __init beagle_opp_init(void) { int r = 0; if (!machine_is_omap3_beagle()) return 0; /* Initialize the omap3 opp table if not already created. */ r = omap3_opp_init(); if (r < 0 && (r != -EEXIST)) { pr_err("%s: opp default init failed\n", __func__); return r; } /* Custom OPP enabled for all xM versions */ if (cpu_is_omap3630()) { struct device *mpu_dev, *iva_dev; mpu_dev = get_cpu_device(0); iva_dev = omap_device_get_by_hwmod_name("iva"); if (!mpu_dev || IS_ERR(iva_dev)) { pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n", __func__, mpu_dev, iva_dev); return -ENODEV; } /* Enable MPU 1GHz and lower opps */ r = dev_pm_opp_enable(mpu_dev, 800000000); /* TODO: MPU 1GHz needs SR and ABB */ /* Enable IVA 800MHz and lower opps */ r |= dev_pm_opp_enable(iva_dev, 660000000); /* TODO: DSP 800MHz needs SR and ABB */ if (r) { pr_err("%s: failed to enable higher opp %d\n", __func__, r); /* * Cleanup - disable the higher freqs - we dont care * about the results */ dev_pm_opp_disable(mpu_dev, 800000000); dev_pm_opp_disable(iva_dev, 660000000); } } return 0; }
static int _omap_mstandby_pm_notifier(struct notifier_block *self, unsigned long action, void *dev) { struct omap_hwmod_list *oh_list_item = NULL; struct platform_device *pdev; struct omap_device *od; switch (action) { case PM_POST_SUSPEND: list_for_each_entry(oh_list_item, omap_hwmod_force_mstandby_list_get(), oh_list) { pdev = to_platform_device( omap_device_get_by_hwmod_name( oh_list_item->oh->name)); od = to_omap_device(pdev); if (od && od->_driver_status != BUS_NOTIFY_BOUND_DRIVER) { omap_hwmod_enable(oh_list_item->oh); omap_hwmod_idle(oh_list_item->oh); } } }
int am33x_mpu_voltdm_init(struct voltagedomain *voltdm) { struct regulator *mpu_regulator; struct device *mpu_dev; mpu_dev = omap_device_get_by_hwmod_name("mpu"); if (!mpu_dev) { pr_warning("%s: unable to get the mpu device\n", __func__); return -EINVAL; } mpu_regulator = regulator_get(mpu_dev, voltdm->name); if (IS_ERR(mpu_regulator)) { pr_err("%s: Could not get regulator for %s\n", __func__, voltdm->name); return -ENODEV; } else { voltdm->regulator = mpu_regulator; voltdm->scale = &am33x_mpu_voltdm_scale; } return 0; }
/* * This API is to be called during init to set 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 sets the voltage domain to the voltage specified * in the opp entry */ static int __init omap2_set_init_voltage(char *vdd_name, char *clk_name, const char *oh_name) { struct voltagedomain *voltdm; struct clk *clk; struct opp *opp; struct device *dev; unsigned long freq_cur, freq_valid, bootup_volt; int ret = -EINVAL; dev = omap_device_get_by_hwmod_name(oh_name); if (IS_ERR(dev)) { pr_err("%s: Unable to get dev pointer for hwmod %s\n", __func__, oh_name); goto exit; } voltdm = voltdm_lookup(vdd_name); if (IS_ERR(voltdm)) { pr_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)) { pr_err("%s: unable to get clk %s\n", __func__, clk_name); goto exit; } freq_cur = clk->rate; freq_valid = freq_cur; rcu_read_lock(); opp = opp_find_freq_ceil(dev, &freq_valid); if (IS_ERR(opp)) { opp = opp_find_freq_floor(dev, &freq_valid); if (IS_ERR(opp)) { rcu_read_unlock(); pr_err("%s: no boot OPP match for %ld on vdd_%s\n", __func__, freq_cur, vdd_name); ret = -ENOENT; goto exit_ck; } } bootup_volt = opp_get_voltage(opp); rcu_read_unlock(); if (!bootup_volt) { pr_err("%s: unable to find voltage corresponding " "to the bootup OPP for vdd_%s\n", __func__, vdd_name); ret = -ENOENT; goto exit_ck; } /* * Frequency and Voltage have to be sequenced: if we move from * a lower frequency to higher frequency, raise voltage, followed by * frequency, and vice versa. we assume that the voltage at boot * is the required voltage for the frequency it was set for. * NOTE: * we can check the frequency, but there is numerous ways to set * voltage. We play the safe path and just set the voltage. */ if (freq_cur < freq_valid) { ret = voltdm_scale(voltdm, bootup_volt); if (ret) { pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", __func__, vdd_name, freq_valid, bootup_volt, vdd_name); goto exit_ck; } } /* Set freq only if there is a difference in freq */ if (freq_valid != freq_cur) { ret = clk_set_rate(clk, freq_valid); if (ret) { pr_err("%s: Fail set clk-%s(f=%ld v=%ld)on vdd%s\n", __func__, clk_name, freq_valid, bootup_volt, vdd_name); goto exit_ck; } } if (freq_cur >= freq_valid) { ret = voltdm_scale(voltdm, bootup_volt); if (ret) { pr_err("%s: Fail set voltage-%s(f=%ld v=%ld)on vdd%s\n", __func__, clk_name, freq_valid, bootup_volt, vdd_name); goto exit_ck; } } ret = 0; exit_ck: clk_put(clk); if (!ret) return 0; exit: pr_err("%s: unable to set vdd_%s\n", __func__, vdd_name); return -EINVAL; }
static int __init am33xx_pm_init(void) { int ret; #ifdef CONFIG_SUSPEND void __iomem *base; u32 reg; u32 evm_id; #endif if (!cpu_is_am33xx()) return -ENODEV; pr_info("Power Management for AM33XX family\n"); #ifdef CONFIG_SUSPEND #ifdef CONFIG_TI_PM_DISABLE_VT_SWITCH pm_set_vt_switch(0); #endif /* Read SDRAM_CONFIG register to determine Memory Type */ base = am33xx_get_ram_base(); reg = readl(base + EMIF4_0_SDRAM_CONFIG); reg = (reg & SDRAM_TYPE_MASK) >> SDRAM_TYPE_SHIFT; suspend_cfg_param_list[MEMORY_TYPE] = reg; /* * vtp_ctrl register value for DDR2 and DDR3 as suggested * by h/w team */ if (reg == MEM_TYPE_DDR2) suspend_cfg_param_list[SUSP_VTP_CTRL_VAL] = SUSP_VTP_CTRL_DDR2; else suspend_cfg_param_list[SUSP_VTP_CTRL_VAL] = SUSP_VTP_CTRL_DDR3; /* Get Board Id */ evm_id = am335x_evm_get_id(); if (evm_id != -EINVAL) suspend_cfg_param_list[EVM_ID] = evm_id; else suspend_cfg_param_list[EVM_ID] = 0xff; /* CPU Revision */ reg = omap_rev(); if (reg == AM335X_REV_ES2_0) suspend_cfg_param_list[CPU_REV] = CPU_REV_2; else suspend_cfg_param_list[CPU_REV] = CPU_REV_1; (void) clkdm_for_each(clkdms_setup, NULL); /* CEFUSE domain should be turned off post bootup */ cefuse_pwrdm = pwrdm_lookup("cefuse_pwrdm"); if (cefuse_pwrdm == NULL) pr_err("Failed to get cefuse_pwrdm\n"); else pwrdm_set_next_pwrst(cefuse_pwrdm, PWRDM_POWER_OFF); gfx_pwrdm = pwrdm_lookup("gfx_pwrdm"); if (gfx_pwrdm == NULL) pr_err("Failed to get gfx_pwrdm\n"); per_pwrdm = pwrdm_lookup("per_pwrdm"); if (per_pwrdm == NULL) pr_err("Failed to get per_pwrdm\n"); gfx_l3_clkdm = clkdm_lookup("gfx_l3_clkdm"); if (gfx_l3_clkdm == NULL) pr_err("Failed to get gfx_l3_clkdm\n"); gfx_l4ls_clkdm = clkdm_lookup("gfx_l4ls_gfx_clkdm"); if (gfx_l4ls_clkdm == NULL) pr_err("Failed to get gfx_l4ls_gfx_clkdm\n"); mpu_dev = omap_device_get_by_hwmod_name("mpu"); if (!mpu_dev) { pr_warning("%s: unable to get the mpu device\n", __func__); return -EINVAL; } ret = wkup_m3_init(); if (ret) { pr_err("Could not initialise WKUP_M3. " "Power management will be compromised\n"); enable_deep_sleep = false; } if (enable_deep_sleep) suspend_set_ops(&am33xx_pm_ops); #endif /* CONFIG_SUSPEND */ return ret; }