1/*
2 * Helper functions for I/O pins.
3 *
4 * Copyright (c) 2004 Axis Communications AB.
5 */
6
7#include <linux/types.h>
8#include <linux/errno.h>
9#include <linux/init.h>
10#include <linux/string.h>
11#include <linux/ctype.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <asm/io.h>
15#include <asm/arch/pinmux.h>
16#include <asm/arch/hwregs/gio_defs.h>
17
18struct crisv32_ioport crisv32_ioports[] =
19{
20	{
21		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_oe),
22		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_dout),
23		(unsigned long*)REG_ADDR(gio, regi_gio, r_pa_din),
24		8
25	},
26	{
27		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_oe),
28		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_dout),
29		(unsigned long*)REG_ADDR(gio, regi_gio, r_pb_din),
30		18
31	},
32	{
33		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_oe),
34		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_dout),
35		(unsigned long*)REG_ADDR(gio, regi_gio, r_pc_din),
36		18
37	},
38	{
39		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_oe),
40		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_dout),
41		(unsigned long*)REG_ADDR(gio, regi_gio, r_pd_din),
42		18
43	},
44	{
45		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_oe),
46		(unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_dout),
47		(unsigned long*)REG_ADDR(gio, regi_gio, r_pe_din),
48		18
49	}
50};
51
52#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
53
54struct crisv32_iopin crisv32_led1_green;
55struct crisv32_iopin crisv32_led1_red;
56struct crisv32_iopin crisv32_led2_green;
57struct crisv32_iopin crisv32_led2_red;
58struct crisv32_iopin crisv32_led3_green;
59struct crisv32_iopin crisv32_led3_red;
60
61/* Dummy port used when green LED and red LED is on the same bit */
62static unsigned long io_dummy;
63static struct crisv32_ioport dummy_port =
64{
65	&io_dummy,
66	&io_dummy,
67	&io_dummy,
68	18
69};
70static struct crisv32_iopin dummy_led =
71{
72	&dummy_port,
73	0
74};
75
76static int __init crisv32_io_init(void)
77{
78	int ret = 0;
79	/* Initialize LEDs */
80	ret += crisv32_io_get_name(&crisv32_led1_green, CONFIG_ETRAX_LED1G);
81	ret += crisv32_io_get_name(&crisv32_led1_red, CONFIG_ETRAX_LED1R);
82	ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_LED2G);
83	ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_LED2R);
84	ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_LED3G);
85	ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_LED3R);
86	crisv32_io_set_dir(&crisv32_led1_green, crisv32_io_dir_out);
87	crisv32_io_set_dir(&crisv32_led1_red, crisv32_io_dir_out);
88	crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
89	crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
90	crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
91	crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
92
93	if (!strcmp(CONFIG_ETRAX_LED1G, CONFIG_ETRAX_LED1R))
94		crisv32_led1_red = dummy_led;
95	if (!strcmp(CONFIG_ETRAX_LED2G, CONFIG_ETRAX_LED2R))
96		crisv32_led2_red = dummy_led;
97
98	return ret;
99}
100
101__initcall(crisv32_io_init);
102
103int crisv32_io_get(struct crisv32_iopin* iopin,
104                   unsigned int port, unsigned int pin)
105{
106	if (port > NBR_OF_PORTS)
107		return -EINVAL;
108	if (port > crisv32_ioports[port].pin_count)
109		return -EINVAL;
110
111	iopin->bit = 1 << pin;
112	iopin->port = &crisv32_ioports[port];
113
114	if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
115		return -EIO;
116
117	return 0;
118}
119
120int crisv32_io_get_name(struct crisv32_iopin* iopin,
121                         char* name)
122{
123	int port;
124	int pin;
125
126	if (toupper(*name) == 'P')
127		name++;
128
129	if (toupper(*name) < 'A' || toupper(*name) > 'E')
130		return -EINVAL;
131
132	port = toupper(*name) - 'A';
133	name++;
134	pin = simple_strtoul(name, NULL, 10);
135
136	if (pin < 0 || pin > crisv32_ioports[port].pin_count)
137		return -EINVAL;
138
139	iopin->bit = 1 << pin;
140	iopin->port = &crisv32_ioports[port];
141
142	if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
143		return -EIO;
144
145	return 0;
146}
147
148#ifdef CONFIG_PCI
149/* PCI I/O access stuff */
150struct cris_io_operations* cris_iops = NULL;
151EXPORT_SYMBOL(cris_iops);
152#endif
153