123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- /*
- * arch/sh/boards/se/73180/io.c
- *
- * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
- * Based on arch/sh/boards/se/7300/io.c
- *
- * I/O routine for SH-Mobile3 73180 SolutionEngine.
- *
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <asm/mach/se73180.h>
- #include <asm/io.h>
- #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
- struct iop {
- unsigned long start, end;
- unsigned long base;
- struct iop *(*check) (struct iop * p, unsigned long port);
- unsigned char (*inb) (struct iop * p, unsigned long port);
- unsigned short (*inw) (struct iop * p, unsigned long port);
- void (*outb) (struct iop * p, unsigned char value, unsigned long port);
- void (*outw) (struct iop * p, unsigned short value, unsigned long port);
- };
- struct iop *
- simple_check(struct iop *p, unsigned long port)
- {
- if ((p->start <= port) && (port <= p->end))
- return p;
- else
- badio(check, port);
- }
- struct iop *
- ide_check(struct iop *p, unsigned long port)
- {
- if (((0x1f0 <= port) && (port <= 0x1f7)) || (port == 0x3f7))
- return p;
- return NULL;
- }
- unsigned char
- simple_inb(struct iop *p, unsigned long port)
- {
- return *(unsigned char *) (p->base + port);
- }
- unsigned short
- simple_inw(struct iop *p, unsigned long port)
- {
- return *(unsigned short *) (p->base + port);
- }
- void
- simple_outb(struct iop *p, unsigned char value, unsigned long port)
- {
- *(unsigned char *) (p->base + port) = value;
- }
- void
- simple_outw(struct iop *p, unsigned short value, unsigned long port)
- {
- *(unsigned short *) (p->base + port) = value;
- }
- unsigned char
- pcc_inb(struct iop *p, unsigned long port)
- {
- unsigned long addr = p->base + port + 0x40000;
- unsigned long v;
- if (port & 1)
- addr += 0x00400000;
- v = *(volatile unsigned char *) addr;
- return v;
- }
- void
- pcc_outb(struct iop *p, unsigned char value, unsigned long port)
- {
- unsigned long addr = p->base + port + 0x40000;
- if (port & 1)
- addr += 0x00400000;
- *(volatile unsigned char *) addr = value;
- }
- unsigned char
- bad_inb(struct iop *p, unsigned long port)
- {
- badio(inb, port);
- }
- void
- bad_outb(struct iop *p, unsigned char value, unsigned long port)
- {
- badio(inw, port);
- }
- /* MSTLANEX01 LAN at 0xb400:0000 */
- static struct iop laniop = {
- .start = 0x300,
- .end = 0x30f,
- .base = 0xb4000000,
- .check = simple_check,
- .inb = simple_inb,
- .inw = simple_inw,
- .outb = simple_outb,
- .outw = simple_outw,
- };
- /* NE2000 pc card NIC */
- static struct iop neiop = {
- .start = 0x280,
- .end = 0x29f,
- .base = 0xb0600000 + 0x80, /* soft 0x280 -> hard 0x300 */
- .check = simple_check,
- .inb = pcc_inb,
- .inw = simple_inw,
- .outb = pcc_outb,
- .outw = simple_outw,
- };
- /* CF in CF slot */
- static struct iop cfiop = {
- .base = 0xb0600000,
- .check = ide_check,
- .inb = pcc_inb,
- .inw = simple_inw,
- .outb = pcc_outb,
- .outw = simple_outw,
- };
- static __inline__ struct iop *
- port2iop(unsigned long port)
- {
- if (0) ;
- #if defined(CONFIG_SMC91111)
- else if (laniop.check(&laniop, port))
- return &laniop;
- #endif
- #if defined(CONFIG_NE2000)
- else if (neiop.check(&neiop, port))
- return &neiop;
- #endif
- #if defined(CONFIG_IDE)
- else if (cfiop.check(&cfiop, port))
- return &cfiop;
- #endif
- else
- return &neiop; /* fallback */
- }
- static inline void
- delay(void)
- {
- ctrl_inw(0xac000000);
- ctrl_inw(0xac000000);
- }
- unsigned char
- sh73180se_inb(unsigned long port)
- {
- struct iop *p = port2iop(port);
- return (p->inb) (p, port);
- }
- unsigned char
- sh73180se_inb_p(unsigned long port)
- {
- unsigned char v = sh73180se_inb(port);
- delay();
- return v;
- }
- unsigned short
- sh73180se_inw(unsigned long port)
- {
- struct iop *p = port2iop(port);
- return (p->inw) (p, port);
- }
- unsigned int
- sh73180se_inl(unsigned long port)
- {
- badio(inl, port);
- }
- void
- sh73180se_outb(unsigned char value, unsigned long port)
- {
- struct iop *p = port2iop(port);
- (p->outb) (p, value, port);
- }
- void
- sh73180se_outb_p(unsigned char value, unsigned long port)
- {
- sh73180se_outb(value, port);
- delay();
- }
- void
- sh73180se_outw(unsigned short value, unsigned long port)
- {
- struct iop *p = port2iop(port);
- (p->outw) (p, value, port);
- }
- void
- sh73180se_outl(unsigned int value, unsigned long port)
- {
- badio(outl, port);
- }
- void
- sh73180se_insb(unsigned long port, void *addr, unsigned long count)
- {
- unsigned char *a = addr;
- struct iop *p = port2iop(port);
- while (count--)
- *a++ = (p->inb) (p, port);
- }
- void
- sh73180se_insw(unsigned long port, void *addr, unsigned long count)
- {
- unsigned short *a = addr;
- struct iop *p = port2iop(port);
- while (count--)
- *a++ = (p->inw) (p, port);
- }
- void
- sh73180se_insl(unsigned long port, void *addr, unsigned long count)
- {
- badio(insl, port);
- }
- void
- sh73180se_outsb(unsigned long port, const void *addr, unsigned long count)
- {
- unsigned char *a = (unsigned char *) addr;
- struct iop *p = port2iop(port);
- while (count--)
- (p->outb) (p, *a++, port);
- }
- void
- sh73180se_outsw(unsigned long port, const void *addr, unsigned long count)
- {
- unsigned short *a = (unsigned short *) addr;
- struct iop *p = port2iop(port);
- while (count--)
- (p->outw) (p, *a++, port);
- }
- void
- sh73180se_outsl(unsigned long port, const void *addr, unsigned long count)
- {
- badio(outsw, port);
- }
|