[PATCH] try to keep hd64465 socket driver up to date
Dominik Brodowski
linux at brodo.de
Sat Jul 5 13:00:29 BST 2003
Even though the hd64465_ss.c driver seems to be very broken [note the
#error in lines 625-628], try to keep it up to date wrt pcmcia core
changes in 2.5.
This patch includes the following changes:
- irqreturn_t update
- callbacks use pcmcia_socket * not integer
- remove "inquire_socket"
- move "owner" field to pcmcia_socket
- allow socket drivers to call pcmcia_parse_events directly
- Remove work handler and work queue. Call pcmcia_parse_events direct
from interrupt handler.
- update registration process
drivers/pcmcia/hd64465_ss.c | 186 ++++++++++++++------------------------------
1 files changed, 62 insertions(+), 124 deletions(-)
diff -ruN linux-original/drivers/pcmcia/hd64465_ss.c linux/drivers/pcmcia/hd64465_ss.c
--- linux-original/drivers/pcmcia/hd64465_ss.c 2003-07-05 10:22:58.000000000 +0200
+++ linux/drivers/pcmcia/hd64465_ss.c 2003-07-05 11:51:06.000000000 +0200
@@ -1,5 +1,5 @@
/*
- * $Id$
+ * $Id: hd64465_ss.c,v 1.6 2003/05/04 19:29:58 lethal Exp $
*
* Device driver for the PCMCIA controller module of the
* Hitachi HD64465 handheld companion chip.
@@ -74,38 +74,26 @@
typedef struct hs_socket_t
{
+ unsigned int number;
u_int irq;
u_long mem_base;
u_long mem_length;
- void (*handler)(void *info, u_int events);
- void *handler_info;
- u_int pending_events;
u_int ctrl_base;
socket_state_t state;
pccard_io_map io_maps[MAX_IO_WIN];
pccard_mem_map mem_maps[MAX_WIN];
struct vm_struct *io_vma; /* allocated kernel vm for mapping IO space */
+ struct pcmcia_socket socket;
} hs_socket_t;
+
+
#define HS_MAX_SOCKETS 2
static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
-static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED;
/* Calculate socket number from ptr into hs_sockets[] */
#define hs_sockno(sp) (sp - hs_sockets)
-static socket_cap_t hs_socket_cap =
-{
- SS_CAP_PCCARD /* support 16 bit cards */
- |SS_CAP_STATIC_MAP /* mappings are fixed in host memory */
- ,
- 0xffde/*0xffff*/, /* IRQs mapped in s/w so can do any, really */
- HD64465_PCC_WINDOW, /* 16MB fixed window size */
- 0, /* no PCI support */
- 0, /* no CardBus support */
- 0 /* no bus operations needed */
-};
-
#define hs_in(sp, r) inb((sp)->ctrl_base + (r))
#define hs_out(sp, v, r) outb(v, (sp)->ctrl_base + (r))
@@ -359,11 +347,11 @@
/*============================================================*/
-static int hs_init(unsigned int sock)
+static int hs_init(struct pcmcia_socket *s)
{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
- DPRINTK("hs_init(%d)\n", sock);
+ DPRINTK("hs_init(%d)\n", sp->number);
sp->pending_events = 0;
sp->state.Vcc = 0;
@@ -375,9 +363,10 @@
/*============================================================*/
-static int hs_suspend(unsigned int sock)
+static int hs_suspend(struct pcmcia_socket *s)
{
- DPRINTK("hs_suspend(%d)\n", sock);
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
+ DPRINTK("hs_suspend(%d)\n", sp->number);
/* TODO */
@@ -386,32 +375,10 @@
/*============================================================*/
-static int hs_register_callback(unsigned int sock,
- void (*handler)(void *, unsigned int), void * info)
-{
- hs_socket_t *sp = &hs_sockets[sock];
-
- DPRINTK("hs_register_callback(%d)\n", sock);
- sp->handler = handler;
- sp->handler_info = info;
- return 0;
-}
-
-/*============================================================*/
-static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap)
+static int hs_get_status(struct pcmcia_socket *s, u_int *value)
{
- DPRINTK("hs_inquire_socket(%d)\n", sock);
-
- *cap = hs_socket_cap;
- return 0;
-}
-
-/*============================================================*/
-
-static int hs_get_status(unsigned int sock, u_int *value)
-{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
unsigned int isr;
u_int status = 0;
@@ -473,9 +440,9 @@
/*============================================================*/
-static int hs_get_socket(unsigned int sock, socket_state_t *state)
+static int hs_get_socket(struct pcmcia_socket *s, socket_state_t *state)
{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
DPRINTK("hs_get_socket(%d)\n", sock);
@@ -485,9 +452,9 @@
/*============================================================*/
-static int hs_set_socket(unsigned int sock, socket_state_t *state)
+static int hs_set_socket(struct pcmcia_socket *s, socket_state_t *state)
{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
u_long flags;
u_int changed;
unsigned short cscier;
@@ -495,12 +462,12 @@
DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n",
sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
- save_and_cli(flags); /* Don't want interrupts happening here */
+ local_irq_save(flags); /* Don't want interrupts happening here */
if (state->Vpp != sp->state.Vpp ||
state->Vcc != sp->state.Vcc) {
if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) {
- restore_flags(flags);
+ local_irq_restore(flags);
return -EINVAL;
}
}
@@ -588,7 +555,7 @@
/* hd64465_io_debug = 0; */
sp->state = *state;
- restore_flags(flags);
+ local_irq_restore(flags);
#if HD64465_DEBUG > 10
if (state->flags & SS_OUTPUT_ENA)
@@ -599,9 +566,9 @@
/*============================================================*/
-static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
+static int hs_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
int map = io->map;
struct pccard_io_map *sio;
pgprot_t prot;
@@ -681,9 +648,9 @@
/*============================================================*/
-static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+static int hs_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
{
- hs_socket_t *sp = &hs_sockets[sock];
+ hs_socket_t *sp = container_of(s, struct hs_socket_t, socket);
struct pccard_mem_map *smem;
int map = mem->map;
unsigned long paddr, size;
@@ -722,13 +689,6 @@
/*============================================================*/
-static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base)
-{
- DPRINTK("hs_proc_setup(%d)\n", sock);
-}
-
-/*============================================================*/
-
/*
* This function is registered with the HD64465 glue code to do a
* secondary demux step on the PCMCIA interrupts. It handles
@@ -756,35 +716,9 @@
/*
* Interrupt handling routine.
- *
- * This uses the schedule_work() technique to cause reportable events
- * such as card insertion and removal to be handled in keventd's
- * process context.
*/
-
-static void hs_events_bh(void *dummy)
-{
- hs_socket_t *sp;
- u_int events;
- int i;
-
- for (i=0; i<HS_MAX_SOCKETS; i++) {
- sp = &hs_sockets[i];
-
- spin_lock_irq(&hs_pending_event_lock);
- events = sp->pending_events;
- sp->pending_events = 0;
- spin_unlock_irq(&hs_pending_event_lock);
-
- if (sp->handler)
- sp->handler(sp->handler_info, events);
- }
-}
-
-static DECLARE_WORK(hs_events_task, hs_events_bh, NULL);
-
-static void hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+static irqreturn_t hs_interrupt(int irq, void *dev, struct pt_regs *regs)
{
hs_socket_t *sp = (hs_socket_t *)dev;
u_int events = 0;
@@ -839,34 +773,22 @@
hs_out(sp, cscr, CSCR);
- if (events) {
- /*
- * Arrange for events to be reported to the registered
- * event handler function (from CardServices) in a process
- * context (keventd) "soon".
- */
- spin_lock(&hs_pending_event_lock);
- sp->pending_events |= events;
- spin_unlock(&hs_pending_event_lock);
-
- schedule_work(&hs_events_task);
- }
+ if (events)
+ pcmcia_parse_events(&sp->socket, events);
+
+ return IRQ_HANDLED;
}
/*============================================================*/
static struct pccard_operations hs_operations = {
- .owner = THIS_MODULE,
.init = hs_init,
.suspend = hs_suspend,
- .register_callback = hs_register_callback,
- .inquire_socket = hs_inquire_socket,
.get_status = hs_get_status,
.get_socket = hs_get_socket,
.set_socket = hs_set_socket,
.set_io_map = hs_set_io_map,
.set_mem_map = hs_set_mem_map,
- .proc_setup = hs_proc_setup,
};
static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base,
@@ -959,15 +881,9 @@
vfree(sp->io_vma->addr);
}
-static struct pcmcia_socket_class_data hd64465_data = {
- .nsock = HS_MAX_SOCKETS,
- .ops = &hs_operations,
-};
-
static struct device_driver hd64465_driver = {
.name = "hd64465-pcmcia",
.bus = &platform_bus_type,
- .devclass = &pcmcia_socket_class,
.suspend = pcmcia_socket_dev_suspend,
.resume = pcmcia_socket_dev_resume,
};
@@ -996,7 +912,8 @@
}
/* hd64465_io_debug = 1; */
- register_driver(&hd64465_driver);
+ if (driver_register(&hd64465_driver))
+ return -EINVAL;
/* Wake both sockets out of STANDBY mode */
/* TODO: wait 15ms */
@@ -1014,36 +931,53 @@
v |= HD64465_PCCCSCR_PSWSEL;
outb(v, HD64465_REG_PCC0CSCR);
- hs_set_voltages(&hs_sockets[0], 0, 0);
- hs_set_voltages(&hs_sockets[1], 0, 0);
-
/*
* Setup hs_sockets[] structures and request system resources.
* TODO: on memory allocation failure, power down the socket
* before quitting.
*/
+ for (i=0; i<2; i++) {
+ hs_set_voltages(&hs_sockets[i], 0, 0);
+
+ hs_sockets[i].socket.features |= SS_CAP_PCCARD | SS_CAP_STATIC_MAP; /* mappings are fixed in host memory */
+ hs_sockets[i].socket.irq_mask = 0xffde;/*0xffff*/ /* IRQs mapped in s/w so can do any, really */
+ hs_sockets[i].socket.map_size = HD64465_PCC_WINDOW; /* 16MB fixed window size */
+
+ hs_sockets[i].socket.owner = THIS_MODULE;
+ hs_sockets[i].socket.ss_entry = &hs_operations;
+ }
+
i = hs_init_socket(&hs_sockets[0],
HD64465_IRQ_PCMCIA0,
HD64465_PCC0_BASE,
HD64465_REG_PCC0ISR);
if (i < 0) {
unregister_driver(&hd64465_driver);
- return i;
+ return i;
}
+
i = hs_init_socket(&hs_sockets[1],
HD64465_IRQ_PCMCIA1,
HD64465_PCC1_BASE,
HD64465_REG_PCC1ISR);
if (i < 0) {
unregister_driver(&hd64465_driver);
- return i;
+ return i;
}
/* hd64465_io_debug = 0; */
- hd64465_device.dev.class_data = &hd64465_data;
+
platform_device_register(&hd64465_device);
- return 0;
+ for (i=0; i<2; i++) {
+ unsigned int ret;
+ hs_sockets[i].socket.dev.dev = &hd64465_device.dev;
+ ret = pcmcia_register_socket(&hs_sockets[i].socket);
+ if (ret && i)
+ pcmcia_unregister_socket(&hs_socket[0].socket);
+ }
+
+ return 0;
}
static void __exit exit_hs(void)
@@ -1051,16 +985,20 @@
u_long flags;
int i;
- save_and_cli(flags);
+ for (i=0 ; i<HS_MAX_SOCKETS ; i++)
+ pcmcia_unregister_socket(&hs_socket[i].socket);
+
+ local_irq_save(flags);
/*
* Release kernel resources
*/
for (i=0 ; i<HS_MAX_SOCKETS ; i++)
hs_exit_socket(&hs_sockets[i]);
- platform_device_unregister(&hd64465_device);
- restore_flags(flags);
+ local_irq_restore(flags);
+
+ platform_device_unregister(&hd64465_device);
unregister_driver(&hd64465_driver);
}
More information about the linux-pcmcia
mailing list