66 * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
77 */
88
9+ #include <linux/slab.h>
910#include "linux/delay.h"
1011#include "internals.h"
1112
3132
3233#define MXIC_CMD_POWER_DOWN 0xB9
3334
35+ #define ONFI_FEATURE_ADDR_30LFXG18AC_OTP 0x90
36+ #define MACRONIX_30LFXG18AC_OTP_START_PAGE 2
37+ #define MACRONIX_30LFXG18AC_OTP_PAGES 30
38+ #define MACRONIX_30LFXG18AC_OTP_PAGE_SIZE 2112
39+ #define MACRONIX_30LFXG18AC_OTP_SIZE_BYTES \
40+ (MACRONIX_30LFXG18AC_OTP_PAGES * \
41+ MACRONIX_30LFXG18AC_OTP_PAGE_SIZE)
42+
43+ #define MACRONIX_30LFXG18AC_OTP_EN BIT(0)
44+
3445struct nand_onfi_vendor_macronix {
3546 u8 reserved ;
3647 u8 reliability_func ;
@@ -315,6 +326,161 @@ static void macronix_nand_deep_power_down_support(struct nand_chip *chip)
315326 chip -> ops .resume = mxic_nand_resume ;
316327}
317328
329+ static int macronix_30lfxg18ac_get_otp_info (struct mtd_info * mtd , size_t len ,
330+ size_t * retlen ,
331+ struct otp_info * buf )
332+ {
333+ 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+
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+
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+
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+
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+
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+
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+
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+
318484static int macronix_nand_init (struct nand_chip * chip )
319485{
320486 if (nand_is_slc (chip ))
@@ -324,6 +490,7 @@ static int macronix_nand_init(struct nand_chip *chip)
324490 macronix_nand_onfi_init (chip );
325491 macronix_nand_block_protection_support (chip );
326492 macronix_nand_deep_power_down_support (chip );
493+ macronix_nand_setup_otp (chip );
327494
328495 return 0 ;
329496}
0 commit comments