⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_drv_spi.c

📁 cx3110 drivers for linux 2.6 (基于SPI)
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -