summaryrefslogblamecommitdiffstats
path: root/drivers/staging/wilc1000/linux_wlan_spi.c
blob: 039d06192d6b1af853e97207a1a11ccb642cb828 (plain) (tree)
1
2
3
4
5
6
7
8






                         
                          



                              
                           



























                                                
                             
 
                                















                                                                  










































                                                                            












                                                         
                            
 
                                   

                
 




                                                      
                                                                      

                                       





                                                                            




                                                               
 











                                                                             







                                                                      




                                                   












                                                                                                    
                                













                                                                                                           
                                   







                                          



                                          
                                                          

                                       
 































                                                                                                           
                            
 
                                    








                                                       
                                                                      

                                       




                                                          























                                                                             





                                                                       













                                                                                                    
                                
                
                                                                                  








                                                         
                                    






                                          





                                          
                                                           

                                       
 















                                                             
                                                                                  









                                                         
                                                  


























                                                             
                                                                                  














                                                                                      
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>
#include <linux/spi/spi.h>

#include "linux_wlan_common.h"
#include "linux_wlan_spi.h"

#define USE_SPI_DMA     0       /* johnny add */

#ifdef WILC_ASIC_A0
 #if defined(PLAT_PANDA_ES_OMAP4460)
  #define MIN_SPEED 12000000
  #define MAX_SPEED 24000000
 #elif defined(PLAT_WMS8304)
  #define MIN_SPEED 12000000
  #define MAX_SPEED 24000000 /* 4000000 */
 #elif defined(CUSTOMER_PLATFORM)
/*
  TODO : define Clock speed under 48M.
 *
 * ex)
 * #define MIN_SPEED 24000000
 * #define MAX_SPEED 48000000
 */
 #else
  #define MIN_SPEED 24000000
  #define MAX_SPEED 48000000
 #endif
#else /* WILC_ASIC_A0 */
/* Limit clk to 6MHz on FPGA. */
 #define MIN_SPEED 6000000
 #define MAX_SPEED 6000000
#endif /* WILC_ASIC_A0 */

static u32 SPEED = MIN_SPEED;

struct spi_device *wilc_spi_dev;
void linux_spi_deinit(void *vp);

static int __init wilc_bus_probe(struct spi_device *spi)
{

	PRINT_D(BUS_DBG, "spiModalias: %s\n", spi->modalias);
	PRINT_D(BUS_DBG, "spiMax-Speed: %d\n", spi->max_speed_hz);
	wilc_spi_dev = spi;

	printk("Driver Initializing success\n");
	return 0;
}

static int __exit wilc_bus_remove(struct spi_device *spi)
{

	return 0;
}

#ifdef CONFIG_OF
static const struct of_device_id wilc1000_of_match[] = {
	{ .compatible = "atmel,wilc_spi", },
	{}
};
MODULE_DEVICE_TABLE(of, wilc1000_of_match);
#endif

struct spi_driver wilc_bus __refdata = {
	.driver = {
		.name = MODALIAS,
#ifdef CONFIG_OF
		.of_match_table = wilc1000_of_match,
#endif
	},
	.probe =  wilc_bus_probe,
	.remove = __exit_p(wilc_bus_remove),
};


void linux_spi_deinit(void *vp)
{

	spi_unregister_driver(&wilc_bus);

	SPEED = MIN_SPEED;
	PRINT_ER("@@@@@@@@@@@@ restore SPI speed to %d @@@@@@@@@\n", SPEED);

}



int linux_spi_init(void *vp)
{
	int ret = 1;
	static int called;


	if (called == 0) {
		called++;
		ret = spi_register_driver(&wilc_bus);
	}

	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);

	return ret;
}

#if defined(PLAT_WMS8304)
#define TXRX_PHASE_SIZE (4096)
#endif

#if defined(TXRX_PHASE_SIZE)

int linux_spi_write(u8 *b, u32 len)
{
	int ret;

	if (len > 0 && b != NULL) {
		int i = 0;
		int blk = len / TXRX_PHASE_SIZE;
		int remainder = len % TXRX_PHASE_SIZE;

		char *r_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
		if (!r_buffer)
			return -ENOMEM;

		if (blk) {
			while (i < blk)	{
				struct spi_message msg;
				struct spi_transfer tr = {
					.tx_buf = b + (i * TXRX_PHASE_SIZE),
					.len = TXRX_PHASE_SIZE,
					.speed_hz = SPEED,
					.bits_per_word = 8,
					.delay_usecs = 0,
				};

				tr.rx_buf = r_buffer;

				memset(&msg, 0, sizeof(msg));
				spi_message_init(&msg);
				msg.spi = wilc_spi_dev;
				msg.is_dma_mapped = USE_SPI_DMA;

				spi_message_add_tail(&tr, &msg);
				ret = spi_sync(wilc_spi_dev, &msg);
				if (ret < 0) {
					PRINT_ER("SPI transaction failed\n");
				}
				i++;

			}
		}
		if (remainder) {
			struct spi_message msg;
			struct spi_transfer tr = {
				.tx_buf = b + (blk * TXRX_PHASE_SIZE),
				.len = remainder,
				.speed_hz = SPEED,
				.bits_per_word = 8,
				.delay_usecs = 0,
			};
			tr.rx_buf = r_buffer;

			memset(&msg, 0, sizeof(msg));
			spi_message_init(&msg);
			msg.spi = wilc_spi_dev;
			msg.is_dma_mapped = USE_SPI_DMA;                                /* rachel */

			spi_message_add_tail(&tr, &msg);
			ret = spi_sync(wilc_spi_dev, &msg);
			if (ret < 0) {
				PRINT_ER("SPI transaction failed\n");
			}
		}
		kfree(r_buffer);
	} else {
		PRINT_ER("can't write data with the following length: %d\n", len);
		PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len);
		ret = -1;
	}

	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);

	return ret;

}

#else
int linux_spi_write(u8 *b, u32 len)
{

	int ret;
	struct spi_message msg;

	if (len > 0 && b != NULL) {
		struct spi_transfer tr = {
			.tx_buf = b,
			.len = len,
			.speed_hz = SPEED,
			.delay_usecs = 0,
		};
		char *r_buffer = kzalloc(len, GFP_KERNEL);
		if (!r_buffer)
			return -ENOMEM;

		tr.rx_buf = r_buffer;
		PRINT_D(BUS_DBG, "Request writing %d bytes\n", len);

		memset(&msg, 0, sizeof(msg));
		spi_message_init(&msg);
/* [[johnny add */
		msg.spi = wilc_spi_dev;
		msg.is_dma_mapped = USE_SPI_DMA;
/* ]] */
		spi_message_add_tail(&tr, &msg);

		ret = spi_sync(wilc_spi_dev, &msg);
		if (ret < 0) {
			PRINT_ER("SPI transaction failed\n");
		}

		kfree(r_buffer);
	} else {
		PRINT_ER("can't write data with the following length: %d\n", len);
		PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len);
		ret = -1;
	}

	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);


	return ret;
}

#endif

#if defined(TXRX_PHASE_SIZE)

int linux_spi_read(u8 *rb, u32 rlen)
{
	int ret;

	if (rlen > 0) {
		int i = 0;

		int blk = rlen / TXRX_PHASE_SIZE;
		int remainder = rlen % TXRX_PHASE_SIZE;

		char *t_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL);
		if (!t_buffer)
			return -ENOMEM;

		if (blk) {
			while (i < blk)	{
				struct spi_message msg;
				struct spi_transfer tr = {
					.rx_buf = rb + (i * TXRX_PHASE_SIZE),
					.len = TXRX_PHASE_SIZE,
					.speed_hz = SPEED,
					.bits_per_word = 8,
					.delay_usecs = 0,
				};
				tr.tx_buf = t_buffer;

				memset(&msg, 0, sizeof(msg));
				spi_message_init(&msg);
				msg.spi = wilc_spi_dev;
				msg.is_dma_mapped = USE_SPI_DMA;

				spi_message_add_tail(&tr, &msg);
				ret = spi_sync(wilc_spi_dev, &msg);
				if (ret < 0) {
					PRINT_ER("SPI transaction failed\n");
				}
				i++;
			}
		}
		if (remainder) {
			struct spi_message msg;
			struct spi_transfer tr = {
				.rx_buf = rb + (blk * TXRX_PHASE_SIZE),
				.len = remainder,
				.speed_hz = SPEED,
				.bits_per_word = 8,
				.delay_usecs = 0,
			};
			tr.tx_buf = t_buffer;

			memset(&msg, 0, sizeof(msg));
			spi_message_init(&msg);
			msg.spi = wilc_spi_dev;
			msg.is_dma_mapped = USE_SPI_DMA;                                /* rachel */

			spi_message_add_tail(&tr, &msg);
			ret = spi_sync(wilc_spi_dev, &msg);
			if (ret < 0) {
				PRINT_ER("SPI transaction failed\n");
			}
		}

		kfree(t_buffer);
	} else {
		PRINT_ER("can't read data with the following length: %u\n", rlen);
		ret = -1;
	}
	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);

	return ret;
}

#else
int linux_spi_read(u8 *rb, u32 rlen)
{

	int ret;

	if (rlen > 0) {
		struct spi_message msg;
		struct spi_transfer tr = {
			.rx_buf = rb,
			.len = rlen,
			.speed_hz = SPEED,
			.delay_usecs = 0,

		};
		char *t_buffer = kzalloc(rlen, GFP_KERNEL);
		if (!t_buffer)
			return -ENOMEM;

		tr.tx_buf = t_buffer;

		memset(&msg, 0, sizeof(msg));
		spi_message_init(&msg);
/* [[ johnny add */
		msg.spi = wilc_spi_dev;
		msg.is_dma_mapped = USE_SPI_DMA;
/* ]] */
		spi_message_add_tail(&tr, &msg);

		ret = spi_sync(wilc_spi_dev, &msg);
		if (ret < 0) {
			PRINT_ER("SPI transaction failed\n");
		}
		kfree(t_buffer);
	} else {
		PRINT_ER("can't read data with the following length: %u\n", rlen);
		ret = -1;
	}
	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);

	return ret;
}

#endif

int linux_spi_write_read(u8 *wb, u8 *rb, u32 rlen)
{

	int ret;

	if (rlen > 0) {
		struct spi_message msg;
		struct spi_transfer tr = {
			.rx_buf = rb,
			.tx_buf = wb,
			.len = rlen,
			.speed_hz = SPEED,
			.bits_per_word = 8,
			.delay_usecs = 0,

		};

		memset(&msg, 0, sizeof(msg));
		spi_message_init(&msg);
		msg.spi = wilc_spi_dev;
		msg.is_dma_mapped = USE_SPI_DMA;

		spi_message_add_tail(&tr, &msg);
		ret = spi_sync(wilc_spi_dev, &msg);
		if (ret < 0) {
			PRINT_ER("SPI transaction failed\n");
		}
	} else {
		PRINT_ER("can't read data with the following length: %u\n", rlen);
		ret = -1;
	}
	/* change return value to match WILC interface */
	(ret < 0) ? (ret = 0) : (ret = 1);

	return ret;
}

int linux_spi_set_max_speed(void)
{
	SPEED = MAX_SPEED;

	PRINT_INFO(BUS_DBG, "@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED);
	return 1;
}