blob: 825a1a07a815f3aa3cae8f13f17e22409076ec89 [file] [log] [blame]
/** @file bt_drv.h
* @brief This header file contains global constant/enum definitions,
* global variable declaration.
*
* Copyright (C) 2007-2008, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available along with the File in the gpl.txt file or by writing to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*
*/
#ifndef _BT_DRV_H_
#define _BT_DRV_H_
#ifndef BIT
/** BIT definition */
#define BIT(x) (1UL << (x))
#endif
/** Debug level : Message */
#define DBG_MSG BIT(0)
/** Debug level : Fatal */
#define DBG_FATAL BIT(1)
/** Debug level : Error */
#define DBG_ERROR BIT(2)
/** Debug level : Command */
#define DBG_CMD BIT(3)
/** Debug level : Data */
#define DBG_DATA BIT(27)
/** Debug level : Entry */
#define DBG_ENTRY BIT(28)
/** Debug level : Warning */
#define DBG_WARN BIT(29)
/** Debug level : Informative */
#define DBG_INFO BIT(30)
#ifdef DEBUG_LEVEL1
extern u32 drvdbg;
/** Print informative message */
#define PRINTM_INFO(msg...) do {if (drvdbg & DBG_INFO) printk(KERN_DEBUG msg);} while(0)
/** Print warning message */
#define PRINTM_WARN(msg...) do {if (drvdbg & DBG_WARN) printk(KERN_DEBUG msg);} while(0)
/** Print entry message */
#define PRINTM_ENTRY(msg...) do {if (drvdbg & DBG_ENTRY) printk(KERN_DEBUG msg);} while(0)
/** Print command message */
#define PRINTM_CMD(msg...) do {if (drvdbg & DBG_CMD) printk(KERN_DEBUG msg);} while(0)
/** Print erro message */
#define PRINTM_ERROR(msg...) do {if (drvdbg & DBG_ERROR) printk(KERN_DEBUG msg);} while(0)
/** Print fatal message */
#define PRINTM_FATAL(msg...) do {if (drvdbg & DBG_FATAL) printk(KERN_DEBUG msg);} while(0)
/** Print message */
#define PRINTM_MSG(msg...) do {if (drvdbg & DBG_MSG) printk(KERN_ALERT msg);} while(0)
/** Print message with required level */
#define PRINTM(level,msg...) PRINTM_##level(msg)
/** Debug dump buffer length */
#define DBG_DUMP_BUF_LEN 64
/** Maximum number of dump per line */
#define MAX_DUMP_PER_LINE 16
/** Maximum data dump length */
#define MAX_DATA_DUMP_LEN 48
static inline void
hexdump(char *prompt, u8 * buf, int len)
{
int i;
char dbgdumpbuf[DBG_DUMP_BUF_LEN];
char *ptr = dbgdumpbuf;
printk(KERN_DEBUG "%s: len=%d\n", prompt, len);
for (i = 1; i <= len; i++) {
ptr += sprintf(ptr, "%02x ", *buf);
buf++;
if (i % MAX_DUMP_PER_LINE == 0) {
*ptr = 0;
printk(KERN_DEBUG "%s\n", dbgdumpbuf);
ptr = dbgdumpbuf;
}
}
if (len % MAX_DUMP_PER_LINE) {
*ptr = 0;
printk(KERN_DEBUG "%s\n", dbgdumpbuf);
}
}
/** Debug hexdump of debug data */
#define DBG_HEXDUMP_DBG_DATA(x,y,z) do {if (drvdbg & DBG_DATA) hexdump(x,y,z);} while(0)
/** Debug hexdump */
#define DBG_HEXDUMP(level,x,y,z) DBG_HEXDUMP_##level(x,y,z)
/** Mark entry point */
#define ENTER() PRINTM(ENTRY, "Enter: %s, %s:%i\n", __FUNCTION__, \
__FILE__, __LINE__)
/** Mark exit point */
#define LEAVE() PRINTM(ENTRY, "Leave: %s, %s:%i\n", __FUNCTION__, \
__FILE__, __LINE__)
#else
/** Do nothing */
#define PRINTM(level,msg...) do {} while (0);
/** Do nothing */
#define DBG_HEXDUMP(level,x,y,z) do {} while (0);
/** Do nothing */
#define ENTER() do {} while (0);
/** Do nothing */
#define LEAVE() do {} while (0);
#endif /* DEBUG_LEVEL1 */
/** Length of device name */
#define DEV_NAME_LEN 32
/** Bluetooth upload size */
#define BT_UPLD_SIZE 2312
/** Bluetooth status success */
#define BT_STATUS_SUCCESS (0)
/** Bluetooth status failure */
#define BT_STATUS_FAILURE (-1)
#ifndef TRUE
/** True value */
#define TRUE 1
#endif
#ifndef FALSE
/** False value */
#define FALSE 0
#endif
/** Set thread state */
#define OS_SET_THREAD_STATE(x) set_current_state(x)
/** Time to wait until Host Sleep state change in millisecond */
#define WAIT_UNTIL_HS_STATE_CHANGED 5000
/** Time to wait cmd resp in millisecond */
#define WAIT_UNTIL_CMD_RESP 5000
/** Sleep until a condition gets true or a timeout elapses */
#define os_wait_interruptible_timeout(waitq, cond, timeout) \
wait_event_interruptible_timeout(waitq, cond, ((timeout) * HZ / 1000))
typedef struct
{
/** Task */
struct task_struct *task;
/** Queue */
wait_queue_head_t waitQ;
/** PID */
pid_t pid;
/** Private structure */
void *priv;
} bt_thread;
static inline void
bt_activate_thread(bt_thread * thr)
{
/** Record the thread pid */
thr->pid = current->pid;
/** Initialize the wait queue */
init_waitqueue_head(&thr->waitQ);
}
static inline void
bt_deactivate_thread(bt_thread * thr)
{
thr->pid = 0;
return;
}
static inline void
bt_create_thread(int (*btfunc) (void *), bt_thread * thr, char *name)
{
thr->task = kthread_run(btfunc, thr, "%s", name);
}
static inline int
bt_terminate_thread(bt_thread * thr)
{
/* Check if the thread is active or not */
if (!thr->pid)
return -1;
kthread_stop(thr->task);
return 0;
}
static inline void
os_sched_timeout(u32 millisec)
{
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout((millisec * HZ) / 1000);
}
#ifndef __ATTRIB_ALIGN__
#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
#endif
#ifndef __ATTRIB_PACK__
#define __ATTRIB_PACK__ __attribute__ ((packed))
#endif
/** Data structure for the Marvell Bluetooth device */
typedef struct _bt_dev
{
/** device name */
char name[DEV_NAME_LEN];
/** card pointer */
void *card;
/** IO port */
u32 ioport;
/** HCI device */
struct hci_dev *hcidev;
/** Tx download ready flag */
u8 tx_dnld_rdy;
/** Function */
u8 fn;
/** Rx unit */
u8 rx_unit;
/** Power Save mode */
u8 psmode;
/** Power Save command */
u8 pscmd;
/** Host Sleep mode */
u8 hsmode;
/** Host Sleep command */
u8 hscmd;
/** Low byte is gap, high byte is GPIO */
u16 gpio_gap;
/** Host Sleep configuration command */
u8 hscfgcmd;
/** Host Send Cmd Flag */
u8 sendcmdflag;
/** Device Type */
u8 devType;
} bt_dev_t, *pbt_dev_t;
typedef struct _bt_adapter
{
/** Chip revision ID */
u8 chip_rev;
/** Surprise removed flag */
u8 SurpriseRemoved;
/** IRQ number */
int irq;
/** Interrupt counter */
u32 IntCounter;
/** Tx packet queue */
struct sk_buff_head tx_queue;
/** Power Save mode */
u8 psmode;
/** Power Save state */
u8 ps_state;
/** Host Sleep state */
u8 hs_state;
/** Number of wakeup tries */
u8 WakeupTries;
/** Host Sleep wait queue */
wait_queue_head_t cmd_wait_q __ATTRIB_ALIGN__;
/** Host Cmd complet state */
u8 cmd_complete;
/** last irq recv */
u8 irq_recv;
/** last irq processed */
u8 irq_done;
/** tx pending */
u32 skb_pending;
} bt_adapter, *pbt_adapter;
/** Private structure for the MV device */
typedef struct _bt_private
{
/** Bluetooth device */
bt_dev_t bt_dev;
/** Adapter */
bt_adapter *adapter;
/** Firmware helper */
const struct firmware *fw_helper;
/** Firmware */
const struct firmware *firmware;
/** Hotplug device */
struct device *hotplug_device;
/** thread to service interrupts */
bt_thread MainThread;
/** Proc directory entry */
struct proc_dir_entry *proc_entry;
/** Proc mbt directory entry */
struct proc_dir_entry *proc_mbt;
/** Driver lock */
spinlock_t driver_lock;
/** Driver lock flags */
ulong driver_flags;
} bt_private, *pbt_private;
/** Disable interrupt */
#define OS_INT_DISABLE spin_lock_irqsave(&priv->driver_lock, priv->driver_flags)
/** Enable interrupt */
#define OS_INT_RESTORE spin_unlock_irqrestore(&priv->driver_lock, priv->driver_flags); \
priv->driver_lock = SPIN_LOCK_UNLOCKED
/** BT_AMP flag for device type */
#define HCI_BT_AMP 0x80
/** Device type of AMP */
#define DEV_TYPE_AMP 0x01
/** Marvell vendor packet */
#define MRVL_VENDOR_PKT 0xFE
/** Bluetooth command : Sleep mode */
#define BT_CMD_AUTO_SLEEP_MODE 0x23
/** Bluetooth command : Host Sleep configuration */
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
/** Bluetooth command : Host Sleep enable */
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
/** Bluetooth command : Module Configuration request */
#define BT_CMD_MODULE_CFG_REQ 0x5B
/** Sub Command: Module Bring Up Request */
#define MODULE_BRINGUP_REQ 0xF1
/** Sub Command: Module Shut Down Request */
#define MODULE_SHUTDOWN_REQ 0xF2
/** Module already up */
#define MODULE_CFG_RESP_ALREADY_UP 0x0c
/** Sub Command: Host Interface Control Request */
#define MODULE_INTERFACE_CTRL_REQ 0xF5
/** Bluetooth event : Power State */
#define BT_EVENT_POWER_STATE 0x20
/** Bluetooth Power State : Enable */
#define BT_PS_ENABLE 0x02
/** Bluetooth Power State : Disable */
#define BT_PS_DISABLE 0x03
/** Bluetooth Power State : Sleep */
#define BT_PS_SLEEP 0x01
/** Bluetooth Power State : Awake */
#define BT_PS_AWAKE 0x02
/** OGF */
#define OGF 0x3F
/** Host Sleep activated */
#define HS_ACTIVATED 0x01
/** Host Sleep deactivated */
#define HS_DEACTIVATED 0x00
/** Power Save sleep */
#define PS_SLEEP 0x01
/** Power Save awake */
#define PS_AWAKE 0x00
/** bt header length */
#define BT_HEADER_LEN 4
#ifndef MAX
/** Return maximum of two */
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
/** This is for firmware specific length */
#define EXTRA_LEN 36
/** Command buffer size for Marvell driver */
#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
/** Bluetooth Rx packet buffer size for Marvell driver */
#define MRVDRV_BT_RX_PACKET_BUFFER_SIZE \
(HCI_MAX_FRAME_SIZE + EXTRA_LEN)
/** Buffer size to allocate */
#define ALLOC_BUF_SIZE (((MAX(MRVDRV_BT_RX_PACKET_BUFFER_SIZE, \
MRVDRV_SIZE_OF_CMD_BUFFER) + SDIO_HEADER_LEN \
+ SD_BLOCK_SIZE - 1) / SD_BLOCK_SIZE) * SD_BLOCK_SIZE)
/** The number of times to try when polling for status bits */
#define MAX_POLL_TRIES 100
/** The number of times to try when waiting for downloaded firmware to
become active when multiple interface is present */
#define MAX_MULTI_INTERFACE_POLL_TRIES 1000
/** The number of times to try when waiting for downloaded firmware to
become active. (polling the scratch register). */
#define MAX_FIRMWARE_POLL_TRIES 100
typedef struct _BT_CMD
{
/** OCF OGF */
u16 ocf_ogf;
/** Length */
u8 length;
/** Data */
u8 data[4];
} __ATTRIB_PACK__ BT_CMD;
typedef struct _BT_EVENT
{
/** Event Counter */
u8 EC;
/** Length */
u8 length;
/** Data */
u8 data[4];
} BT_EVENT;
void check_evtpkt(bt_private * priv, struct sk_buff *skb);
/* Prototype of global function */
bt_private *bt_add_card(void *card);
int bt_remove_card(void *card);
void bt_interrupt(struct hci_dev *hdev);
int bt_proc_init(bt_private * priv);
void bt_proc_remove(bt_private * priv);
int bt_process_event(bt_private * priv, struct sk_buff *skb);
int bt_enable_hs(bt_private * priv);
int bt_prepare_command(bt_private * priv);
int *sbi_register(void);
void sbi_unregister(void);
int sbi_register_dev(bt_private * priv);
int sbi_unregister_dev(bt_private * priv);
int sbi_host_to_card(bt_private * priv, u8 * payload, u16 nb);
int sbi_enable_host_int(bt_private * priv);
int sbi_disable_host_int(bt_private * priv);
int sbi_dowload_fw(bt_private * priv);
int sbi_get_int_status(bt_private * priv, u8 * ireg);
int sbi_wakeup_firmware(bt_private * priv);
#endif /* _BT_DRV_H_ */