Path: blob/master/arch/m32r/platforms/m32700ut/io.c
10819 views
/*1* linux/arch/m32r/platforms/m32700ut/io.c2*3* Typical I/O routines for M32700UT board.4*5* Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,6* Hitoshi Yamamoto, Takeo Takahashi7*8* This file is subject to the terms and conditions of the GNU General9* Public License. See the file "COPYING" in the main directory of this10* archive for more details.11*/1213#include <asm/m32r.h>14#include <asm/page.h>15#include <asm/io.h>16#include <asm/byteorder.h>1718#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)19#include <linux/types.h>2021#define M32R_PCC_IOMAP_SIZE 0x10002223#define M32R_PCC_IOSTART0 0x100024#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)2526extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);27extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);28extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);29extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);30#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */3132#define PORT2ADDR(port) _port2addr(port)33#define PORT2ADDR_USB(port) _port2addr_usb(port)3435static inline void *_port2addr(unsigned long port)36{37return (void *)(port | NONCACHE_OFFSET);38}3940#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)41static inline void *__port2addr_ata(unsigned long port)42{43static int dummy_reg;4445switch (port) {46case 0x1f0: return (void *)(0x0c002000 | NONCACHE_OFFSET);47case 0x1f1: return (void *)(0x0c012800 | NONCACHE_OFFSET);48case 0x1f2: return (void *)(0x0c012002 | NONCACHE_OFFSET);49case 0x1f3: return (void *)(0x0c012802 | NONCACHE_OFFSET);50case 0x1f4: return (void *)(0x0c012004 | NONCACHE_OFFSET);51case 0x1f5: return (void *)(0x0c012804 | NONCACHE_OFFSET);52case 0x1f6: return (void *)(0x0c012006 | NONCACHE_OFFSET);53case 0x1f7: return (void *)(0x0c012806 | NONCACHE_OFFSET);54case 0x3f6: return (void *)(0x0c01200e | NONCACHE_OFFSET);55default: return (void *)&dummy_reg;56}57}58#endif5960/*61* M32700UT-LAN is located in the extended bus space62* from 0x10000000 to 0x13ffffff on physical address.63* The base address of LAN controller(LAN91C111) is 0x300.64*/65#define LAN_IOSTART (0x300 | NONCACHE_OFFSET)66#define LAN_IOEND (0x320 | NONCACHE_OFFSET)67static inline void *_port2addr_ne(unsigned long port)68{69return (void *)(port + 0x10000000);70}71static inline void *_port2addr_usb(unsigned long port)72{73return (void *)((port & 0x0f) + NONCACHE_OFFSET + 0x10303000);74}7576static inline void delay(void)77{78__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");79}8081/*82* NIC I/O function83*/8485#define PORT2ADDR_NE(port) _port2addr_ne(port)8687static inline unsigned char _ne_inb(void *portp)88{89return *(volatile unsigned char *)portp;90}9192static inline unsigned short _ne_inw(void *portp)93{94return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);95}9697static inline void _ne_insb(void *portp, void *addr, unsigned long count)98{99unsigned char *buf = (unsigned char *)addr;100101while (count--)102*buf++ = _ne_inb(portp);103}104105static inline void _ne_outb(unsigned char b, void *portp)106{107*(volatile unsigned char *)portp = b;108}109110static inline void _ne_outw(unsigned short w, void *portp)111{112*(volatile unsigned short *)portp = cpu_to_le16(w);113}114115unsigned char _inb(unsigned long port)116{117if (port >= LAN_IOSTART && port < LAN_IOEND)118return _ne_inb(PORT2ADDR_NE(port));119120#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)121else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {122return *(volatile unsigned char *)__port2addr_ata(port);123}124#endif125#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)126else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {127unsigned char b;128pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);129return b;130} else131#endif132133return *(volatile unsigned char *)PORT2ADDR(port);134}135136unsigned short _inw(unsigned long port)137{138if (port >= LAN_IOSTART && port < LAN_IOEND)139return _ne_inw(PORT2ADDR_NE(port));140#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)141else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {142return *(volatile unsigned short *)__port2addr_ata(port);143}144#endif145#if defined(CONFIG_USB)146else if(port >= 0x340 && port < 0x3a0)147return *(volatile unsigned short *)PORT2ADDR_USB(port);148#endif149#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)150else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {151unsigned short w;152pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);153return w;154} else155#endif156return *(volatile unsigned short *)PORT2ADDR(port);157}158159unsigned long _inl(unsigned long port)160{161#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)162if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {163unsigned long l;164pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);165return l;166} else167#endif168return *(volatile unsigned long *)PORT2ADDR(port);169}170171unsigned char _inb_p(unsigned long port)172{173unsigned char v = _inb(port);174delay();175return (v);176}177178unsigned short _inw_p(unsigned long port)179{180unsigned short v = _inw(port);181delay();182return (v);183}184185unsigned long _inl_p(unsigned long port)186{187unsigned long v = _inl(port);188delay();189return (v);190}191192void _outb(unsigned char b, unsigned long port)193{194if (port >= LAN_IOSTART && port < LAN_IOEND)195_ne_outb(b, PORT2ADDR_NE(port));196else197#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)198if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {199*(volatile unsigned char *)__port2addr_ata(port) = b;200} else201#endif202#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)203if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {204pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);205} else206#endif207*(volatile unsigned char *)PORT2ADDR(port) = b;208}209210void _outw(unsigned short w, unsigned long port)211{212if (port >= LAN_IOSTART && port < LAN_IOEND)213_ne_outw(w, PORT2ADDR_NE(port));214else215#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)216if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {217*(volatile unsigned short *)__port2addr_ata(port) = w;218} else219#endif220#if defined(CONFIG_USB)221if(port >= 0x340 && port < 0x3a0)222*(volatile unsigned short *)PORT2ADDR_USB(port) = w;223else224#endif225#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)226if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {227pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);228} else229#endif230*(volatile unsigned short *)PORT2ADDR(port) = w;231}232233void _outl(unsigned long l, unsigned long port)234{235#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)236if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {237pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);238} else239#endif240*(volatile unsigned long *)PORT2ADDR(port) = l;241}242243void _outb_p(unsigned char b, unsigned long port)244{245_outb(b, port);246delay();247}248249void _outw_p(unsigned short w, unsigned long port)250{251_outw(w, port);252delay();253}254255void _outl_p(unsigned long l, unsigned long port)256{257_outl(l, port);258delay();259}260261void _insb(unsigned int port, void *addr, unsigned long count)262{263if (port >= LAN_IOSTART && port < LAN_IOEND)264_ne_insb(PORT2ADDR_NE(port), addr, count);265#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)266else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {267unsigned char *buf = addr;268unsigned char *portp = __port2addr_ata(port);269while (count--)270*buf++ = *(volatile unsigned char *)portp;271}272#endif273#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)274else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {275pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),276count, 1);277}278#endif279else {280unsigned char *buf = addr;281unsigned char *portp = PORT2ADDR(port);282while (count--)283*buf++ = *(volatile unsigned char *)portp;284}285}286287void _insw(unsigned int port, void *addr, unsigned long count)288{289unsigned short *buf = addr;290unsigned short *portp;291292if (port >= LAN_IOSTART && port < LAN_IOEND) {293/*294* This portion is only used by smc91111.c to read data295* from the DATA_REG. Do not swap the data.296*/297portp = PORT2ADDR_NE(port);298while (count--)299*buf++ = *(volatile unsigned short *)portp;300#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)301} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {302pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),303count, 1);304#endif305#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)306} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {307portp = __port2addr_ata(port);308while (count--)309*buf++ = *(volatile unsigned short *)portp;310#endif311} else {312portp = PORT2ADDR(port);313while (count--)314*buf++ = *(volatile unsigned short *)portp;315}316}317318void _insl(unsigned int port, void *addr, unsigned long count)319{320unsigned long *buf = addr;321unsigned long *portp;322323portp = PORT2ADDR(port);324while (count--)325*buf++ = *(volatile unsigned long *)portp;326}327328void _outsb(unsigned int port, const void *addr, unsigned long count)329{330const unsigned char *buf = addr;331unsigned char *portp;332333if (port >= LAN_IOSTART && port < LAN_IOEND) {334portp = PORT2ADDR_NE(port);335while (count--)336_ne_outb(*buf++, portp);337#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)338} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {339portp = __port2addr_ata(port);340while (count--)341*(volatile unsigned char *)portp = *buf++;342#endif343#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)344} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {345pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),346count, 1);347#endif348} else {349portp = PORT2ADDR(port);350while (count--)351*(volatile unsigned char *)portp = *buf++;352}353}354355void _outsw(unsigned int port, const void *addr, unsigned long count)356{357const unsigned short *buf = addr;358unsigned short *portp;359360if (port >= LAN_IOSTART && port < LAN_IOEND) {361/*362* This portion is only used by smc91111.c to write data363* into the DATA_REG. Do not swap the data.364*/365portp = PORT2ADDR_NE(port);366while (count--)367*(volatile unsigned short *)portp = *buf++;368#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)369} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {370portp = __port2addr_ata(port);371while (count--)372*(volatile unsigned short *)portp = *buf++;373#endif374#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)375} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {376pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),377count, 1);378#endif379} else {380portp = PORT2ADDR(port);381while (count--)382*(volatile unsigned short *)portp = *buf++;383}384}385386void _outsl(unsigned int port, const void *addr, unsigned long count)387{388const unsigned long *buf = addr;389unsigned char *portp;390391portp = PORT2ADDR(port);392while (count--)393*(volatile unsigned long *)portp = *buf++;394}395396397