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 <mach/pinmux.h> 16#include <hwregs/gio_defs.h> 17 18#ifndef DEBUG 19#define DEBUG(x) 20#endif 21 22struct 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 ARRAY_SIZE(crisv32_ioports) 56 57struct crisv32_iopin crisv32_led_net0_green; 58struct crisv32_iopin crisv32_led_net0_red; 59struct crisv32_iopin crisv32_led_net1_green; 60struct crisv32_iopin crisv32_led_net1_red; 61struct crisv32_iopin crisv32_led2_green; 62struct crisv32_iopin crisv32_led2_red; 63struct crisv32_iopin crisv32_led3_green; 64struct crisv32_iopin crisv32_led3_red; 65 66/* Dummy port used when green LED and red LED is on the same bit */ 67static unsigned long io_dummy; 68static struct crisv32_ioport dummy_port = { 69 &io_dummy, 70 &io_dummy, 71 &io_dummy, 72 18 73}; 74static struct crisv32_iopin dummy_led = { 75 &dummy_port, 76 0 77}; 78 79static 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 133int 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 154int 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 */ 189struct cris_io_operations *cris_iops = NULL; 190EXPORT_SYMBOL(cris_iops); 191#endif 192