162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci** asm-m68k/pcmcia.c -- Amiga Linux PCMCIA support
362306a36Sopenharmony_ci**                      most information was found by disassembling card.resource
462306a36Sopenharmony_ci**                      I'm still looking for an official doc !
562306a36Sopenharmony_ci**
662306a36Sopenharmony_ci** Copyright 1997 by Alain Malek
762306a36Sopenharmony_ci**
862306a36Sopenharmony_ci** This file is subject to the terms and conditions of the GNU General Public
962306a36Sopenharmony_ci** License.  See the file COPYING in the main directory of this archive
1062306a36Sopenharmony_ci** for more details.
1162306a36Sopenharmony_ci**
1262306a36Sopenharmony_ci** Created: 12/10/97 by Alain Malek
1362306a36Sopenharmony_ci*/
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/jiffies.h>
1762306a36Sopenharmony_ci#include <linux/timer.h>
1862306a36Sopenharmony_ci#include <linux/module.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <asm/amigayle.h>
2162306a36Sopenharmony_ci#include <asm/amipcmcia.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* gayle config byte for program voltage and access speed */
2462306a36Sopenharmony_cistatic unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_civoid pcmcia_reset(void)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	unsigned long reset_start_time = jiffies;
2962306a36Sopenharmony_ci	unsigned char b;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	gayle_reset = 0x00;
3262306a36Sopenharmony_ci	while (time_before(jiffies, reset_start_time + 1*HZ/100));
3362306a36Sopenharmony_ci	b = gayle_reset;
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_reset);
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* copy a tuple, including tuple header. return nb bytes copied */
3962306a36Sopenharmony_ci/* be careful as this may trigger a GAYLE_IRQ_WR interrupt ! */
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciint pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	unsigned char id, *dest;
4462306a36Sopenharmony_ci	int cnt, pos, len;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	dest = tuple;
4762306a36Sopenharmony_ci	pos = 0;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	id = gayle_attribute[pos];
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	while((id != CISTPL_END) && (pos < 0x10000)) {
5262306a36Sopenharmony_ci		len = (int)gayle_attribute[pos+2] + 2;
5362306a36Sopenharmony_ci		if (id == tuple_id) {
5462306a36Sopenharmony_ci			len = (len > max_len)?max_len:len;
5562306a36Sopenharmony_ci			for (cnt = 0; cnt < len; cnt++) {
5662306a36Sopenharmony_ci				*dest++ = gayle_attribute[pos+(cnt<<1)];
5762306a36Sopenharmony_ci			}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci			return len;
6062306a36Sopenharmony_ci		}
6162306a36Sopenharmony_ci		pos += len<<1;
6262306a36Sopenharmony_ci		id = gayle_attribute[pos];
6362306a36Sopenharmony_ci	}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_copy_tuple);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_civoid pcmcia_program_voltage(int voltage)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	unsigned char v;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	switch (voltage) {
7462306a36Sopenharmony_ci	case PCMCIA_0V:
7562306a36Sopenharmony_ci		v = GAYLE_CFG_0V;
7662306a36Sopenharmony_ci		break;
7762306a36Sopenharmony_ci	case PCMCIA_5V:
7862306a36Sopenharmony_ci		v = GAYLE_CFG_5V;
7962306a36Sopenharmony_ci		break;
8062306a36Sopenharmony_ci	case PCMCIA_12V:
8162306a36Sopenharmony_ci		v = GAYLE_CFG_12V;
8262306a36Sopenharmony_ci		break;
8362306a36Sopenharmony_ci	default:
8462306a36Sopenharmony_ci		v = GAYLE_CFG_0V;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	cfg_byte = (cfg_byte & 0xfc) | v;
8862306a36Sopenharmony_ci	gayle.config = cfg_byte;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_program_voltage);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_civoid pcmcia_access_speed(int speed)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	unsigned char s;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	if (speed <= PCMCIA_SPEED_100NS)
9862306a36Sopenharmony_ci		s = GAYLE_CFG_100NS;
9962306a36Sopenharmony_ci	else if (speed <= PCMCIA_SPEED_150NS)
10062306a36Sopenharmony_ci		s = GAYLE_CFG_150NS;
10162306a36Sopenharmony_ci	else if (speed <= PCMCIA_SPEED_250NS)
10262306a36Sopenharmony_ci		s = GAYLE_CFG_250NS;
10362306a36Sopenharmony_ci	else
10462306a36Sopenharmony_ci		s = GAYLE_CFG_720NS;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	cfg_byte = (cfg_byte & 0xf3) | s;
10762306a36Sopenharmony_ci	gayle.config = cfg_byte;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_access_speed);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_civoid pcmcia_write_enable(void)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_write_enable);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_civoid pcmcia_write_disable(void)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	gayle.cardstatus = 0;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ciEXPORT_SYMBOL(pcmcia_write_disable);
12262306a36Sopenharmony_ci
123