static int hinfc610_get_toggle_info(struct hinfc_host *host, int *type) { char buf[8]; *type = 0; if (!hinfc610_toggle_support_sync(host)) return 0; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); hinfc_write(host, 0x40, HINFC610_ADDRL); hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); if (memcmp(buf, "JESD", 4)) return 0; if (buf[4] & (1 << 1)) /* supports revision 1.0 */ *type = NAND_TYPE_TOGGLE_10; else pr_warn("sync NAND has unknown toggle revision.\n"); return 1; }
static int hinfc610_get_onfi_info(struct hinfc_host *host, int *type) { char buf[6]; *type = 0; if (!hinfc610_onfi_support_sync(host)) return 0; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); hinfc_write(host, NAND_CMD_PARAM, HINFC610_CMD); hinfc_write(host, 0x00, HINFC610_ADDRL); hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); if (memcmp(buf, "ONFI", 4)) return 0; if (buf[4] & (1 << 6)) *type = NAND_TYPE_ONFI_30; else if (buf[4] & (1 << 5) || buf[4] & (1 << 4) || buf[4] & (1 << 3) || buf[4] & (1 << 2)) *type = NAND_TYPE_ONFI_23; return 1; }
static void hinfc504_hynix_cg_adie_get_rr(struct hinfc_host *host) { int index; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC504_DATA_NUM); for (index = 0; index < 8; index++) { memset(host->chip->IO_ADDR_R, 0xff, 1024); hinfc_write(host, 0x37, HINFC504_CMD); hinfc_write(host, hinfc504_hynix_cg_adie__rr_reg[index], HINFC504_ADDRL); hinfc_write(host, HINFC504_READ_1CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); printf("%02X ", readl(host->chip->IO_ADDR_R) & 0xff); } host->enable_ecc_randomizer(host, ENABLE, ENABLE); }
static int hinfc610_toshiba_24nm_set_rr_param(struct hinfc_host *host, int param) { hinfc_write(host, HINFC_CMD_SEQ(0x5C, 0xC5), HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); hinfc610_toshiba_24nm_set_rr_reg(host, param); hinfc_write(host, HINFC_CMD_SEQ(0x26, 0x5D), HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_2CMD_0ADD_NODATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); return 0; }
static int hinfc610_onfi_support_sync(struct hinfc_host *host) { char buf[6]; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); hinfc_write(host, 0x20, HINFC610_ADDRL); hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); if (memcmp(buf, "ONFI", 4)) return 0; hinfc_write(host, sizeof(buf), HINFC610_DATA_NUM); hinfc_write(host, NAND_CMD_READID, HINFC610_CMD); hinfc_write(host, 0x40, HINFC610_ADDRL); hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); memcpy(buf, host->chip->IO_ADDR_R, sizeof(buf)); if (memcmp(buf, "JEDEC", 5)) return 0; return (buf[5] == 0x05); }
static void hinfc610_sync_clock(struct hinfc_host *host, unsigned int enable) { unsigned int regval; hinfc_write(host, HINFC610_SYNC_ONFI_T_CAD | HINFC610_SYNC_ONFI_T_DQZ | HINFC610_SYNC_TOGGLE_PRE_RDQS | HINFC610_SYNC_TOGGLE_POST_RDQS | HINFC610_SYNC_TOGGLE_PRE_WDQS | HINFC610_SYNC_TOGGLE_POST_WDQS | HINFC610_SYNC_TOGGLE_RW_PSTH, HINFC610_SYNC_TIMING); /* * toggle1.0 nandc clock must be lower than 150M, otherwise * read/write will fail. * here configure to 100M for safety. */ regval = readl(HI3716CV200_PERI_CRG24); regval &= ~HI3716CV200_PERI_CRG24_CLK_SEL_MASK; regval |= enable ? HI3716CV200_PERI_CRG24_CLK_SEL_100M : HI3716CV200_PERI_CRG24_CLK_SEL_200M; writel(regval, HI3716CV200_PERI_CRG24); }
static int hinfc610_onfi_disable_sync(struct nand_chip *chip) { struct hinfc_host *host = chip->priv; unsigned char micron_sync_param[4] = { 0x00, 0x00, 0x00, 0x00, }; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC610_DATA_NUM); hinfc_write(host, 0xEF, HINFC610_CMD); hinfc_write(host, 0x01, HINFC610_ADDRL); writel(micron_sync_param[0], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA_SYNC, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(micron_sync_param[1], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(micron_sync_param[2], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(micron_sync_param[3], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_SYNC_WAIT_READY, HINFC610_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }
static int hinfc610_onfi_enable_sync(struct nand_chip *chip) { struct hinfc_host *host = chip->priv; unsigned char micron_sync_param[4] = { 0x14, /* set sync mode timing */ 0x00, 0x00, 0x00, }; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC610_DATA_NUM); hinfc_write(host, 0xEF, HINFC610_CMD); hinfc_write(host, 0x01, HINFC610_ADDRL); writel(micron_sync_param[0], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(micron_sync_param[1], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(micron_sync_param[2], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); /* need to config WAIT_READY_EN, here config this bit. */ writel(micron_sync_param[3], host->chip->IO_ADDR_R); hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA_WAIT_READY, HINFC610_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }
static int hinfc610_toshiba_24nm_set_rr_param(struct hinfc_host *host, int param) { int opval; host->enable_ecc_randomizer(host, DISABLE, DISABLE); opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_2CMD_0ADD_NODATA_SYNC : HINFC610_WRITE_2CMD_0ADD_NODATA); hinfc_write(host, HINFC_CMD_SEQ(0x5C, 0xC5), HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); hinfc610_toshiba_24nm_set_rr_reg(host, param); hinfc_write(host, HINFC_CMD_SEQ(0x26, 0x5D), HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }
static int hinfc504_os_resume(struct platform_device *pltdev) { int cs; struct hinfc_host *host = platform_get_drvdata(pltdev); struct nand_chip *chip = host->chip; host->enable(host, ENABLE); for (cs = 0; cs < chip->numchips; cs++) host->send_cmd_reset(host, cs); hinfc_write(host, SET_HINFC504_PWIDTH(CONFIG_HINFC504_W_LATCH, CONFIG_HINFC504_R_LATCH, CONFIG_HINFC504_RW_LATCH), HINFC504_PWIDTH); return 0; }
static int hinfc504_hynix_cg_adie_set_rr_reg(struct hinfc_host *host, char *val) { int i; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC504_DATA_NUM);/* data length 1 */ for (i = 0; i <= 8; i++) { switch (i) { case 0: writel(val[i], host->chip->IO_ADDR_R); hinfc_write(host, hinfc504_hynix_cg_adie__rr_reg[i], HINFC504_ADDRL); hinfc_write(host, 0x36, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_1ADD_DATA, HINFC504_OP); break; case 8: hinfc_write(host, 0x16, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_0ADD_NODATA, HINFC504_OP); break; default: writel(val[i], host->chip->IO_ADDR_R); hinfc_write(host, hinfc504_hynix_cg_adie__rr_reg[i], HINFC504_ADDRL); hinfc_write(host, HINFC504_WRITE_0CMD_1ADD_DATA, HINFC504_OP); break; } WAIT_CONTROLLER_FINISH(); } host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }
static int hinfc610_toshiba_24nm_set_rr_reg(struct hinfc_host *host, int param) { #define TOSHIBA_RR_CMD 0x55 static char toshiba_rr_param[] = {0x00, 0x04, 0x7c, 0x78, 0x74, 0x08}; if (!param) { host->send_cmd_reset(host, host->chipselect); return 0; } if (param >= 6) param = (param % 6); hinfc_write(host, 1, HINFC610_DATA_NUM); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x4, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x5, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x6, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x7, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); return 0; #undef TOSHIBA_RR_CMD }
static int hinfc610_toshiba_24nm_set_rr_reg(struct hinfc_host *host, int param) { #define TOSHIBA_RR_CMD 0x55 int opval; static char toshiba_rr_param[] = {0x00, 0x04, 0x7c, 0x78, 0x74, 0x08}; if (!param) { host->send_cmd_reset(host, host->chipselect); return 0; } if (param >= 6) param = (param % 6); /* * no need to config WAIT_READY_EN, here not config WAIT_READY_EN */ opval = (HINFC610_IS_SYNC(host) ? HINFC610_WRITE_1CMD_1ADD_DATA_SYNC : HINFC610_WRITE_1CMD_1ADD_DATA); hinfc_write(host, 1, HINFC610_DATA_NUM); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x4, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x5, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x6, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); writel(toshiba_rr_param[param], host->chip->IO_ADDR_R); hinfc_write(host, 0x7, HINFC610_ADDRL); hinfc_write(host, TOSHIBA_RR_CMD, HINFC610_CMD); hinfc_write(host, opval, HINFC610_OP); WAIT_CONTROLLER_FINISH(); return 0; #undef TOSHIBA_RR_CMD }
static int hinfc504_hynix_cg_adie_get_rr_param(struct hinfc_host *host) { char *otp; host->enable_ecc_randomizer(host, DISABLE, DISABLE); /* step1: reset the chip */ host->send_cmd_reset(host, host->chipselect); /* step2: cmd: 0x36, address: 0xFF, data: 0x40 */ hinfc_write(host, 1, HINFC504_DATA_NUM);/* data length 1 */ writel(0x40, host->chip->IO_ADDR_R); /* data: 0x00 */ hinfc_write(host, 0xFF, HINFC504_ADDRL);/* address: 0xAE */ hinfc_write(host, 0x36, HINFC504_CMD); /* cmd: 0x36 */ hinfc_write(host, HINFC504_WRITE_1CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); /* step3: address: 0xCC, data: 0x4D */ hinfc_write(host, 1, HINFC504_DATA_NUM);/* data length 1 */ writel(0x4D, host->chip->IO_ADDR_R); /* data: 0x4d */ hinfc_write(host, 0xCC, HINFC504_ADDRL);/* address: 0xB0 */ /* only address and data, without cmd */ hinfc_write(host, HINFC504_WRITE_0CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); /* step4: cmd: 0x16, 0x17, 0x04, 0x19 */ hinfc_write(host, 0x17 << 8 | 0x16, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_2CMD_0ADD_NODATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); hinfc_write(host, 0x19 << 8 | 0x04, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_2CMD_0ADD_NODATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); /* step5: cmd: 0x00 0x30, address: 0x02 00 00 00 */ hinfc_write(host, 0x2000000, HINFC504_ADDRL); hinfc_write(host, 0x00, HINFC504_ADDRH); hinfc_write(host, 0x30 << 8 | 0x00, HINFC504_CMD); hinfc_write(host, 0x800, HINFC504_DATA_NUM); hinfc_write(host, HINFC504_READ_2CMD_5ADD, HINFC504_OP); WAIT_CONTROLLER_FINISH(); /*step6 save otp read retry table to mem*/ otp = hinfc504_hynix_cg_adie_otp_check(host->chip->IO_ADDR_R + 2); if (!otp) { printf("Read Retry select parameter failed, " "this Nand Chip maybe unstable!\n"); return -1; } memcpy(host->rr_data, otp, 64); host->need_rr_data = 1; /* step7: reset the chip */ host->send_cmd_reset(host, host->chipselect); /* step8: cmd: 0x38 */ hinfc_write(host, 0x38, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_0ADD_NODATA_WAIT_READY, HINFC504_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); /* get hynix otp table finish */ return 0; }
static int hinfc504_hynix_cg_adie_eslc_enable(struct hinfc_host *host, int enable) { int ix; char HYNIX_CG_ADIE_ESLC_REG[4] = {0xB0, 0xB1, 0xA0, 0xA1}; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC504_DATA_NUM); for (ix = 0; enable && ix < 4; ix++) { memset(host->chip->IO_ADDR_R, 0xff, 32); hinfc_write(host, 0x37, HINFC504_CMD); hinfc_write(host, HYNIX_CG_ADIE_ESLC_REG[ix], HINFC504_ADDRL); hinfc_write(host, HINFC504_READ_1CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); HYNIX_CG_ADIE_ESLC_PARAM[ix] = (char)(readl(host->chip->IO_ADDR_R) & 0xff); } for (ix = 0; ix <= 4; ix++) { int offset = enable ? 0x0A : 0x00; switch (ix) { case 0: writel(HYNIX_CG_ADIE_ESLC_PARAM[ix] + offset, host->chip->IO_ADDR_R); hinfc_write(host, HYNIX_CG_ADIE_ESLC_REG[ix], HINFC504_ADDRL); hinfc_write(host, 0x36, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_1ADD_DATA, HINFC504_OP); break; case 4: hinfc_write(host, 0x16, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_0ADD_NODATA, HINFC504_OP); break; default: writel(HYNIX_CG_ADIE_ESLC_PARAM[ix] + offset, host->chip->IO_ADDR_R); hinfc_write(host, HYNIX_CG_ADIE_ESLC_REG[ix], HINFC504_ADDRL); hinfc_write(host, HINFC504_WRITE_0CMD_1ADD_DATA, HINFC504_OP); break; } WAIT_CONTROLLER_FINISH(); } host->enable_ecc_randomizer(host, ENABLE, ENABLE); if (!enable) { hinfc_write(host, host->addr_value[0] & 0xffff0000, HINFC504_ADDRL); hinfc_write(host, host->addr_value[1], HINFC504_ADDRH); hinfc_write(host, NAND_CMD_READSTART << 8 | NAND_CMD_READ0, HINFC504_CMD); hinfc_write(host, HINFC504_READ_2CMD_5ADD, HINFC504_OP); WAIT_CONTROLLER_FINISH(); } return 0; }
static int hinfc610_hynix_bg_bdie_set_rr_reg(struct hinfc_host *host, int index) { int ix; char HYNIX_BG_BDIE_RR_REG[4] = {0xA7, 0xAD, 0xAE, 0xAF}; char value_offset[7][4] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x06, 0x0A, 0x06}, {0x7F, -0x03, -0x07, -0x08}, {0x7F, -0x06, -0x0D, -0x0F}, {0x7F, -0x09, -0x14, -0x17}, {0x7F, 0x7F, -0x1A, -0x1E}, {0x7F, 0x7F, -0x20, -0x25} }; char *value = &value_offset[index][0]; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC610_DATA_NUM); if (!hynix_bg_bdie_rr_org_exist) { for (ix = 0; ix < 4; ix++) { memset(host->chip->IO_ADDR_R, 0xff, 32); hinfc_write(host, 0x37, HINFC610_CMD); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC610_ADDRL); /* * according to hynix doc, no need to config HINFC610_OP_WAIT_READY_EN, * here not config this bit, confirmed by yubingxu. */ hinfc_write(host, HINFC610_READ_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); hynix_bg_bdie_rr_org[ix] = (char)(readl(host->chip->IO_ADDR_R) & 0xff); } hynix_bg_bdie_rr_org_exist = 1; } for (ix = 0; ix < 4; ix++) { if (value[ix] == 0x7F) value[ix] = 0x00; else value[ix] += hynix_bg_bdie_rr_org[ix]; } writel(value[0], host->chip->IO_ADDR_W); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[0], HINFC610_ADDRL); hinfc_write(host, 0x36, HINFC610_CMD); /* * according to hynix doc, no need to config HINFC610_OP_WAIT_READY_EN, * here not config this bit. */ hinfc_write(host, HINFC610_WRITE_1CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); for (ix = 1; ix < 4; ix++) { writel(value[ix], host->chip->IO_ADDR_W); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC610_ADDRL); /* * according to hynix doc, no need to config HINFC610_OP_WAIT_READY_EN, * here not config this bit. */ hinfc_write(host, HINFC610_WRITE_0CMD_1ADD_DATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); } hinfc_write(host, 0x16, HINFC610_CMD); /* * according to hynix doc, only 1 cmd: 0x16. * And no need to config HINFC610_OP_WAIT_READY_EN, here not config this bit. */ hinfc_write(host, HINFC610_WRITE_1CMD_0ADD_NODATA, HINFC610_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }
static int hinfc504_samsung_set_rr_reg(struct hinfc_host *host,int param) { #define SAMSUNG_RR_CMD 0xA1 unsigned char samsung_rr_params[15][4] = { {0x00, 0x00, 0x00, 0x00}, {0x05, 0x0A, 0x00, 0x00}, {0x28, 0x00, 0xEC, 0xD8}, {0xED, 0xF5, 0xED, 0xE6}, {0x0A, 0x0F, 0x05, 0x00}, {0x0F, 0x0A, 0xFB, 0xEC}, {0xE8, 0xEF, 0xE8, 0xDC}, {0xF1, 0xFB, 0xFE, 0xF0}, {0x0A, 0x00, 0xFB, 0xEC}, {0xD0, 0xE2, 0xD0, 0xC2}, {0x14, 0x0F, 0xFB, 0xEC}, {0xE8, 0xFB, 0xE8, 0xDC}, {0x1E, 0x14, 0xFB, 0xEC}, {0xFB, 0xFF, 0xFB, 0xF8}, {0x07, 0x0C, 0x02, 0x00} }; if (param >= 15) param = (param % 15); hinfc_write(host, 1, HINFC504_DATA_NUM); writel(samsung_rr_params[param][0], host->chip->IO_ADDR_R); hinfc_write(host, 0xA700, HINFC504_ADDRL); hinfc_write(host, SAMSUNG_RR_CMD, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_2ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); writel(samsung_rr_params[param][1], host->chip->IO_ADDR_R); hinfc_write(host, 0xA400, HINFC504_ADDRL); hinfc_write(host, SAMSUNG_RR_CMD, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_2ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); writel(samsung_rr_params[param][2], host->chip->IO_ADDR_R); hinfc_write(host, 0xA500, HINFC504_ADDRL); hinfc_write(host, SAMSUNG_RR_CMD, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_2ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); writel(samsung_rr_params[param][3], host->chip->IO_ADDR_R); hinfc_write(host, 0xA600, HINFC504_ADDRL); hinfc_write(host, SAMSUNG_RR_CMD, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_2ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); return 0; #undef SAMSUNG_RR_CMD }
static int hinfc504_hynix_bg_bdie_set_rr_reg(struct hinfc_host *host, int index) { int ix; char HYNIX_BG_BDIE_RR_REG[4] = {0xA7, 0xAD, 0xAE, 0xAF}; char value_offset[7][4] = { {0x00, 0x00, 0x00, 0x00}, {0x00, 0x06, 0x0A, 0x06}, {0x7F, -0x03, -0x07, -0x08}, {0x7F, -0x06, -0x0D, -0x0F}, {0x7F, -0x09, -0x14, -0x17}, {0x7F, 0x7F, -0x1A, -0x1E}, {0x7F, 0x7F, -0x20, -0x25} }; char *value = &value_offset[index][0]; host->enable_ecc_randomizer(host, DISABLE, DISABLE); hinfc_write(host, 1, HINFC504_DATA_NUM); if (!hynix_bg_bdie_rr_org_exist) { for (ix = 0; ix < 4; ix++) { memset(host->chip->IO_ADDR_R, 0xff, 32); hinfc_write(host, 0x37, HINFC504_CMD); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC504_ADDRL); hinfc_write(host, HINFC504_READ_1CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); hynix_bg_bdie_rr_org[ix] = (char)(readl(host->chip->IO_ADDR_R) & 0xff); } hynix_bg_bdie_rr_org_exist = 1; } for (ix = 0; ix < 4; ix++) { if (value[ix] == 0x7F) value[ix] = 0x00; else value[ix] += hynix_bg_bdie_rr_org[ix]; } writel(value[0], host->chip->IO_ADDR_W); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[0], HINFC504_ADDRL); hinfc_write(host, 0x36, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); for (ix = 1; ix < 4; ix++) { writel(value[ix], host->chip->IO_ADDR_W); hinfc_write(host, HYNIX_BG_BDIE_RR_REG[ix], HINFC504_ADDRL); hinfc_write(host, HINFC504_WRITE_0CMD_1ADD_DATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); } hinfc_write(host, 0x16, HINFC504_CMD); hinfc_write(host, HINFC504_WRITE_1CMD_0ADD_NODATA, HINFC504_OP); WAIT_CONTROLLER_FINISH(); host->enable_ecc_randomizer(host, ENABLE, ENABLE); return 0; }