linux/drivers/spi/spi-s3c24xx.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006 Ben Dooks
   3 * Copyright 2006-2009 Simtec Electronics
   4 *      Ben Dooks <ben@simtec.co.uk>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10*/
  11
  12#include <linux/init.h>
  13#include <linux/spinlock.h>
  14#include <linux/workqueue.h>
  15#include <linux/interrupt.h>
  16#include <linux/delay.h>
  17#include <linux/errno.h>
  18#include <linux/err.h>
  19#include <linux/clk.h>
  20#include <linux/platform_device.h>
  21#include <linux/gpio.h>
  22#include <linux/io.h>
  23#include <linux/slab.h>
  24
  25#include <linux/spi/spi.h>
  26#include <linux/spi/spi_bitbang.h>
  27#include <linux/spi/s3c24xx.h>
  28#include <linux/module.h>
  29
  30#include <plat/regs-spi.h>
  31
  32#include <plat/fiq.h>
  33#include <asm/fiq.h>
  34
  35#include "spi-s3c24xx-fiq.h"
  36
  37/**
  38 * s3c24xx_spi_devstate - per device data
  39 * @hz: Last frequency calculated for @sppre field.
  40 * @mode: Last mode setting for the @spcon field.
  41 * @spcon: Value to write to the SPCON register.
  42 * @sppre: Value to write to the SPPRE register.
  43 */
  44struct s3c24xx_spi_devstate {
  45        unsigned int    hz;
  46        unsigned int    mode;
  47        u8              spcon;
  48        u8              sppre;
  49};
  50
  51enum spi_fiq_mode {
  52        FIQ_MODE_NONE   = 0,
  53        FIQ_MODE_TX     = 1,
  54        FIQ_MODE_RX     = 2,
  55        FIQ_MODE_TXRX   = 3,
  56};
  57
  58struct s3c24xx_spi {
  59        /* bitbang has to be first */
  60        struct spi_bitbang       bitbang;
  61        struct completion        done;
  62
  63        void __iomem            *regs;
  64        int                      irq;
  65        int                      len;
  66        int                      count;
  67
  68        struct fiq_handler       fiq_handler;
  69        enum spi_fiq_mode        fiq_mode;
  70        unsigned char            fiq_inuse;
  71        unsigned char            fiq_claimed;
  72
  73        void                    (*set_cs)(struct s3c2410_spi_info *spi,
  74                                          int cs, int pol);
  75
  76        /* data buffers */
  77        const unsigned char     *tx;
  78        unsigned char           *rx;
  79
  80        struct clk              *clk;
  81        struct resource         *ioarea;
  82        struct spi_master       *master;
  83        struct spi_device       *curdev;
  84        struct device           *dev;
  85        struct s3c2410_spi_info *pdata;
  86};
  87
  88
  89#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT)
  90#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP)
  91
  92static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev)
  93{
  94        return spi_master_get_devdata(sdev->master);
  95}
  96
  97static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol)
  98{
  99        gpio_set_value(spi->pin_cs, pol);
 100}
 101
 102static void s3c24xx_spi_chipsel(struct spi_device *spi, int value)
 103{
 104        struct s3c24xx_spi_devstate *cs = spi->controller_state;
 105        struct s3c24xx_spi *hw = to_hw(spi);
 106        unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0;
 107
 108        /* change the chipselect state and the state of the spi engine clock */
 109
 110        switch (value) {
 111        case BITBANG_CS_INACTIVE:
 112                hw->set_cs(hw->pdata, spi->chip_select, cspol^1);
 113                writeb(cs->spcon, hw->regs + S3C2410_SPCON);
 114                break;
 115
 116        case BITBANG_CS_ACTIVE:
 117                writeb(cs->spcon | S3C2410_SPCON_ENSCK,
 118                       hw->regs + S3C2410_SPCON);
 119                hw->set_cs(hw->pdata, spi->chip_select, cspol);
 120                break;
 121        }
 122}
 123
 124static int s3c24xx_spi_update_state(struct spi_device *spi,
 125                                    struct spi_transfer *t)
 126{
 127        struct s3c24xx_spi *hw = to_hw(spi);
 128        struct s3c24xx_spi_devstate *cs = spi->controller_state;
 129        unsigned int bpw;
 130        unsigned int hz;
 131        unsigned int div;
 132        unsigned long clk;
 133
 134        bpw = t ? t->bits_per_word : spi->bits_per_word;
 135        hz  = t ? t->speed_hz : spi->max_speed_hz;
 136
 137        if (!bpw)
 138                bpw = 8;
 139
 140        if (!hz)
 141                hz = spi->max_speed_hz;
 142
 143        if (bpw != 8) {
 144                dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
 145                return -EINVAL;
 146        }
 147
 148        if (spi->mode != cs->mode) {
 149                u8 spcon = SPCON_DEFAULT | S3C2410_SPCON_ENSCK;
 150
 151                if (spi->mode & SPI_CPHA)
 152                        spcon |= S3C2410_SPCON_CPHA_FMTB;
 153
 154                if (spi->mode & SPI_CPOL)
 155                        spcon |= S3C2410_SPCON_CPOL_HIGH;
 156
 157                cs->mode = spi->mode;
 158                cs->spcon = spcon;
 159        }
 160
 161        if (cs->hz != hz) {
 162                clk = clk_get_rate(hw->clk);
 163                div = DIV_ROUND_UP(clk, hz * 2) - 1;
 164
 165                if (div > 255)
 166                        div = 255;
 167
 168                dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n",
 169                        div, hz, clk / (2 * (div + 1)));
 170
 171                cs->hz = hz;
 172                cs->sppre = div;
 173        }
 174
 175        return 0;
 176}
 177
 178static int s3c24xx_spi_setupxfer(struct spi_device *spi,
 179                                 struct spi_transfer *t)
 180{
 181        struct s3c24xx_spi_devstate *cs = spi->controller_state;
 182        struct s3c24xx_spi *hw = to_hw(spi);
 183        int ret;
 184
 185        ret = s3c24xx_spi_update_state(spi, t);
 186        if (!ret)
 187                writeb(cs->sppre, hw->regs + S3C2410_SPPRE);
 188
 189        return ret;
 190}
 191
 192static int s3c24xx_spi_setup(struct spi_device *spi)
 193{
 194        struct s3c24xx_spi_devstate *cs = spi->controller_state;
 195        struct s3c24xx_spi *hw = to_hw(spi);
 196        int ret;
 197
 198        /* allocate settings on the first call */
 199        if (!cs) {
 200                cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL);
 201                if (!cs) {
 202                        dev_err(&spi->dev, "no memory for controller state\n");
 203                        return -ENOMEM;
 204                }
 205
 206                cs->spcon = SPCON_DEFAULT;
 207                cs->hz = -1;
 208                spi->controller_state = cs;
 209        }
 210
 211        /* initialise the state from the device */
 212        ret = s3c24xx_spi_update_state(spi, NULL);
 213        if (ret)
 214                return ret;
 215
 216        spin_lock(&hw->bitbang.lock);
 217        if (!hw->bitbang.busy) {
 218                hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE);
 219                /* need to ndelay for 0.5 clocktick ? */
 220        }
 221        spin_unlock(&hw->bitbang.lock);
 222
 223        return 0;
 224}
 225
 226static void s3c24xx_spi_cleanup(struct spi_device *spi)
 227{
 228        kfree(spi->controller_state);
 229}
 230
 231static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count)
 232{
 233        return hw->tx ? hw->tx[count] : 0;
 234}
 235
 236#ifdef CONFIG_SPI_S3C24XX_FIQ
 237/* Support for FIQ based pseudo-DMA to improve the transfer speed.
 238 *
 239 * This code uses the assembly helper in spi_s3c24xx_spi.S which is
 240 * used by the FIQ core to move data between main memory and the peripheral
 241 * block. Since this is code running on the processor, there is no problem
 242 * with cache coherency of the buffers, so we can use any buffer we like.
 243 */
 244
 245/**
 246 * struct spi_fiq_code - FIQ code and header
 247 * @length: The length of the code fragment, excluding this header.
 248 * @ack_offset: The offset from @data to the word to place the IRQ ACK bit at.
 249 * @data: The code itself to install as a FIQ handler.
 250 */
 251struct spi_fiq_code {
 252        u32     length;
 253        u32     ack_offset;
 254        u8      data[0];
 255};
 256
 257extern struct spi_fiq_code s3c24xx_spi_fiq_txrx;
 258extern struct spi_fiq_code s3c24xx_spi_fiq_tx;
 259extern struct spi_fiq_code s3c24xx_spi_fiq_rx;
 260
 261/**
 262 * ack_bit - turn IRQ into IRQ acknowledgement bit
 263 * @irq: The interrupt number
 264 *
 265 * Returns the bit to write to the interrupt acknowledge register.
 266 */
 267static inline u32 ack_bit(unsigned int irq)
 268{
 269        return 1 << (irq - IRQ_EINT0);
 270}
 271
 272/**
 273 * s3c24xx_spi_tryfiq - attempt to claim and setup FIQ for transfer
 274 * @hw: The hardware state.
 275 *
 276 * Claim the FIQ handler (only one can be active at any one time) and
 277 * then setup the correct transfer code for this transfer.
 278 *
 279 * This call updates all the necessary state information if successful,
 280 * so the caller does not need to do anything more than start the transfer
 281 * as normal, since the IRQ will have been re-routed to the FIQ handler.
 282*/
 283void s3c24xx_spi_tryfiq(struct s3c24xx_spi *hw)
 284{
 285        struct pt_regs regs;
 286        enum spi_fiq_mode mode;
 287        struct spi_fiq_code *code;
 288        int ret;
 289
 290        if (!hw->fiq_claimed) {
 291                /* try and claim fiq if we haven't got it, and if not
 292                 * then return and simply use another transfer method */
 293
 294                ret = claim_fiq(&hw->fiq_handler);
 295                if (ret)
 296                        return;
 297        }
 298
 299        if (hw->tx && !hw->rx)
 300                mode = FIQ_MODE_TX;
 301        else if (hw->rx && !hw->tx)
 302                mode = FIQ_MODE_RX;
 303        else
 304                mode = FIQ_MODE_TXRX;
 305
 306        regs.uregs[fiq_rspi] = (long)hw->regs;
 307        regs.uregs[fiq_rrx]  = (long)hw->rx;
 308        regs.uregs[fiq_rtx]  = (long)hw->tx + 1;
 309        regs.uregs[fiq_rcount] = hw->len - 1;
 310        regs.uregs[fiq_rirq] = (long)S3C24XX_VA_IRQ;
 311
 312        set_fiq_regs(&regs);
 313
 314        if (hw->fiq_mode != mode) {
 315                u32 *ack_ptr;
 316
 317                hw->fiq_mode = mode;
 318
 319                switch (mode) {
 320                case FIQ_MODE_TX:
 321                        code = &s3c24xx_spi_fiq_tx;
 322                        break;
 32C323" id="L3ef="d44
        return 0;
 321                        spi_fiq_code  224}
 322ptr" clas name="L225"> 225
mof="d44
spi)
 321                        spi_fiq_code  227{
 322ss="line"ontroller_state);
 229}
 321" id="L321" clae_state( 322 230
