/*-------------------------------------------------------------------------------------*\ * * $Id: gpio_ssi.c 1.10 2004/03/04 15:03:19Z strevisany Exp $ * * $Log: gpio_ssi.c $ * Revision 1.10 2004/03/04 15:03:19Z strevisany * Revision 1.9 2004/03/03 15:56:54Z strevisany * Revision 1.8 2004/02/12 09:54:26Z strevisany * Revision 1.7 2004/02/11 12:05:25Z mpommerenke * Revision 1.6 2004/02/11 11:49:00Z strevisany * Revision 1.5 2004/02/10 16:16:33Z strevisany * Revision 1.4 2004/02/10 14:48:09Z strevisany * Revision 1.3 2004/02/10 13:32:30Z strevisany * Revision 1.2 2004/02/10 12:00:04Z mpommerenke * Revision 1.1 2003/11/11 10:32:37Z mpommerenke * \*-------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include /*--- #include ---*/ #include /*--- #include ---*/ #include #include #include #define DECT_TAC_CLOCKCYCLES 44 /* 1 Zyklus etwa 750ns */ #define DECT_TLN_CLOCKCYCLES 280 /* 1 Zyklus etwa 750ns */ /*------------------------------------------------------------------------------------------*\ \*------------------------------------------------------------------------------------------*/ #if defined(CONFIG_GPIO_SSI) #include #include #include #define TRUE 1 #define FALSE 0 /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ extern spinlock_t gpio_device_lock; static int data_is_input; /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ static struct timer_list ssi_timmer; static struct semaphore ssi_sema; static void Ssi_timer_Handler(unsigned long nr) { del_timer(&ssi_timmer); up(&ssi_sema); } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ static unsigned long sleep(void) { sema_init(&ssi_sema, 0); init_timer(&ssi_timmer); ssi_timmer.data = 0; ssi_timmer.function = Ssi_timer_Handler; ssi_timmer.expires = jiffies + (2* (HZ / 100)); /*--- 10-20 ms ---*/ add_timer(&ssi_timmer); down_interruptible(&ssi_sema); } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ int gpio_dataonly_test(void) { int DataOnly = 0; unsigned int flags = 0x00; spin_lock_irqsave(&gpio_device_lock, flags); /* Testen ob Sicofi/DUSLIC da ist */ /*--- CS high, DCLK low ---*/ avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS, TRUE); avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CLK, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, FALSE); sleep(); /*--- PIO Port zeit geben zum umschalten(ca. xx us) ---*/ if ((avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CLK) == FALSE) && (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CS) != FALSE)) { /*--- kein Kurzschluß ---*/ avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS, GPIO_PIN, GPIO_INPUT_PIN); sleep(); /*--- PIO Port zeit geben zum umschalten(ca. xx us) ---*/ if ((avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CLK) == FALSE) && (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CS) == FALSE)) { /*--- 1 KOhm R vorhanden ? ---*/ /*--- CS low,DCLK high ---*/ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS, FALSE); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); sleep(); /*--- PIO Port zeit geben zum umschalten(ca. xx us) ---*/ if ((avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CLK) == TRUE) && (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_CS) == TRUE)) { /*--- 1 KOhm R sicher vorhanden ---*/ DataOnly = TRUE; } } avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS, GPIO_PIN, GPIO_OUTPUT_PIN); } else printk("ERROR: gpio_dataonly_test short circuit!!!\n"); /* CS,CLK ruecksetzen */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS, TRUE); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); printk("gpio_dataonly_test: %d\n",DataOnly); spin_unlock_irqrestore(&gpio_device_lock, flags); return DataOnly; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ void gpio_ssi_init(void) { unsigned int flags = 0x00; spin_lock_irqsave(&gpio_device_lock, flags); /*--- printk("gpio_ssi_init: init\n"); ---*/ avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS3, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS3, TRUE); avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS2, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS2, TRUE); avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CS, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS, TRUE); avalanche_gpio_ctrl(CONFIG_GPIO_SSI_CLK, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); avalanche_gpio_ctrl(CONFIG_GPIO_SSI_DATA, GPIO_PIN, GPIO_OUTPUT_PIN); avalanche_gpio_out_bit(CONFIG_GPIO_SSI_DATA, TRUE); data_is_input = FALSE; printk("gpio_ssi_init: done\n"); spin_unlock_irqrestore(&gpio_device_lock, flags); } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ void gpio_ssi_select(unsigned int chip, unsigned int select) { unsigned int flags = 0x00; unsigned int cnt; /*--- printk("gpio_ssi_select: chip %x= %d\n", chip, select); ---*/ spin_lock_irqsave(&gpio_device_lock, flags); if (chip & 0x01) avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS, select ? FALSE : TRUE); if (chip & 0x02) avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS2, select ? FALSE : TRUE); if (chip & 0x04) { avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CS3, select ? FALSE : TRUE); /* DECT: "busy waiting" durch Dummy-Schreibzugriffe */ if (data_is_input == TRUE) { avalanche_gpio_ctrl(CONFIG_GPIO_SSI_DATA, GPIO_PIN, GPIO_OUTPUT_PIN); data_is_input = FALSE; } for (cnt = (select ? DECT_TAC_CLOCKCYCLES : DECT_TLN_CLOCKCYCLES); cnt > 0; cnt--) { avalanche_gpio_out_bit(CONFIG_GPIO_SSI_DATA, TRUE); /* Dummy-Schreibzugriff */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); /* 1 Zyklus etwa 750 ns */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); } } if ((data_is_input != FALSE) && (select == FALSE)) { /* am schluss wieder auf output */ avalanche_gpio_ctrl(CONFIG_GPIO_SSI_DATA, GPIO_PIN, GPIO_OUTPUT_PIN); data_is_input = FALSE; } spin_unlock_irqrestore(&gpio_device_lock, flags); } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ unsigned int gpio_ssi_read(void) { unsigned int flags = 0x00; unsigned int index; unsigned int in = 0; /*--- printk("gpio_ssi_read: start\n"); ---*/ spin_lock_irqsave(&gpio_device_lock, flags); if (data_is_input == FALSE) { avalanche_gpio_ctrl(CONFIG_GPIO_SSI_DATA, GPIO_PIN, GPIO_INPUT_PIN); data_is_input = TRUE; } for (index = 128; index > 0; index = index>>1) { avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, FALSE);/* Datenbit rein mit CLK auf 0 */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); /* Datenbit rein mit CLK auf 1 */ if (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_DATA)) { in |= index; } } spin_unlock_irqrestore(&gpio_device_lock, flags); /*--- printk("gpio_ssi_read: %x\n", in); ---*/ return in; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ unsigned int gpio_ssi_detect0_and_read(unsigned char* buffer) { unsigned int flags = 0x00; unsigned int index; unsigned char* in = buffer; unsigned int frame_cnt; unsigned int byte_cnt; unsigned int wait_cycles = 500; /* Vermeidung einer Endlosschleife */ /* auf 'Input' schalten */ /*--- printk("gpio_ssi_detect0_and_read: start\n"); ---*/ if (data_is_input == FALSE) { avalanche_gpio_ctrl(CONFIG_GPIO_SSI_DATA, GPIO_PIN, GPIO_INPUT_PIN); data_is_input = TRUE; } /* 11 Frames zu jeweils 4 Octets einlesen (erster Frame enthält Handshake) */ spin_lock_irqsave(&gpio_device_lock, flags); for (frame_cnt = 0; frame_cnt < 11; frame_cnt++) { for (byte_cnt = 0; byte_cnt < 4; byte_cnt++, in++) { *in = 0; for (index = (1 << 7); index > 0; index = (index >> 1)) { /* vor dem ersten Frame: warten auf das erste '0'-bit */ if (frame_cnt == 0 && byte_cnt == 0 && index == (1 << 7)) { do { avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); /* Zyklusdauer etwa 1us */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, FALSE); /* auslesen bei CLK auf 0 */ } while (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_DATA) && wait_cycles--); index = (index >> 1); /* das oberste Bit ist die bereits gelesen '0' */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); /* CLK auf TRUE am Ende des Zyklus */ } if (byte_cnt == 3 && index == 1) { /* vor der letzten negative Flanke des Frames: Interrupts sperren */ spin_lock_irqsave(&gpio_device_lock, flags); } avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, FALSE);/* Datenbit rein mit CLK auf 0 */ if (avalanche_gpio_in_bit(CONFIG_GPIO_SSI_DATA)) { *in |= index; } avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); if (byte_cnt == 0 && index == (1 << 6)) { /* am Ende des 2. eingelesenen Bits nach positiver Flanke Interrupts freigeben */ spin_unlock_irqrestore(&gpio_device_lock, flags); } } } /* Handshake-Frame auswerten: falls nicht RECV_CONF (=0x0F), dann raus */ if (frame_cnt == 0 && buffer[0] != 0x0F) { spin_unlock_irqrestore(&gpio_device_lock, flags); return 4; } } spin_unlock_irqrestore(&gpio_device_lock, flags); /*--- printk("gpio_ssi_read: %x\n", in); ---*/ return 44; } /*-------------------------------------------------------------------------------------*\ \*-------------------------------------------------------------------------------------*/ void gpio_ssi_write(unsigned int byte) { unsigned int flags = 0x00; unsigned int index; /*--- printk("gpio_ssi_write: %x\n", byte); ---*/ spin_lock_irqsave(&gpio_device_lock, flags); for (index = 128; index > 0; index = index>>1) { avalanche_gpio_out_bit(CONFIG_GPIO_SSI_DATA, ((byte & (unsigned char)index) == 0) ? FALSE : TRUE);/* Datenbit auf 0/1 */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, FALSE);/* Datenbit raus mit CLK auf 0 */ avalanche_gpio_out_bit(CONFIG_GPIO_SSI_CLK, TRUE); /* Datenbit raus mit CLK auf 1 */ } spin_unlock_irqrestore(&gpio_device_lock, flags); } EXPORT_SYMBOL(gpio_dataonly_test); EXPORT_SYMBOL(gpio_ssi_init); EXPORT_SYMBOL(gpio_ssi_read); EXPORT_SYMBOL(gpio_ssi_detect0_and_read); EXPORT_SYMBOL(gpio_ssi_write); EXPORT_SYMBOL(gpio_ssi_select); #endif