/*
 * linux/net/driver/wireless/cx3110x/sm_drv_spi.h
 *
 * Copyright (C) 2003 Conexant Americas Inc. All Rights Reserved.
 * Copyright (C) 2004, 2005 Nokia Corporation
 * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */
#ifndef _SM_DRV_SPI_H
#define _SM_DRV_SPI_H

/*
 * INCLUDES
 */
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <asm/io.h>
#include <asm/arch/board.h> /* omap_get_config etc */

#include "islspi_io.h"

/*
 * FUNCTION PROTOTYPES
 */

/*
 * DEFINES
 */

#define SPI_ADRS_ARM_INTERRUPTS     0x00
#define SPI_ADRS_ARM_INT_EN	    0x04

#define SPI_ADRS_HOST_INTERRUPTS    0x08
#define SPI_ADRS_HOST_INT_EN	    0x0c
#define SPI_ADRS_HOST_INT_ACK	    0x10

#define SPI_ADRS_GEN_PURP_1   	    0x14
#define SPI_ADRS_GEN_PURP_2   	    0x18

#define SPI_ADRS_DEV_CTRL_STAT      0x26    // high word

#define SPI_ADRS_DMA_DATA      	    0x28

#define SPI_ADRS_DMA_WRITE_CTRL     0x2c
#define SPI_ADRS_DMA_WRITE_LEN      0x2e
#define SPI_ADRS_DMA_WRITE_BASE     0x30

#define SPI_ADRS_DMA_READ_CTRL      0x34
#define SPI_ADRS_DMA_READ_LEN       0x36
#define SPI_ADRS_DMA_READ_BASE      0x38

#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000
#define SPI_CTRL_STAT_START_HALTED  0x4000
#define SPI_CTRL_STAT_RAM_BOOT      0x2000
#define SPI_CTRL_STAT_HOST_RESET    0x1000
#define SPI_CTRL_STAT_HOST_CPU_EN   0x0800

#define SPI_DMA_WRITE_CTRL_ENABLE   0x0001
#define SPI_DMA_READ_CTRL_ENABLE    0x0001
#define HOST_ALLOWED                (1 << 7)

#define UMAC_FIRMWARE_FILE                      "3825.arm"
#define MTUM_FIRMWARE_FILE                      "mtlm3825.arm"

#define FIRMWARE_ADDRESS                        0x20000

#define SPI_TIMEOUT                             100         /* msec */

#define SPI_MAX_RX_PACKETS                      32
#define SPI_MAX_TX_PACKETS                      32

#define SPI_MAX_PACKET_SIZE                     32767

#define SPI_TARGET_INT_WAKEUP                   0x00000001
#define SPI_TARGET_INT_SLEEP                    0x00000002
#define SPI_TARGET_INT_RDDONE                   0x00000004

#define SPI_TARGET_INT_CTS                      0x00004000
#define SPI_TARGET_INT_DR                       0x00008000

#define SPI_HOST_INT_READY                      0x00000001
#define SPI_HOST_INT_SW_UPDATE                  0x00000004
#define SPI_HOST_INT_UPDATE                     0x10000000

#define SPI_HOST_INT_CTS			0x00004000	// clear to send
#define SPI_HOST_INT_DR				0x00008000	// data ready

#define SPI_HOST_INTS_DEFAULT                   SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE


#define UPLOAD_STATE_BOOTING                    0
#define UPLOAD_STATE_RUNNING                    1

/*
 * Structure definitions
 */

struct s_dma_regs{
	unsigned short cmd;
	unsigned short len;
	unsigned long addr;
};

struct s_txinfo {
	uint32_t p;
	uint32_t c;
	uint32_t f;
	/* in islsm the skb contains everything */
	struct sk_buff *txdata[SPI_MAX_TX_PACKETS];
};

#define SPI_DELAY_THRESHOLD 6
struct spi_hif_local_data {
	spinlock_t lock;                           /* lock */
	struct net_device *netdev;

	/* Basically RX and TX queues. only the TX queue is used */
	/* TODO: replace this with a simple skb_queue */
	struct s_txinfo txinfo;                    /* TX info */

