| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Copyright (C) STMicroelectronics 2020
- */
- #include <linux/bitfield.h>
- #include <linux/clk.h>
- #include <linux/mfd/syscon.h>
- #include <linux/module.h>
- #include <linux/of.h>
- #include <linux/of_platform.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/platform_device.h>
- #include <linux/pm_runtime.h>
- #include <linux/regmap.h>
- #include <linux/reset.h>
- /* FMC2 Controller Registers */
- #define FMC2_BCR1 0x0
- #define FMC2_BTR1 0x4
- #define FMC2_BCR(x) ((x) * 0x8 + FMC2_BCR1)
- #define FMC2_BTR(x) ((x) * 0x8 + FMC2_BTR1)
- #define FMC2_PCSCNTR 0x20
- #define FMC2_CFGR 0x20
- #define FMC2_SR 0x84
- #define FMC2_BWTR1 0x104
- #define FMC2_BWTR(x) ((x) * 0x8 + FMC2_BWTR1)
- #define FMC2_SECCFGR 0x300
- #define FMC2_CIDCFGR0 0x30c
- #define FMC2_CIDCFGR(x) ((x) * 0x8 + FMC2_CIDCFGR0)
- #define FMC2_SEMCR0 0x310
- #define FMC2_SEMCR(x) ((x) * 0x8 + FMC2_SEMCR0)
- /* Register: FMC2_BCR1 */
- #define FMC2_BCR1_CCLKEN BIT(20)
- #define FMC2_BCR1_FMC2EN BIT(31)
- /* Register: FMC2_BCRx */
- #define FMC2_BCR_MBKEN BIT(0)
- #define FMC2_BCR_MUXEN BIT(1)
- #define FMC2_BCR_MTYP GENMASK(3, 2)
- #define FMC2_BCR_MWID GENMASK(5, 4)
- #define FMC2_BCR_FACCEN BIT(6)
- #define FMC2_BCR_BURSTEN BIT(8)
- #define FMC2_BCR_WAITPOL BIT(9)
- #define FMC2_BCR_WAITCFG BIT(11)
- #define FMC2_BCR_WREN BIT(12)
- #define FMC2_BCR_WAITEN BIT(13)
- #define FMC2_BCR_EXTMOD BIT(14)
- #define FMC2_BCR_ASYNCWAIT BIT(15)
- #define FMC2_BCR_CPSIZE GENMASK(18, 16)
- #define FMC2_BCR_CBURSTRW BIT(19)
- #define FMC2_BCR_CSCOUNT GENMASK(21, 20)
- #define FMC2_BCR_NBLSET GENMASK(23, 22)
- /* Register: FMC2_BTRx/FMC2_BWTRx */
- #define FMC2_BXTR_ADDSET GENMASK(3, 0)
- #define FMC2_BXTR_ADDHLD GENMASK(7, 4)
- #define FMC2_BXTR_DATAST GENMASK(15, 8)
- #define FMC2_BXTR_BUSTURN GENMASK(19, 16)
- #define FMC2_BTR_CLKDIV GENMASK(23, 20)
- #define FMC2_BTR_DATLAT GENMASK(27, 24)
- #define FMC2_BXTR_ACCMOD GENMASK(29, 28)
- #define FMC2_BXTR_DATAHLD GENMASK(31, 30)
- /* Register: FMC2_PCSCNTR */
- #define FMC2_PCSCNTR_CSCOUNT GENMASK(15, 0)
- #define FMC2_PCSCNTR_CNTBEN(x) BIT((x) + 16)
- /* Register: FMC2_CFGR */
- #define FMC2_CFGR_CLKDIV GENMASK(19, 16)
- #define FMC2_CFGR_CCLKEN BIT(20)
- #define FMC2_CFGR_FMC2EN BIT(31)
- /* Register: FMC2_SR */
- #define FMC2_SR_ISOST GENMASK(1, 0)
- /* Register: FMC2_CIDCFGR */
- #define FMC2_CIDCFGR_CFEN BIT(0)
- #define FMC2_CIDCFGR_SEMEN BIT(1)
- #define FMC2_CIDCFGR_SCID GENMASK(6, 4)
- #define FMC2_CIDCFGR_SEMWLC1 BIT(17)
- /* Register: FMC2_SEMCR */
- #define FMC2_SEMCR_SEM_MUTEX BIT(0)
- #define FMC2_SEMCR_SEMCID GENMASK(6, 4)
- #define FMC2_MAX_EBI_CE 4
- #define FMC2_MAX_BANKS 5
- #define FMC2_MAX_RESOURCES 6
- #define FMC2_CID1 1
- #define FMC2_BCR_CPSIZE_0 0x0
- #define FMC2_BCR_CPSIZE_128 0x1
- #define FMC2_BCR_CPSIZE_256 0x2
- #define FMC2_BCR_CPSIZE_512 0x3
- #define FMC2_BCR_CPSIZE_1024 0x4
- #define FMC2_BCR_MWID_8 0x0
- #define FMC2_BCR_MWID_16 0x1
- #define FMC2_BCR_MTYP_SRAM 0x0
- #define FMC2_BCR_MTYP_PSRAM 0x1
- #define FMC2_BCR_MTYP_NOR 0x2
- #define FMC2_BCR_CSCOUNT_0 0x0
- #define FMC2_BCR_CSCOUNT_1 0x1
- #define FMC2_BCR_CSCOUNT_64 0x2
- #define FMC2_BCR_CSCOUNT_256 0x3
- #define FMC2_BXTR_EXTMOD_A 0x0
- #define FMC2_BXTR_EXTMOD_B 0x1
- #define FMC2_BXTR_EXTMOD_C 0x2
- #define FMC2_BXTR_EXTMOD_D 0x3
- #define FMC2_BCR_NBLSET_MAX 0x3
- #define FMC2_BXTR_ADDSET_MAX 0xf
- #define FMC2_BXTR_ADDHLD_MAX 0xf
- #define FMC2_BXTR_DATAST_MAX 0xff
- #define FMC2_BXTR_BUSTURN_MAX 0xf
- #define FMC2_BXTR_DATAHLD_MAX 0x3
- #define FMC2_BTR_CLKDIV_MAX 0xf
- #define FMC2_BTR_DATLAT_MAX 0xf
- #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff
- #define FMC2_CFGR_CLKDIV_MAX 0xf
- enum stm32_fmc2_ebi_bank {
- FMC2_EBI1 = 0,
- FMC2_EBI2,
- FMC2_EBI3,
- FMC2_EBI4,
- FMC2_NAND
- };
- enum stm32_fmc2_ebi_register_type {
- FMC2_REG_BCR = 1,
- FMC2_REG_BTR,
- FMC2_REG_BWTR,
- FMC2_REG_PCSCNTR,
- FMC2_REG_CFGR
- };
- enum stm32_fmc2_ebi_transaction_type {
- FMC2_ASYNC_MODE_1_SRAM = 0,
- FMC2_ASYNC_MODE_1_PSRAM,
- FMC2_ASYNC_MODE_A_SRAM,
- FMC2_ASYNC_MODE_A_PSRAM,
- FMC2_ASYNC_MODE_2_NOR,
- FMC2_ASYNC_MODE_B_NOR,
- FMC2_ASYNC_MODE_C_NOR,
- FMC2_ASYNC_MODE_D_NOR,
- FMC2_SYNC_READ_SYNC_WRITE_PSRAM,
- FMC2_SYNC_READ_ASYNC_WRITE_PSRAM,
- FMC2_SYNC_READ_SYNC_WRITE_NOR,
- FMC2_SYNC_READ_ASYNC_WRITE_NOR
- };
- enum stm32_fmc2_ebi_buswidth {
- FMC2_BUSWIDTH_8 = 8,
- FMC2_BUSWIDTH_16 = 16
- };
- enum stm32_fmc2_ebi_cpsize {
- FMC2_CPSIZE_0 = 0,
- FMC2_CPSIZE_128 = 128,
- FMC2_CPSIZE_256 = 256,
- FMC2_CPSIZE_512 = 512,
- FMC2_CPSIZE_1024 = 1024
- };
- enum stm32_fmc2_ebi_cscount {
- FMC2_CSCOUNT_0 = 0,
- FMC2_CSCOUNT_1 = 1,
- FMC2_CSCOUNT_64 = 64,
- FMC2_CSCOUNT_256 = 256
- };
- struct stm32_fmc2_ebi;
- struct stm32_fmc2_ebi_data {
- const struct stm32_fmc2_prop *child_props;
- unsigned int nb_child_props;
- u32 fmc2_enable_reg;
- u32 fmc2_enable_bit;
- int (*nwait_used_by_ctrls)(struct stm32_fmc2_ebi *ebi);
- void (*set_setup)(struct stm32_fmc2_ebi *ebi);
- int (*save_setup)(struct stm32_fmc2_ebi *ebi);
- int (*check_rif)(struct stm32_fmc2_ebi *ebi, u32 resource);
- void (*put_sems)(struct stm32_fmc2_ebi *ebi);
- void (*get_sems)(struct stm32_fmc2_ebi *ebi);
- };
- struct stm32_fmc2_ebi {
- struct device *dev;
- struct clk *clk;
- struct regmap *regmap;
- const struct stm32_fmc2_ebi_data *data;
- u8 bank_assigned;
- u8 sem_taken;
- bool access_granted;
- u32 bcr[FMC2_MAX_EBI_CE];
- u32 btr[FMC2_MAX_EBI_CE];
- u32 bwtr[FMC2_MAX_EBI_CE];
- u32 pcscntr;
- u32 cfgr;
- };
- /*
- * struct stm32_fmc2_prop - STM32 FMC2 EBI property
- * @name: the device tree binding name of the property
- * @bprop: indicate that it is a boolean property
- * @mprop: indicate that it is a mandatory property
- * @reg_type: the register that have to be modified
- * @reg_mask: the bit that have to be modified in the selected register
- * in case of it is a boolean property
- * @reset_val: the default value that have to be set in case the property
- * has not been defined in the device tree
- * @check: this callback ckecks that the property is compliant with the
- * transaction type selected
- * @calculate: this callback is called to calculate for exemple a timing
- * set in nanoseconds in the device tree in clock cycles or in
- * clock period
- * @set: this callback applies the values in the registers
- */
- struct stm32_fmc2_prop {
- const char *name;
- bool bprop;
- bool mprop;
- int reg_type;
- u32 reg_mask;
- u32 reset_val;
- int (*check)(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop, int cs);
- u32 (*calculate)(struct stm32_fmc2_ebi *ebi, int cs, u32 setup);
- int (*set)(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup);
- };
- static int stm32_fmc2_ebi_check_mux(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (bcr & FMC2_BCR_MTYP)
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_waitcfg(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_sync_trans(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (bcr & FMC2_BCR_BURSTEN)
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_mp25_check_cclk(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- if (!ebi->access_granted)
- return -EACCES;
- return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
- }
- static int stm32_fmc2_ebi_mp25_check_clk_period(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 cfgr;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_CFGR, &cfgr);
- if (ret)
- return ret;
- if (cfgr & FMC2_CFGR_CCLKEN && !ebi->access_granted)
- return -EACCES;
- return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
- }
- static int stm32_fmc2_ebi_check_async_trans(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW))
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_cpsize(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr, val = FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if ((bcr & FMC2_BCR_MTYP) == val && bcr & FMC2_BCR_BURSTEN)
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_address_hold(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr, bxtr, val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (prop->reg_type == FMC2_REG_BWTR)
- ret = regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
- else
- ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
- if (ret)
- return ret;
- if ((!(bcr & FMC2_BCR_BURSTEN) || !(bcr & FMC2_BCR_CBURSTRW)) &&
- ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN))
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_clk_period(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- u32 bcr, bcr1;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (cs) {
- ret = regmap_read(ebi->regmap, FMC2_BCR1, &bcr1);
- if (ret)
- return ret;
- } else {
- bcr1 = bcr;
- }
- if (bcr & FMC2_BCR_BURSTEN && (!cs || !(bcr1 & FMC2_BCR1_CCLKEN)))
- return 0;
- return -EINVAL;
- }
- static int stm32_fmc2_ebi_check_cclk(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- if (cs)
- return -EINVAL;
- return stm32_fmc2_ebi_check_sync_trans(ebi, prop, cs);
- }
- static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi,
- int cs, u32 setup)
- {
- unsigned long hclk = clk_get_rate(ebi->clk);
- unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000);
- return DIV_ROUND_UP(setup * 1000, hclkp);
- }
- static u32 stm32_fmc2_ebi_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
- int cs, u32 setup)
- {
- u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
- u32 bcr, btr, clk_period;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR1, &bcr);
- if (ret)
- return ret;
- if (bcr & FMC2_BCR1_CCLKEN || !cs)
- ret = regmap_read(ebi->regmap, FMC2_BTR1, &btr);
- else
- ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &btr);
- if (ret)
- return ret;
- clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
- return DIV_ROUND_UP(nb_clk_cycles, clk_period);
- }
- static u32 stm32_fmc2_ebi_mp25_ns_to_clk_period(struct stm32_fmc2_ebi *ebi,
- int cs, u32 setup)
- {
- u32 nb_clk_cycles = stm32_fmc2_ebi_ns_to_clock_cycles(ebi, cs, setup);
- u32 cfgr, btr, clk_period;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_CFGR, &cfgr);
- if (ret)
- return ret;
- if (cfgr & FMC2_CFGR_CCLKEN) {
- clk_period = FIELD_GET(FMC2_CFGR_CLKDIV, cfgr) + 1;
- } else {
- ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &btr);
- if (ret)
- return ret;
- clk_period = FIELD_GET(FMC2_BTR_CLKDIV, btr) + 1;
- }
- return DIV_ROUND_UP(nb_clk_cycles, clk_period);
- }
- static int stm32_fmc2_ebi_get_reg(int reg_type, int cs, u32 *reg)
- {
- switch (reg_type) {
- case FMC2_REG_BCR:
- *reg = FMC2_BCR(cs);
- break;
- case FMC2_REG_BTR:
- *reg = FMC2_BTR(cs);
- break;
- case FMC2_REG_BWTR:
- *reg = FMC2_BWTR(cs);
- break;
- case FMC2_REG_PCSCNTR:
- *reg = FMC2_PCSCNTR;
- break;
- case FMC2_REG_CFGR:
- *reg = FMC2_CFGR;
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static int stm32_fmc2_ebi_set_bit_field(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 reg;
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- regmap_update_bits(ebi->regmap, reg, prop->reg_mask,
- setup ? prop->reg_mask : 0);
- return 0;
- }
- static int stm32_fmc2_ebi_set_trans_type(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 bcr_mask, bcr = FMC2_BCR_WREN;
- u32 btr_mask, btr = 0;
- u32 bwtr_mask, bwtr = 0;
- bwtr_mask = FMC2_BXTR_ACCMOD;
- btr_mask = FMC2_BXTR_ACCMOD;
- bcr_mask = FMC2_BCR_MUXEN | FMC2_BCR_MTYP | FMC2_BCR_FACCEN |
- FMC2_BCR_WREN | FMC2_BCR_WAITEN | FMC2_BCR_BURSTEN |
- FMC2_BCR_EXTMOD | FMC2_BCR_CBURSTRW;
- switch (setup) {
- case FMC2_ASYNC_MODE_1_SRAM:
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
- /*
- * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
- */
- break;
- case FMC2_ASYNC_MODE_1_PSRAM:
- /*
- * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
- break;
- case FMC2_ASYNC_MODE_A_SRAM:
- /*
- * MUXEN = 0, MTYP = 0, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_SRAM);
- bcr |= FMC2_BCR_EXTMOD;
- btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
- bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
- break;
- case FMC2_ASYNC_MODE_A_PSRAM:
- /*
- * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
- bcr |= FMC2_BCR_EXTMOD;
- btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
- bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_A);
- break;
- case FMC2_ASYNC_MODE_2_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN;
- break;
- case FMC2_ASYNC_MODE_B_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 1
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
- btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
- bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_B);
- break;
- case FMC2_ASYNC_MODE_C_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 2
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
- btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
- bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_C);
- break;
- case FMC2_ASYNC_MODE_D_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 0, WAITEN = 0,
- * WREN = 1, EXTMOD = 1, CBURSTRW = 0, ACCMOD = 3
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN | FMC2_BCR_EXTMOD;
- btr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
- bwtr |= FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
- break;
- case FMC2_SYNC_READ_SYNC_WRITE_PSRAM:
- /*
- * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
- bcr |= FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
- break;
- case FMC2_SYNC_READ_ASYNC_WRITE_PSRAM:
- /*
- * MUXEN = 0, MTYP = 1, FACCEN = 0, BURSTEN = 1, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_PSRAM);
- bcr |= FMC2_BCR_BURSTEN;
- break;
- case FMC2_SYNC_READ_SYNC_WRITE_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 1, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN | FMC2_BCR_CBURSTRW;
- break;
- case FMC2_SYNC_READ_ASYNC_WRITE_NOR:
- /*
- * MUXEN = 0, MTYP = 2, FACCEN = 1, BURSTEN = 1, WAITEN = 0,
- * WREN = 1, EXTMOD = 0, CBURSTRW = 0, ACCMOD = 0
- */
- bcr |= FIELD_PREP(FMC2_BCR_MTYP, FMC2_BCR_MTYP_NOR);
- bcr |= FMC2_BCR_FACCEN | FMC2_BCR_BURSTEN;
- break;
- default:
- /* Type of transaction not supported */
- return -EINVAL;
- }
- if (bcr & FMC2_BCR_EXTMOD)
- regmap_update_bits(ebi->regmap, FMC2_BWTR(cs),
- bwtr_mask, bwtr);
- regmap_update_bits(ebi->regmap, FMC2_BTR(cs), btr_mask, btr);
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs), bcr_mask, bcr);
- return 0;
- }
- static int stm32_fmc2_ebi_set_buswidth(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- switch (setup) {
- case FMC2_BUSWIDTH_8:
- val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_8);
- break;
- case FMC2_BUSWIDTH_16:
- val = FIELD_PREP(FMC2_BCR_MWID, FMC2_BCR_MWID_16);
- break;
- default:
- /* Buswidth not supported */
- return -EINVAL;
- }
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MWID, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_cpsize(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- switch (setup) {
- case FMC2_CPSIZE_0:
- val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_0);
- break;
- case FMC2_CPSIZE_128:
- val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_128);
- break;
- case FMC2_CPSIZE_256:
- val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_256);
- break;
- case FMC2_CPSIZE_512:
- val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_512);
- break;
- case FMC2_CPSIZE_1024:
- val = FIELD_PREP(FMC2_BCR_CPSIZE, FMC2_BCR_CPSIZE_1024);
- break;
- default:
- /* Cpsize not supported */
- return -EINVAL;
- }
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_CPSIZE, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_bl_setup(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- val = min_t(u32, setup, FMC2_BCR_NBLSET_MAX);
- val = FIELD_PREP(FMC2_BCR_NBLSET, val);
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_NBLSET, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_address_setup(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 bcr, bxtr, reg;
- u32 val = FIELD_PREP(FMC2_BXTR_ACCMOD, FMC2_BXTR_EXTMOD_D);
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if (prop->reg_type == FMC2_REG_BWTR)
- ret = regmap_read(ebi->regmap, FMC2_BWTR(cs), &bxtr);
- else
- ret = regmap_read(ebi->regmap, FMC2_BTR(cs), &bxtr);
- if (ret)
- return ret;
- if ((bxtr & FMC2_BXTR_ACCMOD) == val || bcr & FMC2_BCR_MUXEN)
- val = clamp_val(setup, 1, FMC2_BXTR_ADDSET_MAX);
- else
- val = min_t(u32, setup, FMC2_BXTR_ADDSET_MAX);
- val = FIELD_PREP(FMC2_BXTR_ADDSET, val);
- regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_ADDSET, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_address_hold(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val, reg;
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- val = clamp_val(setup, 1, FMC2_BXTR_ADDHLD_MAX);
- val = FIELD_PREP(FMC2_BXTR_ADDHLD, val);
- regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_ADDHLD, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_data_setup(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val, reg;
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- val = clamp_val(setup, 1, FMC2_BXTR_DATAST_MAX);
- val = FIELD_PREP(FMC2_BXTR_DATAST, val);
- regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_DATAST, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_bus_turnaround(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val, reg;
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- val = setup ? min_t(u32, setup - 1, FMC2_BXTR_BUSTURN_MAX) : 0;
- val = FIELD_PREP(FMC2_BXTR_BUSTURN, val);
- regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_BUSTURN, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_data_hold(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val, reg;
- int ret;
- ret = stm32_fmc2_ebi_get_reg(prop->reg_type, cs, ®);
- if (ret)
- return ret;
- if (prop->reg_type == FMC2_REG_BWTR)
- val = setup ? min_t(u32, setup - 1, FMC2_BXTR_DATAHLD_MAX) : 0;
- else
- val = min_t(u32, setup, FMC2_BXTR_DATAHLD_MAX);
- val = FIELD_PREP(FMC2_BXTR_DATAHLD, val);
- regmap_update_bits(ebi->regmap, reg, FMC2_BXTR_DATAHLD, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_clk_period(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
- val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
- regmap_update_bits(ebi->regmap, FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
- return 0;
- }
- static int stm32_fmc2_ebi_mp25_set_clk_period(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val, cfgr;
- int ret;
- ret = regmap_read(ebi->regmap, FMC2_CFGR, &cfgr);
- if (ret)
- return ret;
- if (cfgr & FMC2_CFGR_CCLKEN) {
- val = setup ? clamp_val(setup - 1, 1, FMC2_CFGR_CLKDIV_MAX) : 1;
- val = FIELD_PREP(FMC2_CFGR_CLKDIV, val);
- regmap_update_bits(ebi->regmap, FMC2_CFGR, FMC2_CFGR_CLKDIV, val);
- } else {
- val = setup ? clamp_val(setup - 1, 1, FMC2_BTR_CLKDIV_MAX) : 1;
- val = FIELD_PREP(FMC2_BTR_CLKDIV, val);
- regmap_update_bits(ebi->regmap, FMC2_BTR(cs), FMC2_BTR_CLKDIV, val);
- }
- return 0;
- }
- static int stm32_fmc2_ebi_set_data_latency(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- val = setup > 1 ? min_t(u32, setup - 2, FMC2_BTR_DATLAT_MAX) : 0;
- val = FIELD_PREP(FMC2_BTR_DATLAT, val);
- regmap_update_bits(ebi->regmap, FMC2_BTR(cs), FMC2_BTR_DATLAT, val);
- return 0;
- }
- static int stm32_fmc2_ebi_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 old_val, new_val, pcscntr;
- int ret;
- if (setup < 1)
- return 0;
- ret = regmap_read(ebi->regmap, FMC2_PCSCNTR, &pcscntr);
- if (ret)
- return ret;
- /* Enable counter for the bank */
- regmap_update_bits(ebi->regmap, FMC2_PCSCNTR,
- FMC2_PCSCNTR_CNTBEN(cs),
- FMC2_PCSCNTR_CNTBEN(cs));
- new_val = min_t(u32, setup - 1, FMC2_PCSCNTR_CSCOUNT_MAX);
- old_val = FIELD_GET(FMC2_PCSCNTR_CSCOUNT, pcscntr);
- if (old_val && new_val > old_val)
- /* Keep current counter value */
- return 0;
- new_val = FIELD_PREP(FMC2_PCSCNTR_CSCOUNT, new_val);
- regmap_update_bits(ebi->regmap, FMC2_PCSCNTR,
- FMC2_PCSCNTR_CSCOUNT, new_val);
- return 0;
- }
- static int stm32_fmc2_ebi_mp25_set_max_low_pulse(struct stm32_fmc2_ebi *ebi,
- const struct stm32_fmc2_prop *prop,
- int cs, u32 setup)
- {
- u32 val;
- if (setup == FMC2_CSCOUNT_0)
- val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_0);
- else if (setup == FMC2_CSCOUNT_1)
- val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_1);
- else if (setup <= FMC2_CSCOUNT_64)
- val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_64);
- else
- val = FIELD_PREP(FMC2_BCR_CSCOUNT, FMC2_BCR_CSCOUNT_256);
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs),
- FMC2_BCR_CSCOUNT, val);
- return 0;
- }
- static const struct stm32_fmc2_prop stm32_fmc2_child_props[] = {
- /* st,fmc2-ebi-cs-trans-type must be the first property */
- {
- .name = "st,fmc2-ebi-cs-transaction-type",
- .mprop = true,
- .set = stm32_fmc2_ebi_set_trans_type,
- },
- {
- .name = "st,fmc2-ebi-cs-cclk-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR1_CCLKEN,
- .check = stm32_fmc2_ebi_check_cclk,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-mux-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_MUXEN,
- .check = stm32_fmc2_ebi_check_mux,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-buswidth",
- .reset_val = FMC2_BUSWIDTH_16,
- .set = stm32_fmc2_ebi_set_buswidth,
- },
- {
- .name = "st,fmc2-ebi-cs-waitpol-high",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITPOL,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-waitcfg-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITCFG,
- .check = stm32_fmc2_ebi_check_waitcfg,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-wait-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITEN,
- .check = stm32_fmc2_ebi_check_sync_trans,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-asyncwait-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_ASYNCWAIT,
- .check = stm32_fmc2_ebi_check_async_trans,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-cpsize",
- .check = stm32_fmc2_ebi_check_cpsize,
- .set = stm32_fmc2_ebi_set_cpsize,
- },
- {
- .name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bl_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-address-setup-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_ADDSET_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-address-hold-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_ADDHLD_MAX,
- .check = stm32_fmc2_ebi_check_address_hold,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-data-setup-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_DATAST_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-bus-turnaround-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bus_turnaround,
- },
- {
- .name = "st,fmc2-ebi-cs-data-hold-ns",
- .reg_type = FMC2_REG_BTR,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-clk-period-ns",
- .reset_val = FMC2_BTR_CLKDIV_MAX + 1,
- .check = stm32_fmc2_ebi_check_clk_period,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_clk_period,
- },
- {
- .name = "st,fmc2-ebi-cs-data-latency-ns",
- .check = stm32_fmc2_ebi_check_sync_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clk_period,
- .set = stm32_fmc2_ebi_set_data_latency,
- },
- {
- .name = "st,fmc2-ebi-cs-write-address-setup-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_ADDSET_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-write-address-hold-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_ADDHLD_MAX,
- .check = stm32_fmc2_ebi_check_address_hold,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-write-data-setup-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_DATAST_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bus_turnaround,
- },
- {
- .name = "st,fmc2-ebi-cs-write-data-hold-ns",
- .reg_type = FMC2_REG_BWTR,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-max-low-pulse-ns",
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_max_low_pulse,
- },
- };
- static const struct stm32_fmc2_prop stm32_fmc2_mp25_child_props[] = {
- /* st,fmc2-ebi-cs-trans-type must be the first property */
- {
- .name = "st,fmc2-ebi-cs-transaction-type",
- .mprop = true,
- .set = stm32_fmc2_ebi_set_trans_type,
- },
- {
- .name = "st,fmc2-ebi-cs-cclk-enable",
- .bprop = true,
- .reg_type = FMC2_REG_CFGR,
- .reg_mask = FMC2_CFGR_CCLKEN,
- .check = stm32_fmc2_ebi_mp25_check_cclk,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-mux-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_MUXEN,
- .check = stm32_fmc2_ebi_check_mux,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-buswidth",
- .reset_val = FMC2_BUSWIDTH_16,
- .set = stm32_fmc2_ebi_set_buswidth,
- },
- {
- .name = "st,fmc2-ebi-cs-waitpol-high",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITPOL,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-waitcfg-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITCFG,
- .check = stm32_fmc2_ebi_check_waitcfg,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-wait-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_WAITEN,
- .check = stm32_fmc2_ebi_check_sync_trans,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-asyncwait-enable",
- .bprop = true,
- .reg_type = FMC2_REG_BCR,
- .reg_mask = FMC2_BCR_ASYNCWAIT,
- .check = stm32_fmc2_ebi_check_async_trans,
- .set = stm32_fmc2_ebi_set_bit_field,
- },
- {
- .name = "st,fmc2-ebi-cs-cpsize",
- .check = stm32_fmc2_ebi_check_cpsize,
- .set = stm32_fmc2_ebi_set_cpsize,
- },
- {
- .name = "st,fmc2-ebi-cs-byte-lane-setup-ns",
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bl_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-address-setup-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_ADDSET_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-address-hold-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_ADDHLD_MAX,
- .check = stm32_fmc2_ebi_check_address_hold,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-data-setup-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_DATAST_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-bus-turnaround-ns",
- .reg_type = FMC2_REG_BTR,
- .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bus_turnaround,
- },
- {
- .name = "st,fmc2-ebi-cs-data-hold-ns",
- .reg_type = FMC2_REG_BTR,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-clk-period-ns",
- .reset_val = FMC2_CFGR_CLKDIV_MAX + 1,
- .check = stm32_fmc2_ebi_mp25_check_clk_period,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_mp25_set_clk_period,
- },
- {
- .name = "st,fmc2-ebi-cs-data-latency-ns",
- .check = stm32_fmc2_ebi_check_sync_trans,
- .calculate = stm32_fmc2_ebi_mp25_ns_to_clk_period,
- .set = stm32_fmc2_ebi_set_data_latency,
- },
- {
- .name = "st,fmc2-ebi-cs-write-address-setup-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_ADDSET_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-write-address-hold-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_ADDHLD_MAX,
- .check = stm32_fmc2_ebi_check_address_hold,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_address_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-write-data-setup-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_DATAST_MAX,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_setup,
- },
- {
- .name = "st,fmc2-ebi-cs-write-bus-turnaround-ns",
- .reg_type = FMC2_REG_BWTR,
- .reset_val = FMC2_BXTR_BUSTURN_MAX + 1,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_bus_turnaround,
- },
- {
- .name = "st,fmc2-ebi-cs-write-data-hold-ns",
- .reg_type = FMC2_REG_BWTR,
- .check = stm32_fmc2_ebi_check_async_trans,
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_set_data_hold,
- },
- {
- .name = "st,fmc2-ebi-cs-max-low-pulse-ns",
- .calculate = stm32_fmc2_ebi_ns_to_clock_cycles,
- .set = stm32_fmc2_ebi_mp25_set_max_low_pulse,
- },
- };
- static int stm32_fmc2_ebi_mp25_check_rif(struct stm32_fmc2_ebi *ebi, u32 resource)
- {
- u32 seccfgr, cidcfgr, semcr;
- int cid, ret;
- if (resource >= FMC2_MAX_RESOURCES)
- return -EINVAL;
- ret = regmap_read(ebi->regmap, FMC2_SECCFGR, &seccfgr);
- if (ret)
- return ret;
- if (seccfgr & BIT(resource)) {
- if (resource)
- dev_err(ebi->dev, "resource %d is configured as secure\n",
- resource);
- return -EACCES;
- }
- ret = regmap_read(ebi->regmap, FMC2_CIDCFGR(resource), &cidcfgr);
- if (ret)
- return ret;
- if (!(cidcfgr & FMC2_CIDCFGR_CFEN))
- /* CID filtering is turned off: access granted */
- return 0;
- if (!(cidcfgr & FMC2_CIDCFGR_SEMEN)) {
- /* Static CID mode */
- cid = FIELD_GET(FMC2_CIDCFGR_SCID, cidcfgr);
- if (cid != FMC2_CID1) {
- if (resource)
- dev_err(ebi->dev, "static CID%d set for resource %d\n",
- cid, resource);
- return -EACCES;
- }
- return 0;
- }
- /* Pass-list with semaphore mode */
- if (!(cidcfgr & FMC2_CIDCFGR_SEMWLC1)) {
- if (resource)
- dev_err(ebi->dev, "CID1 is block-listed for resource %d\n",
- resource);
- return -EACCES;
- }
- ret = regmap_read(ebi->regmap, FMC2_SEMCR(resource), &semcr);
- if (ret)
- return ret;
- if (!(semcr & FMC2_SEMCR_SEM_MUTEX)) {
- regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
- FMC2_SEMCR_SEM_MUTEX, FMC2_SEMCR_SEM_MUTEX);
- ret = regmap_read(ebi->regmap, FMC2_SEMCR(resource), &semcr);
- if (ret)
- return ret;
- }
- cid = FIELD_GET(FMC2_SEMCR_SEMCID, semcr);
- if (cid != FMC2_CID1) {
- if (resource)
- dev_err(ebi->dev, "resource %d is already used by CID%d\n",
- resource, cid);
- return -EACCES;
- }
- ebi->sem_taken |= BIT(resource);
- return 0;
- }
- static void stm32_fmc2_ebi_mp25_put_sems(struct stm32_fmc2_ebi *ebi)
- {
- unsigned int resource;
- for (resource = 0; resource < FMC2_MAX_RESOURCES; resource++) {
- if (!(ebi->sem_taken & BIT(resource)))
- continue;
- regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
- FMC2_SEMCR_SEM_MUTEX, 0);
- }
- }
- static void stm32_fmc2_ebi_mp25_get_sems(struct stm32_fmc2_ebi *ebi)
- {
- unsigned int resource;
- for (resource = 0; resource < FMC2_MAX_RESOURCES; resource++) {
- if (!(ebi->sem_taken & BIT(resource)))
- continue;
- regmap_update_bits(ebi->regmap, FMC2_SEMCR(resource),
- FMC2_SEMCR_SEM_MUTEX, FMC2_SEMCR_SEM_MUTEX);
- }
- }
- static int stm32_fmc2_ebi_parse_prop(struct stm32_fmc2_ebi *ebi,
- struct device_node *dev_node,
- const struct stm32_fmc2_prop *prop,
- int cs)
- {
- struct device *dev = ebi->dev;
- u32 setup = 0;
- if (!prop->set) {
- dev_err(dev, "property %s is not well defined\n", prop->name);
- return -EINVAL;
- }
- if (prop->check && prop->check(ebi, prop, cs))
- /* Skeep this property */
- return 0;
- if (prop->bprop) {
- bool bprop;
- bprop = of_property_read_bool(dev_node, prop->name);
- if (prop->mprop && !bprop) {
- dev_err(dev, "mandatory property %s not defined in the device tree\n",
- prop->name);
- return -EINVAL;
- }
- if (bprop)
- setup = 1;
- } else {
- u32 val;
- int ret;
- ret = of_property_read_u32(dev_node, prop->name, &val);
- if (prop->mprop && ret) {
- dev_err(dev, "mandatory property %s not defined in the device tree\n",
- prop->name);
- return ret;
- }
- if (ret)
- setup = prop->reset_val;
- else if (prop->calculate)
- setup = prop->calculate(ebi, cs, val);
- else
- setup = val;
- }
- return prop->set(ebi, prop, cs, setup);
- }
- static void stm32_fmc2_ebi_enable_bank(struct stm32_fmc2_ebi *ebi, int cs)
- {
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs),
- FMC2_BCR_MBKEN, FMC2_BCR_MBKEN);
- }
- static void stm32_fmc2_ebi_disable_bank(struct stm32_fmc2_ebi *ebi, int cs)
- {
- regmap_update_bits(ebi->regmap, FMC2_BCR(cs), FMC2_BCR_MBKEN, 0);
- }
- static int stm32_fmc2_ebi_save_setup(struct stm32_fmc2_ebi *ebi)
- {
- unsigned int cs;
- int ret;
- for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
- if (!(ebi->bank_assigned & BIT(cs)))
- continue;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &ebi->bcr[cs]);
- ret |= regmap_read(ebi->regmap, FMC2_BTR(cs), &ebi->btr[cs]);
- ret |= regmap_read(ebi->regmap, FMC2_BWTR(cs), &ebi->bwtr[cs]);
- if (ret)
- return ret;
- }
- return 0;
- }
- static int stm32_fmc2_ebi_mp1_save_setup(struct stm32_fmc2_ebi *ebi)
- {
- int ret;
- ret = stm32_fmc2_ebi_save_setup(ebi);
- if (ret)
- return ret;
- return regmap_read(ebi->regmap, FMC2_PCSCNTR, &ebi->pcscntr);
- }
- static int stm32_fmc2_ebi_mp25_save_setup(struct stm32_fmc2_ebi *ebi)
- {
- int ret;
- ret = stm32_fmc2_ebi_save_setup(ebi);
- if (ret)
- return ret;
- if (ebi->access_granted)
- ret = regmap_read(ebi->regmap, FMC2_CFGR, &ebi->cfgr);
- return ret;
- }
- static void stm32_fmc2_ebi_set_setup(struct stm32_fmc2_ebi *ebi)
- {
- unsigned int cs;
- for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
- if (!(ebi->bank_assigned & BIT(cs)))
- continue;
- regmap_write(ebi->regmap, FMC2_BCR(cs), ebi->bcr[cs]);
- regmap_write(ebi->regmap, FMC2_BTR(cs), ebi->btr[cs]);
- regmap_write(ebi->regmap, FMC2_BWTR(cs), ebi->bwtr[cs]);
- }
- }
- static void stm32_fmc2_ebi_mp1_set_setup(struct stm32_fmc2_ebi *ebi)
- {
- stm32_fmc2_ebi_set_setup(ebi);
- regmap_write(ebi->regmap, FMC2_PCSCNTR, ebi->pcscntr);
- }
- static void stm32_fmc2_ebi_mp25_set_setup(struct stm32_fmc2_ebi *ebi)
- {
- stm32_fmc2_ebi_set_setup(ebi);
- if (ebi->access_granted)
- regmap_write(ebi->regmap, FMC2_CFGR, ebi->cfgr);
- }
- static void stm32_fmc2_ebi_disable_banks(struct stm32_fmc2_ebi *ebi)
- {
- unsigned int cs;
- for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
- if (!(ebi->bank_assigned & BIT(cs)))
- continue;
- stm32_fmc2_ebi_disable_bank(ebi, cs);
- }
- }
- /* NWAIT signal can not be connected to EBI controller and NAND controller */
- static int stm32_fmc2_ebi_nwait_used_by_ctrls(struct stm32_fmc2_ebi *ebi)
- {
- struct device *dev = ebi->dev;
- unsigned int cs;
- u32 bcr;
- int ret;
- for (cs = 0; cs < FMC2_MAX_EBI_CE; cs++) {
- if (!(ebi->bank_assigned & BIT(cs)))
- continue;
- ret = regmap_read(ebi->regmap, FMC2_BCR(cs), &bcr);
- if (ret)
- return ret;
- if ((bcr & FMC2_BCR_WAITEN || bcr & FMC2_BCR_ASYNCWAIT) &&
- ebi->bank_assigned & BIT(FMC2_NAND)) {
- dev_err(dev, "NWAIT signal connected to EBI and NAND controllers\n");
- return -EINVAL;
- }
- }
- return 0;
- }
- static void stm32_fmc2_ebi_enable(struct stm32_fmc2_ebi *ebi)
- {
- if (!ebi->access_granted)
- return;
- regmap_update_bits(ebi->regmap, ebi->data->fmc2_enable_reg,
- ebi->data->fmc2_enable_bit,
- ebi->data->fmc2_enable_bit);
- }
- static void stm32_fmc2_ebi_disable(struct stm32_fmc2_ebi *ebi)
- {
- if (!ebi->access_granted)
- return;
- regmap_update_bits(ebi->regmap, ebi->data->fmc2_enable_reg,
- ebi->data->fmc2_enable_bit, 0);
- }
- static int stm32_fmc2_ebi_setup_cs(struct stm32_fmc2_ebi *ebi,
- struct device_node *dev_node,
- u32 cs)
- {
- unsigned int i;
- int ret;
- stm32_fmc2_ebi_disable_bank(ebi, cs);
- for (i = 0; i < ebi->data->nb_child_props; i++) {
- const struct stm32_fmc2_prop *p = &ebi->data->child_props[i];
- ret = stm32_fmc2_ebi_parse_prop(ebi, dev_node, p, cs);
- if (ret) {
- dev_err(ebi->dev, "property %s could not be set: %d\n",
- p->name, ret);
- return ret;
- }
- }
- stm32_fmc2_ebi_enable_bank(ebi, cs);
- return 0;
- }
- static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi)
- {
- struct device *dev = ebi->dev;
- bool child_found = false;
- u32 bank;
- int ret;
- for_each_available_child_of_node_scoped(dev->of_node, child) {
- ret = of_property_read_u32(child, "reg", &bank);
- if (ret)
- return dev_err_probe(dev, ret, "could not retrieve reg property\n");
- if (bank >= FMC2_MAX_BANKS) {
- dev_err(dev, "invalid reg value: %d\n", bank);
- return -EINVAL;
- }
- if (ebi->bank_assigned & BIT(bank)) {
- dev_err(dev, "bank already assigned: %d\n", bank);
- return -EINVAL;
- }
- if (ebi->data->check_rif) {
- ret = ebi->data->check_rif(ebi, bank + 1);
- if (ret) {
- dev_err(dev, "bank access failed: %d\n", bank);
- return ret;
- }
- }
- if (bank < FMC2_MAX_EBI_CE) {
- ret = stm32_fmc2_ebi_setup_cs(ebi, child, bank);
- if (ret)
- return dev_err_probe(dev, ret,
- "setup chip select %d failed\n", bank);
- }
- ebi->bank_assigned |= BIT(bank);
- child_found = true;
- }
- if (!child_found) {
- dev_warn(dev, "no subnodes found, disable the driver.\n");
- return -ENODEV;
- }
- if (ebi->data->nwait_used_by_ctrls) {
- ret = ebi->data->nwait_used_by_ctrls(ebi);
- if (ret)
- return ret;
- }
- stm32_fmc2_ebi_enable(ebi);
- return of_platform_populate(dev->of_node, NULL, NULL, dev);
- }
- static int stm32_fmc2_ebi_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
- struct stm32_fmc2_ebi *ebi;
- struct reset_control *rstc;
- int ret;
- ebi = devm_kzalloc(&pdev->dev, sizeof(*ebi), GFP_KERNEL);
- if (!ebi)
- return -ENOMEM;
- ebi->dev = dev;
- platform_set_drvdata(pdev, ebi);
- ebi->data = of_device_get_match_data(dev);
- if (!ebi->data)
- return -EINVAL;
- ebi->regmap = device_node_to_regmap(dev->of_node);
- if (IS_ERR(ebi->regmap))
- return PTR_ERR(ebi->regmap);
- ebi->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(ebi->clk))
- return PTR_ERR(ebi->clk);
- rstc = devm_reset_control_get(dev, NULL);
- if (PTR_ERR(rstc) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- ret = devm_pm_runtime_enable(dev);
- if (ret)
- return ret;
- ret = pm_runtime_resume_and_get(dev);
- if (ret < 0)
- return ret;
- if (!IS_ERR(rstc)) {
- reset_control_assert(rstc);
- reset_control_deassert(rstc);
- }
- /* Check if CFGR register can be modified */
- ebi->access_granted = true;
- if (ebi->data->check_rif) {
- ret = ebi->data->check_rif(ebi, 0);
- if (ret) {
- u32 sr;
- ebi->access_granted = false;
- ret = regmap_read(ebi->regmap, FMC2_SR, &sr);
- if (ret)
- goto err_release;
- /* In case of CFGR is secure, just check that the FMC2 is enabled */
- if (sr & FMC2_SR_ISOST) {
- dev_err(dev, "FMC2 is not ready to be used.\n");
- ret = -EACCES;
- goto err_release;
- }
- }
- }
- ret = stm32_fmc2_ebi_parse_dt(ebi);
- if (ret)
- goto err_release;
- ret = ebi->data->save_setup(ebi);
- if (ret)
- goto err_release;
- return 0;
- err_release:
- stm32_fmc2_ebi_disable_banks(ebi);
- stm32_fmc2_ebi_disable(ebi);
- if (ebi->data->put_sems)
- ebi->data->put_sems(ebi);
- pm_runtime_put_sync_suspend(dev);
- return ret;
- }
- static void stm32_fmc2_ebi_remove(struct platform_device *pdev)
- {
- struct stm32_fmc2_ebi *ebi = platform_get_drvdata(pdev);
- of_platform_depopulate(&pdev->dev);
- stm32_fmc2_ebi_disable_banks(ebi);
- stm32_fmc2_ebi_disable(ebi);
- if (ebi->data->put_sems)
- ebi->data->put_sems(ebi);
- pm_runtime_put_sync_suspend(&pdev->dev);
- }
- static int __maybe_unused stm32_fmc2_ebi_runtime_suspend(struct device *dev)
- {
- struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
- clk_disable_unprepare(ebi->clk);
- return 0;
- }
- static int __maybe_unused stm32_fmc2_ebi_runtime_resume(struct device *dev)
- {
- struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
- return clk_prepare_enable(ebi->clk);
- }
- static int __maybe_unused stm32_fmc2_ebi_suspend(struct device *dev)
- {
- struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
- stm32_fmc2_ebi_disable(ebi);
- if (ebi->data->put_sems)
- ebi->data->put_sems(ebi);
- pm_runtime_put_sync_suspend(dev);
- pinctrl_pm_select_sleep_state(dev);
- return 0;
- }
- static int __maybe_unused stm32_fmc2_ebi_resume(struct device *dev)
- {
- struct stm32_fmc2_ebi *ebi = dev_get_drvdata(dev);
- int ret;
- pinctrl_pm_select_default_state(dev);
- ret = pm_runtime_resume_and_get(dev);
- if (ret < 0)
- return ret;
- if (ebi->data->get_sems)
- ebi->data->get_sems(ebi);
- ebi->data->set_setup(ebi);
- stm32_fmc2_ebi_enable(ebi);
- return 0;
- }
- static const struct dev_pm_ops stm32_fmc2_ebi_pm_ops = {
- SET_RUNTIME_PM_OPS(stm32_fmc2_ebi_runtime_suspend,
- stm32_fmc2_ebi_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(stm32_fmc2_ebi_suspend, stm32_fmc2_ebi_resume)
- };
- static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp1_data = {
- .child_props = stm32_fmc2_child_props,
- .nb_child_props = ARRAY_SIZE(stm32_fmc2_child_props),
- .fmc2_enable_reg = FMC2_BCR1,
- .fmc2_enable_bit = FMC2_BCR1_FMC2EN,
- .nwait_used_by_ctrls = stm32_fmc2_ebi_nwait_used_by_ctrls,
- .set_setup = stm32_fmc2_ebi_mp1_set_setup,
- .save_setup = stm32_fmc2_ebi_mp1_save_setup,
- };
- static const struct stm32_fmc2_ebi_data stm32_fmc2_ebi_mp25_data = {
- .child_props = stm32_fmc2_mp25_child_props,
- .nb_child_props = ARRAY_SIZE(stm32_fmc2_mp25_child_props),
- .fmc2_enable_reg = FMC2_CFGR,
- .fmc2_enable_bit = FMC2_CFGR_FMC2EN,
- .set_setup = stm32_fmc2_ebi_mp25_set_setup,
- .save_setup = stm32_fmc2_ebi_mp25_save_setup,
- .check_rif = stm32_fmc2_ebi_mp25_check_rif,
- .put_sems = stm32_fmc2_ebi_mp25_put_sems,
- .get_sems = stm32_fmc2_ebi_mp25_get_sems,
- };
- static const struct of_device_id stm32_fmc2_ebi_match[] = {
- {
- .compatible = "st,stm32mp1-fmc2-ebi",
- .data = &stm32_fmc2_ebi_mp1_data,
- },
- {
- .compatible = "st,stm32mp25-fmc2-ebi",
- .data = &stm32_fmc2_ebi_mp25_data,
- },
- {}
- };
- MODULE_DEVICE_TABLE(of, stm32_fmc2_ebi_match);
- static struct platform_driver stm32_fmc2_ebi_driver = {
- .probe = stm32_fmc2_ebi_probe,
- .remove_new = stm32_fmc2_ebi_remove,
- .driver = {
- .name = "stm32_fmc2_ebi",
- .of_match_table = stm32_fmc2_ebi_match,
- .pm = &stm32_fmc2_ebi_pm_ops,
- },
- };
- module_platform_driver(stm32_fmc2_ebi_driver);
- MODULE_ALIAS("platform:stm32_fmc2_ebi");
- MODULE_AUTHOR("Christophe Kerello <christophe.kerello@st.com>");
- MODULE_DESCRIPTION("STMicroelectronics STM32 FMC2 ebi driver");
- MODULE_LICENSE("GPL v2");
|