From 3a3672cc3769a43750dd9fea90ed7a7900cb227f Mon Sep 17 00:00:00 2001 From: Weijie Gao Date: Tue, 20 Apr 2021 16:37:10 +0800 Subject: [PATCH 1/7] mmc: mtk-sd: increase the minimum bus frequency With a 48MHz input clock, the lowest bus frequency can be as low as 48000000 / (4 * 4095) = 2930Hz. Such an extremely low frequency will cause the mmc framework take seconds to finish the initialization. Limiting the minimum bus frequency to a slightly higher value can solve the issue without any side effects. Reviewed-by: Jaehoon Chung Signed-off-by: Weijie Gao --- drivers/mmc/mtk-sd.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 48a764be82..8599f095bc 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -232,6 +232,8 @@ #define SCLK_CYCLES_SHIFT 20 +#define MIN_BUS_CLK 200000 + #define CMD_INTS_MASK \ (MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO) @@ -1639,6 +1641,9 @@ static int msdc_drv_probe(struct udevice *dev) else cfg->f_min = host->src_clk_freq / (4 * 4095); + if (cfg->f_min < MIN_BUS_CLK) + cfg->f_min = MIN_BUS_CLK; + if (cfg->f_max < cfg->f_min || cfg->f_max > host->src_clk_freq) cfg->f_max = host->src_clk_freq; From 8cb9d3ed3a6402f984356988c581546866acf0da Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Mon, 26 Apr 2021 11:35:05 +0800 Subject: [PATCH 2/7] mmc: dw_mmc: Fixes data read when receiving DTO interrupt in FIFO mode The data read is not working when using FIFO mode. From DesignWare databook, when a Data_Transfer_Over (DTO) interrupt is received, the software should read the remaining data from FIFO. Add DTO interrupt checking on data read path and clear interrupts before start reading from FIFO. So, it doesn't clear the next pending interrupts unintentionally after read from FIFO. Signed-off-by: Ley Foon Tan Reviewed-by: Jaehoon Chung --- drivers/mmc/dw_mmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 7c8a312fa7..a949dad574 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -166,7 +166,9 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) if (host->fifo_mode && size) { len = 0; if (data->flags == MMC_DATA_READ && - (mask & DWMCI_INTMSK_RXDR)) { + (mask & (DWMCI_INTMSK_RXDR | DWMCI_INTMSK_DTO))) { + dwmci_writel(host, DWMCI_RINTSTS, + DWMCI_INTMSK_RXDR | DWMCI_INTMSK_DTO); while (size) { ret = dwmci_fifo_ready(host, DWMCI_FIFO_EMPTY, @@ -182,8 +184,6 @@ static int dwmci_data_transfer(struct dwmci_host *host, struct mmc_data *data) dwmci_readl(host, DWMCI_DATA); size = size > len ? (size - len) : 0; } - dwmci_writel(host, DWMCI_RINTSTS, - DWMCI_INTMSK_RXDR); } else if (data->flags == MMC_DATA_WRITE && (mask & DWMCI_INTMSK_TXDR)) { while (size) { From 1925e65706b84ec83b99e6335d9a36d8644c9085 Mon Sep 17 00:00:00 2001 From: Ley Foon Tan Date: Mon, 26 Apr 2021 13:17:46 +0800 Subject: [PATCH 3/7] mmc: dwmmc: socfpga: Get "fifo-mode" property from DT Add FIFO mode support for SoCFPGA dwmmc, read "fifo-mode" property from DT. Signed-off-by: Ley Foon Tan Reviewed-by: Jaehoon Chung --- drivers/mmc/socfpga_dw_mmc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index d6d2d57214..be3d8bfb3d 100644 --- a/drivers/mmc/socfpga_dw_mmc.c +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -144,6 +144,8 @@ static int socfpga_dwmmc_of_to_plat(struct udevice *dev) "smplsel", 0); host->priv = priv; + host->fifo_mode = dev_read_bool(dev, "fifo-mode"); + return 0; } From 5c2beda545dde4d27c0e893e97c74740ff27ff2f Mon Sep 17 00:00:00 2001 From: Reuben Dowle Date: Fri, 14 May 2021 10:15:43 +1200 Subject: [PATCH 4/7] mmc: Update environment variable with active partition This patch allows uboot scripts make choices about where to boot from based on the active mmc boot partition. This allows having two copies of kernel, filesystems etc, and choosing which to boot from based off of the active bootloader partition. Signed-off-by: Reuben Dowle Reviewed-by: Jaehoon Chung --- cmd/mmc.c | 14 +++++++++----- doc/usage/mmc.rst | 4 +++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index a10f137204..b942576b58 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -808,7 +808,7 @@ static int do_mmc_boot_resize(struct cmd_tbl *cmdtp, int flag, return CMD_RET_SUCCESS; } -static int mmc_partconf_print(struct mmc *mmc) +static int mmc_partconf_print(struct mmc *mmc, const char *varname) { u8 ack, access, part; @@ -821,6 +821,9 @@ static int mmc_partconf_print(struct mmc *mmc) ack = EXT_CSD_EXTRACT_BOOT_ACK(mmc->part_config); part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config); + if(varname) + env_set_hex(varname, part); + printf("EXT_CSD[179], PARTITION_CONFIG:\n" "BOOT_ACK: 0x%x\n" "BOOT_PARTITION_ENABLE: 0x%x\n" @@ -836,7 +839,7 @@ static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag, struct mmc *mmc; u8 ack, part_num, access; - if (argc != 2 && argc != 5) + if (argc != 2 && argc != 3 && argc != 5) return CMD_RET_USAGE; dev = simple_strtoul(argv[1], NULL, 10); @@ -850,8 +853,8 @@ static int do_mmc_partconf(struct cmd_tbl *cmdtp, int flag, return CMD_RET_FAILURE; } - if (argc == 2) - return mmc_partconf_print(mmc); + if (argc == 2 || argc == 3) + return mmc_partconf_print(mmc, argc == 3 ? argv[2] : NULL); ack = simple_strtoul(argv[2], NULL, 10); part_num = simple_strtoul(argv[3], NULL, 10); @@ -1061,8 +1064,9 @@ U_BOOT_CMD( " - Set the BOOT_BUS_WIDTH field of the specified device\n" "mmc bootpart-resize \n" " - Change sizes of boot and RPMB partitions of specified device\n" - "mmc partconf [boot_ack boot_partition partition_access]\n" + "mmc partconf [[varname] | [ ]]\n" " - Show or change the bits of the PARTITION_CONFIG field of the specified device\n" + " If showing the bits, optionally store the boot_partition field into varname\n" "mmc rst-function \n" " - Change the RST_n_FUNCTION field of the specified device\n" " WARNING: This is a write-once field and 0 / 1 / 2 are the only valid values.\n" diff --git a/doc/usage/mmc.rst b/doc/usage/mmc.rst index 458c7642c0..f20efe3d70 100644 --- a/doc/usage/mmc.rst +++ b/doc/usage/mmc.rst @@ -19,7 +19,7 @@ Synopsis mmc wp mmc bootbus mmc bootpart-resize - mmc partconf [boot_ack boot_partition partition_access] + mmc partconf [[varname] | [ ]] mmc rst-function Description @@ -92,6 +92,8 @@ The 'mmc bootbus' command sets the BOOT_BUS_WIDTH field. (*Refer to eMMC specifi The 'mmc partconf' command shows or changes PARTITION_CONFIG field. + varname + When showing the PARTITION_CONFIG, an optional environment variable to store the current boot_partition value into. boot_ack boot acknowledge value boot_partition From 2da2335a18a1b7123da08c325fdcd7960c0f0642 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 31 May 2021 08:31:49 +0900 Subject: [PATCH 5/7] mmc: fsl_esdhc_imx: use mmc_send_cmd instead of dm_mmc_send_cmd Use mmc_send_cmd instead of dm_mmc_send_cmd. It doesn't need to distinguish this function. Signed-off-by: Jaehoon Chung --- drivers/mmc/fsl_esdhc_imx.c | 2 +- drivers/mmc/mmc_private.h | 1 - include/mmc.h | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 566ce046ae..40c797c990 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -865,7 +865,7 @@ static void esdhc_stop_tuning(struct mmc *mmc) cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1b; - dm_mmc_send_cmd(mmc->dev, &cmd, NULL); + mmc_send_cmd(mmc, &cmd, NULL); } static int fsl_esdhc_execute_tuning(struct udevice *dev, uint32_t opcode) diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index a0900e8cad..a6cd250d29 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -12,7 +12,6 @@ #include -int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data); int mmc_send_status(struct mmc *mmc, unsigned int *status); int mmc_poll_for_busy(struct mmc *mmc, int timeout); diff --git a/include/mmc.h b/include/mmc.h index 8600881705..7f8ba2b017 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -795,6 +795,7 @@ int mmc_initialize(struct bd_info *bis); int mmc_init_device(int num); int mmc_init(struct mmc *mmc); int mmc_send_tuning(struct mmc *mmc, u32 opcode, int *cmd_error); +int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data); #if CONFIG_IS_ENABLED(MMC_UHS_SUPPORT) || \ CONFIG_IS_ENABLED(MMC_HS200_SUPPORT) || \ From d77d61ea1b21d93a5035719f82699bcbe8227364 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 31 May 2021 08:31:50 +0900 Subject: [PATCH 6/7] mmc: mmc-uclass: change to static about dm function Change to static about dm function. They can be used with wrapper functions. Signed-off-by: Jaehoon Chung --- drivers/mmc/mmc-uclass.c | 24 ++++++++++++------------ include/mmc.h | 12 ------------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index d36aae367e..579d7a1406 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -15,7 +15,7 @@ #include #include "mmc_private.h" -int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt) +static int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt) { struct dm_mmc_ops *ops = mmc_get_ops(dev); struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -31,7 +31,7 @@ int mmc_get_b_max(struct mmc *mmc, void *dst, lbaint_t blkcnt) return dm_mmc_get_b_max(mmc->dev, dst, blkcnt); } -int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, +static int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { struct mmc *mmc = mmc_get_mmc_dev(dev); @@ -53,7 +53,7 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) return dm_mmc_send_cmd(mmc->dev, cmd, data); } -int dm_mmc_set_ios(struct udevice *dev) +static int dm_mmc_set_ios(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -67,7 +67,7 @@ int mmc_set_ios(struct mmc *mmc) return dm_mmc_set_ios(mmc->dev); } -int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us) +static int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -81,7 +81,7 @@ int mmc_wait_dat0(struct mmc *mmc, int state, int timeout_us) return dm_mmc_wait_dat0(mmc->dev, state, timeout_us); } -int dm_mmc_get_wp(struct udevice *dev) +static int dm_mmc_get_wp(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -95,7 +95,7 @@ int mmc_getwp(struct mmc *mmc) return dm_mmc_get_wp(mmc->dev); } -int dm_mmc_get_cd(struct udevice *dev) +static int dm_mmc_get_cd(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -110,7 +110,7 @@ int mmc_getcd(struct mmc *mmc) } #ifdef MMC_SUPPORTS_TUNING -int dm_mmc_execute_tuning(struct udevice *dev, uint opcode) +static int dm_mmc_execute_tuning(struct udevice *dev, uint opcode) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -126,7 +126,7 @@ int mmc_execute_tuning(struct mmc *mmc, uint opcode) #endif #if CONFIG_IS_ENABLED(MMC_HS400_ES_SUPPORT) -int dm_mmc_set_enhanced_strobe(struct udevice *dev) +static int dm_mmc_set_enhanced_strobe(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -142,7 +142,7 @@ int mmc_set_enhanced_strobe(struct mmc *mmc) } #endif -int dm_mmc_hs400_prepare_ddr(struct udevice *dev) +static int dm_mmc_hs400_prepare_ddr(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -157,7 +157,7 @@ int mmc_hs400_prepare_ddr(struct mmc *mmc) return dm_mmc_hs400_prepare_ddr(mmc->dev); } -int dm_mmc_host_power_cycle(struct udevice *dev) +static int dm_mmc_host_power_cycle(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -171,7 +171,7 @@ int mmc_host_power_cycle(struct mmc *mmc) return dm_mmc_host_power_cycle(mmc->dev); } -int dm_mmc_deferred_probe(struct udevice *dev) +static int dm_mmc_deferred_probe(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); @@ -186,7 +186,7 @@ int mmc_deferred_probe(struct mmc *mmc) return dm_mmc_deferred_probe(mmc->dev); } -int dm_mmc_reinit(struct udevice *dev) +static int dm_mmc_reinit(struct udevice *dev) { struct dm_mmc_ops *ops = mmc_get_ops(dev); diff --git a/include/mmc.h b/include/mmc.h index 7f8ba2b017..6f943e78b7 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -539,18 +539,6 @@ struct dm_mmc_ops { #define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops) -int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, - struct mmc_data *data); -int dm_mmc_set_ios(struct udevice *dev); -int dm_mmc_get_cd(struct udevice *dev); -int dm_mmc_get_wp(struct udevice *dev); -int dm_mmc_execute_tuning(struct udevice *dev, uint opcode); -int dm_mmc_wait_dat0(struct udevice *dev, int state, int timeout_us); -int dm_mmc_host_power_cycle(struct udevice *dev); -int dm_mmc_deferred_probe(struct udevice *dev); -int dm_mmc_reinit(struct udevice *dev); -int dm_mmc_get_b_max(struct udevice *dev, void *dst, lbaint_t blkcnt); - /* Transition functions for compatibility */ int mmc_set_ios(struct mmc *mmc); int mmc_getcd(struct mmc *mmc); From f132aab403271ff00c0cfdd3af6504e87c7d0aaf Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 7 Jun 2021 17:40:09 -0300 Subject: [PATCH 7/7] Revert "mmc: fsl_esdhc_imx: use VENDORSPEC_FRC_SDCLK_ON to control card clock output" This reverts commit 63756575b42b8b4fb3f59cbbf0cedf03331bc2d2. Since this commit a imx6qdl-pico board boots extremely slowly in both SPL as well as U-Boot proper. Fix this regression by reverting the offending commit for now. Signed-off-by: Fabio Estevam Reviewed-by: Jaehoon Chung Tested-by: Pierre-Jean Texier --- drivers/mmc/fsl_esdhc_imx.c | 29 ++++++++--------------------- include/fsl_esdhc_imx.h | 2 -- 2 files changed, 8 insertions(+), 23 deletions(-) diff --git a/drivers/mmc/fsl_esdhc_imx.c b/drivers/mmc/fsl_esdhc_imx.c index 40c797c990..465d935daf 100644 --- a/drivers/mmc/fsl_esdhc_imx.c +++ b/drivers/mmc/fsl_esdhc_imx.c @@ -653,10 +653,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) clk = (pre_div << 8) | (div << 4); #ifdef CONFIG_FSL_USDHC - esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); - ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); - if (ret) - pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); #else esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); #endif @@ -668,7 +665,7 @@ static void set_sysctl(struct fsl_esdhc_priv *priv, struct mmc *mmc, uint clock) pr_warn("fsl_esdhc_imx: Internal clock never stabilised.\n"); #ifdef CONFIG_FSL_USDHC - esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | VENDORSPEC_CKEN); #else esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); #endif @@ -723,14 +720,8 @@ static void esdhc_set_strobe_dll(struct mmc *mmc) struct fsl_esdhc_priv *priv = dev_get_priv(mmc->dev); struct fsl_esdhc *regs = priv->esdhc_regs; u32 val; - u32 tmp; - int ret; if (priv->clock > ESDHC_STROBE_DLL_CLK_FREQ) { - esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); - ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); - if (ret) - pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); esdhc_write32(®s->strobe_dllctrl, ESDHC_STROBE_DLL_CTRL_RESET); /* @@ -748,7 +739,6 @@ static void esdhc_set_strobe_dll(struct mmc *mmc) pr_warn("HS400 strobe DLL status REF not lock!\n"); if (!(val & ESDHC_STROBE_DLL_STS_SLV_LOCK)) pr_warn("HS400 strobe DLL status SLV not lock!\n"); - esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); } } @@ -980,18 +970,14 @@ static int esdhc_set_ios_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) #ifdef MMC_SUPPORTS_TUNING if (mmc->clk_disable) { #ifdef CONFIG_FSL_USDHC - u32 tmp; - - esdhc_clrbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); - ret = readx_poll_timeout(esdhc_read32, ®s->prsstat, tmp, tmp & PRSSTAT_SDOFF, 100); - if (ret) - pr_warn("fsl_esdhc_imx: Internal clock never gate off.\n"); + esdhc_clrbits32(®s->vendorspec, VENDORSPEC_CKEN); #else esdhc_clrbits32(®s->sysctl, SYSCTL_CKEN); #endif } else { #ifdef CONFIG_FSL_USDHC - esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | + VENDORSPEC_CKEN); #else esdhc_setbits32(®s->sysctl, SYSCTL_PEREN | SYSCTL_CKEN); #endif @@ -1067,7 +1053,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) #ifndef CONFIG_FSL_USDHC esdhc_setbits32(®s->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN); #else - esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_HCKEN | VENDORSPEC_IPGEN); #endif /* Set the initial clock speed */ @@ -1205,7 +1191,8 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, esdhc_write32(®s->autoc12err, 0); esdhc_write32(®s->clktunectrlstatus, 0); #else - esdhc_setbits32(®s->vendorspec, VENDORSPEC_FRC_SDCLK_ON); + esdhc_setbits32(®s->vendorspec, VENDORSPEC_PEREN | + VENDORSPEC_HCKEN | VENDORSPEC_IPGEN | VENDORSPEC_CKEN); #endif if (priv->vs18_enable) diff --git a/include/fsl_esdhc_imx.h b/include/fsl_esdhc_imx.h index b092034464..45ed635a77 100644 --- a/include/fsl_esdhc_imx.h +++ b/include/fsl_esdhc_imx.h @@ -39,7 +39,6 @@ #define VENDORSPEC_HCKEN 0x00001000 #define VENDORSPEC_IPGEN 0x00000800 #define VENDORSPEC_INIT 0x20007809 -#define VENDORSPEC_FRC_SDCLK_ON 0x00000100 #define IRQSTAT 0x0002e030 #define IRQSTAT_DMAE (0x10000000) @@ -97,7 +96,6 @@ #define PRSSTAT_CINS (0x00010000) #define PRSSTAT_BREN (0x00000800) #define PRSSTAT_BWEN (0x00000400) -#define PRSSTAT_SDOFF (0x00000080) #define PRSSTAT_SDSTB (0X00000008) #define PRSSTAT_DLA (0x00000004) #define PRSSTAT_CICHB (0x00000002)