📄 sm_drv_spi.c
字号:
int i, callb_mask; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); if(prism_softmac_describe(&lp->sm_descr, lp->sm_initdata) != SM_ENONE) { printk(KERN_ERR "%s: Fatal Error: LMAC - UMAC incomptability\n", DRIVER_NAME ); return; } setup.mode = lp->sm_mode; setup.rx_align = 0; setup.max_sta = DEV_MAX_STA; setup.max_bss = DEV_MAX_BSS; setup.mtu = lp->sm_descr.mtu; get_random_bytes(&rand, sizeof(unsigned long)); setup.seed = rand; for(i = 0; i < 8; i++) setup.depth[i] = 0; /* allocate a memory region for the UMAC context */ lp->sm_context = (uint32_t *)kmalloc(lp->sm_descr.context_size, GFP_ATOMIC); if(!lp->sm_context) { printk(KERN_ERR "%s: Fatal Error: UMAC Context Memory could not be allocated\n", DRIVER_NAME); return; } DEBUG(DBG_CALLS, "sm_drv_spi_initialize: Mode %d\n", setup.mode); callb_mask = prism_softmac_create(lp->sm_context, &setup, lp->sm_pda, lp->sm_initdata); if(callb_mask < 0) { printk(KERN_ERR "%s: Fatal Error: could not create SoftMAC (%d)\n", DRIVER_NAME, callb_mask); lp->sm_descr.mtu = 0; } /* We can now free the PDA */ kfree(lp->sm_pda); lp->sm_initialization = 1;}static void sm_drv_spi_reset_device(struct net_device * dev, unsigned boot){ unsigned short dev_reg; /* We do the ROM boot */ if (boot) dev_reg = SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | SPI_CTRL_STAT_RAM_BOOT; else dev_reg = SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | SPI_CTRL_STAT_START_HALTED; sm_spi_write(dev, SPI_ADRS_DEV_CTRL_STAT, (unsigned char *)&dev_reg, sizeof(dev_reg)); msleep(30); if (boot) dev_reg = SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT; else dev_reg = SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_START_HALTED; sm_spi_write(dev, SPI_ADRS_DEV_CTRL_STAT, (unsigned char *)&dev_reg, sizeof(dev_reg)); msleep(30);}int sm_drv_fetch_firmware(struct net_device *ndev, char *fw_id, struct device * dev){ struct net_local *lp = ndev->priv; const struct firmware *fw_entry = 0; int ret = 0; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); ret = request_firmware(&fw_entry, fw_id, dev); if (ret) { printk(KERN_ERR "sm_drv_fetch_firmware failed (err: %d) for '%s' \n", ret, fw_id); return ret; } lp->fw_len = fw_entry->size; lp->fw_ptr = (uint8_t *)kmalloc(lp->fw_len, GFP_ATOMIC); if (!lp->fw_ptr) { printk("Couldn't allocate fw\n"); ret = -1; goto out; } memcpy(lp->fw_ptr, fw_entry->data, lp->fw_len); DEBUG(DBG_CALLS, "sm_drv_fetch_firmware: file %s (%d bytes)\n", fw_id, fw_entry->size); if (lp->fw_len % 4) { printk(KERN_ERR "firmware '%s' size is not multiple of 32bit, aborting!\n", fw_id); ret = -EILSEQ; /* Illegal byte sequence */; goto err_out; } /* add offset 20 to point to the bra directly */ ret = prism_softmac_parse_bra(lp->fw_ptr + 20, lp->sm_initdata); if(ret != SM_ENONE) { printk(KERN_WARNING "%s firmware(%s) image does not contain LMAC description %d\n", DRIVER_NAME, fw_id, ret); ret = -1; goto err_out; } out: /* Firmware version is at offset 40 */ memcpy(wlan_fw_version, fw_entry->data + 40, 16); wlan_fw_version[16] = '\0'; printk("%s: firmware version: %s\n", DRIVER_NAME, wlan_fw_version); release_firmware(fw_entry); return ret; err_out: kfree(lp->fw_ptr); lp->fw_len = 0; release_firmware(fw_entry); return ret; }void sm_drv_release_firmware(struct net_device *ndev){ struct net_local *lp = ndev->priv; if (lp->fw_ptr) kfree(lp->fw_ptr); lp->fw_len = 0;}int sm_drv_spi_upload_firmware(struct net_device *dev){ struct net_local *lp = dev->priv; struct spi_hif_local_data *hif_lp = HIF_LP(lp); struct s_dma_regs dma_regs; unsigned long fw_len, address = FIRMWARE_ADDRESS; uint32_t host_reg; uint8_t * fw_buffer; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); fw_len = lp->fw_len; fw_buffer = lp->fw_ptr; if (lp->fw_len == 0) return -1; HIF_CLK_USE(hif_lp); /* Stop device */ sm_drv_spi_reset_device(dev, 0); while (fw_len > 0) { long _fw_len = (fw_len > SPI_MAX_PACKET_SIZE) ? SPI_MAX_PACKET_SIZE : fw_len; dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE; dma_regs.len = cpu_to_le16(_fw_len); dma_regs.addr = cpu_to_le32(address); fw_len -= _fw_len; address += _fw_len; sm_spi_write(dev, SPI_ADRS_DMA_WRITE_CTRL, (unsigned char *)(&dma_regs.cmd), sizeof(short)); if (wlan_wait_bit(dev, SPI_ADRS_DMA_WRITE_CTRL, HOST_ALLOWED, HOST_ALLOWED) == 0) { printk("fw_upload: Not allowed to DMA write\n"); cx3110x_dump_register(dev); HIF_CLK_UNUSE(hif_lp); return -EAGAIN; } sm_spi_write(dev, SPI_ADRS_DMA_WRITE_LEN, (unsigned char *)(&dma_regs.len), sizeof(short)); sm_spi_write(dev, SPI_ADRS_DMA_WRITE_BASE, (unsigned char *)(&dma_regs.addr), sizeof(long)); sm_spi_dma_write(dev, SPI_ADRS_DMA_DATA, fw_buffer, _fw_len); } BUG_ON(fw_len != 0); /* Enable host interrupts */ host_reg = SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE; sm_spi_write(dev, SPI_ADRS_HOST_INT_EN, (unsigned char *)&host_reg, sizeof host_reg ); /* Boot device */ sm_drv_spi_reset_device(dev, 1); HIF_CLK_UNUSE(hif_lp); DEBUG(DBG_CALLS, "Upload firmware done\n"); return 0;}extern pda_record_t sm_drv_pda[];static struct wlan_pda_add_regulatory_limits_channel_s wlan_pda_add_regulatory_limits[4] ={ { .frequency = 2412, .regulatory_domain = 0x10, .country_code = {0x0, 0x0, 0x0}, .modulation = 0x1f, .power_limit = 68, }, { .frequency = 2412, .regulatory_domain = 0x30, .country_code = {0x0, 0x0, 0x0}, .modulation = 0x1f, .power_limit = 68, }, { .frequency = 2462, .regulatory_domain = 0x10, .country_code = {0x0, 0x0, 0x0}, .modulation = 0x1f, .power_limit = 68, }, { .frequency = 2472, .regulatory_domain = 0x01, .country_code = {0x0, 0x0, 0x0}, .modulation = 0x1f, .power_limit = 68, },};struct s_pda * sm_drv_spi_get_pda(struct device *dev){ struct s_pda * pda; const unsigned char * default_pda; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); if (driver_type == SM_DRIVER_TYPE_UMAC) default_pda = umac_pda; else default_pda = mtum_pda; /* We first build the pda_record array */ sm_drv_pda_init(sm_drv_pda, (uint8_t *)default_pda, sizeof(default_pda)); /* Now we can replace any PDR we want */ if (wlan_pda_mac_address.mac_addr[0] != 0xff) sm_drv_pda_replace_pdr(sm_drv_pda, PDR_MAC_ADDRESS, wlan_pda_mac_address.mac_addr, sizeof(wlan_pda_mac_address.mac_addr)); if (wlan_pda_iq) sm_drv_pda_replace_pdr(sm_drv_pda, PDR_PRISM_ZIF_TX_IQ_CALIBRATION, (uint8_t *)wlan_pda_iq, NUM_CHANNELS * sizeof(struct wlan_pda_iq_autocal_s)); if (wlan_pda_pa_curve_data) sm_drv_pda_replace_pdr(sm_drv_pda, PDR_PRISM_PA_CAL_CURVE_DATA, (uint8_t *)wlan_pda_pa_curve_data, sizeof(struct wlan_pda_pa_curve_data_s)); if (wlan_pda_output_limits) sm_drv_pda_replace_pdr(sm_drv_pda, PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS, (uint8_t *)wlan_pda_output_limits, sizeof(struct wlan_pda_output_limit_s)); if (wlan_pda_rssi) { sm_drv_pda_replace_pdr(sm_drv_pda, PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED, (uint8_t *)wlan_pda_rssi, sizeof(struct wlan_pda_rssi_cal_s)); } if (wlan_pda_default_country) sm_drv_pda_replace_pdr(sm_drv_pda, PDR_DEFAULT_COUNTRY, (uint8_t *)wlan_pda_default_country, sizeof(struct wlan_pda_default_country_s)); sm_drv_pda_replace_pdr(sm_drv_pda, PDR_REGULATORY_POWER_LIMITS, (uint8_t *)wlan_pda_add_regulatory_limits, sizeof(wlan_pda_add_regulatory_limits)); /* Then we get the s_pda from the pda_record array */ pda = sm_drv_pda_get_pda(sm_drv_pda); return pda;}static irqreturn_t sm_drv_spi_interrupt(int irq, void *config, struct pt_regs *regs){ struct net_device *dev = config; struct net_local *lp = dev->priv; if(lp->device_state == DEVSTATE_ACTIVE || lp->device_state == DEVSTATE_BOOTING) tasklet_hi_schedule(&lp->tasklet); return IRQ_HANDLED;}int sm_drv_spi_request_irq(struct net_device *dev){ struct net_local *lp = dev->priv; struct spi_hif_local_data *hif_lp = HIF_LP(lp); int rval; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); HIF_CLK_USE(hif_lp); /* Install interrupt handler */ rval = cx3110x_request_irq(sm_drv_spi_interrupt, DRIVER_NAME, (void*)dev); if (rval < 0) return rval; HIF_CLK_UNUSE(hif_lp); return 0;}void sm_drv_spi_free_irq( struct net_device *dev ){ DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); cx3110x_free_irq((void *)dev);}struct sm_drv_firmware_file { u8 chip_type; u8* name; /* Chip's manufacturer name */ u8* lm; /* LMAC name */ u8* mtlm; /* MTLM name */} firmware_array [] = { {0x21, "STLC4370", "3825.arm", "mtlm3825.arm"}, /* STLC4370, aka gen2.1 */ {0x25, "STLC4550", "3826.arm", "mtlm3826.arm"}, /* STLC4550, aka gen2.5 */ {0x0, "Unknown" , "3825.arm", "mtlm3825.arm"}, /* Default to STLC4370 */};static u8 * sm_drv_firmware_name(u8 chip_type, unsigned int driver_type){ int i = 0; while (firmware_array[i].chip_type) { if (firmware_array[i].chip_type == chip_type) { printk("CX3110x chip variant: %s\n", firmware_array[i].name); if (driver_type == SM_DRIVER_TYPE_UMAC) return firmware_array[i].lm; else return firmware_array[i].mtlm; } i++; } return NULL; }#define N770_WLAN_CS_GPIO 21#define N770_WLAN_POWER_GPIO 59#define N770_WLAN_IRQ_GPIO 36static struct net_device *sm_drv_spi_probe(void){ struct net_local *lp; struct net_device * dev = NULL; struct spi_hif_local_data *spi_lp = NULL; const struct omap_wlan_cx3110x_config * cx3110x_wlan_config; DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); /* Create the Network device instance that will interface with the kernel Network stack */ dev = sm_drv_netdev_create(0,0); if (!dev) { printk(KERN_ERR "Cannot allocate network device"); return NULL; } /* Register platform device and create sysfs files */ if(sm_drv_register_platform(dev)) { cx3110x_spi_stop(dev); return NULL; } if (driver_register(&wlan_omap_driver)) goto err_out_1; sm_drv_sysfs_create_files(); lp = dev->priv; spi_lp = HIF_LP(lp); spi_lp = (struct spi_hif_local_data *)kzalloc(sizeof(struct spi_hif_local_data), GFP_KERNEL); if (!spi_lp) { printk(KERN_ERR "Cannot allocate SPI local data"); goto err_out_2; } spi_lp->netdev = dev; wlan_config = kzalloc(sizeof(struct omap_wlan_cx3110x_config), GFP_KERNEL); if (wlan_config == NULL) return NULL; cx3110x_wlan_config = omap_get_config(OMAP_TAG_WLAN_CX3110X, struct omap_wlan_cx3110x_config); /* With some old N770 bootloaders, the chip type s not set */ if (cx3110x_wlan_config == NULL || ((cx3110x_wlan_config->chip_type != 0x21) && (cx3110x_wlan_config->chip_type != 0x25))) { wlan_config->chip_type = 0x21; wlan_config->power_gpio = N770_WLAN_POWER_GPIO; wlan_config->irq_gpio = N770_WLAN_IRQ_GPIO; wlan_config->spi_cs_gpio = N770_WLAN_CS_GPIO; } else { memcpy(wlan_config, cx3110x_wlan_config, sizeof(struct omap_wlan_cx3110x_config)); } /* McBSP2 clock is ARM_PER */ HIF_CLK(spi_lp) = clk_get(NULL, "armper_ck"); BUG_ON(HIF_CLK(spi_lp) == NULL); /* Instantiate the Host Interface specific handlers */ lp->hif_up = &sm_drv_spi_up; lp->hif_down = &sm_drv_spi_down; lp->hif_cli = &sm_drv_spi_cli; lp->hif_local_data = spi_lp; /* point back to SPI local data */ spin_lock_init(&spi_lp->lock); /* Initialise initial packet count */ spi_lp->initial_packets = 0; spi_lp->spi_packets = 0; /* Init our Bottom halve handler */ tasklet_init(&lp->tasklet, sm_drv_spi_tasklet_action, (unsigned long)dev); /* Init the wireless stats queue */ INIT_WORK(&lp->stats_work, sm_drv_update_stats, dev); lp->stats_timestamp = 0; /* Init the WPA IE list */ INIT_LIST_HEAD(&lp->bss_wpa_list); sema_init(&lp->wpa_sem, 1); /* Initial mode is CLIENT */ lp->sm_mode = SM_MODE_CLIENT; /* 802.11 initial state */ lp->link_state = DOT11_STATE_NONE; /* No SSID */ memset(&lp->ssid, 0, sizeof(struct obj_ssid)); /* Init the tuning values */ wlan_pda_mac_address.mac_addr[0] = 0xff; wlan_pda_iq = NULL; wlan_pda_output_limits = NULL; wlan_pda_pa_curve_data = NULL; wlan_pda_rssi = NULL; /* Default country is EU if this is NULL */ wlan_pda_default_country = NULL; lp->sm_initdata = (struct s_sm_initdata *) kmalloc(sizeof(struct s_sm_initdata), GFP_KERNEL ); if(!lp->sm_initdata) { printk(KERN_ERR "Cannot allocate SPI initdata"); goto err_out_4; } register_netdev(dev); /* Let's fetch the firmware from userspace */ firmware_file = sm_drv_firmware_name(wlan_config->chip_type, driver_type); if (firmware_file == NULL) goto err_out_4; if (sm_drv_fetch_firmware(dev, firmware_file, &(wlan_omap_device.dev)) < 0) goto err_out_4; return dev; err_out_4: kfree(spi_lp); kfree(wlan_config); err_out_2: driver_unregister(&wlan_omap_driver); err_out_1: platform_device_unregister(&wlan_omap_device); return NULL;}static void sm_drv_spi_unprobe(struct net_device *dev){ DEBUG(DBG_CALLS, "%s\n", __FUNCTION__); driver_unregister(&wlan_omap_driver); sm_drv_unregister_platform(); unregister_netdev(dev); sm_drv_wpa_ie_clean(dev); sm_drv_release_firmware(dev); kfree(wlan_config);}/****************************************************************************** * Module Init ******************************************************************************/static int __init sm_drv_spi_init_module(void){ sm_net_device = sm_drv_spi_probe(); if (!sm_net_device) { printk(KERN_WARNING "Could not register SoftMAC SPI Driver\n"); return -ENODEV; } printk("Loaded %s driver, version %s\n", DRIVER_NAME, VERSIONID); return 0;}static void __exit sm_drv_spi_cleanup_module( void ){ sm_drv_spi_unprobe(sm_net_device); printk("Unloaded %s driver, version %s\n", DRIVER_NAME, VERSIONID);}MODULE_LICENSE("GPL v2");module_init(sm_drv_spi_init_module);module_exit(sm_drv_spi_cleanup_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -