static int exynos3_pd_lcd0_clk_enable_off(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power off\n", "LCD"); s3c_pm_do_save(exynos_pd_lcd0_clk_save, ARRAY_SIZE(exynos_pd_lcd0_clk_save)); tmp = __raw_readl(EXYNOS3_CLKSRC_MASK_LCD); tmp |= ((0x1 << 12)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKSRC_MASK_LCD); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_LCD); tmp |= ((0x7F << 14)|(0x3 << 9)|(0x1F << 3)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_LCD); tmp = __raw_readl(EXYNOS3_CLKGATE_SCLK_LCD); tmp |= ((0x3 << 3)|(0x3)); __raw_writel(tmp, EXYNOS3_CLKGATE_SCLK_LCD); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_LCD); tmp |= ((0x3F << 2)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKGATE_IP_LCD); return 0; }
static int exynos3_pd_cam_clk_enable_off(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power off\n", "CAM"); s3c_pm_do_save(exynos_pd_cam_clk_save, ARRAY_SIZE(exynos_pd_cam_clk_save)); tmp = __raw_readl(EXYNOS3_CLKSRC_MASK_CAM); tmp |= ((0x1 << 20)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKSRC_MASK_CAM); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_CAM0); tmp |= ((0x3 << 29)|(0x1 << 27)|(0xF << 22)|(0x7 << 18)|(0x3 << 14)|(0x7 << 10)|(0xF << 5)|(0x7)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_CAM0); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_CAM1); tmp |= ((0xF << 10)|(0x7)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_CAM1); tmp = __raw_readl(EXYNOS3_CLKGATE_SCLK_CAM); tmp |= (0x1 << 8); __raw_writel(tmp, EXYNOS3_CLKGATE_SCLK_CAM); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_CAM); tmp |= ((0xF << 16)|(0xF << 11)|(0xF << 6)|(0x7)); __raw_writel(tmp, EXYNOS3_CLKGATE_IP_CAM); return 0; }
int mali_devfreq_remove(void) { if (mali_devfreq) devfreq_remove_device(mali_devfreq); DEBUG_PRINT_INFO("\n[mali_devfreq]mali_devfreq_remove"); return MALI_TRUE; }
/* Sub-domain does not have power on/off features. * dummy power on/off function is required. */ static inline int exynos_pd_power_dummy(struct exynos_pm_domain *pd, int power_flags) { DEBUG_PRINT_INFO("%s: dummy power %s\n", pd->genpd.name, power_flags ? "on":"off"); pd->status = power_flags; return 0; }
int mali_devfreq_add(struct kbase_device *kbdev) { struct device *dev = kbdev->osdev.dev; mali_devfreq = devfreq_add_device(dev, &exynos5_g3d_devfreq_profile, &exynos5_g3d_abs_governor, NULL); if (mali_devfreq < 0) return MALI_FALSE; DEBUG_PRINT_INFO("\n[mali_devfreq]mali_devfreq_add"); return MALI_TRUE; }
static void kbase_platform_dvfs_set_vol(unsigned int vol) { static int _vol = -1; #ifdef MALI_DEBUG int gotvol = -1; #endif if (_vol == vol) return; kbase_platform_set_voltage(NULL, vol); _vol = vol; #ifdef MALI_DEBUG DEBUG_PRINT_INFO("***set voltage:%d\n", vol); kbase_platform_get_voltage(NULL, &gotvol); DEBUG_PRINT_INFO("***get voltage:%d\n", gotvol); #endif return; }
/*---------------------------------------------------------------------------*/ uint8_t lwb_stream_add(const lwb_stream_req_t* const stream_info) { uint8_t i = 0, idx = 0xff; if(LWB_INVALID_STREAM_ID == stream_info->stream_id) { return 0; } for(; i < LWB_CONF_MAX_N_STREAMS_PER_NODE; i++) { if(streams[i].id == stream_info->stream_id) { /* exists already -> update steam data */ memcpy((uint8_t*)&streams[i] + 2, /* skip the first 2 bytes */ (uint8_t*)stream_info + 4, /* skip the first 4 bytes */ LWB_STREAM_REQ_HEADER_LEN - 4 + LWB_CONF_STREAM_EXTRA_DATA_LEN); streams[i].state = LWB_STREAM_STATE_WAITING; /* rejoin */ lwb_pending_requests |= (1 << i); /* set the 'request pending' bit */ DEBUG_PRINT_INFO("stream with ID %u updated (IPI %u)", stream_info->stream_id, stream_info->ipi); return 1; } if(idx == 0xff && streams[i].state == LWB_STREAM_STATE_INACTIVE) { idx = i; /* this stream is not being used -> take this slot */ } } /* add the new stream */ if(idx != 0xff) { /* copy the stream info (skip the first 2 bytes, the node ID) */ memcpy((uint8_t*)&streams[idx], (uint8_t*)stream_info + 2, (LWB_STREAM_REQ_HEADER_LEN + LWB_CONF_STREAM_EXTRA_DATA_LEN - 2)); streams[idx].state = LWB_STREAM_STATE_WAITING; lwb_pending_requests |= (1 << idx); /* set the 'request pending' bit */ DEBUG_PRINT_INFO("stream with ID %u added (IPI %u)", streams[idx].id, streams[idx].ipi); return 1; } else { DEBUG_PRINT_ERROR("no more space for new streams"); } return 0; }
static int mali_governor_get_target_freq(struct devfreq *df, unsigned long *freq) { mali_dvfs_status *dvfs_status; mutex_lock(&mali_enable_clock_lock); dvfs_status = &mali_dvfs_status_current; mali_dvfs_decide_next_level(dvfs_status); mutex_unlock(&mali_enable_clock_lock); *freq = dvfs_status->step; DEBUG_PRINT_INFO("\n[mali_devfreq] get_target_freq:%d", *freq); return 0; }
static int exynos3_pd_isp_clk_enable_off(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power off : save clocks and masking\n", "ISP"); s3c_pm_do_save(exynos_pd_isp_clk_save, ARRAY_SIZE(exynos_pd_isp_clk_save)); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_ISP0); tmp |= ((0x7 << 27)|(0xF << 21)|(0xFFF << 8)|(0x7F)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_ISP0); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_ISP1); tmp |= ((0x7F << 15)|(0x1 << 4)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_ISP1); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_ISP2); tmp |= ((0x3 << 30)|(0x1 << 28)|(0xF << 23)|(0x3 << 20)|(0x1F << 14)|(0xFFF << 1)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_ISP2); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_ISP3); tmp |= ((0x7F << 15)|(0x3 << 12)|(0x3 << 3)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_ISP3); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_ISP0); tmp |= ((0x3 << 30)|(0x1 << 28)|(0xF << 23)|(0x3 << 20)|(0x3FFFF)); __raw_writel(tmp, EXYNOS3_CLKGATE_IP_ISP0); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_ISP1); tmp |= ((0x7F << 15)|(0x3 << 12)|(0x1 << 4)|(0x1)); __raw_writel(tmp, EXYNOS3_CLKGATE_IP_ISP1); tmp = __raw_readl(EXYNOS3_CLKSRC_MASK_ISP); tmp |= ((0x1 << 12)|(0x1 << 8)|(0x3 << 4)); __raw_writel(tmp, EXYNOS3_CLKSRC_MASK_ISP); tmp = __raw_readl(EXYNOS3_CLKGATE_SCLK_TOP_ISP); tmp |= (0xF << 1); __raw_writel(tmp, EXYNOS3_CLKGATE_SCLK_TOP_ISP); tmp = __raw_readl(EXYNOS3_CLKGATE_SCLK_ISP); tmp |= (0x1); __raw_writel(tmp, EXYNOS3_CLKGATE_SCLK_ISP); return 0; }
/*---------------------------------------------------------------------------*/ void lwb_stream_drop(uint8_t stream_id) { uint8_t i = 0; for(; i < LWB_CONF_MAX_N_STREAMS_PER_NODE; i++) { if(streams[i].id == stream_id) { /* clear the corresponding bit */ lwb_pending_requests &= ~((uint32_t)1 << i); streams[i].ipi = 0; if(streams[i].state > LWB_STREAM_STATE_INACTIVE && lwb_joined_streams_cnt) { lwb_joined_streams_cnt--; } streams[i].state = LWB_STREAM_STATE_INACTIVE; DEBUG_PRINT_INFO("stream with ID %u dropped", stream_id); } } }
static int mali_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) { mali_dvfs_status *dvfs_status; struct kbase_device *kbdev; mutex_lock(&mali_enable_clock_lock); dvfs_status = &mali_dvfs_status_current; kbdev = mali_dvfs_status_current.kbdev; KBASE_DEBUG_ASSERT(kbdev != NULL); kbase_platform_dvfs_set_level(dvfs_status->kbdev, *freq); mutex_unlock(&mali_enable_clock_lock); DEBUG_PRINT_INFO("\n[mali_devfreq] set_target:%d", *freq); return 0; }
static int exynos3_pd_g3d_clk_enable_on(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power on\n", "G3D"); s3c_pm_do_restore_core(exynos_pd_g3d_clk_save, ARRAY_SIZE(exynos_pd_g3d_clk_save)); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_G3D); tmp |= ((0x1 << 18)|(0x1 << 16)|(0x7 << 3)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_G3D); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_G3D); tmp |= 0xF; __raw_writel(tmp, EXYNOS3_CLKGATE_IP_G3D); return 0; }
static int exynos3_pd_isp_clk_enable_on(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power on : restore clock and masking\n", "ISP"); s3c_pm_do_restore_core(exynos_pd_isp_clk_save, ARRAY_SIZE(exynos_pd_isp_clk_save)); tmp = __raw_readl(EXYNOS3_CLKSRC_MASK_ISP); tmp |= ((0x1 << 12)|(0x1 << 8)|(0x1 << 4)); __raw_writel(tmp, EXYNOS3_CLKSRC_MASK_ISP); tmp = __raw_readl(EXYNOS3_CLKGATE_SCLK_TOP_ISP); tmp |= (0xF << 1); __raw_writel(tmp, EXYNOS3_CLKGATE_SCLK_TOP_ISP); return 0; }
static int exynos3_pd_mfc_clk_enable_off(struct exynos_pm_domain *domain) { unsigned int tmp; DEBUG_PRINT_INFO("%s pre power off\n", "MFC"); s3c_pm_do_save(exynos_pd_mfc_clk_save, ARRAY_SIZE(exynos_pd_mfc_clk_save)); tmp = __raw_readl(EXYNOS3_CLKGATE_BUS_MFC); tmp |= ((0x1 << 19)|(0x7 << 15)|(0x1 << 6)|(0x1 << 4)|(0x3 << 1)); __raw_writel(tmp, EXYNOS3_CLKGATE_BUS_MFC); tmp = __raw_readl(EXYNOS3_CLKGATE_IP_MFC); tmp |= ((0x1 << 5)|(0x1 << 3)|(0x3)); __raw_writel(tmp, EXYNOS3_CLKGATE_IP_MFC); return 0; }
static int exynos3_pd_isp_arm_control_off(struct exynos_pm_domain *domain) { unsigned int tmp; unsigned long timeout; DEBUG_PRINT_INFO("%s post power off : ISP ARM control\n", "ISP"); /* Wait max 70ms */ timeout = 700; do { tmp = (__raw_readl(EXYNOS3_ISP_STATUS) & 0x7); if (timeout == 0) { pr_err("PM DOMAIN : %s can't turn off, timeout\n", "ISP_ARM"); break; } --timeout; cpu_relax(); usleep_range(80, 100); } while (tmp != 0); if(tmp != 0){ /* Wait max 5ms */ timeout = 50; do { tmp = (__raw_readl(EXYNOS3_ISP_STATUS) & 0x7); if (timeout == 0) { pr_err("PM DOMAIN : %s can't turn off, timeout\n", "ISP_ARM"); break; } --timeout; cpu_relax(); usleep_range(80, 100); } while (tmp != 0); } if(tmp != 0) __raw_writel(0x00000000, EXYNOS3_ISP_ARM_OPTION); return 0; }
static int mali_governor_init(struct devfreq *df) { DEBUG_PRINT_INFO("\n[mali_devfreq]mali_governor_init"); return 0; }
void kbase_platform_dvfs_set_clock(kbase_device *kbdev, int freq) { #if defined(CONFIG_SUPPORT_WQXGA) struct clk *mout_dpll = NULL; struct clk *mout_vpll = NULL; struct clk *fout_vpll = NULL; struct clk *aclk_g3d_dout = NULL; struct clk *parent= NULL; static long vpll_rate_prev = -1; unsigned long vpll_rate = freq * 1000000; unsigned long aclk_rate = freq * 1000000; unsigned long tmp = 0; struct exynos_context *platform; if (!kbdev) panic("oops"); platform = (struct exynos_context *) kbdev->platform_context; if (NULL == platform) { panic("oops"); } if (platform->aclk_g3d == 0) return; aclk_g3d_dout = clk_get(kbdev->osdev.dev, "aclk_g3d_dout"); if (IS_ERR(aclk_g3d_dout)) { printk(KERN_ERR "[kbase_platform_dvfs_set_clock] failed to clk_get [aclk_g3d_dout] = %ld\n", aclk_rate); return; } /* if changed the VPLL rate, set rate for VPLL and wait for lock time */ if (vpll_rate != vpll_rate_prev) { mout_dpll = clk_get(kbdev->osdev.dev, "mout_dpll"); mout_vpll = clk_get(kbdev->osdev.dev, "mout_vpll"); fout_vpll = clk_get(kbdev->osdev.dev, "fout_vpll"); if (IS_ERR(mout_dpll) || IS_ERR(mout_vpll) || IS_ERR(fout_vpll)) { printk(KERN_ERR "[kbase_platform_dvfs_set_clock] failed to clk_get ext_xtal, aclk_g3d_sw or fout_vpll\n"); return; } /*for stable clock input.*/ clk_set_rate(aclk_g3d_dout, get_dpll_freq(clk_get_rate(platform->aclk_g3d)/1000000,freq)); clk_set_parent(aclk_g3d_dout, mout_dpll); /*change vpll*/ clk_set_rate(fout_vpll, vpll_rate); /*restore parent*/ clk_set_parent(aclk_g3d_dout, mout_vpll); vpll_rate_prev = vpll_rate; } #else struct clk *ext_xtal = NULL; struct clk *aclk_g3d_sw = NULL; struct clk *fout_vpll = NULL; struct clk *aclk_g3d_dout = NULL; static long vpll_rate_prev = -1; unsigned long vpll_rate = freq * 1000000; unsigned long aclk_rate = freq * 1000000; unsigned long tmp = 0; struct exynos_context *platform; if (!kbdev) panic("oops"); platform = (struct exynos_context *) kbdev->platform_context; if (NULL == platform) { panic("oops"); } if (platform->aclk_g3d == 0) return; aclk_g3d_dout = clk_get(kbdev->osdev.dev, "aclk_g3d_dout"); if (IS_ERR(aclk_g3d_dout)) { printk(KERN_ERR "[kbase_platform_dvfs_set_clock] failed to clk_get [aclk_g3d_dout] = %ld\n", aclk_rate); return; } /* if changed the VPLL rate, set rate for VPLL and wait for lock time */ if (vpll_rate != vpll_rate_prev) { ext_xtal = clk_get(kbdev->osdev.dev, "ext_xtal"); aclk_g3d_sw = clk_get(kbdev->osdev.dev, "aclk_g3d_sw"); fout_vpll = clk_get(kbdev->osdev.dev, "fout_vpll"); if (IS_ERR(ext_xtal) || IS_ERR(aclk_g3d_sw) || IS_ERR(fout_vpll)) { printk(KERN_ERR "[kbase_platform_dvfs_set_clock] failed to clk_get ext_xtal, aclk_g3d_sw or fout_vpll\n"); return; } /*for stable clock input.*/ clk_set_rate(aclk_g3d_dout, 100000000); clk_set_parent(platform->aclk_g3d, ext_xtal); /*change vpll*/ clk_set_rate(fout_vpll, vpll_rate); /*restore parent*/ clk_set_parent(platform->aclk_g3d, aclk_g3d_sw); vpll_rate_prev = vpll_rate; } #endif clk_set_rate(aclk_g3d_dout, aclk_rate); /* Waiting for clock is stable */ do { tmp = __raw_readl(EXYNOS5_CLKDIV_STAT_TOP2); } while (tmp & 0x10000); #ifdef MALI_DEBUG DEBUG_PRINT_INFO("===clock set: %ld\n", aclk_rate); DEBUG_PRINT_INFO("===clock get: %ld\n", clk_get_rate(platform->aclk_g3d)); DEBUG_PRINT_INFO("===clock get: %ld\n", clk_get_rate(aclk_g3d_dout)); #endif return; }