Exemplo n.º 1
0
/*!
 * This function sends a SPI frame.
 *
 * @param        buffer		The buffer to send, this buffer must
 *				be allocated with 'nb' bytes size by user
 * @param        bytes          The number of bytes to send, can not be more than 32 bytes.
 * @param        client_config  The handle to identify the SPI device.
 *
 * @return       		This function returns the number of bytes sent
 *				minus the number of received bytes, -1 in case of error.
 */
ssize_t spi_send_frame(unsigned char *buffer, unsigned int bytes,
		       spi_config * client_config)
{
	unsigned long reg;
	module_nb_t mod;
	int error, result;

	if ((buffer == NULL) || (client_config == NULL)) {
		return -1;
	}
	result = -1;
	spin_lock(&mxc_spi_lock);

	if ((bytes * 8) > (client_config->bit_count * 8)) {
		goto error_out;
	}

	mod = client_config->module_number;
	spi_port[mod].hw_config = client_config;

	spi_port[mod].bytes_to_send = bytes;
	spi_port[mod].bytes_received = 0;

	if (spi_port[mod].current_config_handle != client_config) {
		error = spi_hard_config(mod, (void *)client_config);
		if (error < 0) {
			goto error_out;
		}

		spi_port[mod].current_config_handle = (void *)client_config;
	}

	spi_put_tx_data(mod, buffer, bytes);
	DBG_PRINTK("spi%d : sent %d bytes\n", mod + 1, bytes);

	do {
		reg = __raw_readl(IO_ADDRESS(spi_add[mod].ctrl_address));

	} while (reg & MXC_CSPICONREG_XCH);

	spi_port[mod].rx_buffer = buffer;
	result = 0;
	do {
		result += spi_get_rx_data(mod, buffer, bytes);
		buffer += result;
	} while (spi_port[mod].bytes_to_send > result);

	DBG_PRINTK("spi%d : received %d bytes\n", mod + 1, result);
	spi_port[mod].bytes_received = result;
	result = bytes - result;

      error_out:
	spin_unlock(&mxc_spi_lock);
	return result;
}
Exemplo n.º 2
0
static ssize_t mymsg_read(struct file *file, char __user *buf,
			 size_t count, loff_t *ppos)
{    
    int i = 0;
	int error = 0;
    char ch;

	if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_flag())
		return -EAGAIN;

    DBG_PRINTK("%s %d\n", __FUNCTION__, __LINE__);
    DBG_PRINTK("count = %d\n", count);
    DBG_PRINTK("mylog_read = %d\n", mylog_read);
    DBG_PRINTK("mylog_write = %d\n", mylog_write);

    error = wait_event_interruptible(mymsg_waitq, !is_mylog_empty_flag());

    DBG_PRINTK("%s %d\n", __FUNCTION__, __LINE__);
    DBG_PRINTK("count = %d\n", count);
    DBG_PRINTK("mylog_read = %d\n", mylog_read);
    DBG_PRINTK("mylog_write = %d\n", mylog_write);

    /* copy_to_user */
    while (!error && mylog_getc_flag(&ch) && i < count) {
        error = __put_user(ch, buf);
        buf++;
        i++;
    }    

    if (!error)
        error = i;

    return error;
}
Exemplo n.º 3
0
/*!
 * This function is called when an interrupt occurs on the SPI modules.
 * It is the interrupt handler for the SPI modules.
 *
 * @param        irq        the irq number
 * @param        dev_id     the pointer on the device
 * @param        regs       the interrupt parameters
 *
 * @return       The function returns IRQ_RETVAL(1) when handled.
 */
