[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-mips
Subject:    patch for  2.6.14-rc1 for pcmcia on swarm
From:       "Peter 'p2' De Schrijver" <p2 () debian ! org>
Date:       2005-09-23 0:35:03
Message-ID: 20050923003502.GC16161 () codecarver
[Download RAW message or body]

[Attachment #2 (multipart/mixed)]


Hi,

The attached patch implements a hacked pcmcia driver for the Sibyte
swarm board. The driver has only been tested with storage cards (eg. CF
cards). It will probably not work with anything else.
The main problem is that the swarm pcmcia hardware only seems to be capable of 
generating memory accesses on the pcmcia bus. I don't know if this is a 
hardware limition of the swarm board or just a lack of documentation. I 
haven't found any documented way of generating a pcmcia i/o access on the 
swarm board. 

Cheers,

Peter (p2).

-- 
goa is a state of mind

["patch-sb1-pcmcia" (text/plain)]

diff -urN -x asm -x scripts -x config linux/drivers/ide/legacy/ide-cs.c \
                linux-my/drivers/ide/legacy/ide-cs.c
--- linux/drivers/ide/legacy/ide-cs.c	2005-09-15 10:54:18.000000000 +0200
+++ linux-my/drivers/ide/legacy/ide-cs.c	2005-09-22 18:06:17.000000000 +0200
@@ -186,10 +186,19 @@
 static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq)
 {
     hw_regs_t hw;
+
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+	extern int sb_pcmcia_ack_intr(struct hwif_s *hwif);
+#endif
+
     memset(&hw, 0, sizeof(hw));
     ide_init_hwif_ports(&hw, io, ctl, NULL);
     hw.irq = irq;
     hw.chipset = ide_pci;
+
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+    hw.ack_intr=sb_pcmcia_ack_intr;
+#endif
     return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave);
 }
 
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/Kconfig \
                linux-my/drivers/pcmcia/Kconfig
--- linux/drivers/pcmcia/Kconfig	2005-09-15 10:54:58.000000000 +0200
+++ linux-my/drivers/pcmcia/Kconfig	2005-09-22 16:50:27.000000000 +0200
@@ -221,6 +221,10 @@
 	tristate "NEC VRC4173 CARDU support"
 	depends on CPU_VR41XX && PCI && PCMCIA
 
+config PCMCIA_SIBYTE_SB1xxx_SOC
+        tristate "SiByte SB1xxxx PCMCIA support"
+        depends on PCMCIA && SIBYTE_SB1xxx_SOC
+
 config OMAP_CF
 	tristate "OMAP CompactFlash Controller"
 	depends on PCMCIA && ARCH_OMAP16XX
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/Makefile \
                linux-my/drivers/pcmcia/Makefile
--- linux/drivers/pcmcia/Makefile	2005-09-17 02:38:10.000000000 +0200
+++ linux-my/drivers/pcmcia/Makefile	2005-09-22 16:50:43.000000000 +0200
@@ -35,6 +35,8 @@
 obj-$(CONFIG_PCMCIA_VRC4171)			+= vrc4171_card.o
 obj-$(CONFIG_PCMCIA_VRC4173)			+= vrc4173_cardu.o
 obj-$(CONFIG_OMAP_CF)				+= omap_cf.o
+obj-$(CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC)          += sibyte_generic.o
+
 
 sa11xx_core-y					+= soc_common.o sa11xx_base.o
 pxa2xx_core-y					+= soc_common.o pxa2xx_base.o
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/pcmcia_resource.c \
                linux-my/drivers/pcmcia/pcmcia_resource.c
--- linux/drivers/pcmcia/pcmcia_resource.c	2005-09-15 10:54:58.000000000 +0200
+++ linux-my/drivers/pcmcia/pcmcia_resource.c	2005-09-22 17:26:24.000000000 +0200
@@ -648,6 +648,7 @@
 		c->Copy = req->Copy;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy);
 	}
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
 	if (req->Present & PRESENT_OPTION) {
 		if (s->functions == 1) {
 			c->Option = req->ConfigIndex & COR_CONFIG_MASK;
@@ -663,6 +664,7 @@
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option);
 		mdelay(40);
 	}
