patches attached :-)
--
Nicholas Henke
Undergraduate - Engineerring 2002
--
Senior Architect and Developer
Liniac Project - University of Pennsylvania
http://clubmask.sourceforge.net
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There's nothing like good food, good beer, and a bad girl.
--- i82365.c Wed Jan 16 20:36:29 2002
+++ /home/henken/armbuild/2.4.7/linux/drivers/pcmcia/i82365.c Sun Nov 25 13:15:13
+2001
@@ -73,15 +73,23 @@
#define I365_MASK (1 << 6)
#define SOCKIRQ2REG(sock,irq) ((sock) ? 3 : 4)
#define REG2SOCKIRQ(sock,reg) (6)
+#elif defined (CONFIG_SA1100_OMNIMETER)
+#define SOCKIRQ2REG(sock,irq) (sock ? 3 : 3)
+#define REG2SOCKIRQ(sock,reg) (PIN_cardInt1)
#else
#define SOCKIRQ2REG(sock,irq) (irq)
#define REG2SOCKIRQ(sock,reg) (reg)
#endif
+#define PCMCIA_DEBUG 100
+
+
+
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
-#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
+/* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) */
+#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_INFO args)
static const char *version =
"i82365.c 1.265 1999/11/10 18:36:21 (David Hinds)";
#else
@@ -114,6 +122,9 @@
/* The card status change interrupt -- 0 means autoselect */
static int cs_irq = 0;
#endif
+#ifdef __arm__
+static int cs_irq = 0;
+#endif
/* Probe for safe interrupts? */
static int do_scan = 1;
@@ -221,13 +232,13 @@
PCI_COMMAND_MASTER|PCI_COMMAND_WAIT)
/* These definitions must match the pcic table! */
-#ifdef CONFIG_ISA
+/* #ifdef CONFIG_ISA */
typedef enum pcic_id {
IS_I82365A, IS_I82365B, IS_I82365DF,
IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
IS_PD6710, IS_PD672X, IS_VT83C469,
} pcic_id;
-#endif
+/* #endif */
/* Flags for classifying groups of controllers */
#define IS_VADEM 0x0001
@@ -249,7 +260,7 @@
} pcic_t;
static pcic_t pcic[] = {
-#ifdef CONFIG_ISA
+/* #ifdef CONFIG_ISA */
{ "Intel i82365sl A step", 0 },
{ "Intel i82365sl B step", 0 },
{ "Intel i82365sl DF", IS_DF_PWR },
@@ -261,7 +272,7 @@
{ "Cirrus PD6710", IS_CIRRUS },
{ "Cirrus PD672x", IS_CIRRUS },
{ "VIA VT83C469", IS_CIRRUS|IS_VIA },
-#endif
+/* #endif */
};
#define PCIC_COUNT (sizeof(pcic)/sizeof(pcic_t))
@@ -738,8 +749,14 @@
/*====================================================================*/
-static void __init add_socket(u_short port, int psock, int type)
+static void __init add_socket(ioaddr_t port, int psock, int type)
{
+#ifdef __arm__
+ port = (u_int)__ioremap(port, 0x8000, 0);
+ DEBUG (1, "socket mapped to virt=%x\n", port);
+ if (!port)
+ printk ("add_socket: Cannot ioremap\n");
+#endif
socket[sockets].ioaddr = port;
socket[sockets].psock = psock;
socket[sockets].type = type;
@@ -749,6 +766,11 @@
sockets++;
}
+#ifdef __arm__
+static void pcic_interrupt(int irq, void *dev,
+ struct pt_regs *regs);
+#endif
+
static void __init add_pcic(int ns, int type)
{
u_int mask = 0, i, base;
@@ -803,22 +825,64 @@
}
}
#endif
-
+
+#ifdef CONFIG_SA1100_OMNIMETER
+ use_pci = 0;
+#endif
if (!use_pci && !isa_irq) {
if (poll_interval == 0)
poll_interval = HZ;
printk(" polling interval = %d ms\n",
poll_interval * 1000 / HZ);
-
+
}
-
+
+#ifdef CONFIG_SA1100_OMNIMETER
+ if (use_pci)
+ printk(" status change on irqs");
+#endif
+
/* Update socket interrupt information, capabilities */
for (i = 0; i < ns; i++) {
+
t[i].cap.features |= SS_CAP_PCCARD;
- t[i].cap.map_size = 0x1000;
+#ifdef __arm__
+ t[i].cap.features |= SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP;
+ t[i].cap.io_offset = i ? 0xf6008000 : 0xf6000000;
+ t[i].cap.irq_mask = 0;
+
+#ifdef CONFIG_SA1100_OMNIMETER
+ {
+ cs_irq = PIN_cardInt1;
+ if (use_pci)
+ {
+ t[i].cap.pci_irq = cs_irq;
+ printk(" %d", cs_irq);
+ GPDR &= ~(1 << cs_irq); /* make it an input */
+ set_GPIO_IRQ_edge(1 << cs_irq, GPIO_RISING_EDGE);
+ if (request_irq(cs_irq, pcic_interrupt, SA_INTERRUPT, "i82365",
+ &t[i]) < 0)
+ printk( KERN_ERR "%s: Request for IRQ %u failed\n", __FUNCTION__,
+ cs_irq );
+ }
+ else
+ {
+ t[i].cap.pci_irq = cs_irq;
+ set_GPIO_IRQ_edge(1 << cs_irq, GPIO_RISING_EDGE);
+ GPDR &= ~(1 << cs_irq); /* make it an input */
+ }
+ }
+#endif
+#else
t[i].cap.irq_mask = mask;
t[i].cs_irq = isa_irq;
+#endif
+ t[i].cap.map_size = 0x1000;
}
+#ifdef CONFIG_SA1100_OMNIMETER
+ if (use_pci)
+ printk("\n");
+#endif
} /* add_pcic */
@@ -917,8 +980,8 @@
#ifdef CONFIG_ISA
u_long flags = 0;
#endif
-
- DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq);
+
+/* DEBUG(4, "i82365: pcic_interrupt(%d)\n", irq); */
for (j = 0; j < 20; j++) {
active = 0;
@@ -928,28 +991,31 @@
continue;
ISA_LOCK(i, flags);
csc = i365_get(i, I365_CSC);
+/* printk("status=%x\n", csc); */
if ((csc == 0) || (!socket[i].handler) ||
(i365_get(i, I365_IDENT) & 0x70)) {
ISA_UNLOCK(i, flags);
continue;
}
events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
-
-
+
/* Several sockets will send multiple "new card detected"
- events in rapid succession. However, the rest of the pcmcia expects
+ events in rapid succession. However, the rest of the pcmcia expects
only one such event. We just ignore these events by having a
timeout */
if (events) {
- if ((jiffies - last_detect_jiffies)<(HZ/20))
+ if ((jiffies - last_detect_jiffies)<(HZ/20))
events = 0;
last_detect_jiffies = jiffies;
-
+
}
-
+
if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
+ {
events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
+ DEBUG(1, "io card\n");
+ }
else {
events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
@@ -971,7 +1037,7 @@
if (j == 20)
printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
- DEBUG(4, "i82365: interrupt done\n");
+/* DEBUG(4, "i82365: interrupt done\n"); */
} /* pcic_interrupt */
static void pcic_interrupt_wrapper(u_long data)
@@ -1118,21 +1184,26 @@
{
socket_info_t *t = &socket[sock];
u_char reg;
-
+
DEBUG(1, "i82365: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-
+
/* First set global controller options */
set_bridge_state(sock);
-
+
/* IO card, RESET flag, IO interrupt */
reg = t->intr;
- if (state->io_irq != t->cap.pci_irq) reg |= SOCKIRQ2REG(sock, state->io_irq);
+#ifndef CONFIG_SA1100_OMNIMETER /* uses polling */
+ if (state->io_irq != t->cap.pci_irq)
+#endif
+ reg |= SOCKIRQ2REG(sock, state->io_irq);
reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
+ DEBUG(1, "i82365: setting intctl to %x\n", reg);
+/* printk ("i82365: setting intctl to %x, flags =%x\n", reg); */
i365_set(sock, I365_INTCTL, reg);
-
+
reg = I365_PWR_NORESET;
if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
@@ -1205,9 +1276,14 @@
i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
state->flags & SS_SPKR_ENA);
}
-
+
/* Card status change interrupt mask */
+#ifdef CONFIG_SA1100_OMNIMETER
+ reg = 4;
+ reg |= I365_CSC_STSCHG | I365_CSC_BVD2 | I365_CSC_READY;
+#else
reg = SOCKIRQ2REG(sock, t->cs_irq) << 4;
+#endif
if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
if (state->flags & SS_IOCARD) {
if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
@@ -1216,9 +1292,16 @@
if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
}
+ DEBUG(1, "i82365: setting cscint to %x\n", reg);
+/* printk ("i82365: setting cscint to %x\n", reg); */
i365_set(sock, I365_CSCINT, reg);
+#ifdef CONFIG_SA1100_OMNIMETER
+ i365_set(sock, I365_GENCTL, 0x0c);
+ i365_set(sock, I365_GENCTL, 0x0c);
+/* printk ("i82365: setting genctl to %x\n", 0xc); */
+#endif
i365_get(sock, I365_CSC);
-
+
return 0;
} /* i365_set_socket */
@@ -1262,6 +1345,9 @@
i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
+#ifdef CONFIG_SA1100_OMNIMETER
+ i365_set_pair(sock, I365_IO(map)+I365_W_OFF, sock ? 0x8000 : 0);
+#endif
ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
@@ -1311,12 +1397,15 @@
} /* i365_get_mem_map */
/*====================================================================*/
-
+
static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
{
- u_short base, i;
+ u_int base, i;
u_char map;
-
+#ifdef __arm__
+ unsigned int start;
+#endif
+
DEBUG(1, "i82365: SetMemMap(%d, %d, %#2.2x, %d ns, %#5.5lx-%#5.5"
"lx, %#5.5x)\n", sock, mem->map, mem->flags, mem->speed,
mem->sys_start, mem->sys_stop, mem->card_start);
@@ -1324,22 +1413,65 @@
map = mem->map;
if ((map > 4) || (mem->card_start > 0x3ffffff) ||
(mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+ {
+ DEBUG(1, "i82365: eEINVAL\n");
return -EINVAL;
+ }
+#ifndef CONFIG_SA1100_OMNIMETER
if (!(socket[sock].flags & IS_PCI) &&
((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff)))
+ {
+ DEBUG(1, "i82365: eEINVAL\n");
return -EINVAL;
-
+ }
+#endif
+#ifdef CONFIG_SA1100_OMNIMETER
+ start = mem->sys_start;
+
+ if(mem->sys_stop == 0)
+ mem->sys_stop = 0x10000 - 1;
+
+ mem->sys_start = mem->flags & MAP_ATTRIB
+ ? 0x38000000
+ : 0x3c010000;
+ if (sock)
+ mem->sys_start += 0x00400000;
+
+ mem->sys_stop = mem->sys_start + (mem->sys_stop - start);
+
+/* socket0 socket1 */
+/* 00800000 00c00000 */
+/* 00bfffff 00ffffff */
+/* 03800000 03400000 */
+#endif
+
/* Turn off the window before changing anything */
if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
-
+
+ /* set map 'map' start address bits 23:12 */
base = I365_MEM(map);
- i = (mem->sys_start >> 12) & 0x0fff;
+#ifdef CONFIG_SA1100_OMNIMETER
+ i = mem->sys_start + 0x800000;
+#else
+ i = mem->sys_start;
+#endif
+ DEBUG(1, "start=%x, ", i);
+ i = (i >> 12) & 0x0fff;
+/* i = 0xc00000 >> 12; */
if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
i365_set_pair(sock, base+I365_W_START, i);
-
- i = (mem->sys_stop >> 12) & 0x0fff;
+
+ /* set map 'map' end address bits 23:12 */
+#ifdef CONFIG_SA1100_OMNIMETER
+ i = mem->sys_stop + 0x800000;
+#else
+ i = mem->sys_stop;
+#endif
+ DEBUG(1, "stop=%x, ", i);
+ i = (i >> 12) & 0x0fff;
+/* i = 0xfff000 >> 12; */
switch (to_cycles(mem->speed)) {
case 0: break;
case 1: i |= I365_MEM_WS0; break;
@@ -1347,15 +1479,34 @@
default: i |= I365_MEM_WS1 | I365_MEM_WS0; break;
}
i365_set_pair(sock, base+I365_W_STOP, i);
-
- i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+
+ /* set map 'map' offset address bits 25:12 */
+#ifdef CONFIG_SA1100_OMNIMETER
+/* i = mem->card_start - mem->sys_start - 0x80000; */
+ i = mem->card_start - mem->sys_start;
+ if (sock)
+ i += 0x800000;
+#else
+ i = mem->card_start - mem->sys_start;
+#endif
+ DEBUG(1, "offset=%x\n", i);
+/* i = 0x03400000; */
+ i = (i >> 12) & 0x3fff;
if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
i365_set_pair(sock, base+I365_W_OFF, i);
-
+
+ i = i365_get_pair(sock, base+I365_W_OFF);
+
/* Turn on the window if necessary */
if (mem->flags & MAP_ACTIVE)
i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
+
+/* i365_get_mem_map(sock, mem); */
+/* for (i = 0; i <= 0x3f; i ++) */
+/* DEBUG(1, " %02x: %x\n", i, i365_get (sock, i)); */
+/* DEBUG(1,"\n"); */
+
return 0;
} /* i365_set_mem_map */
@@ -1528,6 +1679,25 @@
mem.map = i;
pcic_set_mem_map(s, &mem);
}
+#ifdef CONFIG_SA1100_OMNIMETER
+ {
+ struct pccard_mem_map mem;
+ struct pccard_io_map io;
+
+ mem.sys_start = mem.card_start = 0;
+ mem.map = 4;
+ mem.flags = MAP_ACTIVE | MAP_16BIT;
+ mem.speed = 300;
+ i365_set_mem_map(s, &mem);
+
+ io.map = 0;
+ io.flags = MAP_AUTOSZ;
+ io.speed = 0;
+ io.start = s ? 0x8000 : 0;
+ io.stop = s ? 0x83df : 0x3df;
+ i365_set_io_map (s, &io);
+ }
+#endif
return 0;
}
@@ -1569,6 +1740,11 @@
#ifdef CONFIG_ISA
isa_probe();
#endif
+#ifdef CONFIG_SA1100_OMNIMETER
+ add_socket (PCCardIndexRegister, 0, IS_PD672X);
+ add_socket (PCCardIndexRegister, 1, IS_PD672X);
+ add_pcic (2, IS_PD672X);
+#endif
if (sockets == 0) {
printk("not found.\n");
--- cs.c Wed Jan 16 20:36:29 2002
+++ /home/henken/armbuild/2.4.7/linux/drivers/pcmcia/cs.c Sun Nov 25 13:15:25
+2001
@@ -1718,6 +1718,9 @@
if (c->state & CONFIG_IRQ_REQ)
if (!(c->irq.Attributes & IRQ_FORCED_PULSE))
c->Option |= COR_LEVEL_REQ;
+#ifdef CONFIG_SA1100_OMNIMETER
+ c->Option &= ~COR_FUNC_ENA; /* force to use memory map, not io space */
+#endif
write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
mdelay(40);
}
@@ -1895,18 +1898,26 @@
if (ret != 0) return ret;
if (req->Attributes & IRQ_HANDLE_PRESENT) {
- if (bus_request_irq(s->cap.bus, irq, req->Handler,
- ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) ||
- (s->functions > 1) ||
- (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0,
- handle->dev_info, req->Instance))
+ int result;
+ int type = ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING)
+#ifndef CONFIG_SA1100_OMNIMETER
+ || (irq == s->cap.pci_irq)
+#endif
+ || (s->functions > 1))
+ ? SA_SHIRQ : 0;
+
+ result = bus_request_irq(s->cap.bus, irq, req->Handler, type,
+ handle->dev_info, req->Instance);
+ printk ("pcmcis_request_irq: %d, %d, %d. result=%d\n", irq,
+ req->Attributes & IRQ_HANDLE_PRESENT, type, result);
+ if (result)
return CS_IN_USE;
}
c->irq.Attributes = req->Attributes;
s->irq.AssignedIRQ = req->AssignedIRQ = irq;
s->irq.Config++;
-
+
c->state |= CONFIG_IRQ_REQ;
handle->state |= CLIENT_IRQ_REQ;
return CS_SUCCESS;