@@ -116,23 +116,145 @@ static int bcm47xxsflash_read(struct mtd_info *mtd, loff_t from, size_t len,
116116 return len ;
117117}
118118
119+ static int bcm47xxsflash_write_st (struct mtd_info * mtd , u32 offset , size_t len ,
120+ const u_char * buf )
121+ {
122+ struct bcm47xxsflash * b47s = mtd -> priv ;
123+ int written = 0 ;
124+
125+ /* Enable writes */
126+ bcm47xxsflash_cmd (b47s , OPCODE_ST_WREN );
127+
128+ /* Write first byte */
129+ b47s -> cc_write (b47s , BCMA_CC_FLASHADDR , offset );
130+ b47s -> cc_write (b47s , BCMA_CC_FLASHDATA , * buf ++ );
131+
132+ /* Program page */
133+ if (b47s -> bcma_cc -> core -> id .rev < 20 ) {
134+ bcm47xxsflash_cmd (b47s , OPCODE_ST_PP );
135+ return 1 ; /* 1B written */
136+ }
137+
138+ /* Program page and set CSA (on newer chips we can continue writing) */
139+ bcm47xxsflash_cmd (b47s , OPCODE_ST_CSA | OPCODE_ST_PP );
140+ offset ++ ;
141+ len -- ;
142+ written ++ ;
143+
144+ while (len > 0 ) {
145+ /* Page boundary, another function call is needed */
146+ if ((offset & 0xFF ) == 0 )
147+ break ;
148+
149+ bcm47xxsflash_cmd (b47s , OPCODE_ST_CSA | * buf ++ );
150+ offset ++ ;
151+ len -- ;
152+ written ++ ;
153+ }
154+
155+ /* All done, drop CSA & poll */
156+ b47s -> cc_write (b47s , BCMA_CC_FLASHCTL , 0 );
157+ udelay (1 );
158+ if (bcm47xxsflash_poll (b47s , HZ / 10 ))
159+ pr_err ("Flash rejected dropping CSA\n" );
160+
161+ return written ;
162+ }
163+
164+ static int bcm47xxsflash_write_at (struct mtd_info * mtd , u32 offset , size_t len ,
165+ const u_char * buf )
166+ {
167+ struct bcm47xxsflash * b47s = mtd -> priv ;
168+ u32 mask = b47s -> blocksize - 1 ;
169+ u32 page = (offset & ~mask ) << 1 ;
170+ u32 byte = offset & mask ;
171+ int written = 0 ;
172+
173+ /* If we don't overwrite whole page, read it to the buffer first */
174+ if (byte || (len < b47s -> blocksize )) {
175+ int err ;
176+
177+ b47s -> cc_write (b47s , BCMA_CC_FLASHADDR , page );
178+ bcm47xxsflash_cmd (b47s , OPCODE_AT_BUF1_LOAD );
179+ /* 250 us for AT45DB321B */
180+ err = bcm47xxsflash_poll (b47s , HZ / 1000 );
181+ if (err ) {
182+ pr_err ("Timeout reading page 0x%X info buffer\n" , page );
183+ return err ;
184+ }
185+ }
186+
187+ /* Change buffer content with our data */
188+ while (len > 0 ) {
189+ /* Page boundary, another function call is needed */
190+ if (byte == b47s -> blocksize )
191+ break ;
192+
193+ b47s -> cc_write (b47s , BCMA_CC_FLASHADDR , byte ++ );
194+ b47s -> cc_write (b47s , BCMA_CC_FLASHDATA , * buf ++ );
195+ bcm47xxsflash_cmd (b47s , OPCODE_AT_BUF1_WRITE );
196+ len -- ;
197+ written ++ ;
198+ }
199+
200+ /* Program page with the buffer content */
201+ b47s -> cc_write (b47s , BCMA_CC_FLASHADDR , page );
202+ bcm47xxsflash_cmd (b47s , OPCODE_AT_BUF1_PROGRAM );
203+
204+ return written ;
205+ }
206+
207+ static int bcm47xxsflash_write (struct mtd_info * mtd , loff_t to , size_t len ,
208+ size_t * retlen , const u_char * buf )
209+ {
210+ struct bcm47xxsflash * b47s = mtd -> priv ;
211+ int written ;
212+
213+ /* Writing functions can return without writing all passed data, for
214+ * example when the hardware is too old or when we git page boundary.
215+ */
216+ while (len > 0 ) {
217+ switch (b47s -> type ) {
218+ case BCM47XXSFLASH_TYPE_ST :
219+ written = bcm47xxsflash_write_st (mtd , to , len , buf );
220+ break ;
221+ case BCM47XXSFLASH_TYPE_ATMEL :
222+ written = bcm47xxsflash_write_at (mtd , to , len , buf );
223+ break ;
224+ default :
225+ BUG_ON (1 );
226+ }
227+ if (written < 0 ) {
228+ pr_err ("Error writing at offset 0x%llX\n" , to );
229+ return written ;
230+ }
231+ to += (loff_t )written ;
232+ len -= written ;
233+ * retlen += written ;
234+ buf += written ;
235+ }
236+
237+ return 0 ;
238+ }
239+
119240static void bcm47xxsflash_fill_mtd (struct bcm47xxsflash * b47s )
120241{
121242 struct mtd_info * mtd = & b47s -> mtd ;
122243
123244 mtd -> priv = b47s ;
124245 mtd -> name = "bcm47xxsflash" ;
125246 mtd -> owner = THIS_MODULE ;
126- mtd -> type = MTD_ROM ;
127247
128- /* TODO: implement writing support and verify/change following code */
129- mtd -> flags = MTD_CAP_ROM ;
248+ mtd -> type = MTD_NORFLASH ;
249+ mtd -> flags = MTD_CAP_NORFLASH ;
130250 mtd -> size = b47s -> size ;
131251 mtd -> erasesize = b47s -> blocksize ;
132- mtd -> writebufsize = mtd -> writesize = 1 ;
252+ mtd -> writesize = 1 ;
253+ mtd -> writebufsize = 1 ;
133254
134255 mtd -> _erase = bcm47xxsflash_erase ;
135256 mtd -> _read = bcm47xxsflash_read ;
257+ mtd -> _write = bcm47xxsflash_write ;
136258}
137259
138260/**************************************************
0 commit comments