static irqreturn_t spi_isr_handler(int irq, void *dev_id, struct pt_regs *regs)
{
	int handled = 0;
	int nb_bytes = 0;
	module_nb_t module = 0;
	spi_mxc_port *port = NULL;
	unsigned int buf_size_empty = 0;

	port = (spi_mxc_port *) (dev_id);

	module = port->hw_config->module_number;
	buf_size_empty = port->bytes_to_send - port->bytes_received;

	DBG_PRINTK("spi%d : spi_isr_handler : rx_fifo_data_ready \n",
		   module + 1);

	if (buf_size_empty > 0) {
		nb_bytes = spi_get_rx_data(module, port->rx_buffer,
					   buf_size_empty);
	}
	spi_clear_interrupt(module, SPI_STATUS_RX_FIFO_DATA_READY);
	port->rx_buffer += nb_bytes;
	port->bytes_received += nb_bytes;

	if (port->bytes_received >= port->bytes_to_send) {
		/* wakeup a synchronous call to spi_send_frame */
		up(&(port->sync_interface));
	}

	handled = 1;

	return IRQ_RETVAL(handled);
}
Exemplo n.º 4
0
static int usb2ip_disable (void)
{
	gcgu_config_regs = (unsigned int *) ioremap_nocache(CGU_CONFIG_REGS_BASE, CGU_CONFIG_REGS_LENGTH) ;
	if ( gcgu_config_regs == 0){
		printk( "USB2: Unable to map the CGU_BASE configuration memory region.\n" ) ;
		return -ENOMEM;
	}
	DBG_PRINTK( "USB2: gcgu_config_regs: phys: 0X%08x  virt: 0X%08x.\n",CGU_CONFIG_REGS_BASE, gcgu_config_regs);
	writel(0, gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT);
	writel(1, VA_SYSCREG_USB_ATX_PLL_PD_REG);

	iounmap((void*) gcgu_config_regs );
	return 0;
}
Exemplo n.º 5
0
int usb2ip_init (struct amba_device *d)
{
	int retval = 0;

	// set driver private data
	d->res.start	= USB_OTG_SLV_BASE;
	d->res.end	= USB_OTG_SLV_BASE + USB_OTG_SLV_LENGTH - 1;
	d->res.flags	= IORESOURCE_MEM;
	d->irq[0]	= IRQ_USB_OTG_IRQ;
	d->irq[1]	= NO_IRQ;
	d->periphid	= 0x00141077; /* TODO: what needs to be in here? (made up: conf=0, rev=1, manuf=0x41?=arm, part=0x077) */
	//strcpy(d->name, "ehci-amba ");

	// initialize core
	if ((retval = usb2ip_enable()) < 0)  {
		DBG_PRINTK("Failed to enable usb core\n");
		return retval;
	}

	return 0;
}
Exemplo n.º 6
0
static int usb2ip_enable (void)
{
	u32 value=0;

	/*Memory for CGU registers */
	gcgu_config_regs = (unsigned int *) ioremap_nocache(CGU_CONFIG_REGS_BASE, CGU_CONFIG_REGS_LENGTH) ;
	if ( gcgu_config_regs == 0){
		printk( "USB2: Unable to map the CGU_BASE configuration memory region.\n" ) ;
		return -ENOMEM;
	}
	DBG_PRINTK( "USB2: gpcgu_config_regs: phys: 0X%08x  virt: 0X%08x.\n",CGU_CONFIG_REGS_BASE, gcgu_config_regs);

	DBG_PRINTK( "USB2: gpsyscreg_regs: phys:0X%08x virt:0X%08x.\n",SYSCREG_REGS_BASE, IO_ADDRESS_SYSCREG_BASE);

	/*Memory for USB OTG */
	gpusb_otg_regs = (pusb_otg_regs) ioremap_nocache(USB_OTG_SLV_BASE, USB_OTG_SLV_LENGTH);
	if ( gpusb_otg_regs == 0 ){
		printk( "USB2: Unable to map the USB_OTG_SLV_BASE configuration memory region.\n" ) ;
		return -ENOMEM;
	}
	DBG_PRINTK( "USB2: gpusb_otg_regs: phys:0X%08x virt:0X%08x.\n",USB_OTG_SLV_BASE, (unsigned int)gpusb_otg_regs);

	/*
	 * Init sequence
	 */
#ifdef PNX0106_USB_DEBUG
	DBG_PRINTK("usb_otg_ahb_rst_n_soft(0X%08x) = 0x%08x\n",
			(unsigned int)(gcgu_config_regs +CGU_CONFIG_USB_AHB_RST_N_SOFT),
			readl(gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT));
#endif
	writel(0, gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT);

	/*1- set PLL SYSCREG_USB_ATX_PLL_PD_REG On */
	value = readl(VA_SYSCREG_USB_ATX_PLL_PD_REG);
	DBG_PRINTK( "USB2: SYSCREG_USB_ATX_PLL_PD_REG(0X%08x) = 0X%08x\n",(unsigned int)VA_SYSCREG_USB_ATX_PLL_PD_REG , value);
	writel(0, VA_SYSCREG_USB_ATX_PLL_PD_REG);
	mdelay (2) ;
	/*value = readl(gpsyscreg_regs + SYSCREG_USB_ATX_PLL_PD_REG); */
	value = readl(VA_SYSCREG_USB_ATX_PLL_PD_REG);
	DBG_PRINTK( "USB2: SYSCREG_USB_ATX_PLL_PD_REG(0X%08x) = 0X%08x\n",(unsigned int)VA_SYSCREG_USB_ATX_PLL_PD_REG , value);

	/*Wait PLL Lock */
	DBG_PRINTK("Wait PLL...\n");
	for(;;){
		udelay (100);
		value = readl(IO_ADDRESS_EVENT_ROUTER_BASE + 0x0C00 + ( 4 * ( ER_EVENT_SLICE(EVENT_ID_USB_ATX_PLL_LOCK) ) ) );
		if( !(value & (ER_EVENT_MASK(EVENT_ID_USB_ATX_PLL_LOCK))) )
			break;
		DBG_PRINTK("EVENT PENDING Register value: 0X%08x\n", value);
	}
	DBG_PRINTK("\nUSB PLL locked\n");
	DBG_PRINTK("usb_atx_pll_pd_reg(0X%08x) = 0x%08x\n",(unsigned int) (unsigned int)VA_SYSCREG_USB_ATX_PLL_PD_REG, readl(VA_SYSCREG_USB_ATX_PLL_PD_REG) );
	DBG_PRINTK("Wait 25 secs\n");
	mdelay (25);

	/*Set AHB clock ON */
	DBG_PRINTK("usb_otg_ahb_rst_n_soft(0X%08x) = 0x%08x\n",(unsigned int)(gcgu_config_regs +CGU_CONFIG_USB_AHB_RST_N_SOFT),readl(gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT));
	writel(0, gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT);
	mdelay (50) ;
	writel(1, gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT);
	mdelay (10) ;
	DBG_PRINTK("usb_otg_ahb_rst_n_soft(0X%08x) = 0x%08x\n",(unsigned int)(gcgu_config_regs +CGU_CONFIG_USB_AHB_RST_N_SOFT),readl(gcgu_config_regs+CGU_CONFIG_USB_AHB_RST_N_SOFT));

	/*Select OTG CORE */
	DBG_PRINTK("usb_otg_cfg(0X%08x) = 0x%08x\n",(unsigned int)VA_SYSCREG_USB_OTG_CFG, readl(VA_SYSCREG_USB_OTG_CFG));
	/*gpsyscreg_regs->usb_otg_cfg |= ~0x1; */
	writel(0x5, VA_SYSCREG_USB_OTG_CFG);
	mdelay (10) ;
	DBG_PRINTK("usb_otg_cfg(0X%08x) = 0x%08x\n",(unsigned int)VA_SYSCREG_USB_OTG_CFG, readl(VA_SYSCREG_USB_OTG_CFG));
	if ((gpusb_otg_regs->usbsts) & (1<<4))
		DBG_PRINTK("Error usb_otg_cfg(0X%08x) = 0x%08x\n",(unsigned int)&(gpusb_otg_regs->usbsts),(unsigned int)gpusb_otg_regs->usbsts);

	/* we may have to set host mode and USB power enable gpio bits */
	/* USB power is initially off (unless bootloader has detected service mode UART on pce da2007 platforms...) */
	/* USB power is switched on from userspace via /proc/vbus during application startup */

#if defined (CONFIG_ARCH_PNX0106)
#if defined (CONFIG_SERIAL_PNX010X_CONSOLE)
#if defined (CONFIG_PNX0106_HASLI7) || \
	defined (CONFIG_PNX0106_HACLI7) || \
	defined (CONFIG_PNX0106_MCIH) || \
	defined (CONFIG_PNX0106_MCI)

	extern int pnx010x_console_in_use;

	if (pnx010x_console_in_use)
	{
		printk ("%s"
			"##\n"
			"## Console is on internal UART0... switching on USB vbus.\n"
			"##\n"
			"## THIS MESSAGE SHOULD ONLY BE SEEN WHEN SERVICE UART USED !!\n"
			"##\n"
			"%s",
			"##################################################################\n",
			"##################################################################\n");

		usb_set_vbus_on();
	}
	else
#endif
#endif
#endif
	{
		usb_set_vbus_off();
	}

#if defined (GPIO_USB_POWER_FAULT)
	gpio_set_as_input (GPIO_USB_POWER_FAULT);	// set as input for USB power fault detection (fixme... bootloader should have done this already)
#endif

	DBG_PRINTK( "NEW SYSCREG_USB_ATX_PLL_PD_REG (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_ATX_PLL_PD_REG, readl(VA_SYSCREG_USB_ATX_PLL_PD_REG) ) ;
	DBG_PRINTK( "SYSCREG_USB_OTG_CFG (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_OTG_CFG, readl(VA_SYSCREG_USB_OTG_CFG)) ;
	DBG_PRINTK( "SYSCREG_USB_OTG_PORT_IND_CTL (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_OTG_PORT_IND_CTL, readl(VA_SYSCREG_USB_OTG_PORT_IND_CTL) );
	DBG_PRINTK( "SYSCREG_USB_TPR_DYN (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_SYS_USB_TPR_DYN, readl(VA_SYSCREG_SYS_USB_TPR_DYN ));
	DBG_PRINTK( "SYSCREG_USB_PLL_NDEC (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_NDEC , readl(VA_SYSCREG_USB_PLL_NDEC)) ;
	DBG_PRINTK( "SYSCREG_USB_PLL_MDEC  (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_MDEC , readl(VA_SYSCREG_USB_PLL_MDEC)) ;
	DBG_PRINTK( "SYSCREG_USB_PLL_PDEC  (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_PDEC , readl(VA_SYSCREG_USB_PLL_PDEC)) ;
	DBG_PRINTK( "SYSCREG_USB_PLL_SELR (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_SELR, readl(VA_SYSCREG_USB_PLL_SELR)) ;
	DBG_PRINTK( "SYSCREG_USB_PLL_SELI (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_SELI, readl(VA_SYSCREG_USB_PLL_SELI)) ;
	DBG_PRINTK( "SYSCREG_USB_PLL_SELP (0x%08X) set to 0x%08X.\n",(unsigned int)VA_SYSCREG_USB_PLL_SELP, readl(VA_SYSCREG_USB_PLL_SELP)) ;

	/* Cleanup */
	iounmap((void*) gcgu_config_regs );
	iounmap((void*) gpusb_otg_regs );

	return 0;
}
static bool ieee80211_resmgr_state_multichan_idle_event(void *ctx, u_int16_t event_type, u_int16_t event_data_len, void *event_data) 
{
    ieee80211_resmgr_t resmgr = (ieee80211_resmgr_t)ctx;
    ieee80211_resmgr_sm_event_t event = (ieee80211_resmgr_sm_event_t)event_data;
    ieee80211_vap_t vap = event->vap;
    ieee80211_resmgr_vap_priv_t resmgr_vap = NULL;
    bool retVal = true;
    struct ieee80211com *ic = resmgr->ic;
    ieee80211_resmgr_oc_scheduler_operation_data_t next_scheduled_operation = {OC_SCHED_OP_NONE, NULL};
    ieee80211_vap_t curr_vap, next_vap;
    bool transition_vap = false;
    bool transition_scan = false;
    bool check_scheduled_operation = false;
    
    if (vap) {
        resmgr_vap = ieee80211vap_get_resmgr(vap);
    }

    switch (event_type) {
    case IEEE80211_RESMGR_EVENT_VAP_START_REQUEST:
    {
        if (!resmgr_vap)
            break;

        ieee80211_resmgr_oc_sched_set_state(resmgr, OC_SCHEDULER_ON);

        /* Turn scheduler on before invoking next routine */
        ieee80211_resmgr_oc_sched_vap_transition(resmgr, vap,
            resmgr_vap, OFF_CHAN_SCHED_VAP_START);
        
        resmgr_vap->state = VAP_STARTING;
        resmgr_vap->chan = event->chan;
        
        DBG_PRINTK("VAP_STARTING:  resmgr_vap->chan = 0x%08x\n", resmgr_vap->chan);
        check_scheduled_operation = true;
        break;
    }

    case IEEE80211_RESMGR_EVENT_VAP_STOPPED:
    {
        struct vap_iter_check_state_params params;

        if (!resmgr_vap)
            break;

        /* Stop associated VAP */
        resmgr_vap->state = VAP_STOPPED;

        ieee80211_resmgr_oc_sched_vap_transition(resmgr, vap, 
            resmgr_vap, OFF_CHAN_SCHED_VAP_STOPPED);
        
        /* Check if any other vaps exist */
        OS_MEMZERO(&params, sizeof(struct vap_iter_check_state_params));
        wlan_iterate_vap_list(ic, ieee80211_vap_iter_check_state, &params);

        if (!params.vaps_running && !params.vap_starting) {
            ieee80211_resmgr_oc_sched_set_state(resmgr, OC_SCHEDULER_OFF); 
        }
        else {          
            check_scheduled_operation = true;
        }
        break;
    }

    case IEEE80211_RESMGR_EVENT_VAP_UP:
    {
        struct vap_iter_unpause_params params = {0, 0};
    
        resmgr_vap->state = VAP_ACTIVE;
    
        ieee80211_resmgr_oc_sched_vap_transition(resmgr, vap, 
            resmgr_vap, OFF_CHAN_SCHED_VAP_UP);
        
        /* Unpause VAP's on same channel */
        params.chan = resmgr_vap->chan;
        if (resmgr->mode == IEEE80211_RESMGR_MODE_MULTI_CHANNEL) {
            wlan_iterate_vap_list(ic, ieee80211_vap_iter_unpause_request, &params);
        } else {
            wlan_iterate_vap_list(ic, ieee80211_vap_iter_resume_request, &params);
        }
    
        break;
    }
        
    case IEEE80211_RESMGR_EVENT_VAP_PAUSE_COMPLETE:
    case IEEE80211_RESMGR_EVENT_VAP_PAUSE_FAIL:
    case IEEE80211_RESMGR_EVENT_VAP_RESUME_COMPLETE:
    case IEEE80211_RESMGR_EVENT_CHAN_SWITCH_REQUEST:
    case IEEE80211_RESMGR_EVENT_CSA_COMPLETE:
    case IEEE80211_RESMGR_EVENT_SCHED_BSS_REQUEST:
        DBG_PRINTK("%s : [*** WARNING ***] Encountered unhandled event_type!!\n", __func__);        
        ASSERT(0);
        break;
        
    case IEEE80211_RESMGR_EVENT_BSSCHAN_REQUEST:
    {
        ieee80211_resmgr_notification notif;

        /* Is Off-Channel Scheduler active? */
        if (ieee80211_resmgr_oc_sched_get_state(resmgr) != OC_SCHEDULER_ON) {       
            /* Set home channel */
            ASSERT(resmgr->scandata.chan); /* scanner should go to foreign first? */
            if (resmgr->scandata.chan)
                ic->ic_curchan = resmgr->scandata.chan;
            ic->ic_set_channel(ic);
        }
        
        resmgr->scandata.chan = NULL;
        resmgr->scandata.scan_chan = NULL;
        
        /* Intimate request completion */
        notif.type = IEEE80211_RESMGR_BSSCHAN_SWITCH_COMPLETE;
        notif.req_id = IEEE80211_RESMGR_REQID;
        notif.status = 0;
        notif.vap = NULL;
        IEEE80211_RESMGR_NOTIFICATION(resmgr, &notif);
        break;
    }

    case IEEE80211_RESMGR_EVENT_OFFCHAN_REQUEST:
    {
        ieee80211_resmgr_notification notif;

        /* Store current channel as home channel */
        resmgr->scandata.chan = ic->ic_curchan;
        resmgr->scandata.scan_chan = event->chan;

        /* Is Off-Channel Scheduler active? */
        if (ieee80211_resmgr_oc_sched_get_state(resmgr) != OC_SCHEDULER_ON) {       
            /* Set desired channel */
            ic->ic_curchan = event->chan;
            ic->ic_scan_start(ic);
            ic->ic_set_channel(ic);

            /* Intimate request completion */
            notif.type = IEEE80211_RESMGR_OFFCHAN_SWITCH_COMPLETE;
            notif.req_id = IEEE80211_RESMGR_REQID;
            notif.status = EOK;
            notif.vap = NULL;
            IEEE80211_RESMGR_NOTIFICATION(resmgr, &notif);
        }
        else {
            DBG_PRINTK("%s : OFFCHAN_REQ - max_dwell_time = %d\n", __func__, event->max_dwell_time);
            ieee80211_resmgr_oc_sched_req_duration_usec_set(resmgr->scandata.oc_sched_req, event->max_dwell_time * 1000);
            ieee80211_resmgr_oc_sched_req_start(resmgr, resmgr->scandata.oc_sched_req);
            
            ieee80211_resmgr_off_chan_scheduler(resmgr, IEEE80211_RESMGR_EVENT_OFF_CHAN_SCHED_START_REQUEST);           
        }
        
        break;
    }

    case IEEE80211_RESMGR_EVENT_TSF_TIMER_EXPIRED:
    case IEEE80211_RESMGR_EVENT_TSF_TIMER_CHANGED:
    case IEEE80211_RESMGR_EVENT_OFF_CHAN_SCHED_START_REQUEST:
    case IEEE80211_RESMGR_EVENT_OFF_CHAN_SCHED_STOP_REQUEST:
        ieee80211_resmgr_off_chan_scheduler(resmgr, event_type);
        check_scheduled_operation = true;
        break;
        
    default:
        retVal = false;
        break;
    }

    if (ieee80211_resmgr_oc_sched_get_state(resmgr) == OC_SCHEDULER_ON) {
        
        if (check_scheduled_operation == true) {
            
            /* Fetch next scheduled operation */
            ieee80211_resmgr_oc_sched_get_scheduled_operation(resmgr, &next_scheduled_operation);

            next_vap = next_scheduled_operation.vap;

            /* Take care of post operation cleanup */
            
            switch (next_scheduled_operation.operation_type) {
                
            case OC_SCHED_OP_VAP:           
                if (resmgr->current_scheduled_operation.operation_type == OC_SCHED_OP_VAP) {
                    curr_vap = resmgr->current_scheduled_operation.vap;
                    resmgr_vap = ieee80211vap_get_resmgr(curr_vap); 
                    
                    if (next_vap != curr_vap) {                     
                        DBG_PRINTK("OP_VAP:  vap_force_pause curr_vap = 0x%08x\n", curr_vap);
                        
                        /* Force pause the currently active VAP */
                        curr_vap->iv_ic->ic_vap_pause_control(curr_vap->iv_ic,curr_vap,true);
                        //ieee80211_sm_transition_to(resmgr->hsm_handle, IEEE80211_RESMGR_STATE_PAUSING);
                        
                        resmgr_vap->state = VAP_PAUSED;
                        transition_vap = true;
                    }
                }
                else {
                    transition_vap = true;
                }
                break;
                
            case OC_SCHED_OP_SCAN:
                transition_scan = true;
                /* Falling through INTENTIONALLY */
            case OC_SCHED_OP_SLEEP:
                if (resmgr->current_scheduled_operation.operation_type == OC_SCHED_OP_VAP) {
                    curr_vap = resmgr->current_scheduled_operation.vap;
                    resmgr_vap = ieee80211vap_get_resmgr(curr_vap); 
                    
                    DBG_PRINTK("OP_SCAN:  vap_force_pause curr_vap = 0x%08x\n", curr_vap);

                    /* Force pause the current VAP */
                    curr_vap->iv_ic->ic_vap_pause_control(curr_vap->iv_ic,curr_vap,true);
                    //ieee80211_sm_transition_to(resmgr->hsm_handle, IEEE80211_RESMGR_STATE_PAUSING);
                    
                    
                    resmgr_vap->state = VAP_PAUSED;
                }           
                break;
                
            case OC_SCHED_OP_NOP:
            case OC_SCHED_OP_NONE:
            default:
                break;
            }

            /* Initiate the next operation */
            if (transition_scan == true) {
                
                DBG_PRINTK("%s : transition_scan == true\n", __func__);
                ieee80211_resmgr_notification notif;
                    
                /* Set desired channel */
                ic->ic_curchan = resmgr->scandata.scan_chan;
                ic->ic_scan_start(ic);
                ic->ic_set_channel(ic);

                /* Intimate request completion */
                notif.type = IEEE80211_RESMGR_OFFCHAN_SWITCH_COMPLETE;
                notif.req_id = IEEE80211_RESMGR_REQID;
                notif.status = EOK;
                notif.vap = NULL;
                IEEE80211_RESMGR_NOTIFICATION(resmgr, &notif);
            }

            if (transition_vap == true) {
                if (next_vap != NULL) {
                    
                    DBG_PRINTK("%s : transition_vap == true\n", __func__);                  
                    resmgr_vap = ieee80211vap_get_resmgr(next_vap);

                    switch (resmgr_vap->state) {
                    case VAP_STARTING:
                        {
                            ieee80211_resmgr_notification notif;
                            struct vap_iter_check_state_params params;
                            
                            /* Check if this is the first VAP starting */
                            OS_MEMZERO(&params, sizeof(struct vap_iter_check_state_params));
                            wlan_iterate_vap_list(ic, ieee80211_vap_iter_check_state, &params);
                            
                            /* Set the requested channel */
                            if (resmgr_vap && (!params.vaps_active || !IS_CHAN_EQUAL(ic->ic_curchan, resmgr_vap->chan))) {
                                ic->ic_curchan = resmgr_vap->chan;
                                ic->ic_bsschan = ic->ic_curchan;
                                ic->ic_set_channel(ic);
                                ieee80211_reset_erp(ic, ic->ic_curmode, next_vap->iv_opmode);
                                ieee80211_wme_initparams(next_vap);
                            }
                            
                            /* Set passed channel as BSS channel */
                            ic->ic_bsschan = ic->ic_curchan;
                            
                            /* Intimate start completion to VAP module */
                            notif.type = IEEE80211_RESMGR_VAP_START_COMPLETE;
                            notif.req_id = IEEE80211_RESMGR_REQID;
                            notif.status = 0;
                            notif.vap = next_vap;
                            IEEE80211_RESMGR_NOTIFICATION(resmgr, &notif);
                        }
                        break;
                        
                    case VAP_PAUSED:
                        DBG_PRINTK("%s : vap_force_unpause; next_vap\n", __func__);
                        
                        next_vap->iv_ic->ic_vap_pause_control(next_vap->iv_ic, next_vap, false);
                        resmgr_vap->state = VAP_ACTIVE;
                        break;
                        
                    default:
                        if (ic->ic_curchan != resmgr_vap->chan) {
                            /* Set home channel */
                            DBG_PRINTK("%s : resmgr_vap->chan = 0x%08x\n", __func__, resmgr_vap->chan);
                            ic->ic_curchan = resmgr_vap->chan;
                            ic->ic_set_channel(ic);
                        }
                        break;
                    }
                }
            }
        }
    }
    
    return retVal;
}
Exemplo n.º 8
0
int start_fx2lp_fw_dl(void) {
    unsigned int volatile sr = 0;
    unsigned int volatile cr = 0;
    unsigned int index = 0;
    unsigned int ret = 0;
    unsigned int offset = 8;
    char __iomem* fw;
    char __iomem* tmp;
    unsigned int fw_address = mot_usb_firmware_address();
    unsigned int fw_size = mot_usb_firmware_size();

    if(!fw_address || !fw_size) {
        printk(KERN_ERR "fx2lp: atag values look invalid\n");
        return 1;
    }

    if(!(fw = ioremap(fw_address, fw_size))) {
        printk(KERN_ERR "fx2lp: unable to relocate memory holding firmware\n");
        return 1;
    }

    DBG_PRINTK("fx2lp: firmware pointer is %p\n", fw);

    /* use this to "reset" our pointer when we get the address */
    tmp = fw;

    /* set up mxc i2c bus */
    writeb((I2C_SLAVE_ADDRESS << 1), I2C_MEMBASE + MXC_IADR);
    writeb(I2C_100KHZ_DIVIDER, I2C_MEMBASE + MXC_IFDR);
    writeb(I2C_CLEAR_STATUS_REG, I2C_MEMBASE + MXC_I2SR);

    gpio_i2c_active(I2C_NUM);
    mxc_clks_enable(I2C_CLK);

    /* slave mode is set by default */
    writeb(MXC_I2CR_IEN, I2C_MEMBASE + MXC_I2CR);

    /* initialize EPIT hardware
     * - set 32K clock source and initial counter value to 0xffffffff */
    writel(EPITCR_CLKSRC_32K | EPITCR_ENMOD, _reg_EPIT_EPITCR);

    next_timeout = EPIT_MAX - (FX2LP_RESET_TIMEOUT / MICROSECONDS_PER_TICK);

    mxc_clks_enable(EPIT1_CLK);

    DBG_PRINTK("fx2lp: reset chip and start download\n");

    gpio_usb_hs_reset_set_data(TURN_CHIP_ON);

    /* start EPIT counter */
    *_reg_EPIT_EPITCR |= EPITCR_EN;

    while(1) {
        sr = readb(I2C_MEMBASE + MXC_I2SR);

        if(MXC_I2SR_IIF & sr) {
            if(MXC_I2SR_IAL & sr) {
                /* arbitration lost? this is a problem */
                printk(KERN_ERR "fx2lp: arbitration lost\n");
                ret = 1;
                break;
            }
            else if(MXC_I2SR_IAAS & sr) {
                DBG_PRINTK("fx2lp: slave address match\n");

                if(MXC_I2SR_SRW & sr) {
                    /* slave write */
                    writeb(I2C_CLEAR_STATUS_REG, I2C_MEMBASE + MXC_I2SR);

                    cr = readb(I2C_MEMBASE + MXC_I2CR);
                    cr |= MXC_I2CR_MTX;
                    writeb(cr, I2C_MEMBASE + MXC_I2CR);

                    DBG_PRINTK("fx2lp:write:0x%02x\n", readb(fw + index));

                    /* initial write is in response to a probe and it doesn't
                       really matter what we write for it */
                    writeb(readb(fw + index++), I2C_MEMBASE + MXC_I2DR);
                    set_next_timeout();
                }
                else {
                    /* slave read */
                    writeb(I2C_CLEAR_STATUS_REG, I2C_MEMBASE + MXC_I2SR);
                    
                    cr = readb(I2C_MEMBASE + MXC_I2CR);
                    cr &= ~MXC_I2CR_MTX;
                    writeb(cr, I2C_MEMBASE + MXC_I2CR);

                    DBG_PRINTK("fx2lp:reading first byte\n");

                    /* the fx2lp sends out 3 bytes...the first byte is a
                       control byte that we don't care about and the last
                       two bytes will contain our address */
                    (void)readb(I2C_MEMBASE + MXC_I2DR);
                    index = 0;
                    set_next_timeout();
                }
            }
            else {
                /* transfer complete interrupt */
                if(index == CONFIG_BYTE_400KHZ) {
                    DBG_PRINTK("fx2lp: switching to 400kbps\n");

                    /* bit 0 in previous byte tells fx2lp to operate at
                       400kbps instead of 100kbps, the bit should be set to 1 */
                    writeb(I2C_400KHZ_DIVIDER, I2C_MEMBASE + MXC_IFDR);
                }

                writeb(I2C_CLEAR_STATUS_REG, I2C_MEMBASE + MXC_I2SR);
                cr = readb(I2C_MEMBASE + MXC_I2CR);

                if(MXC_I2CR_MTX & cr) {
                    /* we're in transmit mode */
                    if(!(MXC_I2SR_RXAK & sr)) {
                        /* ACK received from master */
                        DBG_PRINTK("fx2lp:write:0x%02x\n", readb(fw + index));

                        writeb(readb(fw + index++), I2C_MEMBASE + MXC_I2DR);
                        set_next_timeout();
                    }
                    else {
                        DBG_PRINTK("fx2lp: NACK received from master\n");

                        /* give up i2c bus */
                        cr = readb(I2C_MEMBASE + MXC_I2CR);
                        cr &= ~MXC_I2CR_MTX;
                        writeb(cr, I2C_MEMBASE + MXC_I2CR);
                        (void)readb(I2C_MEMBASE + MXC_I2DR);

                        set_next_timeout();

                        /* index can be 1 after the probe so we need to check
                           for a size greater than 1...when firmware download is
                           complete the fx2lp will send a STOP */
                        if(index > 1) {
                            /* last byte has been transferred */
                            DBG_PRINTK("fx2lp: wait for STOP\n");

                            do {
                                sr = readb(I2C_MEMBASE + MXC_I2SR);
                            } while ((MXC_I2SR_IBB & sr) &&
                                    (next_timeout <= *_reg_EPIT_EPITCNR));

                            if(!(MXC_I2SR_IBB & sr)) {
                                DBG_PRINTK("fx2lp: got the STOP\n");
                            }
                            else {
                                printk(KERN_ERR "fx2lp: i2c STOP timed out\n");
                                ret = 1;
                            }

                            break;
                        }
                    }
                }
                else {
                    /* in receive mode */
                    /* the SCM-A11 is considered a two-byte addressable
                       eeprom on the bus, grab the two bytes of address */
                    index |= (readb(I2C_MEMBASE + MXC_I2DR) << offset);

                    if(!offset) {
                        fw = tmp + index;
                        DBG_PRINTK("fx2lp: index set to %0x\n", index);
                    }

                    /* update offset so we grab the next byte correctly */
                    offset = 0;
                    set_next_timeout();
                }
            }
        }
        else if(next_timeout >= *_reg_EPIT_EPITCNR) {
            if(index ? printk(KERN_ERR "fx2lp: i2c transfer timed out\n") :
                       printk(KERN_ERR "fx2lp: chip reset timed out\n"));

            ret = 1;
            break;
        }
    }

    mxc_clks_disable(EPIT1_CLK);
    mxc_clks_disable(I2C_CLK);
    gpio_i2c_inactive(I2C_NUM);

    if(ret) {
        /* if firmware download didn't work then put the fx2lp back in reset */
        gpio_usb_hs_reset_set_data(TURN_CHIP_OFF);
    }

    iounmap(fw);

    return ret;
}