All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jeff Garzik <jgarzik@pobox.com>
To: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Cc: Russell King <rmk+lkml@arm.linux.org.uk>,
	linux-kernel@vger.kernel.org,
	linux-ppc-embedded <linuxppc-embedded@ozlabs.org>
Subject: Re: [PATCH] MPC8xx PCMCIA driver
Date: Mon, 29 Aug 2005 23:39:02 -0400	[thread overview]
Message-ID: <4313D4D6.7080108@pobox.com> (raw)
In-Reply-To: <20050830024840.GA5381@dmt.cnet>

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.

WARNING: multiple messages have this Message-ID (diff)
From: Jeff Garzik <jgarzik@pobox.com>
To: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Cc: linux-ppc-embedded <linuxppc-embedded@ozlabs.org>,
	linux-kernel@vger.kernel.org,
	Russell King <rmk+lkml@arm.linux.org.uk>,
	Dan Malek <dan@embeddededge.com>,
	Pantelis Antoniou <panto@intracom.gr>
Subject: Re: [PATCH] MPC8xx PCMCIA driver
Date: Mon, 29 Aug 2005 23:39:02 -0400	[thread overview]
Message-ID: <4313D4D6.7080108@pobox.com> (raw)
In-Reply-To: <20050830024840.GA5381@dmt.cnet>

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.


  reply	other threads:[~2005-08-30  3:39 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-08-30  2:48 [PATCH] MPC8xx PCMCIA driver Marcelo Tosatti
2005-08-30  2:48 ` Marcelo Tosatti
2005-08-30  3:39 ` Jeff Garzik [this message]
2005-08-30  3:39   ` Jeff Garzik
2005-08-30  3:53   ` Marcelo Tosatti
2005-08-30  3:53     ` Marcelo Tosatti
2005-08-30  4:32     ` Paul Mackerras
2005-08-30  4:32       ` Paul Mackerras
2005-08-30 15:07       ` Marcelo Tosatti
2005-08-30 15:07         ` Marcelo Tosatti
2005-08-30  4:33     ` Jeff Garzik
2005-08-30  4:33       ` Jeff Garzik
2005-08-30  7:06 ` Russell King
2005-08-30  7:06   ` Russell King
2005-09-01  8:53 ` Dominik Brodowski
2005-09-01  8:53   ` Dominik Brodowski
2005-09-01 11:44   ` Magnus Damm
2005-09-01 11:44     ` Magnus Damm
2005-09-01 14:51   ` Marcelo Tosatti
2005-09-14 14:11   ` Marcelo Tosatti
2005-09-14 14:27     ` Dominik Brodowski
2005-09-14 14:27       ` Dominik Brodowski
2005-09-14 18:21       ` Marcelo Tosatti
2005-09-14 18:21         ` Marcelo Tosatti
2005-09-14 18:46         ` Jeff Garzik
2005-09-14 18:46           ` Jeff Garzik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4313D4D6.7080108@pobox.com \
    --to=jgarzik@pobox.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-embedded@ozlabs.org \
    --cc=marcelo.tosatti@cyclades.com \
    --cc=rmk+lkml@arm.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.