| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with
- * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c
- *
- * Copyright (C) 2005, Intec Automation Inc.
- * Copyright (C) 2014, Freescale Semiconductor, Inc.
- */
- #include <linux/cleanup.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/err.h>
- #include <linux/errno.h>
- #include <linux/math64.h>
- #include <linux/module.h>
- #include <linux/mtd/mtd.h>
- #include <linux/mtd/spi-nor.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/regulator/consumer.h>
- #include <linux/sched/task_stack.h>
- #include <linux/sizes.h>
- #include <linux/slab.h>
- #include <linux/spi/flash.h>
- #include "core.h"
- /* Define max times to check status register before we give up. */
- /*
- * For everything but full-chip erase; probably could be much smaller, but kept
- * around for safety for now
- */
- #define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ)
- /*
- * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up
- * for larger flash
- */
- #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ)
- #define SPI_NOR_MAX_ADDR_NBYTES 4
- #define SPI_NOR_SRST_SLEEP_MIN 200
- #define SPI_NOR_SRST_SLEEP_MAX 400
- /**
- * spi_nor_get_cmd_ext() - Get the command opcode extension based on the
- * extension type.
- * @nor: pointer to a 'struct spi_nor'
- * @op: pointer to the 'struct spi_mem_op' whose properties
- * need to be initialized.
- *
- * Right now, only "repeat" and "invert" are supported.
- *
- * Return: The opcode extension.
- */
- static u8 spi_nor_get_cmd_ext(const struct spi_nor *nor,
- const struct spi_mem_op *op)
- {
- switch (nor->cmd_ext_type) {
- case SPI_NOR_EXT_INVERT:
- return ~op->cmd.opcode;
- case SPI_NOR_EXT_REPEAT:
- return op->cmd.opcode;
- default:
- dev_err(nor->dev, "Unknown command extension type\n");
- return 0;
- }
- }
- /**
- * spi_nor_spimem_setup_op() - Set up common properties of a spi-mem op.
- * @nor: pointer to a 'struct spi_nor'
- * @op: pointer to the 'struct spi_mem_op' whose properties
- * need to be initialized.
- * @proto: the protocol from which the properties need to be set.
- */
- void spi_nor_spimem_setup_op(const struct spi_nor *nor,
- struct spi_mem_op *op,
- const enum spi_nor_protocol proto)
- {
- u8 ext;
- op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(proto);
- if (op->addr.nbytes)
- op->addr.buswidth = spi_nor_get_protocol_addr_nbits(proto);
- if (op->dummy.nbytes)
- op->dummy.buswidth = spi_nor_get_protocol_addr_nbits(proto);
- if (op->data.nbytes)
- op->data.buswidth = spi_nor_get_protocol_data_nbits(proto);
- if (spi_nor_protocol_is_dtr(proto)) {
- /*
- * SPIMEM supports mixed DTR modes, but right now we can only
- * have all phases either DTR or STR. IOW, SPIMEM can have
- * something like 4S-4D-4D, but SPI NOR can't. So, set all 4
- * phases to either DTR or STR.
- */
- op->cmd.dtr = true;
- op->addr.dtr = true;
- op->dummy.dtr = true;
- op->data.dtr = true;
- /* 2 bytes per clock cycle in DTR mode. */
- op->dummy.nbytes *= 2;
- ext = spi_nor_get_cmd_ext(nor, op);
- op->cmd.opcode = (op->cmd.opcode << 8) | ext;
- op->cmd.nbytes = 2;
- }
- if (proto == SNOR_PROTO_8_8_8_DTR && nor->flags & SNOR_F_SWAP16)
- op->data.swap16 = true;
- }
- /**
- * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data
- * transfer
- * @nor: pointer to 'struct spi_nor'
- * @op: pointer to 'struct spi_mem_op' template for transfer
- *
- * If we have to use the bounce buffer, the data field in @op will be updated.
- *
- * Return: true if the bounce buffer is needed, false if not
- */
- static bool spi_nor_spimem_bounce(struct spi_nor *nor, struct spi_mem_op *op)
- {
- /* op->data.buf.in occupies the same memory as op->data.buf.out */
- if (object_is_on_stack(op->data.buf.in) ||
- !virt_addr_valid(op->data.buf.in)) {
- if (op->data.nbytes > nor->bouncebuf_size)
- op->data.nbytes = nor->bouncebuf_size;
- op->data.buf.in = nor->bouncebuf;
- return true;
- }
- return false;
- }
- /**
- * spi_nor_spimem_exec_op() - execute a memory operation
- * @nor: pointer to 'struct spi_nor'
- * @op: pointer to 'struct spi_mem_op' template for transfer
- *
- * Return: 0 on success, -error otherwise.
- */
- static int spi_nor_spimem_exec_op(struct spi_nor *nor, struct spi_mem_op *op)
- {
- int error;
- error = spi_mem_adjust_op_size(nor->spimem, op);
- if (error)
- return error;
- return spi_mem_exec_op(nor->spimem, op);
- }
- int spi_nor_controller_ops_read_reg(struct spi_nor *nor, u8 opcode,
- u8 *buf, size_t len)
- {
- if (spi_nor_protocol_is_dtr(nor->reg_proto))
- return -EOPNOTSUPP;
- return nor->controller_ops->read_reg(nor, opcode, buf, len);
- }
- int spi_nor_controller_ops_write_reg(struct spi_nor *nor, u8 opcode,
- const u8 *buf, size_t len)
- {
- if (spi_nor_protocol_is_dtr(nor->reg_proto))
- return -EOPNOTSUPP;
- return nor->controller_ops->write_reg(nor, opcode, buf, len);
- }
- static int spi_nor_controller_ops_erase(struct spi_nor *nor, loff_t offs)
- {
- if (spi_nor_protocol_is_dtr(nor->reg_proto))
- return -EOPNOTSUPP;
- return nor->controller_ops->erase(nor, offs);
- }
- /**
- * spi_nor_spimem_read_data() - read data from flash's memory region via
- * spi-mem
- * @nor: pointer to 'struct spi_nor'
- * @from: offset to read from
- * @len: number of bytes to read
- * @buf: pointer to dst buffer
- *
- * Return: number of bytes read successfully, -errno otherwise
- */
- static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from,
- size_t len, u8 *buf)
- {
- struct spi_mem_op op =
- SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
- SPI_MEM_OP_ADDR(nor->addr_nbytes, from, 0),
- SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
- SPI_MEM_OP_DATA_IN(len, buf, 0));
- bool usebouncebuf;
- ssize_t nbytes;
- int error;
- spi_nor_spimem_setup_op(nor, &op, nor->read_proto);
- /* convert the dummy cycles to the number of bytes */
- op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
- if (spi_nor_protocol_is_dtr(nor->read_proto))
- op.dummy.nbytes *= 2;
- usebouncebuf = spi_nor_spimem_bounce(nor, &op);
- if (nor->dirmap.rdesc) {
- nbytes = spi_mem_dirmap_read(nor->dirmap.rdesc, op.addr.val,
- op.data.nbytes, op.data.buf.in);
- } else {
- error = spi_nor_spimem_exec_op(nor, &op);
- if (error)
- return error;
- nbytes = op.data.nbytes;
- }
- if (usebouncebuf && nbytes > 0)
- memcpy(buf, op.data.buf.in, nbytes);
- return nbytes;
- }
- /**
- * spi_nor_read_data() - read data from flash memory
- * @nor: pointer to 'struct spi_nor'
- * @from: offset to read from
- * @len: number of bytes to read
- * @buf: pointer to dst buffer
- *
- * Return: number of bytes read successfully, -errno otherwise
- */
- ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf)
- {
- if (nor->spimem)
- return spi_nor_spimem_read_data(nor, from, len, buf);
- return nor->controller_ops->read(nor, from, len, buf);
- }
- /**
- * spi_nor_spimem_write_data() - write data to flash memory via
- * spi-mem
- * @nor: pointer to 'struct spi_nor'
- * @to: offset to write to
- * @len: number of bytes to write
- * @buf: pointer to src buffer
- *
- * Return: number of bytes written successfully, -errno otherwise
- */
- static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to,
- size_t len, const u8 *buf)
- {
- struct spi_mem_op op =
- SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0),
- SPI_MEM_OP_ADDR(nor->addr_nbytes, to, 0),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_OUT(len, buf, 0));
- ssize_t nbytes;
- int error;
- if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
- op.addr.nbytes = 0;
- spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
- if (spi_nor_spimem_bounce(nor, &op))
- memcpy(nor->bouncebuf, buf, op.data.nbytes);
- if (nor->dirmap.wdesc) {
- nbytes = spi_mem_dirmap_write(nor->dirmap.wdesc, op.addr.val,
- op.data.nbytes, op.data.buf.out);
- } else {
- error = spi_nor_spimem_exec_op(nor, &op);
- if (error)
- return error;
- nbytes = op.data.nbytes;
- }
- return nbytes;
- }
- /**
- * spi_nor_write_data() - write data to flash memory
- * @nor: pointer to 'struct spi_nor'
- * @to: offset to write to
- * @len: number of bytes to write
- * @buf: pointer to src buffer
- *
- * Return: number of bytes written successfully, -errno otherwise
- */
- ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
- const u8 *buf)
- {
- if (nor->spimem)
- return spi_nor_spimem_write_data(nor, to, len, buf);
- return nor->controller_ops->write(nor, to, len, buf);
- }
- /**
- * spi_nor_read_any_reg() - read any register from flash memory, nonvolatile or
- * volatile.
- * @nor: pointer to 'struct spi_nor'.
- * @op: SPI memory operation. op->data.buf must be DMA-able.
- * @proto: SPI protocol to use for the register operation.
- *
- * Return: zero on success, -errno otherwise
- */
- int spi_nor_read_any_reg(struct spi_nor *nor, struct spi_mem_op *op,
- enum spi_nor_protocol proto)
- {
- if (!nor->spimem)
- return -EOPNOTSUPP;
- spi_nor_spimem_setup_op(nor, op, proto);
- return spi_nor_spimem_exec_op(nor, op);
- }
- /**
- * spi_nor_write_any_volatile_reg() - write any volatile register to flash
- * memory.
- * @nor: pointer to 'struct spi_nor'
- * @op: SPI memory operation. op->data.buf must be DMA-able.
- * @proto: SPI protocol to use for the register operation.
- *
- * Writing volatile registers are instant according to some manufacturers
- * (Cypress, Micron) and do not need any status polling.
- *
- * Return: zero on success, -errno otherwise
- */
- int spi_nor_write_any_volatile_reg(struct spi_nor *nor, struct spi_mem_op *op,
- enum spi_nor_protocol proto)
- {
- int ret;
- if (!nor->spimem)
- return -EOPNOTSUPP;
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
- spi_nor_spimem_setup_op(nor, op, proto);
- return spi_nor_spimem_exec_op(nor, op);
- }
- /**
- * spi_nor_write_enable() - Set write enable latch with Write Enable command.
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_write_enable(struct spi_nor *nor)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_WREN_OP;
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WREN,
- NULL, 0);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d on Write Enable\n", ret);
- return ret;
- }
- /**
- * spi_nor_write_disable() - Send Write Disable instruction to the chip.
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_write_disable(struct spi_nor *nor)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_WRDI_OP;
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WRDI,
- NULL, 0);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d on Write Disable\n", ret);
- return ret;
- }
- /**
- * spi_nor_read_id() - Read the JEDEC ID.
- * @nor: pointer to 'struct spi_nor'.
- * @naddr: number of address bytes to send. Can be zero if the operation
- * does not need to send an address.
- * @ndummy: number of dummy bytes to send after an opcode or address. Can
- * be zero if the operation does not require dummy bytes.
- * @id: pointer to a DMA-able buffer where the value of the JEDEC ID
- * will be written.
- * @proto: the SPI protocol for register operation.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
- enum spi_nor_protocol proto)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op =
- SPI_NOR_READID_OP(naddr, ndummy, id, SPI_NOR_MAX_ID_LEN);
- spi_nor_spimem_setup_op(nor, &op, proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
- SPI_NOR_MAX_ID_LEN);
- }
- return ret;
- }
- /**
- * spi_nor_read_sr() - Read the Status Register.
- * @nor: pointer to 'struct spi_nor'.
- * @sr: pointer to a DMA-able buffer where the value of the
- * Status Register will be written. Should be at least 2 bytes.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_RDSR_OP(sr);
- if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
- op.addr.nbytes = nor->params->rdsr_addr_nbytes;
- op.dummy.nbytes = nor->params->rdsr_dummy;
- /*
- * We don't want to read only one byte in DTR mode. So,
- * read 2 and then discard the second byte.
- */
- op.data.nbytes = 2;
- }
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDSR, sr,
- 1);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d reading SR\n", ret);
- return ret;
- }
- /**
- * spi_nor_read_cr() - Read the Configuration Register using the
- * SPINOR_OP_RDCR (35h) command.
- * @nor: pointer to 'struct spi_nor'
- * @cr: pointer to a DMA-able buffer where the value of the
- * Configuration Register will be written.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_RDCR_OP(cr);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDCR, cr,
- 1);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d reading CR\n", ret);
- return ret;
- }
- /**
- * spi_nor_set_4byte_addr_mode_en4b_ex4b() - Enter/Exit 4-byte address mode
- * using SPINOR_OP_EN4B/SPINOR_OP_EX4B. Typically used by
- * Winbond and Macronix.
- * @nor: pointer to 'struct spi_nor'.
- * @enable: true to enter the 4-byte address mode, false to exit the 4-byte
- * address mode.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_set_4byte_addr_mode_en4b_ex4b(struct spi_nor *nor, bool enable)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_EN4B_EX4B_OP(enable);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor,
- enable ? SPINOR_OP_EN4B :
- SPINOR_OP_EX4B,
- NULL, 0);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret);
- return ret;
- }
- /**
- * spi_nor_set_4byte_addr_mode_wren_en4b_ex4b() - Set 4-byte address mode using
- * SPINOR_OP_WREN followed by SPINOR_OP_EN4B or SPINOR_OP_EX4B. Typically used
- * by ST and Micron flashes.
- * @nor: pointer to 'struct spi_nor'.
- * @enable: true to enter the 4-byte address mode, false to exit the 4-byte
- * address mode.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_set_4byte_addr_mode_wren_en4b_ex4b(struct spi_nor *nor, bool enable)
- {
- int ret;
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
- ret = spi_nor_set_4byte_addr_mode_en4b_ex4b(nor, enable);
- if (ret)
- return ret;
- return spi_nor_write_disable(nor);
- }
- /**
- * spi_nor_set_4byte_addr_mode_brwr() - Set 4-byte address mode using
- * SPINOR_OP_BRWR. Typically used by Spansion flashes.
- * @nor: pointer to 'struct spi_nor'.
- * @enable: true to enter the 4-byte address mode, false to exit the 4-byte
- * address mode.
- *
- * 8-bit volatile bank register used to define A[30:A24] bits. MSB (bit[7]) is
- * used to enable/disable 4-byte address mode. When MSB is set to ‘1’, 4-byte
- * address mode is active and A[30:24] bits are don’t care. Write instruction is
- * SPINOR_OP_BRWR(17h) with 1 byte of data.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_set_4byte_addr_mode_brwr(struct spi_nor *nor, bool enable)
- {
- int ret;
- nor->bouncebuf[0] = enable << 7;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_BRWR_OP(nor->bouncebuf);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_BRWR,
- nor->bouncebuf, 1);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d setting 4-byte mode\n", ret);
- return ret;
- }
- /**
- * spi_nor_sr_ready() - Query the Status Register to see if the flash is ready
- * for new commands.
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: 1 if ready, 0 if not ready, -errno on errors.
- */
- int spi_nor_sr_ready(struct spi_nor *nor)
- {
- int ret;
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
- return !(nor->bouncebuf[0] & SR_WIP);
- }
- /**
- * spi_nor_use_parallel_locking() - Checks if RWW locking scheme shall be used
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: true if parallel locking is enabled, false otherwise.
- */
- static bool spi_nor_use_parallel_locking(struct spi_nor *nor)
- {
- return nor->flags & SNOR_F_RWW;
- }
- /* Locking helpers for status read operations */
- static int spi_nor_rww_start_rdst(struct spi_nor *nor)
- {
- struct spi_nor_rww *rww = &nor->rww;
- guard(mutex)(&nor->lock);
- if (rww->ongoing_io || rww->ongoing_rd)
- return -EAGAIN;
- rww->ongoing_io = true;
- rww->ongoing_rd = true;
- return 0;
- }
- static void spi_nor_rww_end_rdst(struct spi_nor *nor)
- {
- struct spi_nor_rww *rww = &nor->rww;
- guard(mutex)(&nor->lock);
- rww->ongoing_io = false;
- rww->ongoing_rd = false;
- }
- static int spi_nor_lock_rdst(struct spi_nor *nor)
- {
- if (spi_nor_use_parallel_locking(nor))
- return spi_nor_rww_start_rdst(nor);
- return 0;
- }
- static void spi_nor_unlock_rdst(struct spi_nor *nor)
- {
- if (spi_nor_use_parallel_locking(nor)) {
- spi_nor_rww_end_rdst(nor);
- wake_up(&nor->rww.wait);
- }
- }
- /**
- * spi_nor_ready() - Query the flash to see if it is ready for new commands.
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: 1 if ready, 0 if not ready, -errno on errors.
- */
- static int spi_nor_ready(struct spi_nor *nor)
- {
- int ret;
- ret = spi_nor_lock_rdst(nor);
- if (ret)
- return 0;
- /* Flashes might override the standard routine. */
- if (nor->params->ready)
- ret = nor->params->ready(nor);
- else
- ret = spi_nor_sr_ready(nor);
- spi_nor_unlock_rdst(nor);
- return ret;
- }
- /**
- * spi_nor_wait_till_ready_with_timeout() - Service routine to read the
- * Status Register until ready, or timeout occurs.
- * @nor: pointer to "struct spi_nor".
- * @timeout_jiffies: jiffies to wait until timeout.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
- unsigned long timeout_jiffies)
- {
- unsigned long deadline;
- int timeout = 0, ret;
- deadline = jiffies + timeout_jiffies;
- while (!timeout) {
- if (time_after_eq(jiffies, deadline))
- timeout = 1;
- ret = spi_nor_ready(nor);
- if (ret < 0)
- return ret;
- if (ret)
- return 0;
- cond_resched();
- }
- dev_dbg(nor->dev, "flash operation timed out\n");
- return -ETIMEDOUT;
- }
- /**
- * spi_nor_wait_till_ready() - Wait for a predefined amount of time for the
- * flash to be ready, or timeout occurs.
- * @nor: pointer to "struct spi_nor".
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_wait_till_ready(struct spi_nor *nor)
- {
- return spi_nor_wait_till_ready_with_timeout(nor,
- DEFAULT_READY_WAIT_JIFFIES);
- }
- /**
- * spi_nor_global_block_unlock() - Unlock Global Block Protection.
- * @nor: pointer to 'struct spi_nor'.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_global_block_unlock(struct spi_nor *nor)
- {
- int ret;
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_GBULK_OP;
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_GBULK,
- NULL, 0);
- }
- if (ret) {
- dev_dbg(nor->dev, "error %d on Global Block Unlock\n", ret);
- return ret;
- }
- return spi_nor_wait_till_ready(nor);
- }
- /**
- * spi_nor_write_sr() - Write the Status Register.
- * @nor: pointer to 'struct spi_nor'.
- * @sr: pointer to DMA-able buffer to write to the Status Register.
- * @len: number of bytes to write to the Status Register.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len)
- {
- int ret;
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_WRSR_OP(sr, len);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WRSR, sr,
- len);
- }
- if (ret) {
- dev_dbg(nor->dev, "error %d writing SR\n", ret);
- return ret;
- }
- return spi_nor_wait_till_ready(nor);
- }
- /**
- * spi_nor_write_sr1_and_check() - Write one byte to the Status Register 1 and
- * ensure that the byte written match the received value.
- * @nor: pointer to a 'struct spi_nor'.
- * @sr1: byte value to be written to the Status Register.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_write_sr1_and_check(struct spi_nor *nor, u8 sr1)
- {
- int ret;
- nor->bouncebuf[0] = sr1;
- ret = spi_nor_write_sr(nor, nor->bouncebuf, 1);
- if (ret)
- return ret;
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
- if (nor->bouncebuf[0] != sr1) {
- dev_dbg(nor->dev, "SR1: read back test failed\n");
- return -EIO;
- }
- return 0;
- }
- /**
- * spi_nor_write_16bit_sr_and_check() - Write the Status Register 1 and the
- * Status Register 2 in one shot. Ensure that the byte written in the Status
- * Register 1 match the received value, and that the 16-bit Write did not
- * affect what was already in the Status Register 2.
- * @nor: pointer to a 'struct spi_nor'.
- * @sr1: byte value to be written to the Status Register 1.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
- {
- int ret;
- u8 *sr_cr = nor->bouncebuf;
- u8 cr_written;
- /* Make sure we don't overwrite the contents of Status Register 2. */
- if (!(nor->flags & SNOR_F_NO_READ_CR)) {
- ret = spi_nor_read_cr(nor, &sr_cr[1]);
- if (ret)
- return ret;
- } else if (spi_nor_get_protocol_width(nor->read_proto) == 4 &&
- spi_nor_get_protocol_width(nor->write_proto) == 4 &&
- nor->params->quad_enable) {
- /*
- * If the Status Register 2 Read command (35h) is not
- * supported, we should at least be sure we don't
- * change the value of the SR2 Quad Enable bit.
- *
- * When the Quad Enable method is set and the buswidth is 4, we
- * can safely assume that the value of the QE bit is one, as a
- * consequence of the nor->params->quad_enable() call.
- *
- * According to the JESD216 revB standard, BFPT DWORDS[15],
- * bits 22:20, the 16-bit Write Status (01h) command is
- * available just for the cases in which the QE bit is
- * described in SR2 at BIT(1).
- */
- sr_cr[1] = SR2_QUAD_EN_BIT1;
- } else {
- sr_cr[1] = 0;
- }
- sr_cr[0] = sr1;
- ret = spi_nor_write_sr(nor, sr_cr, 2);
- if (ret)
- return ret;
- ret = spi_nor_read_sr(nor, sr_cr);
- if (ret)
- return ret;
- if (sr1 != sr_cr[0]) {
- dev_dbg(nor->dev, "SR: Read back test failed\n");
- return -EIO;
- }
- if (nor->flags & SNOR_F_NO_READ_CR)
- return 0;
- cr_written = sr_cr[1];
- ret = spi_nor_read_cr(nor, &sr_cr[1]);
- if (ret)
- return ret;
- if (cr_written != sr_cr[1]) {
- dev_dbg(nor->dev, "CR: read back test failed\n");
- return -EIO;
- }
- return 0;
- }
- /**
- * spi_nor_write_16bit_cr_and_check() - Write the Status Register 1 and the
- * Configuration Register in one shot. Ensure that the byte written in the
- * Configuration Register match the received value, and that the 16-bit Write
- * did not affect what was already in the Status Register 1.
- * @nor: pointer to a 'struct spi_nor'.
- * @cr: byte value to be written to the Configuration Register.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_write_16bit_cr_and_check(struct spi_nor *nor, u8 cr)
- {
- int ret;
- u8 *sr_cr = nor->bouncebuf;
- u8 sr_written;
- /* Keep the current value of the Status Register 1. */
- ret = spi_nor_read_sr(nor, sr_cr);
- if (ret)
- return ret;
- sr_cr[1] = cr;
- ret = spi_nor_write_sr(nor, sr_cr, 2);
- if (ret)
- return ret;
- sr_written = sr_cr[0];
- ret = spi_nor_read_sr(nor, sr_cr);
- if (ret)
- return ret;
- if (sr_written != sr_cr[0]) {
- dev_dbg(nor->dev, "SR: Read back test failed\n");
- return -EIO;
- }
- if (nor->flags & SNOR_F_NO_READ_CR)
- return 0;
- ret = spi_nor_read_cr(nor, &sr_cr[1]);
- if (ret)
- return ret;
- if (cr != sr_cr[1]) {
- dev_dbg(nor->dev, "CR: read back test failed\n");
- return -EIO;
- }
- return 0;
- }
- /**
- * spi_nor_write_sr_and_check() - Write the Status Register 1 and ensure that
- * the byte written match the received value without affecting other bits in the
- * Status Register 1 and 2.
- * @nor: pointer to a 'struct spi_nor'.
- * @sr1: byte value to be written to the Status Register.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1)
- {
- if (nor->flags & SNOR_F_HAS_16BIT_SR)
- return spi_nor_write_16bit_sr_and_check(nor, sr1);
- return spi_nor_write_sr1_and_check(nor, sr1);
- }
- /**
- * spi_nor_write_sr2() - Write the Status Register 2 using the
- * SPINOR_OP_WRSR2 (3eh) command.
- * @nor: pointer to 'struct spi_nor'.
- * @sr2: pointer to DMA-able buffer to write to the Status Register 2.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2)
- {
- int ret;
- ret = spi_nor_write_enable(nor);
- if (ret)
- return ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_WRSR2_OP(sr2);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_write_reg(nor, SPINOR_OP_WRSR2,
- sr2, 1);
- }
- if (ret) {
- dev_dbg(nor->dev, "error %d writing SR2\n", ret);
- return ret;
- }
- return spi_nor_wait_till_ready(nor);
- }
- /**
- * spi_nor_read_sr2() - Read the Status Register 2 using the
- * SPINOR_OP_RDSR2 (3fh) command.
- * @nor: pointer to 'struct spi_nor'.
- * @sr2: pointer to DMA-able buffer where the value of the
- * Status Register 2 will be written.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2)
- {
- int ret;
- if (nor->spimem) {
- struct spi_mem_op op = SPI_NOR_RDSR2_OP(sr2);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- ret = spi_nor_controller_ops_read_reg(nor, SPINOR_OP_RDSR2, sr2,
- 1);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d reading SR2\n", ret);
- return ret;
- }
- /**
- * spi_nor_erase_die() - Erase the entire die.
- * @nor: pointer to 'struct spi_nor'.
- * @addr: address of the die.
- * @die_size: size of the die.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_erase_die(struct spi_nor *nor, loff_t addr, size_t die_size)
- {
- bool multi_die = nor->mtd.size != die_size;
- int ret;
- dev_dbg(nor->dev, " %lldKiB\n", (long long)(die_size >> 10));
- if (nor->spimem) {
- struct spi_mem_op op =
- SPI_NOR_DIE_ERASE_OP(nor->params->die_erase_opcode,
- nor->addr_nbytes, addr, multi_die);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- } else {
- if (multi_die)
- return -EOPNOTSUPP;
- ret = spi_nor_controller_ops_write_reg(nor,
- SPINOR_OP_CHIP_ERASE,
- NULL, 0);
- }
- if (ret)
- dev_dbg(nor->dev, "error %d erasing chip\n", ret);
- return ret;
- }
- static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
- {
- size_t i;
- for (i = 0; i < size; i++)
- if (table[i][0] == opcode)
- return table[i][1];
- /* No conversion found, keep input op code. */
- return opcode;
- }
- u8 spi_nor_convert_3to4_read(u8 opcode)
- {
- static const u8 spi_nor_3to4_read[][2] = {
- { SPINOR_OP_READ, SPINOR_OP_READ_4B },
- { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B },
- { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B },
- { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B },
- { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B },
- { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B },
- { SPINOR_OP_READ_1_1_8, SPINOR_OP_READ_1_1_8_4B },
- { SPINOR_OP_READ_1_8_8, SPINOR_OP_READ_1_8_8_4B },
- { SPINOR_OP_READ_1_1_1_DTR, SPINOR_OP_READ_1_1_1_DTR_4B },
- { SPINOR_OP_READ_1_2_2_DTR, SPINOR_OP_READ_1_2_2_DTR_4B },
- { SPINOR_OP_READ_1_4_4_DTR, SPINOR_OP_READ_1_4_4_DTR_4B },
- };
- return spi_nor_convert_opcode(opcode, spi_nor_3to4_read,
- ARRAY_SIZE(spi_nor_3to4_read));
- }
- static u8 spi_nor_convert_3to4_program(u8 opcode)
- {
- static const u8 spi_nor_3to4_program[][2] = {
- { SPINOR_OP_PP, SPINOR_OP_PP_4B },
- { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B },
- { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B },
- { SPINOR_OP_PP_1_1_8, SPINOR_OP_PP_1_1_8_4B },
- { SPINOR_OP_PP_1_8_8, SPINOR_OP_PP_1_8_8_4B },
- };
- return spi_nor_convert_opcode(opcode, spi_nor_3to4_program,
- ARRAY_SIZE(spi_nor_3to4_program));
- }
- static u8 spi_nor_convert_3to4_erase(u8 opcode)
- {
- static const u8 spi_nor_3to4_erase[][2] = {
- { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B },
- { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B },
- { SPINOR_OP_SE, SPINOR_OP_SE_4B },
- };
- return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase,
- ARRAY_SIZE(spi_nor_3to4_erase));
- }
- static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
- {
- return !!nor->params->erase_map.uniform_region.erase_mask;
- }
- static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
- {
- nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
- nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
- nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
- if (!spi_nor_has_uniform_erase(nor)) {
- struct spi_nor_erase_map *map = &nor->params->erase_map;
- struct spi_nor_erase_type *erase;
- int i;
- for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
- erase = &map->erase_type[i];
- erase->opcode =
- spi_nor_convert_3to4_erase(erase->opcode);
- }
- }
- }
- static int spi_nor_prep(struct spi_nor *nor)
- {
- int ret = 0;
- if (nor->controller_ops && nor->controller_ops->prepare)
- ret = nor->controller_ops->prepare(nor);
- return ret;
- }
- static void spi_nor_unprep(struct spi_nor *nor)
- {
- if (nor->controller_ops && nor->controller_ops->unprepare)
- nor->controller_ops->unprepare(nor);
- }
- static void spi_nor_offset_to_banks(u64 bank_size, loff_t start, size_t len,
- u8 *first, u8 *last)
- {
- /* This is currently safe, the number of banks being very small */
- *first = DIV_ROUND_DOWN_ULL(start, bank_size);
- *last = DIV_ROUND_DOWN_ULL(start + len - 1, bank_size);
- }
- /* Generic helpers for internal locking and serialization */
- static bool spi_nor_rww_start_io(struct spi_nor *nor)
- {
- struct spi_nor_rww *rww = &nor->rww;
- guard(mutex)(&nor->lock);
- if (rww->ongoing_io)
- return false;
- rww->ongoing_io = true;
- return true;
- }
- static void spi_nor_rww_end_io(struct spi_nor *nor)
- {
- guard(mutex)(&nor->lock);
- nor->rww.ongoing_io = false;
- }
- static int spi_nor_lock_device(struct spi_nor *nor)
- {
- if (!spi_nor_use_parallel_locking(nor))
- return 0;
- return wait_event_killable(nor->rww.wait, spi_nor_rww_start_io(nor));
- }
- static void spi_nor_unlock_device(struct spi_nor *nor)
- {
- if (spi_nor_use_parallel_locking(nor)) {
- spi_nor_rww_end_io(nor);
- wake_up(&nor->rww.wait);
- }
- }
- /* Generic helpers for internal locking and serialization */
- static bool spi_nor_rww_start_exclusive(struct spi_nor *nor)
- {
- struct spi_nor_rww *rww = &nor->rww;
- mutex_lock(&nor->lock);
- if (rww->ongoing_io || rww->ongoing_rd || rww->ongoing_pe)
- return false;
- rww->ongoing_io = true;
- rww->ongoing_rd = true;
- rww->ongoing_pe = true;
- return true;
- }
- static void spi_nor_rww_end_exclusive(struct spi_nor *nor)
- {
- struct spi_nor_rww *rww = &nor->rww;
- guard(mutex)(&nor->lock);
- rww->ongoing_io = false;
- rww->ongoing_rd = false;
- rww->ongoing_pe = false;
- }
- int spi_nor_prep_and_lock(struct spi_nor *nor)
- {
- int ret;
- ret = spi_nor_prep(nor);
- if (ret)
- return ret;
- if (!spi_nor_use_parallel_locking(nor))
- mutex_lock(&nor->lock);
- else
- ret = wait_event_killable(nor->rww.wait,
- spi_nor_rww_start_exclusive(nor));
- return ret;
- }
- void spi_nor_unlock_and_unprep(struct spi_nor *nor)
- {
- if (!spi_nor_use_parallel_locking(nor)) {
- mutex_unlock(&nor->lock);
- } else {
- spi_nor_rww_end_exclusive(nor);
- wake_up(&nor->rww.wait);
- }
- spi_nor_unprep(nor);
- }
- /* Internal locking helpers for program and erase operations */
- static bool spi_nor_rww_start_pe(struct spi_nor *nor, loff_t start, size_t len)
- {
- struct spi_nor_rww *rww = &nor->rww;
- unsigned int used_banks = 0;
- u8 first, last;
- int bank;
- guard(mutex)(&nor->lock);
- if (rww->ongoing_io || rww->ongoing_rd || rww->ongoing_pe)
- return false;
- spi_nor_offset_to_banks(nor->params->bank_size, start, len, &first, &last);
- for (bank = first; bank <= last; bank++) {
- if (rww->used_banks & BIT(bank))
- return false;
- used_banks |= BIT(bank);
- }
- rww->used_banks |= used_banks;
- rww->ongoing_pe = true;
- return true;
- }
- static void spi_nor_rww_end_pe(struct spi_nor *nor, loff_t start, size_t len)
- {
- struct spi_nor_rww *rww = &nor->rww;
- u8 first, last;
- int bank;
- guard(mutex)(&nor->lock);
- spi_nor_offset_to_banks(nor->params->bank_size, start, len, &first, &last);
- for (bank = first; bank <= last; bank++)
- rww->used_banks &= ~BIT(bank);
- rww->ongoing_pe = false;
- }
- static int spi_nor_prep_and_lock_pe(struct spi_nor *nor, loff_t start, size_t len)
- {
- int ret;
- ret = spi_nor_prep(nor);
- if (ret)
- return ret;
- if (!spi_nor_use_parallel_locking(nor))
- mutex_lock(&nor->lock);
- else
- ret = wait_event_killable(nor->rww.wait,
- spi_nor_rww_start_pe(nor, start, len));
- return ret;
- }
- static void spi_nor_unlock_and_unprep_pe(struct spi_nor *nor, loff_t start, size_t len)
- {
- if (!spi_nor_use_parallel_locking(nor)) {
- mutex_unlock(&nor->lock);
- } else {
- spi_nor_rww_end_pe(nor, start, len);
- wake_up(&nor->rww.wait);
- }
- spi_nor_unprep(nor);
- }
- /* Internal locking helpers for read operations */
- static bool spi_nor_rww_start_rd(struct spi_nor *nor, loff_t start, size_t len)
- {
- struct spi_nor_rww *rww = &nor->rww;
- unsigned int used_banks = 0;
- u8 first, last;
- int bank;
- guard(mutex)(&nor->lock);
- if (rww->ongoing_io || rww->ongoing_rd)
- return false;
- spi_nor_offset_to_banks(nor->params->bank_size, start, len, &first, &last);
- for (bank = first; bank <= last; bank++) {
- if (rww->used_banks & BIT(bank))
- return false;
- used_banks |= BIT(bank);
- }
- rww->used_banks |= used_banks;
- rww->ongoing_io = true;
- rww->ongoing_rd = true;
- return true;
- }
- static void spi_nor_rww_end_rd(struct spi_nor *nor, loff_t start, size_t len)
- {
- struct spi_nor_rww *rww = &nor->rww;
- u8 first, last;
- int bank;
- guard(mutex)(&nor->lock);
- spi_nor_offset_to_banks(nor->params->bank_size, start, len, &first, &last);
- for (bank = first; bank <= last; bank++)
- nor->rww.used_banks &= ~BIT(bank);
- rww->ongoing_io = false;
- rww->ongoing_rd = false;
- }
- static int spi_nor_prep_and_lock_rd(struct spi_nor *nor, loff_t start, size_t len)
- {
- int ret;
- ret = spi_nor_prep(nor);
- if (ret)
- return ret;
- if (!spi_nor_use_parallel_locking(nor))
- mutex_lock(&nor->lock);
- else
- ret = wait_event_killable(nor->rww.wait,
- spi_nor_rww_start_rd(nor, start, len));
- return ret;
- }
- static void spi_nor_unlock_and_unprep_rd(struct spi_nor *nor, loff_t start, size_t len)
- {
- if (!spi_nor_use_parallel_locking(nor)) {
- mutex_unlock(&nor->lock);
- } else {
- spi_nor_rww_end_rd(nor, start, len);
- wake_up(&nor->rww.wait);
- }
- spi_nor_unprep(nor);
- }
- /*
- * Initiate the erasure of a single sector
- */
- int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
- {
- int i;
- if (nor->spimem) {
- struct spi_mem_op op =
- SPI_NOR_SECTOR_ERASE_OP(nor->erase_opcode,
- nor->addr_nbytes, addr);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- return spi_mem_exec_op(nor->spimem, &op);
- } else if (nor->controller_ops->erase) {
- return spi_nor_controller_ops_erase(nor, addr);
- }
- /*
- * Default implementation, if driver doesn't have a specialized HW
- * control
- */
- for (i = nor->addr_nbytes - 1; i >= 0; i--) {
- nor->bouncebuf[i] = addr & 0xff;
- addr >>= 8;
- }
- return spi_nor_controller_ops_write_reg(nor, nor->erase_opcode,
- nor->bouncebuf, nor->addr_nbytes);
- }
- /**
- * spi_nor_div_by_erase_size() - calculate remainder and update new dividend
- * @erase: pointer to a structure that describes a SPI NOR erase type
- * @dividend: dividend value
- * @remainder: pointer to u32 remainder (will be updated)
- *
- * Return: the result of the division
- */
- static u64 spi_nor_div_by_erase_size(const struct spi_nor_erase_type *erase,
- u64 dividend, u32 *remainder)
- {
- /* JEDEC JESD216B Standard imposes erase sizes to be power of 2. */
- *remainder = (u32)dividend & erase->size_mask;
- return dividend >> erase->size_shift;
- }
- /**
- * spi_nor_find_best_erase_type() - find the best erase type for the given
- * offset in the serial flash memory and the
- * number of bytes to erase. The region in
- * which the address fits is expected to be
- * provided.
- * @map: the erase map of the SPI NOR
- * @region: pointer to a structure that describes a SPI NOR erase region
- * @addr: offset in the serial flash memory
- * @len: number of bytes to erase
- *
- * Return: a pointer to the best fitted erase type, NULL otherwise.
- */
- static const struct spi_nor_erase_type *
- spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
- const struct spi_nor_erase_region *region,
- u64 addr, u32 len)
- {
- const struct spi_nor_erase_type *erase;
- u32 rem;
- int i;
- /*
- * Erase types are ordered by size, with the smallest erase type at
- * index 0.
- */
- for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
- /* Does the erase region support the tested erase type? */
- if (!(region->erase_mask & BIT(i)))
- continue;
- erase = &map->erase_type[i];
- if (!erase->size)
- continue;
- /* Alignment is not mandatory for overlaid regions */
- if (region->overlaid && region->size <= len)
- return erase;
- /* Don't erase more than what the user has asked for. */
- if (erase->size > len)
- continue;
- spi_nor_div_by_erase_size(erase, addr, &rem);
- if (!rem)
- return erase;
- }
- return NULL;
- }
- /**
- * spi_nor_init_erase_cmd() - initialize an erase command
- * @region: pointer to a structure that describes a SPI NOR erase region
- * @erase: pointer to a structure that describes a SPI NOR erase type
- *
- * Return: the pointer to the allocated erase command, ERR_PTR(-errno)
- * otherwise.
- */
- static struct spi_nor_erase_command *
- spi_nor_init_erase_cmd(const struct spi_nor_erase_region *region,
- const struct spi_nor_erase_type *erase)
- {
- struct spi_nor_erase_command *cmd;
- cmd = kmalloc_obj(*cmd);
- if (!cmd)
- return ERR_PTR(-ENOMEM);
- INIT_LIST_HEAD(&cmd->list);
- cmd->opcode = erase->opcode;
- cmd->count = 1;
- if (region->overlaid)
- cmd->size = region->size;
- else
- cmd->size = erase->size;
- return cmd;
- }
- /**
- * spi_nor_destroy_erase_cmd_list() - destroy erase command list
- * @erase_list: list of erase commands
- */
- static void spi_nor_destroy_erase_cmd_list(struct list_head *erase_list)
- {
- struct spi_nor_erase_command *cmd, *next;
- list_for_each_entry_safe(cmd, next, erase_list, list) {
- list_del(&cmd->list);
- kfree(cmd);
- }
- }
- /**
- * spi_nor_init_erase_cmd_list() - initialize erase command list
- * @nor: pointer to a 'struct spi_nor'
- * @erase_list: list of erase commands to be executed once we validate that the
- * erase can be performed
- * @addr: offset in the serial flash memory
- * @len: number of bytes to erase
- *
- * Builds the list of best fitted erase commands and verifies if the erase can
- * be performed.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
- struct list_head *erase_list,
- u64 addr, u32 len)
- {
- const struct spi_nor_erase_map *map = &nor->params->erase_map;
- const struct spi_nor_erase_type *erase, *prev_erase = NULL;
- struct spi_nor_erase_region *region;
- struct spi_nor_erase_command *cmd = NULL;
- u64 region_end;
- unsigned int i;
- int ret = -EINVAL;
- for (i = 0; i < map->n_regions && len; i++) {
- region = &map->regions[i];
- region_end = region->offset + region->size;
- while (len && addr >= region->offset && addr < region_end) {
- erase = spi_nor_find_best_erase_type(map, region, addr,
- len);
- if (!erase)
- goto destroy_erase_cmd_list;
- if (prev_erase != erase || erase->size != cmd->size ||
- region->overlaid) {
- cmd = spi_nor_init_erase_cmd(region, erase);
- if (IS_ERR(cmd)) {
- ret = PTR_ERR(cmd);
- goto destroy_erase_cmd_list;
- }
- list_add_tail(&cmd->list, erase_list);
- } else {
- cmd->count++;
- }
- len -= cmd->size;
- addr += cmd->size;
- prev_erase = erase;
- }
- }
- return 0;
- destroy_erase_cmd_list:
- spi_nor_destroy_erase_cmd_list(erase_list);
- return ret;
- }
- /**
- * spi_nor_erase_multi_sectors() - perform a non-uniform erase
- * @nor: pointer to a 'struct spi_nor'
- * @addr: offset in the serial flash memory
- * @len: number of bytes to erase
- *
- * Build a list of best fitted erase commands and execute it once we validate
- * that the erase can be performed.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_erase_multi_sectors(struct spi_nor *nor, u64 addr, u32 len)
- {
- LIST_HEAD(erase_list);
- struct spi_nor_erase_command *cmd, *next;
- int ret;
- ret = spi_nor_init_erase_cmd_list(nor, &erase_list, addr, len);
- if (ret)
- return ret;
- list_for_each_entry_safe(cmd, next, &erase_list, list) {
- nor->erase_opcode = cmd->opcode;
- while (cmd->count) {
- dev_vdbg(nor->dev, "erase_cmd->size = 0x%08x, erase_cmd->opcode = 0x%02x, erase_cmd->count = %u\n",
- cmd->size, cmd->opcode, cmd->count);
- ret = spi_nor_lock_device(nor);
- if (ret)
- goto destroy_erase_cmd_list;
- ret = spi_nor_write_enable(nor);
- if (ret) {
- spi_nor_unlock_device(nor);
- goto destroy_erase_cmd_list;
- }
- ret = spi_nor_erase_sector(nor, addr);
- spi_nor_unlock_device(nor);
- if (ret)
- goto destroy_erase_cmd_list;
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto destroy_erase_cmd_list;
- addr += cmd->size;
- cmd->count--;
- }
- list_del(&cmd->list);
- kfree(cmd);
- }
- return 0;
- destroy_erase_cmd_list:
- spi_nor_destroy_erase_cmd_list(&erase_list);
- return ret;
- }
- static int spi_nor_erase_dice(struct spi_nor *nor, loff_t addr,
- size_t len, size_t die_size)
- {
- unsigned long timeout;
- int ret;
- /*
- * Scale the timeout linearly with the size of the flash, with
- * a minimum calibrated to an old 2MB flash. We could try to
- * pull these from CFI/SFDP, but these values should be good
- * enough for now.
- */
- timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES,
- CHIP_ERASE_2MB_READY_WAIT_JIFFIES *
- (unsigned long)(nor->mtd.size / SZ_2M));
- do {
- ret = spi_nor_lock_device(nor);
- if (ret)
- return ret;
- ret = spi_nor_write_enable(nor);
- if (ret) {
- spi_nor_unlock_device(nor);
- return ret;
- }
- ret = spi_nor_erase_die(nor, addr, die_size);
- spi_nor_unlock_device(nor);
- if (ret)
- return ret;
- ret = spi_nor_wait_till_ready_with_timeout(nor, timeout);
- if (ret)
- return ret;
- addr += die_size;
- len -= die_size;
- } while (len);
- return 0;
- }
- /*
- * Erase an address range on the nor chip. The address range may extend
- * one or more erase sectors. Return an error if there is a problem erasing.
- */
- static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
- {
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- u8 n_dice = nor->params->n_dice;
- bool multi_die_erase = false;
- u32 addr, len, rem;
- size_t die_size;
- int ret;
- dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
- (long long)instr->len);
- if (spi_nor_has_uniform_erase(nor)) {
- div_u64_rem(instr->len, mtd->erasesize, &rem);
- if (rem)
- return -EINVAL;
- }
- addr = instr->addr;
- len = instr->len;
- if (n_dice) {
- die_size = div_u64(mtd->size, n_dice);
- if (!(len & (die_size - 1)) && !(addr & (die_size - 1)))
- multi_die_erase = true;
- } else {
- die_size = mtd->size;
- }
- ret = spi_nor_prep_and_lock_pe(nor, instr->addr, instr->len);
- if (ret)
- return ret;
- /* chip (die) erase? */
- if ((len == mtd->size && !(nor->flags & SNOR_F_NO_OP_CHIP_ERASE)) ||
- multi_die_erase) {
- ret = spi_nor_erase_dice(nor, addr, len, die_size);
- if (ret)
- goto erase_err;
- /* REVISIT in some cases we could speed up erasing large regions
- * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up
- * to use "small sector erase", but that's not always optimal.
- */
- /* "sector"-at-a-time erase */
- } else if (spi_nor_has_uniform_erase(nor)) {
- while (len) {
- ret = spi_nor_lock_device(nor);
- if (ret)
- goto erase_err;
- ret = spi_nor_write_enable(nor);
- if (ret) {
- spi_nor_unlock_device(nor);
- goto erase_err;
- }
- ret = spi_nor_erase_sector(nor, addr);
- spi_nor_unlock_device(nor);
- if (ret)
- goto erase_err;
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto erase_err;
- addr += mtd->erasesize;
- len -= mtd->erasesize;
- }
- /* erase multiple sectors */
- } else {
- ret = spi_nor_erase_multi_sectors(nor, addr, len);
- if (ret)
- goto erase_err;
- }
- ret = spi_nor_write_disable(nor);
- erase_err:
- spi_nor_unlock_and_unprep_pe(nor, instr->addr, instr->len);
- return ret;
- }
- /**
- * spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status
- * Register 1.
- * @nor: pointer to a 'struct spi_nor'
- *
- * Bit 6 of the Status Register 1 is the QE bit for Macronix like QSPI memories.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
- {
- int ret;
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
- if (nor->bouncebuf[0] & SR1_QUAD_EN_BIT6)
- return 0;
- nor->bouncebuf[0] |= SR1_QUAD_EN_BIT6;
- return spi_nor_write_sr1_and_check(nor, nor->bouncebuf[0]);
- }
- /**
- * spi_nor_sr2_bit1_quad_enable() - set the Quad Enable BIT(1) in the Status
- * Register 2.
- * @nor: pointer to a 'struct spi_nor'.
- *
- * Bit 1 of the Status Register 2 is the QE bit for Spansion like QSPI memories.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
- {
- int ret;
- if (nor->flags & SNOR_F_NO_READ_CR)
- return spi_nor_write_16bit_cr_and_check(nor, SR2_QUAD_EN_BIT1);
- ret = spi_nor_read_cr(nor, nor->bouncebuf);
- if (ret)
- return ret;
- if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)
- return 0;
- nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
- return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]);
- }
- /**
- * spi_nor_sr2_bit7_quad_enable() - set QE bit in Status Register 2.
- * @nor: pointer to a 'struct spi_nor'
- *
- * Set the Quad Enable (QE) bit in the Status Register 2.
- *
- * This is one of the procedures to set the QE bit described in the SFDP
- * (JESD216 rev B) specification but no manufacturer using this procedure has
- * been identified yet, hence the name of the function.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
- {
- u8 *sr2 = nor->bouncebuf;
- int ret;
- u8 sr2_written;
- /* Check current Quad Enable bit value. */
- ret = spi_nor_read_sr2(nor, sr2);
- if (ret)
- return ret;
- if (*sr2 & SR2_QUAD_EN_BIT7)
- return 0;
- /* Update the Quad Enable bit. */
- *sr2 |= SR2_QUAD_EN_BIT7;
- ret = spi_nor_write_sr2(nor, sr2);
- if (ret)
- return ret;
- sr2_written = *sr2;
- /* Read back and check it. */
- ret = spi_nor_read_sr2(nor, sr2);
- if (ret)
- return ret;
- if (*sr2 != sr2_written) {
- dev_dbg(nor->dev, "SR2: Read back test failed\n");
- return -EIO;
- }
- return 0;
- }
- static const struct spi_nor_manufacturer *manufacturers[] = {
- &spi_nor_atmel,
- &spi_nor_eon,
- &spi_nor_esmt,
- &spi_nor_everspin,
- &spi_nor_gigadevice,
- &spi_nor_intel,
- &spi_nor_issi,
- &spi_nor_macronix,
- &spi_nor_micron,
- &spi_nor_st,
- &spi_nor_spansion,
- &spi_nor_sst,
- &spi_nor_winbond,
- &spi_nor_xmc,
- };
- static const struct flash_info spi_nor_generic_flash = {
- .name = "spi-nor-generic",
- };
- static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
- const u8 *id)
- {
- const struct flash_info *part;
- unsigned int i, j;
- for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
- for (j = 0; j < manufacturers[i]->nparts; j++) {
- part = &manufacturers[i]->parts[j];
- if (part->id &&
- !memcmp(part->id->bytes, id, part->id->len)) {
- nor->manufacturer = manufacturers[i];
- return part;
- }
- }
- }
- return NULL;
- }
- static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
- {
- const struct flash_info *info;
- u8 *id = nor->bouncebuf;
- int ret;
- ret = spi_nor_read_id(nor, 0, 0, id, nor->reg_proto);
- if (ret) {
- dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret);
- return ERR_PTR(ret);
- }
- /* Cache the complete flash ID. */
- nor->id = devm_kmemdup(nor->dev, id, SPI_NOR_MAX_ID_LEN, GFP_KERNEL);
- if (!nor->id)
- return ERR_PTR(-ENOMEM);
- info = spi_nor_match_id(nor, id);
- /* Fallback to a generic flash described only by its SFDP data. */
- if (!info) {
- ret = spi_nor_check_sfdp_signature(nor);
- if (!ret)
- info = &spi_nor_generic_flash;
- }
- if (!info) {
- dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
- SPI_NOR_MAX_ID_LEN, id);
- return ERR_PTR(-ENODEV);
- }
- return info;
- }
- /*
- * On Octal DTR capable flashes, reads cannot start or end at an odd
- * address in Octal DTR mode. Extra bytes need to be read at the start
- * or end to make sure both the start address and length remain even.
- */
- static int spi_nor_octal_dtr_read(struct spi_nor *nor, loff_t from, size_t len,
- u_char *buf)
- {
- u_char *tmp_buf;
- size_t tmp_len;
- loff_t start, end;
- int ret, bytes_read;
- if (IS_ALIGNED(from, 2) && IS_ALIGNED(len, 2))
- return spi_nor_read_data(nor, from, len, buf);
- else if (IS_ALIGNED(from, 2) && len > PAGE_SIZE)
- return spi_nor_read_data(nor, from, round_down(len, PAGE_SIZE),
- buf);
- tmp_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!tmp_buf)
- return -ENOMEM;
- start = round_down(from, 2);
- end = round_up(from + len, 2);
- /*
- * Avoid allocating too much memory. The requested read length might be
- * quite large. Allocating a buffer just as large (slightly bigger, in
- * fact) would put unnecessary memory pressure on the system.
- *
- * For example if the read is from 3 to 1M, then this will read from 2
- * to 4098. The reads from 4098 to 1M will then not need a temporary
- * buffer so they can proceed as normal.
- */
- tmp_len = min_t(size_t, end - start, PAGE_SIZE);
- ret = spi_nor_read_data(nor, start, tmp_len, tmp_buf);
- if (ret == 0) {
- ret = -EIO;
- goto out;
- }
- if (ret < 0)
- goto out;
- /*
- * More bytes are read than actually requested, but that number can't be
- * reported to the calling function or it will confuse its calculations.
- * Calculate how many of the _requested_ bytes were read.
- */
- bytes_read = ret;
- if (from != start)
- ret -= from - start;
- /*
- * Only account for extra bytes at the end if they were actually read.
- * For example, if the total length was truncated because of temporary
- * buffer size limit then the adjustment for the extra bytes at the end
- * is not needed.
- */
- if (start + bytes_read == end)
- ret -= end - (from + len);
- memcpy(buf, tmp_buf + (from - start), ret);
- out:
- kfree(tmp_buf);
- return ret;
- }
- static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
- {
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- loff_t from_lock = from;
- size_t len_lock = len;
- ssize_t ret;
- dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
- ret = spi_nor_prep_and_lock_rd(nor, from_lock, len_lock);
- if (ret)
- return ret;
- while (len) {
- loff_t addr = from;
- if (nor->read_proto == SNOR_PROTO_8_8_8_DTR)
- ret = spi_nor_octal_dtr_read(nor, addr, len, buf);
- else
- ret = spi_nor_read_data(nor, addr, len, buf);
- if (ret == 0) {
- /* We shouldn't see 0-length reads */
- ret = -EIO;
- goto read_err;
- }
- if (ret < 0)
- goto read_err;
- WARN_ON(ret > len);
- *retlen += ret;
- buf += ret;
- from += ret;
- len -= ret;
- }
- ret = 0;
- read_err:
- spi_nor_unlock_and_unprep_rd(nor, from_lock, len_lock);
- return ret;
- }
- /*
- * On Octal DTR capable flashes, writes cannot start or end at an odd address
- * in Octal DTR mode. Extra 0xff bytes need to be appended or prepended to
- * make sure the start address and end address are even. 0xff is used because
- * on NOR flashes a program operation can only flip bits from 1 to 0, not the
- * other way round. 0 to 1 flip needs to happen via erases.
- */
- static int spi_nor_octal_dtr_write(struct spi_nor *nor, loff_t to, size_t len,
- const u8 *buf)
- {
- u8 *tmp_buf;
- size_t bytes_written;
- loff_t start, end;
- int ret;
- if (IS_ALIGNED(to, 2) && IS_ALIGNED(len, 2))
- return spi_nor_write_data(nor, to, len, buf);
- tmp_buf = kmalloc(nor->params->page_size, GFP_KERNEL);
- if (!tmp_buf)
- return -ENOMEM;
- memset(tmp_buf, 0xff, nor->params->page_size);
- start = round_down(to, 2);
- end = round_up(to + len, 2);
- memcpy(tmp_buf + (to - start), buf, len);
- ret = spi_nor_write_data(nor, start, end - start, tmp_buf);
- if (ret == 0) {
- ret = -EIO;
- goto out;
- }
- if (ret < 0)
- goto out;
- /*
- * More bytes are written than actually requested, but that number can't
- * be reported to the calling function or it will confuse its
- * calculations. Calculate how many of the _requested_ bytes were
- * written.
- */
- bytes_written = ret;
- if (to != start)
- ret -= to - start;
- /*
- * Only account for extra bytes at the end if they were actually
- * written. For example, if for some reason the controller could only
- * complete a partial write then the adjustment for the extra bytes at
- * the end is not needed.
- */
- if (start + bytes_written == end)
- ret -= end - (to + len);
- out:
- kfree(tmp_buf);
- return ret;
- }
- /*
- * Write an address range to the nor chip. Data must be written in
- * FLASH_PAGESIZE chunks. The address range may be any size provided
- * it is within the physical boundaries.
- */
- static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
- {
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- size_t i;
- ssize_t ret;
- u32 page_size = nor->params->page_size;
- dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
- ret = spi_nor_prep_and_lock_pe(nor, to, len);
- if (ret)
- return ret;
- for (i = 0; i < len; ) {
- ssize_t written;
- loff_t addr = to + i;
- size_t page_offset = addr & (page_size - 1);
- /* the size of data remaining on the first page */
- size_t page_remain = min_t(size_t, page_size - page_offset, len - i);
- ret = spi_nor_lock_device(nor);
- if (ret)
- goto write_err;
- ret = spi_nor_write_enable(nor);
- if (ret) {
- spi_nor_unlock_device(nor);
- goto write_err;
- }
- if (nor->write_proto == SNOR_PROTO_8_8_8_DTR)
- ret = spi_nor_octal_dtr_write(nor, addr, page_remain,
- buf + i);
- else
- ret = spi_nor_write_data(nor, addr, page_remain,
- buf + i);
- spi_nor_unlock_device(nor);
- if (ret < 0)
- goto write_err;
- written = ret;
- ret = spi_nor_wait_till_ready(nor);
- if (ret)
- goto write_err;
- *retlen += written;
- i += written;
- }
- write_err:
- spi_nor_unlock_and_unprep_pe(nor, to, len);
- return ret;
- }
- static int spi_nor_check(struct spi_nor *nor)
- {
- if (!nor->dev ||
- (!nor->spimem && !nor->controller_ops) ||
- (!nor->spimem && nor->controller_ops &&
- (!nor->controller_ops->read ||
- !nor->controller_ops->write ||
- !nor->controller_ops->read_reg ||
- !nor->controller_ops->write_reg))) {
- pr_err("spi-nor: please fill all the necessary fields!\n");
- return -EINVAL;
- }
- if (nor->spimem && nor->controller_ops) {
- dev_err(nor->dev, "nor->spimem and nor->controller_ops are mutually exclusive, please set just one of them.\n");
- return -EINVAL;
- }
- return 0;
- }
- void
- spi_nor_set_read_settings(struct spi_nor_read_command *read,
- u8 num_mode_clocks,
- u8 num_wait_states,
- u8 opcode,
- enum spi_nor_protocol proto)
- {
- read->num_mode_clocks = num_mode_clocks;
- read->num_wait_states = num_wait_states;
- read->opcode = opcode;
- read->proto = proto;
- }
- void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
- enum spi_nor_protocol proto)
- {
- pp->opcode = opcode;
- pp->proto = proto;
- }
- static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size)
- {
- size_t i;
- for (i = 0; i < size; i++)
- if (table[i][0] == (int)hwcaps)
- return table[i][1];
- return -EINVAL;
- }
- int spi_nor_hwcaps_read2cmd(u32 hwcaps)
- {
- static const int hwcaps_read2cmd[][2] = {
- { SNOR_HWCAPS_READ, SNOR_CMD_READ },
- { SNOR_HWCAPS_READ_FAST, SNOR_CMD_READ_FAST },
- { SNOR_HWCAPS_READ_1_1_1_DTR, SNOR_CMD_READ_1_1_1_DTR },
- { SNOR_HWCAPS_READ_1_1_2, SNOR_CMD_READ_1_1_2 },
- { SNOR_HWCAPS_READ_1_2_2, SNOR_CMD_READ_1_2_2 },
- { SNOR_HWCAPS_READ_2_2_2, SNOR_CMD_READ_2_2_2 },
- { SNOR_HWCAPS_READ_1_2_2_DTR, SNOR_CMD_READ_1_2_2_DTR },
- { SNOR_HWCAPS_READ_1_1_4, SNOR_CMD_READ_1_1_4 },
- { SNOR_HWCAPS_READ_1_4_4, SNOR_CMD_READ_1_4_4 },
- { SNOR_HWCAPS_READ_4_4_4, SNOR_CMD_READ_4_4_4 },
- { SNOR_HWCAPS_READ_1_4_4_DTR, SNOR_CMD_READ_1_4_4_DTR },
- { SNOR_HWCAPS_READ_1_1_8, SNOR_CMD_READ_1_1_8 },
- { SNOR_HWCAPS_READ_1_8_8, SNOR_CMD_READ_1_8_8 },
- { SNOR_HWCAPS_READ_8_8_8, SNOR_CMD_READ_8_8_8 },
- { SNOR_HWCAPS_READ_1_8_8_DTR, SNOR_CMD_READ_1_8_8_DTR },
- { SNOR_HWCAPS_READ_8_8_8_DTR, SNOR_CMD_READ_8_8_8_DTR },
- };
- return spi_nor_hwcaps2cmd(hwcaps, hwcaps_read2cmd,
- ARRAY_SIZE(hwcaps_read2cmd));
- }
- int spi_nor_hwcaps_pp2cmd(u32 hwcaps)
- {
- static const int hwcaps_pp2cmd[][2] = {
- { SNOR_HWCAPS_PP, SNOR_CMD_PP },
- { SNOR_HWCAPS_PP_1_1_4, SNOR_CMD_PP_1_1_4 },
- { SNOR_HWCAPS_PP_1_4_4, SNOR_CMD_PP_1_4_4 },
- { SNOR_HWCAPS_PP_4_4_4, SNOR_CMD_PP_4_4_4 },
- { SNOR_HWCAPS_PP_1_1_8, SNOR_CMD_PP_1_1_8 },
- { SNOR_HWCAPS_PP_1_8_8, SNOR_CMD_PP_1_8_8 },
- { SNOR_HWCAPS_PP_8_8_8, SNOR_CMD_PP_8_8_8 },
- { SNOR_HWCAPS_PP_8_8_8_DTR, SNOR_CMD_PP_8_8_8_DTR },
- };
- return spi_nor_hwcaps2cmd(hwcaps, hwcaps_pp2cmd,
- ARRAY_SIZE(hwcaps_pp2cmd));
- }
- /**
- * spi_nor_spimem_check_read_pp_op - check if a read or a page program operation is
- * supported by controller
- *@nor: pointer to a 'struct spi_nor'
- *@op: pointer to op template to be checked
- *
- * Returns 0 if operation is supported, -EOPNOTSUPP otherwise.
- */
- static int spi_nor_spimem_check_read_pp_op(struct spi_nor *nor,
- struct spi_mem_op *op)
- {
- /*
- * First test with 4 address bytes. The opcode itself might
- * be a 3B addressing opcode but we don't care, because
- * SPI controller implementation should not check the opcode,
- * but just the sequence.
- */
- op->addr.nbytes = 4;
- if (!spi_mem_supports_op(nor->spimem, op)) {
- if (nor->params->size > SZ_16M)
- return -EOPNOTSUPP;
- /* If flash size <= 16MB, 3 address bytes are sufficient */
- op->addr.nbytes = 3;
- if (!spi_mem_supports_op(nor->spimem, op))
- return -EOPNOTSUPP;
- }
- return 0;
- }
- /**
- * spi_nor_spimem_check_readop - check if the read op is supported
- * by controller
- *@nor: pointer to a 'struct spi_nor'
- *@read: pointer to op template to be checked
- *
- * Returns 0 if operation is supported, -EOPNOTSUPP otherwise.
- */
- static int spi_nor_spimem_check_readop(struct spi_nor *nor,
- const struct spi_nor_read_command *read)
- {
- struct spi_mem_op op = SPI_NOR_READ_OP(read->opcode);
- spi_nor_spimem_setup_op(nor, &op, read->proto);
- /* convert the dummy cycles to the number of bytes */
- op.dummy.nbytes = (read->num_mode_clocks + read->num_wait_states) *
- op.dummy.buswidth / 8;
- if (spi_nor_protocol_is_dtr(nor->read_proto))
- op.dummy.nbytes *= 2;
- return spi_nor_spimem_check_read_pp_op(nor, &op);
- }
- /**
- * spi_nor_spimem_check_pp - check if the page program op is supported
- * by controller
- *@nor: pointer to a 'struct spi_nor'
- *@pp: pointer to op template to be checked
- *
- * Returns 0 if operation is supported, -EOPNOTSUPP otherwise.
- */
- static int spi_nor_spimem_check_pp(struct spi_nor *nor,
- const struct spi_nor_pp_command *pp)
- {
- struct spi_mem_op op = SPI_NOR_PP_OP(pp->opcode);
- spi_nor_spimem_setup_op(nor, &op, pp->proto);
- return spi_nor_spimem_check_read_pp_op(nor, &op);
- }
- /**
- * spi_nor_spimem_adjust_hwcaps - Find optimal Read/Write protocol
- * based on SPI controller capabilities
- * @nor: pointer to a 'struct spi_nor'
- * @hwcaps: pointer to resulting capabilities after adjusting
- * according to controller and flash's capability
- */
- static void
- spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- unsigned int cap;
- /* X-X-X modes are not supported yet, mask them all. */
- *hwcaps &= ~SNOR_HWCAPS_X_X_X;
- /*
- * If the reset line is broken, we do not want to enter a stateful
- * mode.
- */
- if (nor->flags & SNOR_F_BROKEN_RESET)
- *hwcaps &= ~(SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_X_X_X_DTR);
- for (cap = 0; cap < sizeof(*hwcaps) * BITS_PER_BYTE; cap++) {
- int rdidx, ppidx;
- if (!(*hwcaps & BIT(cap)))
- continue;
- rdidx = spi_nor_hwcaps_read2cmd(BIT(cap));
- if (rdidx >= 0 &&
- spi_nor_spimem_check_readop(nor, ¶ms->reads[rdidx]))
- *hwcaps &= ~BIT(cap);
- ppidx = spi_nor_hwcaps_pp2cmd(BIT(cap));
- if (ppidx < 0)
- continue;
- if (spi_nor_spimem_check_pp(nor,
- ¶ms->page_programs[ppidx]))
- *hwcaps &= ~BIT(cap);
- }
- /* Some SPI controllers might not support CR read opcode. */
- if (!(nor->flags & SNOR_F_NO_READ_CR)) {
- struct spi_mem_op op = SPI_NOR_RDCR_OP(nor->bouncebuf);
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- if (!spi_mem_supports_op(nor->spimem, &op))
- nor->flags |= SNOR_F_NO_READ_CR;
- }
- }
- /**
- * spi_nor_set_erase_type() - set a SPI NOR erase type
- * @erase: pointer to a structure that describes a SPI NOR erase type
- * @size: the size of the sector/block erased by the erase type
- * @opcode: the SPI command op code to erase the sector/block
- */
- void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size,
- u8 opcode)
- {
- erase->size = size;
- erase->opcode = opcode;
- /* JEDEC JESD216B Standard imposes erase sizes to be power of 2. */
- erase->size_shift = ffs(erase->size) - 1;
- erase->size_mask = (1 << erase->size_shift) - 1;
- }
- /**
- * spi_nor_mask_erase_type() - mask out a SPI NOR erase type
- * @erase: pointer to a structure that describes a SPI NOR erase type
- */
- void spi_nor_mask_erase_type(struct spi_nor_erase_type *erase)
- {
- erase->size = 0;
- }
- /**
- * spi_nor_init_uniform_erase_map() - Initialize uniform erase map
- * @map: the erase map of the SPI NOR
- * @erase_mask: bitmask encoding erase types that can erase the entire
- * flash memory
- * @flash_size: the spi nor flash memory size
- */
- void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
- u8 erase_mask, u64 flash_size)
- {
- map->uniform_region.offset = 0;
- map->uniform_region.size = flash_size;
- map->uniform_region.erase_mask = erase_mask;
- map->regions = &map->uniform_region;
- map->n_regions = 1;
- }
- int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
- const struct sfdp_parameter_header *bfpt_header,
- const struct sfdp_bfpt *bfpt)
- {
- int ret;
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->post_bfpt) {
- ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header,
- bfpt);
- if (ret)
- return ret;
- }
- if (nor->info->fixups && nor->info->fixups->post_bfpt)
- return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt);
- return 0;
- }
- static int spi_nor_select_read(struct spi_nor *nor,
- u32 shared_hwcaps)
- {
- int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_READ_MASK) - 1;
- const struct spi_nor_read_command *read;
- if (best_match < 0)
- return -EINVAL;
- cmd = spi_nor_hwcaps_read2cmd(BIT(best_match));
- if (cmd < 0)
- return -EINVAL;
- read = &nor->params->reads[cmd];
- nor->read_opcode = read->opcode;
- nor->read_proto = read->proto;
- /*
- * In the SPI NOR framework, we don't need to make the difference
- * between mode clock cycles and wait state clock cycles.
- * Indeed, the value of the mode clock cycles is used by a QSPI
- * flash memory to know whether it should enter or leave its 0-4-4
- * (Continuous Read / XIP) mode.
- * eXecution In Place is out of the scope of the mtd sub-system.
- * Hence we choose to merge both mode and wait state clock cycles
- * into the so called dummy clock cycles.
- */
- nor->read_dummy = read->num_mode_clocks + read->num_wait_states;
- return 0;
- }
- static int spi_nor_select_pp(struct spi_nor *nor,
- u32 shared_hwcaps)
- {
- int cmd, best_match = fls(shared_hwcaps & SNOR_HWCAPS_PP_MASK) - 1;
- const struct spi_nor_pp_command *pp;
- if (best_match < 0)
- return -EINVAL;
- cmd = spi_nor_hwcaps_pp2cmd(BIT(best_match));
- if (cmd < 0)
- return -EINVAL;
- pp = &nor->params->page_programs[cmd];
- nor->program_opcode = pp->opcode;
- nor->write_proto = pp->proto;
- return 0;
- }
- /**
- * spi_nor_select_uniform_erase() - select optimum uniform erase type
- * @map: the erase map of the SPI NOR
- *
- * Once the optimum uniform sector erase command is found, disable all the
- * other.
- *
- * Return: pointer to erase type on success, NULL otherwise.
- */
- static const struct spi_nor_erase_type *
- spi_nor_select_uniform_erase(struct spi_nor_erase_map *map)
- {
- const struct spi_nor_erase_type *tested_erase, *erase = NULL;
- int i;
- u8 uniform_erase_type = map->uniform_region.erase_mask;
- /*
- * Search for the biggest erase size, except for when compiled
- * to use 4k erases.
- */
- for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
- if (!(uniform_erase_type & BIT(i)))
- continue;
- tested_erase = &map->erase_type[i];
- /* Skip masked erase types. */
- if (!tested_erase->size)
- continue;
- /*
- * If the current erase size is the 4k one, stop here,
- * we have found the right uniform Sector Erase command.
- */
- if (IS_ENABLED(CONFIG_MTD_SPI_NOR_USE_4K_SECTORS) &&
- tested_erase->size == SZ_4K) {
- erase = tested_erase;
- break;
- }
- /*
- * Otherwise, the current erase size is still a valid candidate.
- * Select the biggest valid candidate.
- */
- if (!erase && tested_erase->size)
- erase = tested_erase;
- /* keep iterating to find the wanted_size */
- }
- if (!erase)
- return NULL;
- /* Disable all other Sector Erase commands. */
- map->uniform_region.erase_mask = BIT(erase - map->erase_type);
- return erase;
- }
- static int spi_nor_select_erase(struct spi_nor *nor)
- {
- struct spi_nor_erase_map *map = &nor->params->erase_map;
- const struct spi_nor_erase_type *erase = NULL;
- struct mtd_info *mtd = &nor->mtd;
- int i;
- /*
- * The previous implementation handling Sector Erase commands assumed
- * that the SPI flash memory has an uniform layout then used only one
- * of the supported erase sizes for all Sector Erase commands.
- * So to be backward compatible, the new implementation also tries to
- * manage the SPI flash memory as uniform with a single erase sector
- * size, when possible.
- */
- if (spi_nor_has_uniform_erase(nor)) {
- erase = spi_nor_select_uniform_erase(map);
- if (!erase)
- return -EINVAL;
- nor->erase_opcode = erase->opcode;
- mtd->erasesize = erase->size;
- return 0;
- }
- /*
- * For non-uniform SPI flash memory, set mtd->erasesize to the
- * maximum erase sector size. No need to set nor->erase_opcode.
- */
- for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
- if (map->erase_type[i].size) {
- erase = &map->erase_type[i];
- break;
- }
- }
- if (!erase)
- return -EINVAL;
- mtd->erasesize = erase->size;
- return 0;
- }
- static int spi_nor_set_addr_nbytes(struct spi_nor *nor)
- {
- if (nor->params->addr_nbytes) {
- nor->addr_nbytes = nor->params->addr_nbytes;
- } else if (nor->read_proto == SNOR_PROTO_8_8_8_DTR) {
- /*
- * In 8D-8D-8D mode, one byte takes half a cycle to transfer. So
- * in this protocol an odd addr_nbytes cannot be used because
- * then the address phase would only span a cycle and a half.
- * Half a cycle would be left over. We would then have to start
- * the dummy phase in the middle of a cycle and so too the data
- * phase, and we will end the transaction with half a cycle left
- * over.
- *
- * Force all 8D-8D-8D flashes to use an addr_nbytes of 4 to
- * avoid this situation.
- */
- nor->addr_nbytes = 4;
- } else if (nor->info->addr_nbytes) {
- nor->addr_nbytes = nor->info->addr_nbytes;
- } else {
- nor->addr_nbytes = 3;
- }
- if (nor->addr_nbytes == 3 && nor->params->size > 0x1000000) {
- /* enable 4-byte addressing if the device exceeds 16MiB */
- nor->addr_nbytes = 4;
- }
- if (nor->addr_nbytes > SPI_NOR_MAX_ADDR_NBYTES) {
- dev_dbg(nor->dev, "The number of address bytes is too large: %u\n",
- nor->addr_nbytes);
- return -EINVAL;
- }
- /* Set 4byte opcodes when possible. */
- if (nor->addr_nbytes == 4 && nor->flags & SNOR_F_4B_OPCODES &&
- !(nor->flags & SNOR_F_HAS_4BAIT))
- spi_nor_set_4byte_opcodes(nor);
- return 0;
- }
- static int spi_nor_setup(struct spi_nor *nor,
- const struct spi_nor_hwcaps *hwcaps)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- u32 ignored_mask, shared_mask;
- int err;
- /*
- * Keep only the hardware capabilities supported by both the SPI
- * controller and the SPI flash memory.
- */
- shared_mask = hwcaps->mask & params->hwcaps.mask;
- if (nor->spimem) {
- /*
- * When called from spi_nor_probe(), all caps are set and we
- * need to discard some of them based on what the SPI
- * controller actually supports (using spi_mem_supports_op()).
- */
- spi_nor_spimem_adjust_hwcaps(nor, &shared_mask);
- } else {
- /*
- * SPI n-n-n protocols are not supported when the SPI
- * controller directly implements the spi_nor interface.
- * Yet another reason to switch to spi-mem.
- */
- ignored_mask = SNOR_HWCAPS_X_X_X | SNOR_HWCAPS_X_X_X_DTR;
- if (shared_mask & ignored_mask) {
- dev_dbg(nor->dev,
- "SPI n-n-n protocols are not supported.\n");
- shared_mask &= ~ignored_mask;
- }
- }
- /* Select the (Fast) Read command. */
- err = spi_nor_select_read(nor, shared_mask);
- if (err) {
- dev_dbg(nor->dev,
- "can't select read settings supported by both the SPI controller and memory.\n");
- return err;
- }
- /* Select the Page Program command. */
- err = spi_nor_select_pp(nor, shared_mask);
- if (err) {
- dev_dbg(nor->dev,
- "can't select write settings supported by both the SPI controller and memory.\n");
- return err;
- }
- /* Select the Sector Erase command. */
- err = spi_nor_select_erase(nor);
- if (err) {
- dev_dbg(nor->dev,
- "can't select erase settings supported by both the SPI controller and memory.\n");
- return err;
- }
- return spi_nor_set_addr_nbytes(nor);
- }
- /**
- * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
- * settings based on MFR register and ->default_init() hook.
- * @nor: pointer to a 'struct spi_nor'.
- */
- static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
- {
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->default_init)
- nor->manufacturer->fixups->default_init(nor);
- if (nor->info->fixups && nor->info->fixups->default_init)
- nor->info->fixups->default_init(nor);
- }
- /**
- * spi_nor_no_sfdp_init_params() - Initialize the flash's parameters and
- * settings based on nor->info->sfdp_flags. This method should be called only by
- * flashes that do not define SFDP tables. If the flash supports SFDP but the
- * information is wrong and the settings from this function can not be retrieved
- * by parsing SFDP, one should instead use the fixup hooks and update the wrong
- * bits.
- * @nor: pointer to a 'struct spi_nor'.
- */
- static void spi_nor_no_sfdp_init_params(struct spi_nor *nor)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- struct spi_nor_erase_map *map = ¶ms->erase_map;
- const struct flash_info *info = nor->info;
- const u8 no_sfdp_flags = info->no_sfdp_flags;
- u8 i, erase_mask;
- if (no_sfdp_flags & SPI_NOR_DUAL_READ) {
- params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_2],
- 0, 8, SPINOR_OP_READ_1_1_2,
- SNOR_PROTO_1_1_2);
- }
- if (no_sfdp_flags & SPI_NOR_QUAD_READ) {
- params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_4],
- 0, 8, SPINOR_OP_READ_1_1_4,
- SNOR_PROTO_1_1_4);
- }
- if (no_sfdp_flags & SPI_NOR_OCTAL_READ) {
- params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_1_1_8],
- 0, 8, SPINOR_OP_READ_1_1_8,
- SNOR_PROTO_1_1_8);
- }
- if (no_sfdp_flags & SPI_NOR_OCTAL_DTR_READ) {
- params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_8_8_8_DTR],
- 0, 20, SPINOR_OP_READ_FAST,
- SNOR_PROTO_8_8_8_DTR);
- }
- if (no_sfdp_flags & SPI_NOR_OCTAL_DTR_PP) {
- params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
- /*
- * Since xSPI Page Program opcode is backward compatible with
- * Legacy SPI, use Legacy SPI opcode there as well.
- */
- spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_8_8_8_DTR],
- SPINOR_OP_PP, SNOR_PROTO_8_8_8_DTR);
- }
- /*
- * Sector Erase settings. Sort Erase Types in ascending order, with the
- * smallest erase size starting at BIT(0).
- */
- erase_mask = 0;
- i = 0;
- if (no_sfdp_flags & SECT_4K) {
- erase_mask |= BIT(i);
- spi_nor_set_erase_type(&map->erase_type[i], 4096u,
- SPINOR_OP_BE_4K);
- i++;
- }
- erase_mask |= BIT(i);
- spi_nor_set_erase_type(&map->erase_type[i],
- info->sector_size ?: SPI_NOR_DEFAULT_SECTOR_SIZE,
- SPINOR_OP_SE);
- spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
- }
- /**
- * spi_nor_init_flags() - Initialize NOR flags for settings that are not defined
- * in the JESD216 SFDP standard, thus can not be retrieved when parsing SFDP.
- * @nor: pointer to a 'struct spi_nor'
- */
- static void spi_nor_init_flags(struct spi_nor *nor)
- {
- struct device_node *np = spi_nor_get_flash_node(nor);
- const u16 flags = nor->info->flags;
- if (of_property_read_bool(np, "broken-flash-reset"))
- nor->flags |= SNOR_F_BROKEN_RESET;
- if (of_property_read_bool(np, "no-wp"))
- nor->flags |= SNOR_F_NO_WP;
- if (flags & SPI_NOR_SWP_IS_VOLATILE)
- nor->flags |= SNOR_F_SWP_IS_VOLATILE;
- if (flags & SPI_NOR_HAS_LOCK)
- nor->flags |= SNOR_F_HAS_LOCK;
- if (flags & SPI_NOR_HAS_TB) {
- nor->flags |= SNOR_F_HAS_SR_TB;
- if (flags & SPI_NOR_TB_SR_BIT6)
- nor->flags |= SNOR_F_HAS_SR_TB_BIT6;
- }
- if (flags & SPI_NOR_4BIT_BP) {
- nor->flags |= SNOR_F_HAS_4BIT_BP;
- if (flags & SPI_NOR_BP3_SR_BIT6)
- nor->flags |= SNOR_F_HAS_SR_BP3_BIT6;
- }
- if (flags & SPI_NOR_RWW && nor->params->n_banks > 1 &&
- !nor->controller_ops)
- nor->flags |= SNOR_F_RWW;
- }
- /**
- * spi_nor_init_fixup_flags() - Initialize NOR flags for settings that can not
- * be discovered by SFDP for this particular flash because the SFDP table that
- * indicates this support is not defined in the flash. In case the table for
- * this support is defined but has wrong values, one should instead use a
- * post_sfdp() hook to set the SNOR_F equivalent flag.
- * @nor: pointer to a 'struct spi_nor'
- */
- static void spi_nor_init_fixup_flags(struct spi_nor *nor)
- {
- const u8 fixup_flags = nor->info->fixup_flags;
- if (fixup_flags & SPI_NOR_4B_OPCODES)
- nor->flags |= SNOR_F_4B_OPCODES;
- if (fixup_flags & SPI_NOR_IO_MODE_EN_VOLATILE)
- nor->flags |= SNOR_F_IO_MODE_EN_VOLATILE;
- }
- /**
- * spi_nor_late_init_params() - Late initialization of default flash parameters.
- * @nor: pointer to a 'struct spi_nor'
- *
- * Used to initialize flash parameters that are not declared in the JESD216
- * SFDP standard, or where SFDP tables are not defined at all.
- * Will replace the spi_nor_manufacturer_init_params() method.
- */
- static int spi_nor_late_init_params(struct spi_nor *nor)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- int ret;
- if (nor->manufacturer && nor->manufacturer->fixups &&
- nor->manufacturer->fixups->late_init) {
- ret = nor->manufacturer->fixups->late_init(nor);
- if (ret)
- return ret;
- }
- /* Needed by some flashes late_init hooks. */
- spi_nor_init_flags(nor);
- if (nor->info->fixups && nor->info->fixups->late_init) {
- ret = nor->info->fixups->late_init(nor);
- if (ret)
- return ret;
- }
- if (!nor->params->die_erase_opcode)
- nor->params->die_erase_opcode = SPINOR_OP_CHIP_ERASE;
- /* Default method kept for backward compatibility. */
- if (!params->set_4byte_addr_mode)
- params->set_4byte_addr_mode = spi_nor_set_4byte_addr_mode_brwr;
- spi_nor_init_fixup_flags(nor);
- /*
- * NOR protection support. When locking_ops are not provided, we pick
- * the default ones.
- */
- if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
- spi_nor_init_default_locking_ops(nor);
- if (params->n_banks > 1)
- params->bank_size = div_u64(params->size, params->n_banks);
- return 0;
- }
- /**
- * spi_nor_sfdp_init_params_deprecated() - Deprecated way of initializing flash
- * parameters and settings based on JESD216 SFDP standard.
- * @nor: pointer to a 'struct spi_nor'.
- *
- * The method has a roll-back mechanism: in case the SFDP parsing fails, the
- * legacy flash parameters and settings will be restored.
- */
- static void spi_nor_sfdp_init_params_deprecated(struct spi_nor *nor)
- {
- struct spi_nor_flash_parameter sfdp_params;
- memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
- if (spi_nor_parse_sfdp(nor)) {
- memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
- nor->flags &= ~SNOR_F_4B_OPCODES;
- }
- }
- /**
- * spi_nor_init_params_deprecated() - Deprecated way of initializing flash
- * parameters and settings.
- * @nor: pointer to a 'struct spi_nor'.
- *
- * The method assumes that flash doesn't support SFDP so it initializes flash
- * parameters in spi_nor_no_sfdp_init_params() which later on can be overwritten
- * when parsing SFDP, if supported.
- */
- static void spi_nor_init_params_deprecated(struct spi_nor *nor)
- {
- spi_nor_no_sfdp_init_params(nor);
- spi_nor_manufacturer_init_params(nor);
- if (nor->info->no_sfdp_flags & (SPI_NOR_DUAL_READ |
- SPI_NOR_QUAD_READ |
- SPI_NOR_OCTAL_READ |
- SPI_NOR_OCTAL_DTR_READ))
- spi_nor_sfdp_init_params_deprecated(nor);
- }
- /**
- * spi_nor_init_default_params() - Default initialization of flash parameters
- * and settings. Done for all flashes, regardless is they define SFDP tables
- * or not.
- * @nor: pointer to a 'struct spi_nor'.
- */
- static void spi_nor_init_default_params(struct spi_nor *nor)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- const struct flash_info *info = nor->info;
- struct device_node *np = spi_nor_get_flash_node(nor);
- params->quad_enable = spi_nor_sr2_bit1_quad_enable;
- params->otp.org = info->otp;
- /* Default to 16-bit Write Status (01h) Command */
- nor->flags |= SNOR_F_HAS_16BIT_SR;
- /* Set SPI NOR sizes. */
- params->writesize = 1;
- params->size = info->size;
- params->bank_size = params->size;
- params->page_size = info->page_size ?: SPI_NOR_DEFAULT_PAGE_SIZE;
- params->n_banks = info->n_banks ?: SPI_NOR_DEFAULT_N_BANKS;
- /* Default to Fast Read for non-DT and enable it if requested by DT. */
- if (!np || of_property_read_bool(np, "m25p,fast-read"))
- params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
- /* (Fast) Read settings. */
- params->hwcaps.mask |= SNOR_HWCAPS_READ;
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ],
- 0, 0, SPINOR_OP_READ,
- SNOR_PROTO_1_1_1);
- if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
- spi_nor_set_read_settings(¶ms->reads[SNOR_CMD_READ_FAST],
- 0, 8, SPINOR_OP_READ_FAST,
- SNOR_PROTO_1_1_1);
- /* Page Program settings. */
- params->hwcaps.mask |= SNOR_HWCAPS_PP;
- spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP],
- SPINOR_OP_PP, SNOR_PROTO_1_1_1);
- if (info->flags & SPI_NOR_QUAD_PP) {
- params->hwcaps.mask |= SNOR_HWCAPS_PP_1_1_4;
- spi_nor_set_pp_settings(¶ms->page_programs[SNOR_CMD_PP_1_1_4],
- SPINOR_OP_PP_1_1_4, SNOR_PROTO_1_1_4);
- }
- }
- /**
- * spi_nor_init_params() - Initialize the flash's parameters and settings.
- * @nor: pointer to a 'struct spi_nor'.
- *
- * The flash parameters and settings are initialized based on a sequence of
- * calls that are ordered by priority:
- *
- * 1/ Default flash parameters initialization. The initializations are done
- * based on nor->info data:
- * spi_nor_info_init_params()
- *
- * which can be overwritten by:
- * 2/ Manufacturer flash parameters initialization. The initializations are
- * done based on MFR register, or when the decisions can not be done solely
- * based on MFR, by using specific flash_info tweeks, ->default_init():
- * spi_nor_manufacturer_init_params()
- *
- * which can be overwritten by:
- * 3/ SFDP flash parameters initialization. JESD216 SFDP is a standard and
- * should be more accurate that the above.
- * spi_nor_parse_sfdp() or spi_nor_no_sfdp_init_params()
- *
- * Please note that there is a ->post_bfpt() fixup hook that can overwrite
- * the flash parameters and settings immediately after parsing the Basic
- * Flash Parameter Table.
- * spi_nor_post_sfdp_fixups() is called after the SFDP tables are parsed.
- * It is used to tweak various flash parameters when information provided
- * by the SFDP tables are wrong.
- *
- * which can be overwritten by:
- * 4/ Late flash parameters initialization, used to initialize flash
- * parameters that are not declared in the JESD216 SFDP standard, or where SFDP
- * tables are not defined at all.
- * spi_nor_late_init_params()
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_init_params(struct spi_nor *nor)
- {
- int ret;
- nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
- if (!nor->params)
- return -ENOMEM;
- spi_nor_init_default_params(nor);
- if (spi_nor_needs_sfdp(nor)) {
- ret = spi_nor_parse_sfdp(nor);
- if (ret) {
- dev_err(nor->dev, "BFPT parsing failed. Please consider using SPI_NOR_SKIP_SFDP when declaring the flash\n");
- return ret;
- }
- } else if (nor->info->no_sfdp_flags & SPI_NOR_SKIP_SFDP) {
- spi_nor_no_sfdp_init_params(nor);
- } else {
- spi_nor_init_params_deprecated(nor);
- }
- ret = spi_nor_late_init_params(nor);
- if (ret)
- return ret;
- if (WARN_ON(!is_power_of_2(nor->params->page_size)))
- return -EINVAL;
- return 0;
- }
- /** spi_nor_set_octal_dtr() - enable or disable Octal DTR I/O.
- * @nor: pointer to a 'struct spi_nor'
- * @enable: whether to enable or disable Octal DTR
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_set_octal_dtr(struct spi_nor *nor, bool enable)
- {
- int ret;
- if (!nor->params->set_octal_dtr)
- return 0;
- if (!(nor->read_proto == SNOR_PROTO_8_8_8_DTR &&
- nor->write_proto == SNOR_PROTO_8_8_8_DTR))
- return 0;
- if (!(nor->flags & SNOR_F_IO_MODE_EN_VOLATILE))
- return 0;
- ret = nor->params->set_octal_dtr(nor, enable);
- if (ret)
- return ret;
- if (enable)
- nor->reg_proto = SNOR_PROTO_8_8_8_DTR;
- else
- nor->reg_proto = SNOR_PROTO_1_1_1;
- return 0;
- }
- /**
- * spi_nor_quad_enable() - enable Quad I/O if needed.
- * @nor: pointer to a 'struct spi_nor'
- *
- * Return: 0 on success, -errno otherwise.
- */
- static int spi_nor_quad_enable(struct spi_nor *nor)
- {
- if (!nor->params->quad_enable)
- return 0;
- if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
- spi_nor_get_protocol_width(nor->write_proto) == 4))
- return 0;
- return nor->params->quad_enable(nor);
- }
- /**
- * spi_nor_set_4byte_addr_mode() - Set address mode.
- * @nor: pointer to a 'struct spi_nor'.
- * @enable: enable/disable 4 byte address mode.
- *
- * Return: 0 on success, -errno otherwise.
- */
- int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
- {
- struct spi_nor_flash_parameter *params = nor->params;
- int ret;
- if (enable) {
- /*
- * If the RESET# pin isn't hooked up properly, or the system
- * otherwise doesn't perform a reset command in the boot
- * sequence, it's impossible to 100% protect against unexpected
- * reboots (e.g., crashes). Warn the user (or hopefully, system
- * designer) that this is bad.
- */
- WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
- "enabling reset hack; may not recover from unexpected reboots\n");
- }
- ret = params->set_4byte_addr_mode(nor, enable);
- if (ret && ret != -EOPNOTSUPP)
- return ret;
- if (enable) {
- params->addr_nbytes = 4;
- params->addr_mode_nbytes = 4;
- } else {
- params->addr_nbytes = 3;
- params->addr_mode_nbytes = 3;
- }
- return 0;
- }
- static int spi_nor_init(struct spi_nor *nor)
- {
- int err;
- err = spi_nor_set_octal_dtr(nor, true);
- if (err) {
- dev_dbg(nor->dev, "octal mode not supported\n");
- return err;
- }
- err = spi_nor_quad_enable(nor);
- if (err) {
- dev_dbg(nor->dev, "quad mode not supported\n");
- return err;
- }
- /*
- * Some SPI NOR flashes are write protected by default after a power-on
- * reset cycle, in order to avoid inadvertent writes during power-up.
- * Backward compatibility imposes to unlock the entire flash memory
- * array at power-up by default. Depending on the kernel configuration
- * (1) do nothing, (2) always unlock the entire flash array or (3)
- * unlock the entire flash array only when the software write
- * protection bits are volatile. The latter is indicated by
- * SNOR_F_SWP_IS_VOLATILE.
- */
- if (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE) ||
- (IS_ENABLED(CONFIG_MTD_SPI_NOR_SWP_DISABLE_ON_VOLATILE) &&
- nor->flags & SNOR_F_SWP_IS_VOLATILE))
- spi_nor_try_unlock_all(nor);
- if (nor->addr_nbytes == 4 &&
- nor->read_proto != SNOR_PROTO_8_8_8_DTR &&
- !(nor->flags & SNOR_F_4B_OPCODES))
- return spi_nor_set_4byte_addr_mode(nor, true);
- return 0;
- }
- /**
- * spi_nor_soft_reset() - Perform a software reset
- * @nor: pointer to 'struct spi_nor'
- *
- * Performs a "Soft Reset and Enter Default Protocol Mode" sequence which resets
- * the device to its power-on-reset state. This is useful when the software has
- * made some changes to device (volatile) registers and needs to reset it before
- * shutting down, for example.
- *
- * Not every flash supports this sequence. The same set of opcodes might be used
- * for some other operation on a flash that does not support this. Support for
- * this sequence can be discovered via SFDP in the BFPT table.
- *
- * Return: 0 on success, -errno otherwise.
- */
- static void spi_nor_soft_reset(struct spi_nor *nor)
- {
- struct spi_mem_op op;
- int ret;
- op = (struct spi_mem_op)SPINOR_SRSTEN_OP;
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- if (ret) {
- if (ret != -EOPNOTSUPP)
- dev_warn(nor->dev, "Software reset failed: %d\n", ret);
- return;
- }
- op = (struct spi_mem_op)SPINOR_SRST_OP;
- spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
- ret = spi_mem_exec_op(nor->spimem, &op);
- if (ret) {
- dev_warn(nor->dev, "Software reset failed: %d\n", ret);
- return;
- }
- /*
- * Software Reset is not instant, and the delay varies from flash to
- * flash. Looking at a few flashes, most range somewhere below 100
- * microseconds. So, sleep for a range of 200-400 us.
- */
- usleep_range(SPI_NOR_SRST_SLEEP_MIN, SPI_NOR_SRST_SLEEP_MAX);
- }
- /* mtd suspend handler */
- static int spi_nor_suspend(struct mtd_info *mtd)
- {
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- int ret;
- /* Disable octal DTR mode if we enabled it. */
- ret = spi_nor_set_octal_dtr(nor, false);
- if (ret)
- dev_err(nor->dev, "suspend() failed\n");
- return ret;
- }
- /* mtd resume handler */
- static void spi_nor_resume(struct mtd_info *mtd)
- {
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- struct device *dev = nor->dev;
- int ret;
- /* re-initialize the nor chip */
- ret = spi_nor_init(nor);
- if (ret)
- dev_err(dev, "resume() failed\n");
- }
- static int spi_nor_get_device(struct mtd_info *mtd)
- {
- struct mtd_info *master = mtd_get_master(mtd);
- struct spi_nor *nor = mtd_to_spi_nor(master);
- struct device *dev;
- if (nor->spimem)
- dev = nor->spimem->spi->controller->dev.parent;
- else
- dev = nor->dev;
- if (!try_module_get(dev->driver->owner))
- return -ENODEV;
- return 0;
- }
- static void spi_nor_put_device(struct mtd_info *mtd)
- {
- struct mtd_info *master = mtd_get_master(mtd);
- struct spi_nor *nor = mtd_to_spi_nor(master);
- struct device *dev;
- if (nor->spimem)
- dev = nor->spimem->spi->controller->dev.parent;
- else
- dev = nor->dev;
- module_put(dev->driver->owner);
- }
- static void spi_nor_restore(struct spi_nor *nor)
- {
- int ret;
- /* restore the addressing mode */
- if (nor->addr_nbytes == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
- nor->flags & SNOR_F_BROKEN_RESET) {
- ret = spi_nor_set_4byte_addr_mode(nor, false);
- if (ret)
- /*
- * Do not stop the execution in the hope that the flash
- * will default to the 3-byte address mode after the
- * software reset.
- */
- dev_err(nor->dev, "Failed to exit 4-byte address mode, err = %d\n", ret);
- }
- if (nor->flags & SNOR_F_SOFT_RESET)
- spi_nor_soft_reset(nor);
- }
- static const struct flash_info *spi_nor_match_name(struct spi_nor *nor,
- const char *name)
- {
- unsigned int i, j;
- for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
- for (j = 0; j < manufacturers[i]->nparts; j++) {
- if (manufacturers[i]->parts[j].name &&
- !strcmp(name, manufacturers[i]->parts[j].name)) {
- nor->manufacturer = manufacturers[i];
- return &manufacturers[i]->parts[j];
- }
- }
- }
- return NULL;
- }
- static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
- const char *name)
- {
- const struct flash_info *info = NULL;
- if (name)
- info = spi_nor_match_name(nor, name);
- /*
- * Auto-detect if chip name wasn't specified or not found, or the chip
- * has an ID. If the chip supposedly has an ID, we also do an
- * auto-detection to compare it later.
- */
- if (!info || info->id) {
- const struct flash_info *jinfo;
- jinfo = spi_nor_detect(nor);
- if (IS_ERR(jinfo))
- return jinfo;
- /*
- * If caller has specified name of flash model that can normally
- * be detected using JEDEC, let's verify it.
- */
- if (info && jinfo != info)
- dev_warn(nor->dev, "found %s, expected %s\n",
- jinfo->name, info->name);
- /* If info was set before, JEDEC knows better. */
- info = jinfo;
- }
- return info;
- }
- static u32
- spi_nor_get_region_erasesize(const struct spi_nor_erase_region *region,
- const struct spi_nor_erase_type *erase_type)
- {
- int i;
- if (region->overlaid)
- return region->size;
- for (i = SNOR_ERASE_TYPE_MAX - 1; i >= 0; i--) {
- if (region->erase_mask & BIT(i))
- return erase_type[i].size;
- }
- return 0;
- }
- static int spi_nor_set_mtd_eraseregions(struct spi_nor *nor)
- {
- const struct spi_nor_erase_map *map = &nor->params->erase_map;
- const struct spi_nor_erase_region *region = map->regions;
- struct mtd_erase_region_info *mtd_region;
- struct mtd_info *mtd = &nor->mtd;
- u32 erasesize, i;
- mtd_region = devm_kcalloc(nor->dev, map->n_regions, sizeof(*mtd_region),
- GFP_KERNEL);
- if (!mtd_region)
- return -ENOMEM;
- for (i = 0; i < map->n_regions; i++) {
- erasesize = spi_nor_get_region_erasesize(®ion[i],
- map->erase_type);
- if (!erasesize)
- return -EINVAL;
- mtd_region[i].erasesize = erasesize;
- mtd_region[i].numblocks = div_u64(region[i].size, erasesize);
- mtd_region[i].offset = region[i].offset;
- }
- mtd->numeraseregions = map->n_regions;
- mtd->eraseregions = mtd_region;
- return 0;
- }
- static int spi_nor_set_mtd_info(struct spi_nor *nor)
- {
- struct mtd_info *mtd = &nor->mtd;
- struct device *dev = nor->dev;
- spi_nor_set_mtd_locking_ops(nor);
- spi_nor_set_mtd_otp_ops(nor);
- mtd->dev.parent = dev;
- if (!mtd->name)
- mtd->name = dev_name(dev);
- mtd->type = MTD_NORFLASH;
- mtd->flags = MTD_CAP_NORFLASH;
- /* Unset BIT_WRITEABLE to enable JFFS2 write buffer for ECC'd NOR */
- if (nor->flags & SNOR_F_ECC)
- mtd->flags &= ~MTD_BIT_WRITEABLE;
- if (nor->info->flags & SPI_NOR_NO_ERASE)
- mtd->flags |= MTD_NO_ERASE;
- else
- mtd->_erase = spi_nor_erase;
- mtd->writesize = nor->params->writesize;
- mtd->writebufsize = nor->params->page_size;
- mtd->size = nor->params->size;
- mtd->_read = spi_nor_read;
- /* Might be already set by some SST flashes. */
- if (!mtd->_write)
- mtd->_write = spi_nor_write;
- mtd->_suspend = spi_nor_suspend;
- mtd->_resume = spi_nor_resume;
- mtd->_get_device = spi_nor_get_device;
- mtd->_put_device = spi_nor_put_device;
- if (!spi_nor_has_uniform_erase(nor))
- return spi_nor_set_mtd_eraseregions(nor);
- return 0;
- }
- static int spi_nor_hw_reset(struct spi_nor *nor)
- {
- struct gpio_desc *reset;
- reset = devm_gpiod_get_optional(nor->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR_OR_NULL(reset))
- return PTR_ERR_OR_ZERO(reset);
- /*
- * Experimental delay values by looking at different flash device
- * vendors datasheets.
- */
- usleep_range(1, 5);
- gpiod_set_value_cansleep(reset, 1);
- usleep_range(100, 150);
- gpiod_set_value_cansleep(reset, 0);
- usleep_range(1000, 1200);
- return 0;
- }
- int spi_nor_scan(struct spi_nor *nor, const char *name,
- const struct spi_nor_hwcaps *hwcaps)
- {
- const struct flash_info *info;
- struct device *dev = nor->dev;
- int ret;
- ret = spi_nor_check(nor);
- if (ret)
- return ret;
- /* Reset SPI protocol for all commands. */
- nor->reg_proto = SNOR_PROTO_1_1_1;
- nor->read_proto = SNOR_PROTO_1_1_1;
- nor->write_proto = SNOR_PROTO_1_1_1;
- /*
- * We need the bounce buffer early to read/write registers when going
- * through the spi-mem layer (buffers have to be DMA-able).
- * For spi-mem drivers, we'll reallocate a new buffer if
- * nor->params->page_size turns out to be greater than PAGE_SIZE (which
- * shouldn't happen before long since NOR pages are usually less
- * than 1KB) after spi_nor_scan() returns.
- */
- nor->bouncebuf_size = PAGE_SIZE;
- nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
- GFP_KERNEL);
- if (!nor->bouncebuf)
- return -ENOMEM;
- ret = spi_nor_hw_reset(nor);
- if (ret)
- return ret;
- info = spi_nor_get_flash_info(nor, name);
- if (IS_ERR(info))
- return PTR_ERR(info);
- nor->info = info;
- mutex_init(&nor->lock);
- /* Init flash parameters based on flash_info struct and SFDP */
- ret = spi_nor_init_params(nor);
- if (ret)
- return ret;
- if (spi_nor_use_parallel_locking(nor))
- init_waitqueue_head(&nor->rww.wait);
- /*
- * Configure the SPI memory:
- * - select op codes for (Fast) Read, Page Program and Sector Erase.
- * - set the number of dummy cycles (mode cycles + wait states).
- * - set the SPI protocols for register and memory accesses.
- * - set the number of address bytes.
- */
- ret = spi_nor_setup(nor, hwcaps);
- if (ret)
- return ret;
- /* Send all the required SPI flash commands to initialize device */
- ret = spi_nor_init(nor);
- if (ret)
- return ret;
- /* No mtd_info fields should be used up to this point. */
- ret = spi_nor_set_mtd_info(nor);
- if (ret)
- return ret;
- dev_dbg(dev, "Manufacturer and device ID: %*phN\n",
- SPI_NOR_MAX_ID_LEN, nor->id);
- return 0;
- }
- EXPORT_SYMBOL_GPL(spi_nor_scan);
- static int spi_nor_create_read_dirmap(struct spi_nor *nor)
- {
- struct spi_mem_dirmap_info info = {
- .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
- SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
- SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
- SPI_MEM_OP_DATA_IN(0, NULL, 0)),
- .offset = 0,
- .length = nor->params->size,
- };
- struct spi_mem_op *op = &info.op_tmpl;
- spi_nor_spimem_setup_op(nor, op, nor->read_proto);
- /* convert the dummy cycles to the number of bytes */
- op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8;
- if (spi_nor_protocol_is_dtr(nor->read_proto))
- op->dummy.nbytes *= 2;
- /*
- * Since spi_nor_spimem_setup_op() only sets buswidth when the number
- * of data bytes is non-zero, the data buswidth won't be set here. So,
- * do it explicitly.
- */
- op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
- nor->dirmap.rdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem,
- &info);
- return PTR_ERR_OR_ZERO(nor->dirmap.rdesc);
- }
- static int spi_nor_create_write_dirmap(struct spi_nor *nor)
- {
- struct spi_mem_dirmap_info info = {
- .op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 0),
- SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
- SPI_MEM_OP_NO_DUMMY,
- SPI_MEM_OP_DATA_OUT(0, NULL, 0)),
- .offset = 0,
- .length = nor->params->size,
- };
- struct spi_mem_op *op = &info.op_tmpl;
- if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
- op->addr.nbytes = 0;
- spi_nor_spimem_setup_op(nor, op, nor->write_proto);
- /*
- * Since spi_nor_spimem_setup_op() only sets buswidth when the number
- * of data bytes is non-zero, the data buswidth won't be set here. So,
- * do it explicitly.
- */
- op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
- nor->dirmap.wdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem,
- &info);
- return PTR_ERR_OR_ZERO(nor->dirmap.wdesc);
- }
- static int spi_nor_probe(struct spi_mem *spimem)
- {
- struct spi_device *spi = spimem->spi;
- struct device *dev = &spi->dev;
- struct flash_platform_data *data = dev_get_platdata(dev);
- struct spi_nor *nor;
- /*
- * Enable all caps by default. The core will mask them after
- * checking what's really supported using spi_mem_supports_op().
- */
- const struct spi_nor_hwcaps hwcaps = { .mask = SNOR_HWCAPS_ALL };
- char *flash_name;
- int ret;
- ret = devm_regulator_get_enable(dev, "vcc");
- if (ret)
- return ret;
- nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL);
- if (!nor)
- return -ENOMEM;
- nor->spimem = spimem;
- nor->dev = dev;
- spi_nor_set_flash_node(nor, dev->of_node);
- spi_mem_set_drvdata(spimem, nor);
- if (data && data->name)
- nor->mtd.name = data->name;
- if (!nor->mtd.name)
- nor->mtd.name = spi_mem_get_name(spimem);
- /*
- * For some (historical?) reason many platforms provide two different
- * names in flash_platform_data: "name" and "type". Quite often name is
- * set to "m25p80" and then "type" provides a real chip name.
- * If that's the case, respect "type" and ignore a "name".
- */
- if (data && data->type)
- flash_name = data->type;
- else if (!strcmp(spi->modalias, "spi-nor"))
- flash_name = NULL; /* auto-detect */
- else
- flash_name = spi->modalias;
- ret = spi_nor_scan(nor, flash_name, &hwcaps);
- if (ret)
- return ret;
- spi_nor_debugfs_register(nor);
- /*
- * None of the existing parts have > 512B pages, but let's play safe
- * and add this logic so that if anyone ever adds support for such
- * a NOR we don't end up with buffer overflows.
- */
- if (nor->params->page_size > PAGE_SIZE) {
- nor->bouncebuf_size = nor->params->page_size;
- devm_kfree(dev, nor->bouncebuf);
- nor->bouncebuf = devm_kmalloc(dev, nor->bouncebuf_size,
- GFP_KERNEL);
- if (!nor->bouncebuf)
- return -ENOMEM;
- }
- ret = spi_nor_create_read_dirmap(nor);
- if (ret)
- return ret;
- ret = spi_nor_create_write_dirmap(nor);
- if (ret)
- return ret;
- return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
- data ? data->nr_parts : 0);
- }
- static int spi_nor_remove(struct spi_mem *spimem)
- {
- struct spi_nor *nor = spi_mem_get_drvdata(spimem);
- spi_nor_restore(nor);
- /* Clean up MTD stuff. */
- return mtd_device_unregister(&nor->mtd);
- }
- static void spi_nor_shutdown(struct spi_mem *spimem)
- {
- struct spi_nor *nor = spi_mem_get_drvdata(spimem);
- spi_nor_restore(nor);
- }
- /*
- * Do NOT add to this array without reading the following:
- *
- * Historically, many flash devices are bound to this driver by their name. But
- * since most of these flash are compatible to some extent, and their
- * differences can often be differentiated by the JEDEC read-ID command, we
- * encourage new users to add support to the spi-nor library, and simply bind
- * against a generic string here (e.g., "jedec,spi-nor").
- *
- * Many flash names are kept here in this list to keep them available
- * as module aliases for existing platforms.
- */
- static const struct spi_device_id spi_nor_dev_ids[] = {
- /*
- * Allow non-DT platform devices to bind to the "spi-nor" modalias, and
- * hack around the fact that the SPI core does not provide uevent
- * matching for .of_match_table
- */
- {"spi-nor"},
- /*
- * Entries not used in DTs that should be safe to drop after replacing
- * them with "spi-nor" in platform data.
- */
- {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"},
- /*
- * Entries that were used in DTs without "jedec,spi-nor" fallback and
- * should be kept for backward compatibility.
- */
- {"at25df321a"}, {"at25df641"}, {"at26df081a"},
- {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"},
- {"mx25l25635e"},{"mx66l51235l"},
- {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"},
- {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"},
- {"s25fl064k"},
- {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"},
- {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"},
- {"m25p64"}, {"m25p128"},
- {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"},
- {"w25q80bl"}, {"w25q128"}, {"w25q256"},
- /* Flashes that can't be detected using JEDEC */
- {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"},
- {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"},
- {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"},
- /* Everspin MRAMs (non-JEDEC) */
- { "mr25h128" }, /* 128 Kib, 40 MHz */
- { "mr25h256" }, /* 256 Kib, 40 MHz */
- { "mr25h10" }, /* 1 Mib, 40 MHz */
- { "mr25h40" }, /* 4 Mib, 40 MHz */
- { },
- };
- MODULE_DEVICE_TABLE(spi, spi_nor_dev_ids);
- static const struct of_device_id spi_nor_of_table[] = {
- /*
- * Generic compatibility for SPI NOR that can be identified by the
- * JEDEC READ ID opcode (0x9F). Use this, if possible.
- */
- { .compatible = "jedec,spi-nor" },
- { /* sentinel */ },
- };
- MODULE_DEVICE_TABLE(of, spi_nor_of_table);
- /*
- * REVISIT: many of these chips have deep power-down modes, which
- * should clearly be entered on suspend() to minimize power use.
- * And also when they're otherwise idle...
- */
- static struct spi_mem_driver spi_nor_driver = {
- .spidrv = {
- .driver = {
- .name = "spi-nor",
- .of_match_table = spi_nor_of_table,
- .dev_groups = spi_nor_sysfs_groups,
- },
- .id_table = spi_nor_dev_ids,
- },
- .probe = spi_nor_probe,
- .remove = spi_nor_remove,
- .shutdown = spi_nor_shutdown,
- };
- static int __init spi_nor_module_init(void)
- {
- return spi_mem_driver_register(&spi_nor_driver);
- }
- module_init(spi_nor_module_init);
- static void __exit spi_nor_module_exit(void)
- {
- spi_mem_driver_unregister(&spi_nor_driver);
- spi_nor_debugfs_shutdown();
- }
- module_exit(spi_nor_module_exit);
- MODULE_LICENSE("GPL v2");
- MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>");
- MODULE_AUTHOR("Mike Lavender");
- MODULE_DESCRIPTION("framework for SPI NOR");
|