LCOV - code coverage report
Current view: top level - lkbce/drivers/mmc/core - sdio_io.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 24 235 10.2 %
Date: 2017-01-25 Functions: 3 20 15.0 %

          Line data    Source code
       1             : /*
       2             :  *  linux/drivers/mmc/core/sdio_io.c
       3             :  *
       4             :  *  Copyright 2007-2008 Pierre Ossman
       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 as published by
       8             :  * the Free Software Foundation; either version 2 of the License, or (at
       9             :  * your option) any later version.
      10             :  */
      11             : 
      12             : #include <linux/mmc/host.h>
      13             : #include <linux/mmc/card.h>
      14             : #include <linux/mmc/sdio.h>
      15             : #include <linux/mmc/sdio_func.h>
      16             : 
      17             : #include "sdio_ops.h"
      18             : 
      19             : /**
      20             :  *      sdio_claim_host - exclusively claim a bus for a certain SDIO function
      21             :  *      @func: SDIO function that will be accessed
      22             :  *
      23             :  *      Claim a bus for a set of operations. The SDIO function given
      24             :  *      is used to figure out which bus is relevant.
      25             :  */
      26             : void sdio_claim_host(struct sdio_func *func)
      27             : {
      28         168 :         BUG_ON(!func);
      29         192 :         BUG_ON(!func->card);
      30             : 
      31          48 :         mmc_claim_host(func->card->host);
      32          24 : }
      33             : EXPORT_SYMBOL_GPL(sdio_claim_host);
      34             : 
      35             : /**
      36             :  *      sdio_release_host - release a bus for a certain SDIO function
      37             :  *      @func: SDIO function that was accessed
      38             :  *
      39             :  *      Release a bus, allowing others to claim the bus for their
      40             :  *      operations.
      41             :  */
      42             : void sdio_release_host(struct sdio_func *func)
      43             : {
      44         168 :         BUG_ON(!func);
      45         192 :         BUG_ON(!func->card);
      46             : 
      47          48 :         mmc_release_host(func->card->host);
      48          24 : }
      49             : EXPORT_SYMBOL_GPL(sdio_release_host);
      50             : 
      51             : /**
      52             :  *      sdio_enable_func - enables a SDIO function for usage
      53             :  *      @func: SDIO function to enable
      54             :  *
      55             :  *      Powers up and activates a SDIO function so that register
      56             :  *      access is possible.
      57             :  */
      58             : int sdio_enable_func(struct sdio_func *func)
      59             : {
      60           0 :         int ret;
      61           0 :         unsigned char reg;
      62           0 :         unsigned long timeout;
      63           0 : 
      64           0 :         BUG_ON(!func);
      65           0 :         BUG_ON(!func->card);
      66           0 : 
      67           0 :         pr_debug("SDIO: Enabling device %s...\n", sdio_func_id(func));
      68           0 : 
      69           0 :         ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, &reg);
      70           0 :         if (ret)
      71           0 :                 goto err;
      72             : 
      73           0 :         reg |= 1 << func->num;
      74             : 
      75           0 :         ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
      76           0 :         if (ret)
      77           0 :                 goto err;
      78             : 
      79           0 :         timeout = jiffies + msecs_to_jiffies(func->enable_timeout);
      80             : 
      81           0 :         while (1) {
      82           0 :                 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IORx, 0, &reg);
      83           0 :                 if (ret)
      84           0 :                         goto err;
      85           0 :                 if (reg & (1 << func->num))
      86           0 :                         break;
      87           0 :                 ret = -ETIME;
      88           0 :                 if (time_after(jiffies, timeout))
      89           0 :                         goto err;
      90           0 :         }
      91           0 : 
      92           0 :         pr_debug("SDIO: Enabled device %s\n", sdio_func_id(func));
      93             : 
      94           0 :         return 0;
      95           0 : 
      96             : err:
      97           0 :         pr_debug("SDIO: Failed to enable device %s\n", sdio_func_id(func));
      98           0 :         return ret;
      99             : }
     100             : EXPORT_SYMBOL_GPL(sdio_enable_func);
     101             : 
     102             : /**
     103             :  *      sdio_disable_func - disable a SDIO function
     104             :  *      @func: SDIO function to disable
     105             :  *
     106             :  *      Powers down and deactivates a SDIO function. Register access
     107             :  *      to this function will fail until the function is reenabled.
     108             :  */
     109             : int sdio_disable_func(struct sdio_func *func)
     110             : {
     111           0 :         int ret;
     112           0 :         unsigned char reg;
     113           0 : 
     114           0 :         BUG_ON(!func);
     115           0 :         BUG_ON(!func->card);
     116           0 : 
     117           0 :         pr_debug("SDIO: Disabling device %s...\n", sdio_func_id(func));
     118             : 
     119           0 :         ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IOEx, 0, &reg);
     120           0 :         if (ret)
     121           0 :                 goto err;
     122             : 
     123           0 :         reg &= ~(1 << func->num);
     124             : 
     125           0 :         ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IOEx, reg, NULL);
     126           0 :         if (ret)
     127           0 :                 goto err;
     128             : 
     129           0 :         pr_debug("SDIO: Disabled device %s\n", sdio_func_id(func));
     130             : 
     131           0 :         return 0;
     132           0 : 
     133             : err:
     134           0 :         pr_debug("SDIO: Failed to disable device %s\n", sdio_func_id(func));
     135           0 :         return -EIO;
     136             : }
     137             : EXPORT_SYMBOL_GPL(sdio_disable_func);
     138             : 
     139             : /**
     140             :  *      sdio_set_block_size - set the block size of an SDIO function
     141             :  *      @func: SDIO function to change
     142             :  *      @blksz: new block size or 0 to use the default.
     143             :  *
     144             :  *      The default block size is the largest supported by both the function
     145             :  *      and the host, with a maximum of 512 to ensure that arbitrarily sized
     146             :  *      data transfer use the optimal (least) number of commands.
     147             :  *
     148             :  *      A driver may call this to override the default block size set by the
     149             :  *      core. This can be used to set a block size greater than the maximum
     150             :  *      that reported by the card; it is the driver's responsibility to ensure
     151             :  *      it uses a value that the card supports.
     152             :  *
     153             :  *      Returns 0 on success, -EINVAL if the host does not support the
     154             :  *      requested block size, or -EIO (etc.) if one of the resultant FBR block
     155             :  *      size register writes failed.
     156             :  *
     157             :  */
     158             : int sdio_set_block_size(struct sdio_func *func, unsigned blksz)
     159             : {
     160          12 :         int ret;
     161          12 : 
     162          36 :         if (blksz > func->card->host->max_blk_size)
     163          24 :                 return -EINVAL;
     164          12 : 
     165          24 :         if (blksz == 0) {
     166          96 :                 blksz = min(func->max_blksize, func->card->host->max_blk_size);
     167          96 :                 blksz = min(blksz, 512u);
     168             :         }
     169             : 
     170          36 :         ret = mmc_io_rw_direct(func->card, 1, 0,
     171             :                 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE,
     172             :                 blksz & 0xff, NULL);
     173          24 :         if (ret)
     174          12 :                 return ret;
     175          36 :         ret = mmc_io_rw_direct(func->card, 1, 0,
     176             :                 SDIO_FBR_BASE(func->num) + SDIO_FBR_BLKSIZE + 1,
     177             :                 (blksz >> 8) & 0xff, NULL);
     178          24 :         if (ret)
     179          12 :                 return ret;
     180          12 :         func->cur_blksize = blksz;
     181          12 :         return 0;
     182             : }
     183             : EXPORT_SYMBOL_GPL(sdio_set_block_size);
     184             : 
     185           0 : /*
     186           0 :  * Calculate the maximum byte mode transfer size
     187           0 :  */
     188           0 : static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
     189           0 : {
     190           0 :         unsigned mval = min(func->card->host->max_seg_size,
     191           0 :                             func->card->host->max_blk_size);
     192           0 :         mval = min(mval, func->max_blksize);
     193           0 :         return min(mval, 512u); /* maximum size for byte mode */
     194             : }
     195             : 
     196             : /**
     197             :  *      sdio_align_size - pads a transfer size to a more optimal value
     198             :  *      @func: SDIO function
     199             :  *      @sz: original transfer size
     200             :  *
     201             :  *      Pads the original data size with a number of extra bytes in
     202             :  *      order to avoid controller bugs and/or performance hits
     203             :  *      (e.g. some controllers revert to PIO for certain sizes).
     204             :  *
     205             :  *      If possible, it will also adjust the size so that it can be
     206             :  *      handled in just a single request.
     207             :  *
     208             :  *      Returns the improved size, which might be unmodified.
     209             :  */
     210             : unsigned int sdio_align_size(struct sdio_func *func, unsigned int sz)
     211             : {
     212           0 :         unsigned int orig_sz;
     213           0 :         unsigned int blk_sz, byte_sz;
     214           0 :         unsigned chunk_sz;
     215           0 : 
     216           0 :         orig_sz = sz;
     217           0 : 
     218           0 :         /*
     219           0 :          * Do a first check with the controller, in case it
     220             :          * wants to increase the size up to a point where it
     221             :          * might need more than one block.
     222             :          */
     223           0 :         sz = mmc_align_data_size(func->card, sz);
     224             : 
     225             :         /*
     226             :          * If we can still do this with just a byte transfer, then
     227             :          * we're done.
     228             :          */
     229           0 :         if (sz <= sdio_max_byte_size(func))
     230           0 :                 return sz;
     231             : 
     232           0 :         if (func->card->cccr.multi_block) {
     233             :                 /*
     234             :                  * Check if the transfer is already block aligned
     235             :                  */
     236           0 :                 if ((sz % func->cur_blksize) == 0)
     237           0 :                         return sz;
     238             : 
     239             :                 /*
     240             :                  * Realign it so that it can be done with one request,
     241             :                  * and recheck if the controller still likes it.
     242             :                  */
     243           0 :                 blk_sz = ((sz + func->cur_blksize - 1) /
     244             :                         func->cur_blksize) * func->cur_blksize;
     245           0 :                 blk_sz = mmc_align_data_size(func->card, blk_sz);
     246             : 
     247             :                 /*
     248             :                  * This value is only good if it is still just
     249             :                  * one request.
     250             :                  */
     251           0 :                 if ((blk_sz % func->cur_blksize) == 0)
     252           0 :                         return blk_sz;
     253             : 
     254             :                 /*
     255             :                  * We failed to do one request, but at least try to
     256             :                  * pad the remainder properly.
     257             :                  */
     258           0 :                 byte_sz = mmc_align_data_size(func->card,
     259             :                                 sz % func->cur_blksize);
     260           0 :                 if (byte_sz <= sdio_max_byte_size(func)) {
     261           0 :                         blk_sz = sz / func->cur_blksize;
     262           0 :                         return blk_sz * func->cur_blksize + byte_sz;
     263             :                 }
     264             :         } else {
     265             :                 /*
     266             :                  * We need multiple requests, so first check that the
     267             :                  * controller can handle the chunk size;
     268             :                  */
     269           0 :                 chunk_sz = mmc_align_data_size(func->card,
     270             :                                 sdio_max_byte_size(func));
     271           0 :                 if (chunk_sz == sdio_max_byte_size(func)) {
     272             :                         /*
     273             :                          * Fix up the size of the remainder (if any)
     274             :                          */
     275           0 :                         byte_sz = orig_sz % chunk_sz;
     276           0 :                         if (byte_sz) {
     277           0 :                                 byte_sz = mmc_align_data_size(func->card,
     278             :                                                 byte_sz);
     279             :                         }
     280             : 
     281           0 :                         return (orig_sz / chunk_sz) * chunk_sz + byte_sz;
     282             :                 }
     283             :         }
     284             : 
     285             :         /*
     286             :          * The controller is simply incapable of transferring the size
     287             :          * we want in decent manner, so just return the original size.
     288             :          */
     289           0 :         return orig_sz;
     290             : }
     291             : EXPORT_SYMBOL_GPL(sdio_align_size);
     292             : 
     293             : /* Split an arbitrarily sized data transfer into several
     294             :  * IO_RW_EXTENDED commands. */
     295             : static int sdio_io_rw_ext_helper(struct sdio_func *func, int write,
     296             :         unsigned addr, int incr_addr, u8 *buf, unsigned size)
     297             : {
     298           0 :         unsigned remainder = size;
     299           0 :         unsigned max_blocks;
     300           0 :         int ret;
     301           0 : 
     302           0 :         /* Do the bulk of the transfer using block mode (if supported). */
     303           0 :         if (func->card->cccr.multi_block && (size > sdio_max_byte_size(func))) {
     304           0 :                 /* Blocks per command is limited by host count, host transfer
     305           0 :                  * size (we only use a single sg entry) and the maximum for
     306           0 :                  * IO_RW_EXTENDED of 511 blocks. */
     307           0 :                 max_blocks = min(func->card->host->max_blk_count,
     308           0 :                         func->card->host->max_seg_size / func->cur_blksize);
     309           0 :                 max_blocks = min(max_blocks, 511u);
     310             : 
     311           0 :                 while (remainder > func->cur_blksize) {
     312           0 :                         unsigned blocks;
     313           0 : 
     314           0 :                         blocks = remainder / func->cur_blksize;
     315           0 :                         if (blocks > max_blocks)
     316           0 :                                 blocks = max_blocks;
     317           0 :                         size = blocks * func->cur_blksize;
     318             : 
     319           0 :                         ret = mmc_io_rw_extended(func->card, write,
     320             :                                 func->num, addr, incr_addr, buf,
     321             :                                 blocks, func->cur_blksize);
     322           0 :                         if (ret)
     323           0 :                                 return ret;
     324             : 
     325           0 :                         remainder -= size;
     326           0 :                         buf += size;
     327           0 :                         if (incr_addr)
     328           0 :                                 addr += size;
     329             :                 }
     330             :         }
     331             : 
     332           0 :         /* Write the remainder using byte mode. */
     333           0 :         while (remainder > 0) {
     334           0 :                 size = min(remainder, sdio_max_byte_size(func));
     335           0 : 
     336           0 :                 ret = mmc_io_rw_extended(func->card, write, func->num, addr,
     337             :                          incr_addr, buf, 1, size);
     338           0 :                 if (ret)
     339           0 :                         return ret;
     340             : 
     341           0 :                 remainder -= size;
     342           0 :                 buf += size;
     343           0 :                 if (incr_addr)
     344           0 :                         addr += size;
     345             :         }
     346           0 :         return 0;
     347             : }
     348           0 : 
     349             : /**
     350             :  *      sdio_readb - read a single byte from a SDIO function
     351             :  *      @func: SDIO function to access
     352             :  *      @addr: address to read
     353             :  *      @err_ret: optional status value from transfer
     354             :  *
     355             :  *      Reads a single byte from the address space of a given SDIO
     356             :  *      function. If there is a problem reading the address, 0xff
     357             :  *      is returned and @err_ret will contain the error code.
     358             :  */
     359             : u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)
     360             : {
     361           0 :         int ret;
     362           0 :         u8 val;
     363           0 : 
     364           0 :         BUG_ON(!func);
     365             : 
     366           0 :         if (err_ret)
     367           0 :                 *err_ret = 0;
     368             : 
     369           0 :         ret = mmc_io_rw_direct(func->card, 0, func->num, addr, 0, &val);
     370           0 :         if (ret) {
     371           0 :                 if (err_ret)
     372           0 :                         *err_ret = ret;
     373           0 :                 return 0xFF;
     374             :         }
     375             : 
     376           0 :         return val;
     377             : }
     378             : EXPORT_SYMBOL_GPL(sdio_readb);
     379             : 
     380             : /**
     381             :  *      sdio_writeb - write a single byte to a SDIO function
     382             :  *      @func: SDIO function to access
     383             :  *      @b: byte to write
     384             :  *      @addr: address to write to
     385             :  *      @err_ret: optional status value from transfer
     386             :  *
     387             :  *      Writes a single byte to the address space of a given SDIO
     388             :  *      function. @err_ret will contain the status of the actual
     389             :  *      transfer.
     390             :  */
     391             : void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret)
     392             : {
     393           0 :         int ret;
     394           0 : 
     395           0 :         BUG_ON(!func);
     396             : 
     397           0 :         ret = mmc_io_rw_direct(func->card, 1, func->num, addr, b, NULL);
     398           0 :         if (err_ret)
     399           0 :                 *err_ret = ret;
     400           0 : }
     401             : EXPORT_SYMBOL_GPL(sdio_writeb);
     402             : 
     403             : /**
     404             :  *      sdio_memcpy_fromio - read a chunk of memory from a SDIO function
     405             :  *      @func: SDIO function to access
     406             :  *      @dst: buffer to store the data
     407             :  *      @addr: address to begin reading from
     408             :  *      @count: number of bytes to read
     409             :  *
     410             :  *      Reads from the address space of a given SDIO function. Return
     411             :  *      value indicates if the transfer succeeded or not.
     412             :  */
     413             : int sdio_memcpy_fromio(struct sdio_func *func, void *dst,
     414             :         unsigned int addr, int count)
     415           0 : {
     416           0 :         return sdio_io_rw_ext_helper(func, 0, addr, 1, dst, count);
     417             : }
     418             : EXPORT_SYMBOL_GPL(sdio_memcpy_fromio);
     419             : 
     420             : /**
     421             :  *      sdio_memcpy_toio - write a chunk of memory to a SDIO function
     422             :  *      @func: SDIO function to access
     423             :  *      @addr: address to start writing to
     424             :  *      @src: buffer that contains the data to write
     425             :  *      @count: number of bytes to write
     426             :  *
     427             :  *      Writes to the address space of a given SDIO function. Return
     428             :  *      value indicates if the transfer succeeded or not.
     429             :  */
     430             : int sdio_memcpy_toio(struct sdio_func *func, unsigned int addr,
     431             :         void *src, int count)
     432           0 : {
     433           0 :         return sdio_io_rw_ext_helper(func, 1, addr, 1, src, count);
     434             : }
     435             : EXPORT_SYMBOL_GPL(sdio_memcpy_toio);
     436             : 
     437             : /**
     438             :  *      sdio_readsb - read from a FIFO on a SDIO function
     439             :  *      @func: SDIO function to access
     440             :  *      @dst: buffer to store the data
     441             :  *      @addr: address of (single byte) FIFO
     442             :  *      @count: number of bytes to read
     443             :  *
     444             :  *      Reads from the specified FIFO of a given SDIO function. Return
     445             :  *      value indicates if the transfer succeeded or not.
     446             :  */
     447             : int sdio_readsb(struct sdio_func *func, void *dst, unsigned int addr,
     448             :         int count)
     449           0 : {
     450           0 :         return sdio_io_rw_ext_helper(func, 0, addr, 0, dst, count);
     451             : }
     452             : EXPORT_SYMBOL_GPL(sdio_readsb);
     453             : 
     454             : /**
     455             :  *      sdio_writesb - write to a FIFO of a SDIO function
     456             :  *      @func: SDIO function to access
     457             :  *      @addr: address of (single byte) FIFO
     458             :  *      @src: buffer that contains the data to write
     459             :  *      @count: number of bytes to write
     460             :  *
     461             :  *      Writes to the specified FIFO of a given SDIO function. Return
     462             :  *      value indicates if the transfer succeeded or not.
     463             :  */
     464             : int sdio_writesb(struct sdio_func *func, unsigned int addr, void *src,
     465             :         int count)
     466           0 : {
     467           0 :         return sdio_io_rw_ext_helper(func, 1, addr, 0, src, count);
     468             : }
     469             : EXPORT_SYMBOL_GPL(sdio_writesb);
     470             : 
     471             : /**
     472             :  *      sdio_readw - read a 16 bit integer from a SDIO function
     473             :  *      @func: SDIO function to access
     474             :  *      @addr: address to read
     475             :  *      @err_ret: optional status value from transfer
     476             :  *
     477             :  *      Reads a 16 bit integer from the address space of a given SDIO
     478             :  *      function. If there is a problem reading the address, 0xffff
     479             :  *      is returned and @err_ret will contain the error code.
     480             :  */
     481             : u16 sdio_readw(struct sdio_func *func, unsigned int addr, int *err_ret)
     482             : {
     483           0 :         int ret;
     484           0 : 
     485           0 :         if (err_ret)
     486           0 :                 *err_ret = 0;
     487             : 
     488           0 :         ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 2);
     489           0 :         if (ret) {
     490           0 :                 if (err_ret)
     491           0 :                         *err_ret = ret;
     492           0 :                 return 0xFFFF;
     493             :         }
     494             : 
     495           0 :         return le16_to_cpup((__le16 *)func->tmpbuf);
     496             : }
     497             : EXPORT_SYMBOL_GPL(sdio_readw);
     498             : 
     499             : /**
     500             :  *      sdio_writew - write a 16 bit integer to a SDIO function
     501             :  *      @func: SDIO function to access
     502             :  *      @b: integer to write
     503             :  *      @addr: address to write to
     504             :  *      @err_ret: optional status value from transfer
     505             :  *
     506             :  *      Writes a 16 bit integer to the address space of a given SDIO
     507             :  *      function. @err_ret will contain the status of the actual
     508             :  *      transfer.
     509             :  */
     510             : void sdio_writew(struct sdio_func *func, u16 b, unsigned int addr, int *err_ret)
     511             : {
     512           0 :         int ret;
     513             : 
     514           0 :         *(__le16 *)func->tmpbuf = cpu_to_le16(b);
     515             : 
     516           0 :         ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 2);
     517           0 :         if (err_ret)
     518           0 :                 *err_ret = ret;
     519           0 : }
     520             : EXPORT_SYMBOL_GPL(sdio_writew);
     521             : 
     522             : /**
     523             :  *      sdio_readl - read a 32 bit integer from a SDIO function
     524             :  *      @func: SDIO function to access
     525             :  *      @addr: address to read
     526             :  *      @err_ret: optional status value from transfer
     527             :  *
     528             :  *      Reads a 32 bit integer from the address space of a given SDIO
     529             :  *      function. If there is a problem reading the address,
     530             :  *      0xffffffff is returned and @err_ret will contain the error
     531             :  *      code.
     532             :  */
     533             : u32 sdio_readl(struct sdio_func *func, unsigned int addr, int *err_ret)
     534             : {
     535           0 :         int ret;
     536           0 : 
     537           0 :         if (err_ret)
     538           0 :                 *err_ret = 0;
     539             : 
     540           0 :         ret = sdio_memcpy_fromio(func, func->tmpbuf, addr, 4);
     541           0 :         if (ret) {
     542           0 :                 if (err_ret)
     543           0 :                         *err_ret = ret;
     544           0 :                 return 0xFFFFFFFF;
     545             :         }
     546             : 
     547           0 :         return le32_to_cpup((__le32 *)func->tmpbuf);
     548             : }
     549             : EXPORT_SYMBOL_GPL(sdio_readl);
     550             : 
     551             : /**
     552             :  *      sdio_writel - write a 32 bit integer to a SDIO function
     553             :  *      @func: SDIO function to access
     554             :  *      @b: integer to write
     555             :  *      @addr: address to write to
     556             :  *      @err_ret: optional status value from transfer
     557             :  *
     558             :  *      Writes a 32 bit integer to the address space of a given SDIO
     559             :  *      function. @err_ret will contain the status of the actual
     560             :  *      transfer.
     561             :  */
     562             : void sdio_writel(struct sdio_func *func, u32 b, unsigned int addr, int *err_ret)
     563             : {
     564           0 :         int ret;
     565             : 
     566           0 :         *(__le32 *)func->tmpbuf = cpu_to_le32(b);
     567             : 
     568           0 :         ret = sdio_memcpy_toio(func, addr, func->tmpbuf, 4);
     569           0 :         if (err_ret)
     570           0 :                 *err_ret = ret;
     571           0 : }
     572             : EXPORT_SYMBOL_GPL(sdio_writel);
     573             : 
     574             : /**
     575             :  *      sdio_f0_readb - read a single byte from SDIO function 0
     576             :  *      @func: an SDIO function of the card
     577             :  *      @addr: address to read
     578             :  *      @err_ret: optional status value from transfer
     579             :  *
     580             :  *      Reads a single byte from the address space of SDIO function 0.
     581             :  *      If there is a problem reading the address, 0xff is returned
     582             :  *      and @err_ret will contain the error code.
     583             :  */
     584             : unsigned char sdio_f0_readb(struct sdio_func *func, unsigned int addr,
     585             :         int *err_ret)
     586           0 : {
     587           0 :         int ret;
     588           0 :         unsigned char val;
     589             : 
     590           0 :         BUG_ON(!func);
     591             : 
     592           0 :         if (err_ret)
     593           0 :                 *err_ret = 0;
     594             : 
     595           0 :         ret = mmc_io_rw_direct(func->card, 0, 0, addr, 0, &val);
     596           0 :         if (ret) {
     597           0 :                 if (err_ret)
     598           0 :                         *err_ret = ret;
     599           0 :                 return 0xFF;
     600             :         }
     601             : 
     602           0 :         return val;
     603             : }
     604             : EXPORT_SYMBOL_GPL(sdio_f0_readb);
     605             : 
     606             : /**
     607             :  *      sdio_f0_writeb - write a single byte to SDIO function 0
     608             :  *      @func: an SDIO function of the card
     609             :  *      @b: byte to write
     610             :  *      @addr: address to write to
     611             :  *      @err_ret: optional status value from transfer
     612             :  *
     613             :  *      Writes a single byte to the address space of SDIO function 0.
     614             :  *      @err_ret will contain the status of the actual transfer.
     615             :  *
     616             :  *      Only writes to the vendor specific CCCR registers (0xF0 -
     617             :  *      0xFF) are permiited; @err_ret will be set to -EINVAL for *
     618             :  *      writes outside this range.
     619             :  */
     620             : void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
     621             :         int *err_ret)
     622             : {
     623           0 :         int ret;
     624           0 : 
     625           0 :         BUG_ON(!func);
     626             : 
     627           0 :         if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) {
     628           0 :                 if (err_ret)
     629           0 :                         *err_ret = -EINVAL;
     630           0 :                 return;
     631             :         }
     632             : 
     633           0 :         ret = mmc_io_rw_direct(func->card, 1, 0, addr, b, NULL);
     634           0 :         if (err_ret)
     635           0 :                 *err_ret = ret;
     636           0 : }
     637             : EXPORT_SYMBOL_GPL(sdio_f0_writeb);

Generated by: LCOV version 1.10