PageRenderTime 33ms CodeModel.GetById 15ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/block/sun3i_nand/src/physic/nand_simple_r.c

https://bitbucket.org/ndreys/linux-sunxi
C | 695 lines | 432 code | 117 blank | 146 comment | 77 complexity | 6a80b1bfad05ca458a59a1f196e6f46e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * drivers/block/sun3i_nand/src/physic/nand_simple_r.c
  3 *
  4 * (C) Copyright 2007-2012
  5 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  6 *
  7 * This program is free software; you can redistribute it and/or
  8 * modify it under the terms of the GNU General Public License as
  9 * published by the Free Software Foundation; either version 2 of
 10 * the License, or (at your option) any later version.
 11 *
 12 * This program is distributed in the hope that it will be useful,
 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 15 * GNU General Public License for more details.
 16 *
 17 * You should have received a copy of the GNU General Public License
 18 * along with this program; if not, write to the Free Software
 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 20 * MA 02111-1307 USA
 21 */
 22
 23#include "../include/nand_type.h"
 24#include "../include/nand_physic.h"
 25#include "../include/nand_simple.h"
 26#include "../../nfc/nfc.h"
 27
 28#include <linux/io.h>
 29
 30struct __NandStorageInfo_t  NandStorageInfo;
 31struct __NandPageCachePool_t PageCachePool;
 32void __iomem *nand_base;
 33
 34/**************************************************************************
 35************************* add one cmd to cmd list******************************
 36****************************************************************************/
 37void _add_cmd_list(NFC_CMD_LIST *cmd,__u32 value,__u32 addr_cycle,__u8 *addr,__u8 data_fetch_flag,
 38					__u8 main_data_fetch,__u32 bytecnt,__u8 wait_rb_flag)
 39{
 40	cmd->addr = addr;
 41	cmd->addr_cycle = addr_cycle;
 42	cmd->data_fetch_flag = data_fetch_flag;
 43	cmd->main_data_fetch = main_data_fetch;
 44	cmd->bytecnt = bytecnt;
 45	cmd->value = value;
 46	cmd->wait_rb_flag = wait_rb_flag;
 47	cmd->next = NULL;
 48}
 49
 50/****************************************************************************
 51*********************translate (block + page+ sector) into 5 bytes addr***************
 52*****************************************************************************/
 53void _cal_addr_in_chip(__u32 block, __u32 page, __u32 sector,__u8 *addr, __u8 cycle)
 54{
 55	__u32 row;
 56	__u32 column;
 57
 58	column = 512 * sector;
 59	row = block * PAGE_CNT_OF_PHY_BLK + page;
 60
 61	switch(cycle){
 62		case 1:
 63			addr[0] = 0x00;
 64			break;
 65		case 2:
 66			addr[0] = column & 0xff;
 67			addr[1] = (column >> 8) & 0xff;
 68			break;
 69		case 3:
 70			addr[0] = row & 0xff;
 71			addr[1] = (row >> 8) & 0xff;
 72			addr[2] = (row >> 16) & 0xff;
 73			break;
 74		case 4:
 75			addr[0] = column && 0xff;
 76			addr[1] = (column >> 8) & 0xff;
 77			addr[2] = row & 0xff;
 78			addr[3] = (row >> 8) & 0xff;
 79			break;
 80		case 5:
 81			addr[0] = column & 0xff;
 82			addr[1] = (column >> 8) & 0xff;
 83			addr[2] = row & 0xff;
 84			addr[3] = (row >> 8) & 0xff;
 85			addr[4] = (row >> 16) & 0xff;
 86			break;
 87		default:
 88			break;
 89	}
 90
 91}
 92
 93
 94
 95#if 0
 96__u8 _cal_real_chip(__u32 global_bank)
 97{
 98	__u8 chip;
 99	__u8 i,cnt;
100
101	cnt = 0;
102	chip = global_bank / BNK_CNT_OF_CHIP;
103
104	for (i = 0; i <MAX_CHIP_SELECT_CNT; i++ ){
105		if (CHIP_CONNECT_INFO & (1 << i)) {
106			cnt++;
107			if (cnt == (chip+1)){
108				chip = i;
109				return chip;
110			}
111		}
112	}
113
114	PHY_ERR("wrong chip number ,chip = %d, chip info = %x\n",chip,CHIP_CONNECT_INFO);
115
116	return 0xff;
117}
118#endif
119
120__u8 _cal_real_chip(__u32 global_bank)
121{
122	__u8 chip = 0;
123
124	if((RB_CONNECT_MODE == 0)&&(global_bank<=2))
125	{
126	    if(global_bank)
127		chip = 7;
128	    else
129		chip = 0;
130
131	    return chip;
132	}
133	if((RB_CONNECT_MODE == 1)&&(global_bank<=1))
134      	{
135      	    chip = global_bank;
136	    return chip;
137      	}
138	if((RB_CONNECT_MODE == 2)&&(global_bank<=2))
139      	{
140      	    chip = global_bank;
141	    return chip;
142      	}
143	if((RB_CONNECT_MODE == 3)&&(global_bank<=2))
144      	{
145      	    chip = global_bank*2;
146	    return chip;
147      	}
148	if((RB_CONNECT_MODE == 4)&&(global_bank<=4))
149      	{
150      	    switch(global_bank){
151		  case 0:
152		  	chip = 0;
153			break;
154		  case 1:
155		  	chip = 2;
156			break;
157		  case 2:
158		  	chip = 1;
159			break;
160		  case 3:
161		  	chip = 3;
162			break;
163		  default :
164		  	chip =0;
165	    }
166
167	    return chip;
168      	}
169	if((RB_CONNECT_MODE == 5)&&(global_bank<=4))
170      	{
171      	    chip = global_bank*2;
172
173	    return chip;
174      	}
175	if((RB_CONNECT_MODE == 8)&&(global_bank<=8))
176      	{
177      	    switch(global_bank){
178		  case 0:
179		  	chip = 0;
180			break;
181		  case 1:
182		  	chip = 2;
183			break;
184		  case 2:
185		  	chip = 1;
186			break;
187		  case 3:
188		  	chip = 3;
189			break;
190		  case 4:
191		  	chip = 4;
192			break;
193		  case 5:
194		  	chip = 6;
195			break;
196		  case 6:
197		  	chip = 5;
198			break;
199		  case 7:
200		  	chip = 7;
201			break;
202		  default : chip =0;
203
204	    }
205
206	    return chip;
207      	}
208
209	//dump_stack();
210	PHY_ERR("wrong chip number ,rb_mode = %d, bank = %d, chip = %d, chip info = %x\n",RB_CONNECT_MODE, global_bank, chip, CHIP_CONNECT_INFO);
211
212	return 0xff;
213}
214
215__u8 _cal_real_rb(__u32 chip)
216{
217	__u8 rb;
218
219
220	rb = 0;
221
222	if(RB_CONNECT_MODE == 0)
223      	{
224      	    rb = 0;
225      	}
226      if(RB_CONNECT_MODE == 1)
227      	{
228      	    rb = chip;
229      	}
230	if(RB_CONNECT_MODE == 2)
231      	{
232      	    rb = chip;
233      	}
234	if(RB_CONNECT_MODE == 3)
235      	{
236      	    rb = chip/2;
237      	}
238	if(RB_CONNECT_MODE == 4)
239      	{
240      	    rb = chip/2;
241      	}
242	if(RB_CONNECT_MODE == 5)
243      	{
244      	    rb = (chip/2)%2;
245      	}
246	if(RB_CONNECT_MODE == 8)
247      	{
248      	    rb = (chip/2)%2;
249      	}
250
251	if((rb!=0)&&(rb!=1))
252	{
253	    PHY_ERR("wrong Rb connect Mode  ,chip = %d, RbConnectMode = %d \n",chip,RB_CONNECT_MODE);
254	    return 0xff;
255	}
256
257	return rb;
258}
259
260/*******************************************************************
261**********************get status**************************************
262********************************************************************/
263__s32 _read_status(__u32 cmd_value, __u32 nBank)
264{
265	/*get status*/
266	__u8 addr[5];
267	__u32 addr_cycle;
268	NFC_CMD_LIST cmd_list;
269
270	addr_cycle = 0;
271
272	if(!(cmd_value == 0x70 || cmd_value == 0x71))
273	{
274        	/* not 0x70 or 0x71, need send some address cycle */
275       	 if(cmd_value == 0x78)
276	 		addr_cycle = 3;
277       	 else
278       		addr_cycle = 1;
279      		 _cal_addr_in_chip(nBank*BLOCK_CNT_OF_DIE,0,0,addr,addr_cycle);
280	}
281	_add_cmd_list(&cmd_list, cmd_value, addr_cycle, addr, 1,NFC_IGNORE,1,NFC_IGNORE);
282	return (NFC_GetStatus(&cmd_list));
283
284}
285
286/********************************************************************
287***************************wait rb ready*******************************
288*********************************************************************/
289__s32 _wait_rb_ready(__u32 chip)
290{
291	__s32 timeout = 0xffff;
292	__u32 rb;
293
294
295      rb = _cal_real_rb(chip);
296
297
298	/*wait rb ready*/
299	while((timeout--) && (NFC_CheckRbReady(rb)));
300	if (timeout < 0)
301		return -ERR_TIMEOUT;
302
303	return 0;
304}
305
306void _pending_dma_irq_sem(void)
307{
308	return;
309}
310
311__s32 _read_single_page(struct boot_physical_param *readop,__u8 dma_wait_mode)
312{
313	__s32 ret;
314	__u32 rb;
315
316	//__u8 *sparebuf;
317	__u8 sparebuf[4*16];
318	__u8 addr[5];
319	NFC_CMD_LIST cmd_list[4];
320	__u32 list_len,i;
321
322	//sparebuf = (__u8 *)MALLOC(SECTOR_CNT_OF_SINGLE_PAGE * 4);
323	/*create cmd list*/
324	/*samll block*/
325	if (SECTOR_CNT_OF_SINGLE_PAGE == 1){
326		_cal_addr_in_chip(readop->block,readop->page,0,addr,4);
327		_add_cmd_list(cmd_list,0x00,4,addr,NFC_DATA_FETCH,NFC_IGNORE,NFC_IGNORE,NFC_WAIT_RB);
328	}
329	/*large block*/
330	else{
331		/*the cammand have no corresponding feature if IGNORE was set, */
332		_cal_addr_in_chip(readop->block,readop->page,0,addr,5);
333		_add_cmd_list(cmd_list,0x00,5,addr,NFC_NO_DATA_FETCH,NFC_IGNORE,NFC_IGNORE,NFC_NO_WAIT_RB);
334
335	}
336	_add_cmd_list(cmd_list + 1,0x05,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE);
337	_add_cmd_list(cmd_list + 2,0xe0,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE);
338	_add_cmd_list(cmd_list + 3,0x30,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE,NFC_IGNORE);
339	list_len = 4;
340	for(i = 0; i < list_len - 1; i++){
341		cmd_list[i].next = &(cmd_list[i+1]);
342	}
343
344	/*wait rb ready*/
345	ret = _wait_rb_ready(readop->chip);
346	if (ret)
347		return ret;
348
349	rb = _cal_real_rb(readop->chip);
350	NFC_SelectChip(readop->chip);
351	NFC_SelectRb(rb);
352
353
354	ret = NFC_Read(cmd_list, readop->mainbuf, sparebuf, dma_wait_mode , NFC_PAGE_MODE);
355	if (dma_wait_mode)
356		_pending_dma_irq_sem();
357
358	if (readop->oobbuf){
359		MEMCPY(readop->oobbuf,sparebuf, 2 * 4);
360	}
361
362	NFC_DeSelectChip(readop->chip);
363	NFC_DeSelectRb(rb);
364
365	//FREE(sparebuf);
366	return ret;
367}
368
369
370
371/*
372************************************************************************************************************************
373*                       INIT NAND FLASH DRIVER PHYSICAL MODULE
374*
375* Description: init nand flash driver physical module.
376*
377* Aguments   : none
378*
379* Returns    : the resutl of initial.
380*                   = 0     initial successful;
381*                   = -1    initial failed.
382************************************************************************************************************************
383*/
384__s32 PHY_Init(void)
385{
386	NFC_INIT_INFO nand_info;
387	nand_info.bus_width = 0x0;
388	nand_info.ce_ctl = 0x0;
389	nand_info.ce_ctl1 = 0x0;
390	nand_info.debug = 0x0;
391	nand_info.pagesize = 4;
392	nand_info.rb_sel = 1;
393	nand_info.serial_access_mode = 1;
394
395	//nand_base = ioremap(0x01C03000, 4096 );
396	//modify by penggang for f20 linux
397
398//	if (nand_base == NULL) {
399//		printk(KERN_ERR "dma failed to remap register block\n");
400//		return -ENOMEM;
401//	}
402
403	return (NFC_Init(&nand_info));
404}
405
406__s32 PHY_ChangeMode(__u8 serial_mode)
407{
408
409	NFC_INIT_INFO nand_info;
410
411	/*memory allocate*/
412	if (!PageCachePool.PageCache0){
413		PageCachePool.PageCache0 = (__u8 *)MALLOC(SECTOR_CNT_OF_SUPER_PAGE * 512);
414		if (!PageCachePool.PageCache0)
415			return -1;
416	}
417
418	if (!PageCachePool.SpareCache){
419		PageCachePool.SpareCache = (__u8 *)MALLOC(SECTOR_CNT_OF_SUPER_PAGE * 4);
420		if (!PageCachePool.SpareCache)
421			return -1;
422	}
423
424	if (!PageCachePool.TmpPageCache){
425		PageCachePool.TmpPageCache = (__u8 *)MALLOC(SECTOR_CNT_OF_SUPER_PAGE * 512);
426		if (!PageCachePool.TmpPageCache)
427			return -1;
428	}
429
430      NFC_SetEccMode(ECC_MODE);
431
432
433	nand_info.bus_width = 0x0;
434	nand_info.ce_ctl = 0x0;
435	nand_info.ce_ctl1 = 0x0;
436	nand_info.debug = 0x0;
437	nand_info.pagesize = SECTOR_CNT_OF_SINGLE_PAGE;
438
439
440	nand_info.serial_access_mode = serial_mode;
441	return (NFC_ChangMode(&nand_info));
442}
443
444
445/*
446************************************************************************************************************************
447*                       NAND FLASH DRIVER PHYSICAL MODULE EXIT
448*
449* Description: nand flash driver physical module exit.
450*
451* Aguments   : none
452*
453* Returns    : the resutl of exit.
454*                   = 0     exit successful;
455*                   = -1    exit failed.
456************************************************************************************************************************
457*/
458__s32 PHY_Exit(void)
459{
460
461	if (PageCachePool.PageCache0){
462		FREE(PageCachePool.PageCache0,SECTOR_CNT_OF_SUPER_PAGE * 512);
463		PageCachePool.PageCache0 = NULL;
464	}
465	if (PageCachePool.SpareCache){
466		FREE(PageCachePool.SpareCache,SECTOR_CNT_OF_SUPER_PAGE * 4);
467		PageCachePool.SpareCache = NULL;
468	}
469	if (PageCachePool.TmpPageCache){
470		FREE(PageCachePool.TmpPageCache,SECTOR_CNT_OF_SUPER_PAGE * 512);
471		PageCachePool.TmpPageCache = NULL;
472	}
473
474	NFC_Exit();
475	return 0;
476}
477
478
479/*
480************************************************************************************************************************
481*                       RESET ONE NAND FLASH CHIP
482*
483*Description: Reset the given nand chip;
484*
485*Arguments  : nChip     the chip select number, which need be reset.
486*
487*Return     : the result of chip reset;
488*               = 0     reset nand chip successful;
489*               = -1    reset nand chip failed.
490************************************************************************************************************************
491*/
492__s32  PHY_ResetChip(__u32 nChip)
493{
494	__s32 ret;
495	__s32 timeout = 0xffff;
496
497
498	NFC_CMD_LIST cmd;
499
500	NFC_SelectChip(nChip);
501
502	_add_cmd_list(&cmd, 0xff, 0 , NFC_IGNORE, NFC_NO_DATA_FETCH, NFC_IGNORE, NFC_IGNORE, NFC_NO_WAIT_RB);
503	ret = NFC_ResetChip(&cmd);
504
505      	/*wait rb0 ready*/
506	NFC_SelectRb(0);
507	while((timeout--) && (NFC_CheckRbReady(0)));
508	if (timeout < 0)
509		return -ERR_TIMEOUT;
510
511      /*wait rb0 ready*/
512	NFC_SelectRb(1);
513	while((timeout--) && (NFC_CheckRbReady(1)));
514	if (timeout < 0)
515		return -ERR_TIMEOUT;
516
517	NFC_DeSelectChip(nChip);
518
519
520
521	return ret;
522}
523
524
525/*
526************************************************************************************************************************
527*                       READ NAND FLASH ID
528*
529*Description: Read nand flash ID from the given nand chip.
530*
531*Arguments  : nChip         the chip number whoes ID need be read;
532*             pChipID       the po__s32er to the chip ID buffer.
533*
534*Return     : read nand chip ID result;
535*               = 0     read chip ID successful, the chip ID has been stored in given buffer;
536*               = -1    read chip ID failed.
537************************************************************************************************************************
538*/
539
540__s32  PHY_ReadNandId(__s32 nChip, void *pChipID)
541{
542	__s32 ret;
543
544
545	NFC_CMD_LIST cmd;
546	__u8 addr = 0;
547
548	NFC_SelectChip(nChip);
549
550	_add_cmd_list(&cmd, 0x90,1 , &addr, NFC_DATA_FETCH, NFC_IGNORE, 5, NFC_NO_WAIT_RB);
551	ret = NFC_GetId(&cmd, pChipID);
552
553	NFC_DeSelectChip(nChip);
554
555
556	return ret;
557}
558
559/*
560************************************************************************************************************************
561*                       CHECK WRITE PROTECT STATUS
562*
563*Description: check the status of write protect.
564*
565*Arguments  : nChip     the number of chip, which nand chip need be checked.
566*
567*Return     : the result of status check;
568*             = 0       the nand flash is not write proteced;
569*             = 1       the nand flash is write proteced;
570*             = -1      check status failed.
571************************************************************************************************************************
572*/
573__s32  PHY_CheckWp(__u32 nChip)
574{
575	__s32 status;
576	__u32 rb;
577
578
579	rb = _cal_real_rb(nChip);
580	NFC_SelectChip(nChip);
581	NFC_SelectRb(rb);
582
583
584	status = _read_status(0x70,nChip);
585	NFC_DeSelectChip(nChip);
586	NFC_DeSelectRb(rb);
587
588	if (status < 0)
589		return status;
590
591	if (status & NAND_WRITE_PROTECT){
592		return 1;
593	}
594	else
595		return 0;
596}
597
598void _pending_rb_irq_sem(void)
599{
600	return;
601}
602
603void _do_irq(void)
604{
605
606}
607
608
609__s32 PHY_SimpleRead (struct boot_physical_param *readop)
610{
611	//if (_read_single_page(readop,0) < 0)
612	//	return FAIL;
613	//return SUCESS;
614	return (_read_single_page(readop,0));
615}
616
617/*
618************************************************************************************************************************
619*                       SYNC NAND FLASH PHYSIC OPERATION
620*
621*Description: Sync nand flash operation, check nand flash program/erase operation status.
622*
623*Arguments  : nBank     the number of the bank which need be synchronized;
624*             bMode     the type of synch,
625*                       = 0     sync the chip which the bank belonged to, wait the whole chip
626*                               to be ready, and report status. if the chip support cacheprogram,
627*                               need check if the chip is true ready;
628*                       = 1     only sync the the bank, wait the bank ready and report the status,
629*                               if the chip support cache program, need not check if the cache is
630*                               true ready.
631*
632*Return     : the result of synch;
633*               = 0     synch nand flash successful, nand operation ok;
634*               = -1    synch nand flash failed.
635************************************************************************************************************************
636*/
637__s32 PHY_SynchBank(__u32 nBank, __u32 bMode)
638{
639	__s32 ret,status;
640	__u32 chip;
641	__u32 rb;
642	__u32 cmd_value;
643	__s32 timeout = 0xffff;
644
645	ret = 0;
646	/*get chip no*/
647	chip = _cal_real_chip(nBank);
648	rb = _cal_real_rb(chip);
649
650	if (0xff == chip){
651		PHY_ERR("PHY_SynchBank : beyond chip count\n");
652		return -ERR_INVALIDPHYADDR;
653	}
654
655	if ( (bMode == 1) && SUPPORT_INT_INTERLEAVE){
656		if (nBank%BNK_CNT_OF_CHIP == 0)
657			cmd_value = NandStorageInfo.OptPhyOpPar.InterBnk0StatusCmd;
658		else
659			cmd_value = NandStorageInfo.OptPhyOpPar.InterBnk1StatusCmd;
660	}
661	else{
662		if (SUPPORT_MULTI_PROGRAM)
663			cmd_value = NandStorageInfo.OptPhyOpPar.MultiPlaneStatusCmd;
664		else
665			cmd_value = 0x70;
666	}
667
668	/*if support rb irq , last op is erase or write*/
669	if (SUPPORT_RB_IRQ)
670		_pending_rb_irq_sem();
671
672	NFC_SelectChip(chip);
673	NFC_SelectRb(rb);
674
675	while(1){
676		status = _read_status(cmd_value,nBank%BNK_CNT_OF_CHIP);
677		if (status < 0)
678			return status;
679
680		if (status & NAND_STATUS_READY)
681			break;
682
683		if (timeout-- < 0){
684			PHY_ERR("PHY_SynchBank : wait nand ready timeout,chip = %x, bank = %x, cmd value = %x, status = %x\n",chip,nBank,cmd_value,status);
685			return -ERR_TIMEOUT;
686		}
687	}
688	 if(status & NAND_OPERATE_FAIL)
689	 	ret = NAND_OP_FALSE;
690	NFC_DeSelectChip(chip);
691	NFC_DeSelectRb(rb);
692
693
694	return ret;
695}