Lines Matching full:nfc
216 static void pl35x_smc_update_regs(struct pl35x_nandc *nfc) in pl35x_smc_update_regs() argument
220 nfc->conf_regs + PL35X_SMC_DIRECT_CMD); in pl35x_smc_update_regs()
223 static int pl35x_smc_set_buswidth(struct pl35x_nandc *nfc, unsigned int bw) in pl35x_smc_set_buswidth() argument
228 writel(bw, nfc->conf_regs + PL35X_SMC_OPMODE); in pl35x_smc_set_buswidth()
229 pl35x_smc_update_regs(nfc); in pl35x_smc_set_buswidth()
234 static void pl35x_smc_clear_irq(struct pl35x_nandc *nfc) in pl35x_smc_clear_irq() argument
237 nfc->conf_regs + PL35X_SMC_MEMC_CFG_CLR); in pl35x_smc_clear_irq()
240 static int pl35x_smc_wait_for_irq(struct pl35x_nandc *nfc) in pl35x_smc_wait_for_irq() argument
245 ret = readl_poll_timeout(nfc->conf_regs + PL35X_SMC_MEMC_STATUS, reg, in pl35x_smc_wait_for_irq()
249 dev_err(nfc->dev, in pl35x_smc_wait_for_irq()
253 pl35x_smc_clear_irq(nfc); in pl35x_smc_wait_for_irq()
258 static int pl35x_smc_wait_for_ecc_done(struct pl35x_nandc *nfc) in pl35x_smc_wait_for_ecc_done() argument
263 ret = readl_poll_timeout(nfc->conf_regs + PL35X_SMC_ECC_STATUS, reg, in pl35x_smc_wait_for_ecc_done()
267 dev_err(nfc->dev, in pl35x_smc_wait_for_ecc_done()
273 static int pl35x_smc_set_ecc_mode(struct pl35x_nandc *nfc, in pl35x_smc_set_ecc_mode() argument
280 ecc_cfg = readl(nfc->conf_regs + PL35X_SMC_ECC_CFG); in pl35x_smc_set_ecc_mode()
283 writel(ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); in pl35x_smc_set_ecc_mode()
291 return pl35x_smc_wait_for_ecc_done(nfc); in pl35x_smc_set_ecc_mode()
299 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_smc_force_byte_access() local
306 ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_8); in pl35x_smc_force_byte_access()
308 ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_16); in pl35x_smc_force_byte_access()
311 dev_err(nfc->dev, "Error in Buswidth\n"); in pl35x_smc_force_byte_access()
317 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_select_target() local
320 if (chip == nfc->selected_chip) in pl35x_nand_select_target()
324 writel(plnand->timings, nfc->conf_regs + PL35X_SMC_CYCLES); in pl35x_nand_select_target()
325 pl35x_smc_update_regs(nfc); in pl35x_nand_select_target()
328 writel(plnand->ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); in pl35x_nand_select_target()
330 nfc->selected_chip = chip; in pl35x_nand_select_target()
337 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_read_data_op() local
353 buf32[i] = readl(nfc->io_regs + data_phase_addr); in pl35x_nand_read_data_op()
358 buf8[i] = readb(nfc->io_regs + PL35X_SMC_DATA_PHASE); in pl35x_nand_read_data_op()
369 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_write_data_op() local
385 writel(buf32[i], nfc->io_regs + data_phase_addr); in pl35x_nand_write_data_op()
390 writeb(buf8[i], nfc->io_regs + PL35X_SMC_DATA_PHASE); in pl35x_nand_write_data_op()
396 static int pl35x_nand_correct_data(struct pl35x_nandc *nfc, unsigned char *buf, in pl35x_nand_correct_data() argument
450 static int pl35x_nand_read_eccbytes(struct pl35x_nandc *nfc, in pl35x_nand_read_eccbytes() argument
458 ecc_value = readl(nfc->conf_regs + PL35X_SMC_ECC_VALUE(chunk)); in pl35x_nand_read_eccbytes()
468 static int pl35x_nand_recover_data_hwecc(struct pl35x_nandc *nfc, in pl35x_nand_recover_data_hwecc() argument
481 ecc_value = readl(nfc->conf_regs + PL35X_SMC_ECC_VALUE(chunk)); in pl35x_nand_recover_data_hwecc()
492 stats = pl35x_nand_correct_data(nfc, data, read_ecc, calc_ecc); in pl35x_nand_recover_data_hwecc()
508 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_write_page_hwecc() local
517 ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); in pl35x_nand_write_page_hwecc()
535 writel(addr1, nfc->io_regs + cmd_addr); in pl35x_nand_write_page_hwecc()
537 writel(addr2, nfc->io_regs + cmd_addr); in pl35x_nand_write_page_hwecc()
542 ret = pl35x_smc_wait_for_ecc_done(nfc); in pl35x_nand_write_page_hwecc()
547 ret = pl35x_nand_read_eccbytes(nfc, chip, nfc->ecc_buf); in pl35x_nand_write_page_hwecc()
554 ret = mtd_ooblayout_set_eccbytes(mtd, nfc->ecc_buf, chip->oob_poi, in pl35x_nand_write_page_hwecc()
564 ret = pl35x_smc_wait_for_irq(nfc); in pl35x_nand_write_page_hwecc()
569 pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); in pl35x_nand_write_page_hwecc()
590 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_read_page_hwecc() local
599 ret = pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_APB); in pl35x_nand_read_page_hwecc()
619 writel(addr1, nfc->io_regs + cmd_addr); in pl35x_nand_read_page_hwecc()
621 writel(addr2, nfc->io_regs + cmd_addr); in pl35x_nand_read_page_hwecc()
625 ret = pl35x_smc_wait_for_irq(nfc); in pl35x_nand_read_page_hwecc()
632 ret = pl35x_smc_wait_for_ecc_done(nfc); in pl35x_nand_read_page_hwecc()
639 ret = mtd_ooblayout_get_eccbytes(mtd, nfc->ecc_buf, chip->oob_poi, 0, in pl35x_nand_read_page_hwecc()
644 pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); in pl35x_nand_read_page_hwecc()
647 return pl35x_nand_recover_data_hwecc(nfc, chip, buf, nfc->ecc_buf); in pl35x_nand_read_page_hwecc()
650 pl35x_smc_set_ecc_mode(nfc, chip, PL35X_SMC_ECC_CFG_MODE_BYPASS); in pl35x_nand_read_page_hwecc()
658 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_exec_op() local
715 writel(addr1, nfc->io_regs + cmd_addr); in pl35x_nand_exec_op()
717 writel(addr2, nfc->io_regs + cmd_addr); in pl35x_nand_exec_op()
732 ret = pl35x_smc_wait_for_irq(nfc); in pl35x_nand_exec_op()
780 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nfc_setup_interface() local
791 mclk = of_clk_get_by_name(nfc->dev->parent->of_node, "memclk"); in pl35x_nfc_setup_interface()
793 dev_err(nfc->dev, "Failed to retrieve SMC memclk\n"); in pl35x_nfc_setup_interface()
798 * SDR timings are given in pico-seconds while NFC timings must be in pl35x_nfc_setup_interface()
861 static void pl35x_smc_set_ecc_pg_size(struct pl35x_nandc *nfc, in pl35x_smc_set_ecc_pg_size() argument
883 plnand->ecc_cfg = readl(nfc->conf_regs + PL35X_SMC_ECC_CFG); in pl35x_smc_set_ecc_pg_size()
886 writel(plnand->ecc_cfg, nfc->conf_regs + PL35X_SMC_ECC_CFG); in pl35x_smc_set_ecc_pg_size()
889 static int pl35x_nand_init_hw_ecc_controller(struct pl35x_nandc *nfc, in pl35x_nand_init_hw_ecc_controller() argument
896 dev_err(nfc->dev, in pl35x_nand_init_hw_ecc_controller()
908 pl35x_smc_set_ecc_pg_size(nfc, chip, mtd->writesize); in pl35x_nand_init_hw_ecc_controller()
910 nfc->ecc_buf = devm_kmalloc(nfc->dev, chip->ecc.bytes * chip->ecc.steps, in pl35x_nand_init_hw_ecc_controller()
912 if (!nfc->ecc_buf) in pl35x_nand_init_hw_ecc_controller()
925 dev_err(nfc->dev, "Unsupported OOB size\n"); in pl35x_nand_init_hw_ecc_controller()
936 struct pl35x_nandc *nfc = to_pl35x_nandc(chip->controller); in pl35x_nand_attach_chip() local
947 dev_info(nfc->dev, in pl35x_nand_attach_chip()
974 ret = pl35x_nand_init_hw_ecc_controller(nfc, chip); in pl35x_nand_attach_chip()
979 dev_err(nfc->dev, "Unsupported ECC mode: %d\n", in pl35x_nand_attach_chip()
993 static int pl35x_nand_reset_state(struct pl35x_nandc *nfc) in pl35x_nand_reset_state() argument
1001 nfc->conf_regs + PL35X_SMC_MEMC_CFG_CLR); in pl35x_nand_reset_state()
1004 ret = pl35x_smc_set_buswidth(nfc, PL35X_SMC_OPMODE_BW_8); in pl35x_nand_reset_state()
1009 ret = pl35x_smc_set_ecc_mode(nfc, NULL, PL35X_SMC_ECC_CFG_MODE_BYPASS); in pl35x_nand_reset_state()
1021 nfc->conf_regs + PL35X_SMC_ECC_CMD1); in pl35x_nand_reset_state()
1026 nfc->conf_regs + PL35X_SMC_ECC_CMD2); in pl35x_nand_reset_state()
1031 static int pl35x_nand_chip_init(struct pl35x_nandc *nfc, in pl35x_nand_chip_init() argument
1039 plnand = devm_kzalloc(nfc->dev, sizeof(*plnand), GFP_KERNEL); in pl35x_nand_chip_init()
1048 dev_err(nfc->dev, "Wrong CS %d\n", cs); in pl35x_nand_chip_init()
1052 if (test_and_set_bit(cs, &nfc->assigned_cs)) { in pl35x_nand_chip_init()
1053 dev_err(nfc->dev, "Already assigned CS %d\n", cs); in pl35x_nand_chip_init()
1062 chip->controller = &nfc->controller; in pl35x_nand_chip_init()
1064 mtd->dev.parent = nfc->dev; in pl35x_nand_chip_init()
1065 nand_set_flash_node(chip, nfc->dev->of_node); in pl35x_nand_chip_init()
1067 mtd->name = devm_kasprintf(nfc->dev, GFP_KERNEL, in pl35x_nand_chip_init()
1070 dev_err(nfc->dev, "Failed to allocate mtd->name\n"); in pl35x_nand_chip_init()
1085 list_add_tail(&plnand->node, &nfc->chips); in pl35x_nand_chip_init()
1090 static void pl35x_nand_chips_cleanup(struct pl35x_nandc *nfc) in pl35x_nand_chips_cleanup() argument
1096 list_for_each_entry_safe(plnand, tmp, &nfc->chips, node) { in pl35x_nand_chips_cleanup()
1105 static int pl35x_nand_chips_init(struct pl35x_nandc *nfc) in pl35x_nand_chips_init() argument
1107 struct device_node *np = nfc->dev->of_node, *nand_np; in pl35x_nand_chips_init()
1112 dev_err(nfc->dev, "Incorrect number of NAND chips (%d)\n", in pl35x_nand_chips_init()
1118 ret = pl35x_nand_chip_init(nfc, nand_np); in pl35x_nand_chips_init()
1121 pl35x_nand_chips_cleanup(nfc); in pl35x_nand_chips_init()
1133 struct pl35x_nandc *nfc; in pl35x_nand_probe() local
1136 nfc = devm_kzalloc(&pdev->dev, sizeof(*nfc), GFP_KERNEL); in pl35x_nand_probe()
1137 if (!nfc) in pl35x_nand_probe()
1140 nfc->dev = &pdev->dev; in pl35x_nand_probe()
1141 nand_controller_init(&nfc->controller); in pl35x_nand_probe()
1142 nfc->controller.ops = &pl35x_nandc_ops; in pl35x_nand_probe()
1143 INIT_LIST_HEAD(&nfc->chips); in pl35x_nand_probe()
1145 nfc->conf_regs = devm_ioremap_resource(&smc_amba->dev, &smc_amba->res); in pl35x_nand_probe()
1146 if (IS_ERR(nfc->conf_regs)) in pl35x_nand_probe()
1147 return PTR_ERR(nfc->conf_regs); in pl35x_nand_probe()
1149 nfc->io_regs = devm_platform_ioremap_resource(pdev, 0); in pl35x_nand_probe()
1150 if (IS_ERR(nfc->io_regs)) in pl35x_nand_probe()
1151 return PTR_ERR(nfc->io_regs); in pl35x_nand_probe()
1153 ret = pl35x_nand_reset_state(nfc); in pl35x_nand_probe()
1157 ret = pl35x_nand_chips_init(nfc); in pl35x_nand_probe()
1161 platform_set_drvdata(pdev, nfc); in pl35x_nand_probe()
1168 struct pl35x_nandc *nfc = platform_get_drvdata(pdev); in pl35x_nand_remove() local
1170 pl35x_nand_chips_cleanup(nfc); in pl35x_nand_remove()