diff for duplicates of <20180528000422.7f18dc5f@xps13> diff --git a/a/1.txt b/N1/1.txt index 3538774..a264453 100644 --- a/a/1.txt +++ b/N1/1.txt @@ -4,7 +4,7 @@ I just see your v2 while I'm sending my review on the driver, will probably wait for v4 then ;) Thanks for the work though! -Miqu=C3=A8l +Miquèl On Tue, 22 May 2018 14:07:06 +0200, Stefan Agner <stefan@agner.ch> wrote: @@ -14,7 +14,7 @@ wrote: > command queue feature. Regular operations/data transfers are > done in PIO mode. Page read/writes with hardware ECC make > use of the DMA for data transfer. ->=20 +> > Signed-off-by: Lucas Stach <dev@lynxeye.de> > Signed-off-by: Stefan Agner <stefan@agner.ch> > --- @@ -80,78 +80,77 @@ Please use the BIT(x) macro instead of (1 << x) > + const struct nand_subop *subop) > +{ > + const struct nand_op_instr *instr; -> + const struct nand_op_instr *instr_data_in =3D NULL; -> + struct mtd_info *mtd =3D nand_to_mtd(chip); -> + struct tegra_nand *nand =3D to_tegra_nand(mtd); -> + unsigned int op_id =3D -1, trfr_in_sz =3D 0, trfr_out_sz =3D 0, offset = -=3D 0; -> + bool first_cmd =3D true; +> + const struct nand_op_instr *instr_data_in = NULL; +> + struct mtd_info *mtd = nand_to_mtd(chip); +> + struct tegra_nand *nand = to_tegra_nand(mtd); +> + unsigned int op_id = -1, trfr_in_sz = 0, trfr_out_sz = 0, offset = 0; +> + bool first_cmd = true; > + bool force8bit; -> + u32 cmd =3D 0; +> + u32 cmd = 0; > + u32 value; > + -> + for (op_id =3D 0; op_id < subop->ninstrs; op_id++) { +> + for (op_id = 0; op_id < subop->ninstrs; op_id++) { > + unsigned int naddrs, i; > + const u8 *addrs; -> + u32 addr1 =3D 0, addr2 =3D 0; +> + u32 addr1 = 0, addr2 = 0; > + -> + instr =3D &subop->instrs[op_id]; +> + instr = &subop->instrs[op_id]; > + > + switch (instr->type) { > + case NAND_OP_CMD_INSTR: > + if (first_cmd) { -> + cmd |=3D CMD_CLE; +> + cmd |= CMD_CLE; > + writel(instr->ctx.cmd.opcode, nand->regs + CMD_1); > + } else { -> + cmd |=3D CMD_SEC_CMD; +> + cmd |= CMD_SEC_CMD; > + writel(instr->ctx.cmd.opcode, nand->regs + CMD_2); > + } -> + first_cmd =3D false; +> + first_cmd = false; > + break; > + case NAND_OP_ADDR_INSTR: -> + offset =3D nand_subop_get_addr_start_off(subop, op_id); -> + naddrs =3D nand_subop_get_num_addr_cyc(subop, op_id); -> + addrs =3D &instr->ctx.addr.addrs[offset]; -> + -> + cmd |=3D CMD_ALE | CMD_ALE_SIZE(naddrs); -> + for (i =3D 0; i < min_t(unsigned int, 4, naddrs); i++) -> + addr1 |=3D *addrs++ << (8 * i); -> + naddrs -=3D i; -> + for (i =3D 0; i < min_t(unsigned int, 4, naddrs); i++) -> + addr2 |=3D *addrs++ << (8 * i); +> + offset = nand_subop_get_addr_start_off(subop, op_id); +> + naddrs = nand_subop_get_num_addr_cyc(subop, op_id); +> + addrs = &instr->ctx.addr.addrs[offset]; +> + +> + cmd |= CMD_ALE | CMD_ALE_SIZE(naddrs); +> + for (i = 0; i < min_t(unsigned int, 4, naddrs); i++) +> + addr1 |= *addrs++ << (8 * i); +> + naddrs -= i; +> + for (i = 0; i < min_t(unsigned int, 4, naddrs); i++) +> + addr2 |= *addrs++ << (8 * i); > + writel(addr1, nand->regs + ADDR_1); > + writel(addr2, nand->regs + ADDR_2); > + break; > + > + case NAND_OP_DATA_IN_INSTR: -> + trfr_in_sz =3D nand_subop_get_data_len(subop, op_id); -> + offset =3D nand_subop_get_data_start_off(subop, op_id); +> + trfr_in_sz = nand_subop_get_data_len(subop, op_id); +> + offset = nand_subop_get_data_start_off(subop, op_id); > + -> + cmd |=3D CMD_TRANS_SIZE(trfr_in_sz) | CMD_PIO | CMD_RX | CMD_A_VALID; +> + cmd |= CMD_TRANS_SIZE(trfr_in_sz) | CMD_PIO | CMD_RX | CMD_A_VALID; > + -> + instr_data_in =3D instr; +> + instr_data_in = instr; > + break; > + > + case NAND_OP_DATA_OUT_INSTR: -> + trfr_out_sz =3D nand_subop_get_data_len(subop, op_id); -> + offset =3D nand_subop_get_data_start_off(subop, op_id); -> + trfr_out_sz =3D min_t(size_t, trfr_out_sz, 4); +> + trfr_out_sz = nand_subop_get_data_len(subop, op_id); +> + offset = nand_subop_get_data_start_off(subop, op_id); +> + trfr_out_sz = min_t(size_t, trfr_out_sz, 4); > + -> + cmd |=3D CMD_TRANS_SIZE(trfr_out_sz) | CMD_PIO | CMD_TX | CMD_A_VALID; +> + cmd |= CMD_TRANS_SIZE(trfr_out_sz) | CMD_PIO | CMD_TX | CMD_A_VALID; > + > + memcpy(&value, instr->ctx.data.buf.out + offset, trfr_out_sz); > + writel(value, nand->regs + RESP); > + > + break; > + case NAND_OP_WAITRDY_INSTR: -> + cmd |=3D CMD_RBSY_CHK; +> + cmd |= CMD_RBSY_CHK; > + break; > + > + } > + } > + > + -> + cmd |=3D CMD_GO | CMD_CE(nand->cur_chip); +> + cmd |= CMD_GO | CMD_CE(nand->cur_chip); > + writel(cmd, nand->regs + CMD); > + wait_for_completion(&nand->command_complete); @@ -160,17 +159,16 @@ _timeout? > + > + if (instr_data_in) { > + u32 value; -> + size_t n =3D min_t(size_t, trfr_in_sz, 4); +> + size_t n = min_t(size_t, trfr_in_sz, 4); > + -> + value =3D readl(nand->regs + RESP); +> + value = readl(nand->regs + RESP); > + memcpy(instr_data_in->ctx.data.buf.in + offset, &value, n); > + } > + > + return 0; > +} > + -> +static const struct nand_op_parser tegra_nand_op_parser =3D NAND_OP_PARS= -ER( +> +static const struct nand_op_parser tegra_nand_op_parser = NAND_OP_PARSER( > + NAND_OP_PARSER_PATTERN(tegra_nand_cmd, > + NAND_OP_PARSER_PAT_CMD_ELEM(true), > + NAND_OP_PARSER_PAT_ADDR_ELEM(true, 8), @@ -195,20 +193,19 @@ ER( > +} > +static void tegra_nand_select_chip(struct mtd_info *mtd, int chip) > +{ -> + struct tegra_nand *nand =3D to_tegra_nand(mtd); +> + struct tegra_nand *nand = to_tegra_nand(mtd); > + -> + nand->cur_chip =3D chip; +> + nand->cur_chip = chip; You should probably save the timings configuration and apply them back here in case of using different chips. > +} > + -> +static u32 tegra_nand_fill_address(struct mtd_info *mtd, struct nand_chi= -p *chip, +> +static u32 tegra_nand_fill_address(struct mtd_info *mtd, struct nand_chip *chip, > + int page) > +{ -> + struct tegra_nand *nand =3D to_tegra_nand(mtd); +> + struct tegra_nand *nand = to_tegra_nand(mtd); > + > + /* Lower 16-bits are column, always 0 */ > + writel(page << 16, nand->regs + ADDR_1); @@ -221,20 +218,19 @@ p *chip, > + return 4; > +} > + -> +static int tegra_nand_read_page(struct mtd_info *mtd, struct nand_chip *= -chip, +> +static int tegra_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, > + uint8_t *buf, int oob_required, int page) > +{ -> + struct tegra_nand *nand =3D to_tegra_nand(mtd); +> + struct tegra_nand *nand = to_tegra_nand(mtd); > + u32 value, addrs; > + > + writel(NAND_CMD_READ0, nand->regs + CMD_1); > + writel(NAND_CMD_READSTART, nand->regs + CMD_2); > + -> + addrs =3D tegra_nand_fill_address(mtd, chip, page); +> + addrs = tegra_nand_fill_address(mtd, chip, page); > + -> + value =3D readl(nand->regs + CFG); -> + value |=3D CFG_HW_ECC | CFG_ERR_COR; +> + value = readl(nand->regs + CFG); +> + value |= CFG_HW_ECC | CFG_ERR_COR; > + writel(value, nand->regs + CFG); > + > + writel(mtd->writesize - 1, nand->regs + DMA_CFG_A); @@ -249,18 +245,18 @@ chip, > + writel(0, nand->regs + TAG_PTR); > + } > + -> + value =3D DMA_CTRL_GO | DMA_CTRL_IN | DMA_CTRL_PERF_EN | +> + value = DMA_CTRL_GO | DMA_CTRL_IN | DMA_CTRL_PERF_EN | > + DMA_CTRL_REUSE | DMA_CTRL_IE_DONE | DMA_CTRL_IS_DONE | > + DMA_CTRL_BURST_8 | DMA_CTRL_EN_A; > + if (oob_required) -> + value |=3D DMA_CTRL_EN_B; +> + value |= DMA_CTRL_EN_B; > + writel(value, nand->regs + DMA_CTRL); > + -> + value =3D CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD | +> + value = CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD | > + CMD_RBSY_CHK | CMD_GO | CMD_RX | CMD_TRANS_SIZE(9) | > + CMD_A_VALID | CMD_CE(nand->cur_chip); > + if (oob_required) -> + value |=3D CMD_B_VALID; +> + value |= CMD_B_VALID; > + writel(value, nand->regs + CMD); > + > + wait_for_completion(&nand->command_complete); @@ -279,11 +275,11 @@ refer to them? > + } > + memcpy(buf, nand->data_buf, mtd->writesize); > + -> + value =3D readl(nand->regs + CFG); -> + value &=3D ~(CFG_HW_ECC | CFG_ERR_COR); +> + value = readl(nand->regs + CFG); +> + value &= ~(CFG_HW_ECC | CFG_ERR_COR); > + writel(value, nand->regs + CFG); > + -> + value =3D readl(nand->regs + DEC_STATUS); +> + value = readl(nand->regs + DEC_STATUS); > + if (value & DEC_STATUS_A_ECC_FAIL) { > + /* > + * The ECC isn't smart enough to figure out if a page is @@ -292,17 +288,17 @@ refer to them? > + * error or a false positive. > + */ > + int i, err; -> + int flips_threshold =3D chip->ecc.strength / 2; -> + int max_bitflips =3D 0; +> + int flips_threshold = chip->ecc.strength / 2; +> + int max_bitflips = 0; > + -> + for (i =3D 0; i < chip->ecc.steps; i++) { -> + u8 *data =3D buf + (chip->ecc.size * i); -> + err =3D nand_check_erased_ecc_chunk(data, chip->ecc.size, +> + for (i = 0; i < chip->ecc.steps; i++) { +> + u8 *data = buf + (chip->ecc.size * i); +> + err = nand_check_erased_ecc_chunk(data, chip->ecc.size, Are you sure the data was uncorrected there? I bet you have corrected data in chip->ecc.size and should re-read the page with the raw helpers before using nand_check_erased_ecc_chunk(). -=20 + > + NULL, 0, > + NULL, 0, > + flips_threshold); @@ -316,9 +312,9 @@ I think you should use chip->ecc.strength instead of flips_threshold In case of ECC failure you should increment ecc_stats.failed. > + -> + max_bitflips +=3D max_bitflips; +> + max_bitflips += max_bitflips; -max_bitflipts =3D max_t(unsigned int, max_bitflipts, err); +max_bitflipts = max_t(unsigned int, max_bitflipts, err); > + } > + @@ -328,10 +324,10 @@ max_bitflipts =3D max_t(unsigned int, max_bitflipts, err); > + if (nand->last_read_error) { > + int max_corr_cnt, corr_sec_flag; > + -> + value =3D readl(nand->regs + DEC_STAT_BUF); -> + corr_sec_flag =3D (value & DEC_STAT_BUF_CORR_SEC_FLAG_MASK) >> +> + value = readl(nand->regs + DEC_STAT_BUF); +> + corr_sec_flag = (value & DEC_STAT_BUF_CORR_SEC_FLAG_MASK) >> > + DEC_STAT_BUF_CORR_SEC_FLAG_SHIFT; -> + max_corr_cnt =3D (value & DEC_STAT_BUF_MAX_CORR_CNT_MASK) >> +> + max_corr_cnt = (value & DEC_STAT_BUF_MAX_CORR_CNT_MASK) >> > + DEC_STAT_BUF_MAX_CORR_CNT_SHIFT; > + > + /* @@ -343,31 +339,30 @@ max_bitflipts =3D max_t(unsigned int, max_bitflipts, err); > + * that all regions where errors have been corrected > + * encountered the maximum number of bitflips. > + */ -> + mtd->ecc_stats.corrected +=3D max_corr_cnt * hweight8(corr_sec_flag); +> + mtd->ecc_stats.corrected += max_corr_cnt * hweight8(corr_sec_flag); That's bad. But okay if we don't have the information. -> + nand->last_read_error =3D false; +> + nand->last_read_error = false; > + return value; > + } > + > + return 0; > +} > + -> +static int tegra_nand_write_page(struct mtd_info *mtd, struct nand_chip = -*chip, +> +static int tegra_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, > + const uint8_t *buf, int oob_required, int page) > +{ -> + struct tegra_nand *nand =3D to_tegra_nand(mtd); +> + struct tegra_nand *nand = to_tegra_nand(mtd); > + u32 value, addrs; > + > + writel(NAND_CMD_SEQIN, nand->regs + CMD_1); > + writel(NAND_CMD_PAGEPROG, nand->regs + CMD_2); > + -> + addrs =3D tegra_nand_fill_address(mtd, chip, page); +> + addrs = tegra_nand_fill_address(mtd, chip, page); > + -> + value =3D readl(nand->regs + CFG); -> + value |=3D CFG_HW_ECC | CFG_ERR_COR; +> + value = readl(nand->regs + CFG); +> + value |= CFG_HW_ECC | CFG_ERR_COR; > + writel(value, nand->regs + CFG); You might want to test with the _relaxed() operators? @@ -392,21 +387,21 @@ You might want to test with the _relaxed() operators? > + writel(0, nand->regs + TAG_PTR); > + } > + -> + value =3D DMA_CTRL_GO | DMA_CTRL_OUT | DMA_CTRL_PERF_EN | +> + value = DMA_CTRL_GO | DMA_CTRL_OUT | DMA_CTRL_PERF_EN | > + DMA_CTRL_IE_DONE | DMA_CTRL_IS_DONE | > + DMA_CTRL_BURST_8 | DMA_CTRL_EN_A; > + if (oob_required) -> + value |=3D DMA_CTRL_EN_B; +> + value |= DMA_CTRL_EN_B; Line here > + writel(value, nand->regs + DMA_CTRL); > + -> + value =3D CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD | +> + value = CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD | > + CMD_AFT_DAT | CMD_RBSY_CHK | CMD_GO | CMD_TX | CMD_A_VALID | > + CMD_TRANS_SIZE(9) | CMD_CE(nand->cur_chip); > + if (oob_required) -> + value |=3D CMD_B_VALID; +> + value |= CMD_B_VALID; Line here @@ -415,8 +410,8 @@ Line here > + wait_for_completion(&nand->command_complete); > + wait_for_completion(&nand->dma_complete); > + -> + value =3D readl(nand->regs + CFG); -> + value &=3D ~(CFG_HW_ECC | CFG_ERR_COR); +> + value = readl(nand->regs + CFG); +> + value &= ~(CFG_HW_ECC | CFG_ERR_COR); > + writel(value, nand->regs + CFG); > + > + return 0; @@ -432,65 +427,65 @@ You might wanna check __DIVIDE, PSEC_TO_NSEC and PSEC_TO_MSEC macros in rawnand.h. You could use them in the following derivations. > + */ -> + unsigned int rate =3D clk_get_rate(nand->clk) / 1000000; -> + unsigned int period =3D DIV_ROUND_UP(1000000, rate); +> + unsigned int rate = clk_get_rate(nand->clk) / 1000000; +> + unsigned int period = DIV_ROUND_UP(1000000, rate); > + const struct nand_sdr_timings *timings; -> + u32 val, reg =3D 0; +> + u32 val, reg = 0; > + -> + timings =3D onfi_async_timing_mode_to_sdr_timings(mode); +> + timings = onfi_async_timing_mode_to_sdr_timings(mode); > + -> + val =3D DIV_ROUND_UP(max3(timings->tAR_min, timings->tRR_min, +> + val = DIV_ROUND_UP(max3(timings->tAR_min, timings->tRR_min, > + timings->tRC_min), period); > + if (val > 2) -> + val -=3D 3; -> + reg |=3D TIMING_TCR_TAR_TRR(val); +> + val -= 3; +> + reg |= TIMING_TCR_TAR_TRR(val); > + -> + val =3D DIV_ROUND_UP(max(max(timings->tCS_min, timings->tCH_min), +> + val = DIV_ROUND_UP(max(max(timings->tCS_min, timings->tCH_min), > + max(timings->tALS_min, timings->tALH_min)), Is the second line aligned correctly? > + period); > + if (val > 1) -> + val -=3D 2; +> + val -= 2; This is weird and I would recommend a comment. -> + reg |=3D TIMING_TCS(val); +> + reg |= TIMING_TCS(val); > + -> + val =3D DIV_ROUND_UP(max(timings->tRP_min, timings->tREA_max) + 6000, +> + val = DIV_ROUND_UP(max(timings->tRP_min, timings->tREA_max) + 6000, > + period); -> + reg |=3D TIMING_TRP(val) | TIMING_TRP_RESP(val); +> + reg |= TIMING_TRP(val) | TIMING_TRP_RESP(val); > + -> + reg |=3D TIMING_TWB(DIV_ROUND_UP(timings->tWB_max, period)); -> + reg |=3D TIMING_TWHR(DIV_ROUND_UP(timings->tWHR_min, period)); -> + reg |=3D TIMING_TWH(DIV_ROUND_UP(timings->tWH_min, period)); -> + reg |=3D TIMING_TWP(DIV_ROUND_UP(timings->tWP_min, period)); -> + reg |=3D TIMING_TRH(DIV_ROUND_UP(timings->tRHW_min, period)); +> + reg |= TIMING_TWB(DIV_ROUND_UP(timings->tWB_max, period)); +> + reg |= TIMING_TWHR(DIV_ROUND_UP(timings->tWHR_min, period)); +> + reg |= TIMING_TWH(DIV_ROUND_UP(timings->tWH_min, period)); +> + reg |= TIMING_TWP(DIV_ROUND_UP(timings->tWP_min, period)); +> + reg |= TIMING_TRH(DIV_ROUND_UP(timings->tRHW_min, period)); > + > + writel(reg, nand->regs + TIMING_1); > + -> + val =3D DIV_ROUND_UP(timings->tADL_min, period); +> + val = DIV_ROUND_UP(timings->tADL_min, period); > + if (val > 2) -> + val -=3D 3; +> + val -= 3; Ditto -> + reg =3D TIMING_TADL(val); +> + reg = TIMING_TADL(val); > + > + writel(reg, nand->regs + TIMING_2); > +} > + > +static void tegra_nand_setup_chiptiming(struct tegra_nand *nand) > +{ -> + struct nand_chip *chip =3D &nand->chip; +> + struct nand_chip *chip = &nand->chip; > + int mode; > + -> + mode =3D onfi_get_async_timing_mode(chip); -> + if (mode =3D=3D ONFI_TIMING_MODE_UNKNOWN) -> + mode =3D chip->onfi_timing_mode_default; +> + mode = onfi_get_async_timing_mode(chip); +> + if (mode == ONFI_TIMING_MODE_UNKNOWN) +> + mode = chip->onfi_timing_mode_default; > + else -> + mode =3D fls(mode); +> + mode = fls(mode); > + > + tegra_nand_setup_timing(nand, mode); > +} @@ -515,39 +510,39 @@ be a 'NAND device' structure but rather more a controller structure. s/value/reg/ ? or something more explicit? -> + int irq, err =3D 0; +> + int irq, err = 0; > + -> + nand =3D devm_kzalloc(&pdev->dev, sizeof(*nand), GFP_KERNEL); +> + nand = devm_kzalloc(&pdev->dev, sizeof(*nand), GFP_KERNEL); > + if (!nand) > + return -ENOMEM; > + -> + nand->dev =3D &pdev->dev; +> + nand->dev = &pdev->dev; > + -> + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); -> + nand->regs =3D devm_ioremap_resource(&pdev->dev, res); +> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +> + nand->regs = devm_ioremap_resource(&pdev->dev, res); > + if (IS_ERR(nand->regs)) > + return PTR_ERR(nand->regs); > + -> + irq =3D platform_get_irq(pdev, 0); -> + err =3D devm_request_irq(&pdev->dev, irq, tegra_nand_irq, 0, +> + irq = platform_get_irq(pdev, 0); +> + err = devm_request_irq(&pdev->dev, irq, tegra_nand_irq, 0, > + dev_name(&pdev->dev), nand); > + if (err) > + return err; > + -> + rst =3D devm_reset_control_get(&pdev->dev, "nand"); +> + rst = devm_reset_control_get(&pdev->dev, "nand"); > + if (IS_ERR(rst)) > + return PTR_ERR(rst); > + -> + nand->clk =3D devm_clk_get(&pdev->dev, "nand"); +> + nand->clk = devm_clk_get(&pdev->dev, "nand"); > + if (IS_ERR(nand->clk)) > + return PTR_ERR(nand->clk); > + -> + nand->wp_gpio =3D gpiod_get_optional(&pdev->dev, "wp-gpios", +> + nand->wp_gpio = gpiod_get_optional(&pdev->dev, "wp-gpios", > + GPIOD_OUT_HIGH); > + if (IS_ERR(nand->wp_gpio)) > + return PTR_ERR(nand->wp_gpio); > + -> + err =3D clk_prepare_enable(nand->clk); +> + err = clk_prepare_enable(nand->clk); > + if (err) > + return err; > + @@ -555,7 +550,7 @@ s/value/reg/ ? or something more explicit? > + udelay(2); > + reset_control_deassert(rst); > + -> + value =3D HWSTATUS_RDSTATUS_MASK(1) | HWSTATUS_RDSTATUS_VALUE(0) | +> + value = HWSTATUS_RDSTATUS_MASK(1) | HWSTATUS_RDSTATUS_VALUE(0) | > + HWSTATUS_RBSY_MASK(NAND_STATUS_READY) | > + HWSTATUS_RBSY_VALUE(NAND_STATUS_READY); > + writel(NAND_CMD_STATUS, nand->regs + HWSTATUS_CMD); @@ -565,129 +560,129 @@ s/value/reg/ ? or something more explicit? > + init_completion(&nand->dma_complete); > + > + /* clear interrupts */ -> + value =3D readl(nand->regs + ISR); +> + value = readl(nand->regs + ISR); > + writel(value, nand->regs + ISR); > + > + writel(DMA_CTRL_IS_DONE, nand->regs + DMA_CTRL); > + > + /* enable interrupts */ -> + value =3D IER_UND | IER_OVR | IER_CMD_DONE | IER_ECC_ERR | IER_GIE; +> + value = IER_UND | IER_OVR | IER_CMD_DONE | IER_ECC_ERR | IER_GIE; > + writel(value, nand->regs + IER); > + > + /* reset config */ > + writel(0, nand->regs + CFG); > + -> + chip =3D &nand->chip; -> + mtd =3D nand_to_mtd(chip); +> + chip = &nand->chip; +> + mtd = nand_to_mtd(chip); > + -> + mtd->dev.parent =3D &pdev->dev; -> + mtd->name =3D "tegra_nand"; +> + mtd->dev.parent = &pdev->dev; +> + mtd->name = "tegra_nand"; I just figured it was undocumented (yet) but you could have a label string property in your nand DT node that tells you the name of the MTD device instead of something too generic like tegra_nand. -> + mtd->owner =3D THIS_MODULE; +> + mtd->owner = THIS_MODULE; > + > + nand_set_flash_node(chip, pdev->dev.of_node); > + nand_set_controller_data(chip, nand); > + -> + chip->options =3D NAND_NO_SUBPAGE_WRITE; -> + chip->exec_op =3D tegra_nand_exec_op; -> + chip->select_chip =3D tegra_nand_select_chip; +> + chip->options = NAND_NO_SUBPAGE_WRITE; +> + chip->exec_op = tegra_nand_exec_op; +> + chip->select_chip = tegra_nand_select_chip; > + tegra_nand_setup_timing(nand, 0); You really should implement ->setup_data_interface() and let the core handle the timings issue entirely (mind that chipnr is not the NAND chip id but more the CS id asserted for the pointed NAND chip). -=20 + > + -> + err =3D nand_scan_ident(mtd, 1, NULL); +> + err = nand_scan_ident(mtd, 1, NULL); > + if (err) > + goto err_disable_clk; > + > + if (chip->bbt_options & NAND_BBT_USE_FLASH) -> + chip->bbt_options |=3D NAND_BBT_NO_OOB; +> + chip->bbt_options |= NAND_BBT_NO_OOB; > + -> + nand->data_buf =3D dmam_alloc_coherent(&pdev->dev, mtd->writesize, +> + nand->data_buf = dmam_alloc_coherent(&pdev->dev, mtd->writesize, > + &nand->data_dma, GFP_KERNEL); Do you need these buffers before nand_scan_tail() or could you simply use the ones allocated by the core right after? > + if (!nand->data_buf) { -> + err =3D -ENOMEM; +> + err = -ENOMEM; > + goto err_disable_clk; > + } > + -> + nand->oob_buf =3D dmam_alloc_coherent(&pdev->dev, mtd->oobsize, +> + nand->oob_buf = dmam_alloc_coherent(&pdev->dev, mtd->oobsize, > + &nand->oob_dma, GFP_KERNEL); > + if (!nand->oob_buf) { -> + err =3D -ENOMEM; +> + err = -ENOMEM; > + goto err_disable_clk; > + } > + -> + chip->ecc.mode =3D NAND_ECC_HW; -> + chip->ecc.size =3D 512; -> + chip->ecc.read_page =3D tegra_nand_read_page; -> + chip->ecc.write_page =3D tegra_nand_write_page; +> + chip->ecc.mode = NAND_ECC_HW; +> + chip->ecc.size = 512; +> + chip->ecc.read_page = tegra_nand_read_page; +> + chip->ecc.write_page = tegra_nand_write_page; > + -> + value =3D readl(nand->regs + CFG); -> + value |=3D CFG_PIPE_EN | CFG_SKIP_SPARE | CFG_SKIP_SPARE_SIZE_4 | +> + value = readl(nand->regs + CFG); +> + value |= CFG_PIPE_EN | CFG_SKIP_SPARE | CFG_SKIP_SPARE_SIZE_4 | > + CFG_TAG_BYTE_SIZE(mtd_ooblayout_count_freebytes(mtd) - 1); > + > + if (chip->options & NAND_BUSWIDTH_16) -> + value |=3D CFG_BUS_WIDTH_16; +> + value |= CFG_BUS_WIDTH_16; > + > + switch (mtd->oobsize) { > + case 16: > + mtd_set_ooblayout(mtd, &tegra_nand_oob_16_ops); -> + chip->ecc.strength =3D 1; -> + chip->ecc.bytes =3D 4; +> + chip->ecc.strength = 1; +> + chip->ecc.bytes = 4; > + break; > + case 64: > + mtd_set_ooblayout(mtd, &tegra_nand_oob_64_ops); -> + chip->ecc.strength =3D 8; -> + chip->ecc.bytes =3D 18; -> + value |=3D CFG_ECC_SEL | CFG_TVAL_8; +> + chip->ecc.strength = 8; +> + chip->ecc.bytes = 18; +> + value |= CFG_ECC_SEL | CFG_TVAL_8; > + break; > + case 128: > + mtd_set_ooblayout(mtd, &tegra_nand_oob_128_ops); -> + chip->ecc.strength =3D 8; -> + chip->ecc.bytes =3D 18; -> + value |=3D CFG_ECC_SEL | CFG_TVAL_8; +> + chip->ecc.strength = 8; +> + chip->ecc.bytes = 18; +> + value |= CFG_ECC_SEL | CFG_TVAL_8; > + break; > + case 224: > + mtd_set_ooblayout(mtd, &tegra_nand_oob_224_ops); -> + chip->ecc.strength =3D 8; -> + chip->ecc.bytes =3D 18; -> + value |=3D CFG_ECC_SEL | CFG_TVAL_8; +> + chip->ecc.strength = 8; +> + chip->ecc.bytes = 18; +> + value |= CFG_ECC_SEL | CFG_TVAL_8; > + break; > + default: > + dev_err(&pdev->dev, "unhandled OOB size %d\n", mtd->oobsize); -> + err =3D -ENODEV; +> + err = -ENODEV; > + goto err_disable_clk; > + } > + > + switch (mtd->writesize) { > + case 256: -> + value |=3D CFG_PS_256; +> + value |= CFG_PS_256; > + break; > + case 512: -> + value |=3D CFG_PS_512; +> + value |= CFG_PS_512; > + break; > + case 1024: -> + value |=3D CFG_PS_1024; +> + value |= CFG_PS_1024; > + break; > + case 2048: -> + value |=3D CFG_PS_2048; +> + value |= CFG_PS_2048; > + break; > + case 4096: -> + value |=3D CFG_PS_4096; +> + value |= CFG_PS_4096; > + break; > + default: > + dev_err(&pdev->dev, "unhandled writesize %d\n", mtd->writesize); -> + err =3D -ENODEV; +> + err = -ENODEV; > + goto err_disable_clk; > + } > + @@ -695,11 +690,11 @@ use the ones allocated by the core right after? > + > + tegra_nand_setup_chiptiming(nand); > + -> + err =3D nand_scan_tail(mtd); +> + err = nand_scan_tail(mtd); > + if (err) > + goto err_disable_clk; > + -> + err =3D mtd_device_register(mtd, NULL, 0); +> + err = mtd_device_register(mtd, NULL, 0); > + if (err) > + goto err_cleanup_nand; > + @@ -716,7 +711,7 @@ use the ones allocated by the core right after? > + > +static int tegra_nand_remove(struct platform_device *pdev) > +{ -> + struct tegra_nand *nand =3D platform_get_drvdata(pdev); +> + struct tegra_nand *nand = platform_get_drvdata(pdev); > + > + nand_release(nand_to_mtd(&nand->chip)); > + @@ -725,18 +720,18 @@ use the ones allocated by the core right after? > + return 0; > +} > + -> +static const struct of_device_id tegra_nand_of_match[] =3D { -> + { .compatible =3D "nvidia,tegra20-nand" }, +> +static const struct of_device_id tegra_nand_of_match[] = { +> + { .compatible = "nvidia,tegra20-nand" }, > + { /* sentinel */ } > +}; > + -> +static struct platform_driver tegra_nand_driver =3D { -> + .driver =3D { -> + .name =3D "tegra-nand", -> + .of_match_table =3D tegra_nand_of_match, +> +static struct platform_driver tegra_nand_driver = { +> + .driver = { +> + .name = "tegra-nand", +> + .of_match_table = tegra_nand_of_match, > + }, -> + .probe =3D tegra_nand_probe, -> + .remove =3D tegra_nand_remove, +> + .probe = tegra_nand_probe, +> + .remove = tegra_nand_remove, > +}; > +module_platform_driver(tegra_nand_driver); > + diff --git a/a/content_digest b/N1/content_digest index 7fd6129..a26853d 100644 --- a/a/content_digest +++ b/N1/content_digest @@ -36,7 +36,7 @@ "probably wait for v4 then ;)\n" "\n" "Thanks for the work though!\n" - "Miqu=C3=A8l\n" + "Miqu\303\250l\n" "\n" "On Tue, 22 May 2018 14:07:06 +0200, Stefan Agner <stefan@agner.ch>\n" "wrote:\n" @@ -46,7 +46,7 @@ "> command queue feature. Regular operations/data transfers are\n" "> done in PIO mode. Page read/writes with hardware ECC make\n" "> use of the DMA for data transfer.\n" - ">=20\n" + "> \n" "> Signed-off-by: Lucas Stach <dev@lynxeye.de>\n" "> Signed-off-by: Stefan Agner <stefan@agner.ch>\n" "> ---\n" @@ -112,78 +112,77 @@ "> +\t\t\t const struct nand_subop *subop)\n" "> +{\n" "> +\tconst struct nand_op_instr *instr;\n" - "> +\tconst struct nand_op_instr *instr_data_in =3D NULL;\n" - "> +\tstruct mtd_info *mtd =3D nand_to_mtd(chip);\n" - "> +\tstruct tegra_nand *nand =3D to_tegra_nand(mtd);\n" - "> +\tunsigned int op_id =3D -1, trfr_in_sz =3D 0, trfr_out_sz =3D 0, offset =\n" - "=3D 0;\n" - "> +\tbool first_cmd =3D true;\n" + "> +\tconst struct nand_op_instr *instr_data_in = NULL;\n" + "> +\tstruct mtd_info *mtd = nand_to_mtd(chip);\n" + "> +\tstruct tegra_nand *nand = to_tegra_nand(mtd);\n" + "> +\tunsigned int op_id = -1, trfr_in_sz = 0, trfr_out_sz = 0, offset = 0;\n" + "> +\tbool first_cmd = true;\n" "> +\tbool force8bit;\n" - "> +\tu32 cmd =3D 0;\n" + "> +\tu32 cmd = 0;\n" "> +\tu32 value;\n" "> +\n" - "> +\tfor (op_id =3D 0; op_id < subop->ninstrs; op_id++) {\n" + "> +\tfor (op_id = 0; op_id < subop->ninstrs; op_id++) {\n" "> +\t\tunsigned int naddrs, i;\n" "> +\t\tconst u8 *addrs;\n" - "> +\t\tu32 addr1 =3D 0, addr2 =3D 0;\n" + "> +\t\tu32 addr1 = 0, addr2 = 0;\n" "> +\n" - "> +\t\tinstr =3D &subop->instrs[op_id];\n" + "> +\t\tinstr = &subop->instrs[op_id];\n" "> +\n" "> +\t\tswitch (instr->type) {\n" "> +\t\tcase NAND_OP_CMD_INSTR:\n" "> +\t\t\tif (first_cmd) {\n" - "> +\t\t\t\tcmd |=3D CMD_CLE;\n" + "> +\t\t\t\tcmd |= CMD_CLE;\n" "> +\t\t\t\twritel(instr->ctx.cmd.opcode, nand->regs + CMD_1);\n" "> +\t\t\t} else {\n" - "> +\t\t\t\tcmd |=3D CMD_SEC_CMD;\n" + "> +\t\t\t\tcmd |= CMD_SEC_CMD;\n" "> +\t\t\t\twritel(instr->ctx.cmd.opcode, nand->regs + CMD_2);\n" "> +\t\t\t}\n" - "> +\t\t\tfirst_cmd =3D false;\n" + "> +\t\t\tfirst_cmd = false;\n" "> +\t\t\tbreak;\n" "> +\t\tcase NAND_OP_ADDR_INSTR:\n" - "> +\t\t\toffset =3D nand_subop_get_addr_start_off(subop, op_id);\n" - "> +\t\t\tnaddrs =3D nand_subop_get_num_addr_cyc(subop, op_id);\n" - "> +\t\t\taddrs =3D &instr->ctx.addr.addrs[offset];\n" - "> +\n" - "> +\t\t\tcmd |=3D CMD_ALE | CMD_ALE_SIZE(naddrs);\n" - "> +\t\t\tfor (i =3D 0; i < min_t(unsigned int, 4, naddrs); i++)\n" - "> +\t\t\t\taddr1 |=3D *addrs++ << (8 * i);\n" - "> +\t\t\tnaddrs -=3D i;\n" - "> +\t\t\tfor (i =3D 0; i < min_t(unsigned int, 4, naddrs); i++)\n" - "> +\t\t\t\taddr2 |=3D *addrs++ << (8 * i);\n" + "> +\t\t\toffset = nand_subop_get_addr_start_off(subop, op_id);\n" + "> +\t\t\tnaddrs = nand_subop_get_num_addr_cyc(subop, op_id);\n" + "> +\t\t\taddrs = &instr->ctx.addr.addrs[offset];\n" + "> +\n" + "> +\t\t\tcmd |= CMD_ALE | CMD_ALE_SIZE(naddrs);\n" + "> +\t\t\tfor (i = 0; i < min_t(unsigned int, 4, naddrs); i++)\n" + "> +\t\t\t\taddr1 |= *addrs++ << (8 * i);\n" + "> +\t\t\tnaddrs -= i;\n" + "> +\t\t\tfor (i = 0; i < min_t(unsigned int, 4, naddrs); i++)\n" + "> +\t\t\t\taddr2 |= *addrs++ << (8 * i);\n" "> +\t\t\twritel(addr1, nand->regs + ADDR_1);\n" "> +\t\t\twritel(addr2, nand->regs + ADDR_2);\n" "> +\t\t\tbreak;\n" "> +\n" "> +\t\tcase NAND_OP_DATA_IN_INSTR:\n" - "> +\t\t\ttrfr_in_sz =3D nand_subop_get_data_len(subop, op_id);\n" - "> +\t\t\toffset =3D nand_subop_get_data_start_off(subop, op_id);\n" + "> +\t\t\ttrfr_in_sz = nand_subop_get_data_len(subop, op_id);\n" + "> +\t\t\toffset = nand_subop_get_data_start_off(subop, op_id);\n" "> +\n" - "> +\t\t\tcmd |=3D CMD_TRANS_SIZE(trfr_in_sz) | CMD_PIO | CMD_RX | CMD_A_VALID;\n" + "> +\t\t\tcmd |= CMD_TRANS_SIZE(trfr_in_sz) | CMD_PIO | CMD_RX | CMD_A_VALID;\n" "> +\n" - "> +\t\t\tinstr_data_in =3D instr;\n" + "> +\t\t\tinstr_data_in = instr;\n" "> +\t\t\tbreak;\n" "> +\n" "> +\t\tcase NAND_OP_DATA_OUT_INSTR:\n" - "> +\t\t\ttrfr_out_sz =3D nand_subop_get_data_len(subop, op_id);\n" - "> +\t\t\toffset =3D nand_subop_get_data_start_off(subop, op_id);\n" - "> +\t\t\ttrfr_out_sz =3D min_t(size_t, trfr_out_sz, 4);\n" + "> +\t\t\ttrfr_out_sz = nand_subop_get_data_len(subop, op_id);\n" + "> +\t\t\toffset = nand_subop_get_data_start_off(subop, op_id);\n" + "> +\t\t\ttrfr_out_sz = min_t(size_t, trfr_out_sz, 4);\n" "> +\n" - "> +\t\t\tcmd |=3D CMD_TRANS_SIZE(trfr_out_sz) | CMD_PIO | CMD_TX | CMD_A_VALID;\n" + "> +\t\t\tcmd |= CMD_TRANS_SIZE(trfr_out_sz) | CMD_PIO | CMD_TX | CMD_A_VALID;\n" "> +\n" "> +\t\t\tmemcpy(&value, instr->ctx.data.buf.out + offset, trfr_out_sz);\n" "> +\t\t\twritel(value, nand->regs + RESP);\n" "> +\n" "> +\t\t\tbreak;\n" "> +\t\tcase NAND_OP_WAITRDY_INSTR:\n" - "> +\t\t\tcmd |=3D CMD_RBSY_CHK;\n" + "> +\t\t\tcmd |= CMD_RBSY_CHK;\n" "> +\t\t\tbreak;\n" "> +\n" "> +\t\t}\n" "> +\t}\n" "> +\n" "> +\n" - "> +\tcmd |=3D CMD_GO | CMD_CE(nand->cur_chip);\n" + "> +\tcmd |= CMD_GO | CMD_CE(nand->cur_chip);\n" "> +\twritel(cmd, nand->regs + CMD);\n" "> +\twait_for_completion(&nand->command_complete);\n" "\n" @@ -192,17 +191,16 @@ "> +\n" "> +\tif (instr_data_in) {\n" "> +\t\tu32 value;\n" - "> +\t\tsize_t n =3D min_t(size_t, trfr_in_sz, 4);\n" + "> +\t\tsize_t n = min_t(size_t, trfr_in_sz, 4);\n" "> +\n" - "> +\t\tvalue =3D readl(nand->regs + RESP);\n" + "> +\t\tvalue = readl(nand->regs + RESP);\n" "> +\t\tmemcpy(instr_data_in->ctx.data.buf.in + offset, &value, n);\n" "> +\t}\n" "> +\n" "> +\treturn 0;\n" "> +}\n" "> +\n" - "> +static const struct nand_op_parser tegra_nand_op_parser =3D NAND_OP_PARS=\n" - "ER(\n" + "> +static const struct nand_op_parser tegra_nand_op_parser = NAND_OP_PARSER(\n" "> +\tNAND_OP_PARSER_PATTERN(tegra_nand_cmd,\n" "> +\t\tNAND_OP_PARSER_PAT_CMD_ELEM(true),\n" "> +\t\tNAND_OP_PARSER_PAT_ADDR_ELEM(true, 8),\n" @@ -227,20 +225,19 @@ "> +}\n" "> +static void tegra_nand_select_chip(struct mtd_info *mtd, int chip)\n" "> +{\n" - "> +\tstruct tegra_nand *nand =3D to_tegra_nand(mtd);\n" + "> +\tstruct tegra_nand *nand = to_tegra_nand(mtd);\n" "> +\n" - "> +\tnand->cur_chip =3D chip;\n" + "> +\tnand->cur_chip = chip;\n" "\n" "You should probably save the timings configuration and apply them back\n" "here in case of using different chips.\n" "\n" "> +}\n" "> +\n" - "> +static u32 tegra_nand_fill_address(struct mtd_info *mtd, struct nand_chi=\n" - "p *chip,\n" + "> +static u32 tegra_nand_fill_address(struct mtd_info *mtd, struct nand_chip *chip,\n" "> +\t\t\t\t int page)\n" "> +{\n" - "> +\tstruct tegra_nand *nand =3D to_tegra_nand(mtd);\n" + "> +\tstruct tegra_nand *nand = to_tegra_nand(mtd);\n" "> +\n" "> +\t/* Lower 16-bits are column, always 0 */\n" "> +\twritel(page << 16, nand->regs + ADDR_1);\n" @@ -253,20 +250,19 @@ "> +\treturn 4;\n" "> +}\n" "> +\n" - "> +static int tegra_nand_read_page(struct mtd_info *mtd, struct nand_chip *=\n" - "chip,\n" + "> +static int tegra_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,\n" "> +\t\t\t\tuint8_t *buf, int oob_required, int page)\n" "> +{\n" - "> +\tstruct tegra_nand *nand =3D to_tegra_nand(mtd);\n" + "> +\tstruct tegra_nand *nand = to_tegra_nand(mtd);\n" "> +\tu32 value, addrs;\n" "> +\n" "> +\twritel(NAND_CMD_READ0, nand->regs + CMD_1);\n" "> +\twritel(NAND_CMD_READSTART, nand->regs + CMD_2);\n" "> +\n" - "> +\taddrs =3D tegra_nand_fill_address(mtd, chip, page);\n" + "> +\taddrs = tegra_nand_fill_address(mtd, chip, page);\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + CFG);\n" - "> +\tvalue |=3D CFG_HW_ECC | CFG_ERR_COR;\n" + "> +\tvalue = readl(nand->regs + CFG);\n" + "> +\tvalue |= CFG_HW_ECC | CFG_ERR_COR;\n" "> +\twritel(value, nand->regs + CFG);\n" "> +\n" "> +\twritel(mtd->writesize - 1, nand->regs + DMA_CFG_A);\n" @@ -281,18 +277,18 @@ "> +\t\twritel(0, nand->regs + TAG_PTR);\n" "> +\t}\n" "> +\n" - "> +\tvalue =3D DMA_CTRL_GO | DMA_CTRL_IN | DMA_CTRL_PERF_EN |\n" + "> +\tvalue = DMA_CTRL_GO | DMA_CTRL_IN | DMA_CTRL_PERF_EN |\n" "> +\t\tDMA_CTRL_REUSE | DMA_CTRL_IE_DONE | DMA_CTRL_IS_DONE |\n" "> +\t\tDMA_CTRL_BURST_8 | DMA_CTRL_EN_A;\n" "> +\tif (oob_required)\n" - "> +\t\tvalue |=3D DMA_CTRL_EN_B;\n" + "> +\t\tvalue |= DMA_CTRL_EN_B;\n" "> +\twritel(value, nand->regs + DMA_CTRL);\n" "> +\n" - "> +\tvalue =3D CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD |\n" + "> +\tvalue = CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD |\n" "> +\t\tCMD_RBSY_CHK | CMD_GO | CMD_RX | CMD_TRANS_SIZE(9) |\n" "> +\t\tCMD_A_VALID | CMD_CE(nand->cur_chip);\n" "> +\tif (oob_required)\n" - "> +\t\tvalue |=3D CMD_B_VALID;\n" + "> +\t\tvalue |= CMD_B_VALID;\n" "> +\twritel(value, nand->regs + CMD);\n" "> +\n" "> +\twait_for_completion(&nand->command_complete);\n" @@ -311,11 +307,11 @@ "> +\t}\n" "> +\tmemcpy(buf, nand->data_buf, mtd->writesize);\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + CFG);\n" - "> +\tvalue &=3D ~(CFG_HW_ECC | CFG_ERR_COR);\n" + "> +\tvalue = readl(nand->regs + CFG);\n" + "> +\tvalue &= ~(CFG_HW_ECC | CFG_ERR_COR);\n" "> +\twritel(value, nand->regs + CFG);\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + DEC_STATUS);\n" + "> +\tvalue = readl(nand->regs + DEC_STATUS);\n" "> +\tif (value & DEC_STATUS_A_ECC_FAIL) {\n" "> +\t\t/*\n" "> +\t\t * The ECC isn't smart enough to figure out if a page is\n" @@ -324,17 +320,17 @@ "> +\t\t * error or a false positive.\n" "> +\t\t */\n" "> +\t\tint i, err;\n" - "> +\t\tint flips_threshold =3D chip->ecc.strength / 2;\n" - "> +\t\tint max_bitflips =3D 0;\n" + "> +\t\tint flips_threshold = chip->ecc.strength / 2;\n" + "> +\t\tint max_bitflips = 0;\n" "> +\n" - "> +\t\tfor (i =3D 0; i < chip->ecc.steps; i++) {\n" - "> +\t\t\tu8 *data =3D buf + (chip->ecc.size * i);\n" - "> +\t\t\terr =3D nand_check_erased_ecc_chunk(data, chip->ecc.size,\n" + "> +\t\tfor (i = 0; i < chip->ecc.steps; i++) {\n" + "> +\t\t\tu8 *data = buf + (chip->ecc.size * i);\n" + "> +\t\t\terr = nand_check_erased_ecc_chunk(data, chip->ecc.size,\n" "\n" "Are you sure the data was uncorrected there? I bet you have corrected\n" "data in chip->ecc.size and should re-read the page with the raw\n" "helpers before using nand_check_erased_ecc_chunk().\n" - "=20\n" + " \n" "> +\t\t\t\t\t\t\t NULL, 0,\n" "> +\t\t\t\t\t\t\t NULL, 0,\n" "> +\t\t\t\t\t\t\t flips_threshold);\n" @@ -348,9 +344,9 @@ "In case of ECC failure you should increment ecc_stats.failed.\n" "\n" "> +\n" - "> +\t\t\tmax_bitflips +=3D max_bitflips;\n" + "> +\t\t\tmax_bitflips += max_bitflips;\n" "\n" - "max_bitflipts =3D max_t(unsigned int, max_bitflipts, err);\n" + "max_bitflipts = max_t(unsigned int, max_bitflipts, err);\n" "\n" "> +\t\t}\n" "> +\n" @@ -360,10 +356,10 @@ "> +\tif (nand->last_read_error) {\n" "> +\t\tint max_corr_cnt, corr_sec_flag;\n" "> +\n" - "> +\t\tvalue =3D readl(nand->regs + DEC_STAT_BUF);\n" - "> +\t\tcorr_sec_flag =3D (value & DEC_STAT_BUF_CORR_SEC_FLAG_MASK) >>\n" + "> +\t\tvalue = readl(nand->regs + DEC_STAT_BUF);\n" + "> +\t\tcorr_sec_flag = (value & DEC_STAT_BUF_CORR_SEC_FLAG_MASK) >>\n" "> +\t\t\t\tDEC_STAT_BUF_CORR_SEC_FLAG_SHIFT;\n" - "> +\t\tmax_corr_cnt =3D (value & DEC_STAT_BUF_MAX_CORR_CNT_MASK) >>\n" + "> +\t\tmax_corr_cnt = (value & DEC_STAT_BUF_MAX_CORR_CNT_MASK) >>\n" "> +\t\t\t DEC_STAT_BUF_MAX_CORR_CNT_SHIFT;\n" "> +\n" "> +\t\t/*\n" @@ -375,31 +371,30 @@ "> +\t\t * that all regions where errors have been corrected\n" "> +\t\t * encountered the maximum number of bitflips.\n" "> +\t\t */\n" - "> +\t\tmtd->ecc_stats.corrected +=3D max_corr_cnt * hweight8(corr_sec_flag);\n" + "> +\t\tmtd->ecc_stats.corrected += max_corr_cnt * hweight8(corr_sec_flag);\n" "\n" "That's bad. But okay if we don't have the information.\n" "\n" - "> +\t\tnand->last_read_error =3D false;\n" + "> +\t\tnand->last_read_error = false;\n" "> +\t\treturn value;\n" "> +\t}\n" "> +\n" "> +\treturn 0;\n" "> +}\n" "> +\n" - "> +static int tegra_nand_write_page(struct mtd_info *mtd, struct nand_chip =\n" - "*chip,\n" + "> +static int tegra_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,\n" "> +\t\t\t\t const uint8_t *buf, int oob_required, int page)\n" "> +{\n" - "> +\tstruct tegra_nand *nand =3D to_tegra_nand(mtd);\n" + "> +\tstruct tegra_nand *nand = to_tegra_nand(mtd);\n" "> +\tu32 value, addrs;\n" "> +\n" "> +\twritel(NAND_CMD_SEQIN, nand->regs + CMD_1);\n" "> +\twritel(NAND_CMD_PAGEPROG, nand->regs + CMD_2);\n" "> +\n" - "> +\taddrs =3D tegra_nand_fill_address(mtd, chip, page);\n" + "> +\taddrs = tegra_nand_fill_address(mtd, chip, page);\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + CFG);\n" - "> +\tvalue |=3D CFG_HW_ECC | CFG_ERR_COR;\n" + "> +\tvalue = readl(nand->regs + CFG);\n" + "> +\tvalue |= CFG_HW_ECC | CFG_ERR_COR;\n" "> +\twritel(value, nand->regs + CFG);\n" "\n" "You might want to test with the _relaxed() operators?\n" @@ -424,21 +419,21 @@ "> +\t\twritel(0, nand->regs + TAG_PTR);\n" "> +\t}\n" "> +\n" - "> +\tvalue =3D DMA_CTRL_GO | DMA_CTRL_OUT | DMA_CTRL_PERF_EN |\n" + "> +\tvalue = DMA_CTRL_GO | DMA_CTRL_OUT | DMA_CTRL_PERF_EN |\n" "> +\t\tDMA_CTRL_IE_DONE | DMA_CTRL_IS_DONE |\n" "> +\t\tDMA_CTRL_BURST_8 | DMA_CTRL_EN_A;\n" "> +\tif (oob_required)\n" - "> +\t\tvalue |=3D DMA_CTRL_EN_B;\n" + "> +\t\tvalue |= DMA_CTRL_EN_B;\n" "\n" "Line here\n" "\n" "> +\twritel(value, nand->regs + DMA_CTRL);\n" "> +\n" - "> +\tvalue =3D CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD |\n" + "> +\tvalue = CMD_CLE | CMD_ALE | CMD_ALE_SIZE(addrs) | CMD_SEC_CMD |\n" "> +\t\tCMD_AFT_DAT | CMD_RBSY_CHK | CMD_GO | CMD_TX | CMD_A_VALID |\n" "> +\t\tCMD_TRANS_SIZE(9) | CMD_CE(nand->cur_chip);\n" "> +\tif (oob_required)\n" - "> +\t\tvalue |=3D CMD_B_VALID;\n" + "> +\t\tvalue |= CMD_B_VALID;\n" "\n" "Line here\n" "\n" @@ -447,8 +442,8 @@ "> +\twait_for_completion(&nand->command_complete);\n" "> +\twait_for_completion(&nand->dma_complete);\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + CFG);\n" - "> +\tvalue &=3D ~(CFG_HW_ECC | CFG_ERR_COR);\n" + "> +\tvalue = readl(nand->regs + CFG);\n" + "> +\tvalue &= ~(CFG_HW_ECC | CFG_ERR_COR);\n" "> +\twritel(value, nand->regs + CFG);\n" "> +\n" "> +\treturn 0;\n" @@ -464,65 +459,65 @@ "rawnand.h. You could use them in the following derivations.\n" "\n" "> +\t */\n" - "> +\tunsigned int rate =3D clk_get_rate(nand->clk) / 1000000;\n" - "> +\tunsigned int period =3D DIV_ROUND_UP(1000000, rate);\n" + "> +\tunsigned int rate = clk_get_rate(nand->clk) / 1000000;\n" + "> +\tunsigned int period = DIV_ROUND_UP(1000000, rate);\n" "> +\tconst struct nand_sdr_timings *timings;\n" - "> +\tu32 val, reg =3D 0;\n" + "> +\tu32 val, reg = 0;\n" "> +\n" - "> +\ttimings =3D onfi_async_timing_mode_to_sdr_timings(mode);\n" + "> +\ttimings = onfi_async_timing_mode_to_sdr_timings(mode);\n" "> +\n" - "> +\tval =3D DIV_ROUND_UP(max3(timings->tAR_min, timings->tRR_min,\n" + "> +\tval = DIV_ROUND_UP(max3(timings->tAR_min, timings->tRR_min,\n" "> +\t\t\t\ttimings->tRC_min), period);\n" "> +\tif (val > 2)\n" - "> +\t\tval -=3D 3;\n" - "> +\treg |=3D TIMING_TCR_TAR_TRR(val);\n" + "> +\t\tval -= 3;\n" + "> +\treg |= TIMING_TCR_TAR_TRR(val);\n" "> +\n" - "> +\tval =3D DIV_ROUND_UP(max(max(timings->tCS_min, timings->tCH_min),\n" + "> +\tval = DIV_ROUND_UP(max(max(timings->tCS_min, timings->tCH_min),\n" "> +\t\t\t\t max(timings->tALS_min, timings->tALH_min)),\n" "\n" "Is the second line aligned correctly?\n" "\n" "> +\t\t\t period);\n" "> +\tif (val > 1)\n" - "> +\t\tval -=3D 2;\n" + "> +\t\tval -= 2;\n" "\n" "This is weird and I would recommend a comment.\n" "\n" - "> +\treg |=3D TIMING_TCS(val);\n" + "> +\treg |= TIMING_TCS(val);\n" "> +\n" - "> +\tval =3D DIV_ROUND_UP(max(timings->tRP_min, timings->tREA_max) + 6000,\n" + "> +\tval = DIV_ROUND_UP(max(timings->tRP_min, timings->tREA_max) + 6000,\n" "> +\t\t\t period);\n" - "> +\treg |=3D TIMING_TRP(val) | TIMING_TRP_RESP(val);\n" + "> +\treg |= TIMING_TRP(val) | TIMING_TRP_RESP(val);\n" "> +\n" - "> +\treg |=3D TIMING_TWB(DIV_ROUND_UP(timings->tWB_max, period));\n" - "> +\treg |=3D TIMING_TWHR(DIV_ROUND_UP(timings->tWHR_min, period));\n" - "> +\treg |=3D TIMING_TWH(DIV_ROUND_UP(timings->tWH_min, period));\n" - "> +\treg |=3D TIMING_TWP(DIV_ROUND_UP(timings->tWP_min, period));\n" - "> +\treg |=3D TIMING_TRH(DIV_ROUND_UP(timings->tRHW_min, period));\n" + "> +\treg |= TIMING_TWB(DIV_ROUND_UP(timings->tWB_max, period));\n" + "> +\treg |= TIMING_TWHR(DIV_ROUND_UP(timings->tWHR_min, period));\n" + "> +\treg |= TIMING_TWH(DIV_ROUND_UP(timings->tWH_min, period));\n" + "> +\treg |= TIMING_TWP(DIV_ROUND_UP(timings->tWP_min, period));\n" + "> +\treg |= TIMING_TRH(DIV_ROUND_UP(timings->tRHW_min, period));\n" "> +\n" "> +\twritel(reg, nand->regs + TIMING_1);\n" "> +\n" - "> +\tval =3D DIV_ROUND_UP(timings->tADL_min, period);\n" + "> +\tval = DIV_ROUND_UP(timings->tADL_min, period);\n" "> +\tif (val > 2)\n" - "> +\t\tval -=3D 3;\n" + "> +\t\tval -= 3;\n" "\n" "Ditto\n" "\n" - "> +\treg =3D TIMING_TADL(val);\n" + "> +\treg = TIMING_TADL(val);\n" "> +\n" "> +\twritel(reg, nand->regs + TIMING_2);\n" "> +}\n" "> +\n" "> +static void tegra_nand_setup_chiptiming(struct tegra_nand *nand)\n" "> +{\n" - "> +\tstruct nand_chip *chip =3D &nand->chip;\n" + "> +\tstruct nand_chip *chip = &nand->chip;\n" "> +\tint mode;\n" "> +\n" - "> +\tmode =3D onfi_get_async_timing_mode(chip);\n" - "> +\tif (mode =3D=3D ONFI_TIMING_MODE_UNKNOWN)\n" - "> +\t\tmode =3D chip->onfi_timing_mode_default;\n" + "> +\tmode = onfi_get_async_timing_mode(chip);\n" + "> +\tif (mode == ONFI_TIMING_MODE_UNKNOWN)\n" + "> +\t\tmode = chip->onfi_timing_mode_default;\n" "> +\telse\n" - "> +\t\tmode =3D fls(mode);\n" + "> +\t\tmode = fls(mode);\n" "> +\n" "> +\ttegra_nand_setup_timing(nand, mode);\n" "> +}\n" @@ -547,39 +542,39 @@ "\n" "s/value/reg/ ? or something more explicit?\n" "\n" - "> +\tint irq, err =3D 0;\n" + "> +\tint irq, err = 0;\n" "> +\n" - "> +\tnand =3D devm_kzalloc(&pdev->dev, sizeof(*nand), GFP_KERNEL);\n" + "> +\tnand = devm_kzalloc(&pdev->dev, sizeof(*nand), GFP_KERNEL);\n" "> +\tif (!nand)\n" "> +\t\treturn -ENOMEM;\n" "> +\n" - "> +\tnand->dev =3D &pdev->dev;\n" + "> +\tnand->dev = &pdev->dev;\n" "> +\n" - "> +\tres =3D platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" - "> +\tnand->regs =3D devm_ioremap_resource(&pdev->dev, res);\n" + "> +\tres = platform_get_resource(pdev, IORESOURCE_MEM, 0);\n" + "> +\tnand->regs = devm_ioremap_resource(&pdev->dev, res);\n" "> +\tif (IS_ERR(nand->regs))\n" "> +\t\treturn PTR_ERR(nand->regs);\n" "> +\n" - "> +\tirq =3D platform_get_irq(pdev, 0);\n" - "> +\terr =3D devm_request_irq(&pdev->dev, irq, tegra_nand_irq, 0,\n" + "> +\tirq = platform_get_irq(pdev, 0);\n" + "> +\terr = devm_request_irq(&pdev->dev, irq, tegra_nand_irq, 0,\n" "> +\t\t\t dev_name(&pdev->dev), nand);\n" "> +\tif (err)\n" "> +\t\treturn err;\n" "> +\n" - "> +\trst =3D devm_reset_control_get(&pdev->dev, \"nand\");\n" + "> +\trst = devm_reset_control_get(&pdev->dev, \"nand\");\n" "> +\tif (IS_ERR(rst))\n" "> +\t\treturn PTR_ERR(rst);\n" "> +\n" - "> +\tnand->clk =3D devm_clk_get(&pdev->dev, \"nand\");\n" + "> +\tnand->clk = devm_clk_get(&pdev->dev, \"nand\");\n" "> +\tif (IS_ERR(nand->clk))\n" "> +\t\treturn PTR_ERR(nand->clk);\n" "> +\n" - "> +\tnand->wp_gpio =3D gpiod_get_optional(&pdev->dev, \"wp-gpios\",\n" + "> +\tnand->wp_gpio = gpiod_get_optional(&pdev->dev, \"wp-gpios\",\n" "> +\t\t\t\t\t GPIOD_OUT_HIGH);\n" "> +\tif (IS_ERR(nand->wp_gpio))\n" "> +\t\treturn PTR_ERR(nand->wp_gpio);\n" "> +\n" - "> +\terr =3D clk_prepare_enable(nand->clk);\n" + "> +\terr = clk_prepare_enable(nand->clk);\n" "> +\tif (err)\n" "> +\t\treturn err;\n" "> +\n" @@ -587,7 +582,7 @@ "> +\tudelay(2);\n" "> +\treset_control_deassert(rst);\n" "> +\n" - "> +\tvalue =3D HWSTATUS_RDSTATUS_MASK(1) | HWSTATUS_RDSTATUS_VALUE(0) |\n" + "> +\tvalue = HWSTATUS_RDSTATUS_MASK(1) | HWSTATUS_RDSTATUS_VALUE(0) |\n" "> +\t\tHWSTATUS_RBSY_MASK(NAND_STATUS_READY) |\n" "> +\t\tHWSTATUS_RBSY_VALUE(NAND_STATUS_READY);\n" "> +\twritel(NAND_CMD_STATUS, nand->regs + HWSTATUS_CMD);\n" @@ -597,129 +592,129 @@ "> +\tinit_completion(&nand->dma_complete);\n" "> +\n" "> +\t/* clear interrupts */\n" - "> +\tvalue =3D readl(nand->regs + ISR);\n" + "> +\tvalue = readl(nand->regs + ISR);\n" "> +\twritel(value, nand->regs + ISR);\n" "> +\n" "> +\twritel(DMA_CTRL_IS_DONE, nand->regs + DMA_CTRL);\n" "> +\n" "> +\t/* enable interrupts */\n" - "> +\tvalue =3D IER_UND | IER_OVR | IER_CMD_DONE | IER_ECC_ERR | IER_GIE;\n" + "> +\tvalue = IER_UND | IER_OVR | IER_CMD_DONE | IER_ECC_ERR | IER_GIE;\n" "> +\twritel(value, nand->regs + IER);\n" "> +\n" "> +\t/* reset config */\n" "> +\twritel(0, nand->regs + CFG);\n" "> +\n" - "> +\tchip =3D &nand->chip;\n" - "> +\tmtd =3D nand_to_mtd(chip);\n" + "> +\tchip = &nand->chip;\n" + "> +\tmtd = nand_to_mtd(chip);\n" "> +\n" - "> +\tmtd->dev.parent =3D &pdev->dev;\n" - "> +\tmtd->name =3D \"tegra_nand\";\n" + "> +\tmtd->dev.parent = &pdev->dev;\n" + "> +\tmtd->name = \"tegra_nand\";\n" "\n" "I just figured it was undocumented (yet) but you could have a label\n" "string property in your nand DT node that tells you the name of the\n" "MTD device instead of something too generic like tegra_nand.\n" "\n" - "> +\tmtd->owner =3D THIS_MODULE;\n" + "> +\tmtd->owner = THIS_MODULE;\n" "> +\n" "> +\tnand_set_flash_node(chip, pdev->dev.of_node);\n" "> +\tnand_set_controller_data(chip, nand);\n" "> +\n" - "> +\tchip->options =3D NAND_NO_SUBPAGE_WRITE;\n" - "> +\tchip->exec_op =3D tegra_nand_exec_op;\n" - "> +\tchip->select_chip =3D tegra_nand_select_chip;\n" + "> +\tchip->options = NAND_NO_SUBPAGE_WRITE;\n" + "> +\tchip->exec_op = tegra_nand_exec_op;\n" + "> +\tchip->select_chip = tegra_nand_select_chip;\n" "> +\ttegra_nand_setup_timing(nand, 0);\n" "\n" "You really should implement ->setup_data_interface() and let the core\n" "handle the timings issue entirely (mind that chipnr is not the NAND\n" "chip id but more the CS id asserted for the pointed NAND chip).\n" - "=20\n" + " \n" "> +\n" - "> +\terr =3D nand_scan_ident(mtd, 1, NULL);\n" + "> +\terr = nand_scan_ident(mtd, 1, NULL);\n" "> +\tif (err)\n" "> +\t\tgoto err_disable_clk;\n" "> +\n" "> +\tif (chip->bbt_options & NAND_BBT_USE_FLASH)\n" - "> +\t\tchip->bbt_options |=3D NAND_BBT_NO_OOB;\n" + "> +\t\tchip->bbt_options |= NAND_BBT_NO_OOB;\n" "> +\n" - "> +\tnand->data_buf =3D dmam_alloc_coherent(&pdev->dev, mtd->writesize,\n" + "> +\tnand->data_buf = dmam_alloc_coherent(&pdev->dev, mtd->writesize,\n" "> +\t\t\t\t\t &nand->data_dma, GFP_KERNEL);\n" "\n" "Do you need these buffers before nand_scan_tail() or could you simply\n" "use the ones allocated by the core right after?\n" "\n" "> +\tif (!nand->data_buf) {\n" - "> +\t\terr =3D -ENOMEM;\n" + "> +\t\terr = -ENOMEM;\n" "> +\t\tgoto err_disable_clk;\n" "> +\t}\n" "> +\n" - "> +\tnand->oob_buf =3D dmam_alloc_coherent(&pdev->dev, mtd->oobsize,\n" + "> +\tnand->oob_buf = dmam_alloc_coherent(&pdev->dev, mtd->oobsize,\n" "> +\t\t\t\t\t &nand->oob_dma, GFP_KERNEL);\n" "> +\tif (!nand->oob_buf) {\n" - "> +\t\terr =3D -ENOMEM;\n" + "> +\t\terr = -ENOMEM;\n" "> +\t\tgoto err_disable_clk;\n" "> +\t}\n" "> +\n" - "> +\tchip->ecc.mode =3D NAND_ECC_HW;\n" - "> +\tchip->ecc.size =3D 512;\n" - "> +\tchip->ecc.read_page =3D tegra_nand_read_page;\n" - "> +\tchip->ecc.write_page =3D tegra_nand_write_page;\n" + "> +\tchip->ecc.mode = NAND_ECC_HW;\n" + "> +\tchip->ecc.size = 512;\n" + "> +\tchip->ecc.read_page = tegra_nand_read_page;\n" + "> +\tchip->ecc.write_page = tegra_nand_write_page;\n" "> +\n" - "> +\tvalue =3D readl(nand->regs + CFG);\n" - "> +\tvalue |=3D CFG_PIPE_EN | CFG_SKIP_SPARE | CFG_SKIP_SPARE_SIZE_4 |\n" + "> +\tvalue = readl(nand->regs + CFG);\n" + "> +\tvalue |= CFG_PIPE_EN | CFG_SKIP_SPARE | CFG_SKIP_SPARE_SIZE_4 |\n" "> +\t\t CFG_TAG_BYTE_SIZE(mtd_ooblayout_count_freebytes(mtd) - 1);\n" "> +\n" "> +\tif (chip->options & NAND_BUSWIDTH_16)\n" - "> +\t\tvalue |=3D CFG_BUS_WIDTH_16;\n" + "> +\t\tvalue |= CFG_BUS_WIDTH_16;\n" "> +\n" "> +\tswitch (mtd->oobsize) {\n" "> +\tcase 16:\n" "> +\t\tmtd_set_ooblayout(mtd, &tegra_nand_oob_16_ops);\n" - "> +\t\tchip->ecc.strength =3D 1;\n" - "> +\t\tchip->ecc.bytes =3D 4;\n" + "> +\t\tchip->ecc.strength = 1;\n" + "> +\t\tchip->ecc.bytes = 4;\n" "> +\t\tbreak;\n" "> +\tcase 64:\n" "> +\t\tmtd_set_ooblayout(mtd, &tegra_nand_oob_64_ops);\n" - "> +\t\tchip->ecc.strength =3D 8;\n" - "> +\t\tchip->ecc.bytes =3D 18;\n" - "> +\t\tvalue |=3D CFG_ECC_SEL | CFG_TVAL_8;\n" + "> +\t\tchip->ecc.strength = 8;\n" + "> +\t\tchip->ecc.bytes = 18;\n" + "> +\t\tvalue |= CFG_ECC_SEL | CFG_TVAL_8;\n" "> +\t\tbreak;\n" "> +\tcase 128:\n" "> +\t\tmtd_set_ooblayout(mtd, &tegra_nand_oob_128_ops);\n" - "> +\t\tchip->ecc.strength =3D 8;\n" - "> +\t\tchip->ecc.bytes =3D 18;\n" - "> +\t\tvalue |=3D CFG_ECC_SEL | CFG_TVAL_8;\n" + "> +\t\tchip->ecc.strength = 8;\n" + "> +\t\tchip->ecc.bytes = 18;\n" + "> +\t\tvalue |= CFG_ECC_SEL | CFG_TVAL_8;\n" "> +\t\tbreak;\n" "> +\tcase 224:\n" "> +\t\tmtd_set_ooblayout(mtd, &tegra_nand_oob_224_ops);\n" - "> +\t\tchip->ecc.strength =3D 8;\n" - "> +\t\tchip->ecc.bytes =3D 18;\n" - "> +\t\tvalue |=3D CFG_ECC_SEL | CFG_TVAL_8;\n" + "> +\t\tchip->ecc.strength = 8;\n" + "> +\t\tchip->ecc.bytes = 18;\n" + "> +\t\tvalue |= CFG_ECC_SEL | CFG_TVAL_8;\n" "> +\t\tbreak;\n" "> +\tdefault:\n" "> +\t\tdev_err(&pdev->dev, \"unhandled OOB size %d\\n\", mtd->oobsize);\n" - "> +\t\terr =3D -ENODEV;\n" + "> +\t\terr = -ENODEV;\n" "> +\t\tgoto err_disable_clk;\n" "> +\t}\n" "> +\n" "> +\tswitch (mtd->writesize) {\n" "> +\tcase 256:\n" - "> +\t\tvalue |=3D CFG_PS_256;\n" + "> +\t\tvalue |= CFG_PS_256;\n" "> +\t\tbreak;\n" "> +\tcase 512:\n" - "> +\t\tvalue |=3D CFG_PS_512;\n" + "> +\t\tvalue |= CFG_PS_512;\n" "> +\t\tbreak;\n" "> +\tcase 1024:\n" - "> +\t\tvalue |=3D CFG_PS_1024;\n" + "> +\t\tvalue |= CFG_PS_1024;\n" "> +\t\tbreak;\n" "> +\tcase 2048:\n" - "> +\t\tvalue |=3D CFG_PS_2048;\n" + "> +\t\tvalue |= CFG_PS_2048;\n" "> +\t\tbreak;\n" "> +\tcase 4096:\n" - "> +\t\tvalue |=3D CFG_PS_4096;\n" + "> +\t\tvalue |= CFG_PS_4096;\n" "> +\t\tbreak;\n" "> +\tdefault:\n" "> +\t\tdev_err(&pdev->dev, \"unhandled writesize %d\\n\", mtd->writesize);\n" - "> +\t\terr =3D -ENODEV;\n" + "> +\t\terr = -ENODEV;\n" "> +\t\tgoto err_disable_clk;\n" "> +\t}\n" "> +\n" @@ -727,11 +722,11 @@ "> +\n" "> +\ttegra_nand_setup_chiptiming(nand);\n" "> +\n" - "> +\terr =3D nand_scan_tail(mtd);\n" + "> +\terr = nand_scan_tail(mtd);\n" "> +\tif (err)\n" "> +\t\tgoto err_disable_clk;\n" "> +\n" - "> +\terr =3D mtd_device_register(mtd, NULL, 0);\n" + "> +\terr = mtd_device_register(mtd, NULL, 0);\n" "> +\tif (err)\n" "> +\t\tgoto err_cleanup_nand;\n" "> +\n" @@ -748,7 +743,7 @@ "> +\n" "> +static int tegra_nand_remove(struct platform_device *pdev)\n" "> +{\n" - "> +\tstruct tegra_nand *nand =3D platform_get_drvdata(pdev);\n" + "> +\tstruct tegra_nand *nand = platform_get_drvdata(pdev);\n" "> +\n" "> +\tnand_release(nand_to_mtd(&nand->chip));\n" "> +\n" @@ -757,18 +752,18 @@ "> +\treturn 0;\n" "> +}\n" "> +\n" - "> +static const struct of_device_id tegra_nand_of_match[] =3D {\n" - "> +\t{ .compatible =3D \"nvidia,tegra20-nand\" },\n" + "> +static const struct of_device_id tegra_nand_of_match[] = {\n" + "> +\t{ .compatible = \"nvidia,tegra20-nand\" },\n" "> +\t{ /* sentinel */ }\n" "> +};\n" "> +\n" - "> +static struct platform_driver tegra_nand_driver =3D {\n" - "> +\t.driver =3D {\n" - "> +\t\t.name =3D \"tegra-nand\",\n" - "> +\t\t.of_match_table =3D tegra_nand_of_match,\n" + "> +static struct platform_driver tegra_nand_driver = {\n" + "> +\t.driver = {\n" + "> +\t\t.name = \"tegra-nand\",\n" + "> +\t\t.of_match_table = tegra_nand_of_match,\n" "> +\t},\n" - "> +\t.probe =3D tegra_nand_probe,\n" - "> +\t.remove =3D tegra_nand_remove,\n" + "> +\t.probe = tegra_nand_probe,\n" + "> +\t.remove = tegra_nand_remove,\n" "> +};\n" "> +module_platform_driver(tegra_nand_driver);\n" "> +\n" @@ -779,4 +774,4 @@ "> +MODULE_LICENSE(\"GPL v2\");\n" > +MODULE_DEVICE_TABLE(of, tegra_nand_of_match); -8490f6f7daf879f8dd297e1e32ca65217c30b00b8bb91384fa38a1cd87cf7cf7 +89445f18707fc42b672452ca45d5e1dbe482eea29e29fe6797971f249e76c507
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.