1/* 2 * linux/arch/h8300/kernel/gpio.c 3 * 4 * Yoshinori Sato <ysato@users.sourceforge.jp> 5 * 6 */ 7 8/* 9 * Internal I/O Port Management 10 */ 11 12#include <linux/stddef.h> 13#include <linux/proc_fs.h> 14#include <linux/kernel.h> 15#include <linux/string.h> 16#include <linux/fs.h> 17#include <linux/init.h> 18 19#define _(addr) (volatile unsigned char *)(addr) 20#if defined(CONFIG_H83007) || defined(CONFIG_H83068) 21#include <asm/regs306x.h> 22static volatile unsigned char *ddrs[] = { 23 _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), 24 NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), 25}; 26#define MAX_PORT 11 27#endif 28 29 #if defined(CONFIG_H83002) || defined(CONFIG_H8048) 30/* Fix me!! */ 31#include <asm/regs306x.h> 32static volatile unsigned char *ddrs[] = { 33 _(P1DDR),_(P2DDR),_(P3DDR),_(P4DDR),_(P5DDR),_(P6DDR), 34 NULL, _(P8DDR),_(P9DDR),_(PADDR),_(PBDDR), 35}; 36#define MAX_PORT 11 37#endif 38 39#if defined(CONFIG_H8S2678) 40#include <asm/regs267x.h> 41static volatile unsigned char *ddrs[] = { 42 _(P1DDR),_(P2DDR),_(P3DDR),NULL ,_(P5DDR),_(P6DDR), 43 _(P7DDR),_(P8DDR),NULL, _(PADDR),_(PBDDR),_(PCDDR), 44 _(PDDDR),_(PEDDR),_(PFDDR),_(PGDDR),_(PHDDR), 45 _(PADDR),_(PBDDR),_(PCDDR),_(PDDDR),_(PEDDR),_(PFDDR), 46 _(PGDDR),_(PHDDR) 47}; 48#define MAX_PORT 17 49#endif 50#undef _ 51 52#if !defined(P1DDR) 53#error Unsuppoted CPU Selection 54#endif 55 56static struct { 57 unsigned char used; 58 unsigned char ddr; 59} gpio_regs[MAX_PORT]; 60 61extern char *_platform_gpio_table(int length); 62 63int h8300_reserved_gpio(int port, unsigned int bits) 64{ 65 unsigned char *used; 66 67 if (port < 0 || port >= MAX_PORT) 68 return -1; 69 used = &(gpio_regs[port].used); 70 if ((*used & bits) != 0) 71 return 0; 72 *used |= bits; 73 return 1; 74} 75 76int h8300_free_gpio(int port, unsigned int bits) 77{ 78 unsigned char *used; 79 80 if (port < 0 || port >= MAX_PORT) 81 return -1; 82 used = &(gpio_regs[port].used); 83 if ((*used & bits) != bits) 84 return 0; 85 *used &= (~bits); 86 return 1; 87} 88 89int h8300_set_gpio_dir(int port_bit,int dir) 90{ 91 int port = (port_bit >> 8) & 0xff; 92 int bit = port_bit & 0xff; 93 94 if (ddrs[port] == NULL) 95 return 0; 96 if (gpio_regs[port].used & bit) { 97 if (dir) 98 gpio_regs[port].ddr |= bit; 99 else 100 gpio_regs[port].ddr &= ~bit; 101 *ddrs[port] = gpio_regs[port].ddr; 102 return 1; 103 } else 104 return 0; 105} 106 107int h8300_get_gpio_dir(int port_bit) 108{ 109 int port = (port_bit >> 8) & 0xff; 110 int bit = port_bit & 0xff; 111 112 if (ddrs[port] == NULL) 113 return 0; 114 if (gpio_regs[port].used & bit) { 115 return (gpio_regs[port].ddr & bit) != 0; 116 } else 117 return -1; 118} 119 120#if defined(CONFIG_PROC_FS) 121static char *port_status(int portno) 122{ 123 static char result[10]; 124 static const char io[2]={'I','O'}; 125 char *rp; 126 int c; 127 unsigned char used,ddr; 128 129 used = gpio_regs[portno].used; 130 ddr = gpio_regs[portno].ddr; 131 result[8]='\0'; 132 rp = result + 7; 133 for (c = 8; c > 0; c--,rp--,used >>= 1, ddr >>= 1) 134 if (used & 0x01) 135 *rp = io[ ddr & 0x01]; 136 else 137 *rp = '-'; 138 return result; 139} 140 141static int gpio_proc_read(char *buf, char **start, off_t offset, 142 int len, int *unused_i, void *unused_v) 143{ 144 int c,outlen; 145 static const char port_name[]="123456789ABCDEFGH"; 146 outlen = 0; 147 for (c = 0; c < MAX_PORT; c++) { 148 if (ddrs[c] == NULL) 149 continue ; 150 len = sprintf(buf,"P%c: %s\n",port_name[c],port_status(c)); 151 buf += len; 152 outlen += len; 153 } 154 return outlen; 155} 156 157static __init int register_proc(void) 158{ 159 struct proc_dir_entry *proc_gpio; 160 161 proc_gpio = create_proc_entry("gpio", S_IRUGO, NULL); 162 if (proc_gpio) 163 proc_gpio->read_proc = gpio_proc_read; 164 return proc_gpio != NULL; 165} 166 167__initcall(register_proc); 168#endif 169 170void __init h8300_gpio_init(void) 171{ 172 memcpy(gpio_regs,_platform_gpio_table(sizeof(gpio_regs)),sizeof(gpio_regs)); 173} 174