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