LCOV - code coverage report
Current view: top level - lib - iomap.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 25 149 16.8 %
Date: 2022-03-28 15:32:58 Functions: 9 28 32.1 %
Branches: 16 116 13.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Implement the default iomap interfaces
       4                 :            :  *
       5                 :            :  * (C) Copyright 2004 Linus Torvalds
       6                 :            :  */
       7                 :            : #include <linux/pci.h>
       8                 :            : #include <linux/io.h>
       9                 :            : 
      10                 :            : #include <linux/export.h>
      11                 :            : 
      12                 :            : /*
      13                 :            :  * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
      14                 :            :  * access or a MMIO access, these functions don't care. The info is
      15                 :            :  * encoded in the hardware mapping set up by the mapping functions
      16                 :            :  * (or the cookie itself, depending on implementation and hw).
      17                 :            :  *
      18                 :            :  * The generic routines don't assume any hardware mappings, and just
      19                 :            :  * encode the PIO/MMIO as part of the cookie. They coldly assume that
      20                 :            :  * the MMIO IO mappings are not in the low address range.
      21                 :            :  *
      22                 :            :  * Architectures for which this is not true can't use this generic
      23                 :            :  * implementation and should do their own copy.
      24                 :            :  */
      25                 :            : 
      26                 :            : #ifndef HAVE_ARCH_PIO_SIZE
      27                 :            : /*
      28                 :            :  * We encode the physical PIO addresses (0-0xffff) into the
      29                 :            :  * pointer by offsetting them with a constant (0x10000) and
      30                 :            :  * assuming that all the low addresses are always PIO. That means
      31                 :            :  * we can do some sanity checks on the low bits, and don't
      32                 :            :  * need to just take things for granted.
      33                 :            :  */
      34                 :            : #define PIO_OFFSET      0x10000UL
      35                 :            : #define PIO_MASK        0x0ffffUL
      36                 :            : #define PIO_RESERVED    0x40000UL
      37                 :            : #endif
      38                 :            : 
      39                 :          0 : static void bad_io_access(unsigned long port, const char *access)
      40                 :            : {
      41                 :          0 :         static int count = 10;
      42         [ #  # ]:          0 :         if (count) {
      43                 :          0 :                 count--;
      44                 :          0 :                 WARN(1, KERN_ERR "Bad IO access at port %#lx (%s)\n", port, access);
      45                 :            :         }
      46                 :          0 : }
      47                 :            : 
      48                 :            : /*
      49                 :            :  * Ugly macros are a way of life.
      50                 :            :  */
      51                 :            : #define IO_COND(addr, is_pio, is_mmio) do {                     \
      52                 :            :         unsigned long port = (unsigned long __force)addr;       \
      53                 :            :         if (port >= PIO_RESERVED) {                          \
      54                 :            :                 is_mmio;                                        \
      55                 :            :         } else if (port > PIO_OFFSET) {                              \
      56                 :            :                 port &= PIO_MASK;                           \
      57                 :            :                 is_pio;                                         \
      58                 :            :         } else                                                  \
      59                 :            :                 bad_io_access(port, #is_pio );                  \
      60                 :            : } while (0)
      61                 :            : 
      62                 :            : #ifndef pio_read16be
      63                 :            : #define pio_read16be(port) swab16(inw(port))
      64                 :            : #define pio_read32be(port) swab32(inl(port))
      65                 :            : #endif
      66                 :            : 
      67                 :            : #ifndef mmio_read16be
      68                 :            : #define mmio_read16be(addr) swab16(readw(addr))
      69                 :            : #define mmio_read32be(addr) swab32(readl(addr))
      70                 :            : #define mmio_read64be(addr) swab64(readq(addr))
      71                 :            : #endif
      72                 :            : 
      73                 :     401154 : unsigned int ioread8(void __iomem *addr)
      74                 :            : {
      75   [ -  +  +  - ]:     401154 :         IO_COND(addr, return inb(port), return readb(addr));
      76                 :          0 :         return 0xff;
      77                 :            : }
      78                 :          0 : unsigned int ioread16(void __iomem *addr)
      79                 :            : {
      80   [ #  #  #  # ]:          0 :         IO_COND(addr, return inw(port), return readw(addr));
      81                 :          0 :         return 0xffff;
      82                 :            : }
      83                 :          0 : unsigned int ioread16be(void __iomem *addr)
      84                 :            : {
      85   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr));
      86                 :          0 :         return 0xffff;
      87                 :            : }
      88                 :       9693 : unsigned int ioread32(void __iomem *addr)
      89                 :            : {
      90   [ +  -  -  - ]:       9693 :         IO_COND(addr, return inl(port), return readl(addr));
      91                 :          0 :         return 0xffffffff;
      92                 :            : }
      93                 :          0 : unsigned int ioread32be(void __iomem *addr)
      94                 :            : {
      95   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr));
      96                 :          0 :         return 0xffffffff;
      97                 :            : }
      98                 :            : EXPORT_SYMBOL(ioread8);
      99                 :            : EXPORT_SYMBOL(ioread16);
     100                 :            : EXPORT_SYMBOL(ioread16be);
     101                 :            : EXPORT_SYMBOL(ioread32);
     102                 :            : EXPORT_SYMBOL(ioread32be);
     103                 :            : 
     104                 :            : #ifdef readq
     105                 :          0 : static u64 pio_read64_lo_hi(unsigned long port)
     106                 :            : {
     107                 :          0 :         u64 lo, hi;
     108                 :            : 
     109                 :          0 :         lo = inl(port);
     110                 :          0 :         hi = inl(port + sizeof(u32));
     111                 :            : 
     112                 :          0 :         return lo | (hi << 32);
     113                 :            : }
     114                 :            : 
     115                 :          0 : static u64 pio_read64_hi_lo(unsigned long port)
     116                 :            : {
     117                 :          0 :         u64 lo, hi;
     118                 :            : 
     119                 :          0 :         hi = inl(port + sizeof(u32));
     120                 :          0 :         lo = inl(port);
     121                 :            : 
     122                 :          0 :         return lo | (hi << 32);
     123                 :            : }
     124                 :            : 
     125                 :          0 : static u64 pio_read64be_lo_hi(unsigned long port)
     126                 :            : {
     127                 :          0 :         u64 lo, hi;
     128                 :            : 
     129                 :          0 :         lo = pio_read32be(port + sizeof(u32));
     130                 :          0 :         hi = pio_read32be(port);
     131                 :            : 
     132                 :          0 :         return lo | (hi << 32);
     133                 :            : }
     134                 :            : 
     135                 :          0 : static u64 pio_read64be_hi_lo(unsigned long port)
     136                 :            : {
     137                 :          0 :         u64 lo, hi;
     138                 :            : 
     139                 :          0 :         hi = pio_read32be(port);
     140                 :          0 :         lo = pio_read32be(port + sizeof(u32));
     141                 :            : 
     142                 :          0 :         return lo | (hi << 32);
     143                 :            : }
     144                 :            : 
     145                 :          0 : u64 ioread64_lo_hi(void __iomem *addr)
     146                 :            : {
     147   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read64_lo_hi(port), return readq(addr));
     148                 :          0 :         return 0xffffffffffffffffULL;
     149                 :            : }
     150                 :            : 
     151                 :          0 : u64 ioread64_hi_lo(void __iomem *addr)
     152                 :            : {
     153   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read64_hi_lo(port), return readq(addr));
     154                 :          0 :         return 0xffffffffffffffffULL;
     155                 :            : }
     156                 :            : 
     157                 :          0 : u64 ioread64be_lo_hi(void __iomem *addr)
     158                 :            : {
     159   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read64be_lo_hi(port),
     160                 :            :                 return mmio_read64be(addr));
     161                 :          0 :         return 0xffffffffffffffffULL;
     162                 :            : }
     163                 :            : 
     164                 :          0 : u64 ioread64be_hi_lo(void __iomem *addr)
     165                 :            : {
     166   [ #  #  #  # ]:          0 :         IO_COND(addr, return pio_read64be_hi_lo(port),
     167                 :            :                 return mmio_read64be(addr));
     168                 :          0 :         return 0xffffffffffffffffULL;
     169                 :            : }
     170                 :            : 
     171                 :            : EXPORT_SYMBOL(ioread64_lo_hi);
     172                 :            : EXPORT_SYMBOL(ioread64_hi_lo);
     173                 :            : EXPORT_SYMBOL(ioread64be_lo_hi);
     174                 :            : EXPORT_SYMBOL(ioread64be_hi_lo);
     175                 :            : 
     176                 :            : #endif /* readq */
     177                 :            : 
     178                 :            : #ifndef pio_write16be
     179                 :            : #define pio_write16be(val,port) outw(swab16(val),port)
     180                 :            : #define pio_write32be(val,port) outl(swab32(val),port)
     181                 :            : #endif
     182                 :            : 
     183                 :            : #ifndef mmio_write16be
     184                 :            : #define mmio_write16be(val,port) writew(swab16(val),port)
     185                 :            : #define mmio_write32be(val,port) writel(swab32(val),port)
     186                 :            : #define mmio_write64be(val,port) writeq(swab64(val),port)
     187                 :            : #endif
     188                 :            : 
     189                 :     361840 : void iowrite8(u8 val, void __iomem *addr)
     190                 :            : {
     191   [ -  +  +  - ]:     361840 :         IO_COND(addr, outb(val,port), writeb(val, addr));
     192                 :     361840 : }
     193                 :          0 : void iowrite16(u16 val, void __iomem *addr)
     194                 :            : {
     195   [ #  #  #  # ]:          0 :         IO_COND(addr, outw(val,port), writew(val, addr));
     196                 :          0 : }
     197                 :          0 : void iowrite16be(u16 val, void __iomem *addr)
     198                 :            : {
     199   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write16be(val,port), mmio_write16be(val, addr));
     200                 :          0 : }
     201                 :      38338 : void iowrite32(u32 val, void __iomem *addr)
     202                 :            : {
     203   [ +  +  +  - ]:      38338 :         IO_COND(addr, outl(val,port), writel(val, addr));
     204                 :      38338 : }
     205                 :          0 : void iowrite32be(u32 val, void __iomem *addr)
     206                 :            : {
     207   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write32be(val,port), mmio_write32be(val, addr));
     208                 :          0 : }
     209                 :            : EXPORT_SYMBOL(iowrite8);
     210                 :            : EXPORT_SYMBOL(iowrite16);
     211                 :            : EXPORT_SYMBOL(iowrite16be);
     212                 :            : EXPORT_SYMBOL(iowrite32);
     213                 :            : EXPORT_SYMBOL(iowrite32be);
     214                 :            : 
     215                 :            : #ifdef writeq
     216                 :          0 : static void pio_write64_lo_hi(u64 val, unsigned long port)
     217                 :            : {
     218                 :          0 :         outl(val, port);
     219                 :          0 :         outl(val >> 32, port + sizeof(u32));
     220                 :          0 : }
     221                 :            : 
     222                 :          0 : static void pio_write64_hi_lo(u64 val, unsigned long port)
     223                 :            : {
     224                 :          0 :         outl(val >> 32, port + sizeof(u32));
     225                 :          0 :         outl(val, port);
     226                 :          0 : }
     227                 :            : 
     228                 :          0 : static void pio_write64be_lo_hi(u64 val, unsigned long port)
     229                 :            : {
     230                 :          0 :         pio_write32be(val, port + sizeof(u32));
     231                 :          0 :         pio_write32be(val >> 32, port);
     232                 :          0 : }
     233                 :            : 
     234                 :          0 : static void pio_write64be_hi_lo(u64 val, unsigned long port)
     235                 :            : {
     236                 :          0 :         pio_write32be(val >> 32, port);
     237                 :          0 :         pio_write32be(val, port + sizeof(u32));
     238                 :          0 : }
     239                 :            : 
     240                 :          0 : void iowrite64_lo_hi(u64 val, void __iomem *addr)
     241                 :            : {
     242   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write64_lo_hi(val, port),
     243                 :            :                 writeq(val, addr));
     244                 :          0 : }
     245                 :            : 
     246                 :          0 : void iowrite64_hi_lo(u64 val, void __iomem *addr)
     247                 :            : {
     248   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write64_hi_lo(val, port),
     249                 :            :                 writeq(val, addr));
     250                 :          0 : }
     251                 :            : 
     252                 :          0 : void iowrite64be_lo_hi(u64 val, void __iomem *addr)
     253                 :            : {
     254   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write64be_lo_hi(val, port),
     255                 :            :                 mmio_write64be(val, addr));
     256                 :          0 : }
     257                 :            : 
     258                 :          0 : void iowrite64be_hi_lo(u64 val, void __iomem *addr)
     259                 :            : {
     260   [ #  #  #  # ]:          0 :         IO_COND(addr, pio_write64be_hi_lo(val, port),
     261                 :            :                 mmio_write64be(val, addr));
     262                 :          0 : }
     263                 :            : 
     264                 :            : EXPORT_SYMBOL(iowrite64_lo_hi);
     265                 :            : EXPORT_SYMBOL(iowrite64_hi_lo);
     266                 :            : EXPORT_SYMBOL(iowrite64be_lo_hi);
     267                 :            : EXPORT_SYMBOL(iowrite64be_hi_lo);
     268                 :            : 
     269                 :            : #endif /* readq */
     270                 :            : 
     271                 :            : /*
     272                 :            :  * These are the "repeat MMIO read/write" functions.
     273                 :            :  * Note the "__raw" accesses, since we don't want to
     274                 :            :  * convert to CPU byte order. We write in "IO byte
     275                 :            :  * order" (we also don't have IO barriers).
     276                 :            :  */
     277                 :            : #ifndef mmio_insb
     278                 :          0 : static inline void mmio_insb(void __iomem *addr, u8 *dst, int count)
     279                 :            : {
     280         [ #  # ]:          0 :         while (--count >= 0) {
     281                 :          0 :                 u8 data = __raw_readb(addr);
     282                 :          0 :                 *dst = data;
     283                 :          0 :                 dst++;
     284                 :            :         }
     285                 :            : }
     286                 :          0 : static inline void mmio_insw(void __iomem *addr, u16 *dst, int count)
     287                 :            : {
     288         [ #  # ]:          0 :         while (--count >= 0) {
     289                 :          0 :                 u16 data = __raw_readw(addr);
     290                 :          0 :                 *dst = data;
     291                 :          0 :                 dst++;
     292                 :            :         }
     293                 :            : }
     294                 :          0 : static inline void mmio_insl(void __iomem *addr, u32 *dst, int count)
     295                 :            : {
     296         [ #  # ]:          0 :         while (--count >= 0) {
     297                 :          0 :                 u32 data = __raw_readl(addr);
     298                 :          0 :                 *dst = data;
     299                 :          0 :                 dst++;
     300                 :            :         }
     301                 :            : }
     302                 :            : #endif
     303                 :            : 
     304                 :            : #ifndef mmio_outsb
     305                 :          0 : static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
     306                 :            : {
     307         [ #  # ]:          0 :         while (--count >= 0) {
     308                 :          0 :                 __raw_writeb(*src, addr);
     309                 :          0 :                 src++;
     310                 :            :         }
     311                 :            : }
     312                 :          0 : static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
     313                 :            : {
     314         [ #  # ]:          0 :         while (--count >= 0) {
     315                 :          0 :                 __raw_writew(*src, addr);
     316                 :          0 :                 src++;
     317                 :            :         }
     318                 :            : }
     319                 :          0 : static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
     320                 :            : {
     321         [ #  # ]:          0 :         while (--count >= 0) {
     322                 :          0 :                 __raw_writel(*src, addr);
     323                 :          0 :                 src++;
     324                 :            :         }
     325                 :            : }
     326                 :            : #endif
     327                 :            : 
     328                 :          0 : void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
     329                 :            : {
     330   [ #  #  #  # ]:          0 :         IO_COND(addr, insb(port,dst,count), mmio_insb(addr, dst, count));
     331                 :          0 : }
     332                 :        280 : void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
     333                 :            : {
     334   [ -  +  +  - ]:        280 :         IO_COND(addr, insw(port,dst,count), mmio_insw(addr, dst, count));
     335                 :        280 : }
     336                 :        952 : void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
     337                 :            : {
     338   [ -  +  +  - ]:        952 :         IO_COND(addr, insl(port,dst,count), mmio_insl(addr, dst, count));
     339                 :        952 : }
     340                 :            : EXPORT_SYMBOL(ioread8_rep);
     341                 :            : EXPORT_SYMBOL(ioread16_rep);
     342                 :            : EXPORT_SYMBOL(ioread32_rep);
     343                 :            : 
     344                 :          0 : void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
     345                 :            : {
     346   [ #  #  #  # ]:          0 :         IO_COND(addr, outsb(port, src, count), mmio_outsb(addr, src, count));
     347                 :          0 : }
     348                 :          0 : void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
     349                 :            : {
     350   [ #  #  #  # ]:          0 :         IO_COND(addr, outsw(port, src, count), mmio_outsw(addr, src, count));
     351                 :          0 : }
     352                 :       1176 : void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
     353                 :            : {
     354   [ -  +  +  - ]:       1176 :         IO_COND(addr, outsl(port, src,count), mmio_outsl(addr, src, count));
     355                 :       1176 : }
     356                 :            : EXPORT_SYMBOL(iowrite8_rep);
     357                 :            : EXPORT_SYMBOL(iowrite16_rep);
     358                 :            : EXPORT_SYMBOL(iowrite32_rep);
     359                 :            : 
     360                 :            : #ifdef CONFIG_HAS_IOPORT_MAP
     361                 :            : /* Create a virtual mapping cookie for an IO port range */
     362                 :        140 : void __iomem *ioport_map(unsigned long port, unsigned int nr)
     363                 :            : {
     364         [ +  - ]:        140 :         if (port > PIO_MASK)
     365                 :            :                 return NULL;
     366                 :        140 :         return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
     367                 :            : }
     368                 :            : 
     369                 :          0 : void ioport_unmap(void __iomem *addr)
     370                 :            : {
     371                 :            :         /* Nothing to do */
     372                 :          0 : }
     373                 :            : EXPORT_SYMBOL(ioport_map);
     374                 :            : EXPORT_SYMBOL(ioport_unmap);
     375                 :            : #endif /* CONFIG_HAS_IOPORT_MAP */
     376                 :            : 
     377                 :            : #ifdef CONFIG_PCI
     378                 :            : /* Hide the details if this is a MMIO or PIO address space and just do what
     379                 :            :  * you expect in the correct way. */
     380                 :          3 : void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
     381                 :            : {
     382   [ +  -  -  - ]:          3 :         IO_COND(addr, /* nothing */, iounmap(addr));
     383                 :          3 : }
     384                 :            : EXPORT_SYMBOL(pci_iounmap);
     385                 :            : #endif /* CONFIG_PCI */

Generated by: LCOV version 1.14