123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704 |
- /*
- * File: drivers/ata/pata_bf54x.c
- * Author: Sonic Zhang <sonic.zhang@analog.com>
- *
- * Created:
- * Description: PATA Driver for blackfin 54x
- *
- * Modified:
- * Copyright 2007 Analog Devices Inc.
- *
- * Bugs: Enter bugs at http://blackfin.uclinux.org/
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see the file COPYING, or write
- * to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #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 <asm/dma.h>
- #include <asm/gpio.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
- /* These are the offset of the controller's registers */
- #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)
- /**
- * PIO Mode - Frequency compatibility
- */
- /* mode: 0 1 2 3 4 */
- static const u32 pio_fsclk[] =
- { 33333333, 33333333, 33333333, 33333333, 33333333 };
- /**
- * MDMA Mode - Frequency compatibility
- */
- /* mode: 0 1 2 */
- static const u32 mdma_fsclk[] = { 33333333, 33333333, 33333333 };
- /**
- * UDMA Mode - Frequency compatibility
- *
- * UDMA5 - 100 MB/s - SCLK = 133 MHz
- * UDMA4 - 66 MB/s - SCLK >= 80 MHz
- * UDMA3 - 44.4 MB/s - SCLK >= 50 MHz
- * UDMA2 - 33 MB/s - SCLK >= 40 MHz
- */
- /* mode: 0 1 2 3 4 5 */
- static const u32 udma_fsclk[] =
- { 33333333, 33333333, 40000000, 50000000, 80000000, 133333333 };
- /**
- * Register transfer timing table
- */
- /* mode: 0 1 2 3 4 */
- /* Cycle Time */
- static const u32 reg_t0min[] = { 600, 383, 330, 180, 120 };
- /* DIOR/DIOW to end cycle */
- static const u32 reg_t2min[] = { 290, 290, 290, 70, 25 };
- /* DIOR/DIOW asserted pulse width */
- static const u32 reg_teocmin[] = { 290, 290, 290, 80, 70 };
- /**
- * PIO timing table
- */
- /* mode: 0 1 2 3 4 */
- /* Cycle Time */
- static const u32 pio_t0min[] = { 600, 383, 240, 180, 120 };
- /* Address valid to DIOR/DIORW */
- static const u32 pio_t1min[] = { 70, 50, 30, 30, 25 };
- /* DIOR/DIOW to end cycle */
- static const u32 pio_t2min[] = { 165, 125, 100, 80, 70 };
- /* DIOR/DIOW asserted pulse width */
- static const u32 pio_teocmin[] = { 165, 125, 100, 70, 25 };
- /* DIOW data hold */
- static const u32 pio_t4min[] = { 30, 20, 15, 10, 10 };
- /* ******************************************************************
- * Multiword DMA timing table
- * ******************************************************************
- */
- /* mode: 0 1 2 */
- /* Cycle Time */
- static const u32 mdma_t0min[] = { 480, 150, 120 };
- /* DIOR/DIOW asserted pulse width */
- static const u32 mdma_tdmin[] = { 215, 80, 70 };
- /* DMACK to read data released */
- static const u32 mdma_thmin[] = { 20, 15, 10 };
- /* DIOR/DIOW to DMACK hold */
- static const u32 mdma_tjmin[] = { 20, 5, 5 };
- /* DIOR negated pulse width */
- static const u32 mdma_tkrmin[] = { 50, 50, 25 };
- /* DIOR negated pulse width */
- static const u32 mdma_tkwmin[] = { 215, 50, 25 };
- /* CS[1:0] valid to DIOR/DIOW */
- static const u32 mdma_tmmin[] = { 50, 30, 25 };
- /* DMACK to read data released */
- static const u32 mdma_tzmax[] = { 20, 25, 25 };
- /**
- * Ultra DMA timing table
- */
- /* mode: 0 1 2 3 4 5 */
- 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
- /**
- *
- * Function: num_clocks_min
- *
- * Description:
- * calculate number of SCLK cycles to meet minimum timing
- */
- 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;
- }
- /**
- * bfin_set_piomode - Initialize host controller PATA PIO timings
- * @ap: Port whose timings we are configuring
- * @adev: um
- *
- * Set PIO mode for device.
- *
- * LOCKING:
- * None (inherited from caller).
- */
- 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;
- /* the most restrictive timing value is t6 and tc, the DIOW - data hold
- * If one SCLK pulse is longer than this minimum value then register
- * transfers cannot be supported at this frequency.
- */
- 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);
- /* calculate the timing values for register transfers. */
- while (mode > 0 && pio_fsclk[mode] > fsclk)
- mode--;
- /* DIOR/DIOW to end cycle time */
- t2_reg = num_clocks_min(reg_t2min[mode], fsclk);
- /* DIOR/DIOW asserted pulse width */
- teoc_reg = num_clocks_min(reg_teocmin[mode], fsclk);
- /* Cycle Time */
- n0 = num_clocks_min(reg_t0min[mode], fsclk);
- /* increase t2 until we meed the minimum cycle length */
- if (t2_reg + teoc_reg < n0)
- t2_reg = n0 - teoc_reg;
- /* calculate the timing values for pio transfers. */
- /* DIOR/DIOW to end cycle time */
- t2_pio = num_clocks_min(pio_t2min[mode], fsclk);
- /* DIOR/DIOW asserted pulse width */
- teoc_pio = num_clocks_min(pio_teocmin[mode], fsclk);
- /* Cycle Time */
- n0 = num_clocks_min(pio_t0min[mode], fsclk);
- /* increase t2 until we meed the minimum cycle length */
- if (t2_pio + teoc_pio < n0)
- t2_pio = n0 - teoc_pio;
- /* Address valid to DIOR/DIORW */
- t1_reg = num_clocks_min(pio_t1min[mode], fsclk);
- /* DIOW data hold */
- 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);
- }
- /* Disable host ATAPI PIO interrupts */
- ATAPI_SET_INT_MASK(base, ATAPI_GET_INT_MASK(base)
- & ~(PIO_DONE_MASK | HOST_TERM_XFER_MASK));
- SSYNC();
- }
- }
- /**
- * bfin_set_dmamode - Initialize host controller PATA DMA timings
- * @ap: Port whose timings we are configuring
- * @adev: um
- *
- * Set UDMA mode for device.
- *
- * LOCKING:
- * None (inherited from caller).
- */
- 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);
- /* the most restrictive timing value is t6 and tc,
- * the DIOW - data hold. If one SCLK pulse is longer
- * than this minimum value then register
- * transfers cannot be supported at this frequency.
- */
- while (mode > 0 && udma_fsclk[mode] > fsclk)
- mode--;
- nmin = num_clocks_min(udma_tmin[mode], fsclk);
- if (nmin >= 1) {
- /* calculate the timing values for Ultra DMA. */
- tdvs = num_clocks_min(udma_tdvsmin[mode], fsclk);
- tcyc = num_clocks_min(udma_tcycmin[mode], fsclk);
- tcyc_tdvs = 2;
- /* increase tcyc - tdvs (tcyc_tdvs) until we meed
- * the minimum cycle length
- */
- if (tdvs + tcyc_tdvs < tcyc)
- tcyc_tdvs = tcyc - tdvs;
- /* Mow assign the values required for the timing
- * registers
- */
- 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);
- /* the most restrictive timing value is tf, the DMACK to
- * read data released. If one SCLK pulse is longer than
- * this maximum value then the MDMA mode
- * cannot be supported at this frequency.
- */
- while (mode > 0 && mdma_fsclk[mode] > fsclk)
- mode--;
- nf = num_clocks_min(tfmin, fsclk);
- if (nf >= 1) {
- /* calculate the timing values for Multi-word DMA. */
- /* DIOR/DIOW asserted pulse width */
- td = num_clocks_min(mdma_tdmin[mode], fsclk);
- /* DIOR negated pulse width */
- tkw = num_clocks_min(mdma_tkwmin[mode], fsclk);
- /* Cycle Time */
- n0 = num_clocks_min(mdma_t0min[mode], fsclk);
- /* increase tk until we meed the minimum cycle length */
- if (tkw + td < n0)
- tkw = n0 - td;
- /* DIOR negated pulse width - read */
- tkr = num_clocks_min(mdma_tkrmin[mode], fsclk);
- /* CS{1:0] valid to DIOR/DIOW */
- tm = num_clocks_min(mdma_tmmin[mode], fsclk);
- /* DIOR/DIOW to DMACK hold */
- teoc = num_clocks_min(mdma_tjmin[mode], fsclk);
- /* DIOW Data hold */
- 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;
- }
- /**
- *
- * Function: wait_complete
- *
- * Description: Waits the interrupt from device
- *
- */
- 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);
- }
- /**
- *
- * Function: write_atapi_register
- *
- * Description: Writes to ATA Device Resgister
- *
- */
- static void write_atapi_register(void __iomem *base,
- unsigned long ata_reg, unsigned short value)
- {
- /* Program the ATA_DEV_TXBUF register with write data (to be
- * written into the device).
- */
- ATAPI_SET_DEV_TXBUF(base, value);
- /* Program the ATA_DEV_ADDR register with address of the
- * device register (0x01 to 0x0F).
- */
- ATAPI_SET_DEV_ADDR(base, ata_reg);
- /* Program the ATA_CTRL register with dir set to write (1)
- */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR));
- /* ensure PIO DMA is not set */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- /* and start the transfer */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
- /* Wait for the interrupt to indicate the end of the transfer.
- * (We need to wait on and clear rhe ATA_DEV_INT interrupt status)
- */
- wait_complete(base, PIO_DONE_INT);
- }
- /**
- *
- * Function: read_atapi_register
- *
- *Description: Reads from ATA Device Resgister
- *
- */
- static unsigned short read_atapi_register(void __iomem *base,
- unsigned long ata_reg)
- {
- /* Program the ATA_DEV_ADDR register with address of the
- * device register (0x01 to 0x0F).
- */
- ATAPI_SET_DEV_ADDR(base, ata_reg);
- /* Program the ATA_CTRL register with dir set to read (0) and
- */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR));
- /* ensure PIO DMA is not set */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- /* and start the transfer */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
- /* Wait for the interrupt to indicate the end of the transfer.
- * (PIO_DONE interrupt is set and it doesn't seem to matter
- * that we don't clear it)
- */
- wait_complete(base, PIO_DONE_INT);
- /* Read the ATA_DEV_RXBUF register with write data (to be
- * written into the device).
- */
- return ATAPI_GET_DEV_RXBUF(base);
- }
- /**
- *
- * Function: write_atapi_register_data
- *
- * Description: Writes to ATA Device Resgister
- *
- */
- static void write_atapi_data(void __iomem *base,
- int len, unsigned short *buf)
- {
- int i;
- /* Set transfer length to 1 */
- ATAPI_SET_XFER_LEN(base, 1);
- /* Program the ATA_DEV_ADDR register with address of the
- * ATA_REG_DATA
- */
- ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA);
- /* Program the ATA_CTRL register with dir set to write (1)
- */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | XFER_DIR));
- /* ensure PIO DMA is not set */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- for (i = 0; i < len; i++) {
- /* Program the ATA_DEV_TXBUF register with write data (to be
- * written into the device).
- */
- ATAPI_SET_DEV_TXBUF(base, buf[i]);
- /* and start the transfer */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
- /* Wait for the interrupt to indicate the end of the transfer.
- * (We need to wait on and clear rhe ATA_DEV_INT
- * interrupt status)
- */
- wait_complete(base, PIO_DONE_INT);
- }
- }
- /**
- *
- * Function: read_atapi_register_data
- *
- * Description: Reads from ATA Device Resgister
- *
- */
- static void read_atapi_data(void __iomem *base,
- int len, unsigned short *buf)
- {
- int i;
- /* Set transfer length to 1 */
- ATAPI_SET_XFER_LEN(base, 1);
- /* Program the ATA_DEV_ADDR register with address of the
- * ATA_REG_DATA
- */
- ATAPI_SET_DEV_ADDR(base, ATA_REG_DATA);
- /* Program the ATA_CTRL register with dir set to read (0) and
- */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~XFER_DIR));
- /* ensure PIO DMA is not set */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) & ~PIO_USE_DMA));
- for (i = 0; i < len; i++) {
- /* and start the transfer */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base) | PIO_START));
- /* Wait for the interrupt to indicate the end of the transfer.
- * (PIO_DONE interrupt is set and it doesn't seem to matter
- * that we don't clear it)
- */
- wait_complete(base, PIO_DONE_INT);
- /* Read the ATA_DEV_RXBUF register with write data (to be
- * written into the device).
- */
- buf[i] = ATAPI_GET_DEV_RXBUF(base);
- }
- }
- /**
- * bfin_tf_load - send taskfile registers to host controller
- * @ap: Port to which output is sent
- * @tf: ATA taskfile register set
- *
- * Note: Original code is ata_sff_tf_load().
- */
- 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);
- }
- /**
- * bfin_check_status - Read device status reg & clear interrupt
- * @ap: port where the device is
- *
- * Note: Original code is ata_check_status().
- */
- 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);
- }
- /**
- * bfin_tf_read - input device's ATA taskfile shadow registers
- * @ap: Port from which input is read
- * @tf: ATA taskfile register set for storing input
- *
- * Note: Original code is ata_sff_tf_read().
- */
- 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);
- }
- }
- /**
- * bfin_exec_command - issue ATA command to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Note: Original code is ata_sff_exec_command().
- */
- 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);
- }
- /**
- * bfin_check_altstatus - Read device alternate status reg
- * @ap: port where the device is
- */
- 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);
- }
- /**
- * bfin_dev_select - Select device 0/1 on ATA bus
- * @ap: ATA channel to manipulate
- * @device: ATA device (numbered from zero) to select
- *
- * Note: Original code is ata_sff_dev_select().
- */
- 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);
- }
- /**
- * bfin_set_devctl - Write device control reg
- * @ap: port where the device is
- * @ctl: value to write
- */
- 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);
- }
- /**
- * bfin_bmdma_setup - Set up IDE DMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_setup().
- */
- 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");
- /* Program the ATA_CTRL register with dir */
- 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);
- /* fill the ATAPI DMA controller */
- 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);
- }
- /* Set the last descriptor to stop mode */
- 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));
- /* Enable ATA DMA operation*/
- 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();
- /* Send ATA DMA command */
- bfin_exec_command(ap, &qc->tf);
- if (qc->tf.flags & ATA_TFLAG_WRITE) {
- /* set ATA DMA write direction */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
- | XFER_DIR));
- } else {
- /* set ATA DMA read direction */
- ATAPI_SET_CONTROL(base, (ATAPI_GET_CONTROL(base)
- & ~XFER_DIR));
- }
- /* Reset all transfer count */
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
- /* Set ATAPI state machine contorl in terminate sequence */
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM);
- /* Set transfer length to the total size of sg buffers */
- ATAPI_SET_XFER_LEN(base, size >> 1);
- }
- /**
- * bfin_bmdma_start - Start an IDE DMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_start().
- */
- 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;
- /* start ATAPI transfer*/
- 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);
- }
- /**
- * bfin_bmdma_stop - Stop IDE DMA transfer
- * @qc: Command we are ending DMA for
- */
- 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;
- /* stop ATAPI DMA controller*/
- 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);
- }
- /**
- * bfin_devchk - PATA device presence detection
- * @ap: ATA channel to examine
- * @device: Device to examine (starting at zero)
- *
- * Note: Original code is ata_devchk().
- */
- 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; /* we found a device */
- return 0; /* nothing found */
- }
- /**
- * bfin_bus_post_reset - PATA device post reset
- *
- * Note: Original code is ata_bus_post_reset().
- */
- 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 device 0 was found in ata_devchk, wait for its
- * BSY bit to clear
- */
- if (dev0)
- ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
- /* if device 1 was found in ata_devchk, wait for
- * register access, then wait for BSY to clear
- */
- 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); /* give drive a breather */
- }
- if (dev1)
- ata_sff_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
- /* is all this really necessary? */
- bfin_dev_select(ap, 0);
- if (dev1)
- bfin_dev_select(ap, 1);
- if (dev0)
- bfin_dev_select(ap, 0);
- }
- /**
- * bfin_bus_softreset - PATA device software reset
- *
- * Note: Original code is ata_bus_softreset().
- */
- static unsigned int bfin_bus_softreset(struct ata_port *ap,
- unsigned int devmask)
- {
- void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- /* software reset. causes dev0 to be selected */
- 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);
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready
- */
- ata_msleep(ap, 150);
- /* Before we perform post reset processing we want to see if
- * the bus shows 0xFF because the odd clown forgets the D7
- * pulldown resistor.
- */
- if (bfin_check_status(ap) == 0xFF)
- return 0;
- bfin_bus_post_reset(ap, devmask);
- return 0;
- }
- /**
- * bfin_softreset - reset host port via ATA SRST
- * @ap: port to reset
- * @classes: resulting classes of attached devices
- *
- * Note: Original code is ata_sff_softreset().
- */
- 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;
- /* determine if device 0/1 are present */
- if (bfin_devchk(ap, 0))
- devmask |= (1 << 0);
- if (slave_possible && bfin_devchk(ap, 1))
- devmask |= (1 << 1);
- /* select device 0 again */
- bfin_dev_select(ap, 0);
- /* issue bus reset */
- 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;
- }
- /* determine by signature whether we have ATA or ATAPI devices */
- 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;
- }
- /**
- * bfin_bmdma_status - Read IDE DMA status
- * @ap: Port associated with this ATA transaction.
- */
- 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;
- }
- /**
- * bfin_data_xfer - Transfer data by PIO
- * @adev: device for this I/O
- * @buf: data buffer
- * @buflen: buffer length
- * @write_data: read/write
- *
- * Note: Original code is ata_sff_data_xfer().
- */
- 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;
- /* Transfer multiple of 2 bytes */
- if (rw == READ)
- read_atapi_data(base, words, buf16);
- else
- write_atapi_data(base, words, buf16);
- /* Transfer trailing 1 byte, if any. */
- 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;
- }
- /**
- * bfin_irq_clear - Clear ATAPI interrupt.
- * @ap: Port associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_irq_clear().
- */
- 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);
- }
- /**
- * bfin_thaw - Thaw DMA controller port
- * @ap: port to thaw
- *
- * Note: Original code is ata_sff_thaw().
- */
- 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);
- }
- /**
- * bfin_postreset - standard postreset callback
- * @ap: the target ata_port
- * @classes: classes of attached devices
- *
- * Note: Original code is ata_sff_postreset().
- */
- 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;
- /* re-enable interrupts */
- ata_sff_irq_on(ap);
- /* is double-select really necessary? */
- if (classes[0] != ATA_DEV_NONE)
- bfin_dev_select(ap, 1);
- if (classes[1] != ATA_DEV_NONE)
- bfin_dev_select(ap, 0);
- /* bail out if no device is present */
- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
- return;
- }
- /* set up device control */
- 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);
- /* Check whether we are expecting interrupt in this state */
- switch (ap->hsm_task_state) {
- case HSM_ST_FIRST:
- /* Some pre-ATAPI-4 devices assert INTRQ
- * at this state when ready to receive CDB.
- */
- /* Check the ATA_DFLAG_CDB_INTR flag is enough here.
- * The flag was turned on only for atapi devices.
- * No need to check is_atapi_taskfile(&qc->tf) again.
- */
- 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) {
- /* check status of DMA engine */
- host_stat = ap->ops->bmdma_status(ap);
- VPRINTK("ata%u: host_stat 0x%X\n",
- ap->print_id, host_stat);
- /* if it's not our irq... */
- if (!(host_stat & ATA_DMA_INTR))
- goto idle_irq;
- /* before we do anything else, clear DMA-Start bit */
- ap->ops->bmdma_stop(qc);
- if (unlikely(host_stat & ATA_DMA_ERR)) {
- /* error when transferring data to/from memory */
- qc->err_mask |= AC_ERR_HOST_BUS;
- ap->hsm_task_state = HSM_ST_ERR;
- }
- }
- break;
- case HSM_ST:
- break;
- default:
- goto idle_irq;
- }
- /* check altstatus */
- status = ap->ops->sff_check_altstatus(ap);
- if (status & ATA_BUSY)
- goto busy_ata;
- /* check main status, clearing INTRQ */
- status = ap->ops->sff_check_status(ap);
- if (unlikely(status & ATA_BUSY))
- goto busy_ata;
- /* ack bmdma irq events */
- 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; /* irq handled */
- idle_irq:
- ap->stats.idle_irq++;
- #ifdef ATA_IRQ_TRAP
- if ((ap->stats.idle_irq % 1000) == 0) {
- ap->ops->irq_ack(ap, 0); /* debug trap */
- ata_port_warn(ap, "irq trap\n");
- return 1;
- }
- #endif
- return 0; /* irq not handled */
- }
- 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;
- /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */
- 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,
- },
- };
- /**
- * bfin_reset_controller - initialize BF54x ATAPI controller.
- */
- 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;
- /* Disable all ATAPI interrupts */
- ATAPI_SET_INT_MASK(base, 0);
- SSYNC();
- /* Assert the RESET signal 25us*/
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | DEV_RST);
- udelay(30);
- /* Negate the RESET signal for 2ms*/
- ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) & ~DEV_RST);
- msleep(2);
- /* Wait on Busy flag to clear */
- count = 10000000;
- do {
- status = read_atapi_register(base, ATA_REG_STATUS);
- } while (--count && (status & ATA_BUSY));
- /* Enable only ATAPI Device interrupt */
- ATAPI_SET_INT_MASK(base, 1);
- SSYNC();
- return (!count);
- }
- /**
- * atapi_io_port - define atapi peripheral port pins.
- */
- 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
- };
- /**
- * bfin_atapi_probe - attach a bfin atapi interface
- * @pdev: platform device
- *
- * Register a bfin atapi interface.
- *
- *
- * Platform devices are expected to contain 2 resources per port:
- *
- * - I/O Base (IORESOURCE_IO)
- * - IRQ (IORESOURCE_IRQ)
- *
- */
- 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 };
- /*
- * Simple resource validation ..
- */
- if (unlikely(pdev->num_resources != 2)) {
- dev_err(&pdev->dev, "invalid number of resources\n");
- return -EINVAL;
- }
- /*
- * Get the register base first
- */
- 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;
- }
- /*
- * Now that that's out of the way, wire up the port..
- */
- 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;
- }
- /**
- * bfin_atapi_remove - unplug a bfin atapi interface
- * @pdev: platform device
- *
- * A bfin atapi device has been unplugged. Perform the needed
- * cleanup. Also called on module unload for any active devices.
- */
- 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);
- /*
- * ATAPI mode:
- * pio/PIO
- * udma/UDMA (default)
- * mwdma/MWDMA
- */
- 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);
|