/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include "clk-mtk-v1.h" #include "clk-mt6739-pg.h" #include #define TOPAXI_PROTECT_LOCK #ifdef CONFIG_FPGA_EARLY_PORTING #define IGNORE_MTCMOS_CHECK #endif #if !defined(MT_CCF_DEBUG) || !defined(MT_CCF_BRINGUP) #define MT_CCF_DEBUG 0 #define MT_CCF_BRINGUP 0 #define CONTROL_LIMIT 1 #endif #define CHECK_PWR_ST 1 #ifndef GENMASK #define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l)) #endif #ifdef CONFIG_ARM64 #define IOMEM(a) ((void __force __iomem *)((a))) #endif #if 0 #define clk_readl(addr) readl(addr) #define clk_writel(val, addr) \ do { writel(val, addr); wmb(); } while (0) /* sync_write */ #define clk_setl(mask, addr) clk_writel(clk_readl(addr) | (mask), addr) #define clk_clrl(mask, addr) clk_writel(clk_readl(addr) & ~(mask), addr) #endif #define mt_reg_sync_writel(v, a) \ do { __raw_writel((v), IOMEM(a)); mb(); } while (0) /* sync_write */ #define spm_read(addr) __raw_readl(IOMEM(addr)) #define spm_write(addr, val) mt_reg_sync_writel(val, addr) #define clk_writel(addr, val) \ mt_reg_sync_writel(val, addr) #define clk_readl(addr) __raw_readl(IOMEM(addr)) /*MM Bus*/ #ifdef CONFIG_OF void __iomem *clk_mmsys_config_base; void __iomem *clk_imgsys_base; void __iomem *clk_venc_gcon_base; #endif #if 1 #define MM_CG_CLR0 (clk_mmsys_config_base + 0x108) #define IMG_CG_CLR (clk_imgsys_base + 0x0008) #define VENC_CG_SET (clk_venc_gcon_base + 0x0004) #endif /* * MTCMOS */ #define STA_POWER_DOWN 0 #define STA_POWER_ON 1 #define SUBSYS_PWR_DOWN 0 #define SUBSYS_PWR_ON 1 struct subsys; struct subsys_ops { int (*enable)(struct subsys *sys); int (*disable)(struct subsys *sys); int (*get_state)(struct subsys *sys); }; struct subsys { const char *name; uint32_t sta_mask; void __iomem *ctl_addr; uint32_t sram_pdn_bits; uint32_t sram_pdn_ack_bits; uint32_t bus_prot_mask; struct subsys_ops *ops; }; /*static struct subsys_ops general_sys_ops;*/ static struct subsys_ops MFG0_sys_ops; static struct subsys_ops MFG1_sys_ops; static struct subsys_ops MD1_sys_ops; static struct subsys_ops CONN_sys_ops; static struct subsys_ops MM0_sys_ops; static struct subsys_ops ISP_sys_ops; static struct subsys_ops VEN_sys_ops; static void __iomem *infracfg_base;/*infracfg_ao*/ static void __iomem *spm_base; static void __iomem *infra_base;/*infra*/ #define INFRACFG_REG(offset) (infracfg_base + offset) #define SPM_REG(offset) (spm_base + offset) #define INFRA_REG(offset) (infra_base + offset) /* Define MTCMOS power control */ #define PWR_RST_B (0x1 << 0) #define PWR_ISO (0x1 << 1) #define PWR_ON (0x1 << 2) #define PWR_ON_2ND (0x1 << 3) #define PWR_CLK_DIS (0x1 << 4) #define SRAM_CKISO (0x1 << 5) #define MD_PWR_CLK_DIS (0x1 << 5) #define SRAM_ISOINT_B (0x1 << 6) #define SLPB_CLAMP (0x1 << 7) /* Define MTCMOS Bus Protect Mask */ #define MD1_PROT_BIT_MASK ((0x1 << 3) \ |(0x1 << 4) \ |(0x1 << 7)) #define MD1_PROT_BIT_ACK_MASK ((0x1 << 3) \ |(0x1 << 4) \ |(0x1 << 7)) #define MD1_PROT_BIT_2ND_MASK ((0x1 << 6)) #define MD1_PROT_BIT_ACK_2ND_MASK ((0x1 << 6)) #define CONN_PROT_BIT_MASK ((0x1 << 13) \ |(0x1 << 14)) #define CONN_PROT_BIT_ACK_MASK ((0x1 << 13) \ |(0x1 << 14)) #define DIS_PROT_BIT_MASK (0x1 << 1) #define DIS_PROT_BIT_ACK_MASK (0x1 << 1) #define MFG_PROT_BIT_MASK ((0x1 << 21) \ |(0x1 << 22)) #define MFG_PROT_BIT_ACK_MASK ((0x1 << 21) \ |(0x1 << 22)) /* MFG on/off sequence */ #define CTRL_UPDATE_BIT (0x1 << 24) #define WR_RD_OT_BUSY_BIT ((0x1 << 15) \ |(0x1 << 14)) #define WR_OT_BUSY_BIT (0x1 << 15) #define RD_OT_BUSY_BIT (0x1 << 14) /* Define MTCMOS Power Status Mask */ #define MD1_PWR_STA_MASK (0x1 << 0) #define CONN_PWR_STA_MASK (0x1 << 1) #define DPY_PWR_STA_MASK (0x1 << 2) #define DIS_PWR_STA_MASK (0x1 << 3) #define MFG_PWR_STA_MASK (0x1 << 4) #define ISP_PWR_STA_MASK (0x1 << 5) #define IFR_PWR_STA_MASK (0x1 << 6) #define VCODEC_PWR_STA_MASK (0x1 << 7) #define MFG_CORE0_PWR_STA_MASK (0x1 << 31) /* Define Non-CPU SRAM Mask */ #define MD1_SRAM_PDN (0x1 << 6) #define MD1_SRAM_PDN_ACK (0x0 << 12) #define MD1_SRAM_PDN_ACK_BIT0 (0x1 << 12) #define DPY_SRAM_PDN (0x1 << 5) #define DPY_SRAM_PDN_ACK (0x1 << 6) #define DPY_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define DIS_SRAM_PDN (0x1 << 5) #define DIS_SRAM_PDN_ACK (0x1 << 6) #define DIS_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define MFG_SRAM_PDN (0x1 << 5) #define MFG_SRAM_PDN_ACK (0x1 << 6) #define MFG_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define ISP_SRAM_PDN (0x1 << 5) #define ISP_SRAM_PDN_ACK (0x1 << 6) #define ISP_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define IFR_SRAM_PDN (0x1 << 5) #define IFR_SRAM_PDN_ACK (0x1 << 6) #define IFR_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define VCODEC_SRAM_PDN (0x1 << 5) #define VCODEC_SRAM_PDN_ACK (0x1 << 6) #define VCODEC_SRAM_PDN_ACK_BIT0 (0x1 << 6) #define MFG_CORE0_SRAM_PDN (0x1 << 5) #define MFG_CORE0_SRAM_PDN_ACK (0x1 << 6) #define MFG_CORE0_SRAM_PDN_ACK_BIT0 (0x1 << 6) /************************************** * for non-CPU MTCMOS **************************************/ #if 0 #ifdef TOPAXI_PROTECT_LOCK static DEFINE_SPINLOCK(spm_noncpu_lock); #define spm_mtcmos_noncpu_lock(flags) spin_lock_irqsave(&spm_noncpu_lock, flags) #define spm_mtcmos_noncpu_unlock(flags) spin_unlock_irqrestore(&spm_noncpu_lock, flags) #endif #endif #define POWERON_CONFIG_EN SPM_REG(0x0000) #define SPM_POWER_ON_VAL0 SPM_REG(0x0004) #define SPM_POWER_ON_VAL1 SPM_REG(0x0008) #define PWR_STATUS SPM_REG(0x0180) #define PWR_STATUS_2ND SPM_REG(0x0184) #define MFG_PWR_CON SPM_REG(0x338) #define MFG_CORE0_PWR_CON SPM_REG(0x33C) #define MD1_PWR_CON SPM_REG(0x0320) #define CONN_PWR_CON SPM_REG(0x032c) #define DIS_PWR_CON SPM_REG(0x030C) #define ISP_PWR_CON SPM_REG(0x0308) #define VCODEC_PWR_CON SPM_REG(0x0300) #define MD_EXTRA_PWR_CON SPM_REG(0x0398) #define MD_SRAM_ISO_CON SPM_REG(0x0394) #define INFRA_TOPAXI_SI0_CTL INFRACFG_REG(0x0200) #define INFRA_TOPAXI_PROTECTEN INFRACFG_REG(0x0220) #define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_REG(0x0224) #define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_REG(0x0228) #define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_REG(0x0250) #define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_REG(0x0254) #define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_REG(0x0258) #define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_REG(0x02A0) #define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_REG(0x02A4) #define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_REG(0x02A8) #define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_REG(0x02AC) /* fix with infra config address */ #define INFRA_TOPAXI_SI0_STA INFRA_REG(0x0000) static struct subsys syss[] = /* NR_SYSS */ /* FIXME: set correct value */ { [SYS_MFG0] = { .name = __stringify(SYS_MFG0), .sta_mask = MFG_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &MFG0_sys_ops, }, [SYS_MFG1] = { .name = __stringify(SYS_MFG1), .sta_mask = MFG_CORE0_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &MFG1_sys_ops, }, [SYS_MD1] = { .name = __stringify(SYS_MD1), .sta_mask = MD1_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = MD1_SRAM_PDN, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &MD1_sys_ops, }, [SYS_CONN] = { .name = __stringify(SYS_CONN), .sta_mask = CONN_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &CONN_sys_ops, }, [SYS_MM0] = { .name = __stringify(SYS_MM0), .sta_mask = DIS_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &MM0_sys_ops, }, [SYS_ISP] = { .name = __stringify(SYS_ISP), .sta_mask = ISP_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &ISP_sys_ops, }, [SYS_VEN] = { .name = __stringify(SYS_VEN), .sta_mask = VCODEC_PWR_STA_MASK, /* .ctl_addr = NULL, */ .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, .bus_prot_mask = 0, .ops = &VEN_sys_ops, }, }; spinlock_t pgcb_lock; LIST_HEAD(pgcb_list); struct pg_callbacks *register_pg_callback(struct pg_callbacks *pgcb) { unsigned long spinlock_save_flags; spin_lock_irqsave(&pgcb_lock, spinlock_save_flags); INIT_LIST_HEAD(&pgcb->list); list_add(&pgcb->list, &pgcb_list); spin_unlock_irqrestore(&pgcb_lock, spinlock_save_flags); return pgcb; } static struct subsys *id_to_sys(unsigned int id) { return id < NR_SYSS ? &syss[id] : NULL; } #if 0 /* sync from mtcmos_ctrl.c */ #ifdef CONFIG_MTK_RAM_CONSOLE #if 0 /*add after early porting*/ static void aee_clk_data_rest(void) { aee_rr_rec_clk(0, 0); aee_rr_rec_clk(1, 0); aee_rr_rec_clk(2, 0); aee_rr_rec_clk(3, 0); } #endif #endif #define DBG_ID_MFG0 1 #define DBG_ID_MFG1 2 #define DBG_ID_MD1 3 #define DBG_ID_CONN 4 #define DBG_ID_MM 5 #define DBG_ID_ISP 6 #define DBG_ID_VEN 7 #define ID_MADK 0xFF000000 #define STA_MASK 0x00F00000 #define STEP_MASK 0x000000FF #define INCREASE_STEPS \ do { DBG_STEP++; } while (0) static int DBG_ID; static int DBG_STA; static int DBG_STEP; /* * ram console data0 define * [31:24] : DBG_ID * [23:20] : DBG_STA * [7:0] : DBG_STEP */ static void ram_console_update(void) { unsigned long data1 = 0; data1 = ((DBG_ID << 24)&ID_MADK) |((DBG_STA << 20)&STA_MASK) |(DBG_STEP&STEP_MASK); #ifdef CONFIG_MTK_RAM_CONSOLE aee_rr_rec_clk(0, data1); /*todo: add each domain's debug register to ram console*/ #endif } #endif #ifdef TOPAXI_PROTECT_LOCK #define _TOPAXI_TIMEOUT_CNT_ 900000 /*only power off will wait for ack*/ int spm_topaxi_protect_ready0(unsigned int mask_value) { /*unsigned long flags;*/ int count = 0; struct timeval tm_s, tm_e; unsigned int tm_val = 0; do_gettimeofday(&tm_s); /*spm_mtcmos_noncpu_lock(flags);*/ while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA0) & (mask_value)) != (mask_value)) { count++; if (count > _TOPAXI_TIMEOUT_CNT_) break; } /*spm_mtcmos_noncpu_unlock(flags);*/ if (count > _TOPAXI_TIMEOUT_CNT_) { do_gettimeofday(&tm_e); tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000000 + (tm_e.tv_usec - tm_s.tv_usec); pr_debug("TOPAXI Bus Protect Timeout Error (%d us)(%d) !!\n", tm_val, count); pr_debug("INFRA_TOPAXI_PROTECTEN_STA0 = 0x%x != 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTEN_STA0), mask_value); /*more relative log can add here*/ WARN_ON(1); } return 0; } int spm_topaxi_protect_ready1(unsigned int mask_value) { /*unsigned long flags;*/ int count = 0; struct timeval tm_s, tm_e; unsigned int tm_val = 0; do_gettimeofday(&tm_s); /*spm_mtcmos_noncpu_lock(flags);*/ while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA1) & (mask_value)) != (mask_value)) { count++; if (count > _TOPAXI_TIMEOUT_CNT_) break; } /*spm_mtcmos_noncpu_unlock(flags);*/ if (count > _TOPAXI_TIMEOUT_CNT_) { do_gettimeofday(&tm_e); tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000000 + (tm_e.tv_usec - tm_s.tv_usec); pr_debug("TOPAXI Bus Protect Timeout Error (%d us)(%d) !!\n", tm_val, count); pr_debug("INFRA_TOPAXI_PROTECTEN_STA1 = 0x%x != 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTEN_STA1), mask_value); /*more relative log can add here*/ WARN_ON(1); } return 0; } int spm_topaxi_protect_ready0_1(unsigned int mask_value) { /*unsigned long flags;*/ int count = 0; struct timeval tm_s, tm_e; unsigned int tm_val = 0; do_gettimeofday(&tm_s); /*spm_mtcmos_noncpu_lock(flags);*/ while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA0_1) & (mask_value)) != (mask_value)) { count++; if (count > _TOPAXI_TIMEOUT_CNT_) break; } /*spm_mtcmos_noncpu_unlock(flags);*/ if (count > _TOPAXI_TIMEOUT_CNT_) { do_gettimeofday(&tm_e); tm_val = (tm_e.tv_sec - tm_s.tv_sec) * 1000000 + (tm_e.tv_usec - tm_s.tv_usec); pr_debug("TOPAXI Bus Protect Timeout Error (%d us)(%d) !!\n", tm_val, count); pr_debug("INFRA_TOPAXI_PROTECTEN_STA0_1 = 0x%x != 0x%x\n", clk_readl(INFRA_TOPAXI_PROTECTEN_STA0_1), mask_value); /*more relative log can add here*/ WARN_ON(1); } return 0; } #endif /* auto-gen begin*/ int spm_mtcmos_ctrl_md1(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off MD1" */ /* TINFO="Set bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_SET, MD1_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK #ifdef TOPAXI_PROTECT_LOCK spm_topaxi_protect_ready0(MD1_PROT_BIT_ACK_MASK); #else while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA0) & MD1_PROT_BIT_ACK_MASK) != MD1_PROT_BIT_ACK_MASK) { /* */ /* */ } #endif #endif /* TINFO="Set bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_1_SET, MD1_PROT_BIT_2ND_MASK); #ifndef IGNORE_MTCMOS_CHECK #ifdef TOPAXI_PROTECT_LOCK spm_topaxi_protect_ready0_1(MD1_PROT_BIT_ACK_2ND_MASK); #else while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA0_1) & MD1_PROT_BIT_ACK_2ND_MASK) != MD1_PROT_BIT_ACK_2ND_MASK) { /* */ /* */ } #endif #endif /* TINFO="MD_EXTRA_PWR_CON[0]=1"*/ spm_write(MD_EXTRA_PWR_CON, spm_read(MD_EXTRA_PWR_CON) | (0x1 << 0)); /* TINFO="Set MD_PWR_CLK_DIS = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | MD_PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ISO); /* TINFO="MD_SRAM_ISO_CON[0]=0"*/ spm_write(MD_SRAM_ISO_CON, spm_read(MD_SRAM_ISO_CON) & ~(0x1 << 0)); /* TINFO="Set SRAM_PDN = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | MD1_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK #endif /* TINFO="Set PWR_ON = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & MD1_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & MD1_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ } #endif /* TINFO="Set PWR_RST_B = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_RST_B); /* TINFO="Finish to turn off MD1" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on MD1" */ /* TINFO="Set PWR_RST_B = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & MD1_PWR_STA_MASK) != MD1_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & MD1_PWR_STA_MASK) != MD1_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ /* */ } #endif /* TINFO="Set SRAM_PDN = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~(0x1 << 6)); /* TINFO="MD_SRAM_ISO_CON[0]=1"*/ spm_write(MD_SRAM_ISO_CON, spm_read(MD_SRAM_ISO_CON) | (0x1 << 0)); /* TINFO="Set PWR_ISO = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~PWR_ISO); /* TINFO="Set MD_PWR_CLK_DIS = 0" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) & ~MD_PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 1" */ spm_write(MD1_PWR_CON, spm_read(MD1_PWR_CON) | PWR_RST_B); /* TINFO="MD_EXTRA_PWR_CON[0]=0"*/ spm_write(MD_EXTRA_PWR_CON, spm_read(MD_EXTRA_PWR_CON) & ~(0x1 << 0)); /* TINFO="Release bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_1_CLR, MD1_PROT_BIT_2ND_MASK); #ifndef IGNORE_MTCMOS_CHECK /* Note that this protect ack check after releasing protect has been ignored */ #endif /* TINFO="Release bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_CLR, MD1_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK udelay(250); /* Note that this protect ack check after releasing protect has been ignored */ #endif /* TINFO="Finish to turn on MD1" */ } return err; } int spm_mtcmos_ctrl_conn(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off CONN" */ /* TINFO="Set bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_SET, CONN_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK #ifdef TOPAXI_PROTECT_LOCK spm_topaxi_protect_ready1(CONN_PROT_BIT_ACK_MASK); #else while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA1) & CONN_PROT_BIT_ACK_MASK) != CONN_PROT_BIT_ACK_MASK) { /* */ /* */ } #endif #endif #ifndef IGNORE_MTCMOS_CHECK #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & CONN_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & CONN_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ /* */ } #endif /* TINFO="Finish to turn off CONN" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on CONN" */ /* TINFO="Set PWR_ON = 1" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & CONN_PWR_STA_MASK) != CONN_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & CONN_PWR_STA_MASK) != CONN_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(CONN_PWR_CON, spm_read(CONN_PWR_CON) | PWR_RST_B); #ifndef IGNORE_MTCMOS_CHECK #endif /* TINFO="Release bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_CLR, CONN_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK /* Note that this protect ack check after releasing protect has been ignored */ #endif /* TINFO="Finish to turn on CONN" */ } return err; } int spm_mtcmos_ctrl_dis(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off DIS" */ /* TINFO="Set bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_SET, DIS_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK #ifdef TOPAXI_PROTECT_LOCK spm_topaxi_protect_ready1(DIS_PROT_BIT_ACK_MASK); #else while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA1) & DIS_PROT_BIT_ACK_MASK) != DIS_PROT_BIT_ACK_MASK) { /* */ /* */ } #endif #endif /* TINFO="Set SRAM_PDN = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | DIS_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until DIS_SRAM_PDN_ACK = 1" */ while ((spm_read(DIS_PWR_CON) & DIS_SRAM_PDN_ACK) != DIS_SRAM_PDN_ACK) { /* Need hf_fmm_ck for SRAM PDN delay IP. */ /* */ } #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & DIS_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & DIS_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ /* */ } #endif /* TINFO="Finish to turn off DIS" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on DIS" */ /* TINFO="Set PWR_ON = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & DIS_PWR_STA_MASK) != DIS_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & DIS_PWR_STA_MASK) != DIS_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) | PWR_RST_B); /* TINFO="Set SRAM_PDN = 0" */ spm_write(DIS_PWR_CON, spm_read(DIS_PWR_CON) & ~(0x1 << 5)); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until DIS_SRAM_PDN_ACK_BIT0 = 0" */ while (spm_read(DIS_PWR_CON) & DIS_SRAM_PDN_ACK_BIT0) { /* Need hf_fmm_ck for SRAM PDN delay IP. */ /* */ /* */ } #endif /* TINFO="Release bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_CLR, DIS_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK /* Note that this protect ack check after releasing protect has been ignored */ #endif /* TINFO="Finish to turn on DIS" */ } return err; } int spm_mtcmos_ctrl_mfg(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off MFG" */ /* TINFO="Extra set before setting bus protect of MFG (way_en disable)" */ spm_write(INFRA_TOPAXI_SI0_CTL, spm_read(INFRA_TOPAXI_SI0_CTL) & (0xFFFFFF7F)); #ifndef IGNORE_MTCMOS_CHECK while (((spm_read(INFRA_TOPAXI_SI0_STA) & CTRL_UPDATE_BIT) != CTRL_UPDATE_BIT) && !((spm_read(INFRA_TOPAXI_SI0_STA) | ~(WR_RD_OT_BUSY_BIT)) == ~(WR_RD_OT_BUSY_BIT))) { /* */ /* */ } #endif /* TINFO="Extra set ctrl_bypass" */ spm_write(INFRA_TOPAXI_SI0_CTL, spm_read(INFRA_TOPAXI_SI0_CTL) | 0x2); /* TINFO="Set bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_SET, MFG_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK #ifdef TOPAXI_PROTECT_LOCK spm_topaxi_protect_ready1(MFG_PROT_BIT_ACK_MASK); #else while ((spm_read(INFRA_TOPAXI_PROTECTEN_STA1) & MFG_PROT_BIT_ACK_MASK) != MFG_PROT_BIT_ACK_MASK) { /* */ /* */ } #endif #endif /* TINFO="Set SRAM_PDN = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | MFG_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until MFG_SRAM_PDN_ACK = 1" */ while ((spm_read(MFG_PWR_CON) & MFG_SRAM_PDN_ACK) != MFG_SRAM_PDN_ACK) { /* Need f_fmfg_core_ck for SRAM PDN delay IP. */ /* */ /* */ } #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & MFG_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & MFG_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Finish to turn off MFG" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on MFG" */ /* TINFO="Set PWR_ON = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & MFG_PWR_STA_MASK) != MFG_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & MFG_PWR_STA_MASK) != MFG_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) | PWR_RST_B); /* TINFO="Set SRAM_PDN = 0" */ spm_write(MFG_PWR_CON, spm_read(MFG_PWR_CON) & ~(0x1 << 5)); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until MFG_SRAM_PDN_ACK_BIT0 = 0" */ while (spm_read(MFG_PWR_CON) & MFG_SRAM_PDN_ACK_BIT0) { /* Need f_fmfg_core_ck for SRAM PDN delay IP. */ /* */ } #endif /* TINFO="Release bus protect" */ spm_write(INFRA_TOPAXI_PROTECTEN_CLR, MFG_PROT_BIT_MASK); #ifndef IGNORE_MTCMOS_CHECK /* Note that this protect ack check after releasing protect has been ignored */ #endif /* TINFO="Extra set ctrl_bypass" */ spm_write(INFRA_TOPAXI_SI0_CTL, spm_read(INFRA_TOPAXI_SI0_CTL) & (~(0x2))); /* TINFO="Extra set after releasing bus protect of MFG (way_en enable)" */ spm_write(INFRA_TOPAXI_SI0_CTL, spm_read(INFRA_TOPAXI_SI0_CTL) | (0x1<<7)); #ifndef IGNORE_MTCMOS_CHECK while (((spm_read(INFRA_TOPAXI_SI0_STA) & CTRL_UPDATE_BIT) != CTRL_UPDATE_BIT) && !((spm_read(INFRA_TOPAXI_SI0_STA) | ~(WR_RD_OT_BUSY_BIT)) == ~(WR_RD_OT_BUSY_BIT))) { /* */ /* */ } #endif /* TINFO="Finish to turn on MFG" */ } return err; } int spm_mtcmos_ctrl_isp(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off ISP" */ /* TINFO="Set SRAM_PDN = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | ISP_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until ISP_SRAM_PDN_ACK = 1" */ while ((spm_read(ISP_PWR_CON) & ISP_SRAM_PDN_ACK) != ISP_SRAM_PDN_ACK) { /* Need hf_fmm_ck for SRAM PDN delay IP. */ /* */ } #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & ISP_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & ISP_PWR_STA_MASK)) { } #endif /* TINFO="Finish to turn off ISP" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on ISP" */ /* TINFO="Set PWR_ON = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & ISP_PWR_STA_MASK) != ISP_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & ISP_PWR_STA_MASK) != ISP_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) | PWR_RST_B); /* TINFO="Set SRAM_PDN = 0" */ spm_write(ISP_PWR_CON, spm_read(ISP_PWR_CON) & ~(0x1 << 5)); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until ISP_SRAM_PDN_ACK_BIT0 = 0" */ while (spm_read(ISP_PWR_CON) & ISP_SRAM_PDN_ACK_BIT0) { /* Need hf_fmm_ck for SRAM PDN delay IP. */ /* */ /* */ } #endif /* TINFO="Finish to turn on ISP" */ } return err; } int spm_mtcmos_ctrl_vcodec(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off VCODEC" */ /* TINFO="Set SRAM_PDN = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | VCODEC_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until VCODEC_SRAM_PDN_ACK = 1" */ while ((spm_read(VCODEC_PWR_CON) & VCODEC_SRAM_PDN_ACK) != VCODEC_SRAM_PDN_ACK) { /* Need hf_fmm_ck for SRAM PDN delay IP. */ /* */ } #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & VCODEC_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & VCODEC_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Finish to turn off VCODEC" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on VCODEC" */ /* TINFO="Set PWR_ON = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & VCODEC_PWR_STA_MASK) != VCODEC_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & VCODEC_PWR_STA_MASK) != VCODEC_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) | PWR_RST_B); /* TINFO="Set SRAM_PDN = 0" */ spm_write(VCODEC_PWR_CON, spm_read(VCODEC_PWR_CON) & ~(0x1 << 5)); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until VCODEC_SRAM_PDN_ACK_BIT0 = 0" */ while (spm_read(VCODEC_PWR_CON) & VCODEC_SRAM_PDN_ACK_BIT0) { /* */ /* */ } #endif /* TINFO="Finish to turn on VCODEC" */ } return err; } int spm_mtcmos_ctrl_mfg_core0(int state) { int err = 0; if (state == STA_POWER_DOWN) { /* TINFO="Start to turn off MFG_CORE0" */ /* TINFO="Set SRAM_PDN = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | MFG_CORE0_SRAM_PDN); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until MFG_CORE0_SRAM_PDN_ACK = 1" */ while ((spm_read(MFG_CORE0_PWR_CON) & MFG_CORE0_SRAM_PDN_ACK) != MFG_CORE0_SRAM_PDN_ACK) { /* */ /* */ } #endif /* TINFO="Set PWR_ISO = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | PWR_ISO); /* TINFO="Set PWR_CLK_DIS = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | PWR_CLK_DIS); /* TINFO="Set PWR_RST_B = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~PWR_RST_B); /* TINFO="Set PWR_ON = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~PWR_ON); /* TINFO="Set PWR_ON_2ND = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 0 and PWR_STATUS_2ND = 0" */ while ((spm_read(PWR_STATUS) & MFG_CORE0_PWR_STA_MASK) || (spm_read(PWR_STATUS_2ND) & MFG_CORE0_PWR_STA_MASK)) { /* */ /* */ } #endif /* TINFO="Finish to turn off MFG_CORE0" */ } else { /* STA_POWER_ON */ /* TINFO="Start to turn on MFG_CORE0" */ /* TINFO="Set PWR_ON = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | PWR_ON); /* TINFO="Set PWR_ON_2ND = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | PWR_ON_2ND); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until PWR_STATUS = 1 and PWR_STATUS_2ND = 1" */ while (((spm_read(PWR_STATUS) & MFG_CORE0_PWR_STA_MASK) != MFG_CORE0_PWR_STA_MASK) || ((spm_read(PWR_STATUS_2ND) & MFG_CORE0_PWR_STA_MASK) != MFG_CORE0_PWR_STA_MASK)) { /* No logic between pwr_on and pwr_ack. Print SRAM / MTCMOS control and PWR_ACK for debug. */ /* */ } #endif /* TINFO="Set PWR_CLK_DIS = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~PWR_CLK_DIS); /* TINFO="Set PWR_ISO = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~PWR_ISO); /* TINFO="Set PWR_RST_B = 1" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) | PWR_RST_B); /* TINFO="Set SRAM_PDN = 0" */ spm_write(MFG_CORE0_PWR_CON, spm_read(MFG_CORE0_PWR_CON) & ~(0x1 << 5)); #ifndef IGNORE_MTCMOS_CHECK /* TINFO="Wait until MFG_CORE0_SRAM_PDN_ACK_BIT0 = 0" */ while (spm_read(MFG_CORE0_PWR_CON) & MFG_CORE0_SRAM_PDN_ACK_BIT0) { /* */ /* */ } #endif /* TINFO="Finish to turn on MFG_CORE0" */ } return err; } /* auto-gen end*/ /* enable op*/ /* *static int general_sys_enable_op(struct subsys *sys) *{ * return spm_mtcmos_power_on_general_locked(sys, 1, 0); *} */ static int MFG0_sys_enable_op(struct subsys *sys) { /*pr_debug("MFG0_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_mfg(STA_POWER_ON); } static int MFG1_sys_enable_op(struct subsys *sys) { /*pr_debug("MFG1_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_mfg_core0(STA_POWER_ON); } static int MD1_sys_enable_op(struct subsys *sys) { return spm_mtcmos_ctrl_md1(STA_POWER_ON); } static int CONN_sys_enable_op(struct subsys *sys) { /*pr_debug("CONN_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_conn(STA_POWER_ON); } static int MM0_sys_enable_op(struct subsys *sys) { /*pr_debug("MM0_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_dis(STA_POWER_ON); } static int ISP_sys_enable_op(struct subsys *sys) { /*pr_debug("ISP_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_isp(STA_POWER_ON); } static int VEN_sys_enable_op(struct subsys *sys) { /*pr_debug("VEN_sys_enable_op\r\n"); */ return spm_mtcmos_ctrl_vcodec(STA_POWER_ON); } /* disable op */ /* *static int general_sys_disable_op(struct subsys *sys) *{ * return spm_mtcmos_power_off_general_locked(sys, 1, 0); *} */ static int MFG0_sys_disable_op(struct subsys *sys) { /*pr_debug("MFG0_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_mfg(STA_POWER_DOWN); } static int MFG1_sys_disable_op(struct subsys *sys) { /*pr_debug("MFG1_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_mfg_core0(STA_POWER_DOWN); } static int MD1_sys_disable_op(struct subsys *sys) { return spm_mtcmos_ctrl_md1(STA_POWER_DOWN); } static int CONN_sys_disable_op(struct subsys *sys) { /*pr_debug("CONN_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_conn(STA_POWER_DOWN); } static int MM0_sys_disable_op(struct subsys *sys) { /*pr_debug("MM0_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_dis(STA_POWER_DOWN); } static int ISP_sys_disable_op(struct subsys *sys) { /*pr_debug("ISP_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_isp(STA_POWER_DOWN); } static int VEN_sys_disable_op(struct subsys *sys) { /*pr_debug("VEN_sys_disable_op\r\n"); */ return spm_mtcmos_ctrl_vcodec(STA_POWER_DOWN); } static int sys_get_state_op(struct subsys *sys) { unsigned int sta = clk_readl(PWR_STATUS); unsigned int sta_s = clk_readl(PWR_STATUS_2ND); return (sta & sys->sta_mask) && (sta_s & sys->sta_mask); } /* ops */ /* *static struct subsys_ops general_sys_ops = { * .enable = general_sys_enable_op, * .disable = general_sys_disable_op, * .get_state = sys_get_state_op, *}; */ static struct subsys_ops MFG0_sys_ops = { .enable = MFG0_sys_enable_op, .disable = MFG0_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops MFG1_sys_ops = { .enable = MFG1_sys_enable_op, .disable = MFG1_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops MD1_sys_ops = { .enable = MD1_sys_enable_op, .disable = MD1_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops CONN_sys_ops = { .enable = CONN_sys_enable_op, .disable = CONN_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops MM0_sys_ops = { .enable = MM0_sys_enable_op, .disable = MM0_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops ISP_sys_ops = { .enable = ISP_sys_enable_op, .disable = ISP_sys_disable_op, .get_state = sys_get_state_op, }; static struct subsys_ops VEN_sys_ops = { .enable = VEN_sys_enable_op, .disable = VEN_sys_disable_op, .get_state = sys_get_state_op, }; static int subsys_is_on(enum subsys_id id) { int r; struct subsys *sys = id_to_sys(id); WARN_ON(!sys); r = sys->ops->get_state(sys); #if MT_CCF_DEBUG pr_debug("[CCF] %s:%d, sys=%s, id=%d\n", __func__, r, sys->name, id); #endif /* MT_CCF_DEBUG */ return r; } #if CONTROL_LIMIT int allow[NR_SYSS] = { 1, /*SYS_MFG0*/ 0, /*SYS_MFG1*/ 1, /*SYS_MD1*/ 1, /*SYS_CONN*/ 1, /*SYS_MM0*/ 1, /*SYS_ISP*/ 1, /*SYS_VEN*/ }; #endif static int enable_subsys(enum subsys_id id) { int r; unsigned long flags; struct subsys *sys = id_to_sys(id); struct pg_callbacks *pgcb; unsigned long spinlock_save_flags; WARN_ON(!sys); #if MT_CCF_BRINGUP /*pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id);*/ switch (id) { case SYS_MD1: spm_mtcmos_ctrl_md1(STA_POWER_ON); break; case SYS_CONN: spm_mtcmos_ctrl_conn(STA_POWER_ON); break; default: break; } return 0; #endif /* MT_CCF_BRINGUP */ #if CONTROL_LIMIT #if MT_CCF_DEBUG pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id); #endif if (allow[id] == 0) { #if MT_CCF_DEBUG pr_debug("[CCF] %s: do nothing return\n", __func__); #endif return 0; } #endif mtk_clk_lock(flags); #if CHECK_PWR_ST if (sys->ops->get_state(sys) == SUBSYS_PWR_ON) { mtk_clk_unlock(flags); return 0; } #endif /* CHECK_PWR_ST */ r = sys->ops->enable(sys); WARN_ON(r); mtk_clk_unlock(flags); spin_lock_irqsave(&pgcb_lock, spinlock_save_flags); list_for_each_entry(pgcb, &pgcb_list, list) { if (!pgcb) { pr_notice("pgcb(%d) null\r\n", id); WARN_ON(1); } if (pgcb && pgcb->after_on) pgcb->after_on(id); } spin_unlock_irqrestore(&pgcb_lock, spinlock_save_flags); return r; } static int disable_subsys(enum subsys_id id) { int r; unsigned long flags; struct subsys *sys = id_to_sys(id); struct pg_callbacks *pgcb; unsigned long spinlock_save_flags; WARN_ON(!sys); #if MT_CCF_BRINGUP /*pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id);*/ switch (id) { case SYS_MD1: spm_mtcmos_ctrl_md1(STA_POWER_DOWN); break; case SYS_CONN: spm_mtcmos_ctrl_conn(STA_POWER_DOWN); break; default: break; } return 0; #endif /* MT_CCF_BRINGUP */ #if CONTROL_LIMIT #if MT_CCF_DEBUG pr_debug("[CCF] %s: sys=%s, id=%d\n", __func__, sys->name, id); #endif if (allow[id] == 0) { #if MT_CCF_DEBUG pr_debug("[CCF] %s: do nothing return\n", __func__); #endif return 0; } #endif /* TODO: check all clocks related to this subsys are off */ /* could be power off or not */ spin_lock_irqsave(&pgcb_lock, spinlock_save_flags); list_for_each_entry_reverse(pgcb, &pgcb_list, list) { if (!pgcb) { pr_notice("pgcb(%d) null\r\n", id); WARN_ON(1); } if (pgcb && pgcb->before_off) pgcb->before_off(id); } spin_unlock_irqrestore(&pgcb_lock, spinlock_save_flags); mtk_clk_lock(flags); #if CHECK_PWR_ST if (sys->ops->get_state(sys) == SUBSYS_PWR_DOWN) { mtk_clk_unlock(flags); return 0; } #endif /* CHECK_PWR_ST */ r = sys->ops->disable(sys); WARN_ON(r); mtk_clk_unlock(flags); return r; } /* * power_gate */ struct mt_power_gate { struct clk_hw hw; struct clk *pre_clk; struct clk *pre_clk2; enum subsys_id pd_id; }; #define to_power_gate(_hw) container_of(_hw, struct mt_power_gate, hw) static int pg_enable(struct clk_hw *hw) { struct mt_power_gate *pg = to_power_gate(hw); #if MT_CCF_DEBUG pr_debug("[CCF] %s: sys=%s, pd_id=%u\n", __func__, __clk_get_name(hw->clk), pg->pd_id); #endif /* MT_CCF_DEBUG */ return enable_subsys(pg->pd_id); } static void pg_disable(struct clk_hw *hw) { struct mt_power_gate *pg = to_power_gate(hw); #if MT_CCF_DEBUG pr_debug("[CCF] %s: sys=%s, pd_id=%u\n", __func__, __clk_get_name(hw->clk), pg->pd_id); #endif /* MT_CCF_DEBUG */ disable_subsys(pg->pd_id); } #if MT_CCF_BRINGUP static int pg_is_enabled_dummy(struct clk_hw *hw) { return 1; } #else static int pg_is_enabled(struct clk_hw *hw) { struct mt_power_gate *pg = to_power_gate(hw); return subsys_is_on(pg->pd_id); } #endif int pg_prepare(struct clk_hw *hw) { int r; struct mt_power_gate *pg = to_power_gate(hw); #if MT_CCF_DEBUG pr_debug("[CCF] %s: sys=%s, pre_sys=%s\n", __func__, __clk_get_name(hw->clk), pg->pre_clk ? __clk_get_name(pg->pre_clk) : ""); #endif /* MT_CCF_DEBUG */ if (pg->pre_clk) { r = clk_prepare_enable(pg->pre_clk); if (r) return r; } if (pg->pre_clk2) { r = clk_prepare_enable(pg->pre_clk2); if (r) return r; } return pg_enable(hw); } void pg_unprepare(struct clk_hw *hw) { struct mt_power_gate *pg = to_power_gate(hw); #if MT_CCF_DEBUG pr_debug("[CCF] %s: clk=%s, pre_clk=%s\n", __func__, __clk_get_name(hw->clk), pg->pre_clk ? __clk_get_name(pg->pre_clk) : ""); #endif /* MT_CCF_DEBUG */ pg_disable(hw); if (pg->pre_clk) clk_disable_unprepare(pg->pre_clk); if (pg->pre_clk2) clk_disable_unprepare(pg->pre_clk2); } static const struct clk_ops mt_power_gate_ops = { .prepare = pg_prepare, .unprepare = pg_unprepare, #if MT_CCF_BRINGUP .is_enabled = pg_is_enabled_dummy, #else .is_enabled = pg_is_enabled, #endif }; struct clk *mt_clk_register_power_gate(const char *name, const char *parent_name, struct clk *pre_clk, struct clk *pre_clk2, enum subsys_id pd_id) { struct mt_power_gate *pg; struct clk *clk; struct clk_init_data init = {}; pg = kzalloc(sizeof(*pg), GFP_KERNEL); if (!pg) return ERR_PTR(-ENOMEM); init.name = name; init.flags = CLK_IGNORE_UNUSED; init.parent_names = parent_name ? &parent_name : NULL; init.num_parents = parent_name ? 1 : 0; init.ops = &mt_power_gate_ops; pg->pre_clk = pre_clk; pg->pre_clk2 = pre_clk2; pg->pd_id = pd_id; pg->hw.init = &init; clk = clk_register(NULL, &pg->hw); if (IS_ERR(clk)) kfree(pg); return clk; } #define pg_mfg0 "pg_mfg0" #define pg_mfg1 "pg_mfg1" #define pg_md1 "pg_md1" #define pg_conn "pg_conn" #define pg_mm0 "pg_mm0" #define pg_isp "pg_isp" #define pg_ven "pg_ven" #define mm_sel "mm_sel" #define cam_sel "cam_sel" #define seninf_sel "seninf_sel" #define img_sel "img_sel" #define venc_sel "venc_sel" #define vdec_sel "vdec_sel" #define ipu_if_sel "ipu_if_sel" #define dsp_sel "dsp_sel" #define mfg_sel "mfg_sel" struct mtk_power_gate { int id; const char *name; const char *parent_name; const char *pre_clk_name; const char *pre_clk2_name; enum subsys_id pd_id; }; #define PGATE(_id, _name, _parent, _pre_clk, _pd_id) { \ .id = _id, \ .name = _name, \ .parent_name = _parent, \ .pre_clk_name = _pre_clk, \ .pd_id = _pd_id, \ } #define PGATE2(_id, _name, _parent, _pre_clk, _pre_clk2, _pd_id) { \ .id = _id, \ .name = _name, \ .parent_name = _parent, \ .pre_clk_name = _pre_clk, \ .pre_clk2_name = _pre_clk2, \ .pd_id = _pd_id, \ } #if 1 /* FIXME: all values needed to be verified */ struct mtk_power_gate scp_clks[] __initdata = { PGATE2(SCP_SYS_MFG0, pg_mfg0, NULL, mfg_sel, NULL, SYS_MFG0), PGATE2(SCP_SYS_MFG1, pg_mfg1, NULL, NULL, NULL, SYS_MFG1), PGATE2(SCP_SYS_MD1, pg_md1, NULL, NULL, NULL, SYS_MD1), PGATE2(SCP_SYS_CONN, pg_conn, NULL, NULL, NULL, SYS_CONN), PGATE2(SCP_SYS_MM0, pg_mm0, NULL, mm_sel, NULL, SYS_MM0), PGATE2(SCP_SYS_ISP, pg_isp, NULL, mm_sel, NULL, SYS_ISP), PGATE2(SCP_SYS_VEN, pg_ven, NULL, mm_sel, NULL, SYS_VEN), }; #endif static int init_clk_scpsys(void __iomem *infracfg_reg, void __iomem *spm_reg, struct clk_onecell_data *clk_data) { int i; struct clk *clk; struct clk *pre_clk; struct clk *pre_clk2; infracfg_base = infracfg_reg; spm_base = spm_reg; syss[SYS_MFG0].ctl_addr = MFG_PWR_CON; syss[SYS_MFG1].ctl_addr = MFG_CORE0_PWR_CON; syss[SYS_MD1].ctl_addr = MD1_PWR_CON; syss[SYS_CONN].ctl_addr = CONN_PWR_CON; syss[SYS_MM0].ctl_addr = DIS_PWR_CON; syss[SYS_ISP].ctl_addr = ISP_PWR_CON; syss[SYS_VEN].ctl_addr = VCODEC_PWR_CON; for (i = 0; i < ARRAY_SIZE(scp_clks); i++) { struct mtk_power_gate *pg = &scp_clks[i]; pre_clk = pg->pre_clk_name ? __clk_lookup(pg->pre_clk_name) : NULL; pre_clk2 = pg->pre_clk2_name ? __clk_lookup(pg->pre_clk2_name) : NULL; /*clk = mt_clk_register_power_gate(pg->name, pg->parent_name, pre_clk, pg->pd_id);*/ clk = mt_clk_register_power_gate(pg->name, pg->parent_name, pre_clk, pre_clk2, pg->pd_id); if (IS_ERR(clk)) { pr_debug("[CCF] %s: Failed to register clk %s: %ld\n", __func__, pg->name, PTR_ERR(clk)); continue; } if (clk_data) clk_data->clks[pg->id] = clk; #if MT_CCF_DEBUG pr_debug("[CCF] %s: pgate %3d: %s\n", __func__, i, pg->name); #endif /* MT_CCF_DEBUG */ } return 0; } /* * device tree support */ /* TODO: remove this function */ static struct clk_onecell_data *alloc_clk_data(unsigned int clk_num) { int i; struct clk_onecell_data *clk_data; clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); if (!clk_data) return NULL; clk_data->clks = kcalloc(clk_num, sizeof(struct clk *), GFP_KERNEL); if (!clk_data->clks) { kfree(clk_data); return NULL; } clk_data->clk_num = clk_num; for (i = 0; i < clk_num; ++i) clk_data->clks[i] = ERR_PTR(-ENOENT); return clk_data; } /* TODO: remove this function */ static void __iomem *get_reg(struct device_node *np, int index) { #if DUMMY_REG_TEST return kzalloc(PAGE_SIZE, GFP_KERNEL); #else return of_iomap(np, index); #endif } #ifdef CONFIG_OF void iomap_mm(void) { struct device_node *node; /*mmsys_config*/ node = of_find_compatible_node(NULL, NULL, "mediatek,mmsys_config"); if (!node) pr_debug("[CLK_MMSYS] find node failed\n"); clk_mmsys_config_base = of_iomap(node, 0); if (!clk_mmsys_config_base) pr_debug("[CLK_MMSYS] base failed\n"); /*imgsys*/ node = of_find_compatible_node(NULL, NULL, "mediatek,imgsys"); if (!node) pr_debug("[CLK_IMGSYS_CONFIG] find node failed\n"); clk_imgsys_base = of_iomap(node, 0); if (!clk_imgsys_base) pr_debug("[CLK_IMGSYS_CONFIG] base failed\n"); /*venc_gcon*/ node = of_find_compatible_node(NULL, NULL, "mediatek,venc_global_con"); if (!node) pr_debug("[CLK_VENC_GCON] find node failed\n"); clk_venc_gcon_base = of_iomap(node, 0); if (!clk_venc_gcon_base) pr_debug("[CLK_VENC_GCON] base failed\n"); } #endif /*Bus Protect*/ void mm0_mtcmos_patch(int on) { } void ven_mtcmos_patch(void) { } void isp_mtcmos_patch(int on) { } static int clk_mt6739_scpsys_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_onecell_data *clk_data; void __iomem *infracfg_reg; void __iomem *spm_reg; int r; pr_notice("%s: start\n", __func__); if (!node) { pr_err("%s: node is null\n", __func__); return -EINVAL; } infracfg_reg = get_reg(node, 0); spm_reg = get_reg(node, 1); infra_base = get_reg(node, 2); if (!infracfg_reg || !spm_reg) { pr_debug("clk-pg-mt6739: missing reg\n"); return -EINVAL; } /* * pr_debug("[CCF] %s: sys: %s, reg: 0x%p, 0x%p\n", * __func__, node->name, infracfg_reg, spm_reg); */ clk_data = alloc_clk_data(NR_SYSS); if (!clk_data) return -ENOMEM; init_clk_scpsys(infracfg_reg, spm_reg, clk_data); r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) pr_info("[CCF] %s:could not register clock provide\n", __func__); spin_lock_init(&pgcb_lock); /*MM Bus*/ iomap_mm(); #if !MT_CCF_BRINGUP /* subsys init: per modem owner request, disable modem power first */ disable_subsys(SYS_MD1); #else /*power on all subsys for bring up */ #ifndef CONFIG_FPGA_EARLY_PORTING spm_mtcmos_ctrl_mfg(STA_POWER_ON); spm_mtcmos_ctrl_mfg_core0(STA_POWER_ON); spm_mtcmos_ctrl_md1(STA_POWER_DOWN);/*do after ccif*/ /*spm_mtcmos_ctrl_conn(STA_POWER_ON);*/ spm_mtcmos_ctrl_dis(STA_POWER_ON); spm_mtcmos_ctrl_isp(STA_POWER_ON); spm_mtcmos_ctrl_vcodec(STA_POWER_ON); #endif #endif /* !MT_CCF_BRINGUP */ pr_notice("%s: done\n", __func__); return r; } //CLK_OF_DECLARE_DRIVER(mtk_pg_regs, "mediatek,scpsys", mt_scpsys_init); int mtcmos_mfg_series_on(void) { unsigned int sta = spm_read(PWR_STATUS); unsigned int sta_s = spm_read(PWR_STATUS_2ND); int ret; ret = 0; ret |= (sta & (1U << 1)) && (sta_s & (1U << 1)); ret |= ((sta & (1U << 2)) && (sta_s & (1U << 2))) << 1; ret |= ((sta & (1U << 3)) && (sta_s & (1U << 3))) << 2; ret |= ((sta & (1U << 4)) && (sta_s & (1U << 4))) << 3; /*mfgsys_cg_check();*/ return ret; } void subsys_if_on(void) { unsigned int sta = spm_read(PWR_STATUS); unsigned int sta_s = spm_read(PWR_STATUS_2ND); int ret = 0; if ((sta & (1U << 1)) && (sta_s & (1U << 0))) pr_info("suspend warning: SYS_MD1 is on!!!\n"); if ((sta & (1U << 2)) && (sta_s & (1U << 1))) pr_info("suspend warning: SYS_CONN is on!!!\n"); if ((sta & (1U << 7)) && (sta_s & (1U << 3))) { pr_info("suspend warning: SYS_DISP is on!!!\n"); check_mm0_clk_sts(); ret++; } if ((sta & (1U << 10)) && (sta_s & (1U << 4))) pr_info("suspend warning: SYS_MFG is on!!!\n"); if ((sta & (1U << 14)) && (sta_s & (1U << 5))) { pr_info("suspend warning: SYS_ISP is on!!!\n"); check_img_clk_sts(); ret++; } if ((sta & (1U << 17)) && (sta_s & (1U << 7))) { pr_info("suspend warning: SYS_VCODEC is on!!!\n"); check_ven_clk_sts(); ret++; } if ((sta & (1U << 18)) && (sta_s & (1U << 31))) pr_info("suspend warning: SYS_MFG_CORE0 is on!!!\n"); #if 0 if (ret > 0) WARN_ON(); #endif } #if 1 /*only use for suspend test*/ void mtcmos_force_off(void) { spm_mtcmos_ctrl_mfg_core0(STA_POWER_DOWN); spm_mtcmos_ctrl_mfg(STA_POWER_DOWN); spm_mtcmos_ctrl_conn(STA_POWER_DOWN); spm_mtcmos_ctrl_isp(STA_POWER_DOWN); spm_mtcmos_ctrl_vcodec(STA_POWER_DOWN); spm_mtcmos_ctrl_dis(STA_POWER_DOWN); } #endif static const struct of_device_id of_match_clk_mt6739_scpsys[] = { { .compatible = "mediatek,scpsys", }, {} }; static struct platform_driver clk_mt6739_scpsys_drv = { .probe = clk_mt6739_scpsys_probe, .driver = { .name = "clk-mt6739-scpsys", .owner = THIS_MODULE, .of_match_table = of_match_clk_mt6739_scpsys, }, }; static int __init clk_mt6739_scpsys_init(void) { return platform_driver_register(&clk_mt6739_scpsys_drv); } static void __exit clk_mt6739_scpsys_exit(void) { } #if CLK_DEBUG /* * debug / unit test */ #include #include #include #include static char last_cmd[128] = "null"; static int test_pg_dump_regs(struct seq_file *s, void *v) { int i; for (i = 0; i < NR_SYSS; i++) { if (!syss[i].ctl_addr) continue; seq_printf(s, "%10s: [0x%p]: 0x%08x\n", syss[i].name, syss[i].ctl_addr, clk_readl(syss[i].ctl_addr)); } return 0; } static void dump_pg_state(const char *clkname, struct seq_file *s) { struct clk *c = __clk_lookup(clkname); struct clk *p = IS_ERR_OR_NULL(c) ? NULL : __clk_get_parent(c); if (IS_ERR_OR_NULL(c)) { seq_printf(s, "[%17s: NULL]\n", clkname); return; } seq_printf(s, "[%17s: %3s, %3d, %3d, %10ld, %17s]\n", __clk_get_name(c), __clk_is_enabled(c) ? "ON" : "off", __clk_get_prepare_count(c), __clk_get_enable_count(c), __clk_get_rate(c), p ? __clk_get_name(p) : ""); clk_put(c); } static int test_pg_dump_state_all(struct seq_file *s, void *v) { static const char *const clks[] = { pg_mfg0, pg_mfg1, pg_md1, pg_conn, pg_mm0, pg_isp, pg_ven, }; int i; /* pr_debug("\n");*/ for (i = 0; i < ARRAY_SIZE(clks); i++) dump_pg_state(clks[i], s); return 0; } static struct { const char *name; struct clk *clk; } g_clks[] = { { .name = pg_md1}, { .name = pg_ven}, { .name = pg_mfg},}; static int test_pg_1(struct seq_file *s, void *v) { int i; /* pr_debug("\n");*/ for (i = 0; i < ARRAY_SIZE(g_clks); i++) { g_clks[i].clk = __clk_lookup(g_clks[i].name); if (IS_ERR_OR_NULL(g_clks[i].clk)) { seq_printf(s, "clk_get(%s): NULL\n", g_clks[i].name); continue; } clk_prepare_enable(g_clks[i].clk); seq_printf(s, "clk_prepare_enable(%s)\n", __clk_get_name(g_clks[i].clk)); } return 0; } static int test_pg_2(struct seq_file *s, void *v) { int i; /* pr_debug("\n");*/ for (i = 0; i < ARRAY_SIZE(g_clks); i++) { if (IS_ERR_OR_NULL(g_clks[i].clk)) { seq_printf(s, "(%s).clk: NULL\n", g_clks[i].name); continue; } seq_printf(s, "clk_disable_unprepare(%s)\n", __clk_get_name(g_clks[i].clk)); clk_disable_unprepare(g_clks[i].clk); clk_put(g_clks[i].clk); } return 0; } static int test_pg_show(struct seq_file *s, void *v) { static const struct { int (*fn)(struct seq_file *, void *); const char *cmd; } cmds[] = { { .cmd = "dump_regs", .fn = test_pg_dump_regs}, { .cmd = "dump_state", .fn = test_pg_dump_state_all}, { .cmd = "1", .fn = test_pg_1}, { .cmd = "2", .fn = test_pg_2},}; int i; /* pr_debug("last_cmd: %s\n", last_cmd);*/ for (i = 0; i < ARRAY_SIZE(cmds); i++) { if (strcmp(cmds[i].cmd, last_cmd) == 0) return cmds[i].fn(s, v); } return 0; } static int test_pg_open(struct inode *inode, struct file *file) { return single_open(file, test_pg_show, NULL); } static ssize_t test_pg_write(struct file *file, const char __user *buffer, size_t count, loff_t *data) { char desc[sizeof(last_cmd)]; int len = 0; /* pr_debug("count: %zu\n", count);*/ len = (count < (sizeof(desc) - 1)) ? count : (sizeof(desc) - 1); if (copy_from_user(desc, buffer, len)) return 0; desc[len] = '\0'; strcpy(last_cmd, desc); if (last_cmd[len - 1] == '\n') last_cmd[len - 1] = 0; return count; } static const struct file_operations test_pg_fops = { .owner = THIS_MODULE, .open = test_pg_open, .read = seq_read, .write = test_pg_write, .llseek = seq_lseek, .release = single_release, }; static int __init debug_init(void) { static int init; struct proc_dir_entry *entry; /* pr_debug("init: %d\n", init);*/ if (init) return 0; ++init; entry = proc_create("test_pg", 0, 0, &test_pg_fops); if (!entry) return -ENOMEM; ++init; return 0; } static void __exit debug_exit(void) { remove_proc_entry("test_pg", NULL); } module_init(debug_init); module_exit(debug_exit); #endif /* CLK_DEBUG */ arch_initcall(clk_mt6739_scpsys_init); module_exit(clk_mt6739_scpsys_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("MTK"); MODULE_DESCRIPTION("MTK CCF Driver");