[PATCH] pcmcia: Add support for Possio GCC AKA PCMCIA Siemens MC45
This ugly hack add support for Siemens MC45 PCMCIA GPRS card (which is identical to Possio GCC, and which is offered by one of our local GPRS providers). Card has unfortunate feature that after poweron oxcf950 chip is fully powered and works, but attached MC45 modem is powered down :-( There is a special sequence (which takes 1 sec :-( ) to poweron MC45 (and after MC45 powers on, it takes more than 2 secs until firmware fully boots...) which needs to be executed after all powerons. I'm really not familiar with PCMCIA subsystem, so I have no idea whether I should issue request_region() on rest of oxcf950 address range (0-7 is UART, 8-F are special configuration registers), or how this should be better integrated with PM system and so on - I just put it in same place where another hack already lived... Card uses 18.432MHz XTAL, so to get it to work you must add lines below to the /etc/pcmcia/serial.opts. case "$MANFID-$FUNCID-$PRODID_1-$PRODID_2-$PRODID_3-$PRODID_4" in '030c,0003-2-GPRS-CARD--') SERIAL_OPTS="baud_base 1152000" ;; esac Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
parent
d6ff5a8532
commit
30bac7aa0e
|
@ -41,6 +41,7 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
#include <linux/serial_core.h>
|
#include <linux/serial_core.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/major.h>
|
#include <linux/major.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -102,6 +103,8 @@ struct serial_info {
|
||||||
int multi;
|
int multi;
|
||||||
int slave;
|
int slave;
|
||||||
int manfid;
|
int manfid;
|
||||||
|
int prodid;
|
||||||
|
int c950ctrl;
|
||||||
dev_node_t node[4];
|
dev_node_t node[4];
|
||||||
int line[4];
|
int line[4];
|
||||||
};
|
};
|
||||||
|
@ -116,6 +119,33 @@ struct serial_cfg_mem {
|
||||||
static int serial_config(struct pcmcia_device * link);
|
static int serial_config(struct pcmcia_device * link);
|
||||||
|
|
||||||
|
|
||||||
|
static void wakeup_card(struct serial_info *info)
|
||||||
|
{
|
||||||
|
int ctrl = info->c950ctrl;
|
||||||
|
|
||||||
|
if (info->manfid == MANFID_OXSEMI) {
|
||||||
|
outb(12, ctrl + 1);
|
||||||
|
} else if (info->manfid == MANFID_POSSIO && info->prodid == PRODID_POSSIO_GCC) {
|
||||||
|
/* request_region? oxsemi branch does no request_region too... */
|
||||||
|
/* This sequence is needed to properly initialize MC45 attached to OXCF950.
|
||||||
|
* I tried decreasing these msleep()s, but it worked properly (survived
|
||||||
|
* 1000 stop/start operations) with these timeouts (or bigger). */
|
||||||
|
outb(0xA, ctrl + 1);
|
||||||
|
msleep(100);
|
||||||
|
outb(0xE, ctrl + 1);
|
||||||
|
msleep(300);
|
||||||
|
outb(0xC, ctrl + 1);
|
||||||
|
msleep(100);
|
||||||
|
outb(0xE, ctrl + 1);
|
||||||
|
msleep(200);
|
||||||
|
outb(0xF, ctrl + 1);
|
||||||
|
msleep(100);
|
||||||
|
outb(0xE, ctrl + 1);
|
||||||
|
msleep(100);
|
||||||
|
outb(0xC, ctrl + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*======================================================================
|
/*======================================================================
|
||||||
|
|
||||||
After a card is removed, serial_remove() will unregister
|
After a card is removed, serial_remove() will unregister
|
||||||
|
@ -161,6 +191,7 @@ static int serial_resume(struct pcmcia_device *link)
|
||||||
|
|
||||||
for (i = 0; i < info->ndev; i++)
|
for (i = 0; i < info->ndev; i++)
|
||||||
serial8250_resume_port(info->line[i]);
|
serial8250_resume_port(info->line[i]);
|
||||||
|
wakeup_card(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -503,15 +534,23 @@ static int multi_config(struct pcmcia_device * link)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
|
/* The Oxford Semiconductor OXCF950 cards are in fact single-port:
|
||||||
8 registers are for the UART, the others are extra registers */
|
* 8 registers are for the UART, the others are extra registers.
|
||||||
if (info->manfid == MANFID_OXSEMI) {
|
* Siemen's MC45 PCMCIA (Possio's GCC) is OXCF950 based too.
|
||||||
|
*/
|
||||||
|
if (info->manfid == MANFID_OXSEMI || (info->manfid == MANFID_POSSIO &&
|
||||||
|
info->prodid == PRODID_POSSIO_GCC)) {
|
||||||
|
int err;
|
||||||
|
|
||||||
if (cf->index == 1 || cf->index == 3) {
|
if (cf->index == 1 || cf->index == 3) {
|
||||||
setup_serial(link, info, base2, link->irq.AssignedIRQ);
|
err = setup_serial(link, info, base2,
|
||||||
outb(12, link->io.BasePort1 + 1);
|
link->irq.AssignedIRQ);
|
||||||
|
base2 = link->io.BasePort1;
|
||||||
} else {
|
} else {
|
||||||
setup_serial(link, info, link->io.BasePort1, link->irq.AssignedIRQ);
|
err = setup_serial(link, info, link->io.BasePort1,
|
||||||
outb(12, base2 + 1);
|
link->irq.AssignedIRQ);
|
||||||
}
|
}
|
||||||
|
info->c950ctrl = base2;
|
||||||
|
wakeup_card(info);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto free_cfg_mem;
|
goto free_cfg_mem;
|
||||||
}
|
}
|
||||||
|
@ -583,6 +622,7 @@ static int serial_config(struct pcmcia_device * link)
|
||||||
tuple->DesiredTuple = CISTPL_MANFID;
|
tuple->DesiredTuple = CISTPL_MANFID;
|
||||||
if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
|
if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
|
||||||
info->manfid = parse->manfid.manf;
|
info->manfid = parse->manfid.manf;
|
||||||
|
info->prodid = le16_to_cpu(buf[1]);
|
||||||
for (i = 0; i < MULTI_COUNT; i++)
|
for (i = 0; i < MULTI_COUNT; i++)
|
||||||
if ((info->manfid == multi_id[i].manfid) &&
|
if ((info->manfid == multi_id[i].manfid) &&
|
||||||
(parse->manfid.card == multi_id[i].prodid))
|
(parse->manfid.card == multi_id[i].prodid))
|
||||||
|
|
|
@ -122,4 +122,7 @@
|
||||||
|
|
||||||
#define MANFID_XIRCOM 0x0105
|
#define MANFID_XIRCOM 0x0105
|
||||||
|
|
||||||
|
#define MANFID_POSSIO 0x030c
|
||||||
|
#define PRODID_POSSIO_GCC 0x0003
|
||||||
|
|
||||||
#endif /* _LINUX_CISCODE_H */
|
#endif /* _LINUX_CISCODE_H */
|
||||||
|
|
Loading…
Reference in New Issue