count)
 232{
( 321set_fiq_regs(&count] : 0;
 234}
 321dev_err         321dev_err<>        u8       235
 315                " id="L321" cla">inline  317     "+code=ack_bit" class="srelass="sref">u8      

(&(&312         321dev_err         321dev_err<>        u8       *

spi_fiqme="L3de" class="sref">spi_fiqme="L332" cx.c#L317" id="L317" class="line" name="L317"> 317     "+code=ack_bit" class="srs3c24xx_spi_updateru"line" name="L32eru"" clelass="sref">u8      
 317                hw->fiq_mode =  */
 317         inus    hw-> 244
/**

 2723, excludi3g this header.
spi_fiq_code 2723,ss="line"RQ ACK bit at.
 2723nstall as3a FIQ handler.
 */
spi_fiq_code {
 24as normal, since the IRQ will have been re-r3suse any 3ss="sref">length;
 2723npan clas3sref">ack_offset;
 nal"line" name="L274"> 274 *3data" cla3s="sref">data[0];
 255};
spi_fiq_code 315    p17" class="line"p_spi" class="sref">s3c24xxs=le.c#=set_fiq_regs" clle.c#" cle       * then return and simply use a3se - FIQ 3 name="L256"> 256
s3c34xx_spi_fiq_txrx;
 195        struct s3c2p17" class="line"p_spi" class="sref">hw->s3c24xx_spi_fiq_tx;
tx[s3c24xx_spi_fiq_rx;
 260
                switch (/**
s3c24xxs"L262"> 232 * 36quot;no memory for controllercode="sref">s3c24xx_spi_fiq_tx;
);
BUSYx_spi_fiq_txs3c3" class=3line" name="L263"> 263(&countBITBANG_CS_INACTIVE
data[0];
 * Returns th3 bit 3o write to the interrupt ackn 

<4xx.c#L2la3s="sref">data[0];
ack_bi3(36ng.busy) {
 31/spi/spi-NONEa3href=32rivers/spi/spi-NONEa href="+code=s3c24xx_spi" class="sref">s3c3p17" clasa href="drivers/spi/spi-33c24x36_CS_INACTIVE" class="sbusy" class="sref">busy) {
irq<3a> - 37ent">/* need tQ_MODErs/spi/spx.c#L295" id="L295" cle.c#=setT0);
3a href="drivers/spi/spi-33c24x37="+code=fiq_claimed" cbusy" class="sref">busy) {
 317         inus    }3pi-s3c24x3.c#L272" id="L272" class3"line37a>(&rpan class3"comment"> * s3c24xx_spi3tryfi37de = ret)
 2743/a>->spi-s3c243x.c#L275" id="L275" clas3="lin37id="L209" class="lin3iss="line3="comment">/n class="3omment"> * Claim the FIQ3handl3r (only one can be active atIQ 3ode and header
 * th3n set3p the correct transfer code foi3g this headL210
 278
 * This call updat3s all3the necessary state informatioa href="drivers/spi/spi-s3c24xx.c#L274" id="3c0);
3t"> * so the caller does3not n3ed to do anything more than staStime) andspi/spi-s3cd the i-s3cing3c24xx.c#L28/spa * as normal, since3the I3Q will have been re-routed t2la3s="sref">data[0];
 266 */
 282 283void s3c24xx_spi_tryfiq(struct s3324xx_spi *busy) {
ret =  31ref">busy) {
p38.c#L305" id="L305" class="liref">busy) {
ret =  31ers/lassa> = spi_fiqme="L3                  3pi_fi38->busy) {
ret =  31ame="L255"> 255};
s3i_fiq3code="L288" c3ass="line" name="L288"> 388
hw->3/* t3y and3claim fiq if we haven't glaIQ for transfer
                 * 3hen r39 will have been re-r3suse anya href="drivers/spi/spi-s3c24xx.c#L274" id="3lref="+co3 2723npan classs="co   "+eivers/splatspi-ef="drspecifiesref">lengs/spic=clnel9" id="L239" class="line" name="L239"> 239<3="+code=h3" class="sref">hw-&g3; 264 295 3     39 write to the interrupt acknowledge register.
 266 */
 */ 283void s3c24xx_spi_tryfiq(struct busy) {
IRQ_EI4"+code=mo4e" class="sref">mode4= S3C24XX_V4&&4 ! 271
mode4=  2725rive 271
mode = <4 href40n class="comment"> * @hw: The hardware state.
 275leng succ=clnel9" s
;4<.c#L296" id="L296" clas4ref">40 (only one can be active at anef">leng suc#L28" s
ss="li)
4w-"L266"> 266 */
 */ 283void  ass="sref">s3c24xx_spi_cleanup(struct ] = hw4/a>-&gd int 4iq_rirq] = (long) ass="srivers/spi/spi-s3c24x(vknus    IRQ_EI4=set_fiq_4egs" class="sref">set_fi4_regs4/a>(&a#_MODE_RX" class="sref">FIQ_MODE_RX;
<4egs);4count4ef="+code4fiq_mode" class="sref">f4q_mod4 !"L266"> 266 */
 282 283void  311
 266 */
 282*/
 283void  311
;4 266 */
 */ 283void  311
;4de=fiq_mode" class="sref4>fiq_4ode 266 */
 */ 283void  311
 319         4     4switch#endivesref">BITBANG_CS_INACTIVEivers/spi/spi-s3c24xx.fowledge register.
 420                ca4e S3C24XX_V4"sref">co4e = & "line" name="L321"> 321            x24xx.c#L283" id="L283"    devic    ass="s,href="+code=mode" class="sr<4xx.c#L   42C323" id="L3ef="d44
s3c34xx_spi_fiq_txrx;
 195line" name="L283"> ass="srack_bit" class="srs3c24xx_spi_updateru4sref">spi4fiq_code FIQ_MODE4/spi-s3c24xx.c#L155" id="L322" cla4s="li42.c#L305" id="L305" class="liref">busy) {
uregs[ 195)
uregs[mof="d44
->busy) {
 195)
uregs[hw->regs.uregs[ 195)
uregs[regs. 309    a href="+ref=35rivers/spi/spi-s3c24xx.c#L288" id="L4rs/spi/sp4-s3c24xdefaultf="d44
[s3c24xx_spi_f4tate(4a href="+code="L322" cla4s="li43.c#L260" id="L260" c3emory aL210__CSple3c24comment"> */ 294                 */4ount)4
 4="L321"> 321set_fi4_regs43.c#L313" id="L313" class="line" rivers/spi/suse};
 195)
uregs[] : 0;4*/
u84code=ack_4it" class="srelass="sref4>u8->BITBANG_CS_INACTIVEse24xx.c first bytefowledge register.
hw->
regs.uregs[[ */ 294                 */regs. 309    a href="+ack_bit" class="srs3c24xx_spi_updateru4i33rivers4="L32eru"" clelass="sref4>u8IRQ_EI4em4(&4 href="+c4de=fiq_mode" class="sref4>fiq_4ode 266 309    lrq268" c_0a href="drivers/spi/rivers/spi/s32" cx.c#L317" id=rivers/spi/s32"/spi-=inline" class="sref">inline 4 a>] : 0;4hinus lass="s" class="sr4f">hw4/a>-&gd int 
4a3href=3driveri-s3c24xx.4#L20944.c#L305" id="227" cl3sref">s3c34xx_spi_fiq_txrx;
 195<                   195uregs[[-> 309    a href="+refref="+code=regsref">regs. 309    a href="+ack_bit" class="srs3c24xx_spi_updateru4i (long)<480" baitbad="L272" class4"line44       int  195BITBANG227ing">""lin-collisc24\n"ledge rrack_bit" class="srs3c24xx_spi_updateru4spi-s3c244x.c#L281as normal, since4the I45">hw-> */ 294                 */ 24as normal, since4the I45quot;no memory for cogotoline" class="sref">_do="comment"> */_do="f="+ack_bit" class="srs3c24xx_spi_updateru4="commn" 4lass ou;31d="L272" class4"line45.c#L313" id="="+code=IRQ_EINT0" class="sref">IRQ_EI474"65"> n4l"line" name="L274"> 2744/a>FIQ_MODE4pi-s3c24x4.c#L275               * 4hen r456c#L289" id="L289!9ine" class="sresps     195BITBANG227ing">"et"pan>
readyxrs/spx?\n"ledge rrack_bit" class="srs3c24xx_spi_updateru4s_FIQ4a3href=35rivers/spi/spi-43c24x45ng. */ 294                 */hw45_CS_INACTIVE" class="gotoline" class="sref">_do="comment"> */_do="f="+ack_bit" class="srs3c24xx_spi_updateru488" class4"line" nam cl class="sre4">tx<460c#L313" id="="+code=IRQ_EINT0" class="sref">IRQ_EI4q_rx;4S3C24XX_V4_fiq_regs4 clle.c#" clea>         4     4switch (};
 242 * 46quot;no memory for coref="+code=regsref">regs. 309    a href="+++ack_bit" class="srs3c24xx_spi_updateru48"commn" 4line" name="L263"> 263(&count4spi-s3c244x.c#L264" id="L264" clas4="lin46.c#L244" id="L244" c3_TX" class="sref">FIQ_MODE_TX;
4span clas4="comment"> * Returns th4 bit 46       if (FIQ_MODE_TX;
 321 309    a href="+code=regs" class="sreadbx_spi_tryfiq" creadbi-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="sref">uregs[[ack_bi4(46ng. 309    a href="+++ack_bit" class="srs3c24xx_spi_updateru48 (long)<4a href="drivers/spi/spi-43c24x46       int irq<4a> - 47x.c#L149" id="L149" c_TX" class="sref">F="L309"> 309    a href="+r<neme="L195"> 195regs.uregs[4T0);
4a href="drivers/spi/spi-43c24x47="+code=fiq_claimed" f="+code=busy" class="san>

F="L309"> 309    a href="+)class="line" namef">regs.uregs[[hw->FIQ_MODE_RX;
<4pi-s3c24x4.c#L272" id="L272" class4"line47quot;no memory for controllercode="sref">s3c_CSple3"comment"> */ 294                 */ * s3c24xx_spi4tryfi47de =  2744/a>regs. 309    a href="+refme="L195"> 195regs.uregs[
 * Claim the FIQ4handl47       * th4n set47ng.FIQ_MODE_TX;
42p17" cla4x.c#L278" id="L278" clas4="lin47_CS_INACTIVE" class=" href="+L222" c3 use any 3uffer we like.
 321regs.uregs[uregs[[ * This call updat4s all48>[s3c24xx_spi_f4c0);
4t"> * so the caller does4not n48="+code=fiq_claimed" cbusy" class="s_CSple3"comment"> */ 294                 */ * as normal, since4the I48witch (4href="+co4e=s3c24xx_spi" class="sr4f">s3424xx_sline" class="sref">_do="comment"> */_do="f="+ne"ontroller_state);
hw)
4a href="drivers/spi/spi-43c24x4.c#L284" id="L268" clref="+code=regsIRQ_HANDLEDcomment"> */p48.c#L3t;4pi_fi48      s4i_fiq48de="L282"> 282 283void s3c24xx_spi_tryfiq(struct  488ret;4BITBANG_CS_INACTIVErs/spichmo_INA, permanhref=3enablx.c#L2cthe iowledge register.
hw->4S3C24XX_V4        <4pan class="comment">/* t4y and49.c#L311" id="L311" class="liclk_enablxcomment"> */ */                 * 4hen r49a>(&4lref="+co4BITBANG_CS_INACTIVEprograma>ss="lise=in24xx.ct at.
)
4" class="sref">hw-&g4;FIQ_MODE4l  295 4     49.c#L305" id="L305" class="lian>

regs.uregs[[

[Ff">regs.uregs[ 232{
hw->
[Ff">regs.uregs[ 232{
busy) {
mode5= busy) {
 311
 31ame="L255"> gpiocl11"> 311
 gpioclss="sref">s3c24xx_spi_tryfiq(struct name="L317"> 31gpio_direc3c24_outpu09"> 309    gpio_direc3c24_outpu0i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="srp       311
mode5= (&5"4code=mo5ea href="drivers/spi/spi503" i50x.c#L149" id="L149" cL289ine" class="sreref">busy) {
s3c24xx_spi_tryfiq(struct hw-&g5 href504xx_spi_fiq_rx" clas3ss="lineine" class="sreref">busy) {
busy) {
 295 5s3c2450.c#L305" id="t;;5<.c#L296" id="L296" clas5ref">50 (onlt;;5;55w-"L266">ly use a3s="line" 3ame="L255"> prob    prob /spi-24xx.c#L283" id="L283"platspi-_devic   5a>] = hw5/a>-&gd int 5iq_rirq] = (long) 283void set_fi5_regs513#L268" id="L24xx.c#L283" id="L283" i/sma. i/sma.ma.s3c34xx_resourc   f5q_mod514xx_spi_fiq_rly use a3s="line" 3erse" name="L283">ersine" na=35rivers/spi/spi-s3c24xx.c#L288" id="L5   5 7RX;5ma. 31ai/sallocsma. i/sallocsma. 294p                  p 283void hw->L289ine" class="srema.ma. 31NUL" id="L321" clasNUL"e" nver  int  294p                  pBITBANG227ing">"No memoryxrs/s i/sma. 319         5     52x.c#L149" id="L149" cse a3s="line" 3erse" name="L283">ersine" nan");
NOMEMe" name="L283">
NOMEMd  520                ca5e ers_nomemd 53c2323"> 52C323" id="L3ef="d44
 31ai/sma.ma.busy) {
 283void 5de=mode" 5lass="sref">mof="d44
->busy) {
ma. 31ai/sma.ma.hw->regs. 195 195->regs. 294p                  p[s3c24xx_spi_f5tate(5a href="+code="L322" cla5s="li53.c#L260" id="L289ine" class="sre/       31NUL" id="L321" clasNUL"e" nver  int hw-> 294p                  pBITBANG227ing">"No platspi-ef="drsupplied\n"ledge rrack_bit" class="srs3c24xx_spi_updateru5ount)5ersine" nan");
NOENTuregs[ 5="L321"> 321set_fi5_regs53x.c#L149" id="L149" cgotoline" class="sreers_no_/      u85code=ack_5it" class="srelass="sref5>u8->Ff">regs.hw-> */ 294                 */BITBANG_CS_INACTIVEL210ialisndspi spi-s3cdowledge register.
S3C24XX_V5i33rivers5="L32eru"" clelass="sref5>u8};
Ff">regs.5 href="+c5de=fiq_mode" class="sref5>fiq_544>->BITBANG_CS_INACTIVE time) andma.

hw54+code=FIQ_MODE_TXRX" class="sref">FIQ_MODE5 244
5a3href=3driveri-s3c24xx.5#L20954.c#L305" id="fref">BITBANG_CS_INACTIVE and"sre"+coass= bits und" ctood bygs/spiTXRX" :dowledge register.
ma.mpi-_bitse" n name="L195"> 195 195[ 195[->ma. 195busy) {
num_cshrefack_bit" class="srs3c24xx_spi_updateru5d" id="t254" &31d="L272" class5"line55a>->ma.bus_nume" n name="L195"> 195bus_nume" nack_bit" class="srs3c24xx_spi_updateru5ds5"s=id=" as normal, since5the I55ode=S3C24XX_VA_IRQ" class="sref">S3C24XX_V5spi-s3c245x.c#L281as normal, since5the I55">hw->fref">BITBANG_CS_INACTIVE time) andpan>
Ers/spichbitbangiTXRX" dowledge register.
 24as normal, since5the I55a>(&5="commn" 5lass ou;31d="L272" class5"line55x.c#L149" id=ref="+code=s3c24xx_spi_tryfiq" class="f="drivers/spi/spi-sbitbange" name="L283">bitbanghref href="drivers/sma.ma. 195busy) {
ma. n5l"line" name="L274"> 2745/a>busy) {
bitbanghref href="drivers/s timer<4xx.c#L   31aivers/spi/s timexc#L  busy) {
bitbanghref href="drivers/schipselect   195< ivers/spi/schipsel  ->busy) {
bitbanghref href="drivers/s    _bufse" name="L283">    _bufs/a>-> 195< ivers/spi/s"line" name="L321"> 321            ack_bit" class="srs3c24xx_spi_updateru57_FIQ5a3href=35rivers/spi/spi-53c24x55 the ;hw55->regs.ma. 195< ivers/spi/s  tu/a>};
tx<56a>->regs.ma. 31aivers/spi/scleanu/a>};
S3C24XX_V5_fiq_regs5 clle.c#" clea>         5     56.c#L311" id="L311" class="liers/dbg               BITBANG227ing">"bitbangiat %p\n"ledge r,aname="L294"> 294ref">busy) {
bitbanghrefrack_bit" class="srs3c24xx_spi_updateru5"L262"> 252 * 56a>(&58"commn" 5line" name="L263"> 263->BITBANG_CS_INACTIVEfind and map our resourc siowledge register.
FIQ_MODE5span clas5="comment"> * Returns th5 bit 56.c#L305" id="L305" class="lires   195FIORESOURCE_MEMe" name="L283">IORESOURCE_MEM hre, 0rack_bit" class="srs3c24xx_spi_updateru5"ode=ack_5.c#L266" id="L266" class5"line56-> 31NUL" id="L321" clasNUL"e" nver  int ack_bi5(56ng. 294p                  pBITBANG227ing">"Canan>
get IORESOURCE_MEM\n"ledge rrack_bit" class="srs3c24xx_spi_updateru58 (long)<5a href="drivers/spi/spi-53c24x56_CS_INACTIVE" class="sbusy" class="serse" name="L283">ersine" nan");
NOENTuregs[irq<5a> - 57x.c#L149" id="L149" cgotoline" class="sreers_no_iores  }55pi-s3c24x5.c#L272" id="L272" class5"line57.c#L222" id="L222" c3 use any 3uffer we like.
 195 */Fresourc _size  5p"commn" 5"comment"> * s3c24xx_spi5tryfi57x.c#L149" id="L149" ccccccccccccccccccccccccc"L294"> 294p                  pnxx_hrefrack_bit" class="srs3c24xx_spi_updateru5274" clas5="line" name="L274"> 2745/a>FIQ_MODE5ppan clas5x.c#L275" id="L275" clas5="lin576c#L289" id="L289L222" c3 use any 3uffer we like.
 31NUL" id="L321" clasNUL"e" nver  int  * Claim the FIQ5handl57.c#L316" id="L316" class="line" nameers/erse" name="L283"> 294p                  pBITBANG227ing">"Canan>
reserv.ct at24\n"ledge rrack_bit" class="srs3c24xx_spi_updateru5277 * th5n set57ng.ersine" nan");
NXIOuregs[ * This call updat5s all580c#L313" id="="+code=IRQ_EINT0" class="sref">IRQ_EI5c0);
5t"> * so the caller does5not n58ode=S3C24XX_VA_IRQ" class="sref">S3C24XX_V5c270}5ent"> * as normal, since5the I58.c#L311" id="L311" class="lif">regs.uregs[ 31ioremap  Fresourc _size  
uregs[ 31NUL" id="L321" clasNUL"e" nver  int s358x.c#L149" id="L149" cass="line" nameers/erse" name="L283"> 294p                  pBITBANG227ing">"Canan>
map IO\n"ledge rrack_bit" class="srs3c24xx_spi_updateru5>hw)
5a href="drivers/spi/spi-53c24x58.c#L244" id="L244" c3ss="line"3name=erse" name="L283">ersine" nan");
NXIOuregs[p58       if (5pi_fi587c#L313" id="="+code=IRQ_EINT0" class="sref">IRQ_EI5c77s5i_fiq58 the ; 588->regs.inline  195inline ss="9ine" class="srep                  pbusy) {
inline hw->5 294p                  pBITBANG227ing">"No IRQ specified\n"ledge rrack_bit" class="srs3c24xx_spi_updateru5        <5pan class="comment">/* t5y and59">hw->ersine" nan");
NOENTuregs[                 * 5hen r59quot;no memory for cogotoline" class="sreers_no_i">inline hrefack_bit" class="srs3c24xx_spi_updateru5lref="+co5IRQ_EI5"hw)
5" class="sref">hw-&g5;FIQ_MODE5l  295 5     59.c#L305" id="L305" class="lierse" name="L283">ersine" name="L195"> 195inline i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="srf">inline  31aivers/spi/s32" cx.c#L317" id=rivers/spi/s32"/spi, 0,h"L294"> 294p                  pnxx_href,  class="sref">Ff">regs.ersine"ver  int . 294p                  pBITBANG227ing">"Canan>
BITim IRQ\n"ledge rrack_bit" class="srs3c24xx_spi_updateru5 "L288" c5inline hrefack_bit" class="srs3c24xx_spi_updateru6&&6 !IRQ_EI6"+code=mo6e" class="sref">mode6= S3C24XX_V6&&6 !regs. */ 195<_lk_get   294p                  pBITBANG227ing">"sre"ledge rrack_bit" class="srs3c24xx_spi_updateru6"+code=mo6e" class="sref">mode6= IS_ERRi-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="sr_lkcomment"> */ 294p                  pBITBANG227ing">"No cthe irs/sdevic \n"ledge rrack_bit" class="srs3c24xx_spi_updateru6&5code=mo6e class="sref">hw-&g6 href604xx_spi_fiq_rx" clas3L305" class="lierse" name="L283">ersine" name="L195"> 195PTR_ERRi-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="sr_lkcomment"> */ 295 6s3c2460       if ( */607c#L313" id="="+code=IRQ_EINT0" class="sref">IRQ_EI6T8RX;6;660->BITBANG_CS_INACTIVE time)any gpio we cf">owledge register.
hw61>[s3c24xx_spi_f6s="sref">6iq_rirq] = (long) 311
hw-> 311
set_fi6_regs61quot;no memory for co"L149" c=busy" class="s 294p                  pBITBANG227ing">"No chipselect pin\n"ledge rrack_bit" class="srs3c24xx_spi_updateru6_4code=mo6ersine" nan");
INVA" id="L321" clas
INVA"hrefack_bit" class="srs3c24xx_spi_updateru6_5code=mo6fiq_mode" class="sref">f6q_mod614xx_spi_fiq_rx" clas3ss="linegotoline" class="sreers_t at. */IRQ_EI6 7RX;6;6de=fiq_mode" class="sref6>fiq_61ng.ersine" nasbusy" class="sgpio_requeste" name="L283">gpio_requestss="9ine" class="srep       311
 294p                  persine"ver  int  319         6     62x.c#L149" id="L149" c"L149" c=busy" class="s 294p                  pBITBANG227ing">"Failed tolget gpio rs/scs\n"ledge rrack_bit" class="srs3c24xx_spi_updateru6="L320"> 620                ca6e  */hw->IRQ_EI6/spi-s3c26xx.c#L322" id="L322" cla6s="li62a>(&63c2323"> 62C323" id="L3ef="d44
busy) {
 311
 31ame="L255"> gpiocl11"> 311
 gpioclss="ack_bit" class="srs3c24xx_spi_updateru6=5code=mo6fiq_code  309    gpio_direc3c24_outpu0i-s3cref="+code=s3c2p       311
FIQ_MODE_RX;
<6de=mode" 6lass="sref">mof="d44
busy) {
 311
 31/       311
};
Ff">regs.[s3c24xx_spi_f6tate(6a href="+code="L322" cla6s="li63.c#L260" id="rref">BITBANG_CS_INACTIVEt at.s controls3cdowledge register.
6ount)6ersine" nasbusy" class="spi/sbitbang_ tart   294ref">busy) {
bitbanghrefrack_bit" class="srs3c24xx_spi_updateru6rc2323"> 6="L321"> 321set_fi6_regs63x.c#L149" id=L289ine" class="sreerse" name="L283">ersine"ver  int  294p                  pBITBANG227ing">"Failed tolt at.u8 */u8IRQ_EI6o8RX;6s3c24xx_spi_f6is6 */);
busy) {
 311
 31ame="L255"> gpiocl11"> 311
 gpioclss="sref">s3c24xx_spi_tryfiq(struct 6gpio_fre_i-s3cref="+code=s3c2p       311
hw64c#L284" id="Lcbusy" class="s_lk_disablxcomment"> */ */ 309    _lk_pu0i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="sr_lkcomment"> */6.c#L272" id="L272" class6"line64 the line" class="sreers_no__lkcomment"> */);
->inline i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="srf">inline  31f">regs.[s3c24xx_spi_f6ass="sref6"s=id=" as normal, since61s_lks="srack_bit" class="srack_s"line" name="L3        "2" class6"line64->0lin59_V5spi-s365p6 !inline i-s3cref="+code=s3c24xx_spi_twe like.
 31f">regs. 24as normal, since5the I55a>(&6a href="+6ode=regs" class="sref">56"comm65o4e=s3c24xx_spi" clasif ("2t" class="srs3c24xx_spi_updateru564"65"6 n5l"line" name="L274"> 2745/released  195inline i-s3cref="+code=s3c24xx_spi_tre like.
 31f">regs.i-s3cref="+code=s3c24xx_spi_tre like.
 31f">regs.6.c#L272" id="L272" class6"class="gotoline" class="sreers_no_io"line" name="L3        "2roller_steass="line3 name="L244"56 (lon6)<5s="l272" id="L272" class6"L149" cgotoline" class="sreers_no_/ "line" name="L3        "it" class6"srs3c24xx_spi_updateru568" cl6ss5"line" nam cl class="sre5"s> 31ai/sma64.c#L305" id="L30s> 31ai/sma64.sgpio_fre_e" name="L> i-s3cref="+code=s3c24xx_spi_tai/sma.ma.5S3C24XX_V56fiq_r6gs5 cll272" id="L272" class6laimed" gotoline" class="sreers"line" name="L3        "is3c24xx_s"srs3c24xx_spi_updateru56L262"66>6set_fi6_regs63x.c#L149" id=L289ine" crema.ma.56"comm6" 5linsrelass="sref6>u8
FIQ_MODE56pan c6as5="chref="drivers/spi/spi5ref">5w-"L26removmory for coref=">5w-"L26removmsgpioa href="+cod me="L255"> prob /spi-24xx.c#L283" id="L283"platspi-_devic   ersine"ver  int  283void inline ma.->ma.5 294ref">busy) {
bitbanghrefrack_b class="l6n3=count" c3ass="sref">56i-s3c67n5"las> 24as normal, since5the I55a>(&6 class="l6n3=count" c3ass="sref">56"comm67 5lass ou;31d="L272" class5"">hw64c#L284" id="Lcbusy" class="s_lk_disablxcomment"> */ */hw64.c#L305" id="L305" class="li_lk_pu09"> 309    _lk_pu0i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="sr_lkcomment"> */FIQ_MODE56pan c67252" class="sreclass="sref5>u8 * ="L272" class6"line64->inline i-s3cref="+code=s3c24xx_spi_tryfiq" class="ode=uregs" class="srf">inline  31f">regs.inline i-s3cref="+code=s3c24xx_spi_twe like.
 31f">regs.busy) {
 311
 31ame="L255"> gpiocl11"> 311
 gpioclss="sref"de=IRQ_EI6T0" class="sref">IRQ_EI56068w5 class="sref">hw->5 195busy) {
 311
S3C24XX_V56270 195inline i-s3cref="+code=s3c24xx_spi_tre like.
 31f">regs.i-s3cref="+code=s3c24xx_spi_tre like.
 31f">regs. 31ai/sma64.c#L305" id="L30s> 31ai/sma64.sgpio_fre_e" name="L> i-s3cref="+code=s3c24xx_spi_tai/sma.ma.IRQ_EI5677u8u8[[5w-"L26suspend name="L317"> 31ame="L255">suspendsgpioa href="+cod me="L255"pi-24xx.c#L283" id="Lpi-_devic   ersine"ver  inde=IRQ_EI6T0" class="sref">IRQ_EI56hw 283void inline  prob /spi-24xx.c#L283" id="Lto_> prob /spi-24x ma.FIQ_MODE56 u8hw->regs. 195busy) {
 195busy) {
hw->regs.hw64c#L284" id="Lcbusy" class="s_lk_disablxcomment"> */ */IRQ_EI67+code70w5 class="sreclelass="sref6>u8->S3C24XX_V67amp;&7mp6 !u8 24as normal, since5the I55a>(&7t 5w-"L26resuapin/clss=", =bus>5w-"L26resuapsgpioa href="+cod me="L255"pi-24xx.c#L283" id="Lpi-_devic   ersine"ver  i7it" class7"srs3c24xx_spi_updateru676code7mo6e" name="L2ivers/spi/spi5s3c24512#L268" id="L24xx.c#L283" id="L283" class="line" name="L283"> 283void inline  prob /spi-24xx.c#L283" id="Lto_> prob /spi-24x ma.IRQ_EI678RX->};
Ff">regs.
u8s3c24xx_spi_f67="sre71>5ersine"ver  i7t  31uspendsgpi" class=i-s  tu/a>};
 31ame="L255">suspendsgpiass="sreres  };
u8->u8IRQ_EI677RX;6[ PMOPSin/clss=", =busa3C24XX_5"> PMOPS" claa hre272" id="L272" s/spi/sL210ipmopp"line" nf="drivs/spi/sL210ipmoppref=class="sreclass="sref5>u8;6de=#="L322" cla6s="li62.c#L305" id="t=_MODE_R7it" class7"srs3c24xx_spi_updateru67 (lon7)<6[ PMOPSin/clss=", =busa3C24XX_5"> PMOPS" claaef="+cs=platsp>[s controls3cdowledge regi7it" class7"srs3c24xx_spi_updateru67"L32072>5;6e prob /:456od10-shref,hrref">BITBANG227ing">"sre"ledge rrack_7de=IRQ_EI7T0" class="sref">IRQ_EI67spi-s72m5enthref="da href="+cod me="L255"> prob /spquot;ef="+code=regsplatspi-_ pquot;5 cll272" id="L272" s/spi/sL210ipquot;ef="+code=regsps/spi/sL210ipquot;ref=" css="sreerse" name="L283">ersine"ver  i7a href="+7ode=regs" class="sref">67c232372o6};
ersine"ver  i7ae=IRQ_EI7ref">FIQ_MODE_RX;
<67e=mod7" 6lass="sref">mof="d4sbitbange" name=
BITass="sreres  };
};
 PMOPSin/clss=", =busa3C24XX_5"> PMOPS" class="sreres  s3c24xx_spi_f67ate(6a h}"sref6>u8->
 prob /spquot;ef="+code=regspmodule_> prob /spquot;"sre"ledge rrack_7 class="l7n3=count" c3ass="sref">67unt 24as normal, since5the I55a>(&7it" class7"srs3c24xx_spi_updateru67c23237> 6="Laef="+cs=platspMODULE_DESCRIPTIONin/clss=", =busMODULE_DESCRIPTIONBITBANG227ing">"sre"ledge rrack_7t ersine" name=MODULE_AUTHO3BITBANG227ing">"sre"ledge rrack_7tt" class7"srs3c24xx_spi_updateru67spi-s7c262" aef="+cs=platspMODULE_LICENSEef="+code=regspMODULE_LICENSEBITBANG227ing">"sre"ledge rrack_7te=IRQ_EI7"srs3c24xx_spi_updateru67ode=a7k_6it"


The original LXR software by thfsCPHAuregshttp://a nameob ge.net/projects/lxa.>LXR 6s="unity" clssthis experi"li6al ot;sion by CPHAuregsmailto:lxa@spiux.no">lxa@spiux.no" cl.
lxa.spiux.no kindly hosted by CPHAuregshttp://www.redpill-spipro.no">Redpill Lpipro ASiCS_Isince 1995.