+#endif
 	if (req->Present & PRESENT_STATUS) {
 		c->Status = req->Status;
 		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status);
diff -urN -x asm -x scripts -x config linux/drivers/pcmcia/sibyte_generic.c \
                linux-my/drivers/pcmcia/sibyte_generic.c
--- linux/drivers/pcmcia/sibyte_generic.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-my/drivers/pcmcia/sibyte_generic.c	2005-09-22 16:56:24.000000000 +0200
@@ -0,0 +1,558 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/cpufreq.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/notifier.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+#include <linux/ide.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#include <asm/sibyte/board.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_int.h>
+#include <asm/sibyte/sb1250_genbus.h>
+
+#define IO_MAP_SIZE	0x1000
+
+#define CARDPRESENT(s) (((s) & (M_PCMCIA_STATUS_CD1 | \
+			M_PCMCIA_STATUS_CD2)) == 0)
+
+#define POWERON(s)	((s) & (M_PCMCIA_STATUS_3VEN | \
+			M_PCMCIA_STATUS_5VEN))
+
+#define SIBYTE_PCMCIA_POLL_PERIOD (2*HZ)
+
+DECLARE_MUTEX(pcmcia_sockets_lock);
+
+struct sibyte_pcmcia_socket {
+	struct pcmcia_socket socket;
+
+	struct device *dev;
+	int irq;
+
+	int status;
+	socket_state_t cs_state;
+
+	unsigned short	spd_io[MAX_IO_WIN];
+	unsigned short	spd_mem[MAX_WIN];
+
+	struct resource	res_skt;
+	struct resource	res_io;
+	struct resource	res_mem;
+
+	void *virt_io;
+	ioaddr_t phys_io;
+	unsigned int phys_mem;
+	unsigned short	speed_io, speed_attr, speed_mem;
+
+	unsigned int irq_state;
+
+	struct timer_list       poll_timer;
+
+};
+
+struct sibyte_pcmcia_socket sibyte_pcmcia_socket[1];
+#define PCMCIA_SOCKET(x) (sibyte_pcmcia_socket+x);
+
+static unsigned int sibyte_pcmcia_skt_state(struct sibyte_pcmcia_socket *skt)
+{
+	u32 stat;
+	unsigned int status=0;
+
+	stat=csr_in32(IOADDR(A_IO_PCMCIA_STATUS));
+	
+
+	if(CARDPRESENT(status)) 
+		status=SS_DETECT;
+	if(!(stat & M_PCMCIA_STATUS_VS1))
+		status|=SS_3VCARD;
+	if(!(stat & M_PCMCIA_STATUS_VS2))
+		status|=SS_XVCARD;
+	if(stat & M_PCMCIA_STATUS_WP)
+		status|=SS_WRPROT;
+	if(stat & M_PCMCIA_STATUS_RDY)
+		status|=SS_READY;
+	if(stat & POWERON(status))
+		status|=SS_POWERON;
+	if(stat & (M_PCMCIA_STATUS_CDCHG | M_PCMCIA_STATUS_WPCHG | 
+		   M_PCMCIA_STATUS_RDYCHG))
+		status|=SS_STSCHG;
+
+
+	return status;
+}
+
+static DEFINE_SPINLOCK(status_lock);
+
+static void sibyte_check_status(struct sibyte_pcmcia_socket *skt)
+{
+	unsigned int events;
+
+	do {
+		unsigned int status;
+		unsigned long flags;
+
+		status=sibyte_pcmcia_skt_state(skt);
+
+		spin_lock_irqsave(&status_lock, flags);
+		events = (status ^ skt->status) & skt->cs_state.csc_mask;
+		skt->status=status;
+		spin_unlock_irqrestore(&status_lock, flags);
+
+		if(events)
+			pcmcia_parse_events(&skt->socket, events);
+	} while(events);
+}
+
+
+static void sibyte_pcmcia_poll_event(unsigned long context)
+{
+	struct sibyte_pcmcia_socket *skt=
+		(struct sibyte_pcmcia_socket *)context;
+
+	mod_timer(&skt->poll_timer, jiffies + SIBYTE_PCMCIA_POLL_PERIOD);
+
+	sibyte_check_status(skt);
+}
+
+
+static irqreturn_t sibyte_pcmcia_interrupt(int irq, void *context, 
+					   struct pt_regs *regs)
+{
+	struct sibyte_pcmcia_socket *skt=
+		(struct sibyte_pcmcia_socket *)context;
+
+	sibyte_check_status(skt);
+
+	return IRQ_HANDLED;
+}
+		
+/* Note that Vpp is never set. There are normally 2 lines to the pcmcia
+ * power controller to control the Vpp level. The SB1250 PCMCIA control register
+ * however provides only 1 bit to control Vpp. Any information on the exact
+ * behaviour welcome.
+ */
+static int sibyte_pcmcia_config_skt(struct sibyte_pcmcia_socket *skt, 
+				    socket_state_t *state)
+{
+	u32 config;
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+
+	config &= ~(M_PCMCIA_CFG_3VEN | M_PCMCIA_CFG_5VEN);
+
+	switch(state->Vcc) {
+		case 33:
+			config|=M_PCMCIA_CFG_3VEN;
+			break;
+		case 50:
+			config|=M_PCMCIA_CFG_5VEN;
+			break;
+	}
+
+	if(state->csc_mask & SS_DETECT)
+		config&=~M_PCMCIA_CFG_CDMASK;
+	else
+		config|=M_PCMCIA_CFG_CDMASK;
+
+	config &= ~M_PCMCIA_CFG_RESET;
+	if(state->flags & SS_RESET) {
+		config|=M_PCMCIA_CFG_RESET;
+	}
+
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	return 0;
+}
+
+static int sibyte_pcmcia_sock_init(struct pcmcia_socket *sock)
+{
+	return 0;
+}
+
+
+static int sibyte_pcmcia_get_status(struct pcmcia_socket *sock, 
+				    unsigned int *status)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	skt->status=sibyte_pcmcia_skt_state(skt);
+	*status=skt->status;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_get_socket(struct pcmcia_socket *sock, 
+				    socket_state_t *state)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	*state=skt->cs_state;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_set_socket(struct pcmcia_socket *sock, 
+				    socket_state_t *state)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+
+	return sibyte_pcmcia_config_skt(skt,state);
+}
+
+static int sibyte_pcmcia_set_io_map(struct pcmcia_socket *sock, 
+			     	    struct pccard_io_map *io)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+	unsigned int speed;
+	u32 config;
+
+	if (io->map >= MAX_IO_WIN) {
+		return -1;
+	}
+
+	if (io->flags & MAP_ACTIVE) {
+		speed=(io->speed > 0) ? io->speed : 255;
+		skt->spd_io[io->map]=speed;
+	}
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+        config&=~M_PCMCIA_CFG_ATTRMEM;
+        csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	io->start=(ioaddr_t)(u32)skt->virt_io;
+	io->stop=io->start + IO_MAP_SIZE;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_set_mem_map(struct pcmcia_socket *sock, 
+				     struct pccard_mem_map *io)
+{
+        struct sibyte_pcmcia_socket *skt=
+                (struct sibyte_pcmcia_socket *)sock;
+	u32 config;
+	unsigned int speed=io->speed;
+
+	if(io->map >= MAX_WIN) {
+		return -1;
+	}
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+	if(io->flags & MAP_ATTRIB) {
+		config|=M_PCMCIA_CFG_ATTRMEM;
+	}
+	else {
+		config&=~M_PCMCIA_CFG_ATTRMEM;
+	}
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	skt->spd_mem[io->map]=speed;
+
+	io->static_start=skt->phys_mem;
+
+	return 0;
+}
+
+/* the following functions are a gross layer violation. the pcmcia layer hooks 
+ * into the IDE layer to fiddle around with the config register.
+ */
+
+int sb_pcmcia_ack_intr(struct hwif_s *hwif)
+{
+
+	csr_out32(1 << K_GPIO_PC_READY, IOADDR(A_GPIO_CLR_EDGE));
+
+	return 1;
+}
+
+static void sibyte_pcmcia_selectproc(ide_drive_t *drive)
+{
+        u32 config;
+
+	config=csr_in32(IOADDR(A_IO_PCMCIA_CFG));
+	config&=~M_PCMCIA_CFG_ATTRMEM;
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+}
+
+static int sibyte_pc_prep_ide(void *iobase)
+{
+	int i;
+	ide_hwif_t *hwif = NULL;
+
+	/* Stake early claim on an ide_hwif */
+	for (i = 0; i < MAX_HWIFS; i++) {
+		if (!ide_hwifs[i].io_ports[IDE_DATA_OFFSET]) {
+			hwif = &ide_hwifs[i]; 
+			break;
+		}
+	}
+	if (hwif == NULL) {
+		 printk("No space for SiByte onboard PCMCIA driver in ide_hwifs[].  Not \
enabled.\n"); +		 return 1;
+	}
+
+	/*
+	 * Prime the hwif with port values, so when a card is
+	 * detected, the 'io_offset' from the capabilities will lead
+	 * it here
+	 */
+	hwif->hw.io_ports[IDE_DATA_OFFSET]    = iobase + (0);
+	hwif->hw.io_ports[IDE_ERROR_OFFSET]   = iobase + (1);
+	hwif->hw.io_ports[IDE_NSECTOR_OFFSET] = iobase + (2);
+	hwif->hw.io_ports[IDE_SECTOR_OFFSET]  = iobase + (3);
+	hwif->hw.io_ports[IDE_LCYL_OFFSET]    = iobase + (4);
+	hwif->hw.io_ports[IDE_HCYL_OFFSET]    = iobase + (5);
+	hwif->hw.io_ports[IDE_SELECT_OFFSET]  = iobase + (6);
+	hwif->hw.io_ports[IDE_STATUS_OFFSET]  = iobase + (7);
+	hwif->hw.io_ports[IDE_CONTROL_OFFSET] = iobase + (6); /* XXXKW ? */
+	hwif->hw.ack_intr                     = sb_pcmcia_ack_intr;
+	hwif->selectproc                      = sibyte_pcmcia_selectproc;
+	hwif->hold                            = 1;
+	hwif->mmio                            = 2;
+
+	printk("SiByte onboard PCMCIA-IDE configured as device %i\n", i);
+
+	return 0;
+}
+
+/* end of hack */
+static struct pccard_operations sibyte_pcmcia_operations = {
+        .init                   = sibyte_pcmcia_sock_init,
+	.get_status             = sibyte_pcmcia_get_status,
+	.get_socket             = sibyte_pcmcia_get_socket,
+	.set_socket             = sibyte_pcmcia_set_socket,
+	.set_io_map             = sibyte_pcmcia_set_io_map,
+	.set_mem_map            = sibyte_pcmcia_set_mem_map,
+};
+
+static int sibyte_pcmcia_sock_hw_init(struct sibyte_pcmcia_socket *skt)
+{
+
+	u32 status, config;
+	u32 gpio_ctrl;
+
+	status=csr_in32(IOADDR(A_IO_PCMCIA_STATUS));
+
+	config = M_PCMCIA_CFG_CDMASK | M_PCMCIA_CFG_WPMASK | 
+		 M_PCMCIA_CFG_RDYMASK;
+
+	csr_out32(config,IOADDR(A_IO_PCMCIA_CFG));
+
+	gpio_ctrl=csr_in32(IOADDR(A_GPIO_INT_TYPE));
+	gpio_ctrl&=~M_GPIO_INTR_TYPEX(K_GPIO_PC_READY);
+	gpio_ctrl|=V_GPIO_INTR_TYPEX(K_GPIO_PC_READY, 
+				     K_GPIO_INTR_EDGE);
+
+	csr_out32(gpio_ctrl, IOADDR(A_GPIO_INT_TYPE));
+	csr_out32(1 << K_GPIO_PC_READY, IOADDR(A_GPIO_CLR_EDGE));
+
+	gpio_ctrl=csr_in32(IOADDR(A_GPIO_INPUT_INVERT));
+	gpio_ctrl|=1 << K_GPIO_PC_READY;
+	csr_out32(gpio_ctrl, IOADDR(A_GPIO_INPUT_INVERT));
+
+	if (request_irq(K_INT_PCMCIA, sibyte_pcmcia_interrupt, 0, 
+			"pcmcia", skt))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int sibyte_pcmcia_socket_probe(struct device *dev, u32 base, u32 size)
+{
+	int ret;
+	struct sibyte_pcmcia_socket *skt=PCMCIA_SOCKET(0);
+
+	skt->socket.ops=&sibyte_pcmcia_operations;
+	skt->socket.resource_ops=&pccard_static_ops;
+	skt->socket.owner=THIS_MODULE;
+	skt->socket.dev.dev=dev;
+
+	skt->irq=K_INT_PC_READY;
+	skt->dev=dev;
+
+	init_timer(&skt->poll_timer);
+	skt->poll_timer.function=sibyte_pcmcia_poll_event;
+	skt->poll_timer.data=(unsigned long)skt;
+	skt->poll_timer.expires=jiffies+SIBYTE_PCMCIA_POLL_PERIOD;
+
+	skt->res_skt.start=base;
+	skt->res_skt.end=base+size;
+	skt->res_skt.name="PCMCIA socket 0";
+	skt->res_skt.flags=IORESOURCE_MEM;
+	ret=request_resource(&iomem_resource, &skt->res_skt);
+	if(ret)
+		goto out_err_1;
+
+	skt->res_io.name="io";
+	skt->res_io.flags=IORESOURCE_MEM | IORESOURCE_BUSY;
+	skt->res_io.start=base;
+	skt->res_io.end=base+IO_MAP_SIZE-1;
+	ret=request_resource(&skt->res_skt, &skt->res_io);
+	if(ret)
+		goto out_err_2;
+	
+	skt->res_mem.name="memory";
+	skt->res_mem.flags=IORESOURCE_MEM;
+	skt->res_mem.start=base+IO_MAP_SIZE;
+	skt->res_mem.end=base+size;
+	ret=request_resource(&skt->res_skt, &skt->res_mem);
+	if(ret)
+		goto out_err_3;
+	
+	skt->virt_io=(void *)(ioremap((phys_t)base, IO_MAP_SIZE) -
+				(u32)mips_io_port_base);
+	skt->phys_mem=base;
+
+	skt->socket.features=SS_CAP_STATIC_MAP|SS_CAP_PCCARD|SS_CAP_PAGE_REGS|
+			     SS_CAP_MEM_ALIGN;
+	skt->socket.irq_mask=0;
+	skt->socket.map_size=size;
+	skt->socket.pci_irq=skt->irq;
+	skt->socket.io_offset=(unsigned long)skt->virt_io;
+
+	skt->status=sibyte_pcmcia_skt_state(skt);
+
+	ret=pcmcia_register_socket(&skt->socket);
+	if(ret)
+		goto out_err_4;
+	
+	ret=sibyte_pcmcia_sock_hw_init(skt);
+	if(ret)
+		goto out_err;
+
+	WARN_ON(skt->socket.sock != 0);
+
+	sibyte_pc_prep_ide(skt->virt_io);
+
+	dev_set_drvdata(dev, skt);
+
+	add_timer(&skt->poll_timer);
+
+	return 0;
+
+out_err:
+	pcmcia_unregister_socket(&skt->socket);
+out_err_4:
+	release_resource(&skt->res_mem);
+out_err_3:
+	release_resource(&skt->res_io);
+out_err_2:
+	release_resource(&skt->res_skt);
+out_err_1:
+	del_timer_sync(&skt->poll_timer);
+	flush_scheduled_work();
+
+	return ret;
+}
+
+
+
+static int sibyte_pcmcia_probe(struct device *dev)
+{
+	u64 cfg;
+	u32 pcmcia_size,pcmcia_base,addr;
+	int ret;
+
+	down(&pcmcia_sockets_lock);
+	cfg=__raw_readq(IOADDR(A_SCD_SYSTEM_CFG));
+	if(!(cfg & M_SYS_PCMCIA_ENABLE)) {
+		printk(KERN_INFO "chip not configured for PCMCIA\n");
+		return -ENODEV;
+	}
+
+	addr=A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, PCMCIA_CS));
+	pcmcia_size=(G_IO_MULT_SIZE(csr_in32(IOADDR(addr))) + 1)<<S_IO_REGSIZE;
+
+	addr=A_IO_EXT_REG(R_IO_EXT_REG(R_IO_EXT_START_ADDR, PCMCIA_CS));
+	pcmcia_base=G_IO_START_ADDR(csr_in32(IOADDR(addr))) << S_IO_ADDRBASE;	
+
+	ret=sibyte_pcmcia_socket_probe(dev, pcmcia_base, pcmcia_size);
+
+	up(&pcmcia_sockets_lock);
+
+	return ret;
+}
+
+int sibyte_pcmcia_remove(struct device *dev)
+{
+	struct sibyte_pcmcia_socket *skt=(struct sibyte_pcmcia_socket *)
+					  dev_get_drvdata(dev);
+        down(&pcmcia_sockets_lock);
+
+	dev_set_drvdata(dev, NULL);
+	del_timer_sync(&skt->poll_timer);
+	pcmcia_unregister_socket(&skt->socket);
+	flush_scheduled_work();
+	sibyte_pcmcia_config_skt(skt,&dead_socket);
+	iounmap(skt->virt_io);
+	skt->virt_io = NULL;
+
+	up(&pcmcia_sockets_lock);
+	return 0;
+}
+
+
+static struct device_driver sibyte_pcmcia_driver = {
+	.probe 		= sibyte_pcmcia_probe,
+	.remove 	= sibyte_pcmcia_remove,
+	.name		= "sb1xxx-pcmcia",
+	.bus		= &platform_bus_type,
+};
+
+static struct platform_device sibyte_pcmcia_device = {
+	.name = "sb1xxx-pcmcia",
+	.id = 0,
+};
+
+static int __init sibyte_pcmcia_init(void)
+{
+	int err;
+
+	err=driver_register(&sibyte_pcmcia_driver);
+	if(err)
+		return err;
+
+	platform_device_register(&sibyte_pcmcia_device);
+
+	return 0;
+}
+
+static void __exit sibyte_pcmcia_exit(void)
+{
+	driver_unregister(&sibyte_pcmcia_driver);
+	platform_device_unregister(&sibyte_pcmcia_device);
+}
+
+
+EXPORT_SYMBOL(sb_pcmcia_ack_intr);
+
+module_init(sibyte_pcmcia_init);
+module_exit(sibyte_pcmcia_exit);
+
diff -urN -x asm -x scripts -x config linux/include/asm-mips/ide.h \
                linux-my/include/asm-mips/ide.h
--- linux/include/asm-mips/ide.h	2004-11-24 19:35:14.000000000 +0100
+++ linux-my/include/asm-mips/ide.h	2005-09-22 17:47:08.000000000 +0200
@@ -10,4 +10,9 @@
 
 #include <ide.h>
 
+#ifdef CONFIG_PCMCIA_SIBYTE_SB1xxx_SOC
+#define IDE_ARCH_ACK_INTR
+#define ide_ack_intr(hwif)      ((hwif)->hw.ack_intr ? (hwif)->hw.ack_intr(hwif) : \
1) +#endif
+
 #endif /* __ASM_IDE_H */


["signature.asc" (application/pgp-signature)]

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic