12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502 |
- /*
- * drv_sfc.c
- *
- * Created on: 2016Äê4ÔÂ5ÈÕ
- * Author: Urey
- */
- /*********************************************************************************************************
- ** Include Files
- *********************************************************************************************************/
- #include <rthw.h>
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <cache.h>
- #include <sys/types.h>
- #include "board.h"
- #include "drv_clock.h"
- #include "drv_gpio.h"
- #include "drv_sfc.h"
- //#define SFC_DEBUG
- #if defined(SFC_DEBUG)
- #define SFC_DBG(...) rt_kprintf("[SFC]"),rt_kprintf(__VA_ARGS__)
- #else
- #define SFC_DBG(...)
- #endif
- #define L2CACHE_ALIGN_SIZE 256
- #define THRESHOLD 32
- #define PAGE_SIZE 4096
- /* Max time can take up to 3 seconds! */
- #define MAX_READY_WAIT_TIME 3000 /* the time of erase BE(64KB) */
- #define STATUS_SUSPND (1<<0)
- #define tCHSH 5 //hold
- #define tSLCH 5 //setup
- #define tSHSL_RD 20 //interval
- #define tSHSL_WR 30
- static void sfc_writel(struct sfc *sfc, uint16_t offset, u32 value)
- {
- writel(value, (uint32_t)sfc->iomem + offset);
- }
- static uint32_t sfc_readl(struct sfc *sfc, uint16_t offset)
- {
- return readl((uint32_t)sfc->iomem + offset);
- }
- static void sfc_init(struct sfc *sfc)
- {
- uint32_t n;
- for (n = 0; n < N_MAX; n++)
- {
- sfc_writel(sfc, SFC_TRAN_CONF(n), 0);
- sfc_writel(sfc, SFC_DEV_ADDR(n), 0);
- sfc_writel(sfc, SFC_DEV_ADDR_PLUS(n), 0);
- }
- //sfc_writel(sfc, SFC_GLB, ((1 << 7) | (1 << 3)));
- sfc_writel(sfc, SFC_DEV_CONF, 0);
- sfc_writel(sfc, SFC_DEV_STA_EXP, 0);
- sfc_writel(sfc, SFC_DEV_STA_MSK, 0);
- sfc_writel(sfc, SFC_TRAN_LEN, 0);
- sfc_writel(sfc, SFC_MEM_ADDR, 0);
- sfc_writel(sfc, SFC_TRIG, 0);
- sfc_writel(sfc, SFC_SCR, 0);
- sfc_writel(sfc, SFC_INTC, 0);
- sfc_writel(sfc, SFC_CGE, 0);
- sfc_writel(sfc, SFC_RM_DR, 0);
- }
- static void sfc_stop(struct sfc*sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRIG);
- tmp |= TRIG_STOP;
- sfc_writel(sfc, SFC_TRIG, tmp);
- }
- static void sfc_start(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRIG);
- tmp |= TRIG_START;
- sfc_writel(sfc, SFC_TRIG, tmp);
- }
- static void sfc_flush_fifo(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRIG);
- tmp |= TRIG_FLUSH;
- sfc_writel(sfc, SFC_TRIG, tmp);
- }
- static void sfc_ce_invalid_value(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_CEDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= DEV_CONF_CEDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_hold_invalid_value(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_HOLDDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= DEV_CONF_HOLDDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_wp_invalid_value(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_WPDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= DEV_CONF_WPDL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_clear_end_intc(struct sfc *sfc)
- {
- uint32_t tmp = 0;
- tmp = sfc_readl(sfc, SFC_SCR);
- tmp |= CLR_END;
- sfc_writel(sfc, SFC_SCR, tmp);
- tmp = sfc_readl(sfc, SFC_SCR);
- }
- static void sfc_clear_treq_intc(struct sfc *sfc)
- {
- uint32_t tmp = 0;
- tmp = sfc_readl(sfc, SFC_SCR);
- tmp |= CLR_TREQ;
- sfc_writel(sfc, SFC_SCR, tmp);
- }
- static void sfc_clear_rreq_intc(struct sfc *sfc)
- {
- uint32_t tmp = 0;
- tmp = sfc_readl(sfc, SFC_SCR);
- tmp |= CLR_RREQ;
- sfc_writel(sfc, SFC_SCR, tmp);
- }
- static void sfc_clear_over_intc(struct sfc *sfc)
- {
- uint32_t tmp = 0;
- tmp = sfc_readl(sfc, SFC_SCR);
- tmp |= CLR_OVER;
- sfc_writel(sfc, SFC_SCR, tmp);
- }
- static void sfc_clear_under_intc(struct sfc *sfc)
- {
- uint32_t tmp = 0;
- tmp = sfc_readl(sfc, SFC_SCR);
- tmp |= CLR_UNDER;
- sfc_writel(sfc, SFC_SCR, tmp);
- }
- static void sfc_clear_all_intc(struct sfc *sfc)
- {
- sfc_writel(sfc, SFC_SCR, 0x1f);
- }
- static void sfc_mask_all_intc(struct sfc *sfc)
- {
- sfc_writel(sfc, SFC_INTC, 0x1f);
- }
- static void sfc_mode(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~(TRAN_CONF_TRAN_MODE_MSK << TRAN_CONF_TRAN_MODE_OFFSET);
- tmp |= (value << TRAN_CONF_TRAN_MODE_OFFSET);
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- static void sfc_set_phase_num(struct sfc *sfc,uint32_t num)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp &= ~GLB_PHASE_NUM_MSK;
- tmp |= num << GLB_PHASE_NUM_OFFSET;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- static void sfc_clock_phase(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_CPHA;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= DEV_CONF_CPHA;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_clock_polarity(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_CPOL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= DEV_CONF_CPOL;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_threshold(struct sfc *sfc, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp &= ~GLB_THRESHOLD_MSK;
- tmp |= value << GLB_THRESHOLD_OFFSET;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- static void sfc_smp_delay(struct sfc *sfc, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_SMP_DELAY_MSK;
- tmp |= value << DEV_CONF_SMP_DELAY_OFFSET;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- static void sfc_hold_delay(struct sfc *sfc, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_THOLD_MSK;
- tmp |= value << DEV_CONF_THOLD_OFFSET;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- static void sfc_setup_delay(struct sfc *sfc, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_TSETUP_MSK;
- tmp |= value << DEV_CONF_TSETUP_OFFSET;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- static void sfc_interval_delay(struct sfc *sfc, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~DEV_CONF_TSH_MSK;
- tmp |= value << DEV_CONF_TSH_OFFSET;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- static void sfc_set_cmd_length(struct sfc *sfc, uint32_t value)
- {
- if (value == 1)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp &= ~TRAN_CONF_CMD_LEN;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_DEV_CONF);
- tmp |= TRAN_CONF_CMD_LEN;
- sfc_writel(sfc, SFC_DEV_CONF, tmp);
- }
- }
- static void sfc_transfer_direction(struct sfc *sfc, uint32_t value)
- {
- if (value == GLB_TRAN_DIR_READ)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp &= ~GLB_TRAN_DIR;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp |= GLB_TRAN_DIR;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- }
- static int set_flash_timing(struct sfc *sfc, uint32_t t_hold, uint32_t t_setup, uint32_t t_shslrd, uint32_t t_shslwr)
- {
- uint32_t c_hold;
- uint32_t c_setup;
- uint32_t t_in, c_in, val;
- uint64_t cycle;
- cycle = 1000000000UL / sfc->src_clk;
- c_hold = t_hold / cycle;
- if (c_hold > 0)
- val = c_hold - 1;
- sfc_hold_delay(sfc, val);
- c_setup = t_setup / cycle;
- if(c_setup > 0)
- val = c_setup - 1;
- sfc_setup_delay(sfc, val);
- t_in = max(t_shslrd, t_shslwr);
- c_in = t_in / cycle;
- if(c_in > 0)
- val = c_in - 1;
- sfc_interval_delay(sfc, val);
- return 0;
- }
- static void sfc_set_length(struct sfc *sfc, uint32_t value)
- {
- sfc_writel(sfc, SFC_TRAN_LEN, value);
- }
- static void sfc_transfer_mode(struct sfc *sfc, uint32_t value)
- {
- if (value == 0)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp &= ~GLB_OP_MODE;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_GLB);
- tmp |= GLB_OP_MODE;
- sfc_writel(sfc, SFC_GLB, tmp);
- }
- }
- static void sfc_read_data(struct sfc *sfc, uint32_t *value)
- {
- *value = sfc_readl(sfc, SFC_RM_DR);
- }
- static void sfc_write_data(struct sfc *sfc, const uint32_t value)
- {
- sfc_writel(sfc, SFC_RM_DR, value);
- }
- uint32_t sfc_fifo_num(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- tmp &= (0x7f << 16);
- tmp = tmp >> 16;
- return tmp;
- }
- static uint32_t cpu_read_rxfifo(struct sfc *sfc)
- {
- uint32_t i;
- uint32_t align_len = 0;
- uint32_t fifo_num = 0;
- uint32_t data[1] = {0};
- uint32_t last_word = 0;
- align_len = RT_ALIGN(sfc->transfer->len, 4);
- if (((align_len - sfc->transfer->cur_len) / 4) > THRESHOLD)
- {
- fifo_num = THRESHOLD;
- last_word = 0;
- }
- else
- {
- /* last aligned THRESHOLD data*/
- if (sfc->transfer->len % 4)
- {
- fifo_num = (align_len - sfc->transfer->cur_len) / 4 - 1;
- last_word = 1;
- }
- else
- {
- fifo_num = (align_len - sfc->transfer->cur_len) / 4;
- last_word = 0;
- }
- }
- for (i = 0; i < fifo_num; i++)
- {
- sfc_read_data(sfc, (uint32_t *) sfc->transfer->data);
- sfc->transfer->data += 4;
- sfc->transfer->cur_len += 4;
- }
- /* last word */
- if (last_word == 1)
- {
- sfc_read_data(sfc, data);
- rt_memcpy((void *) sfc->transfer->data, data, sfc->transfer->len % 4);
- sfc->transfer->data += sfc->transfer->len % 4;
- sfc->transfer->cur_len += 4;
- }
- return 0;
- }
- static uint32_t cpu_write_txfifo(struct sfc *sfc)
- {
- uint32_t i;
- uint32_t align_len = 0;
- uint32_t fifo_num = 0;
- align_len = RT_ALIGN(sfc->transfer->len , 4);
- if (((align_len - sfc->transfer->cur_len) / 4) > THRESHOLD){
- fifo_num = THRESHOLD;
- } else {
- fifo_num = (align_len - sfc->transfer->cur_len) / 4;
- }
- for(i = 0; i < fifo_num; i++) {
- sfc_write_data(sfc, *(uint32_t *)sfc->transfer->data);
- sfc->transfer->data += 4;
- sfc->transfer->cur_len += 4;
- }
- return 0;
- }
- static int ssi_underrun(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- if(tmp & CLR_UNDER)
- return 1;
- else
- return 0;
- }
- static int ssi_overrun(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- if(tmp & CLR_OVER)
- return 1;
- else
- return 0;
- }
- static int rxfifo_rreq(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- if(tmp & CLR_RREQ)
- return 1;
- else
- return 0;
- }
- static int txfifo_treq(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- if(tmp & CLR_TREQ)
- return 1;
- else
- return 0;
- }
- static int sfc_end(struct sfc *sfc)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_SR);
- if(tmp & CLR_END)
- return 1;
- else
- return 0;
- }
- static uint32_t sfc_get_sta_rt(struct sfc *sfc)
- {
- return sfc_readl(sfc,SFC_DEV_STA_RT);
- }
- static uint32_t sfc_get_fsm(struct sfc *sfc)
- {
- return sfc_readl(sfc,SFC_FSM);
- }
- static void sfc_set_addr_length(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~(ADDR_WIDTH_MSK);
- tmp |= (value << ADDR_WIDTH_OFFSET);
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- static void sfc_cmd_enble(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- if (value == ENABLE)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp |= TRAN_CONF_CMDEN;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~TRAN_CONF_CMDEN;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- }
- static void sfc_data_en(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- if (value == 1)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp |= TRAN_CONF_DATEEN;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~TRAN_CONF_DATEEN;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- }
- static void sfc_phase_format(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- if (value == 1)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp |= TRAN_CONF_FMAT;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- else
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~TRAN_CONF_FMAT;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- }
- static void sfc_write_cmd(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~TRAN_CONF_CMD_MSK;
- tmp |= value;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- static void sfc_dev_addr(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- sfc_writel(sfc, SFC_DEV_ADDR(channel), value);
- }
- static void sfc_dev_data_dummy_bytes(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- tmp &= ~TRAN_CONF_DMYBITS_MSK;
- tmp |= value << DMYBITS_OFFSET;
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- static void sfc_dev_addr_plus(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- sfc_writel(sfc, SFC_DEV_ADDR_PLUS(channel), value);
- }
- static void sfc_dev_pollen(struct sfc *sfc, uint32_t channel, uint32_t value)
- {
- uint32_t tmp;
- tmp = sfc_readl(sfc, SFC_TRAN_CONF(channel));
- if(value == 1)
- tmp |= TRAN_CONF_POLLEN;
- else
- tmp &= ~(TRAN_CONF_POLLEN);
- sfc_writel(sfc, SFC_TRAN_CONF(channel), tmp);
- }
- static void sfc_dev_sta_exp(struct sfc *sfc, uint32_t value)
- {
- sfc_writel(sfc, SFC_DEV_STA_EXP, value);
- }
- static void sfc_dev_sta_msk(struct sfc *sfc, uint32_t value)
- {
- sfc_writel(sfc, SFC_DEV_STA_MSK, value);
- }
- static void sfc_enable_all_intc(struct sfc *sfc)
- {
- sfc_writel(sfc, SFC_INTC, 0);
- }
- static void sfc_set_mem_addr(struct sfc *sfc,uint32_t addr )
- {
- sfc_writel(sfc, SFC_MEM_ADDR, addr);
- }
- static int sfc_start_transfer(struct sfc *sfc)
- {
- int err;
- sfc_clear_all_intc(sfc);
- sfc_enable_all_intc(sfc);
- sfc_start(sfc);
- err = rt_completion_wait(&sfc->done,RT_TICK_PER_SECOND * 10);
- if (RT_EOK != err)
- {
- sfc_mask_all_intc(sfc);
- sfc_clear_all_intc(sfc);
- SFC_DBG("line:%d Timeout for ACK from SFC device\n", __LINE__);
- return -RT_ETIMEOUT;
- }
- return 0;
- }
- static void sfc_phase_transfer(struct sfc *sfc,struct sfc_transfer * transfer,uint32_t channel)
- {
- sfc_flush_fifo(sfc);
- sfc_set_addr_length(sfc,channel,transfer->addr_len);
- sfc_cmd_enble(sfc,channel,ENABLE);
- sfc_write_cmd(sfc,channel,transfer->cmd_info->cmd);
- sfc_dev_data_dummy_bytes(sfc,channel,transfer->data_dummy_bits);
- sfc_data_en(sfc,channel,transfer->cmd_info->dataen);
- sfc_dev_addr(sfc, channel,transfer->addr);
- sfc_dev_addr_plus(sfc,channel,transfer->addr_plus);
- sfc_mode(sfc,channel,transfer->sfc_mode);
- sfc_phase_format(sfc,channel,0);/*default 0,dummy bits is blow the addr*/
- }
- static void common_cmd_request_transfer(struct sfc *sfc,struct sfc_transfer *transfer,uint32_t channel)
- {
- sfc_phase_transfer(sfc,transfer,channel);
- sfc_dev_sta_exp(sfc,0);
- sfc_dev_sta_msk(sfc,0);
- sfc_dev_pollen(sfc,channel,DISABLE);
- }
- static void poll_cmd_request_transfer(struct sfc *sfc,struct sfc_transfer *transfer,uint32_t channel)
- {
- struct cmd_info *cmd = transfer->cmd_info;
- sfc_phase_transfer(sfc,transfer,channel);
- sfc_dev_sta_exp(sfc,cmd->sta_exp);
- sfc_dev_sta_msk(sfc,cmd->sta_msk);
- sfc_dev_pollen(sfc,channel,ENABLE);
- }
- static void sfc_glb_info_config(struct sfc *sfc,struct sfc_transfer *transfer)
- {
- sfc_transfer_direction(sfc, transfer->direction);
- if ((transfer->ops_mode == DMA_OPS))
- {
- sfc_set_length(sfc, transfer->len);
- if (transfer->direction == GLB_TRAN_DIR_READ)
- r4k_dma_cache_sync((uint32_t) transfer->data, transfer->len,
- DMA_FROM_DEVICE);
- else
- r4k_dma_cache_sync((uint32_t) transfer->data, transfer->len,
- DMA_TO_DEVICE);
- sfc_set_mem_addr(sfc, PHYS(transfer->data));
- sfc_transfer_mode(sfc, DMA_MODE);
- }
- else
- {
- sfc_set_length(sfc, transfer->len);
- sfc_set_mem_addr(sfc, 0);
- sfc_transfer_mode(sfc, SLAVE_MODE);
- }
- }
- #ifdef DEBUG
- static void dump_transfer(struct sfc_transfer *xfer,uint32_t num)
- {
- rt_kprintf("\n");
- rt_kprintf("cmd[%d].cmd = 0x%02x\n",num,xfer->cmd_info->cmd);
- rt_kprintf("cmd[%d].addr_len = %d\n",num,xfer->addr_len);
- rt_kprintf("cmd[%d].dummy_byte = %d\n",num,xfer->data_dummy_bits);
- rt_kprintf("cmd[%d].dataen = %d\n",num,xfer->cmd_info->dataen);
- rt_kprintf("cmd[%d].sta_exp = %d\n",num,xfer->cmd_info->sta_exp);
- rt_kprintf("cmd[%d].sta_msk = %d\n",num,xfer->cmd_info->sta_msk);
- rt_kprintf("transfer[%d].addr = 0x%08x\n",num,xfer->addr);
- rt_kprintf("transfer[%d].len = %d\n",num,xfer->len);
- rt_kprintf("transfer[%d].data = 0x%p\n",num,xfer->data);
- rt_kprintf("transfer[%d].direction = %d\n",num,xfer->direction);
- rt_kprintf("transfer[%d].sfc_mode = %d\n",num,xfer->sfc_mode);
- rt_kprintf("transfer[%d].ops_mode = %d\n",num,xfer->ops_mode);
- }
- #endif
- static int sfc_sync(struct sfc *sfc, struct sfc_message *message)
- {
- struct sfc_transfer *xfer;
- int phase_num = 0,ret = 0;
- sfc_set_length(sfc, 0);
-
- rt_list_for_each_entry(xfer, &message->transfers, transfer_list)
- {
- if (xfer->cmd_info->sta_msk == 0)
- {
- common_cmd_request_transfer(sfc, xfer, phase_num);
- }
- else
- {
- poll_cmd_request_transfer(sfc, xfer, phase_num);
- }
- if (xfer->addr_len || xfer->len)
- sfc_glb_info_config(sfc, xfer);
- phase_num++;
- message->actual_length += xfer->len;
- if (xfer->len > 0)
- sfc->transfer = xfer;
- }
- sfc_set_phase_num(sfc,phase_num);
- ret = sfc_start_transfer(sfc);
- rt_list_remove(&message->transfers);
- return ret;
- }
- static void sfc_transfer_del(struct sfc_transfer *t)
- {
- rt_list_remove(&t->transfer_list);
- }
- static void sfc_message_add_tail(struct sfc_transfer *t, struct sfc_message *m)
- {
- rt_list_insert_before(&m->transfers, &t->transfer_list);
- }
- static void sfc_message_init(struct sfc_message *m)
- {
- rt_memset(m, 0, sizeof *m);
- rt_list_init(&m->transfers);
- }
- static void jz_sfc_pio_irq(int vector,void *param)
- {
- struct sfc *sfc = (struct sfc *)param;
- if (ssi_underrun(sfc))
- {
- sfc_clear_under_intc(sfc);
- rt_completion_done(&sfc->done);
- return ;
- }
- if (ssi_overrun(sfc))
- {
- sfc_clear_over_intc(sfc);
- rt_completion_done(&sfc->done);
- return ;
- }
- if (rxfifo_rreq(sfc))
- {
- sfc_clear_rreq_intc(sfc);
- cpu_read_rxfifo(sfc);
- return ;
- }
- if (txfifo_treq(sfc))
- {
- sfc_clear_treq_intc(sfc);
- cpu_write_txfifo(sfc);
- return ;
- }
- if (sfc_end(sfc))
- {
- sfc_mask_all_intc(sfc);
- sfc_clear_end_intc(sfc);
- rt_completion_done(&sfc->done);
- return ;
- }
- }
- static int jz_sfc_init_setup(struct sfc *sfc)
- {
- sfc_init(sfc);
- sfc_stop(sfc);
- /*set hold high*/
- sfc_hold_invalid_value(sfc, 1);
- /*set wp high*/
- sfc_wp_invalid_value(sfc, 1);
- sfc_clear_all_intc(sfc);
- sfc_mask_all_intc(sfc);
- sfc_threshold(sfc, sfc->threshold);
- /*config the sfc pin init state*/
- sfc_clock_phase(sfc, 0);
- sfc_clock_polarity(sfc, 0);
- sfc_ce_invalid_value(sfc, 1);
- sfc_transfer_mode(sfc, SLAVE_MODE);
- if (sfc->src_clk >= 100000000)
- {
- sfc_smp_delay(sfc, DEV_CONF_HALF_CYCLE_DELAY);
- }
- return 0;
- }
- static struct sfc* jz_sfc_init(void)
- {
- struct sfc *sfc = (struct sfc *)rt_malloc(sizeof(struct sfc));
- if(sfc == RT_NULL)
- return RT_NULL;
- sfc->iomem = (void *)SFC_BASE;
- sfc->irq = IRQ_SFC;
- sfc->clk = clk_get("cgu_ssi");
- sfc->clk_gate = clk_get("sfc");
- sfc->src_clk = 100000000L;
- if(clk_get_rate(sfc->clk) >= sfc->src_clk)
- clk_set_rate(sfc->clk, sfc->src_clk);
- else
- clk_set_rate(sfc->clk, sfc->src_clk);
- clk_enable(sfc->clk);
- clk_enable(sfc->clk_gate);
- sfc->threshold = THRESHOLD;
- /* Init IPC */
- rt_completion_init(&(sfc->done));
- /* Request SFC IRQ */
- rt_hw_interrupt_install(sfc->irq,jz_sfc_pio_irq,sfc,"SFC");
- rt_hw_interrupt_umask(sfc->irq);
- /* SFC controller initializations for SFC */
- jz_sfc_init_setup(sfc);
- rt_completion_init(&sfc->done);
- return sfc;
- }
- static int sfc_flash_read_id(struct sfc_flash *flash, uint8_t command, uint32_t addr, uint32_t addr_len, size_t len, uint32_t dummy_byte)
- {
- struct sfc_transfer transfer;
- struct sfc_message message;
- struct cmd_info cmd;
- int ret;
- uint32_t chip_id = 0;
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = command;
- cmd.dataen = ENABLE;
- transfer.addr_len = addr_len;
- transfer.data_dummy_bits = dummy_byte;
- transfer.addr = addr;
- transfer.len = len;
- transfer.data =(uint8_t *)&chip_id;
- transfer.ops_mode = CPU_OPS;
- transfer.sfc_mode = TM_STD_SPI;
- transfer.direction = GLB_TRAN_DIR_READ;
- transfer.cmd_info = &cmd;
- sfc_message_add_tail(&transfer, &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- return chip_id & 0x00ffffff;
- }
- static uint32_t sfc_flash_do_read(struct sfc_flash *flash,uint8_t command,uint32_t addr,uint32_t addr_len,uint8_t *buf,size_t len,uint32_t dummy_byte)
- {
- struct sfc_transfer transfer;
- struct sfc_message message;
- struct cmd_info cmd;
- int ret;
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = command;
- cmd.dataen = ENABLE;
- transfer.addr_len = addr_len;
- transfer.data_dummy_bits = dummy_byte;
- transfer.addr = addr;
- transfer.len = len;
- transfer.data = buf;
- transfer.cur_len = 0;
- if(len >= L2CACHE_ALIGN_SIZE)
- transfer.ops_mode = DMA_OPS;
- else
- transfer.ops_mode = CPU_OPS;
- transfer.sfc_mode = flash->sfc_mode;
- transfer.direction = GLB_TRAN_DIR_READ;
- transfer.cmd_info = &cmd;
- sfc_message_add_tail(&transfer, &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- /*fix the cache line problem,when use jffs2 filesystem must be flush cache twice*/
- if(transfer.ops_mode == DMA_OPS)
- r4k_dma_cache_sync((rt_base_t)buf, len, DMA_FROM_DEVICE);
- return message.actual_length;
- }
- static unsigned int sfc_flash_do_write(struct sfc_flash *flash,uint8_t command,uint32_t addr,uint32_t addr_len,const uint8_t *buf,size_t len,uint32_t dummy_byte)
- {
- struct sfc_transfer transfer[3];
- struct sfc_message message;
- struct cmd_info cmd[3];
- int ret;
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- /* write enable */
- cmd[0].cmd = CMD_WREN;
- cmd[0].dataen = DISABLE;
- transfer[0].cmd_info = &cmd[0];
- transfer[0].sfc_mode = flash->sfc_mode;
- sfc_message_add_tail(&transfer[0], &message);
- /* write ops */
- cmd[1].cmd = command;
- cmd[1].dataen = ENABLE;
- transfer[1].addr = addr;
- transfer[1].addr_len = addr_len;
- transfer[1].len = len;
- transfer[1].cur_len = 0;
- transfer[1].data_dummy_bits = dummy_byte;
- transfer[1].data = buf;
- if(len >= L2CACHE_ALIGN_SIZE)
- transfer[1].ops_mode = DMA_OPS;
- else
- transfer[1].ops_mode = CPU_OPS;
- transfer[1].sfc_mode = flash->sfc_mode;
- transfer[1].direction = GLB_TRAN_DIR_WRITE;
- transfer[1].cmd_info = &cmd[1];
- sfc_message_add_tail(&transfer[1], &message);
- cmd[2].cmd = CMD_RDSR;
- cmd[2].dataen = DISABLE;
- cmd[2].sta_exp = 0;
- cmd[2].sta_msk = 0x1;
- transfer[2].cmd_info = &cmd[2];
- sfc_message_add_tail(&transfer[2], &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- return message.actual_length;
- }
- #ifdef SFC_USE_QUAD
- static int sfc_flash_set_quad_mode(struct sfc_flash *flash)
- {
- uint8_t command;
- uint32_t sent_data,len,dummy_byte;
- int ret;
- struct sfc_transfer transfer[3];
- struct sfc_message message;
- struct cmd_info cmd[3];
- if (flash->quad_mode == NULL)
- {
- SFC_DBG("quad info is null, use standard spi mode\n");
- flash->sfc_mode = TM_STD_SPI;
- return -1;
- }
- command = flash->quad_mode->WRSR_CMD;
- sent_data = flash->quad_mode->WRSR_DATE;
- len = flash->quad_mode->WD_DATE_SIZE;
- dummy_byte = flash->quad_mode->dummy_byte;
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- /* write enable */
- cmd[0].cmd = CMD_WREN;
- cmd[0].dataen = DISABLE;
- transfer[0].cmd_info = &cmd[0];
- transfer[0].sfc_mode = TM_STD_SPI;
- sfc_message_add_tail(&transfer[0], &message);
- /* write ops */
- cmd[1].cmd = command;
- cmd[1].dataen = ENABLE;
- transfer[1].len = len;
- transfer[1].data = (const uint8_t *)&sent_data;
- transfer[1].data_dummy_bits = dummy_byte;
- transfer[1].ops_mode = CPU_OPS;
- transfer[1].sfc_mode = TM_STD_SPI;
- transfer[1].direction = GLB_TRAN_DIR_WRITE;
- transfer[1].cmd_info = &cmd[1];
- sfc_message_add_tail(&transfer[1], &message);
- cmd[2].cmd = flash->quad_mode->RDSR_CMD;
- cmd[2].dataen = DISABLE;
- cmd[2].sta_exp = 0x2;
- cmd[2].sta_msk = 0x2;
- transfer[2].data_dummy_bits = 0;
- transfer[2].cmd_info = &cmd[2];
- sfc_message_add_tail(&transfer[2], &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- flash->sfc_mode = TM_STD_SPI;
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- else
- {
- flash->sfc_mode = flash->quad_mode->sfc_mode;
- }
- return 0;
- }
- #endif
- static int sfc_flash_write(struct sfc_flash *flash, rt_off_t to, size_t len, const uint8_t *buf)
- {
- uint8_t command;
- int dummy_byte = 0;
- uint32_t s_len = 0, f_len = 0, a_len = 0;
- #ifdef SFC_USE_QUAD
- if((flash->sfc_mode == TM_QI_QO_SPI) || (flash->sfc_mode == TM_QIO_SPI) || (flash->sfc_mode == TM_FULL_QIO_SPI))
- {
- command = CMD_PP;
- }
- else
- {
- command = CMD_PP;
- }
- #else
- command = CMD_PP;
- #endif
- if (len > L2CACHE_ALIGN_SIZE)
- {
- s_len = RT_ALIGN((uint32_t )buf, L2CACHE_ALIGN_SIZE) - (uint32_t)buf;
- if (s_len)
- {
- sfc_flash_do_write(flash, command, (uint32_t) to, flash->addrsize, buf, s_len, dummy_byte);
- }
- a_len = (len - s_len) - (len - s_len) % L2CACHE_ALIGN_SIZE;
- if (a_len)
- {
- sfc_flash_do_write(flash, command, (uint32_t) to + s_len,
- flash->addrsize, &buf[s_len], a_len, dummy_byte);
- }
- f_len = len - s_len - a_len;
- if (f_len)
- {
- sfc_flash_do_write(flash, command, (uint32_t) to + s_len + a_len,
- flash->addrsize, &buf[s_len + a_len], f_len,
- dummy_byte);
- }
- }
- else
- {
- sfc_flash_do_write(flash, command, (uint32_t) to, flash->addrsize,
- buf, len, dummy_byte);
- }
- return len;
- }
- static int sfc_flash_read_cacheline_align(struct sfc_flash *flash,uint8_t command,uint32_t addr,int addr_len,uint8_t *buf,size_t len,int dummy_byte)
- {
- uint32_t ret = 0;
- uint32_t s_len = 0, f_len = 0, a_len = 0;
- /**
- * s_len : start not align length
- * a_len : middle align length
- * f_len : end not align length
- */
- if (len > L2CACHE_ALIGN_SIZE)
- {
- s_len = RT_ALIGN((uint32_t )buf, L2CACHE_ALIGN_SIZE) - (uint32_t)buf;
- if (s_len)
- {
- ret += sfc_flash_do_read(flash, command, (uint32_t) addr,
- flash->addrsize, buf, s_len, dummy_byte);
- }
- a_len = (len - s_len) - (len - s_len) % L2CACHE_ALIGN_SIZE;
- if (a_len)
- {
- ret += sfc_flash_do_read(flash, command, (uint32_t) addr + s_len,
- flash->addrsize, &buf[s_len], a_len,
- dummy_byte);
- }
- f_len = len - s_len - a_len;
- if (f_len)
- {
- ret += sfc_flash_do_read(flash, command,
- (uint32_t) addr + s_len + a_len,
- flash->addrsize, &buf[s_len + a_len], f_len,
- dummy_byte);
- }
- } else {
- ret = sfc_flash_do_read(flash, command, (uint32_t)addr, flash->addrsize, buf, len, dummy_byte);
- }
- return ret;
- }
- static int sfc_flash_read(struct sfc_flash *flash, rt_off_t from, size_t len, uint8_t *buf)
- {
- uint8_t command;
- int dummy_byte;
- int tmp_len = 0, current_len = 0;
- #ifdef SFC_USE_QUAD
- if((flash->sfc_mode == TM_QI_QO_SPI) || (flash->sfc_mode == TM_QIO_SPI) || (flash->sfc_mode == TM_FULL_QIO_SPI))
- {
- command = flash->quad_mode->cmd_read;
- dummy_byte = flash->quad_mode->dummy_byte;
- }
- else
- {
- command = CMD_READ;
- dummy_byte = 0;
- }
- #else
- command = CMD_READ;
- dummy_byte = 0;
- #endif
- while (len)
- {
- tmp_len = sfc_flash_read_cacheline_align(flash, command,
- (uint32_t) from + current_len,
- flash->addrsize,
- &buf[current_len], len, dummy_byte);
- current_len += tmp_len;
- len -= tmp_len;
- }
- return current_len;
- }
- int sfc_norflash_set_addr_width_4byte(struct sfc_flash *flash,int on)
- {
- struct sfc_transfer transfer;
- struct sfc_message message;
- struct cmd_info cmd;
- int ret;
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = CMD_EN4B;
- cmd.dataen = DISABLE;
- transfer.data_dummy_bits = 0;
- transfer.cmd_info = &cmd;
- sfc_message_add_tail(&transfer, &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- return 0;
- }
- size_t sfc_norflash_read(struct sfc_flash *flash, rt_off_t from, uint8_t *buf, size_t len)
- {
- size_t retlen;
- rt_mutex_take(&flash->lock,RT_WAITING_FOREVER);
- retlen = sfc_flash_read(flash, from, len, buf);
- rt_mutex_release(&flash->lock);
- return retlen;
- }
- int sfc_norflash_read_params(struct sfc_flash *flash, rt_off_t from, size_t len, uint8_t *buf)
- {
- struct sfc_transfer transfer;
- struct sfc_message message;
- struct cmd_info cmd;
- uint8_t command;
- int dummy_byte = 0,ret;
- command = CMD_READ;
- rt_mutex_take(&flash->lock,RT_WAITING_FOREVER);
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- cmd.cmd = command;
- cmd.dataen = ENABLE;
- transfer.addr = (uint32_t)from;
- transfer.len = len;
- transfer.data = buf;
- transfer.addr_len = DEFAULT_ADDRSIZE;
- transfer.data_dummy_bits = dummy_byte;
- transfer.ops_mode = CPU_OPS;
- transfer.direction = GLB_TRAN_DIR_READ;
- transfer.sfc_mode = TM_STD_SPI;
- transfer.cmd_info = &cmd;
- sfc_message_add_tail(&transfer, &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- /*fix the cache line problem,when use jffs2 filesystem must be flush cache twice*/
- if(transfer.ops_mode == DMA_OPS)
- r4k_dma_cache_sync((rt_ubase_t)buf,len, DMA_FROM_DEVICE);
- rt_mutex_release(&flash->lock);
- return 0;
- }
- int sfc_norflash_erase_sector(struct sfc_flash *flash, uint32_t addr)
- {
- uint8_t command;
- struct sfc_transfer transfer[3];
- struct sfc_message message;
- struct cmd_info cmd[3];
- int ret;
- rt_mutex_take(&flash->lock,RT_WAITING_FOREVER);
- sfc_message_init(&message);
- rt_memset(&transfer, 0, sizeof(transfer));
- rt_memset(&cmd, 0, sizeof(cmd));
- /* write enable */
- cmd[0].cmd = CMD_WREN;
- cmd[0].dataen = DISABLE;
- transfer[0].sfc_mode = TM_STD_SPI;
- transfer[0].cmd_info = &cmd[0];
- sfc_message_add_tail(&transfer[0], &message);
- switch (flash->erasesize)
- {
- case 0x1000:
- command = CMD_BE_4K;
- break;
- case 0x8000:
- command = CMD_BE_32K;
- break;
- case 0x10000:
- command = CMD_BE_64K;
- break;
- }
- /* erase ops */
- cmd[1].cmd = command;
- cmd[1].dataen = DISABLE;
- transfer[1].addr_len = flash->addrsize;
- transfer[1].data_dummy_bits = 0;
- transfer[1].addr = addr;
- transfer[1].sfc_mode = TM_STD_SPI;
- transfer[1].direction = GLB_TRAN_DIR_WRITE;
- transfer[1].cmd_info = &cmd[1];
- sfc_message_add_tail(&transfer[1], &message);
- cmd[2].cmd = CMD_RDSR;
- cmd[2].dataen = DISABLE;
- cmd[2].sta_exp = 0;
- cmd[2].sta_msk = 0x1;
- transfer[2].cmd_info = &cmd[2];
- sfc_message_add_tail(&transfer[2], &message);
- ret = sfc_sync(flash->sfc, &message);
- if (ret)
- {
- SFC_DBG("sfc_sync error ! %s %s %d\n", __FILE__, __func__, __LINE__);
- ret = -RT_EIO;
- }
- rt_mutex_release(&flash->lock);
- return 0;
- }
- size_t sfc_norflash_write(struct sfc_flash *flash, rt_off_t to, const uint8_t *buf, size_t len)
- {
- size_t retlen;
- u32 page_offset, actual_len;
- int ret;
- rt_mutex_take(&flash->lock,RT_WAITING_FOREVER);
- page_offset = to & (flash->pagesize - 1);
- /* do all the bytes fit onto one page? */
- if (page_offset + len <= flash->pagesize)
- {
- ret = sfc_flash_write(flash, to, len, buf);
- retlen = ret;
- }
- else
- {
- u32 i;
- /* the size of data remaining on the first page */
- actual_len = flash->pagesize - page_offset;
- ret = sfc_flash_write(flash,to,actual_len,buf);
- retlen += ret;
- /* write everything in flash->page_size chunks */
- for (i = actual_len; i < len; i += flash->writesize)
- {
- actual_len = len - i;
- if (actual_len >= flash->writesize)
- actual_len = flash->writesize;
- ret = sfc_flash_write(flash, to + i, actual_len, buf + i);
- retlen += ret;
- }
- }
- rt_mutex_release(&flash->lock);
- return retlen;
- }
- int sfc_norflash_probe(struct sfc_flash *flash)
- {
- struct sfc *sfc;
- sfc = flash->sfc = jz_sfc_init();
- if(sfc == RT_NULL)
- return -RT_EIO;
- /* GPIO Initialize (SFC FUNC1) */
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_26,GPIO_FUNC_1); //CLK
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_27,GPIO_FUNC_1); //CE
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_28,GPIO_FUNC_1); //DR
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_29,GPIO_FUNC_1); //DT
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_30,GPIO_FUNC_1); //WP
- gpio_set_func(GPIO_PORT_A,GPIO_Pin_31,GPIO_FUNC_1); //HOLD
- /* init mutex */
- if(rt_mutex_init(&(flash->lock),"norLock",RT_IPC_FLAG_FIFO) != RT_EOK)
- {
- SFC_DBG("Init mutex error\n");
- RT_ASSERT(0);
- }
- rt_mutex_take(&(flash->lock),RT_WAITING_FOREVER);
- //get ID
- {
- uint8_t command;
- int dummy_byte = 0;
- int addr_len = 0;
- int len = 3;
- int addr = 0;
- int id;
- int i;
- struct spi_nor_platform_data *flash_info;
- struct spi_board_info *binfo;
- command = CMD_RDID;
- SFC_DBG("Get ID:\n");
- id = sfc_flash_read_id(flash, command, addr, addr_len, len, dummy_byte);
- id = ((id & 0xff) << 16) | (((id >> 8) & 0xff) << 8) | ((id >> 16) & 0xff);
- SFC_DBG("id = %06x\n",id);
- flash->id = id;
- }
- #if 0
- //get UID
- {
- int i;
- sfc_flash_do_read(flash,CMD_RUID,0,3,flash->uid,8,8);
- SFC_DBG("uid = ");
- for (i = 0; i < 8; ++i) {
- SFC_DBG("%02x ",flash->uid[i]);
- }
- SFC_DBG("\n");
- }
- #endif
- rt_mutex_release(&(flash->lock));
- return 0;
- }
|