/* sa1100_pcmcia_set_io_map()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the set_io_map() operation for the in-kernel PCMCIA
 * service (formerly SS_SetIOMap in Card Services). We configure
 * the map speed as requested, but override the address ranges
 * supplied by Card Services.
 *
 * Returns: 0 on success, -1 on error
 */
static int
sa1100_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map)
{
  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);

  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);

  DEBUG(3, "\tmap %u  speed %u\n\tstart 0x%08x  stop 0x%08x\n",
	map->map, map->speed, map->start, map->stop);
  DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
	(map->flags==0)?"<NONE>":"",
	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
	(map->flags&MAP_16BIT)?"16BIT ":"",
	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
	(map->flags&MAP_0WS)?"0WS ":"",
	(map->flags&MAP_WRPROT)?"WRPROT ":"",
	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
	(map->flags&MAP_PREFETCH)?"PREFETCH ":"");

  if (map->map >= MAX_IO_WIN) {
    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
	   map->map);
    return -1;
  }

  if (map->flags & MAP_ACTIVE) {
    unsigned int clock, speed = map->speed;
    unsigned long mecr;

    if (speed == 0)
      speed = SA1100_PCMCIA_IO_ACCESS;

    clock = cpufreq_get(0);

    mecr = MECR;

    MECR_BSIO_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));

    skt->speed_io = speed;

    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
	  sock, MECR_BSIO_GET(mecr, sock));

    MECR = mecr;
  }

  if (map->stop == 1)
    map->stop = PAGE_SIZE-1;

  map->stop -= map->start;
  map->stop += (unsigned long)skt->virt_io;
  map->start = (unsigned long)skt->virt_io;

  skt->io_map[map->map] = *map;

  return 0;
}  /* sa1100_pcmcia_set_io_map() */
Пример #2
0
/* pxa_pcmcia_set_mem_map()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the set_mem_map() operation for the in-kernel PCMCIA
 * service (formerly SS_SetMemMap in Card Services). We configure
 * the map speed as requested, but override the address ranges
 * supplied by Card Services.
 *
 * Returns: 0 on success, -1 on error
 */
static int pxa_pcmcia_set_mem_map(unsigned int sock,
				     struct pccard_mem_map *map){
  unsigned int clock, speed;
  unsigned long mecr, start;

  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);

  DEBUG(4, "\tmap %u  speed %u\n\tsys_start  %#lx\n"
	"\tsys_stop   %#lx\n\tcard_start %#x\n"
	"\tflags: %s%s%s%s%s%s%s%s\n",
	map->map, map->speed, map->sys_start, map->sys_stop,
	map->card_start, (map->flags==0)?"<NONE>":"",
	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
	(map->flags&MAP_16BIT)?"16BIT ":"",
	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
	(map->flags&MAP_0WS)?"0WS ":"",
	(map->flags&MAP_WRPROT)?"WRPROT ":"",
	(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");

  if(map->map>=MAX_WIN){
    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
	   map->map);
    return -1;
  }

  if(map->flags&MAP_ACTIVE){
    /* When clients issue RequestMap, the access speed is not always
     * properly configured:
     */
    if(map->speed > 0)
      speed = map->speed;
    else
      switch(pxa_pcmcia_socket[sock].cs_state.Vcc){
      case 33:
	speed = PXA_PCMCIA_3V_MEM_ACCESS;
	break;
      default:
	speed = PXA_PCMCIA_5V_MEM_ACCESS;
      }

    clock = get_lclk_frequency_10khz();

    if(map->flags&MAP_ATTRIB){
      if (sock == 0) {
        MCATT0 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
               | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
               | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
      } else {
        MCATT1 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
               | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
               | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
      }
      pxa_pcmcia_socket[sock].speed_attr=speed;
    } else {
      if (sock == 0) {
        MCMEM0 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
               | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
               | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
      } else {
        MCMEM1 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
               | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
               | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
      }
      pxa_pcmcia_socket[sock].speed_mem=speed;
    }
    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
	  sock, MECR_BSIO_GET(mecr, sock));
  }

  start=map->sys_start;

  if(map->sys_stop==0)
    map->sys_stop=PAGE_SIZE-1;

  map->sys_start=(map->flags & MAP_ATTRIB)?\
    pxa_pcmcia_socket[sock].phys_attr:\
    pxa_pcmcia_socket[sock].phys_mem;

  map->sys_stop=map->sys_start+(map->sys_stop-start);

  pxa_pcmcia_socket[sock].mem_map[map->map]=*map;

  return 0;

}  /* pxa_pcmcia_set_mem_map() */
Пример #3
0
/* pxa_pcmcia_set_io_map()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the set_io_map() operation for the in-kernel PCMCIA
 * service (formerly SS_SetIOMap in Card Services). We configure
 * the map speed as requested, but override the address ranges
 * supplied by Card Services.
 *
 * Returns: 0 on success, -1 on error
 */
