^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) ** asm-m68k/pcmcia.c -- Amiga Linux PCMCIA support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) ** most information was found by disassembling card.resource
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) ** I'm still looking for an official doc !
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) ** Copyright 1997 by Alain Malek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) ** This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) ** License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) ** for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) **
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) ** Created: 12/10/97 by Alain Malek
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/amigayle.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/amipcmcia.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* gayle config byte for program voltage and access speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) void pcmcia_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long reset_start_time = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) unsigned char b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) gayle_reset = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) while (time_before(jiffies, reset_start_time + 1*HZ/100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) b = gayle_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) EXPORT_SYMBOL(pcmcia_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* copy a tuple, including tuple header. return nb bytes copied */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* be careful as this may trigger a GAYLE_IRQ_WR interrupt ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned char id, *dest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int cnt, pos, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) dest = tuple;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) id = gayle_attribute[pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) while((id != CISTPL_END) && (pos < 0x10000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) len = (int)gayle_attribute[pos+2] + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (id == tuple_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) len = (len > max_len)?max_len:len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) for (cnt = 0; cnt < len; cnt++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *dest++ = gayle_attribute[pos+(cnt<<1)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) pos += len<<1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) id = gayle_attribute[pos];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) EXPORT_SYMBOL(pcmcia_copy_tuple);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void pcmcia_program_voltage(int voltage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) unsigned char v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) switch (voltage) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) case PCMCIA_0V:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) v = GAYLE_CFG_0V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) case PCMCIA_5V:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) v = GAYLE_CFG_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) case PCMCIA_12V:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) v = GAYLE_CFG_12V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) v = GAYLE_CFG_0V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) cfg_byte = (cfg_byte & 0xfc) | v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) gayle.config = cfg_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) EXPORT_SYMBOL(pcmcia_program_voltage);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) void pcmcia_access_speed(int speed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned char s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (speed <= PCMCIA_SPEED_100NS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) s = GAYLE_CFG_100NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) else if (speed <= PCMCIA_SPEED_150NS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) s = GAYLE_CFG_150NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) else if (speed <= PCMCIA_SPEED_250NS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) s = GAYLE_CFG_250NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) s = GAYLE_CFG_720NS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) cfg_byte = (cfg_byte & 0xf3) | s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) gayle.config = cfg_byte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) EXPORT_SYMBOL(pcmcia_access_speed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void pcmcia_write_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) EXPORT_SYMBOL(pcmcia_write_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) void pcmcia_write_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) gayle.cardstatus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL(pcmcia_write_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)