/* vdd_core must be >= min_level as a function of vdd_cpu */ static int tegra3_dvfs_rel_vdd_cpu_vdd_core(struct dvfs_rail *vdd_cpu, struct dvfs_rail *vdd_core) { int core_floor = max(vdd_cpu->new_millivolts, vdd_cpu->millivolts); core_floor = tegra3_get_core_floor_mv(core_floor); return max(vdd_core->new_millivolts, core_floor); }
static int __init get_cpu_nominal_mv_index( int speedo_id, int process_id, struct dvfs **cpu_dvfs) { int i, j, mv; struct dvfs *d; struct clk *c; /* * Start with nominal level for the chips with this speedo_id. Then, * make sure cpu nominal voltage is below core ("solve from cpu to * core at nominal"). */ BUG_ON(speedo_id >= ARRAY_SIZE(cpu_speedo_nominal_millivolts)); mv = cpu_speedo_nominal_millivolts[speedo_id]; if (tegra3_dvfs_rail_vdd_core.nominal_millivolts) { int core_mv = tegra3_dvfs_rail_vdd_core.nominal_millivolts; while ((mv > tegra3_dvfs_rail_vdd_cpu.min_millivolts) && (tegra3_get_core_floor_mv(mv) > core_mv)) mv -= 25; } /* * Find matching cpu dvfs entry, and use it to determine index to the * final nominal voltage, that satisfies the following requirements: * - allows CPU to run at minimum of the maximum rates specified in * the dvfs entry and clock tree * - does not violate cpu_to_core dependency as determined above */ for (i = 0, j = 0; j < ARRAY_SIZE(cpu_dvfs_table); j++) { d = &cpu_dvfs_table[j]; if (match_dvfs_one(d, speedo_id, process_id)) { c = tegra_get_clock_by_name(d->clk_name); BUG_ON(!c); for (; i < MAX_DVFS_FREQS; i++) { if ((d->freqs[i] == 0) || (cpu_millivolts[i] == 0) || (mv < cpu_millivolts[i])) break; if (c->max_rate <= d->freqs[i]*d->freqs_mult) { i++; break; } } break; } } BUG_ON(i == 0); if (j == (ARRAY_SIZE(cpu_dvfs_table) - 1)) pr_err("tegra3_dvfs: WARNING!!!\n" "tegra3_dvfs: no cpu dvfs table found for chip speedo_id" " %d and process_id %d: set CPU rate limit at %lu\n" "tegra3_dvfs: WARNING!!!\n", speedo_id, process_id, d->freqs[i-1] * d->freqs_mult); *cpu_dvfs = d; return (i - 1); }
int tegra_dvfs_rail_post_enable(struct dvfs_rail *rail) { if (tegra_emc_get_dram_type() != DRAM_TYPE_DDR3) return 0; if (((&tegra3_dvfs_rail_vdd_core == rail) && (rail->nominal_millivolts > TEGRA_EMC_BRIDGE_MVOLTS_MIN)) || ((&tegra3_dvfs_rail_vdd_cpu == rail) && (tegra3_get_core_floor_mv(rail->nominal_millivolts) > TEGRA_EMC_BRIDGE_MVOLTS_MIN))) { struct clk *bridge = tegra_get_clock_by_name("bridge.emc"); BUG_ON(!bridge); clk_disable(bridge); pr_info("%s: %s: disabled bridge.emc\n", __func__, rail->reg_id); } return 0; }
static int __init get_cpu_nominal_mv_index( int speedo_id, int process_id, struct dvfs **cpu_dvfs) { int i, j, mv, nom_index; struct dvfs *d; struct clk *c; /* * Find maximum cpu voltage that satisfies cpu_to_core dependency for * nominal core voltage ("solve from cpu to core at nominal"). Clip * result to the nominal cpu level for the chips with this speedo_id. */ mv = tegra3_dvfs_rail_vdd_core.nominal_millivolts; for (i = 0; i < MAX_DVFS_FREQS; i++) { if ((cpu_millivolts[i] == 0) || tegra3_get_core_floor_mv(cpu_millivolts[i]) > mv) break; } BUG_ON(i == 0); mv = cpu_millivolts[i - 1]; pr_info("cpu_nominal_mv: %i\n", mv); BUG_ON(mv < tegra3_dvfs_rail_vdd_cpu.min_millivolts); mv = min(mv, tegra_cpu_speedo_mv()); pr_info("cpu_nominal_mv_min: %i\n", mv); /* * Find matching cpu dvfs entry, and use it to determine index to the * final nominal voltage, that satisfies the following requirements: * - allows CPU to run at minimum of the maximum rates specified in * the dvfs entry and clock tree * - does not violate cpu_to_core dependency as determined above */ for (i = 0, j = 0; j < ARRAY_SIZE(cpu_dvfs_table); j++) { d = &cpu_dvfs_table[j]; if (match_dvfs_one(d, speedo_id, process_id)) { c = tegra_get_clock_by_name(d->clk_name); BUG_ON(!c); for (; i < MAX_DVFS_FREQS; i++) { if ((d->freqs[i] == 0) || (cpu_millivolts[i] == 0) || (mv < cpu_millivolts[i])) break; if (c->max_rate <= d->freqs[i]*d->freqs_mult) { i++; break; } } break; } } pr_info("dvfs: freqs_mult: %i\n", d->freqs_mult); BUG_ON(i == 0); if (j == (ARRAY_SIZE(cpu_dvfs_table) - 1)) pr_err("tegra3_dvfs: WARNING!!!\n" "tegra3_dvfs: no cpu dvfs table found for chip speedo_id" " %d and process_id %d: set CPU rate limit at %lu\n" "tegra3_dvfs: WARNING!!!\n", speedo_id, process_id, d->freqs[i-1] * d->freqs_mult); *cpu_dvfs = d; nom_index = i - 1; pr_info("cpu_nominal_mv_index: %i\n", nom_index); pr_info("cpu_dvfs->speedo_id: %i\n", d->speedo_id); pr_info("cpu_dvfs->process_id: %i\n", d->process_id); for (i=0;i<MAX_DVFS_FREQS;i++) { pr_info("cpu_dvfs->freqs: %lu\n", d->freqs[i]); } return nom_index; }