123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704 |
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <scsi/scsi_host.h>
- #include <linux/libata.h>
- #include <linux/platform_device.h>
- #include <linux/gpio.h>
- #include <asm/dma.h>
- #include <asm/portmux.h>
- #define DRV_NAME "pata-bf54x"
- #define DRV_VERSION "0.9"
- #define ATA_REG_CTRL 0x0E
- #define ATA_REG_ALTSTATUS ATA_REG_CTRL
- #define ATAPI_OFFSET_CONTROL 0x00
- #define ATAPI_OFFSET_STATUS 0x04
- #define ATAPI_OFFSET_DEV_ADDR 0x08
- #define ATAPI_OFFSET_DEV_TXBUF 0x0c
- #define ATAPI_OFFSET_DEV_RXBUF 0x10
- #define ATAPI_OFFSET_INT_MASK 0x14
- #define ATAPI_OFFSET_INT_STATUS 0x18
- #define ATAPI_OFFSET_XFER_LEN 0x1c
- #define ATAPI_OFFSET_LINE_STATUS 0x20
- #define ATAPI_OFFSET_SM_STATE 0x24
- #define ATAPI_OFFSET_TERMINATE 0x28
- #define ATAPI_OFFSET_PIO_TFRCNT 0x2c
- #define ATAPI_OFFSET_DMA_TFRCNT 0x30
- #define ATAPI_OFFSET_UMAIN_TFRCNT 0x34
- #define ATAPI_OFFSET_UDMAOUT_TFRCNT 0x38
- #define ATAPI_OFFSET_REG_TIM_0 0x40
- #define ATAPI_OFFSET_PIO_TIM_0 0x44
- #define ATAPI_OFFSET_PIO_TIM_1 0x48
- #define ATAPI_OFFSET_MULTI_TIM_0 0x50
- #define ATAPI_OFFSET_MULTI_TIM_1 0x54
- #define ATAPI_OFFSET_MULTI_TIM_2 0x58
- #define ATAPI_OFFSET_ULTRA_TIM_0 0x60
- #define ATAPI_OFFSET_ULTRA_TIM_1 0x64
- #define ATAPI_OFFSET_ULTRA_TIM_2 0x68
- #define ATAPI_OFFSET_ULTRA_TIM_3 0x6c
- #define ATAPI_GET_CONTROL(base)\
- bfin_read16(base + ATAPI_OFFSET_CONTROL)
- #define ATAPI_SET_CONTROL(base, val)\
- bfin_write16(base + ATAPI_OFFSET_CONTROL, val)
- #define ATAPI_GET_STATUS(base)\
- bfin_read16(base + ATAPI_OFFSET_STATUS)
- #define ATAPI_GET_DEV_ADDR(base)\
- bfin_read16(base + ATAPI_OFFSET_DEV_ADDR)
- #define ATAPI_SET_DEV_ADDR(base, val)\
- bfin_write16(base + ATAPI_OFFSET_DEV_ADDR, val)
- #define ATAPI_GET_DEV_TXBUF(base)\
- bfin_read16(base + ATAPI_OFFSET_DEV_TXBUF)
- #define ATAPI_SET_DEV_TXBUF(base, val)\
- bfin_write16(base + ATAPI_OFFSET_DEV_TXBUF, val)
- #define ATAPI_GET_DEV_RXBUF(base)\
- bfin_read16(base + ATAPI_OFFSET_DEV_RXBUF)
- #define ATAPI_SET_DEV_RXBUF(base, val)\
- bfin_write16(base + ATAPI_OFFSET_DEV_RXBUF, val)
- #define ATAPI_GET_INT_MASK(base)\
- bfin_read16(base + ATAPI_OFFSET_INT_MASK)
- #define ATAPI_SET_INT_MASK(base, val)\
- bfin_write16(base + ATAPI_OFFSET_INT_MASK, val)
- #define ATAPI_GET_INT_STATUS(base)\
- bfin_read16(base + ATAPI_OFFSET_INT_STATUS)
- #define ATAPI_SET_INT_STATUS(base, val)\
- bfin_write16(base + ATAPI_OFFSET_INT_STATUS, val)
- #define ATAPI_GET_XFER_LEN(base)\
- bfin_read16(base + ATAPI_OFFSET_XFER_LEN)
- #define ATAPI_SET_XFER_LEN(base, val)\
- bfin_write16(base + ATAPI_OFFSET_XFER_LEN, val)
- #define ATAPI_GET_LINE_STATUS(base)\
- bfin_read16(base + ATAPI_OFFSET_LINE_STATUS)
- #define ATAPI_GET_SM_STATE(base)\
- bfin_read16(base + ATAPI_OFFSET_SM_STATE)
- #define ATAPI_GET_TERMINATE(base)\
- bfin_read16(base + ATAPI_OFFSET_TERMINATE)
- #define ATAPI_SET_TERMINATE(base, val)\
- bfin_write16(base + ATAPI_OFFSET_TERMINATE, val)
- #define ATAPI_GET_PIO_TFRCNT(base)\
- bfin_read16(base + ATAPI_OFFSET_PIO_TFRCNT)
- #define ATAPI_GET_DMA_TFRCNT(base)\
- bfin_read16(base + ATAPI_OFFSET_DMA_TFRCNT)
- #define ATAPI_GET_UMAIN_TFRCNT(base)\
- bfin_read16(base + ATAPI_OFFSET_UMAIN_TFRCNT)
- #define ATAPI_GET_UDMAOUT_TFRCNT(base)\
- bfin_read16(base + ATAPI_OFFSET_UDMAOUT_TFRCNT)
- #define ATAPI_GET_REG_TIM_0(base)\
- bfin_read16(base + ATAPI_OFFSET_REG_TIM_0)
- #define ATAPI_SET_REG_TIM_0(base, val)\
- bfin_write16(base + ATAPI_OFFSET_REG_TIM_0, val)
- #define ATAPI_GET_PIO_TIM_0(base)\
- bfin_read16(base + ATAPI_OFFSET_PIO_TIM_0)
- #define ATAPI_SET_PIO_TIM_0(base, val)\
- bfin_write16(base + ATAPI_OFFSET_PIO_TIM_0, val)
- #define ATAPI_GET_PIO_TIM_1(base)\
- bfin_read16(base + ATAPI_OFFSET_PIO_TIM_1)
- #define ATAPI_SET_PIO_TIM_1(base, val)\
- bfin_write16(base + ATAPI_OFFSET_PIO_TIM_1, val)
- #define ATAPI_GET_MULTI_TIM_0(base)\
- bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_0)
- #define ATAPI_SET_MULTI_TIM_0(base, val)\
- bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_0, val)
- #define ATAPI_GET_MULTI_TIM_1(base)\
- bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_1)
- #define ATAPI_SET_MULTI_TIM_1(base, val)\
- bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_1, val)
- #define ATAPI_GET_MULTI_TIM_2(base)\
- bfin_read16(base + ATAPI_OFFSET_MULTI_TIM_2)
- #define ATAPI_SET_MULTI_TIM_2(base, val)\
- bfin_write16(base + ATAPI_OFFSET_MULTI_TIM_2, val)
- #define ATAPI_GET_ULTRA_TIM_0(base)\
- bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_0)
- #define ATAPI_SET_ULTRA_TIM_0(base, val)\
- bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_0, val)
- #define ATAPI_GET_ULTRA_TIM_1(base)\
- bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_1)
- #define ATAPI_SET_ULTRA_TIM_1(base, val)\
- bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_1, val)
- #define ATAPI_GET_ULTRA_TIM_2(base)\
- bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_2)
- #define ATAPI_SET_ULTRA_TIM_2(base, val)\
- bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_2, val)
- #define ATAPI_GET_ULTRA_TIM_3(base)\
- bfin_read16(base + ATAPI_OFFSET_ULTRA_TIM_3)
- #define ATAPI_SET_ULTRA_TIM_3(base, val)\
- bfin_write16(base + ATAPI_OFFSET_ULTRA_TIM_3, val)
- static const u32 pio_fsclk[] =
- { 33333333, 33333333, 33333333, 33333333, 33333333 };
- static const u32 mdma_fsclk[] = { 33333333, 33333333, 33333333 };
- static const u32 udma_fsclk[] =
- { 33333333, 33333333, 40000000, 50000000, 80000000, 133333333 };
- static const u32 reg_t0min[] = { 600, 383, 330, 180, 120 };
- static const u32 reg_t2min[] = { 290, 290, 290, 70, 25 };
- static const u32 reg_teocmin[] = { 290, 290, 290, 80, 70 };
- static const u32 pio_t0min[] = { 600, 383, 240, 180, 120 };
- static const u32 pio_t1min[] = { 70, 50, 30, 30, 25 };
- static const u32 pio_t2min[] = { 165, 125, 100, 80, 70 };
- static const u32 pio_teocmin[] = { 165, 125, 100, 70, 25 };
- static const u32 pio_t4min[] = { 30, 20, 15, 10, 10 };
- static const u32 mdma_t0min[] = { 480, 150, 120 };
- static const u32 mdma_tdmin[] = { 215, 80, 70 };
- static const u32 mdma_thmin[] = { 20, 15, 10 };
- static const u32 mdma_tjmin[] = { 20, 5, 5 };
- static const u32 mdma_tkrmin[] = { 50, 50, 25 };
- static const u32 mdma_tkwmin[] = { 215, 50, 25 };
- static const u32 mdma_tmmin[] = { 50, 30, 25 };
- static const u32 mdma_tzmax[] = { 20, 25, 25 };
- static const u32 udma_tcycmin[] = { 112, 73, 54, 39, 25, 17 };
- static const u32 udma_tdvsmin[] = { 70, 48, 31, 20, 7, 5 };
- static const u32 udma_tenvmax[] = { 70, 70, 70, 55, 55, 50 };
- static const u32 udma_trpmin[] = { 160, 125, 100, 100, 100, 85 };
- static const u32 udma_tmin[] = { 5, 5, 5, 5, 3, 3 };
- static const u32 udma_tmlimin = 20;
- static const u32 udma_tzahmin = 20;
- static const u32 udma_tenvmin = 20;
- static const u32 udma_tackmin = 20;
- static const u32 udma_tssmin = 50;
- #define BFIN_MAX_SG_SEGMENTS 4
- static unsigned short num_clocks_min(unsigned long tmin,
- unsigned long fsclk)
- {
- unsigned long tmp ;
- unsigned short result;
- tmp = tmin * (fsclk/1000/1000) / 1000;
- result = (unsigned short)tmp;
- if ((tmp*1000*1000) < (tmin*(fsclk/1000))) {
- result++;
- }
- return result;
- }
- static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev)
- {
- int mode = adev->pio_mode - XFER_PIO_0;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned int fsclk = get_sclk();
- unsigned short teoc_reg, t2_reg, teoc_pio;
- unsigned short t4_reg, t2_pio, t1_reg;
- unsigned short n0, n6, t6min = 5;
-
- n6 = num_clocks_min(t6min, fsclk);
- if (mode >= 0 && mode <= 4 && n6 >= 1) {
- dev_dbg(adev->link->ap->dev, "set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
-
- while (mode > 0 && pio_fsclk[mode] > fsclk)
- mode--;
-
- t2_reg = num_clocks_min(reg_t2min[mode], fsclk);
-
- teoc_reg = num_clocks_min(reg_teocmin[mode], fsclk);
-
- n0 = num_clocks_min(reg_t0min[mode], fsclk);
-
- if (t2_reg + teoc_reg < n0)
- t2_reg = n0 - teoc_reg;
-
-
- t2_pio = num_clocks_min(pio_t2min[mode], fsclk);
-
- teoc_pio = num_clocks_min(pio_teocmin[mode], fsclk);
-
- n0 = num_clocks_min(pio_t0min[mode], fsclk);
-
- if (t2_pio + teoc_pio < n0)
- t2_pio = n0 - teoc_pio;
-
- t1_reg = num_clocks_min(pio_t1min[mode], fsclk);
-
- t4_reg = num_clocks_min(pio_t4min[mode], fsclk);
- ATAPI_SET_REG_TIM_0(base, (teoc_reg<<8 | t2_reg));
- ATAPI_SET_PIO_TIM_0(base, (t4_reg<<12 | t2_pio<<4 | t1_reg));
- ATAPI_SET_PIO_TIM_1(base, teoc_pio);
- if (mode > 2) {
- ATAPI_SET_CONTROL(base,
- ATAPI_GET_CONTROL(base) | IORDY_EN);
- } else {
- ATAPI_SET_CONTROL(base,
- ATAPI_GET_CONTROL(base) & ~IORDY_EN);
- }
-
- ATAPI_SET_INT_MASK(base, ATAPI_GET_INT_MASK(base)
- & ~(PIO_DONE_MASK | HOST_TERM_XFER_MASK));
- SSYNC();
- }
- }
- static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
- {
- int mode;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned long fsclk = get_sclk();
- unsigned short tenv, tack, tcyc_tdvs, tdvs, tmli, tss, trp, tzah;
- unsigned short tm, td, tkr, tkw, teoc, th;
- unsigned short n0, nf, tfmin = 5;
- unsigned short nmin, tcyc;
- mode = adev->dma_mode - XFER_UDMA_0;
- if (mode >= 0 && mode <= 5) {
- dev_dbg(adev->link->ap->dev, "set udmamode: mode=%d\n", mode);
-
- while (mode > 0 && udma_fsclk[mode] > fsclk)
- mode--;
- nmin = num_clocks_min(udma_tmin[mode], fsclk);
- if (nmin >= 1) {
-
- tdvs = num_clocks_min(udma_tdvsmin[mode], fsclk);
- tcyc = num_clocks_min(udma_tcycmin[mode], fsclk);
- tcyc_tdvs = 2;
-
- if (tdvs + tcyc_tdvs < tcyc)
- tcyc_tdvs = tcyc - tdvs;
-
- if (tcyc_tdvs < 2)
- tcyc_tdvs = 2;
- if (tdvs < 2)
- tdvs = 2;
- tack = num_clocks_min(udma_tackmin, fsclk);
- tss = num_clocks_min(udma_tssmin, fsclk);
- tmli = num_clocks_min(udma_tmlimin, fsclk);
- tzah = num_clocks_min(udma_tzahmin, fsclk);
- trp = num_clocks_min(udma_trpmin[mode], fsclk);
- tenv = num_clocks_min(udma_tenvmin, fsclk);
- if (tenv <= udma_tenvmax[mode]) {
- ATAPI_SET_ULTRA_TIM_0(base, (tenv<<8 | tack));
- ATAPI_SET_ULTRA_TIM_1(base,
- (tcyc_tdvs<<8 | tdvs));
- ATAPI_SET_ULTRA_TIM_2(base, (tmli<<8 | tss));
- ATAPI_SET_ULTRA_TIM_3(base, (trp<<8 | tzah));
- }
- }
- }
- mode = adev->dma_mode - XFER_MW_DMA_0;
- if (mode >= 0 && mode <= 2) {
- dev_dbg(adev->link->ap->dev, "set mdmamode: mode=%d\n", mode);
-
- while (mode > 0 && mdma_fsclk[mode] > fsclk)
- mode--;
- nf = num_clocks_min(tfmin, fsclk);
- if (nf >= 1) {
-
-
- td = num_clocks_min(mdma_tdmin[mode], fsclk);
-
- tkw = num_clocks_min(mdma_tkwmin[mode], fsclk);
-
- n0 = num_clocks_min(mdma_t0min[mode], fsclk);
-
- if (tkw + td < n0)
- tkw = n0 - td;
-
- tkr = num_clocks_min(mdma_tkrmin[mode], fsclk);
-
- tm = num_clocks_min(mdma_tmmin[mode], fsclk);
-
- teoc = num_clocks_min(mdma_tjmin[mode], fsclk);
-
- th = num_clocks_min(mdma_thmin[mode], fsclk);
- ATAPI_SET_MULTI_TIM_0(base, (tm<<8 | td));
- ATAPI_SET_MULTI_TIM_1(base, (tkr<<8 | tkw));
- ATAPI_SET_MULTI_TIM_2(base, (teoc<<8 | th));
- SSYNC();
- }
- }
- return;
- }
- static inline void wait_complete(void __iomem *base, unsigned short mask)
- {
- unsigned short status;
- unsigned int i = 0;
- #define PATA_BF54X_WAIT_TIMEOUT 10000
- for (i = 0; i < PATA_BF54X_WAIT_TIMEOUT; i++) {
- status = ATAPI_GET_INT_STATUS(base) & mask;
- if (status)
- break;
- }
- ATAPI_SET_INT_STATUS(base, mask);
- }
- static void write_atapi_register(void __iomem *base,
- unsigned long ata_reg, unsigned short value)
- {
-
- ATAPI_SET_DEV_TXBUF(base, value);
-
- ATAPI_SET_DEV_ADDR(base, ata_reg);
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
-
- wait_complete(base, PIO_DONE_INT);
- }
- static unsigned short read_atapi_register(void __iomem *base,
- unsigned long ata_reg)
- {
-
- ATAPI_SET_DEV_ADDR(base, ata_reg);
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
-
- wait_complete(base, PIO_DONE_INT);
-
- return ATAPI_GET_DEV_RXBUF(base);
- }
- static void write_atapi_data(void __iomem *base,
- int len, unsigned short *buf)
- {
- int i;
-
- ATAPI_SET_XFER_LEN(base, 1);
-
- ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA);
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- for (i = 0; i < len; i++) {
-
- ATAPI_SET_DEV_TXBUF(base, buf[i]);
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
-
- wait_complete(base, PIO_DONE_INT);
- }
- }
- static void read_atapi_data(void __iomem *base,
- int len, unsigned short *buf)
- {
- int i;
-
- ATAPI_SET_XFER_LEN(base, 1);
-
- ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA);
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR));
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- for (i = 0; i < len; i++) {
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
-
- wait_complete(base, PIO_DONE_INT);
-
- buf[i] = ATAPI_GET_DEV_RXBUF(base);
- }
- }
- static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
- if (tf->ctl != ap->last_ctl) {
- write_atapi_register(base, ATA_REG_CTRL, tf->ctl);
- ap->last_ctl = tf->ctl;
- ata_wait_idle(ap);
- }
- if (is_addr) {
- if (tf->flags & ATA_TFLAG_LBA48) {
- write_atapi_register(base, ATA_REG_FEATURE,
- tf->hob_feature);
- write_atapi_register(base, ATA_REG_NSECT,
- tf->hob_nsect);
- write_atapi_register(base, ATA_REG_LBAL, tf->hob_lbal);
- write_atapi_register(base, ATA_REG_LBAM, tf->hob_lbam);
- write_atapi_register(base, ATA_REG_LBAH, tf->hob_lbah);
- dev_dbg(ap->dev, "hob: feat 0x%X nsect 0x%X, lba 0x%X "
- "0x%X 0x%X\n",
- tf->hob_feature,
- tf->hob_nsect,
- tf->hob_lbal,
- tf->hob_lbam,
- tf->hob_lbah);
- }
- write_atapi_register(base, ATA_REG_FEATURE, tf->feature);
- write_atapi_register(base, ATA_REG_NSECT, tf->nsect);
- write_atapi_register(base, ATA_REG_LBAL, tf->lbal);
- write_atapi_register(base, ATA_REG_LBAM, tf->lbam);
- write_atapi_register(base, ATA_REG_LBAH, tf->lbah);
- dev_dbg(ap->dev, "feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
- tf->feature,
- tf->nsect,
- tf->lbal,
- tf->lbam,
- tf->lbah);
- }
- if (tf->flags & ATA_TFLAG_DEVICE) {
- write_atapi_register(base, ATA_REG_DEVICE, tf->device);
- dev_dbg(ap->dev, "device 0x%X\n", tf->device);
- }
- ata_wait_idle(ap);
- }
- static u8 bfin_check_status(struct ata_port *ap)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- return read_atapi_register(base, ATA_REG_STATUS);
- }
- static void bfin_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- tf->command = bfin_check_status(ap);
- tf->feature = read_atapi_register(base, ATA_REG_ERR);
- tf->nsect = read_atapi_register(base, ATA_REG_NSECT);
- tf->lbal = read_atapi_register(base, ATA_REG_LBAL);
- tf->lbam = read_atapi_register(base, ATA_REG_LBAM);
- tf->lbah = read_atapi_register(base, ATA_REG_LBAH);
- tf->device = read_atapi_register(base, ATA_REG_DEVICE);
- if (tf->flags & ATA_TFLAG_LBA48) {
- write_atapi_register(base, ATA_REG_CTRL, tf->ctl | ATA_HOB);
- tf->hob_feature = read_atapi_register(base, ATA_REG_ERR);
- tf->hob_nsect = read_atapi_register(base, ATA_REG_NSECT);
- tf->hob_lbal = read_atapi_register(base, ATA_REG_LBAL);
- tf->hob_lbam = read_atapi_register(base, ATA_REG_LBAM);
- tf->hob_lbah = read_atapi_register(base, ATA_REG_LBAH);
- }
- }
- static void bfin_exec_command(struct ata_port *ap,
- const struct ata_taskfile *tf)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
- write_atapi_register(base, ATA_REG_CMD, tf->command);
- ata_sff_pause(ap);
- }
- static u8 bfin_check_altstatus(struct ata_port *ap)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- return read_atapi_register(base, ATA_REG_ALTSTATUS);
- }
- static void bfin_dev_select(struct ata_port *ap, unsigned int device)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- u8 tmp;
- if (device == 0)
- tmp = ATA_DEVICE_OBS;
- else
- tmp = ATA_DEVICE_OBS | ATA_DEV1;
- write_atapi_register(base, ATA_REG_DEVICE, tmp);
- ata_sff_pause(ap);
- }
- static void bfin_set_devctl(struct ata_port *ap, u8 ctl)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- write_atapi_register(base, ATA_REG_CTRL, ctl);
- }
- static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct dma_desc_array *dma_desc_cpu = (struct dma_desc_array *)ap->bmdma_prd;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned short config = DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_16 | DMAEN;
- struct scatterlist *sg;
- unsigned int si;
- unsigned int channel;
- unsigned int dir;
- unsigned int size = 0;
- dev_dbg(qc->ap->dev, "in atapi dma setup\n");
-
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- channel = CH_ATAPI_TX;
- dir = DMA_TO_DEVICE;
- } else {
- channel = CH_ATAPI_RX;
- dir = DMA_FROM_DEVICE;
- config |= WNR;
- }
- dma_map_sg(ap->dev, qc->sg, qc->n_elem, dir);
-
- for_each_sg(qc->sg, sg, qc->n_elem, si) {
- dma_desc_cpu[si].start_addr = sg_dma_address(sg);
- dma_desc_cpu[si].cfg = config;
- dma_desc_cpu[si].x_count = sg_dma_len(sg) >> 1;
- dma_desc_cpu[si].x_modify = 2;
- size += sg_dma_len(sg);
- }
-
- dma_desc_cpu[qc->n_elem - 1].cfg &= ~(DMAFLOW | NDSIZE);
- flush_dcache_range((unsigned int)dma_desc_cpu,
- (unsigned int)dma_desc_cpu +
- qc->n_elem * sizeof(struct dma_desc_array));
-
- set_dma_curr_desc_addr(channel, (unsigned long *)ap->bmdma_prd_dma);
- set_dma_x_count(channel, 0);
- set_dma_x_modify(channel, 0);
- set_dma_config(channel, config);
- SSYNC();
-
- bfin_exec_command(ap, &qc->tf);
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
- | XFER_DIR));
- } else {
-
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
- & ~XFER_DIR));
- }
-
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
-
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM);
-
- ATAPI_SET_XFER_LEN(base, size >> 1);
- }
- static void bfin_bmdma_start(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- dev_dbg(qc->ap->dev, "in atapi dma start\n");
- if (!(ap->udma_mask || ap->mwdma_mask))
- return;
-
- if (ap->udma_mask)
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base)
- | ULTRA_START);
- else
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base)
- | MULTI_START);
- }
- static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- unsigned int dir;
- dev_dbg(qc->ap->dev, "in atapi dma stop\n");
- if (!(ap->udma_mask || ap->mwdma_mask))
- return;
-
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- dir = DMA_TO_DEVICE;
- disable_dma(CH_ATAPI_TX);
- } else {
- dir = DMA_FROM_DEVICE;
- disable_dma(CH_ATAPI_RX);
- }
- dma_unmap_sg(ap->dev, qc->sg, qc->n_elem, dir);
- }
- static unsigned int bfin_devchk(struct ata_port *ap,
- unsigned int device)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- u8 nsect, lbal;
- bfin_dev_select(ap, device);
- write_atapi_register(base, ATA_REG_NSECT, 0x55);
- write_atapi_register(base, ATA_REG_LBAL, 0xaa);
- write_atapi_register(base, ATA_REG_NSECT, 0xaa);
- write_atapi_register(base, ATA_REG_LBAL, 0x55);
- write_atapi_register(base, ATA_REG_NSECT, 0x55);
- write_atapi_register(base, ATA_REG_LBAL, 0xaa);
- nsect = read_atapi_register(base, ATA_REG_NSECT);
- lbal = read_atapi_register(base, ATA_REG_LBAL);
- if ((nsect == 0x55) && (lbal == 0xaa))
- return 1;
- return 0;
- }
- static void bfin_bus_post_reset(struct ata_port *ap, unsigned int devmask)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned int dev0 = devmask & (1 << 0);
- unsigned int dev1 = devmask & (1 << 1);
- unsigned long deadline;
-
- if (dev0)
- ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-
- deadline = ata_deadline(jiffies, ATA_TMOUT_BOOT);
- while (dev1) {
- u8 nsect, lbal;
- bfin_dev_select(ap, 1);
- nsect = read_atapi_register(base, ATA_REG_NSECT);
- lbal = read_atapi_register(base, ATA_REG_LBAL);
- if ((nsect == 1) && (lbal == 1))
- break;
- if (time_after(jiffies, deadline)) {
- dev1 = 0;
- break;
- }
- ata_msleep(ap, 50);
- }
- if (dev1)
- ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-
- bfin_dev_select(ap, 0);
- if (dev1)
- bfin_dev_select(ap, 1);
- if (dev0)
- bfin_dev_select(ap, 0);
- }
- static unsigned int bfin_bus_softreset(struct ata_port *ap,
- unsigned int devmask)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-
- write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
- udelay(20);
- write_atapi_register(base, ATA_REG_CTRL, ap->ctl | ATA_SRST);
- udelay(20);
- write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
-
- ata_msleep(ap, 150);
-
- if (bfin_check_status(ap) == 0xFF)
- return 0;
- bfin_bus_post_reset(ap, devmask);
- return 0;
- }
- static int bfin_softreset(struct ata_link *link, unsigned int *classes,
- unsigned long deadline)
- {
- struct ata_port *ap = link->ap;
- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
- unsigned int devmask = 0, err_mask;
- u8 err;
-
- if (bfin_devchk(ap, 0))
- devmask |= (1 << 0);
- if (slave_possible && bfin_devchk(ap, 1))
- devmask |= (1 << 1);
-
- bfin_dev_select(ap, 0);
-
- err_mask = bfin_bus_softreset(ap, devmask);
- if (err_mask) {
- ata_port_err(ap, "SRST failed (err_mask=0x%x)\n",
- err_mask);
- return -EIO;
- }
-
- classes[0] = ata_sff_dev_classify(&ap->link.device[0],
- devmask & (1 << 0), &err);
- if (slave_possible && err != 0x81)
- classes[1] = ata_sff_dev_classify(&ap->link.device[1],
- devmask & (1 << 1), &err);
- return 0;
- }
- static unsigned char bfin_bmdma_status(struct ata_port *ap)
- {
- unsigned char host_stat = 0;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON | ULTRA_XFER_ON))
- host_stat |= ATA_DMA_ACTIVE;
- if (ATAPI_GET_INT_STATUS(base) & ATAPI_DEV_INT)
- host_stat |= ATA_DMA_INTR;
- dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat);
- return host_stat;
- }
- static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
- {
- struct ata_port *ap = dev->link->ap;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- unsigned int words = buflen >> 1;
- unsigned short *buf16 = (u16 *)buf;
-
- if (rw == READ)
- read_atapi_data(base, words, buf16);
- else
- write_atapi_data(base, words, buf16);
-
- if (unlikely(buflen & 0x01)) {
- unsigned short align_buf[1] = { 0 };
- unsigned char *trailing_buf = buf + buflen - 1;
- if (rw == READ) {
- read_atapi_data(base, 1, align_buf);
- memcpy(trailing_buf, align_buf, 1);
- } else {
- memcpy(align_buf, trailing_buf, 1);
- write_atapi_data(base, 1, align_buf);
- }
- words++;
- }
- return words << 1;
- }
- static void bfin_irq_clear(struct ata_port *ap)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- dev_dbg(ap->dev, "in atapi irq clear\n");
- ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
- | MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
- | MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
- }
- void bfin_thaw(struct ata_port *ap)
- {
- dev_dbg(ap->dev, "in atapi dma thaw\n");
- bfin_check_status(ap);
- ata_sff_irq_on(ap);
- }
- static void bfin_postreset(struct ata_link *link, unsigned int *classes)
- {
- struct ata_port *ap = link->ap;
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-
- ata_sff_irq_on(ap);
-
- if (classes[0] != ATA_DEV_NONE)
- bfin_dev_select(ap, 1);
- if (classes[1] != ATA_DEV_NONE)
- bfin_dev_select(ap, 0);
-
- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
- return;
- }
-
- write_atapi_register(base, ATA_REG_CTRL, ap->ctl);
- }
- static void bfin_port_stop(struct ata_port *ap)
- {
- dev_dbg(ap->dev, "in atapi port stop\n");
- if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
- dma_free_coherent(ap->dev,
- BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
- ap->bmdma_prd,
- ap->bmdma_prd_dma);
- free_dma(CH_ATAPI_RX);
- free_dma(CH_ATAPI_TX);
- }
- }
- static int bfin_port_start(struct ata_port *ap)
- {
- dev_dbg(ap->dev, "in atapi port start\n");
- if (!(ap->udma_mask || ap->mwdma_mask))
- return 0;
- ap->bmdma_prd = dma_alloc_coherent(ap->dev,
- BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
- &ap->bmdma_prd_dma,
- GFP_KERNEL);
- if (ap->bmdma_prd == NULL) {
- dev_info(ap->dev, "Unable to allocate DMA descriptor array.\n");
- goto out;
- }
- if (request_dma(CH_ATAPI_RX, "BFIN ATAPI RX DMA") >= 0) {
- if (request_dma(CH_ATAPI_TX,
- "BFIN ATAPI TX DMA") >= 0)
- return 0;
- free_dma(CH_ATAPI_RX);
- dma_free_coherent(ap->dev,
- BFIN_MAX_SG_SEGMENTS * sizeof(struct dma_desc_array),
- ap->bmdma_prd,
- ap->bmdma_prd_dma);
- }
- out:
- ap->udma_mask = 0;
- ap->mwdma_mask = 0;
- dev_err(ap->dev, "Unable to request ATAPI DMA!"
- " Continue in PIO mode.\n");
- return 0;
- }
- static unsigned int bfin_ata_host_intr(struct ata_port *ap,
- struct ata_queued_cmd *qc)
- {
- struct ata_eh_info *ehi = &ap->link.eh_info;
- u8 status, host_stat = 0;
- VPRINTK("ata%u: protocol %d task_state %d\n",
- ap->print_id, qc->tf.protocol, ap->hsm_task_state);
-
- switch (ap->hsm_task_state) {
- case HSM_ST_FIRST:
-
-
- if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
- goto idle_irq;
- break;
- case HSM_ST_LAST:
- if (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATAPI_PROT_DMA) {
-
- host_stat = ap->ops->bmdma_status(ap);
- VPRINTK("ata%u: host_stat 0x%X\n",
- ap->print_id, host_stat);
-
- if (!(host_stat & ATA_DMA_INTR))
- goto idle_irq;
-
- ap->ops->bmdma_stop(qc);
- if (unlikely(host_stat & ATA_DMA_ERR)) {
-
- qc->err_mask |= AC_ERR_HOST_BUS;
- ap->hsm_task_state = HSM_ST_ERR;
- }
- }
- break;
- case HSM_ST:
- break;
- default:
- goto idle_irq;
- }
-
- status = ap->ops->sff_check_altstatus(ap);
- if (status & ATA_BUSY)
- goto busy_ata;
-
- status = ap->ops->sff_check_status(ap);
- if (unlikely(status & ATA_BUSY))
- goto busy_ata;
-
- ap->ops->sff_irq_clear(ap);
- ata_sff_hsm_move(ap, qc, status, 0);
- if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
- qc->tf.protocol == ATAPI_PROT_DMA))
- ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
- busy_ata:
- return 1;
- idle_irq:
- ap->stats.idle_irq++;
- #ifdef ATA_IRQ_TRAP
- if ((ap->stats.idle_irq % 1000) == 0) {
- ap->ops->irq_ack(ap, 0);
- ata_port_warn(ap, "irq trap\n");
- return 1;
- }
- #endif
- return 0;
- }
- static irqreturn_t bfin_ata_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- unsigned int i;
- unsigned int handled = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&host->lock, flags);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->link.active_tag);
- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
- handled |= bfin_ata_host_intr(ap, qc);
- }
- spin_unlock_irqrestore(&host->lock, flags);
- return IRQ_RETVAL(handled);
- }
- static struct scsi_host_template bfin_sht = {
- ATA_BASE_SHT(DRV_NAME),
- .sg_tablesize = BFIN_MAX_SG_SEGMENTS,
- .dma_boundary = ATA_DMA_BOUNDARY,
- };
- static struct ata_port_operations bfin_pata_ops = {
- .inherits = &ata_bmdma_port_ops,
- .set_piomode = bfin_set_piomode,
- .set_dmamode = bfin_set_dmamode,
- .sff_tf_load = bfin_tf_load,
- .sff_tf_read = bfin_tf_read,
- .sff_exec_command = bfin_exec_command,
- .sff_check_status = bfin_check_status,
- .sff_check_altstatus = bfin_check_altstatus,
- .sff_dev_select = bfin_dev_select,
- .sff_set_devctl = bfin_set_devctl,
- .bmdma_setup = bfin_bmdma_setup,
- .bmdma_start = bfin_bmdma_start,
- .bmdma_stop = bfin_bmdma_stop,
- .bmdma_status = bfin_bmdma_status,
- .sff_data_xfer = bfin_data_xfer,
- .qc_prep = ata_noop_qc_prep,
- .thaw = bfin_thaw,
- .softreset = bfin_softreset,
- .postreset = bfin_postreset,
- .sff_irq_clear = bfin_irq_clear,
- .port_start = bfin_port_start,
- .port_stop = bfin_port_stop,
- };
- static struct ata_port_info bfin_port_info[] = {
- {
- .flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = ATA_PIO4,
- .mwdma_mask = 0,
- .udma_mask = 0,
- .port_ops = &bfin_pata_ops,
- },
- };
- static int bfin_reset_controller(struct ata_host *host)
- {
- void __iomem *base = (void __iomem *)host->ports[0]->ioaddr.ctl_addr;
- int count;
- unsigned short status;
-
- ATAPI_SET_INT_MASK(base, 0);
- SSYNC();
-
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | DEV_RST);
- udelay(30);
-
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) & ~DEV_RST);
- msleep(2);
-
- count = 10000000;
- do {
- status = read_atapi_register(base, ATA_REG_STATUS);
- } while (--count && (status & ATA_BUSY));
-
- ATAPI_SET_INT_MASK(base, 1);
- SSYNC();
- return (!count);
- }
- static unsigned short atapi_io_port[] = {
- P_ATAPI_RESET,
- P_ATAPI_DIOR,
- P_ATAPI_DIOW,
- P_ATAPI_CS0,
- P_ATAPI_CS1,
- P_ATAPI_DMACK,
- P_ATAPI_DMARQ,
- P_ATAPI_INTRQ,
- P_ATAPI_IORDY,
- P_ATAPI_D0A,
- P_ATAPI_D1A,
- P_ATAPI_D2A,
- P_ATAPI_D3A,
- P_ATAPI_D4A,
- P_ATAPI_D5A,
- P_ATAPI_D6A,
- P_ATAPI_D7A,
- P_ATAPI_D8A,
- P_ATAPI_D9A,
- P_ATAPI_D10A,
- P_ATAPI_D11A,
- P_ATAPI_D12A,
- P_ATAPI_D13A,
- P_ATAPI_D14A,
- P_ATAPI_D15A,
- P_ATAPI_A0A,
- P_ATAPI_A1A,
- P_ATAPI_A2A,
- 0
- };
- static int bfin_atapi_probe(struct platform_device *pdev)
- {
- int board_idx = 0;
- struct resource *res;
- struct ata_host *host;
- unsigned int fsclk = get_sclk();
- int udma_mode = 5;
- const struct ata_port_info *ppi[] =
- { &bfin_port_info[board_idx], NULL };
-
- if (unlikely(pdev->num_resources != 2)) {
- dev_err(&pdev->dev, "invalid number of resources\n");
- return -EINVAL;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL)
- return -EINVAL;
- while (bfin_port_info[board_idx].udma_mask > 0 &&
- udma_fsclk[udma_mode] > fsclk) {
- udma_mode--;
- bfin_port_info[board_idx].udma_mask >>= 1;
- }
-
- host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
- if (!host)
- return -ENOMEM;
- host->ports[0]->ioaddr.ctl_addr = (void *)res->start;
- if (peripheral_request_list(atapi_io_port, "atapi-io-port")) {
- dev_err(&pdev->dev, "Requesting Peripherals failed\n");
- return -EFAULT;
- }
- if (bfin_reset_controller(host)) {
- peripheral_free_list(atapi_io_port);
- dev_err(&pdev->dev, "Fail to reset ATAPI device\n");
- return -EFAULT;
- }
- if (ata_host_activate(host, platform_get_irq(pdev, 0),
- bfin_ata_interrupt, IRQF_SHARED, &bfin_sht) != 0) {
- peripheral_free_list(atapi_io_port);
- dev_err(&pdev->dev, "Fail to attach ATAPI device\n");
- return -ENODEV;
- }
- platform_set_drvdata(pdev, host);
- return 0;
- }
- static int bfin_atapi_remove(struct platform_device *pdev)
- {
- struct ata_host *host = platform_get_drvdata(pdev);
- ata_host_detach(host);
- peripheral_free_list(atapi_io_port);
- return 0;
- }
- #ifdef CONFIG_PM_SLEEP
- static int bfin_atapi_suspend(struct platform_device *pdev, pm_message_t state)
- {
- struct ata_host *host = platform_get_drvdata(pdev);
- if (host)
- return ata_host_suspend(host, state);
- else
- return 0;
- }
- static int bfin_atapi_resume(struct platform_device *pdev)
- {
- struct ata_host *host = platform_get_drvdata(pdev);
- int ret;
- if (host) {
- ret = bfin_reset_controller(host);
- if (ret) {
- printk(KERN_ERR DRV_NAME ": Error during HW init\n");
- return ret;
- }
- ata_host_resume(host);
- }
- return 0;
- }
- #else
- #define bfin_atapi_suspend NULL
- #define bfin_atapi_resume NULL
- #endif
- static struct platform_driver bfin_atapi_driver = {
- .probe = bfin_atapi_probe,
- .remove = bfin_atapi_remove,
- .suspend = bfin_atapi_suspend,
- .resume = bfin_atapi_resume,
- .driver = {
- .name = DRV_NAME,
- },
- };
- #define ATAPI_MODE_SIZE 10
- static char bfin_atapi_mode[ATAPI_MODE_SIZE];
- static int __init bfin_atapi_init(void)
- {
- pr_info("register bfin atapi driver\n");
- switch(bfin_atapi_mode[0]) {
- case 'p':
- case 'P':
- break;
- case 'm':
- case 'M':
- bfin_port_info[0].mwdma_mask = ATA_MWDMA2;
- break;
- default:
- bfin_port_info[0].udma_mask = ATA_UDMA5;
- };
- return platform_driver_register(&bfin_atapi_driver);
- }
- static void __exit bfin_atapi_exit(void)
- {
- platform_driver_unregister(&bfin_atapi_driver);
- }
- module_init(bfin_atapi_init);
- module_exit(bfin_atapi_exit);
- module_param_string(bfin_atapi_mode, bfin_atapi_mode, ATAPI_MODE_SIZE, 0);
- MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
- MODULE_DESCRIPTION("PATA driver for blackfin 54x ATAPI controller");
- MODULE_LICENSE("GPL");
- MODULE_VERSION(DRV_VERSION);
- MODULE_ALIAS("platform:" DRV_NAME);
|