	const struct omap_wlan_config * nokia_wlan_config;
	struct clk *mcbsp2_ck;
	uint32_t fast_mode;

	uint32_t upload_state;
	uint32_t max_packet_size;
	uint32_t initial_packets;
	uint32_t spi_packets;

	struct timer_list spi_timer;          /* SPI timer */

	/* from lp data structure */
	uint32_t                  device_state;           /* Powersave/Active */
	uint32_t                  link_state;             /* Assciated
							   * or not */
	struct tasklet_struct     tasklet;	          /* Our bottom
							   * halve (BH)
							   * handler */
	struct work_struct        stats_work;             /* Wireless stats work queue */
	unsigned long             stats_timestamp;        /* Last stats update */
};

#define HIF_LP(__lp)    ((struct spi_hif_local_data *)__lp->hif_local_data)
#define HIF_CLK(hif_data) (hif_data)->mcbsp2_ck
#define HIF_CLK_USE(hif_data) clk_use((hif_data)->mcbsp2_ck)
#define HIF_CLK_UNUSE(hif_data) clk_unuse((hif_data)->mcbsp2_ck)

#define HIF_OF_ISLSM(islsm) ((struct spi_hif_local_data *) islsm->priv)
#define HIF_OF_NETDEV(ndev) ((struct spi_hif_local_data *) islsm_priv(ndev))

/* struct s_pda * sm_drv_spi_get_pda(struct device *dev); */
/* int sm_drv_spi_request_irq( struct net_device *dev ); */
/* void sm_drv_spi_free_irq( struct net_device *dev ); */

/******************************************************************************
 *   Queue Support Functions
 ******************************************************************************/
/* Get txdata struct at the produce pointer */
static inline void txdata_get_p(struct spi_hif_local_data *hif_lp,
				struct sk_buff **txdata)
{
	struct s_txinfo *txinfo;

	txinfo = &(hif_lp->txinfo);
	*txdata = txinfo->txdata[txinfo->p & (SPI_MAX_RX_PACKETS - 1)];
}

/* Set txdata struct at the produce pointer */
static inline void txdata_set_p(struct spi_hif_local_data *hif_lp,
				struct sk_buff *txdata)
{
	struct s_txinfo *txinfo;

	txinfo = &(hif_lp->txinfo);
	txinfo->txdata[txinfo->p & (SPI_MAX_RX_PACKETS - 1)] = txdata;
}

/* Get txdata struct at the consume pointer */
static inline void txdata_get_c(struct spi_hif_local_data *hif_lp,
				struct sk_buff **txdata)
{
	struct s_txinfo *txinfo;

	txinfo = &(hif_lp->txinfo);
	*txdata = txinfo->txdata[txinfo->c & (SPI_MAX_RX_PACKETS - 1)];
}

/* Increase TX produce pointer */
static inline void tx_produce(struct spi_hif_local_data *hif_lp)
{
	hif_lp->txinfo.p++;
}

/* Increase TX consume pointer */
static inline void tx_consume(struct spi_hif_local_data *hif_lp)
{
	hif_lp->txinfo.c++;
}

/* Returns number of TX frames that can be produced */
static inline int tx_pspace(struct spi_hif_local_data *hif_lp)
{
	struct s_txinfo *txinfo;
	int space;
	unsigned long flags;

	txinfo = &(hif_lp->txinfo);

	spin_lock_irqsave(&hif_lp->lock, flags);
	space = SPI_MAX_TX_PACKETS - (txinfo->p - txinfo->c);
	spin_unlock_irqrestore(&hif_lp->lock, flags);

	return space;
}

/* Returns number of TX frames that can be consumed */
static inline int tx_cspace(struct spi_hif_local_data *hif_lp)
{
	struct s_txinfo *txinfo;
	int space;
	unsigned long flags;

	txinfo = &(hif_lp->txinfo);

	spin_lock_irqsave(&hif_lp->lock, flags);
	space = (txinfo->p - txinfo->c);
	spin_unlock_irqrestore(&hif_lp->lock, flags);

	return space;
}

#endif /* _SM_DRV_SPI_H */