static int pxa_pcmcia_set_io_map(unsigned int sock,
				    struct pccard_io_map *map){
  unsigned int clock, speed;
  unsigned long mecr, start;

  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);

  DEBUG(4, "\tmap %u  speed %u\n\tstart 0x%08lx  stop 0x%08lx\n"
	"\tflags: %s%s%s%s%s%s%s%s\n",
	map->map, map->speed, map->start, map->stop,
	(map->flags==0)?"<NONE>":"",
	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
	(map->flags&MAP_16BIT)?"16BIT ":"",
	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
	(map->flags&MAP_0WS)?"0WS ":"",
	(map->flags&MAP_WRPROT)?"WRPROT ":"",
	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
	(map->flags&MAP_PREFETCH)?"PREFETCH ":"");

  if(map->map>=MAX_IO_WIN){
    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
	   map->map);
    return -1;
  }

  if(map->flags&MAP_ACTIVE){

    speed=(map->speed>0)?map->speed:PXA_PCMCIA_IO_ACCESS;

    clock = get_lclk_frequency_10khz();

    pxa_pcmcia_socket[sock].speed_io=speed;

    if (sock == 0) {
      MCIO0 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
            | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
            | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
    } else {
      MCIO1 = ((pxa_mcxx_setup(speed, clock)
			& MCXX_SETUP_MASK) << MCXX_SETUP_SHIFT)
            | ((pxa_mcxx_asst(speed, clock)
			& MCXX_ASST_MASK) << MCXX_ASST_SHIFT)
            | ((pxa_mcxx_hold(speed, clock)
			& MCXX_HOLD_MASK) << MCXX_HOLD_SHIFT);
    }

    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
	  sock, MECR_BSIO_GET(mecr, sock));

  }

  start=map->start;

  if(map->stop==1)
    map->stop=PAGE_SIZE-1;

  map->start=pxa_pcmcia_socket[sock].virt_io;
  map->stop=map->start+(map->stop-start);

  pxa_pcmcia_socket[sock].io_map[map->map]=*map;

  return 0;

}  /* pxa_pcmcia_set_io_map() */
/* sa1100_pcmcia_proc_status()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the /proc/bus/pccard/??/status file.
 *
 * Returns: the number of characters added to the buffer
 */
