linux/arch/alpha/include/asm/jensen.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef __ALPHA_JENSEN_H
   3#define __ALPHA_JENSEN_H
   4
   5#include <asm/compiler.h>
   6
   7/*
   8 * Defines for the AlphaPC EISA IO and memory address space.
   9 */
  10
  11/*
  12 * NOTE! The memory operations do not set any memory barriers, as it's
  13 * not needed for cases like a frame buffer that is essentially memory-like.
  14 * You need to do them by hand if the operations depend on ordering.
  15 *
  16 * Similarly, the port IO operations do a "mb" only after a write operation:
  17 * if an mb is needed before (as in the case of doing memory mapped IO
  18 * first, and then a port IO operation to the same device), it needs to be
  19 * done by hand.
  20 *
  21 * After the above has bitten me 100 times, I'll give up and just do the
  22 * mb all the time, but right now I'm hoping this will work out.  Avoiding
  23 * mb's may potentially be a noticeable speed improvement, but I can't
  24 * honestly say I've tested it.
  25 *
  26 * Handling interrupts that need to do mb's to synchronize to non-interrupts
  27 * is another fun race area.  Don't do it (because if you do, I'll have to
  28 * do *everything* with interrupts disabled, ugh).
  29 */
  30
  31/*
  32 * EISA Interrupt Acknowledge address
  33 */
  34#define EISA_INTA               (IDENT_ADDR + 0x100000000UL)
  35
  36/*
  37 * FEPROM addresses
  38 */
  39#define EISA_FEPROM0            (IDENT_ADDR + 0x180000000UL)
  40#define EISA_FEPROM1            (IDENT_ADDR + 0x1A0000000UL)
  41
  42/*
  43 * VL82C106 base address
  44 */
  45#define EISA_VL82C106           (IDENT_ADDR + 0x1C0000000UL)
  46
  47/*
  48 * EISA "Host Address Extension" address (bits 25-31 of the EISA address)
  49 */
  50#define EISA_HAE                (IDENT_ADDR + 0x1D0000000UL)
  51
  52/*
  53 * "SYSCTL" register address
  54 */
  55#define EISA_SYSCTL             (IDENT_ADDR + 0x1E0000000UL)
  56
  57/*
  58 * "spare" register address
  59 */
  60#define EISA_SPARE              (IDENT_ADDR + 0x1F0000000UL)
  61
  62/*
  63 * EISA memory address offset
  64 */
  65#define EISA_MEM                (IDENT_ADDR + 0x200000000UL)
  66
  67/*
  68 * EISA IO address offset
  69 */
  70#define EISA_IO                 (IDENT_ADDR + 0x300000000UL)
  71
  72
  73#ifdef __KERNEL__
  74
  75#ifndef __EXTERN_INLINE
  76#define __EXTERN_INLINE extern inline
  77#define __IO_EXTERN_INLINE
  78#endif
  79
  80/*
  81 * Handle the "host address register". This needs to be set
  82 * to the high 7 bits of the EISA address.  This is also needed
  83 * for EISA IO addresses, which are only 16 bits wide (the
  84 * hae needs to be set to 0).
  85 *
  86 * HAE isn't needed for the local IO operations, though.
  87 */
  88
  89#define JENSEN_HAE_ADDRESS      EISA_HAE
  90#define JENSEN_HAE_MASK         0x1ffffff
  91
  92__EXTERN_INLINE void jensen_set_hae(unsigned long addr)
  93{
  94        /* hae on the Jensen is bits 31:25 shifted right */
  95        addr >>= 25;
  96        if (addr != alpha_mv.hae_cache)
  97                set_hae(addr);
  98}
  99
 100#define vuip    volatile unsigned int *
 101
 102/*
 103 * IO functions
 104 *
 105 * The "local" functions are those that don't go out to the EISA bus,
 106 * but instead act on the VL82C106 chip directly.. This is mainly the
 107 * keyboard, RTC,  printer and first two serial lines..
 108 *
 109 * The local stuff makes for some complications, but it seems to be
 110 * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
 111 * convinced that I need one of the newer machines.
 112 */
 113
 114static inline unsigned int jensen_local_inb(unsigned long addr)
 115{
 116        return 0xff & *(vuip)((addr << 9) + EISA_VL82C106);
 117}
 118
 119static inline void jensen_local_outb(u8 b, unsigned long addr)
 120{
 121        *(vuip)((addr << 9) + EISA_VL82C106) = b;
 122        mb();
 123}
 124
 125static inline unsigned int jensen_bus_inb(unsigned long addr)
 126{
 127        long result;
 128
 129        jensen_set_hae(0);
 130        result = *(volatile int *)((addr << 7) + EISA_IO + 0x00);
 131        return __kernel_extbl(result, addr & 3);
 132}
 133
 134static inline void jensen_bus_outb(u8 b, unsigned long addr)
 135{
 136        jensen_set_hae(0);
 137        *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
 138        mb();
 139}
 140
 141/*
 142 * It seems gcc is not very good at optimizing away logical
 143 * operations that result in operations across inline functions.
 144 * Which is why this is a macro.
 145 */
 146
 147#define jensen_is_local(addr) ( \
 148/* keyboard */  (addr == 0x60 || addr == 0x64) || \
 149/* RTC */       (addr == 0x170 || addr == 0x171) || \
 150/* mb COM2 */   (addr >= 0x2f8 && addr <= 0x2ff) || \
 151/* mb LPT1 */   (addr >= 0x3bc && addr <= 0x3be) || \
 152/* mb COM2 */   (addr >= 0x3f8 && addr <= 0x3ff))
 153
 154__EXTERN_INLINE u8 jensen_inb(unsigned long addr)
 155{
 156        if (jensen_is_local(addr))
 157                return jensen_local_inb(addr);
 158        else
 159                return jensen_bus_inb(addr);
 160}
 161
 162__EXTERN_INLINE void jensen_outb(u8 b, unsigned long addr)
 163{
 164        if (jensen_is_local(addr))
 165                jensen_local_outb(b, addr);
 166        else
 167                jensen_bus_outb(b, addr);
 168}
 169
 170__EXTERN_INLINE u16 jensen_inw(unsigned long addr)
 171{
 172        long result;
 173
 174        jensen_set_hae(0);
 175        result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
 176        result >>= (addr & 3) * 8;
 177        return 0xffffUL & result;
 178}
 179
 180__EXTERN_INLINE u32 jensen_inl(unsigned long addr)
 181{
 182        jensen_set_hae(0);
 183        return *(vuip) ((addr << 7) + EISA_IO + 0x60);
 184}
 185
 186__EXTERN_INLINE void jensen_outw(u16 b, unsigned long addr)
 187{
 188        jensen_set_hae(0);
 189        *(vuip) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
 190        mb();
 191}
 192
 193__EXTERN_INLINE void jensen_outl(u32 b, unsigned long addr)
 194{
 195        jensen_set_hae(0);
 196        *(vuip) ((addr << 7) + EISA_IO + 0x60) = b;
 197        mb();
 198}
 199
 200/*
 201 * Memory functions.
 202 */
 203
 204__EXTERN_INLINE u8 jensen_readb(const volatile void __iomem *xaddr)
 205{
 206        unsigned long addr = (unsigned long) xaddr;
 207        long result;
 208
 209        jensen_set_hae(addr);
 210        addr &= JENSEN_HAE_MASK;
 211        result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
 212        result >>= (addr & 3) * 8;
 213        return 0xffUL & result;
 214}
 215
 216__EXTERN_INLINE u16 jensen_readw(const volatile void __iomem *xaddr)
 217{
 218        unsigned long addr = (unsigned long) xaddr;
 219        long result;
 220
 221        jensen_set_hae(addr);
 222        addr &= JENSEN_HAE_MASK;
 223        result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
 224        result >>= (addr & 3) * 8;
 225        return 0xffffUL & result;
 226}
 227
 228__EXTERN_INLINE u32 jensen_readl(const volatile void __iomem *xaddr)
 229{
 230        unsigned long addr = (unsigned long) xaddr;
 231        jensen_set_hae(addr);
 232        addr &= JENSEN_HAE_MASK;
 233        return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
 234}
 235
 236__EXTERN_INLINE u64 jensen_readq(const volatile void __iomem *xaddr)
 237{
 238        unsigned long addr = (unsigned long) xaddr;
 239        unsigned long r0, r1;
 240
 241        jensen_set_hae(addr);
 242        addr &= JENSEN_HAE_MASK;
 243        addr = (addr << 7) + EISA_MEM + 0x60;
 244        r0 = *(vuip) (addr);
 245        r1 = *(vuip) (addr + (4 << 7));
 246        return r1 << 32 | r0;
 247}
 248
 249__EXTERN_INLINE void jensen_writeb(u8 b, volatile void __iomem *xaddr)
 250{
 251        unsigned long addr = (unsigned long) xaddr;
 252        jensen_set_hae(addr);
 253        addr &= JENSEN_HAE_MASK;
 254        *(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
 255}
 256
 257__EXTERN_INLINE void jensen_writew(u16 b, volatile void __iomem *xaddr)
 258{
 259        unsigned long addr = (unsigned long) xaddr;
 260        jensen_set_hae(addr);
 261        addr &= JENSEN_HAE_MASK;
 262        *(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
 263}
 264
 265__EXTERN_INLINE void jensen_writel(u32 b, volatile void __iomem *xaddr)
 266{
 267        unsigned long addr = (unsigned long) xaddr;
 268        jensen_set_hae(addr);
 269        addr &= JENSEN_HAE_MASK;
 270        *(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
 271}
 272
 273__EXTERN_INLINE void jensen_writeq(u64 b, volatile void __iomem *xaddr)
 274{
 275        unsigned long addr = (unsigned long) xaddr;
 276        jensen_set_hae(addr);
 277        addr &= JENSEN_HAE_MASK;
 278        addr = (addr << 7) + EISA_MEM + 0x60;
 279        *(vuip) (addr) = b;
 280        *(vuip) (addr + (4 << 7)) = b >> 32;
 281}
 282
 283__EXTERN_INLINE void __iomem *jensen_ioportmap(unsigned long addr)
 284{
 285        return (void __iomem *)addr;
 286}
 287
 288__EXTERN_INLINE void __iomem *jensen_ioremap(unsigned long addr,
 289                                             unsigned long size)
 290{
 291        return (void __iomem *)(addr + 0x100000000ul);
 292}
 293
 294__EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
 295{
 296        return (long)addr >= 0;
 297}
 298
 299__EXTERN_INLINE int jensen_is_mmio(const volatile void __iomem *addr)
 300{
 301        return (unsigned long)addr >= 0x100000000ul;
 302}
 303
 304/* New-style ioread interface.  All the routines are so ugly for Jensen
 305   that it doesn't make sense to merge them.  */
 306
 307#define IOPORT(OS, NS)                                                  \
 308__EXTERN_INLINE unsigned int jensen_ioread##NS(const void __iomem *xaddr)       \
 309{                                                                       \
 310        if (jensen_is_mmio(xaddr))                                      \
 311                return jensen_read##OS(xaddr - 0x100000000ul);          \
 312        else                                                            \
 313                return jensen_in##OS((unsigned long)xaddr);             \
 314}                                                                       \
 315__EXTERN_INLINE void jensen_iowrite##NS(u##NS b, void __iomem *xaddr)   \
 316{                                                                       \
 317        if (jensen_is_mmio(xaddr))                                      \
 318                jensen_write##OS(b, xaddr - 0x100000000ul);             \
 319        else                                                            \
 320                jensen_out##OS(b, (unsigned long)xaddr);                \
 321}
 322
 323IOPORT(b, 8)
 324IOPORT(w, 16)
 325IOPORT(l, 32)
 326
 327#undef IOPORT
 328
 329#undef vuip
 330
 331#undef __IO_PREFIX
 332#define __IO_PREFIX             jensen
 333#define jensen_trivial_rw_bw    0
 334#define jensen_trivial_rw_lq    0
 335#define jensen_trivial_io_bw    0
 336#define jensen_trivial_io_lq    0
 337#define jensen_trivial_iounmap  1
 338#include <asm/io_trivial.h>
 339
 340#ifdef __IO_EXTERN_INLINE
 341#undef __EXTERN_INLINE
 342#undef __IO_EXTERN_INLINE
 343#endif
 344
 345#endif /* __KERNEL__ */
 346
 347#endif /* __ALPHA_JENSEN_H */
 348