m32r_cfc.c

来自「linux 内核源代码」· C语言 代码 · 共 811 行 · 第 1/2 页

C
811
字号
static int _pcc_get_status(u_short sock, u_int *value){	u_int status;	debug(3, "m32r_cfc: _pcc_get_status:\n");	status = pcc_get(sock, (unsigned int)PLD_CFSTS);	*value = (status) ? SS_DETECT : 0; 	debug(3, "m32r_cfc: _pcc_get_status: status=0x%08x\n", status);#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)	if ( status ) {		/* enable CF power */		status = inw((unsigned int)PLD_CPCR);		if (!(status & PLD_CPCR_CF)) {			debug(3, "m32r_cfc: _pcc_get_status: "				 "power on (CPCR=0x%08x)\n", status);			status |= PLD_CPCR_CF;			outw(status, (unsigned int)PLD_CPCR);			udelay(100);		}		*value |= SS_POWERON;		pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);/* enable buffer */		udelay(100);		*value |= SS_READY; 		/* always ready */		*value |= SS_3VCARD;	} else {		/* disable CF power */		status = inw((unsigned int)PLD_CPCR);		status &= ~PLD_CPCR_CF;		outw(status, (unsigned int)PLD_CPCR);		udelay(100);		debug(3, "m32r_cfc: _pcc_get_status: "			 "power off (CPCR=0x%08x)\n", status);	}#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)	if ( status ) {		status = pcc_get(sock, (unsigned int)PLD_CPCR);		if (status == 0) { /* power off */			pcc_set(sock, (unsigned int)PLD_CPCR, 1);			pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */			udelay(50);		}		*value |= SS_POWERON;		pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);		udelay(50);		pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);		udelay(25); /* for IDE reset */		pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);		mdelay(2);  /* for IDE reset */		*value |= SS_READY;		*value |= SS_3VCARD;	} else {		/* disable CF power */	        pcc_set(sock, (unsigned int)PLD_CPCR, 0);		udelay(100);		debug(3, "m32r_cfc: _pcc_get_status: "			 "power off (CPCR=0x%08x)\n", status);	}#else#error no platform configuration#endif	debug(3, "m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n",		 sock, *value);	return 0;} /* _get_status *//*====================================================================*/static int _pcc_set_socket(u_short sock, socket_state_t *state){	debug(3, "m32r_cfc: SetSocket(%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);#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)	if (state->Vcc) {		if ((state->Vcc != 50) && (state->Vcc != 33))			return -EINVAL;		/* accept 5V and 3.3V */	}#endif	if (state->flags & SS_RESET) {		debug(3, ":RESET\n");		pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);	}else{		pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100);	}	if (state->flags & SS_OUTPUT_ENA){		debug(3, ":OUTPUT_ENA\n");		/* bit clear */		pcc_set(sock,(unsigned int)PLD_CFBUFCR,0);	} else {		pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);	}#ifdef DEBUG	if(state->flags & SS_IOCARD){		debug(3, ":IOCARD");	}	if (state->flags & SS_PWR_AUTO) {		debug(3, ":PWR_AUTO");	}	if (state->csc_mask & SS_DETECT)		debug(3, ":csc-SS_DETECT");	if (state->flags & SS_IOCARD) {		if (state->csc_mask & SS_STSCHG)			debug(3, ":STSCHG");	} else {		if (state->csc_mask & SS_BATDEAD)			debug(3, ":BATDEAD");		if (state->csc_mask & SS_BATWARN)			debug(3, ":BATWARN");		if (state->csc_mask & SS_READY)			debug(3, ":READY");	}	debug(3, "\n");#endif	return 0;} /* _set_socket *//*====================================================================*/static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io){	u_char map;	debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "		  "%#lx-%#lx)\n", sock, io->map, io->flags,		  io->speed, io->start, io->stop);	map = io->map;	return 0;} /* _set_io_map *//*====================================================================*/static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem){	u_char map = mem->map;	u_long addr;	pcc_socket_t *t = &socket[sock];	debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "		 "%#lx, %#x)\n", sock, map, mem->flags,		 mem->speed, mem->static_start, mem->card_start);	/*	 * sanity check	 */	if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){		return -EINVAL;	}	/*	 * de-activate	 */	if ((mem->flags & MAP_ACTIVE) == 0) {		t->current_space = as_none;		return 0;	}	/*	 * Set mode	 */	if (mem->flags & MAP_ATTRIB) {		t->current_space = as_attr;	} else {		t->current_space = as_comm;	}	/*	 * Set address	 */	addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK);	mem->static_start = addr + mem->card_start;	return 0;} /* _set_mem_map */#if 0 /* driver model ordering issue *//*======================================================================	Routines for accessing socket information and register dumps via	/proc/bus/pccard/...======================================================================*/static ssize_t show_info(struct class_device *class_dev, char *buf){	pcc_socket_t *s = container_of(class_dev, struct pcc_socket,		socket.dev);	return sprintf(buf, "type:     %s\nbase addr:    0x%08lx\n",		pcc[s->type].name, s->base);}static ssize_t show_exca(struct class_device *class_dev, char *buf){	/* FIXME */	return 0;}static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);#endif/*====================================================================*//* this is horribly ugly... proper locking needs to be done here at * some time... */#define LOCKED(x) do {					\	int retval;					\	unsigned long flags;				\	spin_lock_irqsave(&pcc_lock, flags);		\	retval = x;					\	spin_unlock_irqrestore(&pcc_lock, flags);	\	return retval;					\} while (0)static int pcc_get_status(struct pcmcia_socket *s, u_int *value){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		debug(3, "m32r_cfc: pcc_get_status: sock(%d) -EINVAL\n", sock);		*value = 0;		return -EINVAL;	}	debug(3, "m32r_cfc: pcc_get_status: sock(%d)\n", sock);	LOCKED(_pcc_get_status(sock, value));}static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		debug(3, "m32r_cfc: pcc_set_socket: sock(%d) -EINVAL\n", sock);		return -EINVAL;	}	debug(3, "m32r_cfc: pcc_set_socket: sock(%d)\n", sock);	LOCKED(_pcc_set_socket(sock, state));}static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		debug(3, "m32r_cfc: pcc_set_io_map: sock(%d) -EINVAL\n", sock);		return -EINVAL;	}	debug(3, "m32r_cfc: pcc_set_io_map: sock(%d)\n", sock);	LOCKED(_pcc_set_io_map(sock, io));}static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem){	unsigned int sock = container_of(s, struct pcc_socket, socket)->number;	if (socket[sock].flags & IS_ALIVE) {		debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d) -EINVAL\n", sock);		return -EINVAL;	}	debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d)\n", sock);	LOCKED(_pcc_set_mem_map(sock, mem));}static int pcc_init(struct pcmcia_socket *s){	debug(3, "m32r_cfc: pcc_init()\n");	return 0;}static struct pccard_operations pcc_operations = {	.init			= pcc_init,	.get_status		= pcc_get_status,	.set_socket		= pcc_set_socket,	.set_io_map		= pcc_set_io_map,	.set_mem_map		= pcc_set_mem_map,};/*====================================================================*/static struct device_driver pcc_driver = {	.name = "cfc",	.bus = &platform_bus_type,	.suspend = pcmcia_socket_dev_suspend,	.resume = pcmcia_socket_dev_resume,};static struct platform_device pcc_device = {	.name = "cfc",	.id = 0,};/*====================================================================*/static int __init init_m32r_pcc(void){	int i, ret;	ret = driver_register(&pcc_driver);	if (ret)		return ret;	ret = platform_device_register(&pcc_device);	if (ret){		driver_unregister(&pcc_driver);		return ret;	}#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)	pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);	pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);#endif	pcc_sockets = 0;#if !defined(CONFIG_PLAT_USRV)	add_pcc_socket(M32R_PCC0_BASE, PLD_IRQ_CFC_INSERT, CFC_ATTR_MAPBASE,		       CFC_IOPORT_BASE);#else	/* CONFIG_PLAT_USRV */	{		ulong base, mapaddr;		kio_addr_t ioaddr;		for (i = 0 ; i < M32R_MAX_PCC ; i++) {			base = (ulong)PLD_CFRSTCR;			base = base | (i << 8);			ioaddr = (i + 1) << 12;			mapaddr = CFC_ATTR_MAPBASE | (i << 20);			add_pcc_socket(base, 0, mapaddr, ioaddr);		}	}#endif	/* CONFIG_PLAT_USRV */	if (pcc_sockets == 0) {		printk("socket is not found.\n");		platform_device_unregister(&pcc_device);		driver_unregister(&pcc_driver);		return -ENODEV;	}	/* Set up interrupt handler(s) */	for (i = 0 ; i < pcc_sockets ; i++) {		socket[i].socket.dev.parent = &pcc_device.dev;		socket[i].socket.ops = &pcc_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)			socket[i].flags |= IS_REGISTERED;#if 0	/* driver model ordering issue */		class_device_create_file(&socket[i].socket.dev,					 &class_device_attr_info);		class_device_create_file(&socket[i].socket.dev,					 &class_device_attr_exca);#endif	}	/* Finally, schedule a polling interrupt */	if (poll_interval != 0) {		poll_timer.function = pcc_interrupt_wrapper;		poll_timer.data = 0;		init_timer(&poll_timer);		poll_timer.expires = jiffies + poll_interval;		add_timer(&poll_timer);	}	return 0;} /* init_m32r_pcc */static void __exit exit_m32r_pcc(void){	int i;	for (i = 0; i < pcc_sockets; i++)		if (socket[i].flags & IS_REGISTERED)			pcmcia_unregister_socket(&socket[i].socket);	platform_device_unregister(&pcc_device);	if (poll_interval != 0)		del_timer_sync(&poll_timer);	driver_unregister(&pcc_driver);} /* exit_m32r_pcc */module_init(init_m32r_pcc);module_exit(exit_m32r_pcc);MODULE_LICENSE("Dual MPL/GPL");/*====================================================================*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?