1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
293db446aSBoris Brezillon /*
393db446aSBoris Brezillon * Copyright (C) 2017 Free Electrons
493db446aSBoris Brezillon * Copyright (C) 2017 NextThing Co
593db446aSBoris Brezillon *
693db446aSBoris Brezillon * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
793db446aSBoris Brezillon */
893db446aSBoris Brezillon
919301d54SMason Yang #include <linux/slab.h>
10348d56a8SBoris Brezillon #include "linux/delay.h"
1193db446aSBoris Brezillon #include "internals.h"
1233535b85SMason Yang
1333535b85SMason Yang #define MACRONIX_READ_RETRY_BIT BIT(0)
1433535b85SMason Yang #define MACRONIX_NUM_READ_RETRY_MODES 6
1503a539c7SMason Yang
1603a539c7SMason Yang #define ONFI_FEATURE_ADDR_MXIC_PROTECTION 0xA0
1703a539c7SMason Yang #define MXIC_BLOCK_PROTECTION_ALL_LOCK 0x38
1803a539c7SMason Yang #define MXIC_BLOCK_PROTECTION_ALL_UNLOCK 0x0
1984234652SMason Yang
2084234652SMason Yang #define ONFI_FEATURE_ADDR_MXIC_RANDOMIZER 0xB0
2184234652SMason Yang #define MACRONIX_RANDOMIZER_BIT BIT(1)
2284234652SMason Yang #define MACRONIX_RANDOMIZER_ENPGM BIT(0)
2384234652SMason Yang #define MACRONIX_RANDOMIZER_RANDEN BIT(1)
2484234652SMason Yang #define MACRONIX_RANDOMIZER_RANDOPT BIT(2)
2584234652SMason Yang #define MACRONIX_RANDOMIZER_MODE_ENTER \
2684234652SMason Yang (MACRONIX_RANDOMIZER_ENPGM | \
2784234652SMason Yang MACRONIX_RANDOMIZER_RANDEN | \
2884234652SMason Yang MACRONIX_RANDOMIZER_RANDOPT)
2984234652SMason Yang #define MACRONIX_RANDOMIZER_MODE_EXIT \
3084234652SMason Yang (MACRONIX_RANDOMIZER_RANDEN | \
3184234652SMason Yang MACRONIX_RANDOMIZER_RANDOPT)
3219301d54SMason Yang
3319301d54SMason Yang #define MXIC_CMD_POWER_DOWN 0xB9
3433535b85SMason Yang
3533535b85SMason Yang #define ONFI_FEATURE_ADDR_30LFXG18AC_OTP 0x90
3633535b85SMason Yang #define MACRONIX_30LFXG18AC_OTP_START_PAGE 2
3733535b85SMason Yang #define MACRONIX_30LFXG18AC_OTP_PAGES 30
3833535b85SMason Yang #define MACRONIX_30LFXG18AC_OTP_PAGE_SIZE 2112
3933535b85SMason Yang #define MACRONIX_30LFXG18AC_OTP_SIZE_BYTES \
4033535b85SMason Yang (MACRONIX_30LFXG18AC_OTP_PAGES * \
4133535b85SMason Yang MACRONIX_30LFXG18AC_OTP_PAGE_SIZE)
4233535b85SMason Yang
4333535b85SMason Yang #define MACRONIX_30LFXG18AC_OTP_EN BIT(0)
4433535b85SMason Yang
4533535b85SMason Yang struct nand_onfi_vendor_macronix {
4633535b85SMason Yang u8 reserved;
4733535b85SMason Yang u8 reliability_func;
4833535b85SMason Yang } __packed;
4933535b85SMason Yang
macronix_nand_setup_read_retry(struct nand_chip * chip,int mode)5033535b85SMason Yang static int macronix_nand_setup_read_retry(struct nand_chip *chip, int mode)
5133535b85SMason Yang {
5284234652SMason Yang u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
5384234652SMason Yang
5484234652SMason Yang if (!chip->parameters.supports_set_get_features ||
5584234652SMason Yang !test_bit(ONFI_FEATURE_ADDR_READ_RETRY,
5684234652SMason Yang chip->parameters.set_feature_list))
5784234652SMason Yang return -ENOTSUPP;
5884234652SMason Yang
5984234652SMason Yang feature[0] = mode;
6084234652SMason Yang return nand_set_features(chip, ONFI_FEATURE_ADDR_READ_RETRY, feature);
6184234652SMason Yang }
6284234652SMason Yang
macronix_nand_randomizer_check_enable(struct nand_chip * chip)6384234652SMason Yang static int macronix_nand_randomizer_check_enable(struct nand_chip *chip)
6484234652SMason Yang {
6584234652SMason Yang u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
6684234652SMason Yang int ret;
6784234652SMason Yang
6884234652SMason Yang ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
6984234652SMason Yang feature);
7084234652SMason Yang if (ret < 0)
7184234652SMason Yang return ret;
7284234652SMason Yang
7384234652SMason Yang if (feature[0])
7484234652SMason Yang return feature[0];
7584234652SMason Yang
7684234652SMason Yang feature[0] = MACRONIX_RANDOMIZER_MODE_ENTER;
7784234652SMason Yang ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
7884234652SMason Yang feature);
7984234652SMason Yang if (ret < 0)
8084234652SMason Yang return ret;
8184234652SMason Yang
8284234652SMason Yang /* RANDEN and RANDOPT OTP bits are programmed */
8384234652SMason Yang feature[0] = 0x0;
8484234652SMason Yang ret = nand_prog_page_op(chip, 0, 0, feature, 1);
8584234652SMason Yang if (ret < 0)
8684234652SMason Yang return ret;
8784234652SMason Yang
8884234652SMason Yang ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
8984234652SMason Yang feature);
9084234652SMason Yang if (ret < 0)
9133535b85SMason Yang return ret;
9233535b85SMason Yang
9333535b85SMason Yang feature[0] &= MACRONIX_RANDOMIZER_MODE_EXIT;
9433535b85SMason Yang ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
9584234652SMason Yang feature);
96*57150c40SRob Herring if (ret < 0)
9784234652SMason Yang return ret;
9833535b85SMason Yang
9933535b85SMason Yang return 0;
10033535b85SMason Yang }
10133535b85SMason Yang
macronix_nand_onfi_init(struct nand_chip * chip)102*57150c40SRob Herring static void macronix_nand_onfi_init(struct nand_chip *chip)
10384234652SMason Yang {
10433535b85SMason Yang struct nand_parameters *p = &chip->parameters;
10584234652SMason Yang struct nand_onfi_vendor_macronix *mxic;
10684234652SMason Yang struct device_node *dn = nand_get_flash_node(chip);
10784234652SMason Yang int rand_otp;
10884234652SMason Yang int ret;
10984234652SMason Yang
11084234652SMason Yang if (!p->onfi)
11184234652SMason Yang return;
11284234652SMason Yang
11384234652SMason Yang rand_otp = of_property_read_bool(dn, "mxic,enable-randomizer-otp");
11484234652SMason Yang
11584234652SMason Yang mxic = (struct nand_onfi_vendor_macronix *)p->onfi->vendor;
11684234652SMason Yang /* Subpage write is prohibited in randomizer operatoin */
11784234652SMason Yang if (rand_otp && chip->options & NAND_NO_SUBPAGE_WRITE &&
11884234652SMason Yang mxic->reliability_func & MACRONIX_RANDOMIZER_BIT) {
11984234652SMason Yang if (p->supports_set_get_features) {
12084234652SMason Yang bitmap_set(p->set_feature_list,
12184234652SMason Yang ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
12284234652SMason Yang bitmap_set(p->get_feature_list,
12384234652SMason Yang ONFI_FEATURE_ADDR_MXIC_RANDOMIZER, 1);
12484234652SMason Yang ret = macronix_nand_randomizer_check_enable(chip);
12584234652SMason Yang if (ret < 0) {
12684234652SMason Yang bitmap_clear(p->set_feature_list,
12784234652SMason Yang ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
12833535b85SMason Yang 1);
12933535b85SMason Yang bitmap_clear(p->get_feature_list,
13033535b85SMason Yang ONFI_FEATURE_ADDR_MXIC_RANDOMIZER,
13133535b85SMason Yang 1);
1328e8b2706SMiquel Raynal pr_info("Macronix NAND randomizer failed\n");
13333535b85SMason Yang } else {
13433535b85SMason Yang pr_info("Macronix NAND randomizer enabled\n");
13533535b85SMason Yang }
13633535b85SMason Yang }
13733535b85SMason Yang }
13833535b85SMason Yang
13933535b85SMason Yang if ((mxic->reliability_func & MACRONIX_READ_RETRY_BIT) == 0)
14033535b85SMason Yang return;
14133535b85SMason Yang
14234c5c01eSMiquel Raynal chip->read_retries = MACRONIX_NUM_READ_RETRY_MODES;
143fe3dd97dSMason Yang chip->ops.setup_read_retry = macronix_nand_setup_read_retry;
14434c5c01eSMiquel Raynal
14534c5c01eSMiquel Raynal if (p->supports_set_get_features) {
14634c5c01eSMiquel Raynal bitmap_set(p->set_feature_list,
147fe3dd97dSMason Yang ONFI_FEATURE_ADDR_READ_RETRY, 1);
148fe3dd97dSMason Yang bitmap_set(p->get_feature_list,
149db7b6aecSYueHaibing ONFI_FEATURE_ADDR_READ_RETRY, 1);
150fe3dd97dSMason Yang }
151fe3dd97dSMason Yang }
152fe3dd97dSMason Yang
153fe3dd97dSMason Yang /*
154fe3dd97dSMason Yang * Macronix AC series does not support using SET/GET_FEATURES to change
155fe3dd97dSMason Yang * the timings unlike what is declared in the parameter page. Unflag
156fe3dd97dSMason Yang * this feature to avoid unnecessary downturns.
157fe3dd97dSMason Yang */
macronix_nand_fix_broken_get_timings(struct nand_chip * chip)158acc9d62bSMason Yang static void macronix_nand_fix_broken_get_timings(struct nand_chip *chip)
159acc9d62bSMason Yang {
160acc9d62bSMason Yang int i;
161acc9d62bSMason Yang static const char * const broken_get_timings[] = {
162acc9d62bSMason Yang "MX30LF1G18AC",
163acc9d62bSMason Yang "MX30LF1G28AC",
164acc9d62bSMason Yang "MX30LF2G18AC",
165fe3dd97dSMason Yang "MX30LF2G28AC",
166fe3dd97dSMason Yang "MX30LF4G18AC",
167fe3dd97dSMason Yang "MX30LF4G28AC",
168fe3dd97dSMason Yang "MX60LF8G18AC",
169fe3dd97dSMason Yang "MX30UF1G18AC",
170db7b6aecSYueHaibing "MX30UF1G16AC",
171db7b6aecSYueHaibing "MX30UF2G18AC",
172db7b6aecSYueHaibing "MX30UF2G16AC",
173fe3dd97dSMason Yang "MX30UF4G18AC",
174fe3dd97dSMason Yang "MX30UF4G16AC",
17534c5c01eSMiquel Raynal "MX30UF4G28AC",
17634c5c01eSMiquel Raynal };
17734c5c01eSMiquel Raynal
17834c5c01eSMiquel Raynal if (!chip->parameters.supports_set_get_features)
17934c5c01eSMiquel Raynal return;
18034c5c01eSMiquel Raynal
18103a539c7SMason Yang i = match_string(broken_get_timings, ARRAY_SIZE(broken_get_timings),
18203a539c7SMason Yang chip->parameters.model);
18303a539c7SMason Yang if (i < 0)
18403a539c7SMason Yang return;
18503a539c7SMason Yang
18603a539c7SMason Yang bitmap_clear(chip->parameters.get_feature_list,
18703a539c7SMason Yang ONFI_FEATURE_ADDR_TIMING_MODE, 1);
18803a539c7SMason Yang bitmap_clear(chip->parameters.set_feature_list,
18903a539c7SMason Yang ONFI_FEATURE_ADDR_TIMING_MODE, 1);
19003a539c7SMason Yang }
19103a539c7SMason Yang
19203a539c7SMason Yang /*
19303a539c7SMason Yang * Macronix NAND supports Block Protection by Protectoin(PT) pin;
19403a539c7SMason Yang * active high at power-on which protects the entire chip even the #WP is
19503a539c7SMason Yang * disabled. Lock/unlock protection area can be partition according to
19603a539c7SMason Yang * protection bits, i.e. upper 1/2 locked, upper 1/4 locked and so on.
19703a539c7SMason Yang */
mxic_nand_lock(struct nand_chip * chip,loff_t ofs,uint64_t len)19803a539c7SMason Yang static int mxic_nand_lock(struct nand_chip *chip, loff_t ofs, uint64_t len)
19903a539c7SMason Yang {
20003a539c7SMason Yang u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
20103a539c7SMason Yang int ret;
20203a539c7SMason Yang
20303a539c7SMason Yang feature[0] = MXIC_BLOCK_PROTECTION_ALL_LOCK;
20403a539c7SMason Yang nand_select_target(chip, 0);
20503a539c7SMason Yang ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
20603a539c7SMason Yang feature);
20703a539c7SMason Yang nand_deselect_target(chip);
20803a539c7SMason Yang if (ret)
20903a539c7SMason Yang pr_err("%s all blocks failed\n", __func__);
21003a539c7SMason Yang
21103a539c7SMason Yang return ret;
21203a539c7SMason Yang }
21303a539c7SMason Yang
mxic_nand_unlock(struct nand_chip * chip,loff_t ofs,uint64_t len)21403a539c7SMason Yang static int mxic_nand_unlock(struct nand_chip *chip, loff_t ofs, uint64_t len)
21503a539c7SMason Yang {
21603a539c7SMason Yang u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
21703a539c7SMason Yang int ret;
21803a539c7SMason Yang
21903a539c7SMason Yang feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
22003a539c7SMason Yang nand_select_target(chip, 0);
22103a539c7SMason Yang ret = nand_set_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
22203a539c7SMason Yang feature);
22303a539c7SMason Yang nand_deselect_target(chip);
22403a539c7SMason Yang if (ret)
22503a539c7SMason Yang pr_err("%s all blocks failed\n", __func__);
22603a539c7SMason Yang
22703a539c7SMason Yang return ret;
22803a539c7SMason Yang }
22903a539c7SMason Yang
macronix_nand_block_protection_support(struct nand_chip * chip)23003a539c7SMason Yang static void macronix_nand_block_protection_support(struct nand_chip *chip)
23103a539c7SMason Yang {
23203a539c7SMason Yang u8 feature[ONFI_SUBFEATURE_PARAM_LEN];
23303a539c7SMason Yang int ret;
23403a539c7SMason Yang
23503a539c7SMason Yang bitmap_set(chip->parameters.get_feature_list,
23603a539c7SMason Yang ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
23703a539c7SMason Yang
23803a539c7SMason Yang feature[0] = MXIC_BLOCK_PROTECTION_ALL_UNLOCK;
23903a539c7SMason Yang nand_select_target(chip, 0);
24003a539c7SMason Yang ret = nand_get_features(chip, ONFI_FEATURE_ADDR_MXIC_PROTECTION,
24103a539c7SMason Yang feature);
24203a539c7SMason Yang nand_deselect_target(chip);
24303a539c7SMason Yang if (ret || feature[0] != MXIC_BLOCK_PROTECTION_ALL_LOCK) {
2448e8b2706SMiquel Raynal if (ret)
2458e8b2706SMiquel Raynal pr_err("Block protection check failed\n");
24603a539c7SMason Yang
24703a539c7SMason Yang bitmap_clear(chip->parameters.get_feature_list,
24819301d54SMason Yang ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
24919301d54SMason Yang return;
25019301d54SMason Yang }
25119301d54SMason Yang
25219301d54SMason Yang bitmap_set(chip->parameters.set_feature_list,
25319301d54SMason Yang ONFI_FEATURE_ADDR_MXIC_PROTECTION, 1);
25419301d54SMason Yang
25519301d54SMason Yang chip->ops.lock_area = mxic_nand_lock;
25619301d54SMason Yang chip->ops.unlock_area = mxic_nand_unlock;
25719301d54SMason Yang }
25819301d54SMason Yang
nand_power_down_op(struct nand_chip * chip)25919301d54SMason Yang static int nand_power_down_op(struct nand_chip *chip)
26019301d54SMason Yang {
26119301d54SMason Yang int ret;
26219301d54SMason Yang
26319301d54SMason Yang if (nand_has_exec_op(chip)) {
26419301d54SMason Yang struct nand_op_instr instrs[] = {
26519301d54SMason Yang NAND_OP_CMD(MXIC_CMD_POWER_DOWN, 0),
26619301d54SMason Yang };
26719301d54SMason Yang
26819301d54SMason Yang struct nand_operation op = NAND_OPERATION(chip->cur_cs, instrs);
26919301d54SMason Yang
27019301d54SMason Yang ret = nand_exec_op(chip, &op);
27119301d54SMason Yang if (ret)
27219301d54SMason Yang return ret;
27319301d54SMason Yang
27419301d54SMason Yang } else {
27519301d54SMason Yang chip->legacy.cmdfunc(chip, MXIC_CMD_POWER_DOWN, -1, -1);
27619301d54SMason Yang }
27719301d54SMason Yang
27819301d54SMason Yang return 0;
27919301d54SMason Yang }
28019301d54SMason Yang
mxic_nand_suspend(struct nand_chip * chip)28119301d54SMason Yang static int mxic_nand_suspend(struct nand_chip *chip)
28219301d54SMason Yang {
28319301d54SMason Yang int ret;
28419301d54SMason Yang
28519301d54SMason Yang nand_select_target(chip, 0);
28619301d54SMason Yang ret = nand_power_down_op(chip);
28719301d54SMason Yang if (ret < 0)
28819301d54SMason Yang pr_err("Suspending MXIC NAND chip failed (%d)\n", ret);
28919301d54SMason Yang nand_deselect_target(chip);
29019301d54SMason Yang
29119301d54SMason Yang return ret;
29219301d54SMason Yang }
29319301d54SMason Yang
mxic_nand_resume(struct nand_chip * chip)29419301d54SMason Yang static void mxic_nand_resume(struct nand_chip *chip)
29519301d54SMason Yang {
29619301d54SMason Yang /*
29719301d54SMason Yang * Toggle #CS pin to resume NAND device and don't care
29819301d54SMason Yang * of the others CLE, #WE, #RE pins status.
29919301d54SMason Yang * A NAND controller ensure it is able to assert/de-assert #CS
30019301d54SMason Yang * by sending any byte over the NAND bus.
30119301d54SMason Yang * i.e.,
30219301d54SMason Yang * NAND power down command or reset command w/o R/B# status checking.
30319301d54SMason Yang */
30419301d54SMason Yang nand_select_target(chip, 0);
30519301d54SMason Yang nand_power_down_op(chip);
30619301d54SMason Yang /* The minimum of a recovery time tRDP is 35 us */
30719301d54SMason Yang usleep_range(35, 100);
30819301d54SMason Yang nand_deselect_target(chip);
30919301d54SMason Yang }
31019301d54SMason Yang
macronix_nand_deep_power_down_support(struct nand_chip * chip)31119301d54SMason Yang static void macronix_nand_deep_power_down_support(struct nand_chip *chip)
31219301d54SMason Yang {
31319301d54SMason Yang int i;
3148e8b2706SMiquel Raynal static const char * const deep_power_down_dev[] = {
3158e8b2706SMiquel Raynal "MX30UF1G28AD",
31619301d54SMason Yang "MX30UF2G28AD",
31719301d54SMason Yang "MX30UF4G28AD",
318fe3dd97dSMason Yang };
319fe3dd97dSMason Yang
320fe3dd97dSMason Yang i = match_string(deep_power_down_dev, ARRAY_SIZE(deep_power_down_dev),
321bb592548SFrieder Schrempf chip->parameters.model);
322fe3dd97dSMason Yang if (i < 0)
323fe3dd97dSMason Yang return;
32433535b85SMason Yang
32503a539c7SMason Yang chip->ops.suspend = mxic_nand_suspend;
32619301d54SMason Yang chip->ops.resume = mxic_nand_resume;
327fe3dd97dSMason Yang }
32893db446aSBoris Brezillon
macronix_30lfxg18ac_get_otp_info(struct mtd_info * mtd,size_t len,size_t * retlen,struct otp_info * buf)32993db446aSBoris Brezillon static int macronix_30lfxg18ac_get_otp_info(struct mtd_info *mtd, size_t len,
33093db446aSBoris Brezillon size_t *retlen,
33193db446aSBoris Brezillon struct otp_info *buf)
33293db446aSBoris Brezillon {
33393db446aSBoris Brezillon if (len < sizeof(*buf))
334 return -EINVAL;
335
336 /* Always report that OTP is unlocked. Reason is that this
337 * type of flash chip doesn't provide way to check that OTP
338 * is locked or not: subfeature parameter is implemented as
339 * volatile register. Technically OTP region could be locked
340 * and become readonly, but as there is no way to check it,
341 * don't allow to lock it ('_lock_user_prot_reg' callback
342 * always returns -EOPNOTSUPP) and thus we report that OTP
343 * is unlocked.
344 */
345 buf->locked = 0;
346 buf->start = 0;
347 buf->length = MACRONIX_30LFXG18AC_OTP_SIZE_BYTES;
348
349 *retlen = sizeof(*buf);
350
351 return 0;
352 }
353
macronix_30lfxg18ac_otp_enable(struct nand_chip * nand)354 static int macronix_30lfxg18ac_otp_enable(struct nand_chip *nand)
355 {
356 u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 };
357
358 feature_buf[0] = MACRONIX_30LFXG18AC_OTP_EN;
359 return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP,
360 feature_buf);
361 }
362
macronix_30lfxg18ac_otp_disable(struct nand_chip * nand)363 static int macronix_30lfxg18ac_otp_disable(struct nand_chip *nand)
364 {
365 u8 feature_buf[ONFI_SUBFEATURE_PARAM_LEN] = { 0 };
366
367 return nand_set_features(nand, ONFI_FEATURE_ADDR_30LFXG18AC_OTP,
368 feature_buf);
369 }
370
__macronix_30lfxg18ac_rw_otp(struct mtd_info * mtd,loff_t offs_in_flash,size_t len,size_t * retlen,u_char * buf,bool write)371 static int __macronix_30lfxg18ac_rw_otp(struct mtd_info *mtd,
372 loff_t offs_in_flash,
373 size_t len, size_t *retlen,
374 u_char *buf, bool write)
375 {
376 struct nand_chip *nand;
377 size_t bytes_handled;
378 off_t offs_in_page;
379 u64 page;
380 int ret;
381
382 nand = mtd_to_nand(mtd);
383 nand_select_target(nand, 0);
384
385 ret = macronix_30lfxg18ac_otp_enable(nand);
386 if (ret)
387 goto out_otp;
388
389 page = offs_in_flash;
390 /* 'page' will be result of division. */
391 offs_in_page = do_div(page, MACRONIX_30LFXG18AC_OTP_PAGE_SIZE);
392 bytes_handled = 0;
393
394 while (bytes_handled < len &&
395 page < MACRONIX_30LFXG18AC_OTP_PAGES) {
396 size_t bytes_to_handle;
397 u64 phys_page = page + MACRONIX_30LFXG18AC_OTP_START_PAGE;
398
399 bytes_to_handle = min_t(size_t, len - bytes_handled,
400 MACRONIX_30LFXG18AC_OTP_PAGE_SIZE -
401 offs_in_page);
402
403 if (write)
404 ret = nand_prog_page_op(nand, phys_page, offs_in_page,
405 &buf[bytes_handled], bytes_to_handle);
406 else
407 ret = nand_read_page_op(nand, phys_page, offs_in_page,
408 &buf[bytes_handled], bytes_to_handle);
409 if (ret)
410 goto out_otp;
411
412 bytes_handled += bytes_to_handle;
413 offs_in_page = 0;
414 page++;
415 }
416
417 *retlen = bytes_handled;
418
419 out_otp:
420 if (ret)
421 dev_err(&mtd->dev, "failed to perform OTP IO: %i\n", ret);
422
423 ret = macronix_30lfxg18ac_otp_disable(nand);
424 if (ret)
425 dev_err(&mtd->dev, "failed to leave OTP mode after %s\n",
426 write ? "write" : "read");
427
428 nand_deselect_target(nand);
429
430 return ret;
431 }
432
macronix_30lfxg18ac_write_otp(struct mtd_info * mtd,loff_t to,size_t len,size_t * rlen,const u_char * buf)433 static int macronix_30lfxg18ac_write_otp(struct mtd_info *mtd, loff_t to,
434 size_t len, size_t *rlen,
435 const u_char *buf)
436 {
437 return __macronix_30lfxg18ac_rw_otp(mtd, to, len, rlen, (u_char *)buf,
438 true);
439 }
440
macronix_30lfxg18ac_read_otp(struct mtd_info * mtd,loff_t from,size_t len,size_t * rlen,u_char * buf)441 static int macronix_30lfxg18ac_read_otp(struct mtd_info *mtd, loff_t from,
442 size_t len, size_t *rlen,
443 u_char *buf)
444 {
445 return __macronix_30lfxg18ac_rw_otp(mtd, from, len, rlen, buf, false);
446 }
447
macronix_30lfxg18ac_lock_otp(struct mtd_info * mtd,loff_t from,size_t len)448 static int macronix_30lfxg18ac_lock_otp(struct mtd_info *mtd, loff_t from,
449 size_t len)
450 {
451 /* See comment in 'macronix_30lfxg18ac_get_otp_info()'. */
452 return -EOPNOTSUPP;
453 }
454
macronix_nand_setup_otp(struct nand_chip * chip)455 static void macronix_nand_setup_otp(struct nand_chip *chip)
456 {
457 static const char * const supported_otp_models[] = {
458 "MX30LF1G18AC",
459 "MX30LF2G18AC",
460 "MX30LF4G18AC",
461 };
462 struct mtd_info *mtd;
463
464 if (match_string(supported_otp_models,
465 ARRAY_SIZE(supported_otp_models),
466 chip->parameters.model) < 0)
467 return;
468
469 if (!chip->parameters.supports_set_get_features)
470 return;
471
472 bitmap_set(chip->parameters.get_feature_list,
473 ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1);
474 bitmap_set(chip->parameters.set_feature_list,
475 ONFI_FEATURE_ADDR_30LFXG18AC_OTP, 1);
476
477 mtd = nand_to_mtd(chip);
478 mtd->_get_user_prot_info = macronix_30lfxg18ac_get_otp_info;
479 mtd->_read_user_prot_reg = macronix_30lfxg18ac_read_otp;
480 mtd->_write_user_prot_reg = macronix_30lfxg18ac_write_otp;
481 mtd->_lock_user_prot_reg = macronix_30lfxg18ac_lock_otp;
482 }
483
macronix_nand_init(struct nand_chip * chip)484 static int macronix_nand_init(struct nand_chip *chip)
485 {
486 if (nand_is_slc(chip))
487 chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
488
489 macronix_nand_fix_broken_get_timings(chip);
490 macronix_nand_onfi_init(chip);
491 macronix_nand_block_protection_support(chip);
492 macronix_nand_deep_power_down_support(chip);
493 macronix_nand_setup_otp(chip);
494
495 return 0;
496 }
497
498 const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
499 .init = macronix_nand_init,
500 };
501