@@ -66,6 +66,115 @@ static int spinand_user_otp_check_bounds(struct spinand_device *spinand,
6666 & spinand -> user_otp -> layout );
6767}
6868
69+ static int spinand_otp_rw (struct spinand_device * spinand , loff_t ofs ,
70+ size_t len , size_t * retlen , u8 * buf , bool is_write ,
71+ const struct spinand_otp_layout * layout )
72+ {
73+ struct nand_page_io_req req = {};
74+ unsigned long long page ;
75+ size_t copied = 0 ;
76+ size_t otp_pagesize = spinand_otp_page_size (spinand );
77+ int ret ;
78+
79+ if (!len )
80+ return 0 ;
81+
82+ ret = spinand_otp_check_bounds (spinand , ofs , len , layout );
83+ if (ret )
84+ return ret ;
85+
86+ ret = spinand_upd_cfg (spinand , CFG_OTP_ENABLE , CFG_OTP_ENABLE );
87+ if (ret )
88+ return ret ;
89+
90+ page = ofs ;
91+ req .dataoffs = do_div (page , otp_pagesize );
92+ req .pos .page = page + layout -> start_page ;
93+ req .type = is_write ? NAND_PAGE_WRITE : NAND_PAGE_READ ;
94+ req .mode = MTD_OPS_RAW ;
95+ req .databuf .in = buf ;
96+
97+ while (copied < len ) {
98+ req .datalen = min_t (unsigned int ,
99+ otp_pagesize - req .dataoffs ,
100+ len - copied );
101+
102+ if (is_write )
103+ ret = spinand_write_page (spinand , & req );
104+ else
105+ ret = spinand_read_page (spinand , & req );
106+
107+ if (ret < 0 )
108+ break ;
109+
110+ req .databuf .in += req .datalen ;
111+ req .pos .page ++ ;
112+ req .dataoffs = 0 ;
113+ copied += req .datalen ;
114+ }
115+
116+ * retlen = copied ;
117+
118+ if (spinand_upd_cfg (spinand , CFG_OTP_ENABLE , 0 )) {
119+ dev_warn (& spinand_to_mtd (spinand )-> dev ,
120+ "Can not disable OTP mode\n" );
121+ ret = - EIO ;
122+ }
123+
124+ return ret ;
125+ }
126+
127+ /**
128+ * spinand_fact_otp_read() - Read from OTP area
129+ * @spinand: the spinand device
130+ * @ofs: the offset to read
131+ * @len: the number of data bytes to read
132+ * @retlen: the pointer to variable to store the number of read bytes
133+ * @buf: the buffer to store the read data
134+ *
135+ * Return: 0 on success, an error code otherwise.
136+ */
137+ int spinand_fact_otp_read (struct spinand_device * spinand , loff_t ofs ,
138+ size_t len , size_t * retlen , u8 * buf )
139+ {
140+ return spinand_otp_rw (spinand , ofs , len , retlen , buf , false,
141+ & spinand -> fact_otp -> layout );
142+ }
143+
144+ /**
145+ * spinand_user_otp_read() - Read from OTP area
146+ * @spinand: the spinand device
147+ * @ofs: the offset to read
148+ * @len: the number of data bytes to read
149+ * @retlen: the pointer to variable to store the number of read bytes
150+ * @buf: the buffer to store the read data
151+ *
152+ * Return: 0 on success, an error code otherwise.
153+ */
154+ int spinand_user_otp_read (struct spinand_device * spinand , loff_t ofs ,
155+ size_t len , size_t * retlen , u8 * buf )
156+ {
157+ return spinand_otp_rw (spinand , ofs , len , retlen , buf , false,
158+ & spinand -> user_otp -> layout );
159+ }
160+
161+ /**
162+ * spinand_user_otp_write() - Write to OTP area
163+ * @spinand: the spinand device
164+ * @ofs: the offset to write to
165+ * @len: the number of bytes to write
166+ * @retlen: the pointer to variable to store the number of written bytes
167+ * @buf: the buffer with data to write
168+ *
169+ * Return: 0 on success, an error code otherwise.
170+ */
171+ int spinand_user_otp_write (struct spinand_device * spinand , loff_t ofs ,
172+ size_t len , size_t * retlen , const u8 * buf )
173+ {
174+ return spinand_otp_rw (spinand , ofs , len , retlen , (u8 * )buf , true,
175+ & spinand -> user_otp -> layout );
176+ }
177+
69178static int spinand_mtd_otp_info (struct mtd_info * mtd , size_t len ,
70179 size_t * retlen , struct otp_info * buf ,
71180 bool is_fact )
0 commit comments