#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/system.h>
-#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/ss.h>
#include <pcmcia/cs.h>
#include "cirrus.h"
#include "vg468.h"
#include "ricoh.h"
-#include "o2micro.h"
#ifdef DEBUG
static const char version[] =
/* Parameters that can be set with 'insmod' */
/* Default base address for i82365sl and other ISA chips */
-static int i365_base = 0x3e0;
+static unsigned long i365_base = 0x3e0;
/* Should we probe at 0x3e2 for an extra ISA controller? */
static int extra_sockets = 0;
/* Specify a socket number to ignore */
static int cable_mode = -1;
static int wakeup = 0;
-module_param(i365_base, int, 0444);
+module_param(i365_base, ulong, 0444);
module_param(ignore, int, 0444);
module_param(extra_sockets, int, 0444);
module_param(irq_mask, int, 0444);
-module_param_array(irq_list, int, irq_list_count, 0444);
+module_param_array(irq_list, int, &irq_list_count, 0444);
module_param(cs_irq, int, 0444);
module_param(async_clock, int, 0444);
module_param(cable_mode, int, 0444);
u_short type, flags;
struct pcmcia_socket socket;
unsigned int number;
- ioaddr_t ioaddr;
+ kio_addr_t ioaddr;
u_short psock;
u_char cs_irq, intr;
union {
#define I365_MASK 0xdeb8 /* irq 15,14,12,11,10,9,7,5,4,3 */
static int grab_irq;
-static spinlock_t isa_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(isa_lock);
#define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
#define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
#define IS_UNKNOWN 0x0400
#define IS_VG_PWR 0x0800
#define IS_DF_PWR 0x1000
+#define IS_REGISTERED 0x2000
#define IS_ALIVE 0x8000
typedef struct pcic_t {
/*====================================================================*/
-static spinlock_t bus_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(bus_lock);
static u_char i365_get(u_short sock, u_short reg)
{
unsigned long flags;
spin_lock_irqsave(&bus_lock,flags);
{
- ioaddr_t port = socket[sock].ioaddr;
+ kio_addr_t port = socket[sock].ioaddr;
u_char val;
reg = I365_REG(socket[sock].psock, reg);
outb(reg, port); val = inb(port+1);
unsigned long flags;
spin_lock_irqsave(&bus_lock,flags);
{
- ioaddr_t port = socket[sock].ioaddr;
+ kio_addr_t port = socket[sock].ioaddr;
u_char val = I365_REG(socket[sock].psock, reg);
outb(val, port); outb(data, port+1);
spin_unlock_irqrestore(&bus_lock,flags);
if (request_irq(irq, i365_count_irq, 0, "scan", i365_count_irq) != 0)
return 1;
irq_hits = 0; irq_sock = sock;
- __set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ/100);
+ msleep(10);
if (irq_hits) {
free_irq(irq, i365_count_irq);
debug(2, " spurious hit!\n");
/*====================================================================*/
-static int __init identify(u_short port, u_short sock)
+static int __init identify(kio_addr_t port, u_short sock)
{
u_char val;
int type = -1;
static int __init is_alive(u_short sock)
{
u_char stat;
- u_short start, stop;
+ kio_addr_t start, stop;
stat = i365_get(sock, I365_STATUS);
start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
(i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&
(i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&
- (check_region(start, stop-start+1) != 0) &&
- ((start & 0xfeef) != 0x02e8))
- return 1;
- else
- return 0;
+ ((start & 0xfeef) != 0x02e8)) {
+ if (!request_region(start, stop-start+1, "i82365"))
+ return 1;
+ release_region(start, stop-start+1);
+ }
+
+ return 0;
}
/*====================================================================*/
-static void __init add_socket(u_short port, int psock, int type)
+static void __init add_socket(kio_addr_t port, int psock, int type)
{
socket[sockets].ioaddr = port;
socket[sockets].psock = psock;
struct i82365_socket *t = &socket[sockets-ns];
base = sockets-ns;
- if (t->ioaddr > 0) request_region(t->ioaddr, 2, "i82365");
-
if (base == 0) printk("\n");
printk(KERN_INFO " %s", pcic[type].name);
- printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
+ printk(" ISA-to-PCMCIA at port %#lx ofs 0x%02x",
t->ioaddr, t->psock*0x40);
printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
static void __init isa_probe(void)
{
int i, j, sock, k, ns, id;
- ioaddr_t port;
+ kio_addr_t port;
#ifdef CONFIG_PNP
struct isapnp_device_id *devid;
struct pnp_dev *dev;
}
#endif
- if (check_region(i365_base, 2) != 0) {
+ if (!request_region(i365_base, 2, "i82365")) {
if (sockets == 0)
- printk("port conflict at %#x\n", i365_base);
+ printk("port conflict at %#lx\n", i365_base);
return;
}
/*====================================================================*/
-static int i365_get_socket(u_short sock, socket_state_t *state)
-{
- struct i82365_socket *t = &socket[sock];
- u_char reg, vcc, vpp;
-
- reg = i365_get(sock, I365_POWER);
- state->flags = (reg & I365_PWR_AUTO) ? SS_PWR_AUTO : 0;
- state->flags |= (reg & I365_PWR_OUT) ? SS_OUTPUT_ENA : 0;
- vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
- state->Vcc = state->Vpp = 0;
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_VCC_3V) {
- if (reg & I365_VCC_5V) state->Vcc = 33;
- if (vpp == I365_VPP1_5V) state->Vpp = 33;
- } else {
- if (reg & I365_VCC_5V) state->Vcc = 50;
- if (vpp == I365_VPP1_5V) state->Vpp = 50;
- }
- if (vpp == I365_VPP1_12V) state->Vpp = 120;
- } else if (t->flags & IS_VG_PWR) {
- if (i365_get(sock, VG469_VSELECT) & VG469_VSEL_VCC) {
- if (reg & I365_VCC_5V) state->Vcc = 33;
- if (vpp == I365_VPP1_5V) state->Vpp = 33;
- } else {
- if (reg & I365_VCC_5V) state->Vcc = 50;
- if (vpp == I365_VPP1_5V) state->Vpp = 50;
- }
- if (vpp == I365_VPP1_12V) state->Vpp = 120;
- } else if (t->flags & IS_DF_PWR) {
- if (vcc == I365_VCC_3V) state->Vcc = 33;
- if (vcc == I365_VCC_5V) state->Vcc = 50;
- if (vpp == I365_VPP1_5V) state->Vpp = 50;
- if (vpp == I365_VPP1_12V) state->Vpp = 120;
- } else {
- if (reg & I365_VCC_5V) {
- state->Vcc = 50;
- if (vpp == I365_VPP1_5V) state->Vpp = 50;
- if (vpp == I365_VPP1_12V) state->Vpp = 120;
- }
- }
-
- /* IO card, RESET flags, IO interrupt */
- reg = i365_get(sock, I365_INTCTL);
- state->flags |= (reg & I365_PC_RESET) ? 0 : SS_RESET;
- if (reg & I365_PC_IOCARD) state->flags |= SS_IOCARD;
- state->io_irq = reg & I365_IRQ_MASK;
-
- /* speaker control */
- if (t->flags & IS_CIRRUS) {
- if (i365_get(sock, PD67_MISC_CTL_1) & PD67_MC1_SPKR_ENA)
- state->flags |= SS_SPKR_ENA;
- }
-
- /* Card status change mask */
- reg = i365_get(sock, I365_CSCINT);
- state->csc_mask = (reg & I365_CSC_DETECT) ? SS_DETECT : 0;
- if (state->flags & SS_IOCARD)
- state->csc_mask |= (reg & I365_CSC_STSCHG) ? SS_STSCHG : 0;
- else {
- state->csc_mask |= (reg & I365_CSC_BVD1) ? SS_BATDEAD : 0;
- state->csc_mask |= (reg & I365_CSC_BVD2) ? SS_BATWARN : 0;
- state->csc_mask |= (reg & I365_CSC_READY) ? SS_READY : 0;
- }
-
- debug(1, "GetSocket(%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);
- return 0;
-} /* i365_get_socket */
-
-/*====================================================================*/
-
static int i365_set_socket(u_short sock, socket_state_t *state)
{
struct i82365_socket *t = &socket[sock];
u_char map, ioctl;
debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4x-%#4.4x)\n", sock, io->map, io->flags,
+ "%#lx-%#lx)\n", sock, io->map, io->flags,
io->speed, io->start, io->stop);
map = io->map;
if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
u_short base, i;
u_char map;
- debug(1, "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);
+ debug(1, "SetMemMap(%d, %d, %#2.2x, %d ns, %#lx-%#lx, "
+ "%#x)\n", sock, mem->map, mem->flags, mem->speed,
+ mem->res->start, mem->res->end, mem->card_start);
map = mem->map;
if ((map > 4) || (mem->card_start > 0x3ffffff) ||
- (mem->sys_start > mem->sys_stop) || (mem->speed > 1000))
+ (mem->res->start > mem->res->end) || (mem->speed > 1000))
return -EINVAL;
- if ((mem->sys_start > 0xffffff) || (mem->sys_stop > 0xffffff))
+ if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
return -EINVAL;
/* Turn off the window before changing anything */
i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
base = I365_MEM(map);
- i = (mem->sys_start >> 12) & 0x0fff;
+ i = (mem->res->start >> 12) & 0x0fff;
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;
+ i = (mem->res->end >> 12) & 0x0fff;
switch (to_cycles(mem->speed)) {
case 0: break;
case 1: i |= I365_MEM_WS0; break;
}
i365_set_pair(sock, base+I365_W_STOP, i);
- i = ((mem->card_start - mem->sys_start) >> 12) & 0x3fff;
+ i = ((mem->card_start - mem->res->start) >> 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);
LOCKED(i365_get_status(sock, value));
}
-static int pcic_get_socket(struct pcmcia_socket *s, socket_state_t *state)
-{
- unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
-
- if (socket[sock].flags & IS_ALIVE)
- return -EINVAL;
-
- LOCKED(i365_get_socket(sock, state));
-}
-
static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
static int pcic_init(struct pcmcia_socket *s)
{
int i;
+ struct resource res = { .start = 0, .end = 0x1000 };
pccard_io_map io = { 0, 0, 0, 0, 1 };
- pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
+ pccard_mem_map mem = { .res = &res, };
- mem.sys_stop = 0x1000;
for (i = 0; i < 2; i++) {
io.map = i;
pcic_set_io_map(s, &io);
return 0;
}
-static int pcic_suspend(struct pcmcia_socket *sock)
-{
- return pcic_set_socket(sock, &dead_socket);
-}
-
static struct pccard_operations pcic_operations = {
.init = pcic_init,
- .suspend = pcic_suspend,
.get_status = pcic_get_status,
- .get_socket = pcic_get_socket,
.set_socket = pcic_set_socket,
.set_io_map = pcic_set_io_map,
.set_mem_map = pcic_set_mem_map,
/*====================================================================*/
-static int i82365_suspend(struct device *dev, u32 state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int i82365_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver i82365_driver = {
.name = "i82365",
.bus = &platform_bus_type,
- .suspend = i82365_suspend,
- .resume = i82365_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
-static struct platform_device i82365_device = {
- .name = "i82365",
- .id = 0,
-};
+static struct platform_device *i82365_device;
static int __init init_i82365(void)
{
int i, ret;
- if (driver_register(&i82365_driver))
- return -1;
+ ret = driver_register(&i82365_driver);
+ if (ret)
+ return ret;
+
+ i82365_device = platform_device_alloc("i82365", 0);
+ if (i82365_device) {
+ ret = platform_device_add(i82365_device);
+ if (ret)
+ platform_device_put(i82365_device);
+ } else
+ ret = -ENOMEM;
+
+ if (ret) {
+ driver_unregister(&i82365_driver);
+ return ret;
+ }
printk(KERN_INFO "Intel ISA PCIC probe: ");
sockets = 0;
if (sockets == 0) {
printk("not found.\n");
+ platform_device_unregister(i82365_device);
+ release_region(i365_base, 2);
driver_unregister(&i82365_driver);
return -ENODEV;
}
- platform_device_register(&i82365_device);
-
/* Set up interrupt handler(s) */
if (grab_irq != 0)
request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
/* register sockets with the pcmcia core */
for (i = 0; i < sockets; i++) {
- socket[i].socket.dev.dev = &i82365_device.dev;
+ socket[i].socket.dev.dev = &i82365_device->dev;
socket[i].socket.ops = &pcic_operations;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
- ret = pcmcia_register_socket(&socket[i].socket);
- if (ret && i--) {
- for (; i>= 0; i--)
- pcmcia_unregister_socket(&socket[i].socket);
- break;
- }
+ ret = pcmcia_register_socket(&socket[i].socket);
+ if (!ret)
+ socket[i].flags |= IS_REGISTERED;
+
#if 0 /* driver model ordering issue */
class_device_create_file(&socket[i].socket.dev,
&class_device_attr_info);
int i;
for (i = 0; i < sockets; i++) {
- pcmcia_unregister_socket(&socket[i].socket);
+ if (socket[i].flags & IS_REGISTERED)
+ pcmcia_unregister_socket(&socket[i].socket);
}
- platform_device_unregister(&i82365_device);
+ platform_device_unregister(i82365_device);
if (poll_interval != 0)
del_timer_sync(&poll_timer);
if (grab_irq != 0)
i365_set(i, I365_CSCINT, 0);
release_region(socket[i].ioaddr, 2);
}
-#ifdef __ISAPNP__
+ release_region(i365_base, 2);
+#ifdef CONFIG_PNP
if (i82365_pnpdev)
pnp_disable_dev(i82365_pnpdev);
#endif