/*! * 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; }
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; }
/*! * 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); }
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; }
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; }
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(¶ms, sizeof(struct vap_iter_check_state_params)); wlan_iterate_vap_list(ic, ieee80211_vap_iter_check_state, ¶ms); 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, ¶ms); } else { wlan_iterate_vap_list(ic, ieee80211_vap_iter_resume_request, ¶ms); } 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, ¬if); 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, ¬if); } 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, ¬if); } 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(¶ms, sizeof(struct vap_iter_check_state_params)); wlan_iterate_vap_list(ic, ieee80211_vap_iter_check_state, ¶ms); /* 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, ¬if); } 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; }
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; }