static int
sa1100_pcmcia_proc_status(char *buf, char **start, off_t pos,
			  int count, int *eof, void *data)
{
  unsigned int sock = (unsigned int)data;
  unsigned int clock = cpufreq_get(0);
  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
  unsigned long mecr = MECR;
  char *p = buf;

  p+=sprintf(p, "k_state  : %s%s%s%s%s%s%s\n", 
	     skt->k_state.detect ? "detect " : "",
	     skt->k_state.ready  ? "ready "  : "",
	     skt->k_state.bvd1   ? "bvd1 "   : "",
	     skt->k_state.bvd2   ? "bvd2 "   : "",
	     skt->k_state.wrprot ? "wrprot " : "",
	     skt->k_state.vs_3v  ? "vs_3v "  : "",
	     skt->k_state.vs_Xv  ? "vs_Xv "  : "");

  p+=sprintf(p, "status   : %s%s%s%s%s%s%s%s%s\n",
	     skt->k_state.detect ? "SS_DETECT " : "",
	     skt->k_state.ready  ? "SS_READY " : "",
	     skt->cs_state.Vcc   ? "SS_POWERON " : "",
	     skt->cs_state.flags & SS_IOCARD ? "SS_IOCARD " : "",
	     (skt->cs_state.flags & SS_IOCARD &&
	      skt->k_state.bvd1) ? "SS_STSCHG " : "",
	     ((skt->cs_state.flags & SS_IOCARD)==0 &&
	      (skt->k_state.bvd1==0)) ? "SS_BATDEAD " : "",
	     ((skt->cs_state.flags & SS_IOCARD)==0 &&
	      (skt->k_state.bvd2==0)) ? "SS_BATWARN " : "",
	     skt->k_state.vs_3v  ? "SS_3VCARD " : "",
	     skt->k_state.vs_Xv  ? "SS_XVCARD " : "");

  p+=sprintf(p, "mask     : %s%s%s%s%s\n",
	     skt->cs_state.csc_mask & SS_DETECT  ? "SS_DETECT "  : "",
	     skt->cs_state.csc_mask & SS_READY   ? "SS_READY "   : "",
	     skt->cs_state.csc_mask & SS_BATDEAD ? "SS_BATDEAD " : "",
	     skt->cs_state.csc_mask & SS_BATWARN ? "SS_BATWARN " : "",
	     skt->cs_state.csc_mask & SS_STSCHG  ? "SS_STSCHG "  : "");

  p+=sprintf(p, "cs_flags : %s%s%s%s%s\n",
	     skt->cs_state.flags & SS_PWR_AUTO   ? "SS_PWR_AUTO "   : "",
	     skt->cs_state.flags & SS_IOCARD     ? "SS_IOCARD "     : "",
	     skt->cs_state.flags & SS_RESET      ? "SS_RESET "      : "",
	     skt->cs_state.flags & SS_SPKR_ENA   ? "SS_SPKR_ENA "   : "",
	     skt->cs_state.flags & SS_OUTPUT_ENA ? "SS_OUTPUT_ENA " : "");

  p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
  p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
  p+=sprintf(p, "IRQ      : %d\n", skt->cs_state.io_irq);

  p+=sprintf(p, "I/O      : %u (%u)\n", skt->speed_io,
	     sa1100_pcmcia_cmd_time(clock, MECR_BSIO_GET(mecr, sock)));

  p+=sprintf(p, "attribute: %u (%u)\n", skt->speed_attr,
	     sa1100_pcmcia_cmd_time(clock, MECR_BSA_GET(mecr, sock)));

  p+=sprintf(p, "common   : %u (%u)\n", skt->speed_mem,
	     sa1100_pcmcia_cmd_time(clock, MECR_BSM_GET(mecr, sock)));

  return p-buf;
}
/* sa1100_pcmcia_set_mem_map()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the set_mem_map() operation for the in-kernel PCMCIA
 * service (formerly SS_SetMemMap in Card Services). We configure
 * the map speed as requested, but override the address ranges
 * supplied by Card Services.
 *
 * Returns: 0 on success, -1 on error
 */
static int
sa1100_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map)
{
  struct sa1100_pcmcia_socket *skt = PCMCIA_SOCKET(sock);
  unsigned long start;

  DEBUG(2, "%s() for sock %u\n", __FUNCTION__, sock);

  DEBUG(3, "\tmap %u speed %u sys_start %08lx sys_stop %08lx card_start %08x\n",
	map->map, map->speed, map->sys_start, map->sys_stop, map->card_start);
  DEBUG(3, "\tflags: %s%s%s%s%s%s%s%s\n",
	(map->flags==0)?"<NONE>":"",
	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
	(map->flags&MAP_16BIT)?"16BIT ":"",
	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
	(map->flags&MAP_0WS)?"0WS ":"",
	(map->flags&MAP_WRPROT)?"WRPROT ":"",
	(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");

  if (map->map >= MAX_WIN){
    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
	   map->map);
    return -1;
  }

  if (map->flags & MAP_ACTIVE) {
    unsigned int clock, speed = map->speed;
    unsigned long mecr;

    /*
     * When clients issue RequestMap, the access speed is not always
     * properly configured.  Choose some sensible defaults.
     */
    if (speed == 0) {
      if (skt->cs_state.Vcc == 33)
	speed = SA1100_PCMCIA_3V_MEM_ACCESS;
      else
	speed = SA1100_PCMCIA_5V_MEM_ACCESS;
    }

    clock = cpufreq_get(0);

    /* Fixme: MECR is not pre-empt safe. */
    mecr = MECR;

    if (map->flags & MAP_ATTRIB) {
      MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
      skt->speed_attr = speed;
    } else {
      MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
      skt->speed_mem = speed;
    }

    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
	  sock, MECR_BSIO_GET(mecr, sock));

    MECR = mecr;
  }

  start = (map->flags & MAP_ATTRIB) ? skt->phys_attr : skt->phys_mem;

  if (map->sys_stop == 0)
    map->sys_stop = PAGE_SIZE-1;

  map->sys_stop -= map->sys_start;
  map->sys_stop += start;
  map->sys_start = start;

  skt->mem_map[map->map] = *map;

  return 0;
}  /* sa1100_pcmcia_set_mem_map() */
Пример #6
0
/* sa1100_pcmcia_set_mem_map()
 * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 * Implements the set_mem_map() operation for the in-kernel PCMCIA
 * service (formerly SS_SetMemMap in Card Services). We configure
 * the map speed as requested, but override the address ranges
 * supplied by Card Services.
 *
 * Returns: 0 on success, -1 on error
 */
