Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __ALPHA_JENSEN_H
0003 #define __ALPHA_JENSEN_H
0004 
0005 #include <asm/compiler.h>
0006 
0007 /*
0008  * Defines for the AlphaPC EISA IO and memory address space.
0009  */
0010 
0011 /*
0012  * NOTE! The memory operations do not set any memory barriers, as it's
0013  * not needed for cases like a frame buffer that is essentially memory-like.
0014  * You need to do them by hand if the operations depend on ordering.
0015  *
0016  * Similarly, the port IO operations do a "mb" only after a write operation:
0017  * if an mb is needed before (as in the case of doing memory mapped IO
0018  * first, and then a port IO operation to the same device), it needs to be
0019  * done by hand.
0020  *
0021  * After the above has bitten me 100 times, I'll give up and just do the
0022  * mb all the time, but right now I'm hoping this will work out.  Avoiding
0023  * mb's may potentially be a noticeable speed improvement, but I can't
0024  * honestly say I've tested it.
0025  *
0026  * Handling interrupts that need to do mb's to synchronize to non-interrupts
0027  * is another fun race area.  Don't do it (because if you do, I'll have to
0028  * do *everything* with interrupts disabled, ugh).
0029  */
0030 
0031 /*
0032  * EISA Interrupt Acknowledge address
0033  */
0034 #define EISA_INTA       (IDENT_ADDR + 0x100000000UL)
0035 
0036 /*
0037  * FEPROM addresses
0038  */
0039 #define EISA_FEPROM0        (IDENT_ADDR + 0x180000000UL)
0040 #define EISA_FEPROM1        (IDENT_ADDR + 0x1A0000000UL)
0041 
0042 /*
0043  * VL82C106 base address
0044  */
0045 #define EISA_VL82C106       (IDENT_ADDR + 0x1C0000000UL)
0046 
0047 /*
0048  * EISA "Host Address Extension" address (bits 25-31 of the EISA address)
0049  */
0050 #define EISA_HAE        (IDENT_ADDR + 0x1D0000000UL)
0051 
0052 /*
0053  * "SYSCTL" register address
0054  */
0055 #define EISA_SYSCTL     (IDENT_ADDR + 0x1E0000000UL)
0056 
0057 /*
0058  * "spare" register address
0059  */
0060 #define EISA_SPARE      (IDENT_ADDR + 0x1F0000000UL)
0061 
0062 /*
0063  * EISA memory address offset
0064  */
0065 #define EISA_MEM        (IDENT_ADDR + 0x200000000UL)
0066 
0067 /*
0068  * EISA IO address offset
0069  */
0070 #define EISA_IO         (IDENT_ADDR + 0x300000000UL)
0071 
0072 
0073 #ifdef __KERNEL__
0074 
0075 #ifndef __EXTERN_INLINE
0076 #define __EXTERN_INLINE extern inline
0077 #define __IO_EXTERN_INLINE
0078 #endif
0079 
0080 /*
0081  * Handle the "host address register". This needs to be set
0082  * to the high 7 bits of the EISA address.  This is also needed
0083  * for EISA IO addresses, which are only 16 bits wide (the
0084  * hae needs to be set to 0).
0085  *
0086  * HAE isn't needed for the local IO operations, though.
0087  */
0088 
0089 #define JENSEN_HAE_ADDRESS  EISA_HAE
0090 #define JENSEN_HAE_MASK     0x1ffffff
0091 
0092 __EXTERN_INLINE void jensen_set_hae(unsigned long addr)
0093 {
0094     /* hae on the Jensen is bits 31:25 shifted right */
0095     addr >>= 25;
0096     if (addr != alpha_mv.hae_cache)
0097         set_hae(addr);
0098 }
0099 
0100 #define vuip    volatile unsigned int *
0101 
0102 /*
0103  * IO functions
0104  *
0105  * The "local" functions are those that don't go out to the EISA bus,
0106  * but instead act on the VL82C106 chip directly.. This is mainly the
0107  * keyboard, RTC,  printer and first two serial lines..
0108  *
0109  * The local stuff makes for some complications, but it seems to be
0110  * gone in the PCI version. I hope I can get DEC suckered^H^H^H^H^H^H^H^H
0111  * convinced that I need one of the newer machines.
0112  */
0113 
0114 __EXTERN_INLINE unsigned int jensen_local_inb(unsigned long addr)
0115 {
0116     return 0xff & *(vuip)((addr << 9) + EISA_VL82C106);
0117 }
0118 
0119 __EXTERN_INLINE void jensen_local_outb(u8 b, unsigned long addr)
0120 {
0121     *(vuip)((addr << 9) + EISA_VL82C106) = b;
0122     mb();
0123 }
0124 
0125 __EXTERN_INLINE unsigned int jensen_bus_inb(unsigned long addr)
0126 {
0127     long result;
0128 
0129     jensen_set_hae(0);
0130     result = *(volatile int *)((addr << 7) + EISA_IO + 0x00);
0131     return __kernel_extbl(result, addr & 3);
0132 }
0133 
0134 __EXTERN_INLINE void jensen_bus_outb(u8 b, unsigned long addr)
0135 {
0136     jensen_set_hae(0);
0137     *(vuip)((addr << 7) + EISA_IO + 0x00) = b * 0x01010101;
0138     mb();
0139 }
0140 
0141 /*
0142  * It seems gcc is not very good at optimizing away logical
0143  * operations that result in operations across inline functions.
0144  * Which is why this is a macro.
0145  */
0146 
0147 #define jensen_is_local(addr) ( \
0148 /* keyboard */  (addr == 0x60 || addr == 0x64) || \
0149 /* RTC */   (addr == 0x170 || addr == 0x171) || \
0150 /* mb COM2 */   (addr >= 0x2f8 && addr <= 0x2ff) || \
0151 /* mb LPT1 */   (addr >= 0x3bc && addr <= 0x3be) || \
0152 /* mb COM2 */   (addr >= 0x3f8 && addr <= 0x3ff))
0153 
0154 __EXTERN_INLINE u8 jensen_inb(unsigned long addr)
0155 {
0156     if (jensen_is_local(addr))
0157         return jensen_local_inb(addr);
0158     else
0159         return jensen_bus_inb(addr);
0160 }
0161 
0162 __EXTERN_INLINE void jensen_outb(u8 b, unsigned long addr)
0163 {
0164     if (jensen_is_local(addr))
0165         jensen_local_outb(b, addr);
0166     else
0167         jensen_bus_outb(b, addr);
0168 }
0169 
0170 __EXTERN_INLINE u16 jensen_inw(unsigned long addr)
0171 {
0172     long result;
0173 
0174     jensen_set_hae(0);
0175     result = *(volatile int *) ((addr << 7) + EISA_IO + 0x20);
0176     result >>= (addr & 3) * 8;
0177     return 0xffffUL & result;
0178 }
0179 
0180 __EXTERN_INLINE u32 jensen_inl(unsigned long addr)
0181 {
0182     jensen_set_hae(0);
0183     return *(vuip) ((addr << 7) + EISA_IO + 0x60);
0184 }
0185 
0186 __EXTERN_INLINE void jensen_outw(u16 b, unsigned long addr)
0187 {
0188     jensen_set_hae(0);
0189     *(vuip) ((addr << 7) + EISA_IO + 0x20) = b * 0x00010001;
0190     mb();
0191 }
0192 
0193 __EXTERN_INLINE void jensen_outl(u32 b, unsigned long addr)
0194 {
0195     jensen_set_hae(0);
0196     *(vuip) ((addr << 7) + EISA_IO + 0x60) = b;
0197     mb();
0198 }
0199 
0200 /*
0201  * Memory functions.
0202  */
0203 
0204 __EXTERN_INLINE u8 jensen_readb(const volatile void __iomem *xaddr)
0205 {
0206     unsigned long addr = (unsigned long) xaddr;
0207     long result;
0208 
0209     jensen_set_hae(addr);
0210     addr &= JENSEN_HAE_MASK;
0211     result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x00);
0212     result >>= (addr & 3) * 8;
0213     return 0xffUL & result;
0214 }
0215 
0216 __EXTERN_INLINE u16 jensen_readw(const volatile void __iomem *xaddr)
0217 {
0218     unsigned long addr = (unsigned long) xaddr;
0219     long result;
0220 
0221     jensen_set_hae(addr);
0222     addr &= JENSEN_HAE_MASK;
0223     result = *(volatile int *) ((addr << 7) + EISA_MEM + 0x20);
0224     result >>= (addr & 3) * 8;
0225     return 0xffffUL & result;
0226 }
0227 
0228 __EXTERN_INLINE u32 jensen_readl(const volatile void __iomem *xaddr)
0229 {
0230     unsigned long addr = (unsigned long) xaddr;
0231     jensen_set_hae(addr);
0232     addr &= JENSEN_HAE_MASK;
0233     return *(vuip) ((addr << 7) + EISA_MEM + 0x60);
0234 }
0235 
0236 __EXTERN_INLINE u64 jensen_readq(const volatile void __iomem *xaddr)
0237 {
0238     unsigned long addr = (unsigned long) xaddr;
0239     unsigned long r0, r1;
0240 
0241     jensen_set_hae(addr);
0242     addr &= JENSEN_HAE_MASK;
0243     addr = (addr << 7) + EISA_MEM + 0x60;
0244     r0 = *(vuip) (addr);
0245     r1 = *(vuip) (addr + (4 << 7));
0246     return r1 << 32 | r0;
0247 }
0248 
0249 __EXTERN_INLINE void jensen_writeb(u8 b, volatile void __iomem *xaddr)
0250 {
0251     unsigned long addr = (unsigned long) xaddr;
0252     jensen_set_hae(addr);
0253     addr &= JENSEN_HAE_MASK;
0254     *(vuip) ((addr << 7) + EISA_MEM + 0x00) = b * 0x01010101;
0255 }
0256 
0257 __EXTERN_INLINE void jensen_writew(u16 b, volatile void __iomem *xaddr)
0258 {
0259     unsigned long addr = (unsigned long) xaddr;
0260     jensen_set_hae(addr);
0261     addr &= JENSEN_HAE_MASK;
0262     *(vuip) ((addr << 7) + EISA_MEM + 0x20) = b * 0x00010001;
0263 }
0264 
0265 __EXTERN_INLINE void jensen_writel(u32 b, volatile void __iomem *xaddr)
0266 {
0267     unsigned long addr = (unsigned long) xaddr;
0268     jensen_set_hae(addr);
0269     addr &= JENSEN_HAE_MASK;
0270     *(vuip) ((addr << 7) + EISA_MEM + 0x60) = b;
0271 }
0272 
0273 __EXTERN_INLINE void jensen_writeq(u64 b, volatile void __iomem *xaddr)
0274 {
0275     unsigned long addr = (unsigned long) xaddr;
0276     jensen_set_hae(addr);
0277     addr &= JENSEN_HAE_MASK;
0278     addr = (addr << 7) + EISA_MEM + 0x60;
0279     *(vuip) (addr) = b;
0280     *(vuip) (addr + (4 << 7)) = b >> 32;
0281 }
0282 
0283 __EXTERN_INLINE void __iomem *jensen_ioportmap(unsigned long addr)
0284 {
0285     return (void __iomem *)addr;
0286 }
0287 
0288 __EXTERN_INLINE void __iomem *jensen_ioremap(unsigned long addr,
0289                          unsigned long size)
0290 {
0291     return (void __iomem *)(addr + 0x100000000ul);
0292 }
0293 
0294 __EXTERN_INLINE int jensen_is_ioaddr(unsigned long addr)
0295 {
0296     return (long)addr >= 0;
0297 }
0298 
0299 __EXTERN_INLINE int jensen_is_mmio(const volatile void __iomem *addr)
0300 {
0301     return (unsigned long)addr >= 0x100000000ul;
0302 }
0303 
0304 /* New-style ioread interface.  All the routines are so ugly for Jensen
0305    that it doesn't make sense to merge them.  */
0306 
0307 #define IOPORT(OS, NS)                          \
0308 __EXTERN_INLINE unsigned int jensen_ioread##NS(const void __iomem *xaddr)   \
0309 {                                   \
0310     if (jensen_is_mmio(xaddr))                  \
0311         return jensen_read##OS(xaddr - 0x100000000ul);      \
0312     else                                \
0313         return jensen_in##OS((unsigned long)xaddr);     \
0314 }                                   \
0315 __EXTERN_INLINE void jensen_iowrite##NS(u##NS b, void __iomem *xaddr)   \
0316 {                                   \
0317     if (jensen_is_mmio(xaddr))                  \
0318         jensen_write##OS(b, xaddr - 0x100000000ul);     \
0319     else                                \
0320         jensen_out##OS(b, (unsigned long)xaddr);        \
0321 }
0322 
0323 IOPORT(b, 8)
0324 IOPORT(w, 16)
0325 IOPORT(l, 32)
0326 
0327 #undef IOPORT
0328 
0329 #undef vuip
0330 
0331 #undef __IO_PREFIX
0332 #define __IO_PREFIX     jensen
0333 #define jensen_trivial_rw_bw    0
0334 #define jensen_trivial_rw_lq    0
0335 #define jensen_trivial_io_bw    0
0336 #define jensen_trivial_io_lq    0
0337 #define jensen_trivial_iounmap  1
0338 #include <asm/io_trivial.h>
0339 
0340 #ifdef __IO_EXTERN_INLINE
0341 #undef __EXTERN_INLINE
0342 #undef __IO_EXTERN_INLINE
0343 #endif
0344 
0345 #endif /* __KERNEL__ */
0346 
0347 #endif /* __ALPHA_JENSEN_H */