1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171 |
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/string.h>
- #include <linux/ioport.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/err.h>
- #include <linux/slab.h>
- #include <linux/io.h>
- #include <linux/bitops.h>
- #include <linux/reboot.h>
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/nand.h>
- #include <linux/mtd/nand_ecc.h>
- #include <linux/mtd/partitions.h>
- #include <mach/nand.h>
- #include <mach/clock.h>
- static char *aml_nand_plane_string[]={
- "NAND_SINGLE_PLANE_MODE",
- "NAND_TWO_PLANE_MODE",
- };
- static char *aml_nand_internal_string[]={
- "NAND_NONE_INTERLEAVING_MODE",
- "NAND_INTERLEAVING_MODE",
- };
- #define ECC_INFORMATION(name_a, bch_a, size_a, parity_a, user_a) { \
- .name=name_a, .bch_mode=bch_a, .bch_unit_size=size_a, .bch_bytes=parity_a, .user_byte_mode=user_a \
- }
- static struct aml_nand_bch_desc m3_bch_list[] = {
- [0]=ECC_INFORMATION("NAND_RAW_MODE", NAND_ECC_SOFT_MODE, 0, 0, 0),
- [1]=ECC_INFORMATION("NAND_SHORT_MODE" ,NAND_ECC_SHORT_MODE, NAND_ECC_UNIT_SHORT, NAND_BCH60_1K_ECC_SIZE, 2),
- [1]=ECC_INFORMATION("NAND_BCH8_MODE", NAND_ECC_BCH8_MODE, NAND_ECC_UNIT_SIZE, NAND_BCH8_ECC_SIZE, 2),
- [2]=ECC_INFORMATION("NAND_BCH8_1K_MODE" ,NAND_ECC_BCH8_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH8_1K_ECC_SIZE, 2),
- [3]=ECC_INFORMATION("NAND_BCH16_1K_MODE" ,NAND_ECC_BCH16_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH16_1K_ECC_SIZE, 2),
- [4]=ECC_INFORMATION("NAND_BCH24_1K_MODE" ,NAND_ECC_BCH24_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH24_1K_ECC_SIZE, 2),
- [5]=ECC_INFORMATION("NAND_BCH30_1K_MODE" ,NAND_ECC_BCH30_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH30_1K_ECC_SIZE, 2),
- [6]=ECC_INFORMATION("NAND_BCH40_1K_MODE" ,NAND_ECC_BCH40_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH40_1K_ECC_SIZE, 2),
- [7]=ECC_INFORMATION("NAND_BCH60_1K_MODE" ,NAND_ECC_BCH60_1K_MODE, NAND_ECC_UNIT_1KSIZE, NAND_BCH60_1K_ECC_SIZE, 2),
- };
- static struct aml_nand_device *to_nand_dev(struct platform_device *pdev)
- {
- return pdev->dev.platform_data;
- }
- static pinmux_item_t nand_ce0_pins[] = {
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<25,
- },
- PINMUX_END_ITEM
- };
- static pinmux_item_t nand_ce1_pins[] = {
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<24,
- },
- PINMUX_END_ITEM
- };
- static pinmux_item_t nand_ce2_pins[] = {
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<23,
- },
- PINMUX_END_ITEM
- };
- static pinmux_item_t nand_ce3_pins[] = {
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<22,
- },
- PINMUX_END_ITEM
- };
- static pinmux_set_t nand_ce0 = {
- .chip_select = NULL,
- .pinmux = &nand_ce0_pins[0]
- };
- static pinmux_set_t nand_ce1 = {
- .chip_select = NULL,
- .pinmux = &nand_ce1_pins[0]
- };
- static pinmux_set_t nand_ce2 = {
- .chip_select = NULL,
- .pinmux = &nand_ce2_pins[0]
- };
- static pinmux_set_t nand_ce3 = {
- .chip_select = NULL,
- .pinmux = &nand_ce3_pins[0]
- };
- static pinmux_item_t nand_rb0_pins[] = {
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<17,
- },
- PINMUX_END_ITEM
- };
- static pinmux_item_t nand_rb1_pins[] ={
- {
- .reg = PINMUX_REG(2),
- .setmask = 1<<16,
- },
- PINMUX_END_ITEM
- };
- static pinmux_set_t nand_rb0 = {
- .chip_select = NULL,
- .pinmux = &nand_rb0_pins[0]
- };
- static pinmux_set_t nand_rb1 = {
- .chip_select = NULL,
- .pinmux = &nand_rb1_pins[0]
- };
- static void m3_nand_select_chip(struct aml_nand_chip *aml_chip, int chipnr)
- {
- int i;
- switch (chipnr) {
- case 0:
- case 1:
- case 2:
- case 3:
- udelay(10);
- aml_chip->chip_selected = aml_chip->chip_enable[chipnr];
- aml_chip->rb_received = aml_chip->rb_enable[chipnr];
- for (i=0; i<aml_chip->chip_num; i++) {
- if (aml_chip->valid_chip[i]) {
- if (!((aml_chip->chip_enable[i] >> 10) & 1))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 25));
- pinmux_set(&nand_ce0);
- if (!((aml_chip->chip_enable[i] >> 10) & 2))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 24));
- pinmux_set(&nand_ce1);
- if (!((aml_chip->chip_enable[i] >> 10) & 4))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 23));
- pinmux_set(&nand_ce2);
- if (!((aml_chip->chip_enable[i] >> 10) & 8))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 22));
- pinmux_set(&nand_ce3);
- if (((aml_chip->ops_mode & AML_CHIP_NONE_RB) == 0) && (aml_chip->rb_enable[i])){
- if (!((aml_chip->rb_enable[i] >> 10) & 1))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 17));
- pinmux_set(&nand_rb0);
- if (!((aml_chip->rb_enable[i] >> 10) & 2))
- //aml_set_reg32_mask(P_PERIPHS_PIN_MUX_2, (1 << 16));
- pinmux_set(&nand_rb1);
- }
- }
- }
- NFC_SEND_CMD_IDLE(aml_chip->chip_selected, 0);
- break;
- default:
- BUG();
- aml_chip->chip_selected = CE_NOT_SEL;
- break;
- }
- return;
- }
- static void m3_nand_hw_init(struct aml_nand_chip *aml_chip)
- {
- struct clk *sys_clk;
- int sys_clk_rate, sys_time, start_cycle, end_cycle, bus_cycle, bus_timing, Tcycle, T_REA = DEFAULT_T_REA, T_RHOH = DEFAULT_T_RHOH;
- sys_clk = clk_get_sys(NAND_SYS_CLK_NAME, NULL);
- sys_clk_rate = clk_get_rate(sys_clk);
- sys_time = (10000 / (sys_clk_rate / 1000000));
- start_cycle = (((NAND_CYCLE_DELAY + T_REA * 10) * 10) / sys_time);
- start_cycle = (start_cycle + 9) / 10;
- for (bus_cycle = 4; bus_cycle <= MAX_CYCLE_NUM; bus_cycle++) {
- Tcycle = bus_cycle * sys_time;
- end_cycle = (((NAND_CYCLE_DELAY + Tcycle / 2 + T_RHOH * 10) * 10) / sys_time);
- end_cycle = end_cycle / 10;
- if ((((start_cycle >= 3) && (start_cycle <= ( bus_cycle + 1)))
- || ((end_cycle >= 3) && (end_cycle <= (bus_cycle + 1))))
- && (start_cycle <= end_cycle)) {
- break;
- }
- }
- if (bus_cycle > MAX_CYCLE_NUM)
- return;
- bus_timing = (start_cycle + end_cycle) / 2;
- NFC_SET_CFG(0);
- NFC_SET_TIMING_ASYC(bus_timing, (bus_cycle - 1));
- NFC_SEND_CMD(1<<31);
- printk("init bus_cycle=%d, bus_timing=%d, start_cycle=%d, end_cycle=%d,system=%d.%dns\n",
- bus_cycle, bus_timing, start_cycle, end_cycle, sys_time/10, sys_time%10);
- return;
- }
- static void m3_nand_adjust_timing(struct aml_nand_chip *aml_chip)
- {
- struct clk *sys_clk;
- int sys_clk_rate, sys_time, start_cycle, end_cycle, bus_cycle, bus_timing, Tcycle;
- if (!aml_chip->T_REA)
- aml_chip->T_REA = 20;
- if (!aml_chip->T_RHOH)
- aml_chip->T_RHOH = 15;
- sys_clk = clk_get_sys(NAND_SYS_CLK_NAME, NULL);
- sys_clk_rate = clk_get_rate(sys_clk);
- sys_time = (10000 / (sys_clk_rate / 1000000));
- start_cycle = (((NAND_CYCLE_DELAY + aml_chip->T_REA * 10) * 10) / sys_time);
- start_cycle = (start_cycle + 9) / 10;
- for (bus_cycle = 4; bus_cycle <= MAX_CYCLE_NUM; bus_cycle++) {
- Tcycle = bus_cycle * sys_time;
- end_cycle = (((NAND_CYCLE_DELAY + Tcycle / 2 + aml_chip->T_RHOH * 10) * 10) / sys_time);
- end_cycle = end_cycle / 10;
- if ((((start_cycle >= 3) && (start_cycle <= ( bus_cycle + 1)))
- || ((end_cycle >= 3) && (end_cycle <= (bus_cycle + 1))))
- && (start_cycle <= end_cycle)) {
- break;
- }
- }
- if (bus_cycle > MAX_CYCLE_NUM)
- return;
- bus_timing = (start_cycle + end_cycle) / 2;
- NFC_SET_CFG(0);
- NFC_SET_TIMING_ASYC(bus_timing, (bus_cycle - 1));
- NFC_SEND_CMD(1<<31);
- printk("bus_cycle=%d, bus_timing=%d, start_cycle=%d, end_cycle=%d,system=%d.%dns\n",
- bus_cycle, bus_timing, start_cycle, end_cycle, sys_time/10, sys_time%10);
- }
- #ifdef CONFIG_HAS_EARLYSUSPEND
- static void m3_nand_early_suspend(struct early_suspend *nand_early_suspend)
- {
- printk("m3_nand_early suspend entered\n");
- return;
- }
- static void m3_nand_late_resume(struct early_suspend *nand_early_suspend)
- {
- printk("m3_nand_late resume entered\n");
- return;
- }
- #endif
- static int m3_nand_suspend(struct mtd_info *mtd)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- struct aml_nand_platform *plat = aml_chip->platform;
- struct nand_chip *chip = &aml_chip->chip;
- spinlock_t *lock = &chip->controller->lock;
- if (!strncmp((char*)plat->name, NAND_BOOT_NAME, strlen((const char*)NAND_BOOT_NAME)))
- return 0;
- spin_lock(lock);
- if (!chip->controller->active)
- chip->controller->active = chip;
- chip->state = FL_PM_SUSPENDED;
- spin_unlock(lock);
- printk("m3 nand suspend entered\n");
- return 0;
- }
- static void m3_nand_resume(struct mtd_info *mtd)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- struct aml_nand_platform *plat = aml_chip->platform;
- struct nand_chip *chip = &aml_chip->chip;
- u8 onfi_features[4];
- if (!strncmp((char*)plat->name, NAND_BOOT_NAME, strlen((const char*)NAND_BOOT_NAME)))
- return;
- chip->select_chip(mtd, 0);
- chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
- if (aml_chip->onfi_mode) {
- aml_nand_set_onfi_features(aml_chip, (uint8_t *)(&aml_chip->onfi_mode), ONFI_TIMING_ADDR);
- aml_nand_get_onfi_features(aml_chip, onfi_features, ONFI_TIMING_ADDR);
- if (onfi_features[0] != aml_chip->onfi_mode) {
- aml_chip->T_REA = DEFAULT_T_REA;
- aml_chip->T_RHOH = DEFAULT_T_RHOH;
- printk("onfi timing mode set failed: %x\n", onfi_features[0]);
- }
- }
- chip->select_chip(mtd, -1);
- spin_lock(&chip->controller->lock);
- chip->controller->active = NULL;
- chip->state = FL_READY;
- spin_unlock(&chip->controller->lock);
- printk("m3 nand resume entered\n");
- return;
- }
- static int m3_nand_options_confirm(struct aml_nand_chip *aml_chip)
- {
- struct mtd_info *mtd = &aml_chip->mtd;
- struct nand_chip *chip = &aml_chip->chip;
- struct aml_nand_platform *plat = aml_chip->platform;
- struct aml_nand_bch_desc *ecc_supports = aml_chip->bch_desc;
- unsigned max_bch_mode = aml_chip->max_bch_mode;
- unsigned options_selected = 0, options_support = 0, ecc_bytes, options_define, valid_chip_num = 0;
- int error = 0, i, j;
- options_selected = (plat->platform_nand_data.chip.options & NAND_ECC_OPTIONS_MASK);
- options_define = (aml_chip->options & NAND_ECC_OPTIONS_MASK);
- for (i=0; i<max_bch_mode; i++) {
- if (ecc_supports[i].bch_mode == options_selected) {
- break;
- }
- }
- j = i;
- for(i=max_bch_mode-1; i>0; i--)
- {
- ecc_bytes = aml_chip->oob_size / (aml_chip->page_size / ecc_supports[i].bch_unit_size);
- if(ecc_bytes >= ecc_supports[i].bch_bytes + ecc_supports[i].user_byte_mode)
- {
- options_support = ecc_supports[i].bch_mode;
- break;
- }
- }
- if (options_define != options_support) {
- options_define = options_support;
- //printk("define oob size: %d could support bch mode: %s\n", aml_chip->oob_size, ecc_supports[options_support].name);
- }
- if (options_selected > options_define) {
- printk("oob size is not enough for selected bch mode: %s force bch to mode: %s\n", ecc_supports[j].name, ecc_supports[i].name);
- options_selected = options_define;
- }
- switch (options_selected) {
- case NAND_ECC_BCH8_MODE:
- chip->ecc.size = NAND_ECC_UNIT_SIZE;
- chip->ecc.bytes = NAND_BCH8_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH8;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH8_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH8_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH8_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH16_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH16_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH16_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH24_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH24_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH24_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH30_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH30_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH30_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH40_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH40_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH40_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_BCH60_1K_MODE:
- chip->ecc.size = NAND_ECC_UNIT_1KSIZE;
- chip->ecc.bytes = NAND_BCH60_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH60_1K;
- aml_chip->user_byte_mode = 2;
- break;
- case NAND_ECC_SHORT_MODE:
- chip->ecc.size = NAND_ECC_UNIT_SHORT;
- chip->ecc.bytes = NAND_BCH60_1K_ECC_SIZE;
- aml_chip->bch_mode = NAND_ECC_BCH_SHORT;
- aml_chip->user_byte_mode = 2;
- chip->ecc.steps = mtd->writesize / 512;
- break;
- default :
- if ((plat->platform_nand_data.chip.options & NAND_ECC_OPTIONS_MASK) != NAND_ECC_SOFT_MODE) {
- printk("soft ecc or none ecc just support in linux self nand base please selected it at platform options\n");
- error = -ENXIO;
- }
- break;
- }
- options_selected = (plat->platform_nand_data.chip.options & NAND_INTERLEAVING_OPTIONS_MASK);
- options_define = (aml_chip->options & NAND_INTERLEAVING_OPTIONS_MASK);
- if (options_selected > options_define) {
- printk("internal mode error for selected internal mode: %s force internal mode to : %s\n", aml_nand_internal_string[options_selected >> 16], aml_nand_internal_string[options_define >> 16]);
- options_selected = options_define;
- }
- switch (options_selected) {
- case NAND_INTERLEAVING_MODE:
- aml_chip->ops_mode |= AML_INTERLEAVING_MODE;
- mtd->erasesize *= aml_chip->internal_chipnr;
- mtd->writesize *= aml_chip->internal_chipnr;
- mtd->oobsize *= aml_chip->internal_chipnr;
- break;
- default:
- break;
- }
- options_selected = (plat->platform_nand_data.chip.options & NAND_PLANE_OPTIONS_MASK);
- options_define = (aml_chip->options & NAND_PLANE_OPTIONS_MASK);
- if (options_selected > options_define) {
- printk("multi plane error for selected plane mode: %s force plane to : %s\n", aml_nand_plane_string[options_selected >> 4], aml_nand_plane_string[options_define >> 4]);
- options_selected = options_define;
- }
-
- for (i=0; i<aml_chip->chip_num; i++) {
- if (aml_chip->valid_chip[i]) {
- valid_chip_num++;
- }
- }
-
- if (aml_chip->ops_mode & AML_INTERLEAVING_MODE)
- valid_chip_num *= aml_chip->internal_chipnr;
-
- if(valid_chip_num > 2){
- printk("detect valid_chip_num:%d over 2, and aml_chip->internal_chipnr:%d, disable NAND_TWO_PLANE_MODE here\n", valid_chip_num, aml_chip->internal_chipnr);
- }
- else{
- switch (options_selected) {
- case NAND_TWO_PLANE_MODE:
- aml_chip->plane_num = 2;
- mtd->erasesize *= 2;
- mtd->writesize *= 2;
- mtd->oobsize *= 2;
- break;
- default:
- aml_chip->plane_num = 1;
- break;
- }
- }
- return error;
- }
- static int aml_platform_dma_waiting(struct aml_nand_chip *aml_chip)
- {
- unsigned time_out_cnt = 0;
- NFC_SEND_CMD_IDLE(aml_chip->chip_selected, 0);
- NFC_SEND_CMD_IDLE(aml_chip->chip_selected, 0);
- do {
- if (NFC_CMDFIFO_SIZE() <= 0)
- break;
- }while (time_out_cnt++ <= AML_DMA_BUSY_TIMEOUT);
- if (time_out_cnt < AML_DMA_BUSY_TIMEOUT)
- return 0;
- return -EBUSY;
- }
- static int m3_nand_dma_write(struct aml_nand_chip *aml_chip, unsigned char *buf, int len, unsigned bch_mode)
- {
- int ret = 0;
- unsigned dma_unit_size = 0, count = 0;
- struct nand_chip *chip = &aml_chip->chip;
- memcpy(aml_chip->aml_nand_data_buf, buf, len);
- smp_wmb();
- wmb();
- if (bch_mode == NAND_ECC_NONE)
- count = 1;
- else if (bch_mode == NAND_ECC_BCH_SHORT) {
- dma_unit_size = (chip->ecc.size >> 3);
- count = len/chip->ecc.size;
- }
- else
- count = len/chip->ecc.size;
- #ifdef CONFIG_CLK81_DFS
- down(&aml_chip->nand_sem);
- #endif
- NFC_SEND_CMD_ADL(aml_chip->data_dma_addr);
- NFC_SEND_CMD_ADH(aml_chip->data_dma_addr);
- NFC_SEND_CMD_AIL(aml_chip->nand_info_dma_addr);
- NFC_SEND_CMD_AIH((aml_chip->nand_info_dma_addr));
-
- if(aml_chip->ran_mode){
- NFC_SEND_CMD_SEED(aml_chip->page_addr);
- }
- if(!bch_mode)
- NFC_SEND_CMD_M2N_RAW(aml_chip->ran_mode, len);
- else
- NFC_SEND_CMD_M2N(aml_chip->ran_mode, ((bch_mode == NAND_ECC_BCH_SHORT)?NAND_ECC_BCH60_1K:bch_mode), ((bch_mode == NAND_ECC_BCH_SHORT)?1:0), dma_unit_size, count);
- ret = aml_platform_dma_waiting(aml_chip);
- #ifdef CONFIG_CLK81_DFS
- up(&aml_chip->nand_sem);
- #endif
- return ret;
- }
- static int m3_nand_dma_read(struct aml_nand_chip *aml_chip, unsigned char *buf, int len, unsigned bch_mode)
- {
- volatile unsigned int * info_buf=NULL;
- //volatile int cmp=0;
- struct nand_chip *chip = &aml_chip->chip;
- unsigned dma_unit_size = 0, count = 0, info_times_int_len;
- int ret = 0;
- info_times_int_len = PER_INFO_BYTE/sizeof(unsigned int);
- if (bch_mode == NAND_ECC_NONE)
- count = 1;
- else if (bch_mode == NAND_ECC_BCH_SHORT) {
- dma_unit_size = (chip->ecc.size >> 3);
- count = len/chip->ecc.size;
- }
- else
- count = len/chip->ecc.size;
- info_buf = (volatile unsigned *)&(aml_chip->user_info_buf[(count-1)*info_times_int_len]);
- memset((unsigned char *)aml_chip->user_info_buf, 0, count*PER_INFO_BYTE);
- smp_wmb();
- wmb();
- #ifdef CONFIG_CLK81_DFS
- down(&aml_chip->nand_sem);
- #endif
- NFC_SEND_CMD_ADL(aml_chip->data_dma_addr);
- NFC_SEND_CMD_ADH(aml_chip->data_dma_addr);
- NFC_SEND_CMD_AIL(aml_chip->nand_info_dma_addr);
- NFC_SEND_CMD_AIH((aml_chip->nand_info_dma_addr));
- if(aml_chip->ran_mode){
- NFC_SEND_CMD_SEED(aml_chip->page_addr);
- }
- if(bch_mode == NAND_ECC_NONE)
- NFC_SEND_CMD_N2M_RAW(aml_chip->ran_mode,len);
- else
- NFC_SEND_CMD_N2M(aml_chip->ran_mode, ((bch_mode == NAND_ECC_BCH_SHORT)?NAND_ECC_BCH60_1K:bch_mode), ((bch_mode == NAND_ECC_BCH_SHORT)?1:0), dma_unit_size, count);
- ret = aml_platform_dma_waiting(aml_chip);
- #ifdef CONFIG_CLK81_DFS
- up(&aml_chip->nand_sem);
- #endif
- if (ret)
- return ret;
- /*do{
- info_buf = (volatile unsigned *)&(aml_chip->user_info_buf[(count-1)*info_times_int_len]);
- cmp = *info_buf;
- }while((cmp)==0);*/
- do{
- smp_rmb();
- }while(NAND_INFO_DONE(aml_read_reg32((unsigned) info_buf)) == 0);
- smp_rmb();
- if (buf != aml_chip->aml_nand_data_buf)
- memcpy(buf, aml_chip->aml_nand_data_buf, len);
- smp_wmb();
- wmb();
- return 0;
- }
- static int m3_nand_hwecc_correct(struct aml_nand_chip *aml_chip, unsigned char *buf, unsigned size, unsigned char *oob_buf)
- {
- struct nand_chip *chip = &aml_chip->chip;
- struct mtd_info *mtd = &aml_chip->mtd;
- unsigned ecc_step_num;
- unsigned info_times_int_len = PER_INFO_BYTE/sizeof(unsigned int);
-
- if (size % chip->ecc.size) {
- printk ("error parameter size for ecc correct %x\n", size);
- return -EINVAL;
- }
- aml_chip->ecc_cnt_cur = 0;
- for (ecc_step_num = 0; ecc_step_num < (size / chip->ecc.size); ecc_step_num++) {
- //check if there have uncorrectable sector
- if(NAND_ECC_CNT(aml_read_reg32((unsigned )(&aml_chip->user_info_buf[ecc_step_num*info_times_int_len]))) == 0x3f)
- {
- aml_chip->zero_cnt = NAND_ZERO_CNT(*(unsigned *)(&aml_chip->user_info_buf[ecc_step_num*info_times_int_len]));
- //printk ("nand communication have uncorrectable ecc error %d\n", ecc_step_num);
- return -EIO;
- }
- else {
- //mtd->ecc_stats.corrected += NAND_ECC_CNT(*(unsigned *)(&aml_chip->user_info_buf[ecc_step_num*info_times_int_len]));
- aml_chip->ecc_cnt_cur = NAND_ECC_CNT(*(unsigned *)(&aml_chip->user_info_buf[ecc_step_num*info_times_int_len]));
- }
- }
- return 0;
- }
- static void m3_nand_boot_erase_cmd(struct mtd_info *mtd, int page)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- struct nand_chip *chip = mtd->priv;
- loff_t ofs;
- int i, page_addr;
- if (page >= M3_BOOT_PAGES_PER_COPY)
- return;
- if (aml_chip->valid_chip[0]) {
- for (i=0; i<M3_BOOT_COPY_NUM; i++) {
- page_addr = page + i*M3_BOOT_PAGES_PER_COPY;
- ofs = (page_addr << chip->page_shift);
- if (chip->block_bad(mtd, ofs, 0))
- continue;
- aml_chip->aml_nand_select_chip(aml_chip, 0);
- aml_chip->aml_nand_command(aml_chip, NAND_CMD_ERASE1, -1, page_addr, i);
- aml_chip->aml_nand_command(aml_chip, NAND_CMD_ERASE2, -1, -1, i);
- chip->waitfunc(mtd, chip);
- }
- }
- return ;
- }
- static int m3_nand_boot_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int page)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- uint8_t *oob_buf = chip->oob_poi;
- unsigned nand_page_size = chip->ecc.steps * chip->ecc.size;
- unsigned pages_per_blk_shift = (chip->phys_erase_shift - chip->page_shift);
- int user_byte_num = (chip->ecc.steps * aml_chip->user_byte_mode);
- int error = 0, i = 0, stat = 0, bch_mode, read_page, read_page_tmp;
- int new_nand_type = 0;
- #ifdef NEW_NAND_SUPPORT
- new_nand_type = aml_chip->new_nand_info.type;
- #endif
- if((new_nand_type < 10)&&(new_nand_type))
- {
- if (page >= (M3_BOOT_PAGES_PER_COPY/2 - 3)) {
- memset(buf, 0, (1 << chip->page_shift));
- goto exit;
- }
- }
- else{
- if (page >= (M3_BOOT_PAGES_PER_COPY - 1)) {
- memset(buf, 0, (1 << chip->page_shift));
- goto exit;
- }
- }
-
- read_page = page;
- read_page++;
-
- if((page > 3) && ((new_nand_type < 10)&&(new_nand_type))){
-
- read_page_tmp = page + 2;
-
- //printk("%s, write_page_tmp:0x%x\n", __func__, write_page_tmp);
-
- if(((read_page_tmp%4) == 2) ||((read_page_tmp%4) == 3)){
- read_page_tmp += (((read_page_tmp/4) -1) *4);
- }
- else if(((read_page_tmp%4) == 0) ||((read_page_tmp%4) == 1)){
- read_page_tmp += (((read_page_tmp/4) -1) *4 -2);
- }
- read_page = read_page_tmp;
- //printk("%s, page:0x%x\n", __func__, page);
- }
- //printk("%s, read_page:0x%x\n", __func__, read_page);
- chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, read_page);
- bch_mode = aml_chip->bch_mode;
- memset(buf, 0xff, (1 << chip->page_shift));
- if (aml_chip->valid_chip[i]) {
- if (!aml_chip->aml_nand_wait_devready(aml_chip, i)) {
- printk ("read couldn`t found selected chip: %d ready\n", i);
- error = -EBUSY;
- goto exit;
- }
-
- if (aml_chip->ops_mode & AML_CHIP_NONE_RB)
- chip->cmd_ctrl(mtd, NAND_CMD_READ0 & 0xff, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
- error = aml_chip->aml_nand_dma_read(aml_chip, buf, nand_page_size, bch_mode);
- if (error)
- goto exit;
- aml_chip->aml_nand_get_user_byte(aml_chip, oob_buf, user_byte_num);
- stat = aml_chip->aml_nand_hwecc_correct(aml_chip, buf, nand_page_size, oob_buf);
- if (stat < 0) {
- mtd->ecc_stats.failed++;
- printk("aml nand read data ecc failed at blk %d page:%d chip %d\n", (page >> pages_per_blk_shift), page, i);
- }
- else
- mtd->ecc_stats.corrected += stat;
- }
- else {
- error = -ENODEV;
- goto exit;
- }
- exit:
- return error;
- }
- static void m3_nand_boot_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- uint8_t *oob_buf = chip->oob_poi;
- unsigned nand_page_size = chip->ecc.steps * chip->ecc.size;
- int user_byte_num = (chip->ecc.steps * aml_chip->user_byte_mode);
- int error = 0, i = 0, bch_mode, ecc_size;
- ecc_size = chip->ecc.size;
- if (((aml_chip->page_addr % M3_BOOT_PAGES_PER_COPY) == 0) && (aml_chip->bch_mode != NAND_ECC_BCH_SHORT)) {
- nand_page_size = (mtd->writesize / 512) * NAND_ECC_UNIT_SHORT;
- bch_mode = NAND_ECC_BCH_SHORT;
- chip->ecc.size = NAND_ECC_UNIT_SHORT;
- }
- else
- bch_mode = aml_chip->bch_mode;
- for (i=0; i<mtd->oobavail; i+=2) {
- oob_buf[i] = 0x55;
- oob_buf[i+1] = 0xaa;
- }
- i = 0;
- if (aml_chip->valid_chip[i]) {
- aml_chip->aml_nand_select_chip(aml_chip, i);
- aml_chip->aml_nand_set_user_byte(aml_chip, oob_buf, user_byte_num);
- error = aml_chip->aml_nand_dma_write(aml_chip, (unsigned char *)buf, nand_page_size, bch_mode);
- if (error)
- goto exit;
- aml_chip->aml_nand_command(aml_chip, NAND_CMD_PAGEPROG, -1, -1, i);
- }
- else {
- error = -ENODEV;
- goto exit;
- }
- exit:
- if (((aml_chip->page_addr % M3_BOOT_PAGES_PER_COPY) == 0) && (aml_chip->bch_mode != NAND_ECC_BCH_SHORT))
- chip->ecc.size = ecc_size;
- return;
- }
- static int m3_nand_boot_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int page, int cached, int raw)
- {
- struct aml_nand_chip *aml_chip = mtd_to_nand_chip(mtd);
- int status, i, write_page, configure_data, pages_per_blk, write_page_tmp, ran_mode;
- int new_nand_type = 0;
- int en_slc = 0;
- #ifdef NEW_NAND_SUPPORT
- new_nand_type = aml_chip->new_nand_info.type;
- en_slc = ((aml_chip->new_nand_info.type < 10)&&(aml_chip->new_nand_info.type))? 1:0;
- #endif
- if(en_slc){
- if (page >= (M3_BOOT_PAGES_PER_COPY/2 - 3))
- return 0;
- #ifdef NEW_NAND_SUPPORT
- if(page > 3)
- aml_chip->new_nand_info.slc_program_info.enter_enslc_mode(mtd);
- #endif
- }
- else{
- if (page >= (M3_BOOT_PAGES_PER_COPY - 1))
- return 0;
- }
- pages_per_blk = (1 << (chip->phys_erase_shift - chip->page_shift));
- for (i=0; i<M3_BOOT_COPY_NUM; i++) {
- write_page = page + i*M3_BOOT_PAGES_PER_COPY;
- if ((write_page % M3_BOOT_PAGES_PER_COPY) == 0) {
- if (aml_chip->bch_mode == NAND_ECC_BCH_SHORT)
- configure_data = NFC_CMD_N2M(aml_chip->ran_mode, NAND_ECC_BCH60_1K, 1, (chip->ecc.size >> 3), chip->ecc.steps);
- else
- configure_data = NFC_CMD_N2M(aml_chip->ran_mode, aml_chip->bch_mode, 0, (chip->ecc.size >> 3), chip->ecc.steps);
- memset(chip->buffers->databuf, 0xbb, mtd->writesize);
- memcpy(chip->buffers->databuf, (unsigned char *)(&configure_data), sizeof(int));
- memcpy(chip->buffers->databuf + sizeof(int), (unsigned char *)(&pages_per_blk), sizeof(int));
- //add for new nand
- memcpy(chip->buffers->databuf + sizeof(int) + sizeof(int), (unsigned char *)(&new_nand_type), sizeof(int));
-
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, write_page);
- ran_mode = aml_chip->ran_mode;
- aml_chip->ran_mode = 0;
- chip->ecc.write_page(mtd, chip, chip->buffers->databuf);
- aml_chip->ran_mode = ran_mode;
- status = chip->waitfunc(mtd, chip);
- if ((status & NAND_STATUS_FAIL) && (chip->errstat))
- status = chip->errstat(mtd, chip, FL_WRITING, status, write_page);
- if (status & NAND_STATUS_FAIL)
- return -EIO;
- }
- write_page++;
- if((page > 3) && en_slc){
- write_page_tmp = page + 2;
-
- //printk("%s, write_page_tmp:0x%x\n", __func__, write_page_tmp);
-
- if(((write_page_tmp%4) == 2) ||((write_page_tmp%4) == 3)){
- write_page_tmp += (((write_page_tmp/4) -1) *4);
- }
- else if(((write_page_tmp%4) == 0) ||((write_page_tmp%4) == 1)){
- write_page_tmp += (((write_page_tmp/4) -1) *4 -2);
- }
- write_page = write_page_tmp + i*M3_BOOT_PAGES_PER_COPY;
- //printk("%s, write_page:0x%x\n", __func__, write_page);
- }
- //printk("%s, write_page:0x%x\n", __func__, write_page);
- chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, write_page);
- if (unlikely(raw))
- chip->ecc.write_page_raw(mtd, chip, buf);
- else
- chip->ecc.write_page(mtd, chip, buf);
- if (!cached || !(chip->options & NAND_CACHEPRG)) {
- status = chip->waitfunc(mtd, chip);
- if ((status & NAND_STATUS_FAIL) && (chip->errstat))
- status = chip->errstat(mtd, chip, FL_WRITING, status, write_page);
- if (status & NAND_STATUS_FAIL){
- #ifdef NEW_NAND_SUPPORT
- if(en_slc && (page > 3))
- aml_chip->new_nand_info.slc_program_info.exit_enslc_mode(mtd);
- #endif
- return -EIO;
- }
- } else {
- status = chip->waitfunc(mtd, chip);
- }
- }
- #ifdef NEW_NAND_SUPPORT
- if(en_slc && (page > 3))
- aml_chip->new_nand_info.slc_program_info.exit_enslc_mode(mtd);
- #endif
- return 0;
- }
- #ifdef CONFIG_CLK81_DFS
- static int nand_pre_change_fun(struct clk81_client* client)
- {
- struct aml_nand_chip *aml_chip = client->param;
- return 0;
- }
- static int nand_check_client_ready(struct clk81_client* client)
- {
- struct aml_nand_chip *aml_chip = client->param;
- if(aml_chip->lock_state){
- printk(KERN_DEBUG "nand already lock");
- return 0;
- }
- else{
- if(down_trylock(&aml_chip->nand_sem)){
- printk(KERN_DEBUG "nand lock not ready");
- return -1;
- }
- aml_chip->lock_state = 1;
- printk(KERN_DEBUG "nand lock ready");
- return 0;
- }
- }
- static int nand_post_change_fun(struct clk81_client* client)
- {
- struct aml_nand_chip *aml_chip = client->param;
- aml_chip->aml_nand_adjust_timing(aml_chip);
-
- up(&aml_chip->nand_sem);
- aml_chip->lock_state = 0;
- printk(KERN_DEBUG "nand unlock");
- return 0;
- }
- #endif
- struct nand_hw_control controller;
- static int aml_nand_probe(struct aml_nand_platform *plat, struct device *dev)
- {
- struct aml_nand_chip *aml_chip = NULL;
- struct nand_chip *chip = NULL;
- struct mtd_info *mtd = NULL;
- int err = 0, i;
- aml_chip = kzalloc(sizeof(*aml_chip), GFP_KERNEL);
- if (aml_chip == NULL) {
- printk("no memory for flash info\n");
- err = -ENOMEM;
- goto exit_error;
- }
- #ifdef CONFIG_CLK81_DFS
- init_MUTEX(&aml_chip->nand_sem);
- aml_chip->lock_state = 0;
- regist_clk81_client(plat->name, nand_pre_change_fun, nand_post_change_fun, nand_check_client_ready, aml_chip);
- #endif
- /* initialize mtd info data struct */
- dev->coherent_dma_mask = DMA_BIT_MASK(32);
- aml_chip->device = dev;
- aml_chip->platform = plat;
- aml_chip->bch_desc = m3_bch_list;
- aml_chip->max_bch_mode = sizeof(m3_bch_list) / sizeof(m3_bch_list[0]);
- plat->aml_chip = aml_chip;
- chip = &aml_chip->chip;
- chip->priv = aml_chip;//&aml_chip->mtd;
- aml_chip->ran_mode = plat->ran_mode;
- aml_chip->rbpin_detect = plat->rbpin_detect;
- chip->controller=&controller;
- printk("chip->controller=%p\n",chip->controller);
- mtd = &aml_chip->mtd;
- mtd->priv = chip;
- mtd->dev.parent= dev->parent;
- mtd->owner = THIS_MODULE;
- aml_chip->aml_nand_hw_init = m3_nand_hw_init;
- aml_chip->aml_nand_adjust_timing = m3_nand_adjust_timing;
- aml_chip->aml_nand_select_chip = m3_nand_select_chip;
- aml_chip->aml_nand_options_confirm = m3_nand_options_confirm;
- aml_chip->aml_nand_dma_read = m3_nand_dma_read;
- aml_chip->aml_nand_dma_write = m3_nand_dma_write;
- aml_chip->aml_nand_hwecc_correct = m3_nand_hwecc_correct;
- // aml_chip->nand_early_suspend.suspend = m3_nand_early_suspend;
- // aml_chip->nand_early_suspend.resume = m3_nand_late_resume;
- err = aml_nand_init(aml_chip);
- if (err)
- goto exit_error;
- if (!strncmp((char*)plat->name, NAND_BOOT_NAME, strlen((const char*)NAND_BOOT_NAME))) {
- chip->erase_cmd = m3_nand_boot_erase_cmd;
- chip->ecc.read_page = m3_nand_boot_read_page_hwecc;
- chip->ecc.write_page = m3_nand_boot_write_page_hwecc;
- chip->write_page = m3_nand_boot_write_page;
- if (chip->ecc.layout)
- chip->ecc.layout->oobfree[0].length = ((mtd->writesize / 512) * aml_chip->user_byte_mode);
- chip->ecc.layout->oobavail = 0;
- for (i = 0; chip->ecc.layout->oobfree[i].length && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)
- chip->ecc.layout->oobavail += chip->ecc.layout->oobfree[i].length;
- mtd->oobavail = chip->ecc.layout->oobavail;
- mtd->ecclayout = chip->ecc.layout;
- }
- mtd->suspend = m3_nand_suspend;
- mtd->resume = m3_nand_resume;
- return 0;
- exit_error:
- if (aml_chip)
- kfree(aml_chip);
- mtd->name = NULL;
- return err;
- }
- #define m3_nand_notifier_to_blk(l) container_of(l, struct aml_nand_device, nb)
- static int m3_nand_reboot_notifier(struct notifier_block *nb, unsigned long priority, void * arg)
- {
- int error = 0;
- struct aml_nand_device *aml_nand_dev = m3_nand_notifier_to_blk(nb);
- struct aml_nand_platform *plat = NULL;
- struct aml_nand_chip *aml_chip = NULL;
- struct mtd_info *mtd = NULL;
- int i;
- for (i=1; i<aml_nand_dev->dev_num; i++) {
- plat = &aml_nand_dev->aml_nand_platform[i];
- aml_chip = plat->aml_chip;
- if (aml_chip) {
- mtd = &aml_chip->mtd;
- #ifdef NEW_NAND_SUPPORT
- if (mtd) {
- if((aml_chip->new_nand_info.type) && (aml_chip->new_nand_info.type < 10)){
- aml_chip->new_nand_info.slc_program_info.exit_enslc_mode(mtd);
- aml_chip->new_nand_info.read_rety_info.set_default_value(mtd);
- }
- }
- #endif
- }
- }
- return error;
- }
- static int m3_nand_probe(struct platform_device *pdev)
- {
- struct aml_nand_device *aml_nand_dev = to_nand_dev(pdev);
- struct aml_nand_platform *plat = NULL;
- int err = 0, i;
- dev_dbg(&pdev->dev, "(%p)\n", pdev);
-
- if (!aml_nand_dev) {
- dev_err(&pdev->dev, "no platform specific information\n");
- err = -ENOMEM;
- goto exit_error;
- }
- platform_set_drvdata(pdev, aml_nand_dev);
- printk("%d\n",aml_nand_dev->dev_num);
- spin_lock_init(&controller.lock);
- init_waitqueue_head(&controller.wq);
- aml_nand_dev->nb.notifier_call = m3_nand_reboot_notifier;
- register_reboot_notifier(&aml_nand_dev->nb);
- atomic_notifier_chain_register(&panic_notifier_list, &aml_nand_dev->nb);
- for (i=0; i<aml_nand_dev->dev_num; i++) {
- plat = &aml_nand_dev->aml_nand_platform[i];
- if (!plat) {
- printk("error for not platform data\n");
- continue;
- }
- err = aml_nand_probe(plat, &pdev->dev);
- if (err) {
- printk("%s dev probe failed %d\n", plat->name, err);
- continue;
- }
- }
- exit_error:
- return err;
- }
- static int m3_nand_remove(struct platform_device *pdev)
- {
- struct aml_nand_device *aml_nand_dev = to_nand_dev(pdev);
- struct aml_nand_platform *plat = NULL;
- struct aml_nand_chip *aml_chip = NULL;
- struct mtd_info *mtd = NULL;
- int i;
- platform_set_drvdata(pdev, NULL);
- for (i=0; i<aml_nand_dev->dev_num; i++) {
- plat = &aml_nand_dev->aml_nand_platform[i];
- aml_chip = plat->aml_chip;
- if (aml_chip) {
- mtd = &aml_chip->mtd;
-
- if (mtd) {
- #ifdef NEW_NAND_SUPPORT
- if((aml_chip->new_nand_info.type) && (aml_chip->new_nand_info.type < 10) && (i == 1)){
- aml_chip->new_nand_info.slc_program_info.exit_enslc_mode(mtd);
- aml_chip->new_nand_info.read_rety_info.set_default_value(mtd);
- }
- #endif
- nand_release(mtd);
- kfree(mtd);
- }
- kfree(aml_chip);
- }
- }
- return 0;
- }
- static void m3_nand_shutdown(struct platform_device *pdev)
- {
- struct aml_nand_device *aml_nand_dev = to_nand_dev(pdev);
- struct aml_nand_platform *plat = NULL;
- struct aml_nand_chip *aml_chip = NULL;
- struct mtd_info *mtd = NULL;
- int i;
- for (i=1; i<aml_nand_dev->dev_num; i++) {
- plat = &aml_nand_dev->aml_nand_platform[i];
- aml_chip = plat->aml_chip;
- if (aml_chip) {
- mtd = &aml_chip->mtd;
- #ifdef NEW_NAND_SUPPORT
- if (mtd) {
- if((aml_chip->new_nand_info.type) && (aml_chip->new_nand_info.type < 10)){
- aml_chip->new_nand_info.slc_program_info.exit_enslc_mode(mtd);
- aml_chip->new_nand_info.read_rety_info.set_default_value(mtd);
- }
- }
- #endif
- }
- }
- return;
- }
- #define DRV_NAME "aml_nand"
- #define DRV_VERSION "1.1"
- #define DRV_AUTHOR "xiaojun_yoyo"
- #define DRV_DESC "Amlogic nand flash AVOS driver for M3"
- /* driver device registration */
- static struct platform_driver m3_nand_driver = {
- .probe = m3_nand_probe,
- .remove = m3_nand_remove,
- .shutdown = m3_nand_shutdown,
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
- };
- static int __init m3_nand_init(void)
- {
- printk(KERN_INFO "%s, Version %s (c) 2010 Amlogic Inc.\n", DRV_DESC, DRV_VERSION);
- return platform_driver_register(&m3_nand_driver);
- }
- static void __exit m3_nand_exit(void)
- {
- platform_driver_unregister(&m3_nand_driver);
- }
- module_init(m3_nand_init);
- module_exit(m3_nand_exit);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR(DRV_AUTHOR);
- MODULE_DESCRIPTION(DRV_DESC);
- MODULE_ALIAS("platform:" DRV_NAME);
|