os/linux-2.6-tag--devboard-R2_10-4/arch/cris/arch-v32/kernel/io.c

Go to the documentation of this file.
00001 /* 
00002  * Helper functions for I/O pins.
00003  *
00004  * Copyright (c) 2004, 2006 Axis Communications AB.
00005  */
00006 
00007 #include <linux/types.h>
00008 #include <linux/errno.h>
00009 #include <linux/init.h>
00010 #include <linux/string.h>
00011 #include <linux/ctype.h>
00012 #include <linux/kernel.h>
00013 #include <linux/module.h>
00014 #include <asm/io.h>
00015 #include <asm/delay.h>
00016 #include <asm/arch/pinmux.h>
00017 #include <asm/arch/hwregs/gio_defs.h>
00018 #include <asm/arch/hwregs/pinmux_defs.h>
00019 #include <asm/arch/hwregs/iop/iop_sw_cfg_defs.h>
00020 
00021 #ifndef DEBUG
00022 #define DEBUG(x)
00023 #endif
00024 
00025 struct crisv32_ioport crisv32_ioports[] =
00026 {
00027         {
00028                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_oe),
00029                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pa_dout),
00030                 (unsigned long*)REG_ADDR(gio, regi_gio, r_pa_din),
00031                 8
00032         },
00033         {
00034                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_oe),
00035                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pb_dout),
00036                 (unsigned long*)REG_ADDR(gio, regi_gio, r_pb_din),
00037                 18
00038         },
00039         {
00040                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_oe),
00041                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pc_dout),
00042                 (unsigned long*)REG_ADDR(gio, regi_gio, r_pc_din),
00043                 18
00044         },
00045         {
00046                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_oe),
00047                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pd_dout),
00048                 (unsigned long*)REG_ADDR(gio, regi_gio, r_pd_din),
00049                 18
00050         },
00051         {
00052                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_oe),
00053                 (unsigned long*)REG_ADDR(gio, regi_gio, rw_pe_dout),
00054                 (unsigned long*)REG_ADDR(gio, regi_gio, r_pe_din),
00055                 18
00056         } 
00057 };
00058 
00059 #define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
00060 
00061 struct crisv32_iopin crisv32_led_net0_green;
00062 struct crisv32_iopin crisv32_led_net0_red;
00063 struct crisv32_iopin crisv32_led_net1_green;
00064 struct crisv32_iopin crisv32_led_net1_red;
00065 struct crisv32_iopin crisv32_led2_green;
00066 struct crisv32_iopin crisv32_led2_red;
00067 struct crisv32_iopin crisv32_led3_green;
00068 struct crisv32_iopin crisv32_led3_red;
00069 
00070 /* Dummy port used when green LED and red LED is on the same bit */
00071 static unsigned long io_dummy;
00072 static struct crisv32_ioport dummy_port =
00073 {
00074         &io_dummy,
00075         &io_dummy,
00076         &io_dummy,
00077         18
00078 };
00079 static struct crisv32_iopin dummy_led =
00080 {
00081         &dummy_port,
00082         0
00083 };
00084 
00085 int _353_io_board_present = 1;
00086 EXPORT_SYMBOL(_353_io_board_present);
00087 
00088 void _353_configure(void) {
00089         int pd16_level = 1;
00090         printk("Check hardware configuration of Elphel 353 camera\n");
00091         /*
00092          * Check IDE capable board
00093          * PD15 - IORDY, 4.7K to 3.3V
00094          * PD16 - DMARQ, 5.6K to GND
00095          * PD16 - INTRQ, 10K to GND
00096          */
00097         reg_iop_sw_cfg_rw_pinmapping _rw_pinmapping = REG_RD(iop_sw_cfg, regi_iop_sw_cfg, rw_pinmapping);
00098         reg_iop_sw_cfg_rw_pinmapping prev_rw_pinmapping = _rw_pinmapping;
00099         _rw_pinmapping.gio3_0 = 2; // switch GIO[3..0] to pd mapping (B)
00100         REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_pinmapping, _rw_pinmapping);
00101         // connect GIO signal pd16 to pin pd16
00102         reg_pinmux_rw_pd_gio _rw_pd_gio = REG_RD(pinmux, regi_pinmux, rw_pd_gio);
00103         reg_pinmux_rw_pd_gio prev_rw_pd_gio = _rw_pd_gio;
00104         _rw_pd_gio.pd16 = 1;
00105         REG_WR(pinmux, regi_pinmux, rw_pd_gio, _rw_pd_gio);
00106         // connect I/O processor port pd to port pd
00107         reg_pinmux_rw_pd_iop _rw_pd_iop = REG_RD(pinmux, regi_pinmux, rw_pd_iop);
00108         reg_pinmux_rw_pd_iop prev_rw_pd_iop = _rw_pd_iop;
00109         _rw_pd_iop.pd16 = 1;
00110         REG_WR(pinmux, regi_pinmux, rw_pd_iop, _rw_pd_iop);
00112         reg_gio_rw_pd_oe _pd_oe = REG_RD(gio, regi_gio, rw_pd_oe);
00113         reg_gio_rw_pd_oe prev_pd_oe = _pd_oe;
00114         _pd_oe.oe |= 1 << 16;
00115         REG_WR(gio, regi_gio, rw_pd_oe, _pd_oe);
00117         reg_gio_r_pd_din _pd_din;
00118 //      _pd_din = REG_RD(gio, regi_gio, r_pd_din);
00119 //      unsigned long prev = _pd_din.data;
00121 
00122         reg_gio_rw_pd_dout _pd_dout;
00123         _pd_dout.data = 1 << 16;
00124         REG_WR(gio, regi_gio, rw_pd_dout, _pd_dout);
00125         udelay(1); // don't need to be long
00126 //      _pd_din = REG_RD(gio, regi_gio, r_pd_din);
00127 //      unsigned long new = _pd_din.data;
00129 //      REG_WR(gio, regi_gio, rw_pd_oe, prev_pd_oe);
00130         _pd_oe.oe &= ~(1 << 16);
00131         REG_WR(gio, regi_gio, rw_pd_oe, _pd_oe);
00132         udelay(10);
00133         _pd_din = REG_RD(gio, regi_gio, r_pd_din);
00134 //      unsigned long again = _pd_din.data;
00135         pd16_level = _pd_din.data >> 16;
00136         pd16_level &= 0x0001;
00137 
00138 //      printk("again: 0x%08X, pd16_level: 0x%08X\n", again, pd16_level);
00139 //      printk("prev value: 0x%08X, new value: 0x%08X, again value: 0x%08X\n", prev, new, again);
00140         // restore switches
00141         REG_WR(gio, regi_gio, rw_pd_oe, prev_pd_oe);
00142         REG_WR(pinmux, regi_pinmux, rw_pd_iop, prev_rw_pd_iop);
00143         REG_WR(pinmux, regi_pinmux, rw_pd_gio, prev_rw_pd_gio);
00144         REG_WR(iop_sw_cfg, regi_iop_sw_cfg, rw_pinmapping, prev_rw_pinmapping);
00146         if(pd16_level) {
00147                 printk("Elphel 10349/10369 IO extension board is not present\n");
00148                 _353_io_board_present = 0;
00149         } else {
00150                 printk("Elphel 10349/10369 IO extension board is present\n");
00151                 _353_io_board_present = 1;
00152         }
00153 //*/
00154 }
00155 
00156 static int __init crisv32_io_init(void)
00157 {
00158         int ret = 0;
00159 
00160         u32 i;
00161 
00162         _353_configure();
00163 
00164         /* Locks *should* be dynamically initialized. */
00165         for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
00166                 spin_lock_init (&crisv32_ioports[i].lock);
00167         spin_lock_init (&dummy_port.lock);
00168 
00169         /* Initialize LEDs */
00170 /*
00171 #if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
00172         ret += crisv32_io_get_name(&crisv32_led_net0_green, CONFIG_ETRAX_LED_G_NET0);
00173         crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
00174         if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
00175                 ret += crisv32_io_get_name(&crisv32_led_net0_red, CONFIG_ETRAX_LED_R_NET0);
00176                 crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
00177         } else
00178                 crisv32_led_net0_red = dummy_led;
00179 #endif
00180 
00181 #ifdef CONFIG_ETRAX_NBR_LED_GRP_TWO
00182         ret += crisv32_io_get_name(&crisv32_led_net1_green, CONFIG_ETRAX_LED_G_NET1);
00183         crisv32_io_set_dir(&crisv32_led_net1_green, crisv32_io_dir_out);
00184         if (strcmp(CONFIG_ETRAX_LED_G_NET1, CONFIG_ETRAX_LED_R_NET1)) {
00185                 crisv32_io_get_name(&crisv32_led_net1_red, CONFIG_ETRAX_LED_R_NET1);
00186                 crisv32_io_set_dir(&crisv32_led_net1_red, crisv32_io_dir_out);
00187         } else
00188                 crisv32_led_net1_red = dummy_led;
00189 #endif
00190 
00191         ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_LED2G);
00192         ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_LED2R);
00193         ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_LED3G);
00194         ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_LED3R);
00195 
00196         crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
00197         crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
00198         crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
00199         crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
00200 */
00201         crisv32_led_net0_red = dummy_led;
00202         crisv32_led_net1_red = dummy_led;
00203 
00204         return ret;
00205 }
00206 
00207 __initcall(crisv32_io_init);
00208 
00209 int crisv32_io_get(struct crisv32_iopin* iopin, 
00210                    unsigned int port, unsigned int pin)
00211 {
00212         if (port > NBR_OF_PORTS) 
00213                 return -EINVAL;
00214         if (port > crisv32_ioports[port].pin_count)
00215                 return -EINVAL;
00216 
00217         iopin->bit = 1 << pin;
00218         iopin->port = &crisv32_ioports[port];
00219 
00220         /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
00221         /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
00222         if (port != 0 && crisv32_pinmux_alloc(port-1, pin, pin, pinmux_gpio)) 
00223                 return -EIO;
00224         DEBUG(printk("crisv32_io_get: Allocated pin %d on port %d\n", pin, port ));
00225         
00226         return 0;
00227 }
00228 
00229 int crisv32_io_get_name(struct crisv32_iopin* iopin,
00230                         const char* name)
00231 {
00232         int port;
00233         int pin;
00234 
00235         if (toupper(*name) == 'P')
00236                 name++;
00237 
00238         if (toupper(*name) < 'A' || toupper(*name) > 'E')
00239                 return -EINVAL;
00240         
00241         port = toupper(*name) - 'A';
00242         name++;
00243         pin = simple_strtoul(name, NULL, 10);
00244 
00245         if (pin < 0 || pin > crisv32_ioports[port].pin_count)
00246                 return -EINVAL;
00247 
00248         iopin->bit = 1 << pin;
00249         iopin->port = &crisv32_ioports[port];
00250 
00251         /* Only allocate pinmux gpiopins if port != PORT_A (port 0) */
00252         /* NOTE! crisv32_pinmux_alloc thinks PORT_B is port 0 */
00253         if (port != 0 && crisv32_pinmux_alloc(port-1, pin, pin, pinmux_gpio)) 
00254                 return -EIO;
00255 
00256         DEBUG(printk("crisv32_io_get_name: Allocated pin %d on port %d\n", pin, port));
00257         return 0;
00258 }
00259 
00260 #ifdef CONFIG_PCI
00261 /* PCI I/O access stuff */
00262 struct cris_io_operations* cris_iops = NULL;
00263 EXPORT_SYMBOL(cris_iops);
00264 #endif
00265 

Generated on Fri Nov 28 00:06:23 2008 for elphel by  doxygen 1.5.1