]>
Commit | Line | Data |
---|---|---|
035e111f JN |
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> | |
556dcee7 JN |
15 | #include <mach/pinmux.h> |
16 | #include <hwregs/gio_defs.h> | |
035e111f JN |
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 |