/** * resource_test_2 - Tests resource framework APIs when two devices requests * the same "opp/freq" resource for same or different levels * @res_name: Name of the resource requested * @req_lvl1: Device 1 level requested for the resource * @req_lvl2: Device 2 level requested for the resource * * Two devices requests the "opp/freq" resource for the specified levels, * verifies if the resource's current level is same as the maximum of * requested levels and releases the resource * * Returns 0 on success, -1 on failure */ static int resource_test_2(const char *res_name, unsigned long req_lvl1, unsigned long req_lvl2) { int ret, result = TEST_PASS; int cur_lvl, req_lvl; struct device dev1, dev2; printk(KERN_INFO "Entry resource_test_2 \n"); if (!strcmp(res_name, "vdd2_opp")) ret = request_vdd2_opp(&dev1, req_lvl1); else ret = resource_request(res_name, &dev1, req_lvl1); if (ret) { printk(KERN_ERR "FAILED!!!! dev1 resource request for %s failed" " with value %d\n", res_name, ret); return TEST_FAIL; } if (!strcmp(res_name, "vdd2_opp")) ret = request_vdd2_opp(&dev2, req_lvl2); else ret = resource_request(res_name, &dev2, req_lvl2); if (ret) { printk(KERN_ERR "FAILED!!!! dev2 resource request for %s failed" " with value %d\n", res_name, ret); resource_release(res_name, &dev1); return TEST_FAIL; } cur_lvl = resource_get_level(res_name); req_lvl = (int) max_level(req_lvl1, req_lvl2); if (cur_lvl != req_lvl) { printk(KERN_ERR "FAILED!!!! resource %s current level:%d" " req lvl:%d\n", res_name, cur_lvl, req_lvl); result = TEST_FAIL; } ret = resource_release(res_name, &dev1); if (ret) { printk(KERN_ERR "FAILED!!!! dev1 resource release for %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } ret = resource_release(res_name, &dev2); if (ret) { printk(KERN_ERR "FAILED!!!! dev2 resource release for %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } if (!result) printk(KERN_INFO "resource_test_2 PASSED for %s\n", res_name); return result; }
void omap_pm_vdd1_set_max_opp(struct device *dev, u8 opp_id) { pr_debug("OMAP PM: requests constraint for max OPP ID\n"); if (opp_id != 0) resource_request("vdd1_max", dev, opp_id); else resource_request("vdd1_max", dev, MAX_VDD1_OPP); }
static void batt_changed(struct power_supply *batt, struct cpcap_batt_data *batt_state) { static char requested; int ret = 0; if (!batt || !batt_state) return; if (batt_state->batt_temp < 0) { /* To reduce OMAP Vdd1 DC/DC converter output voltage dips as * much as possible, limit Vdd1 to OPP3-OPP5 when the * temperature is below 0 degrees C. */ if (!requested) ret = resource_request("vdd1_opp", batt->dev, VDD1_OPP3); if (!ret) requested = 1; } else if (requested) { ret = resource_release("vdd1_opp", batt->dev); if (!ret) requested = 0; } }
static void ac_changed(struct power_supply *ac, struct cpcap_batt_ac_data *ac_state) { static char requested; int ret = 0; if (!ac || !ac_state) return; if (ac_state->online) { /* To reduce OMAP Vdd1 DC/DC converter output voltage dips as * much as possible, limit Vdd1 to OPP3-OPP5 when the phone is * connected to a charger. */ if (!requested) ret = resource_request("vdd1_opp", ac->dev, VDD1_OPP3); if (!ret) requested = 1; } else if (requested) { ret = resource_release("vdd1_opp", ac->dev); if (!ret) requested = 0; } }
/** * request_vdd2_opp - resource_request done for vdd2_opp resource * @dev: device address * @req_lvl: required level * * does a resource_request for vdd2_opp resource by giving the required * throughput input parameter * * Returns TEST_FAIL during failure or return values of resource_request */ static int request_vdd2_opp(struct device *dev, unsigned long req_lvl) { int ret; switch (req_lvl) { case VDD2_OPP2: ret = resource_request("vdd2_opp", dev, VDD2_LEVEL2_THROUGHPUT); break; case VDD2_OPP3: ret = resource_request("vdd2_opp", dev, VDD2_LEVEL3_THROUGHPUT); break; default: printk(KERN_ERR "FAILED!!!! invalid vdd2_opp level\n"); ret = TEST_FAIL; } return ret; }
void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t) { struct omapdev *odev; struct powerdomain *pwrdm_dev; struct platform_device *pdev; char *lat_res_name; if (!dev || t < -1) { WARN_ON(1); return; }; /* Look for the devices Power Domain */ /* * WARNING! If device is not a platform device, container_of will * return a pointer to unknown memory! * TODO: Either change omap-pm interface to support only platform * devices, or change the underlying omapdev implementation to * support normal devices. */ pdev = container_of(dev, struct platform_device, dev); /* Try to catch non platform devices. */ if (pdev->name == NULL) { printk(KERN_ERR "OMAP-PM: Error: platform device not valid\n"); return; } odev = omapdev_find_pdev(pdev); if (odev) { pwrdm_dev = omapdev_get_pwrdm(odev); } else { printk(KERN_ERR "OMAP-PM: Error: Could not find omapdev " "for %s\n", pdev->name); return; } lat_res_name = kmalloc(MAX_LATENCY_RES_NAME, GFP_KERNEL); if (!lat_res_name) { printk(KERN_ERR "OMAP-PM: FATAL ERROR: kmalloc failed\n"); return; } get_lat_res_name(pwrdm_dev->name, &lat_res_name, MAX_LATENCY_RES_NAME); if (t == -1) { pr_debug("OMAP PM: remove max device latency constraint: " "dev %s\n", dev_name(dev)); resource_release(lat_res_name, dev); } else { pr_debug("OMAP PM: add max device latency constraint: " "dev %s, t = %ld usec\n", dev_name(dev), t); resource_request(lat_res_name, dev, t); } kfree(lat_res_name); return; }
void omap_pm_cpu_set_freq(unsigned long f) { if (f == 0) { WARN_ON(1); return; } pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", f); resource_request("mpu_freq", &dummy_cpufreq_dev, f); return; }
void omap_pm_set_min_mpu_freq(struct device *dev, unsigned long f) { if (f == 0) { WARN_ON(1); return; } pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n", f); resource_request("mpu_freq", dev, f); return; }
static int hsmmc2_set_power(struct device *dev, int slot, int power_on, int vdd) { u32 vdd_sel = 0, devconf = 0; int ret = 0; if (power_on) { if (cpu_is_omap24xx()) devconf = omap_readl(OMAP2_CONTROL_DEVCONF1); else devconf = omap_readl(OMAP3_CONTROL_DEVCONF1); switch (1 << vdd) { case MMC_VDD_33_34: case MMC_VDD_32_33: vdd_sel = VSEL_3V; if (cpu_is_omap24xx()) devconf = (devconf | (1 << 31)); break; case MMC_VDD_165_195: vdd_sel = VSEL_18V; if (cpu_is_omap24xx()) devconf = (devconf & ~(1 << 31)); } if (cpu_is_omap24xx()) omap_writel(devconf, OMAP2_CONTROL_DEVCONF1); else omap_writel(devconf | 1 << 6, OMAP3_CONTROL_DEVCONF1); ret = resource_request(rhandlemmc2, vdd_sel); if (ret != 0) goto err; return ret; } else { if (rhandlemmc2 != NULL) { ret = resource_release(rhandlemmc2); if (ret != 0) goto err; } return ret; } err: return 1; }
/** * resource_test_4 - Tests the resource framework basic APIs for * "latency" resources * @res_name: Name of the resource requested * @req_lat: Requested lat for the resource * @ref_table: Pointer to the reference latency table for the given resource * * Requests the "latency" resource for the given level, * verifies if the resource's current level is same as the * closest lower reference level and releases the resource * * Returns 0 on success, -1 on failure */ static int resource_test_4(const char *res_name, unsigned long req_lat, unsigned long *ref_table) { int ret, i, result = TEST_PASS; int cur_lvl; struct device dev; printk(KERN_INFO "Entry resource_test_4 \n"); ret = resource_request(res_name, &dev, req_lat); if (ret) { printk(KERN_ERR "FAILED!!!! resource request for %s failed" " with value %d\n", res_name, ret); return TEST_FAIL; } cur_lvl = resource_get_level(res_name); /* using the ref table to find the appropriate PD state */ for (i = 0; i < 3; i++) { if (ref_table[i] < req_lat) break; } if (!enable_off_mode && i == PD_LATENCY_OFF) i = PD_LATENCY_RET; /* Inactive state is not being tested */ else if (i == 2) i = PD_LATENCY_ON; if (cur_lvl != i) { printk(KERN_ERR "FAILED!!!! resource %s current level:%d" " req lvl:%d\n", res_name, cur_lvl, i); result = TEST_FAIL; } ret = resource_release(res_name, &dev); if (ret) { printk(KERN_ERR "FAILED!!!! resource release for %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } if (!result) printk(KERN_INFO "resource_test_4 PASSED for %s\n", res_name); return result; }
void omap_pm_dsp_set_min_opp(struct device *dev, unsigned long f) { u8 opp_id; if (!dev) { WARN_ON(1); return; }; pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); if (cpu_is_omap3630()) { /* * check if OPP requested is 65Mz or greater if yes set * max opp constraint to OPP4, Which limits scaling of VDD1 * OPP to 1G only. 1.3G will be allowed when DSP load dies * down to 65MHz. */ if ((f > S65M) && !vdd1_max_opp) { vdd1_max_opp = 1; omap_pm_vdd1_set_max_opp(dev, VDD1_OPP4); omap_pm_vdd1_set_max_opp(dev, VDD1_OPP5); // omap_pm_vdd1_set_max_opp(dev, VDD1_OPP6); } else if ((f < S260M) && vdd1_max_opp) { omap_pm_vdd1_set_max_opp(dev, 0); vdd1_max_opp = 0; } /* * DSP table has 65MHz as OPP5, give OPP1-260MHz when DSP request * 65MHz-OPP1 */ if (f == S65M) f = S260M; // f = S520M; } opp_id = get_opp_id(dsp_opps + MAX_VDD1_OPP, f); /* * For now pass a dummy_dev struct for SRF to identify the caller. * Maybe its good to have DSP pass this as an argument */ resource_request("vdd1_opp", dev, opp_id); return; }
void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t) { if (!dev || t < -1) { WARN_ON(1); return; }; if (t == -1) { pr_debug("OMAP PM: remove max MPU wakeup latency constraint: " "dev %s\n", dev_name(dev)); resource_release("mpu_latency", dev); } else { pr_debug("OMAP PM: add max MPU wakeup latency constraint: " "dev %s, t = %ld usec\n", dev_name(dev), t); resource_request("mpu_latency", dev, t); } }
void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) { if (!dev || (agent_id != OCP_INITIATOR_AGENT && agent_id != OCP_TARGET_AGENT)) { WARN_ON(1); return; }; if (r == 0) { pr_debug("OMAP PM: remove min bus tput constraint: " "dev %s for agent_id %d\n", dev_name(dev), agent_id); resource_release("vdd2_opp", dev); } else { pr_debug("OMAP PM: add min bus tput constraint: " "dev %s for agent_id %d: rate %ld KiB\n", dev_name(dev), agent_id, r); resource_request("vdd2_opp", dev, r); } }
void omap_pm_dsp_set_min_opp(struct device *dev, unsigned long f) { u8 opp_id; if (!dev) { WARN_ON(1); return; } pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id); opp_id = get_opp_id(dsp_opps + MAX_VDD1_OPP, f); /* * For now pass a dummy_dev struct for SRF to identify the caller. * Maybe its good to have DSP pass this as an argument */ resource_request("vdd1_opp", dev, opp_id); return; }
/* This function will enable the power for the domain in the which the devices * falls. It is called from clk_enable function. If the device is in PER * domain then the power state for PER becomes ON as soon as the first device * in PER calls clk_enable. */ static int enable_power_domain(struct clk *clk) { char *resource_name; u32 domainid; u32 ret = 0; unsigned short level; domainid = DOMAIN_ID(clk->prcmid); resource_name = id_to_name[domainid - 1]; /* Request for logical resource. Only CORE domain is modelled as a * logical resource. */ if (resource_name == NULL) return ret; pr_debug("%s: pwr_domain_name %s name %s\n", __FUNCTION__, resource_name, clk->name); if (clk->flags & POWER_ON_REQUIRED) { if (clk->res == NULL) { clk->res = resource_get(clk->name, resource_name); if (clk->res == NULL) { printk(KERN_ERR"Could not get resource handle" "for %s\n", resource_name); return -EINVAL; } } level = (!strcmp(resource_name, "core")) ? LOGICAL_USED : POWER_DOMAIN_ON; ret = resource_request(clk->res, level); if (ret) { printk(KERN_ERR "Could not request ON for resource %s\n", resource_name); return ret; } } return ret; }
/* Threads starts here */ void *process_thread(void *param) { /* Process number */ int i = (int) (long) param, j; printf("PROC %d\n", i); /* Allocate request vector */ int *request = malloc(n*sizeof(int)); int q; for(q = 0; q < n; q++){ request[q] = 0; } int legal = 0; while (1) { /* Generate request */ generate_request(i, request); while (!resource_request(i, request)) { printf("%s\n", "Waiting"); /* Wait */ Sleep(1000); } /* Generate release */ generate_release(i, request); /* Release resources */ resource_release(i, request); /* Wait */ Sleep(1000); } free(request); }
/* Threads starts here */ void *process_thread(void *param) { /* Process number */ int i = (int) (long) param, j; /* Allocate request vector */ int *request = malloc(n*sizeof(int)); while (1) { /* Generate request */ generate_request(i, request); while (!resource_request(i, request)) { /* Wait */ Sleep(100); } /* Generate release */ generate_release(i, request); /* Release resources */ resource_release(i, request); /* Wait */ Sleep(1000); } free(request); }
void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r) { #if 1 // Archer-Froyo, KERNEL PANIC in update_resource_level() after EnableSGXClocks() return; #endif // Archer-Froyo if (!dev || (agent_id != OCP_INITIATOR_AGENT && agent_id != OCP_TARGET_AGENT)) { WARN_ON(1); return; }; if (r == 0) { pr_debug("OMAP PM: remove min bus tput constraint: " "dev %s for agent_id %d\n", dev_name(dev), agent_id); resource_release("vdd2_opp", dev); } else { pr_debug("OMAP PM: add min bus tput constraint: " "dev %s for agent_id %d: rate %ld KiB\n", dev_name(dev), agent_id, r); resource_request("vdd2_opp", dev, r); } }
/** * resource_test_7 - Tests the resource_refresh API * @res_name: Name of the resource requested ("vdd1_opp"/"vdd2_opp") * @req_lvl1: Requested lower level for the resource * @req_lvl2: Requested higher level for the resource * * Device 1 requests the resource for the given lower level, * locks the resource. Meanwhile device 2 requests the reource for a * higher level. * Verifies if the resource's current level is same as the requested * higher level after device 1 unlocks the resource * * Returns 0 on success, -1 on failure */ static int resource_test_7(const char *res_name, unsigned long req_lvl1, unsigned long req_lvl2) { int ret, cur_lvl, result = TEST_PASS; int lock_val; struct device dev1, dev2; printk(KERN_INFO "Entry resource_test_7 \n"); if (!strcmp(res_name, "vdd1_opp")) lock_val = VDD1_OPP; else if (!strcmp(res_name, "vdd2_opp")) lock_val = VDD2_OPP; else { printk(KERN_ERR "FAILED!!!! invalid resource name\n"); return TEST_FAIL; } ret = resource_request(res_name, &dev1, req_lvl1); if (ret) { printk(KERN_ERR "FAILED!!!! resource1 request for %s failed" " with value %d\n", res_name, ret); return TEST_FAIL; } cur_lvl = resource_get_level(res_name); if (cur_lvl != req_lvl1) { printk(KERN_ERR "FAILED!!!! resource %s current level:%d" " req lvl:%d\n", res_name, cur_lvl, (int)req_lvl1); result = TEST_FAIL; } if (result == TEST_PASS) { ret = resource_access_opp_lock(lock_val, 1); if (ret < 0) { printk(KERN_ERR "FAILED!!!! resource %s lock failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } } if (result == TEST_PASS) { ret = resource_request(res_name, &dev2, req_lvl2); if (ret) { printk(KERN_ERR "FAILED!!!! resource2 request %s failed" " with value %d\n", res_name, ret); ret = resource_access_opp_lock(lock_val, -1); if (ret < 0) printk(KERN_ERR "FAILED!!!! resource unlock" "for %s failed\n", res_name); result = TEST_FAIL; } } if (result == TEST_PASS) { cur_lvl = resource_get_level(res_name); if (cur_lvl != req_lvl1) { printk(KERN_ERR "FAILED!!!! %s current level:%d" " req lvl:%d\n", res_name, cur_lvl, (int)req_lvl1); result = TEST_FAIL; } ret = resource_access_opp_lock(lock_val, -1); if (ret < 0) { printk(KERN_ERR "FAILED!!!! resource unlock %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } ret = resource_refresh(); if (ret) { printk(KERN_ERR "FAILED!!!! resource refresh failed" " with value %d\n", ret); result = TEST_FAIL; } cur_lvl = resource_get_level(res_name); if (cur_lvl != req_lvl2) { printk(KERN_ERR "FAILED!!!! %s current level:%d" " req lvl:%d\n", res_name, cur_lvl, (int)req_lvl2); result = TEST_FAIL; } } ret = resource_release(res_name, &dev1); if (ret) { printk(KERN_ERR "FAILED!!!! resource1 release for %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } ret = resource_release(res_name, &dev2); if (ret) { printk(KERN_ERR "FAILED!!!! resource2 release for %s failed" " with value %d\n", res_name, ret); result = TEST_FAIL; } if (!result) printk(KERN_INFO "resource_test_7 PASSED for %s\n", res_name); return result; }
static int hsmmc_set_power(struct device *dev, int slot, int power_on, int vdd) { u32 vdd_sel = 0, devconf = 0, reg = 0; int ret = 0; /* REVISIT: Using address directly till the control.h defines * are settled. */ #if defined(CONFIG_ARCH_OMAP2430) #define OMAP2_CONTROL_PBIAS 0x490024A0 #else #define OMAP2_CONTROL_PBIAS 0x48002520 #endif if (power_on) { if (cpu_is_omap24xx()) devconf = omap_readl(OMAP2_CONTROL_DEVCONF1); else devconf = omap_readl(OMAP3_CONTROL_DEVCONF0); switch (1 << vdd) { case MMC_VDD_33_34: case MMC_VDD_32_33: vdd_sel = VSEL_3V; if (cpu_is_omap24xx()) devconf |= OMAP2_CONTROL_DEVCONF1_ACTOV; break; case MMC_VDD_165_195: vdd_sel = VSEL_18V; if (cpu_is_omap24xx()) devconf &= ~OMAP2_CONTROL_DEVCONF1_ACTOV; } if (cpu_is_omap24xx()) omap_writel(devconf, OMAP2_CONTROL_DEVCONF1); else omap_writel(devconf | OMAP2_CONTROL_DEVCONF0_LBCLK, OMAP3_CONTROL_DEVCONF0); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg |= OMAP2_CONTROL_PBIAS_SCTRL; omap_writel(reg, OMAP2_CONTROL_PBIAS); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ; omap_writel(reg, OMAP2_CONTROL_PBIAS); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg |= OMAP2_CONTROL_PBIAS_SCTRL1; omap_writel(reg, OMAP2_CONTROL_PBIAS); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ1; omap_writel(reg, OMAP2_CONTROL_PBIAS); ret = resource_request(rhandlemmc1, (vdd_sel == VSEL_3V ? T2_VMMC1_3V00 : T2_VMMC1_1V85)); if (ret != 0) goto err; /* Enable VSIM to support MMC 8-bit on ES2 */ if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0)) { ret = resource_request(rhandlevsim, (vdd_sel == VSEL_3V ? T2_VSIM_3V00 : T2_VSIM_1V80)); if (ret != 0) return ret; } msleep(100); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg = (vdd_sel == VSEL_18V) ? (((reg | 0x0606) & ~0x1) & ~(1<<8)) : (reg | 0x0707); omap_writel(reg, OMAP2_CONTROL_PBIAS); return ret; } else { /* Power OFF */ /* For MMC1, Toggle PBIAS before every power up sequence */ reg = omap_readl(OMAP2_CONTROL_PBIAS); reg &= ~OMAP2_CONTROL_PBIAS_PWRDNZ; omap_writel(reg, OMAP2_CONTROL_PBIAS); if (rhandlemmc1 != NULL) { ret = resource_release(rhandlemmc1); if (ret != 0) goto err; } if (is_sil_rev_greater_than(OMAP3430_REV_ES1_0) && (rhandlevsim != NULL)) { ret = resource_release(rhandlevsim); if (ret != 0) goto err; } if (is_sil_rev_equal_to(OMAP3430_REV_ES3_0)) { ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, LDO_CLR, VSIM_DEV_GRP); if (ret) goto err; ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, LDO_CLR, VSIM_DEDICATED); if (ret) goto err; } /* 100ms delay required for PBIAS configuration */ msleep(100); reg = omap_readl(OMAP2_CONTROL_PBIAS); reg |= (OMAP2_CONTROL_PBIAS_VMODE | OMAP2_CONTROL_PBIAS_VMODE1 | OMAP2_CONTROL_PBIAS_PWRDNZ | OMAP2_CONTROL_PBIAS_PWRDNZ1 | OMAP2_CONTROL_PBIAS_SCTRL | OMAP2_CONTROL_PBIAS_SCTRL1); omap_writel(reg, OMAP2_CONTROL_PBIAS); } return 0; err: return 1; }