1/* 2 * linux/arch/sh/kernel/io_cat68701.c 3 * 4 * Copyright (C) 2000 Niibe Yutaka 5 * 2001 Yutaro Ebihara 6 * 7 * I/O routine and setup routines for A-ONE Corp CAT-68701 SH7708 Board 8 * 9 * This file is subject to the terms and conditions of the GNU General Public 10 * License. See the file "COPYING" in the main directory of this archive 11 * for more details. 12 * 13 */ 14 15#include <asm/io.h> 16#include <asm/machvec.h> 17#include <linux/config.h> 18#include <linux/module.h> 19 20#define SH3_PCMCIA_BUG_WORKAROUND 1 21#define DUMMY_READ_AREA6 0xba000000 22 23#define PORT2ADDR(x) (cat68701_isa_port2addr(x)) 24 25static inline void delay(void) 26{ 27 ctrl_inw(0xa0000000); 28} 29 30unsigned char cat68701_inb(unsigned long port) 31{ 32 return *(volatile unsigned char*)PORT2ADDR(port); 33} 34 35unsigned short cat68701_inw(unsigned long port) 36{ 37 return *(volatile unsigned short*)PORT2ADDR(port); 38} 39 40unsigned int cat68701_inl(unsigned long port) 41{ 42 return *(volatile unsigned long*)PORT2ADDR(port); 43} 44 45unsigned char cat68701_inb_p(unsigned long port) 46{ 47 unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); 48 49 delay(); 50 return v; 51} 52 53unsigned short cat68701_inw_p(unsigned long port) 54{ 55 unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); 56 57 delay(); 58 return v; 59} 60 61unsigned int cat68701_inl_p(unsigned long port) 62{ 63 unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); 64 65 delay(); 66 return v; 67} 68 69void cat68701_insb(unsigned long port, void *buffer, unsigned long count) 70{ 71 unsigned char *buf=buffer; 72 while(count--) *buf++=inb(port); 73} 74 75void cat68701_insw(unsigned long port, void *buffer, unsigned long count) 76{ 77 unsigned short *buf=buffer; 78 while(count--) *buf++=inw(port); 79#ifdef SH3_PCMCIA_BUG_WORKAROUND 80 ctrl_inb (DUMMY_READ_AREA6); 81#endif 82} 83 84void cat68701_insl(unsigned long port, void *buffer, unsigned long count) 85{ 86 unsigned long *buf=buffer; 87 while(count--) *buf++=inl(port); 88#ifdef SH3_PCMCIA_BUG_WORKAROUND 89 ctrl_inb (DUMMY_READ_AREA6); 90#endif 91} 92 93void cat68701_outb(unsigned char b, unsigned long port) 94{ 95 *(volatile unsigned char*)PORT2ADDR(port) = b; 96} 97 98void cat68701_outw(unsigned short b, unsigned long port) 99{ 100 *(volatile unsigned short*)PORT2ADDR(port) = b; 101} 102 103void cat68701_outl(unsigned int b, unsigned long port) 104{ 105 *(volatile unsigned long*)PORT2ADDR(port) = b; 106} 107 108void cat68701_outb_p(unsigned char b, unsigned long port) 109{ 110 *(volatile unsigned char*)PORT2ADDR(port) = b; 111 delay(); 112} 113 114void cat68701_outw_p(unsigned short b, unsigned long port) 115{ 116 *(volatile unsigned short*)PORT2ADDR(port) = b; 117 delay(); 118} 119 120void cat68701_outl_p(unsigned int b, unsigned long port) 121{ 122 *(volatile unsigned long*)PORT2ADDR(port) = b; 123 delay(); 124} 125 126void cat68701_outsb(unsigned long port, const void *buffer, unsigned long count) 127{ 128 const unsigned char *buf=buffer; 129 while(count--) outb(*buf++, port); 130} 131 132void cat68701_outsw(unsigned long port, const void *buffer, unsigned long count) 133{ 134 const unsigned short *buf=buffer; 135 while(count--) outw(*buf++, port); 136#ifdef SH3_PCMCIA_BUG_WORKAROUND 137 ctrl_inb (DUMMY_READ_AREA6); 138#endif 139} 140 141void cat68701_outsl(unsigned long port, const void *buffer, unsigned long count) 142{ 143 const unsigned long *buf=buffer; 144 while(count--) outl(*buf++, port); 145#ifdef SH3_PCMCIA_BUG_WORKAROUND 146 ctrl_inb (DUMMY_READ_AREA6); 147#endif 148} 149 150unsigned char cat68701_readb(unsigned long addr) 151{ 152 return *(volatile unsigned char*)addr; 153} 154 155unsigned short cat68701_readw(unsigned long addr) 156{ 157 return *(volatile unsigned short*)addr; 158} 159 160unsigned int cat68701_readl(unsigned long addr) 161{ 162 return *(volatile unsigned long*)addr; 163} 164 165void cat68701_writeb(unsigned char b, unsigned long addr) 166{ 167 *(volatile unsigned char*)addr = b; 168} 169 170void cat68701_writew(unsigned short b, unsigned long addr) 171{ 172 *(volatile unsigned short*)addr = b; 173} 174 175void cat68701_writel(unsigned int b, unsigned long addr) 176{ 177 *(volatile unsigned long*)addr = b; 178} 179 180void * cat68701_ioremap(unsigned long offset, unsigned long size) 181{ 182 return (void *) P2SEGADDR(offset); 183} 184EXPORT_SYMBOL(cat68701_ioremap); 185 186void cat68701_iounmap(void *addr) 187{ 188} 189EXPORT_SYMBOL(cat68701_iounmap); 190 191unsigned long cat68701_isa_port2addr(unsigned long offset) 192{ 193 /* CompactFlash (IDE) */ 194 if(((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6)) 195 return 0xba000000 + offset; 196 197 /* INPUT PORT */ 198 if((offset >= 0x3fc) && (offset <= 0x3fd)) 199 return 0xb4007000 + offset; 200 201 /* OUTPUT PORT */ 202 if((offset >= 0x3fe) && (offset <= 0x3ff)) 203 return 0xb4007400 + offset; 204 205 return offset + 0xb4000000; /* other I/O (EREA 5)*/ 206} 207 208 209int cat68701_irq_demux(int irq) 210{ 211 if(irq==13) return 14; 212 if(irq==7) return 10; 213 return irq; 214} 215 216 217 218/*-------------------------------------------------------*/ 219 220void setup_cat68701(){ 221 /* dummy read erea5 (CS8900A) */ 222} 223 224void init_cat68701_IRQ(){ 225 make_imask_irq(10); 226 make_imask_irq(14); 227} 228 229#ifdef CONFIG_HEARTBEAT 230#include <linux/sched.h> 231void heartbeat_cat68701() 232{ 233 static unsigned int cnt = 0, period = 0 , bit = 0; 234 cnt += 1; 235 if (cnt < period) { 236 return; 237 } 238 cnt = 0; 239 240 /* Go through the points (roughly!): 241 * f(0)=10, f(1)=16, f(2)=20, f(5)=35,f(inf)->110 242 */ 243 period = 110 - ( (300<<FSHIFT)/ 244 ((avenrun[0]/5) + (3<<FSHIFT)) ); 245 246 if(bit){ bit=0; }else{ bit=1; } 247 outw(bit<<15,0x3fe); 248} 249#endif /* CONFIG_HEARTBEAT */ 250