⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m8xx_pcmcia.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. * * (C) 1999-2000 Magnus Damm <damm@opensource.se> * * "The ExCA standard specifies that socket controllers should provide  * two IO and five memory windows per socket, which can be independently  * configured and positioned in the host address space and mapped to  * arbitrary segments of card address space. " - David A Hinds. 1999 * * This controller does _not_ meet the ExCA standard. *  * m8xx pcmcia controller brief info: * + 8 windows (attrib, mem, i/o) * + up to two slots (SLOT_A and SLOT_B) * + inputpins, outputpins, event and mask registers. * - no offset register. sigh. * * Because of the lacking offset register we must map the whole card. * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO  * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. * They are maximum 64KByte each... */#include <linux/module.h>#include <linux/init.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/string.h>#include <asm/io.h>#include <asm/bitops.h>#include <asm/system.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/timer.h>#include <linux/ioport.h>#include <linux/delay.h>#include <asm/mpc8xx.h>#include <asm/8xx_immap.h>#include <asm/irq.h>#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/ss.h>#ifdef PCMCIA_DEBUGstatic int pc_debug = PCMCIA_DEBUG;MODULE_PARM(pc_debug, "i");#define DEBUG(n, args...) printk(KERN_DEBUG "m8xx_pcmcia: " args);#else#define DEBUG(n, args...)#endif#define PCMCIA_INFO(args...) printk(KERN_INFO "m8xx_pcmcia: "args)#define PCMCIA_ERROR(args...) printk(KERN_ERR "m8xx_pcmcia: "args)static const char *version = "Version 0.03, 14-Feb-2000, Magnus Damm";/* ------------------------------------------------------------------------- *//* Autoconfigure boards if no settings are defined                           */ #if !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B)/* The RPX series use SLOT_B */#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)#define CONFIG_PCMCIA_SLOT_B#define CONFIG_BD_IS_MHZ#endif/* The ADS board use SLOT_A */#ifdef CONFIG_ADS#define CONFIG_PCMCIA_SLOT_A#define CONFIG_BD_IS_MHZ#endif/* The FADS series are a mess */#ifdef CONFIG_FADS#if defined(CONFIG_MPC860T) || defined(CONFIG_MPC860) || defined(CONFIG_MPC821)#define CONFIG_PCMCIA_SLOT_A#else#define CONFIG_PCMCIA_SLOT_B#endif#endif#endif /* !defined(CONFIG_PCMCIA_SLOT_A) && !defined(CONFIG_PCMCIA_SLOT_B) *//* ------------------------------------------------------------------------- */#define PCMCIA_MEM_WIN_BASE 0xe0000000 /* base address for memory window 0   */#define PCMCIA_MEM_WIN_SIZE 0x04000000 /* each memory window is 64 MByte     */#define PCMCIA_IO_WIN_BASE  _IO_BASE   /* base address for io window 0       */#define PCMCIA_SCHLVL PCMCIA_INTERRUPT /* Status Change Interrupt Level      *//* ------------------------------------------------------------------------- */#if defined(CONFIG_PCMCIA_SLOT_A) && defined(CONFIG_PCMCIA_SLOT_B)#define PCMCIA_SOCKETS_NO 2  /* We have only 8 windows, dualsocket support will be limited. */#define PCMCIA_MEM_WIN_NO 2#define PCMCIA_IO_WIN_NO  2#define PCMCIA_SLOT_MSG "SLOT_A and SLOT_B"#elif defined(CONFIG_PCMCIA_SLOT_A) || defined(CONFIG_PCMCIA_SLOT_B)#define PCMCIA_SOCKETS_NO 1#define PCMCIA_MEM_WIN_NO 5#define PCMCIA_IO_WIN_NO  2/* define _slot_ to be able to optimize macros */#ifdef CONFIG_PCMCIA_SLOT_A#define _slot_ 0#define PCMCIA_SLOT_MSG "SLOT_A"#else#define _slot_ 1#define PCMCIA_SLOT_MSG "SLOT_B"#endif#else#error m8xx_pcmcia: Bad configuration!#endif#if (LINUX_VERSION_CODE >= VERSION(2,4,0))/* 2.4.x has this always in HZ */#define M8XX_BUSFREQ ((((bd_t *)&(__res))->bi_busfreq))#else /* 2.2.x */#ifdef CONFIG_BD_IS_MHZ#define M8XX_BUSFREQ ((mpc8xx_bdinfo->bi_busfreq) * 1000000)#else#define M8XX_BUSFREQ (mpc8xx_bdinfo->bi_busfreq)#endif#endifstatic int pcmcia_schlvl = PCMCIA_SCHLVL;/* ------------------------------------------------------------------------- */#define PCMCIA_SOCKET_KEY_5V 1#define PCMCIA_SOCKET_KEY_LV 2/* look up table for pgcrx registers */static u_int *m8xx_pgcrx[2] = {	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcra,	&((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pgcrb}; /* * This structure is used to address each window in the PCMCIA controller.  *  * Keep in mind that we assume that pcmcia_win_t[n+1] is mapped directly * after pcmcia_win_t[n]...  */typedef struct {             	uint	br;           	uint	or;} pcmcia_win_t;/*  * For some reason the hardware guys decided to make both slots share * some registers. * * Could someone invent object oriented hardware ? * * The macros are used to get the right bit from the registers. * SLOT_A : slot = 0 * SLOT_B : slot = 1 */#define M8XX_PCMCIA_VS1(slot)      (0x80000000 >> (slot << 4))#define M8XX_PCMCIA_VS2(slot)      (0x40000000 >> (slot << 4))#define M8XX_PCMCIA_VS_MASK(slot)  (0xc0000000 >> (slot << 4))#define M8XX_PCMCIA_VS_SHIFT(slot) (30 - (slot << 4))#define M8XX_PCMCIA_WP(slot)       (0x20000000 >> (slot << 4))#define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))#define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))#define M8XX_PCMCIA_BVD2(slot)     (0x04000000 >> (slot << 4))#define M8XX_PCMCIA_BVD1(slot)     (0x02000000 >> (slot << 4))#define M8XX_PCMCIA_RDY(slot)      (0x01000000 >> (slot << 4))#define M8XX_PCMCIA_RDY_L(slot)    (0x00800000 >> (slot << 4))#define M8XX_PCMCIA_RDY_H(slot)    (0x00400000 >> (slot << 4))#define M8XX_PCMCIA_RDY_R(slot)    (0x00200000 >> (slot << 4))#define M8XX_PCMCIA_RDY_F(slot)    (0x00100000 >> (slot << 4))#define M8XX_PCMCIA_MASK(slot)     (0xFFFF0000 >> (slot << 4))#define M8XX_PGCRX(slot)  (*m8xx_pgcrx[slot])#define M8XX_PGCRX_CXOE    0x00000080#define M8XX_PGCRX_CXRESET 0x00000040/* we keep one lookup table per socket to check flags */ #define PCMCIA_EVENTS_MAX 5  /* 4 max at a time + termination */typedef struct  {	u_int regbit;	u_int eventbit;} event_table_t;typedef struct socket_info_t {    void	(*handler)(void *info, u_int events);    void	*info;    u_int  slot;    socket_state_t state;    struct pccard_mem_map mem_win[PCMCIA_MEM_WIN_NO];    struct pccard_io_map  io_win[PCMCIA_IO_WIN_NO];    event_table_t events[PCMCIA_EVENTS_MAX]; } socket_info_t;static socket_info_t socket[PCMCIA_SOCKETS_NO];static socket_cap_t capabilities = {    /* only 16-bit cards, memory windows must be size-aligned */    SS_CAP_PCCARD | SS_CAP_MEM_ALIGN | SS_CAP_STATIC_MAP,    0x000,		/* SIU_LEVEL 7 -> 0          */    0x1000,		/* 4K minimum window size    */    9, 0		/* No PCI or CardBus support */};/*  * Search this table to see if the windowsize is * supported... */#define M8XX_SIZES_NO 32static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] = { 0x00000001, 0x00000002, 0x00000008, 0x00000004,  0x00000080, 0x00000040, 0x00000010, 0x00000020,  0x00008000, 0x00004000, 0x00001000, 0x00002000,  0x00000100, 0x00000200, 0x00000800, 0x00000400,  0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff,  0x01000000, 0x02000000, 0xffffffff, 0x04000000,  0x00010000, 0x00020000, 0x00080000, 0x00040000,  0x00800000, 0x00400000, 0x00100000, 0x00200000 };/* ------------------------------------------------------------------------- */static void m8xx_interrupt(int irq, void *dev, struct pt_regs *regs);static int m8xx_service(u_int sock, u_int cmd, void *arg);#define PCMCIA_BMT_LIMIT (15*4)  /* Bus Monitor Timeout value *//* ------------------------------------------------------------------------- *//* board specific stuff:                                                     *//* voltage_set(), hardware_enable() and hardware_disable()                   *//* ------------------------------------------------------------------------- *//* RPX Boards from Embedded Planet                                           */#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE)/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks. * SYPCR is write once only, therefore must the slowest memory be faster  * than the bus monitor or we will get a machine check due to the bus timeout. */#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE"#undef PCMCIA_BMT_LIMIT#define PCMCIA_BMT_LIMIT (6*8) 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;	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 *//* ------------------------------------------------------------------------- *//* (F)ADS Boards from Motorola                                               */#if defined(CONFIG_ADS) || defined(CONFIG_FADS)#ifdef CONFIG_ADS#define PCMCIA_BOARD_MSG "ADS"#define PCMCIA_GLITCHY_CD  /* My ADS board needs this */#else#define PCMCIA_BOARD_MSG "FADS"#endifstatic int voltage_set(int slot, int vcc, int vpp){	u_int reg = 0;		switch(vpp) {	case 0: reg = 0; break;	case 50: reg = 1; break;	case 120: reg = 2; break;	default: return 1;	}	switch(vcc) {	case 0: reg = 0; break;#ifdef CONFIG_ADS	case 50: reg = BCSR1_PCCVCCON; break;#endif#ifdef CONFIG_FADS	case 33: reg = BCSR1_PCCVCC0 | BCSR1_PCCVCC1; break;	case 50: reg = BCSR1_PCCVCC1; break;#endif	default: return 1;	}	/* first, turn off all power */#ifdef CONFIG_ADS	*((uint *)BCSR1) |= BCSR1_PCCVCCON;  #endif#ifdef CONFIG_FADS	*((uint *)BCSR1) &= ~(BCSR1_PCCVCC0 | BCSR1_PCCVCC1);  #endif	*((uint *)BCSR1) &= ~BCSR1_PCCVPP_MASK;	/* enable new powersettings */#ifdef CONFIG_ADS	*((uint *)BCSR1) &= ~reg;  #endif#ifdef CONFIG_FADS	*((uint *)BCSR1) |= reg;  #endif	 	*((uint *)BCSR1) |= reg << 20;        	return 0;}#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5Vstatic void hardware_enable(int slot){	*((uint *)BCSR1) &= ~BCSR1_PCCEN;}static void hardware_disable(int slot){	*((uint *)BCSR1) &= ~BCSR1_PCCEN;}#endif/* ------------------------------------------------------------------------- */static void m8xx_shutdown(void){	u_int k, m;	pcmcia_win_t *w;#if (PCMCIA_SOCKETS_NO == 2)	u_int _slot_;#endif    		w = (void *) &((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0;	for(k = 0; k < PCMCIA_SOCKETS_NO; k++) {#if (PCMCIA_SOCKETS_NO == 2)		_slot_ = socket[k].slot;#endif    		((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pscr = 

⌨️ 快捷键说明

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