static int sa1100_pcmcia_set_mem_map(unsigned int sock,
				     struct pccard_mem_map *map){
  unsigned int clock, speed;
  unsigned long mecr, start;

  DEBUG(4, "%s() for sock %u\n", __FUNCTION__, sock);

  DEBUG(4, "\tmap %u  speed %u\n\tsys_start  %#lx\n"
	"\tsys_stop   %#lx\n\tcard_start %#x\n"
	"\tflags: %s%s%s%s%s%s%s%s\n",
	map->map, map->speed, map->sys_start, map->sys_stop,
	map->card_start, (map->flags==0)?"<NONE>":"",
	(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
	(map->flags&MAP_16BIT)?"16BIT ":"",
	(map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
	(map->flags&MAP_0WS)?"0WS ":"",
	(map->flags&MAP_WRPROT)?"WRPROT ":"",
	(map->flags&MAP_ATTRIB)?"ATTRIB ":"",
	(map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");

  if(map->map>=MAX_WIN){
    printk(KERN_ERR "%s(): map (%d) out of range\n", __FUNCTION__,
	   map->map);
    return -1;
  }

  if(map->flags&MAP_ACTIVE){

    /* When clients issue RequestMap, the access speed is not always
     * properly configured:
     */
    if(map->speed > 0)
      speed = map->speed;
    else
      switch(sa1100_pcmcia_socket[sock].cs_state.Vcc){
      case 33:
	speed = SA1100_PCMCIA_3V_MEM_ACCESS;
	break;
      default:
	speed = SA1100_PCMCIA_5V_MEM_ACCESS;
      }

    clock = cpufreq_get(0);
    
    mecr=MECR;
    
    if(map->flags&MAP_ATTRIB){

      MECR_BSA_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
      sa1100_pcmcia_socket[sock].speed_attr=speed;

    } else {

      MECR_BSM_SET(mecr, sock, sa1100_pcmcia_mecr_bs(speed, clock));
      sa1100_pcmcia_socket[sock].speed_mem=speed;

    }
    
    DEBUG(4, "%s(): FAST%u %lx  BSM%u %lx  BSA%u %lx  BSIO%u %lx\n",
	  __FUNCTION__, sock, MECR_FAST_GET(mecr, sock), sock,
	  MECR_BSM_GET(mecr, sock), sock, MECR_BSA_GET(mecr, sock), 
	  sock, MECR_BSIO_GET(mecr, sock));
    
    MECR=mecr;

  }

  start=map->sys_start;

  if(map->sys_stop==0)
    map->sys_stop=PAGE_SIZE-1;

  map->sys_start=(map->flags & MAP_ATTRIB)?\
    sa1100_pcmcia_socket[sock].phys_attr:\
    sa1100_pcmcia_socket[sock].phys_mem;

  map->sys_stop=map->sys_start+(map->sys_stop-start);

  sa1100_pcmcia_socket[sock].mem_map[map->map]=*map;

  return 0;

}  /* sa1100_pcmcia_set_mem_map() */