diff options
Diffstat (limited to 'arch/cris/arch-v32/mach-fs/io.c')
-rw-r--r-- | arch/cris/arch-v32/mach-fs/io.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-fs/io.c b/arch/cris/arch-v32/mach-fs/io.c new file mode 100644 index 000000000000..a03a3ad3a188 --- /dev/null +++ b/arch/cris/arch-v32/mach-fs/io.c | |||
@@ -0,0 +1,191 @@ | |||
1 | /* | ||
2 | * Helper functions for I/O pins. | ||
3 | * | ||
4 | * Copyright (c) 2004-2007 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 | |||
18 | #ifndef DEBUG | ||
19 | #define DEBUG(x) | ||
20 | #endif | ||
21 | |||
22 | struct crisv32_ioport crisv32_ioports[] = { | ||
23 | { | ||
24 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe), | ||
25 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout), | ||
26 | (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din), | ||
27 | 8 | ||
28 | }, | ||
29 | { | ||
30 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe), | ||
31 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout), | ||
32 | (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din), | ||
33 | 18 | ||
34 | }, | ||
35 | { | ||
36 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe), | ||
37 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout), | ||
38 | (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din), | ||
39 | 18 | ||
40 | }, | ||
41 | { | ||
42 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_oe), | ||
43 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pd_dout), | ||
44 | (unsigned long *)REG_ADDR(gio, regi_gio, r_pd_din), | ||
45 | 18 | ||
46 | }, | ||
47 | { | ||
48 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_oe), | ||
49 | (unsigned long *)REG_ADDR(gio, regi_gio, rw_pe_dout), | ||
50 | (unsigned long *)REG_ADDR(gio, regi_gio, r_pe_din), | ||
51 | 18 | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | #define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport) | ||
56 | |||
57 | struct crisv32_iopin crisv32_led_net0_green; | ||
58 | struct crisv32_iopin crisv32_led_net0_red; | ||
59 | struct crisv32_iopin crisv32_led_net1_green; | ||
60 | struct crisv32_iopin crisv32_led_net1_red; | ||
61 | struct crisv32_iopin crisv32_led2_green; | ||
62 | struct crisv32_iopin crisv32_led2_red; | ||
63 | struct crisv32_iopin crisv32_led3_green; | ||
64 | struct crisv32_iopin crisv32_led3_red; | ||
65 | |||
66 | /* Dummy port used when green LED and red LED is on the same bit */ | ||
67 | static unsigned long io_dummy; | ||
68 | static struct crisv32_ioport dummy_port = { | ||
69 | &io_dummy, | ||
70 | &io_dummy, | ||
71 | &io_dummy, | ||
72 | 18 | ||
73 | }; | ||
74 | static struct crisv32_iopin dummy_led = { | ||
75 | &dummy_port, | ||
76 | 0 | ||
77 | }; | ||
78 | |||
79 | static int __init crisv32_io_init(void) | ||
80 | { | ||
81 | int ret = 0; | ||
82 | |||
83 | u32 i; | ||
84 | |||
85 | /* Locks *should* be dynamically initialized. */ | ||
86 | for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++) | ||
87 | spin_lock_init(&crisv32_ioports[i].lock); | ||
88 | spin_lock_init(&dummy_port.lock); | ||
89 | |||
90 | /* Initialize LEDs */ | ||
91 | #if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO)) | ||
92 | ret += | ||
93 | crisv32_io_get_name(&crisv32_led_net0_green, | ||
94 | CONFIG_ETRAX_LED_G_NET0); | ||
95 | crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out); | ||
96 | if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) { | ||
97 | ret += | ||
98 | crisv32_io_get_name(&crisv32_led_net0_red, | ||
99 | CONFIG_ETRAX_LED_R_NET0); | ||
100 | crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out); | ||
101 | } else | ||
102 | crisv32_led_net0_red = dummy_led; | ||
103 | #endif | ||
104 | |||
105 | #ifdef CONFIG_ETRAX_NBR_LED_GRP_TWO | ||
106 | ret += | ||
107 | crisv32_io_get_name(&crisv32_led_net1_green, | ||
108 | CONFIG_ETRAX_LED_G_NET1); | ||
109 | crisv32_io_set_dir(&crisv32_led_net1_green, crisv32_io_dir_out); | ||
110 | if (strcmp(CONFIG_ETRAX_LED_G_NET1, CONFIG_ETRAX_LED_R_NET1)) { | ||
111 | crisv32_io_get_name(&crisv32_led_net1_red, | ||
112 | CONFIG_ETRAX_LED_R_NET1); | ||
113 | crisv32_io_set_dir(&crisv32_led_net1_red, crisv32_io_dir_out); | ||
114 | } else | ||
115 | crisv32_led_net1_red = dummy_led; | ||
116 | #endif | ||
117 | |||
118 | ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G); | ||
119 | ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R); | ||
120 | ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G); | ||
121 | ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R); | ||
122 | |||
123 | crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out); | ||
124 | crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out); | ||
125 | crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out); | ||
126 | crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | __initcall(crisv32_io_init); | ||
132 | |||
133 | int crisv32_io_get(struct crisv32_iopin *iopin, | ||
134 | unsigned int port, unsigned int pin) | ||
135 | { | ||
136 | if (port > NBR_OF_PORTS) | ||
137 | return -EINVAL; | ||
138 | if (port > crisv32_ioports[port].pin_count) | ||
139 | return -EINVAL; | ||
140 | |||
141 | iopin->bit = 1 << pin; | ||
142 | iopin->port = &crisv32_ioports[port]; | ||
143 | |||
144 | /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */ | ||
145 | /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */ | ||
146 | if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio)) | ||
147 | return -EIO; | ||
148 | DEBUG(printk(KERN_DEBUG "crisv32_io_get: Allocated pin %d on port %d\n", | ||
149 | pin, port)); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | int crisv32_io_get_name(struct crisv32_iopin *iopin, const char *name) | ||
155 | { | ||
156 | int port; | ||
157 | int pin; | ||
158 | |||
159 | if (toupper(*name) == 'P') | ||
160 | name++; | ||
161 | |||
162 | if (toupper(*name) < 'A' || toupper(*name) > 'E') | ||
163 | return -EINVAL; | ||
164 | |||
165 | port = toupper(*name) - 'A'; | ||
166 | name++; | ||
167 | pin = simple_strtoul(name, NULL, 10); | ||
168 | |||
169 | if (pin < 0 || pin > crisv32_ioports[port].pin_count) | ||
170 | return -EINVAL; | ||
171 | |||
172 | iopin->bit = 1 << pin; | ||
173 | iopin->port = &crisv32_ioports[port]; | ||
174 | |||
175 | /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */ | ||
176 | /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */ | ||
177 | if (port != 0 && crisv32_pinmux_alloc(port - 1, pin, pin, pinmux_gpio)) | ||
178 | return -EIO; | ||
179 | |||
180 | DEBUG(printk(KERN_DEBUG | ||
181 | "crisv32_io_get_name: Allocated pin %d on port %d\n", | ||
182 | pin, port)); | ||
183 | |||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | #ifdef CONFIG_PCI | ||
188 | /* PCI I/O access stuff */ | ||
189 | struct cris_io_operations *cris_iops = NULL; | ||
190 | EXPORT_SYMBOL(cris_iops); | ||
191 | #endif | ||