Re: [PATCH] MPC8xx PCMCIA driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Marcelo Tosatti wrote:
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	u_int reg = 0;
+
+	switch(vcc) {
+	case 0: break;
+	case 33:
+		reg |= BCSR1_PCVCTL4;
+		break;
+ case 50: + reg |= BCSR1_PCVCTL5;
+		break;
+ default: + return 1;
+	}
+
+	switch(vpp) {
+	case 0: break;
+ case 33: + case 50:
+		if(vcc == vpp)
+			reg |= BCSR1_PCVCTL6;
+		else
+			return 1;
+		break;
+ case 120: + reg |= BCSR1_PCVCTL7;
+	default:
+		return 1;
+	}
+
+	if(!((vcc == 50) || (vcc == 0)))
+		return 1;
+
+	/* first, turn off all power */
+
+	*((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5
+				     | BCSR1_PCVCTL6 | BCSR1_PCVCTL7);
+
+	/* enable new powersettings */
+
+	*((uint *)RPX_CSR_ADDR) |= reg;

Should use bus read/write functions, such as foo_readl() or iowrite32().

Don't use weird types in kernel code such as 'uint'. Use the more explicitly-sized u32.


+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_RPXCLASSIC */
+
+/* FADS Boards from Motorola                                               */
+
+#if defined(CONFIG_FADS)
+
+#define PCMCIA_BOARD_MSG "FADS"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	uint reg = 0;
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= BCSR1_PCCVCC0;
+			break;
+		case 50:
+			reg |= BCSR1_PCCVCC1;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= BCSR1_PCCVPP1;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= BCSR1_PCCVPP0;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	/* first, turn off all power */
+	*((uint *)BCSR1) &= ~(BCSR1_PCCVCC_MASK | BCSR1_PCCVPP_MASK);
+
+	/* enable new powersettings */
+	*((uint *)BCSR1) |= reg;

ditto

+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+
+static void hardware_enable(int slot)
+{
+	*((uint *)BCSR1) &= ~BCSR1_PCCEN;
+}

ditto

+static void hardware_disable(int slot)
+{
+	*((uint *)BCSR1) |=  BCSR1_PCCEN;
+}

etc.


+/* ------------------------------------------------------------------------- */
+/* Motorola MBX860                                                           */
+
+#if defined(CONFIG_MBX)
+
+#define PCMCIA_BOARD_MSG "MBX"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	unsigned char reg = 0;
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= CSR2_VCC_33;
+			break;
+		case 50:
+			reg |= CSR2_VCC_50;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= CSR2_VPP_VCC;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= CSR2_VPP_12;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	/* first, turn off all power */
+	*((unsigned char *)MBX_CSR2_ADDR) &= ~(CSR2_VCC_MASK | CSR2_VPP_MASK);
+
+	/* enable new powersettings */
+	*((unsigned char *)MBX_CSR2_ADDR) |= reg;

ditto.

also, use u8 not unsigned char.


+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_MBX */
+
+#if defined(CONFIG_PRxK)
+#include <asm/cpld.h>
+extern volatile fpga_pc_regs *fpga_pc;
+
+#define PCMCIA_BOARD_MSG "MPC855T"
+
+static int voltage_set(int slot, int vcc, int vpp)
+{
+	unsigned char reg = 0;
+	unsigned char regread;
+	cpld_regs *ccpld = get_cpld();
+
+	switch(vcc) {
+		case 0:
+			break;
+		case 33:
+			reg |= PCMCIA_VCC_33;
+			break;
+		case 50:
+			reg |= PCMCIA_VCC_50;
+			break;
+		default:
+			return 1;
+	}
+
+	switch(vpp) {
+		case 0:
+			break;
+		case 33:
+		case 50:
+			if(vcc == vpp)
+				reg |= PCMCIA_VPP_VCC;
+			else
+				return 1;
+			break;
+		case 120:
+			if ((vcc == 33) || (vcc == 50))
+				reg |= PCMCIA_VPP_12;
+			else
+				return 1;
+		default:
+			return 1;
+	}
+
+	reg = reg >> (slot << 2);
+	regread = ccpld->fpga_pc_ctl;
+	if (reg != (regread & ((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2)))) {
+		/* enable new powersettings */
+		regread = regread & ~((PCMCIA_VCC_MASK | PCMCIA_VPP_MASK) >> (slot << 2));
+		ccpld->fpga_pc_ctl = reg | regread;
+		mdelay(100);

should be msleep() AFAICS


+	return 0;
+}
+
+#define socket_get(_slot_) PCMCIA_SOCKET_KEY_LV
+#define hardware_enable(_slot_)  /* No hardware to enable */
+#define hardware_disable(_slot_) /* No hardware to disable */
+
+#endif /* CONFIG_PRxK */
+
+static void m8xx_shutdown(void)
+{
+	u_int m, i;
+	pcmcia_win_t *w;
+
+	for(i = 0; i < PCMCIA_SOCKETS_NO; i++){
+		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+ ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = + M8XX_PCMCIA_MASK(i); + ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per + &= ~M8XX_PCMCIA_MASK(i); + + /* turn off interrupt and disable CxOE */
+		M8XX_PGCRX(i) = M8XX_PGCRX_CXOE;
+		
+		/* turn off memory windows */
+		for(m = 0; m < PCMCIA_MEM_WIN_NO; m++) {
+			w->or = 0;  /* set to not valid */
+			w++;
+		}
+		
+		/* turn off voltage */
+		voltage_set(i, 0, 0);
+		
+		/* disable external hardware */
+		hardware_disable(i);
+	}
+
+	free_irq(pcmcia_schlvl, NULL);

don't you want to free_irq() first?



+}
+
+/* copied from tcic.c */
+
+static int m8xx_drv_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 m8xx_drv_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 m8xx_driver = {
+        .name = "m8xx-pcmcia",
+        .bus = &platform_bus_type,
+        .suspend = m8xx_drv_suspend,
+        .resume = m8xx_drv_resume,
+};
+
+static struct platform_device m8xx_device = {
+        .name = "m8xx-pcmcia",
+        .id = 0,
+};
+
+static u_int pending_events[PCMCIA_SOCKETS_NO];
+static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED;
+
+static irqreturn_t m8xx_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	socket_info_t *s;
+	event_table_t *e;
+	u_int i, events, pscr, pipr, per;
+
+	dprintk("Interrupt!\n");
+	/* get interrupt sources */
+
+	pscr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr;
+	pipr = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pipr;
+	per = ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per;
+
+	for(i = 0; i < PCMCIA_SOCKETS_NO; i++) {
+		s = &socket[i];
+ e = &s->events[0]; + events = 0;
+
+		while(e->regbit) {
+			if(pscr & e->regbit)
+				events |= e->eventbit;
+ + e++;
+		}
+
+ /* + * report only if both card detect signals are the same + * not too nice done, + * we depend on that CD2 is the bit to the left of CD1...
+		 */
+		if(events & SS_DETECT)
+			if(((pipr & M8XX_PCMCIA_CD2(i)) >> 1) ^
+				(pipr & M8XX_PCMCIA_CD1(i)))
+			{
+				events &= ~SS_DETECT;
+			}
+
+#ifdef PCMCIA_GLITCHY_CD
+		/*
+		 * I've experienced CD problems with my ADS board.
+		 * We make an extra check to see if there was a
+		 * real change of Card detection.
+		 */
+ + if((events & SS_DETECT) && + ((pipr &
+		     (M8XX_PCMCIA_CD2(i) | M8XX_PCMCIA_CD1(i))) == 0) &&
+		   (s->state.Vcc | s->state.Vpp)) {
+			events &= ~SS_DETECT;
+			/*printk( "CD glitch workaround - CD = 0x%08x!\n",
+ (pipr & (M8XX_PCMCIA_CD2(i) + | M8XX_PCMCIA_CD1(i))));*/
+		}
+#endif
+ + /* call the handler */
+
+		dprintk("slot %u: events = 0x%02x, pscr = 0x%08x, "
+ "pipr = 0x%08x\n", + i, events, pscr, pipr); + + if(events) {
+			spin_lock(&pending_event_lock);
+			pending_events[i] |= events;
+			spin_unlock(&pending_event_lock);
+ /* + * Turn off RDY_L bits in the PER mask on + * CD interrupt receival.
+			 *
+			 * They can generate bad interrupts on the
+			 * ACS4,8,16,32.   - marcelo
+			 */
+			per &= ~M8XX_PCMCIA_RDY_L(0);
+			per &= ~M8XX_PCMCIA_RDY_L(1);
+
+			((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per = per;
+
+			if (events)
+				pcmcia_parse_events(&socket[i].socket, events);
+		}
+	}
+	
+	/* clear the interrupt sources */
+	((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = pscr;

more direct memory writes which should be foo_writel()


+	dprintk("Interrupt done.\n");
+
+	return IRQ_HANDLED;
+}
+
+static int m8xx_suspend(struct pcmcia_socket *sock)
+{
+	return m8xx_set_socket(sock, &dead_socket);
+}
+
+static struct pccard_operations m8xx_services = {
+	.init	= m8xx_sock_init,	
+	.suspend = m8xx_suspend,
+	.get_status = m8xx_get_status,
+	.get_socket = m8xx_get_socket,
+	.set_socket = m8xx_set_socket,
+	.set_io_map = m8xx_set_io_map,
+	.set_mem_map = m8xx_set_mem_map,
+};
+
+static int __init m8xx_init(void)
+{
+	pcmcia_win_t *w;
+	u_int i,m;
+
+	pcmcia_info("%s\n", version);
+
+	if (driver_register(&m8xx_driver))
+		return -1;
+
+ pcmcia_info(PCMCIA_BOARD_MSG " using " PCMCIA_SLOT_MSG + " with IRQ %u.\n", pcmcia_schlvl); +
+	/* Configure Status change interrupt */
+
+ if(request_irq(pcmcia_schlvl, m8xx_interrupt, 0, + "m8xx_pcmcia", NULL)) { + pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n", + pcmcia_schlvl);
+		return -1;
+	}
+
+	w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;
+
+ ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = + M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1); + ((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_per + &= ~(M8XX_PCMCIA_MASK(0)| M8XX_PCMCIA_MASK(1));

ditto etc.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux