/* ssa_pcmcia_driver_init() * ^^^^^^^^^^^^^^^^^^^^^^^^ * * This routine performs a basic sanity check to ensure that this * kernel has been built with the appropriate board-specific low-level * PCMCIA support, performs low-level PCMCIA initialization, registers * this socket driver with Card Services, and then spawns the daemon * thread which is the real workhorse of the socket driver. * * Returns: 0 on success, -1 on error */ static int __init ssa_pcmcia_driver_init (void) { ssa_pcmcia_socket_t *skt = &ssa_pcmcia_socket; servinfo_t info; int ret; printk (KERN_INFO "SSA PCMCIA (CS release %s)\n", CS_RELEASE); CardServices (GetCardServicesInfo, &info); if (info.Revision != CS_RELEASE_CODE) { printk ("Card Services release codes do not match\n"); return -EINVAL; } /* setup GPIO directions etc ?? */ /* setup irq to catch card detect and battery status changes... */ writel (SMC_WAITSTATES_PCMCIA_IO, IO_ADDRESS_SMC_BASE + 8); lowlevel_socket_state (&skt->k_state); ret = register_ss_entry (SSA_PCMCIA_SOCKET_COUNT, &ssa_pcmcia_operations); if (ret < 0) { printk ("Unable to register sockets\n"); return ret; } ssa_pcmcia_poll_event (0); /* startup the event poll timer. param is not used */ return 0; }
static int __init ivpnss_init(void) { servinfo_t serv; int rc; printk("iVPNSS: IXP4xx/iVPN socket service driver\n" \ "(C) Copyright 2004, Greg Ungerer <*****@*****.**>\n"); ivpnss_hwsetup(); if ((rc = ivpnss_memmap())) return rc; pcmcia_get_card_services_info(&serv); if (serv.Revision != CS_RELEASE_CODE) { printk("iVPNSS: Card Services version mis-match!\n"); return -ENODEV; } if (register_ss_entry(1, &ivpnss_operations)) { printk("iVPNSS: failed to register socket service?\n"); return -ENODEV; } if (register_chrdev(IVPNSS_MAJOR, IVPNSS_NAME, &ivpnss_fops)) printk("iVPNSS: failed to register debug char device?\n"); return 0; }
static int __init clps6700_init(void) { unsigned int v; int err, nr; PLD_CF = 0; v = clps_readl(SYSCON2) | SYSCON2_PCCARD1 | SYSCON2_PCCARD2; clps_writel(v, SYSCON2); v = clps_readl(SYSCON1) | SYSCON1_EXCKEN; clps_writel(v, SYSCON1); for (nr = 0; nr < NR_CLPS6700; nr++) { err = clps6700_init_skt(nr); if (err) goto free; } err = register_ss_entry(nr, &clps6700_operations); if (err) goto free; return 0; free: clps6700_free_resources(); /* * An error occurred. Unmap and free all CLPS6700 */ return err; }
/* pxa_pcmcia_driver_init() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * This routine performs a basic sanity check to ensure that this * kernel has been built with the appropriate board-specific low-level * PCMCIA support, performs low-level PCMCIA initialization, registers * this socket driver with Card Services, and then spawns the daemon * thread which is the real workhorse of the socket driver. * * Please see linux/Documentation/arm/SA1100/PCMCIA for more information * on the low-level kernel interface. * * Returns: 0 on success, -1 on error */ static int __init pxa_pcmcia_driver_init(void){ servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state[PXA_PCMCIA_MAX_SOCK]; struct pcmcia_state_array state_array; unsigned int i, clock; unsigned long mecr; printk(KERN_INFO "Intel PXA250/210 PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if(info.Revision!=CS_RELEASE_CODE){ printk(KERN_ERR "Card Services release codes do not match\n"); return -1; } /* Setup GPIOs for PCMCIA/CF alternate function mode. * * It would be nice if set_GPIO_mode included support * for driving GPIO outputs to default high/low state * before programming GPIOs as outputs. Setting GPIO * outputs to default high/low state via GPSR/GPCR * before defining them as outputs should reduce * the possibility of glitching outputs during GPIO * setup. This of course assumes external terminators * are present to hold GPIOs in a defined state. * * In the meantime, setup default state of GPIO * outputs before we enable them as outputs. */ GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | GPIO_bit(GPIO53_nPCE_2); set_GPIO_mode(GPIO48_nPOE_MD); set_GPIO_mode(GPIO49_nPWE_MD); set_GPIO_mode(GPIO50_nPIOR_MD); set_GPIO_mode(GPIO51_nPIOW_MD); set_GPIO_mode(GPIO52_nPCE_1_MD); set_GPIO_mode(GPIO53_nPCE_2_MD); set_GPIO_mode(GPIO54_pSKTSEL_MD); /* REVISIT: s/b dependent on num sockets */ set_GPIO_mode(GPIO55_nPREG_MD); set_GPIO_mode(GPIO56_nPWAIT_MD); set_GPIO_mode(GPIO57_nIOIS16_MD); if(machine_is_lubbock()){ #ifdef CONFIG_ARCH_LUBBOCK pcmcia_low_level=&lubbock_pcmcia_ops; #endif } else if (machine_is_pxa_idp()) { pcmcia_low_level=&pxa_idp_pcmcia_ops; } else if( machine_is_pxa_cerf()){ pcmcia_low_level=&cerf_pcmcia_ops; } if (!pcmcia_low_level) { printk(KERN_ERR "This hardware is not supported by the PXA250/210 Card Service driver\n"); return -ENODEV; } pcmcia_init.handler=pxa_pcmcia_interrupt; if((pxa_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){ printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n"); return -EIO; } state_array.size=pxa_pcmcia_socket_count; state_array.state=state; /* Configure MECR based on the number of sockets present. */ if (pxa_pcmcia_socket_count == 2) { MECR |= GPIO_bit(0); } else { MECR &= ~GPIO_bit(0); } if(pcmcia_low_level->socket_state(&state_array)<0){ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); return -EIO; } /* Well, it looks good to go. So we can now enable the PCMCIA * controller. */ MECR |= GPIO_bit(1); /* We need to initialize the MCXX registers to default values * here because we're not guaranteed to see a SetIOMap operation * at runtime. */ clock = get_lclk_frequency_10khz(); for(i=0; i<pxa_pcmcia_socket_count; ++i){ pxa_pcmcia_socket[i].k_state=state[i]; /* This is an interim fix. Apparently, SetSocket is no longer * called to initialize each socket (prior to the first detect * event). For now, we'll just manually set up the mask. */ pxa_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT; pxa_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE; pxa_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i); pxa_pcmcia_socket[i].phys_mem=_PCMCIAMem(i); /* REVISIT: cleanup these macros */ //MCIO_SET(i, PXA_PCMCIA_IO_ACCESS, clock); //MCATTR_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock); //MCMEM_SET(i, PXA_PCMCIA_5V_MEM_ACCESS, clock); pxa_pcmcia_socket[i].speed_io=PXA_PCMCIA_IO_ACCESS; pxa_pcmcia_socket[i].speed_attr=PXA_PCMCIA_5V_MEM_ACCESS; pxa_pcmcia_socket[i].speed_mem=PXA_PCMCIA_5V_MEM_ACCESS; } /* REVISIT: cleanup these macros */ MCMEM0 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); MCMEM1 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); MCATT0 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); MCATT1 = ((pxa_mcxx_setup(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_5V_MEM_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); MCIO0 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); MCIO1 = ((pxa_mcxx_setup(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT) | ((pxa_mcxx_asst(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_ASST_MASK) << MCXX_ASST_SHIFT) | ((pxa_mcxx_hold(PXA_PCMCIA_IO_ACCESS, clock) & MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT); #ifdef CONFIG_CPU_FREQ if(cpufreq_register_notifier(&pxa_pcmcia_notifier_block) < 0){ printk(KERN_ERR "Unable to register CPU frequency change notifier\n"); return -ENXIO; } #endif /* Only advertise as many sockets as we can detect: */ if(register_ss_entry(pxa_pcmcia_socket_count, &pxa_pcmcia_operations)<0){ printk(KERN_ERR "Unable to register socket service routine\n"); return -ENXIO; } /* Start the event poll timer. It will reschedule by itself afterwards. */ pxa_pcmcia_poll_event(0); DEBUG(1, "pxa_cs: initialization complete\n"); return 0; } /* pxa_pcmcia_driver_init() */
static int __init au1000_pcmcia_driver_init(void) { servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state; unsigned int i; unsigned long timing3; printk("\nAu1x00 PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if(info.Revision!=CS_RELEASE_CODE){ printk(KERN_ERR "Card Services release codes do not match\n"); return -1; } #ifdef CONFIG_MIPS_PB1000 pcmcia_low_level=&pb1000_pcmcia_ops; #elif defined(CONFIG_MIPS_PB1500) pcmcia_low_level=&pb1500_pcmcia_ops; #else #error Unsupported AU1000 board. #endif pcmcia_init.handler=au1000_pcmcia_interrupt; if((socket_count=pcmcia_low_level->init(&pcmcia_init))<0) { printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); return -EIO; } /* setup the static bus controller */ timing3 = 0x100e3a07; writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ writel(timing3, MEM_STTIME3); writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ au_sync_delay(1); pcmcia_socket = kmalloc(sizeof(struct au1000_pcmcia_socket) * socket_count, GFP_KERNEL); if (!pcmcia_socket) { printk(KERN_ERR "Card Services can't get memory \n"); return -1; } memset(pcmcia_socket, 0, sizeof(struct au1000_pcmcia_socket) * socket_count); for(i=0; i < socket_count; i++) { if(pcmcia_low_level->socket_state(i, &state)<0){ printk(KERN_ERR "Unable to get PCMCIA status\n"); return -EIO; } pcmcia_socket[i].k_state=state; pcmcia_socket[i].cs_state.csc_mask=SS_DETECT; if (i == 0) { pcmcia_socket[i].virt_io = (u32)ioremap(0xC0000000, 0x1000); pcmcia_socket[i].phys_attr = 0xC4000000; pcmcia_socket[i].phys_mem = 0xC8000000; } else { printk(KERN_ERR "au1000: socket 1 not supported\n"); return 1; } } /* Only advertise as many sockets as we can detect: */ if(register_ss_entry(socket_count, &au1000_pcmcia_operations)<0){ printk(KERN_ERR "Unable to register socket service routine\n"); return -ENXIO; } /* Start the event poll timer. * It will reschedule by itself afterwards. */ au1000_pcmcia_poll_event(0); DEBUG(1, "au1000: initialization complete\n"); return 0; } /* au1000_pcmcia_driver_init() */
static int __init au1000_pcmcia_driver_init(void) { servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state; unsigned int i; printk("\nAu1x00 PCMCIA (CS release %s)\n", CS_RELEASE); #ifndef CONFIG_64BIT_PHYS_ADDR printk(KERN_ERR "Au1x00 PCMCIA 36 bit IO support not enabled\n"); return -1; #endif CardServices(GetCardServicesInfo, &info); if(info.Revision!=CS_RELEASE_CODE){ printk(KERN_ERR "Card Services release codes do not match\n"); return -1; } #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) pcmcia_low_level=&pb1x00_pcmcia_ops; #elif defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) pcmcia_low_level=&db1x00_pcmcia_ops; #elif defined(CONFIG_MIPS_XXS1500) pcmcia_low_level=&xxs1500_pcmcia_ops; #else #error Unsupported AU1000 board. #endif pcmcia_init.handler=au1000_pcmcia_interrupt; if((socket_count=pcmcia_low_level->init(&pcmcia_init))<0) { printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); return -EIO; } /* NOTE: the chip select must already be setup */ pcmcia_socket = kmalloc(sizeof(struct au1000_pcmcia_socket) * socket_count, GFP_KERNEL); if (!pcmcia_socket) { printk(KERN_ERR "Card Services can't get memory \n"); return -1; } memset(pcmcia_socket, 0, sizeof(struct au1000_pcmcia_socket) * socket_count); /* * Assuming max of 2 sockets, which the Au1000 supports. * WARNING: the Pb1000 has two sockets, and both work, but you * can't use them both at the same time due to glue logic conflicts. */ for(i=0; i < socket_count; i++) { if(pcmcia_low_level->socket_state(i, &state)<0){ printk(KERN_ERR "Unable to get PCMCIA status\n"); return -EIO; } pcmcia_socket[i].k_state=state; pcmcia_socket[i].cs_state.csc_mask=SS_DETECT; /* * PCMCIA drivers use the inb/outb macros to access the * IO registers. Since mips_io_port_base is added to the * access address, we need to subtract it here. */ if (i == 0) { pcmcia_socket[i].virt_io = (u32)ioremap((ioaddr_t)AU1X_SOCK0_IO, 0x1000) - mips_io_port_base; pcmcia_socket[i].phys_attr = (ioaddr_t)AU1X_SOCK0_PHYS_ATTR; pcmcia_socket[i].phys_mem = (ioaddr_t)AU1X_SOCK0_PHYS_MEM; } #ifndef CONFIG_MIPS_XXS1500 else { pcmcia_socket[i].virt_io = (u32)ioremap((ioaddr_t)AU1X_SOCK1_IO, 0x1000) - mips_io_port_base; pcmcia_socket[i].phys_attr = (ioaddr_t)AU1X_SOCK1_PHYS_ATTR; pcmcia_socket[i].phys_mem = (ioaddr_t)AU1X_SOCK1_PHYS_MEM; } #endif } /* Only advertise as many sockets as we can detect: */ if(register_ss_entry(socket_count, &au1000_pcmcia_operations)<0){ printk(KERN_ERR "Unable to register socket service routine\n"); return -ENXIO; } /* Start the event poll timer. * It will reschedule by itself afterwards. */ au1000_pcmcia_poll_event(0); DEBUG(1, "au1000: initialization complete\n"); return 0; } /* au1000_pcmcia_driver_init() */
/* * bcm47xx_pcmcia_driver_init() * * This routine performs a basic sanity check to ensure that this * kernel has been built with the appropriate board-specific low-level * PCMCIA support, performs low-level PCMCIA initialization, registers * this socket driver with Card Services, and then spawns the daemon * thread which is the real workhorse of the socket driver. * * Please see linux/Documentation/arm/SA1100/PCMCIA for more information * on the low-level kernel interface. * * Returns: 0 on success, -1 on error */ static int __init bcm47xx_pcmcia_driver_init(void) { servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state; unsigned int i; unsigned long tmp; printk("\nBCM47XX PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if (info.Revision != CS_RELEASE_CODE) { printk(KERN_ERR "Card Services release codes do not match\n"); return -1; } #ifdef CONFIG_BCM4710 pcmcia_low_level=&bcm4710_pcmcia_ops; #else #error Unsupported Broadcom BCM47XX board. #endif pcmcia_init.handler=bcm47xx_pcmcia_interrupt; if ((socket_count = pcmcia_low_level->init(&pcmcia_init)) < 0) { printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); return -EIO; } else { printk("\t%d PCMCIA sockets initialized.\n", socket_count); } pcmcia_socket = kmalloc(sizeof(struct bcm47xx_pcmcia_socket) * socket_count, GFP_KERNEL); memset(pcmcia_socket, 0, sizeof(struct bcm47xx_pcmcia_socket) * socket_count); if (!pcmcia_socket) { printk(KERN_ERR "Card Services can't get memory \n"); return -1; } for (i = 0; i < socket_count; i++) { if (pcmcia_low_level->socket_state(i, &state) < 0) { printk(KERN_ERR "Unable to get PCMCIA status\n"); return -EIO; } pcmcia_socket[i].k_state = state; pcmcia_socket[i].cs_state.csc_mask = SS_DETECT; if (i == 0) { pcmcia_socket[i].virt_io = (unsigned long)ioremap_nocache(EXTIF_PCMCIA_IOBASE(BCM4710_EXTIF), 0x1000); /* Substract ioport base which gets added by in/out */ pcmcia_socket[i].virt_io -= mips_io_port_base; pcmcia_socket[i].phys_attr = (unsigned long)EXTIF_PCMCIA_CFGBASE(BCM4710_EXTIF); pcmcia_socket[i].phys_mem = (unsigned long)EXTIF_PCMCIA_MEMBASE(BCM4710_EXTIF); } else { printk(KERN_ERR "bcm4710: socket 1 not supported\n"); return 1; } } /* Only advertise as many sockets as we can detect: */ if (register_ss_entry(socket_count, &bcm47xx_pcmcia_operations) < 0) { printk(KERN_ERR "Unable to register socket service routine\n"); return -ENXIO; } /* Start the event poll timer. * It will reschedule by itself afterwards. */ bcm47xx_pcmcia_poll_event(0); DEBUG(1, "bcm4710: initialization complete\n"); return 0; }
static int __init init_hs(void) { servinfo_t serv; int i; unsigned short v; /* * Check API version */ pcmcia_get_card_services_info(&serv); if (serv.Revision != CS_RELEASE_CODE) { printk(KERN_NOTICE MODNAME ": Card Services release does not match!\n"); return -ENODEV; } /* hd64465_io_debug = 1; */ /* Wake both sockets out of STANDBY mode */ /* TODO: wait 15ms */ v = inw(HD64465_REG_SMSCR); v &= ~(HD64465_SMSCR_PC0ST|HD64465_SMSCR_PC1ST); outw(v, HD64465_REG_SMSCR); /* keep power controller out of shutdown mode */ v = inb(HD64465_REG_PCC0SCR); v |= HD64465_PCCSCR_SHDN; outb(v, HD64465_REG_PCC0SCR); /* use serial (TPS2206) power controller */ v = inb(HD64465_REG_PCC0CSCR); v |= HD64465_PCCCSCR_PSWSEL; outb(v, HD64465_REG_PCC0CSCR); hs_set_voltages(&hs_sockets[0], 0, 0); hs_set_voltages(&hs_sockets[1], 0, 0); /* * Setup hs_sockets[] structures and request system resources. * TODO: on memory allocation failure, power down the socket * before quitting. */ i = hs_init_socket(&hs_sockets[0], HD64465_IRQ_PCMCIA0, HD64465_PCC0_BASE, HD64465_REG_PCC0ISR); if (i < 0) return i; i = hs_init_socket(&hs_sockets[1], HD64465_IRQ_PCMCIA1, HD64465_PCC1_BASE, HD64465_REG_PCC1ISR); if (i < 0) return i; /* hd64465_io_debug = 0; */ if (register_ss_entry(HS_MAX_SOCKETS, &hs_operations) != 0) { for (i=0 ; i<HS_MAX_SOCKETS ; i++) hs_exit_socket(&hs_sockets[i]); return -ENODEV; } printk(KERN_INFO "HD64465 PCMCIA bridge:\n"); for (i=0 ; i<HS_MAX_SOCKETS ; i++) { hs_socket_t *sp = &hs_sockets[i]; printk(KERN_INFO " socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n", i, sp->mem_base, sp->irq, sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr); } return 0; }
/* sa1100_pcmcia_driver_init() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * This routine performs a basic sanity check to ensure that this * kernel has been built with the appropriate board-specific low-level * PCMCIA support, performs low-level PCMCIA initialization, registers * this socket driver with Card Services, and then spawns the daemon * thread which is the real workhorse of the socket driver. * * Returns: 0 on success, -1 on error */ static int __init sa1100_pcmcia_driver_init(void) { servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK]; struct pcmcia_state_array state_array; unsigned int i, clock; unsigned long mecr; int ret; printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if (info.Revision != CS_RELEASE_CODE) { printk(KERN_ERR "Card Services release codes do not match\n"); return -EINVAL; } ret = sa1100_pcmcia_machine_init(); if (ret) return ret; pcmcia_init.handler = sa1100_pcmcia_interrupt; ret = pcmcia_low_level->init(&pcmcia_init); if (ret < 0) { printk(KERN_ERR "Unable to initialize kernel PCMCIA service (%d).\n", ret); return ret == -1 ? -EIO : ret; } sa1100_pcmcia_socket_count = ret; state_array.size = sa1100_pcmcia_socket_count; state_array.state = state; memset(state, 0, sizeof(state)); if (pcmcia_low_level->socket_state(&state_array) < 0) { pcmcia_low_level->shutdown(); printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); return -EIO; } /* * We initialize the MECR to default values here, because we are * not guaranteed to see a SetIOMap operation at runtime. */ mecr = MECR; clock = cpufreq_get(0); for (i = 0; i < sa1100_pcmcia_socket_count; i++) { struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(i); struct pcmcia_irq_info irq_info; if (!request_mem_region(_PCMCIA(i), PCMCIASp, "PCMCIA")) { ret = -EBUSY; goto out_err; } irq_info.sock = i; irq_info.irq = -1; ret = pcmcia_low_level->get_irq_info(&irq_info); if (ret < 0) printk(KERN_ERR "Unable to get IRQ for socket %u (%d)\n", i, ret); skt->irq = irq_info.irq; skt->k_state = state[i]; skt->speed_io = SA1100_PCMCIA_IO_ACCESS; skt->speed_attr = SA1100_PCMCIA_5V_MEM_ACCESS; skt->speed_mem = SA1100_PCMCIA_5V_MEM_ACCESS; skt->phys_attr = _PCMCIAAttr(i); skt->phys_mem = _PCMCIAMem(i); skt->virt_io = ioremap(_PCMCIAIO(i), 0x10000); if (skt->virt_io == NULL) { ret = -ENOMEM; goto out_err; } MECR_FAST_SET(mecr, i, 0); MECR_BSIO_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_io, clock)); MECR_BSA_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_attr, clock)); MECR_BSM_SET(mecr, i, sa1100_pcmcia_mecr_bs(skt->speed_mem, clock)); } MECR = mecr; #ifdef CONFIG_CPU_FREQ ret = cpufreq_register_notifier(&sa1100_pcmcia_notifier_block); if (ret < 0) { printk(KERN_ERR "Unable to register CPU frequency change notifier (%d)\n", ret); goto out_err; } #endif /* Only advertise as many sockets as we can detect */ ret = register_ss_entry(sa1100_pcmcia_socket_count, &sa1100_pcmcia_operations); if (ret < 0) { printk(KERN_ERR "Unable to register sockets\n"); goto out_err; } /* * Start the event poll timer. It will reschedule by itself afterwards. */ sa1100_pcmcia_poll_event(0); return 0; out_err: for (i = 0; i < sa1100_pcmcia_socket_count; i++) { iounmap(sa1100_pcmcia_socket[i].virt_io); release_mem_region(_PCMCIA(i), PCMCIASp); } pcmcia_low_level->shutdown(); return ret; } /* sa1100_pcmcia_driver_init() */
/* sa1100_pcmcia_driver_init() * ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * * This routine performs a basic sanity check to ensure that this * kernel has been built with the appropriate board-specific low-level * PCMCIA support, performs low-level PCMCIA initialization, registers * this socket driver with Card Services, and then spawns the daemon * thread which is the real workhorse of the socket driver. * * Please see linux/Documentation/arm/SA1100/PCMCIA for more information * on the low-level kernel interface. * * Returns: 0 on success, -1 on error */ static int __init sa1100_pcmcia_driver_init(void){ servinfo_t info; struct pcmcia_init pcmcia_init; struct pcmcia_state state[SA1100_PCMCIA_MAX_SOCK]; struct pcmcia_state_array state_array; unsigned int i, clock; unsigned long mecr; printk(KERN_INFO "SA-1100 PCMCIA (CS release %s)\n", CS_RELEASE); CardServices(GetCardServicesInfo, &info); if(info.Revision!=CS_RELEASE_CODE){ printk(KERN_ERR "Card Services release codes do not match\n"); return -1; } if(machine_is_assabet()){ #ifdef CONFIG_SA1100_ASSABET if(machine_has_neponset()){ #ifdef CONFIG_ASSABET_NEPONSET pcmcia_low_level=&neponset_pcmcia_ops; #else printk(KERN_ERR "Card Services disabled: missing Neponset support\n"); return -1; #endif }else{ pcmcia_low_level=&assabet_pcmcia_ops; } #endif } else if (machine_is_freebird()) { #ifdef CONFIG_SA1100_FREEBIRD pcmcia_low_level = &freebird_pcmcia_ops; #endif } else if (machine_is_h3xxx()) { #ifdef CONFIG_SA1100_H3XXX pcmcia_low_level = &h3600_pcmcia_ops; #endif } else if (machine_is_cerf()) { #ifdef CONFIG_SA1100_CERF pcmcia_low_level = &cerf_pcmcia_ops; #endif } else if (machine_is_graphicsclient()) { #ifdef CONFIG_SA1100_GRAPHICSCLIENT pcmcia_low_level = &gcplus_pcmcia_ops; #endif } else if (machine_is_xp860()) { #ifdef CONFIG_SA1100_XP860 pcmcia_low_level = &xp860_pcmcia_ops; #endif } else if (machine_is_yopy()) { #ifdef CONFIG_SA1100_YOPY pcmcia_low_level = &yopy_pcmcia_ops; #endif } else if (machine_is_shannon()) { #ifdef CONFIG_SA1100_SHANNON pcmcia_low_level = &shannon_pcmcia_ops; #endif } else if (machine_is_pangolin()) { #ifdef CONFIG_SA1100_PANGOLIN pcmcia_low_level = &pangolin_pcmcia_ops; #endif } else if (machine_is_jornada720()) { #ifdef CONFIG_SA1100_JORNADA720 pcmcia_low_level = &jornada720_pcmcia_ops; #endif } else if(machine_is_pfs168()){ #ifdef CONFIG_SA1100_PFS168 pcmcia_low_level=&pfs168_pcmcia_ops; #endif } else if(machine_is_flexanet()){ #ifdef CONFIG_SA1100_FLEXANET pcmcia_low_level=&flexanet_pcmcia_ops; #endif } else if(machine_is_simpad()){ #ifdef CONFIG_SA1100_SIMPAD pcmcia_low_level=&simpad_pcmcia_ops; #endif } else if(machine_is_graphicsmaster()) { #ifdef CONFIG_SA1100_GRAPHICSMASTER pcmcia_low_level=&graphicsmaster_pcmcia_ops; #endif } else if(machine_is_adsbitsy()) { #ifdef CONFIG_SA1100_ADSBITSY pcmcia_low_level=&adsbitsy_pcmcia_ops; #endif } else if(machine_is_stork()) { #ifdef CONFIG_SA1100_STORK pcmcia_low_level=&stork_pcmcia_ops; #endif } if (!pcmcia_low_level) { printk(KERN_ERR "This hardware is not supported by the SA1100 Card Service driver\n"); return -ENODEV; } pcmcia_init.handler=sa1100_pcmcia_interrupt; if((sa1100_pcmcia_socket_count=pcmcia_low_level->init(&pcmcia_init))<0){ printk(KERN_ERR "Unable to initialize kernel PCMCIA service.\n"); return -EIO; } state_array.size=sa1100_pcmcia_socket_count; state_array.state=state; if(pcmcia_low_level->socket_state(&state_array)<0){ printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); return -EIO; } /* We initialize the MECR to default values here, because we are * not guaranteed to see a SetIOMap operation at runtime. */ mecr=0; clock = cpufreq_get(0); for(i=0; i<sa1100_pcmcia_socket_count; ++i){ sa1100_pcmcia_socket[i].k_state=state[i]; /* This is an interim fix. Apparently, SetSocket is no longer * called to initialize each socket (prior to the first detect * event). For now, we'll just manually set up the mask. */ sa1100_pcmcia_socket[i].cs_state.csc_mask=SS_DETECT; sa1100_pcmcia_socket[i].virt_io=(i==0)?PCMCIA_IO_0_BASE:PCMCIA_IO_1_BASE; sa1100_pcmcia_socket[i].phys_attr=_PCMCIAAttr(i); sa1100_pcmcia_socket[i].phys_mem=_PCMCIAMem(i); MECR_FAST_SET(mecr, i, 0); MECR_BSIO_SET(mecr, i, sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_IO_ACCESS, clock)); MECR_BSA_SET(mecr, i, sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock)); MECR_BSM_SET(mecr, i, sa1100_pcmcia_mecr_bs(SA1100_PCMCIA_5V_MEM_ACCESS, clock)); sa1100_pcmcia_socket[i].speed_io=SA1100_PCMCIA_IO_ACCESS; sa1100_pcmcia_socket[i].speed_attr=SA1100_PCMCIA_5V_MEM_ACCESS; sa1100_pcmcia_socket[i].speed_mem=SA1100_PCMCIA_5V_MEM_ACCESS; } MECR=mecr; #ifdef CONFIG_CPU_FREQ if(cpufreq_register_notifier(&sa1100_pcmcia_notifier_block) < 0){ printk(KERN_ERR "Unable to register CPU frequency change notifier\n"); return -ENXIO; } #endif /* Only advertise as many sockets as we can detect: */ if(register_ss_entry(sa1100_pcmcia_socket_count, &sa1100_pcmcia_operations)<0){ printk(KERN_ERR "Unable to register socket service routine\n"); return -ENXIO; } /* Start the event poll timer. It will reschedule by itself afterwards. */ sa1100_pcmcia_poll_event(0); DEBUG(1, "sa1100: initialization complete\n"); return 0; } /* sa1100_pcmcia_driver_init() */