From d6b03c5742664b700ade5902983d92d11cf25f26 Mon Sep 17 00:00:00 2001 From: Jian Cao Date: Fri, 12 Apr 2019 19:37:47 +0800 Subject: [PATCH] clk: correct HHI_APICALGDC_CNTL addr offset [1/2] PD#SWPL-7051 Problem: reduce power consumption Solution: correct HHI_APICALGDC_CNTL addr offset Verify: Verified on g12b-w400 Change-Id: I539ea901984256f0a6da72c7305488a725936760 Signed-off-by: Jian Cao gdc: add clk control [2/2] PD#SWPL-7051 Problem: reduce power consumption Solution: add control of clk Verify: Verified on g12b-w400 Change-Id: I8001db369f5e0146459cdbad262017581116a0b9 Signed-off-by: Jian Cao --- drivers/amlogic/clk/g12a/g12a.h | 2 +- drivers/amlogic/media/gdc/app/gdc_module.c | 95 +++++++++++++++++----- drivers/amlogic/media/gdc/inc/api/gdc_api.h | 4 + drivers/amlogic/media/gdc/inc/sys/system_log.h | 2 +- drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c | 31 +++++++ 5 files changed, 112 insertions(+), 22 deletions(-) diff --git a/drivers/amlogic/clk/g12a/g12a.h b/drivers/amlogic/clk/g12a/g12a.h index 508017c..ae555c8 100644 --- a/drivers/amlogic/clk/g12a/g12a.h +++ b/drivers/amlogic/clk/g12a/g12a.h @@ -46,7 +46,7 @@ #define HHI_GCLK_OTHER 0x150 /* 0x54 offset in data sheet */ #define HHI_GCLK_SP_MPEG 0x154 /* 0x55 offset in data sheet */ -#define HHI_APICALGDC_CNTL 0x168 /* 0x5a offset in data sheet */ +#define HHI_APICALGDC_CNTL 0x16C /* 0x5b offset in data sheet */ #define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ #define HHI_AUD_CLK_CNTL 0x178 /* 0x5e offset in data sheet */ diff --git a/drivers/amlogic/media/gdc/app/gdc_module.c b/drivers/amlogic/media/gdc/app/gdc_module.c index 678980b..4b40847 100644 --- a/drivers/amlogic/media/gdc/app/gdc_module.c +++ b/drivers/amlogic/media/gdc/app/gdc_module.c @@ -48,6 +48,7 @@ #include "gdc_dmabuf.h" unsigned int gdc_log_level; +unsigned int gdc_reg_store_mode; struct gdc_manager_s gdc_manager; static int trace_mode_enable; static char *config_out_file; @@ -55,6 +56,8 @@ static int config_out_path_defined; #define WAIT_THRESHOLD 1000 #define CONFIG_PATH_LENG 128 +#define CORE_CLK_RATE 800000000 +#define AXI_CLK_RATE 800000000 static const struct of_device_id gdc_dt_match[] = { {.compatible = "amlogic, g12b-gdc"}, @@ -726,6 +729,7 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, if (gs_ex->config_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) gdc_buffer_dma_flush(gs_ex->config_buffer.shared_fd); + gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -736,6 +740,8 @@ static long gdc_process_ex_info(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "gdc timeout\n"); gdc_stop(gdc_cmd); + if (!gdc_reg_store_mode) + gdc_pwr_config(false); mutex_unlock(&fh->gdev->d_mutext); #if 0 if (gs_ex->output_buffer.mem_alloc_type == AML_GDC_MEM_DMABUF) @@ -1103,6 +1109,7 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, gs_with_fw->gdc_config.config_size; mutex_lock(&fh->gdev->d_mutext); + gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -1113,6 +1120,8 @@ static long gdc_process_with_fw(struct mgdc_fh_s *fh, gdc_log(LOG_ERR, "gdc timeout\n"); gdc_stop(gdc_cmd); + if (!gdc_reg_store_mode) + gdc_pwr_config(false); mutex_unlock(&fh->gdev->d_mutext); release_fw: @@ -1248,6 +1257,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, if (trace_mode_enable >= 1) start_time = ktime_get(); + gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process ret = %ld\n", ret); @@ -1291,6 +1301,8 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, gdc_log(LOG_ERR, "gdc process time = %d\n", process_time); } + if (!gdc_reg_store_mode) + gdc_pwr_config(false); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_RUN: @@ -1324,6 +1336,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, if (trace_mode_enable >= 1) start_time = ktime_get(); + gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -1368,6 +1381,9 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, } meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); + + if (!gdc_reg_store_mode) + gdc_pwr_config(false); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_HANDLE: @@ -1400,6 +1416,7 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, if (trace_mode_enable >= 1) start_time = ktime_get(); + gdc_pwr_config(true); ret = gdc_run(gdc_cmd); if (ret < 0) gdc_log(LOG_ERR, "gdc process failed ret = %ld\n", ret); @@ -1446,6 +1463,9 @@ static long meson_gdc_ioctl(struct file *file, unsigned int cmd, meson_gdc_cache_flush(&fh->gdev->pdev->dev, fh->o_paddr, fh->o_len); meson_gdc_deinit_dma_addr(fh); + + if (!gdc_reg_store_mode) + gdc_pwr_config(false); mutex_unlock(&fh->gdev->d_mutext); break; case GDC_REQUEST_BUFF: @@ -1607,28 +1627,48 @@ static struct miscdevice meson_gdc_dev = { .fops = &meson_gdc_fops, }; -static ssize_t gdc_reg_show(struct device *dev, +static ssize_t gdc_dump_reg_show(struct device *dev, struct device_attribute *attr, char *buf) { ssize_t len = 0; int i; - len += sprintf(buf+len, "gdc adapter register below\n"); - for (i = 0; i <= 0xff; i += 4) { - len += sprintf(buf+len, "\t[0xff950000 + 0x%08x, 0x%-8x\n", + if (gdc_reg_store_mode) { + len += sprintf(buf+len, "gdc adapter register below\n"); + for (i = 0; i <= 0xff; i += 4) { + len += sprintf(buf+len, + "\t[0xff950000 + 0x%08x, 0x%-8x\n", i, system_gdc_read_32(i)); + } + } else { + len += sprintf(buf+len, + "err: please flow blow steps\n"); + len += sprintf(buf+len, + "1. turn on dump mode, \"echo 1 > dump_reg\"\n"); + len += sprintf(buf+len, + "2. run gdc to process\n"); + len += sprintf(buf+len, + "3. show reg value, \"cat dump_reg\"\n"); } return len; } -static ssize_t gdc_reg_store(struct device *dev, +static ssize_t gdc_dump_reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { - gdc_log(LOG_DEBUG, "%s, %d\n", __func__, __LINE__); + + int res = 0; + int ret = 0; + + ret = kstrtoint(buf, 0, &res); + + pr_info("dump mode: %d->%d\n", gdc_reg_store_mode, res); + gdc_reg_store_mode = res; + return len; } -static DEVICE_ATTR(gdc_reg, 0554, gdc_reg_show, gdc_reg_store); +static DEVICE_ATTR(dump_reg, 0664, gdc_dump_reg_show, gdc_dump_reg_store); static ssize_t firmware1_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1738,7 +1778,6 @@ static int gdc_platform_probe(struct platform_device *pdev) int rc = -1; struct resource *gdc_res; struct meson_gdc_dev_t *gdc_dev = NULL; - void *clk_cntl = NULL; void *pd_cntl = NULL; uint32_t reg_value = 0; @@ -1784,22 +1823,36 @@ static int gdc_platform_probe(struct platform_device *pdev) return -EINVAL; } -#if 0 - gdc_dev->clk_core = devm_clk_get(&pdev->dev, "core"); - rc = clk_set_rate(gdc_dev->clk_core, 800000000); - - gdc_dev->clk_axi = devm_clk_get(&pdev->dev, "axi"); - rc = clk_set_rate(gdc_dev->clk_axi, 800000000); -#else - clk_cntl = of_iomap(pdev->dev.of_node, 1); - iowrite32((3<<25)|(1<<24)|(0<<16)|(3<<9)|(1<<8)|(0<<0), clk_cntl); + /* mem_pd */ pd_cntl = of_iomap(pdev->dev.of_node, 2); reg_value = ioread32(pd_cntl); gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); reg_value = reg_value & (~(3<<18)); gdc_log(LOG_DEBUG, "pd_cntl=%x\n", reg_value); iowrite32(reg_value, pd_cntl); -#endif + + /* core/axi clk */ + gdc_dev->clk_core = + devm_clk_get(&pdev->dev, "core"); + if (IS_ERR(gdc_dev->clk_core)) { + gdc_log(LOG_ERR, "cannot get gdc core clk\n"); + } else { + clk_set_rate(gdc_dev->clk_core, CORE_CLK_RATE); + clk_prepare_enable(gdc_dev->clk_core); + rc = clk_get_rate(gdc_dev->clk_core); + gdc_log(LOG_INFO, "gdc core clk is %d MHZ\n", rc/1000000); + } + + gdc_dev->clk_axi = + devm_clk_get(&pdev->dev, "axi"); + if (IS_ERR(gdc_dev->clk_axi)) { + gdc_log(LOG_ERR, "cannot get gdc axi clk\n"); + } else { + clk_set_rate(gdc_dev->clk_axi, AXI_CLK_RATE); + clk_prepare_enable(gdc_dev->clk_axi); + rc = clk_get_rate(gdc_dev->clk_axi); + gdc_log(LOG_INFO, "gdc axi clk is %d MHZ\n", rc/1000000); + } mutex_init(&gdc_dev->d_mutext); init_completion(&gdc_dev->d_com); @@ -1819,7 +1872,7 @@ static int gdc_platform_probe(struct platform_device *pdev) gdc_dev->misc_dev.minor); } device_create_file(gdc_dev->misc_dev.this_device, - &dev_attr_gdc_reg); + &dev_attr_dump_reg); device_create_file(gdc_dev->misc_dev.this_device, &dev_attr_firmware1); device_create_file(gdc_dev->misc_dev.this_device, @@ -1830,6 +1883,8 @@ static int gdc_platform_probe(struct platform_device *pdev) &dev_attr_config_out_path); platform_set_drvdata(pdev, gdc_dev); + gdc_pwr_config(false); + return rc; } @@ -1837,7 +1892,7 @@ static int gdc_platform_remove(struct platform_device *pdev) { device_remove_file(meson_gdc_dev.this_device, - &dev_attr_gdc_reg); + &dev_attr_dump_reg); device_remove_file(meson_gdc_dev.this_device, &dev_attr_firmware1); device_remove_file(meson_gdc_dev.this_device, diff --git a/drivers/amlogic/media/gdc/inc/api/gdc_api.h b/drivers/amlogic/media/gdc/inc/api/gdc_api.h index bc46e96..3ccd62b 100644 --- a/drivers/amlogic/media/gdc/inc/api/gdc_api.h +++ b/drivers/amlogic/media/gdc/inc/api/gdc_api.h @@ -21,6 +21,8 @@ #include #include +extern struct gdc_manager_s gdc_manager; + enum gdc_memtype_s { AML_GDC_MEM_ION, AML_GDC_MEM_DMABUF, @@ -411,4 +413,6 @@ int gdc_run(struct gdc_cmd_s *g); int32_t init_gdc_io(struct device_node *dn); +int gdc_pwr_config(bool enable); + #endif diff --git a/drivers/amlogic/media/gdc/inc/sys/system_log.h b/drivers/amlogic/media/gdc/inc/sys/system_log.h index cae4ee0..53380bd78 100644 --- a/drivers/amlogic/media/gdc/inc/sys/system_log.h +++ b/drivers/amlogic/media/gdc/inc/sys/system_log.h @@ -25,7 +25,7 @@ extern unsigned int gdc_log_level; enum log_level_e { LOG_NO_THING, LOG_CRIT, - LOG_ERR, + LOG_ERR = 0, LOG_WARNING, LOG_INFO, LOG_DEBUG, diff --git a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c index e86cff5..c4c128b 100644 --- a/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c +++ b/drivers/amlogic/media/gdc/src/fw_lib/acamera_gdc.c @@ -22,6 +22,7 @@ #include #include #include +#include //data types and prototypes #include "gdc_api.h" @@ -485,3 +486,33 @@ int gdc_get_frame(struct gdc_cmd_s *gdc_cmd) //spin_unlock_irqrestore(&gdev->slock, flags); return 0; } + +/** + * This function set the GDC power on/off + * + * @param enable - power off/on + * @return 0 - success + * -1 - fail. + */ +int gdc_pwr_config(bool enable) +{ + struct meson_gdc_dev_t *gdc_dev = gdc_manager.gdc_dev; + + if (gdc_dev == NULL || + gdc_dev->clk_core == NULL || + gdc_dev->clk_axi == NULL) { + gdc_log(LOG_ERR, "core/axi set err.\n"); + return -1; + } + + /* clk */ + if (enable) { + clk_prepare_enable(gdc_dev->clk_core); + clk_prepare_enable(gdc_dev->clk_axi); + } else { + clk_disable_unprepare(gdc_dev->clk_core); + clk_disable_unprepare(gdc_dev->clk_axi); + } + + return 0; +} -- 2.7.4