/*
 * Wireless Host Controller (WHC) WUSB operations.
 *
 * Copyright (C) 2007 Cambridge Silicon Radio Ltd.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/uwb/umc.h>
#define D_LOCAL 1
#include <linux/uwb/debug.h>

#include "../../wusbcore/wusbhc.h"

#include "whcd.h"

#if D_LOCAL >= 1
static void dump_di(struct whc *whc, int idx)
{
	struct di_buf_entry *di = &whc->di_buf[idx];
	struct device *dev = &whc->umc->dev;
	char buf[128];

	bitmap_scnprintf(buf, sizeof(buf), (unsigned long *)di->availability_info, UWB_NUM_MAS);

	d_printf(1, dev, "DI[%d]\n", idx);
	d_printf(1, dev, "  availability: %s\n", buf);
	d_printf(1, dev, "  %c%c key idx: %d dev addr: %d\n",
		 (di->addr_sec_info & WHC_DI_SECURE) ? 'S' : ' ',
		 (di->addr_sec_info & WHC_DI_DISABLE) ? 'D' : ' ',
		 (di->addr_sec_info & WHC_DI_KEY_IDX_MASK) >> 8,
		 (di->addr_sec_info & WHC_DI_DEV_ADDR_MASK));
}
#else
static inline void dump_di(struct whc *whc, int idx)
{
}
#endif

static int whc_update_di(struct whc *whc, int idx)
{
	int offset = idx / 32;
	u32 bit = 1 << (idx % 32);

	dump_di(whc, idx);

	le_writel(bit, whc->base + WUSBDIBUPDATED + offset);

	return whci_wait_for(&whc->umc->dev,
			     whc->base + WUSBDIBUPDATED + offset, bit, 0,
			     100, "DI update");
}

/*
 * WHCI starts and stops MMCs based on there being a valid GTK so
 * these need only start/stop the asynchronous and periodic schedules.
 */

int whc_wusbhc_start(struct wusbhc *wusbhc)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);

	asl_start(whc);
	pzl_start(whc);

	return 0;
}

void whc_wusbhc_stop(struct wusbhc *wusbhc)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);

	pzl_stop(whc);
	asl_stop(whc);
}

int whc_mmcie_add(struct wusbhc *wusbhc, u8 interval, u8 repeat_cnt,
		  u8 handle, struct wuie_hdr *wuie)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	u32 params;

	params = (interval << 24)
		| (repeat_cnt << 16)
		| (wuie->bLength << 8)
		| handle;

	return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_ADD, params, wuie, wuie->bLength);
}

int whc_mmcie_rm(struct wusbhc *wusbhc, u8 handle)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	u32 params;

	params = handle;

	return whc_do_gencmd(whc, WUSBGENCMDSTS_MMCIE_RM, params, NULL, 0);
}

int whc_bwa_set(struct wusbhc *wusbhc, s8 stream_index, const struct uwb_mas_bm *mas_bm)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);

	if (stream_index >= 0)
		whc_write_wusbcmd(whc, WUSBCMD_WUSBSI_MASK, WUSBCMD_WUSBSI(stream_index));

	return whc_do_gencmd(whc, WUSBGENCMDSTS_SET_MAS, 0, (void *)mas_bm, sizeof(*mas_bm));
}

int whc_dev_info_set(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	int idx = wusb_dev->port_idx;
	struct di_buf_entry *di = &whc->di_buf[idx];
	int ret;

	mutex_lock(&whc->mutex);

	uwb_mas_bm_copy_le(di->availability_info, &wusb_dev->availability);
	di->addr_sec_info &= ~(WHC_DI_DISABLE | WHC_DI_DEV_ADDR_MASK);
	di->addr_sec_info |= WHC_DI_DEV_ADDR(wusb_dev->addr);

	ret = whc_update_di(whc, idx);

	mutex_unlock(&whc->mutex);

	return ret;
}

/*
 * Set the number of Device Notification Time Slots (DNTS) and enable
 * device notifications.
 */
int whc_set_num_dnts(struct wusbhc *wusbhc, u8 interval, u8 slots)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	u32 dntsctrl;

	dntsctrl = WUSBDNTSCTRL_ACTIVE
		| WUSBDNTSCTRL_INTERVAL(interval)
		| WUSBDNTSCTRL_SLOTS(slots);

	le_writel(dntsctrl, whc->base + WUSBDNTSCTRL);

	return 0;
}

static int whc_set_key(struct whc *whc, u8 key_index, uint32_t tkid,
		       const void *key, size_t key_size, bool is_gtk)
{
	uint32_t setkeycmd;
	uint32_t seckey[4];
	int i;
	int ret;

	memcpy(seckey, key, key_size);
	setkeycmd = WUSBSETSECKEYCMD_SET | WUSBSETSECKEYCMD_IDX(key_index);
	if (is_gtk)
		setkeycmd |= WUSBSETSECKEYCMD_GTK;

	le_writel(tkid, whc->base + WUSBTKID);
	for (i = 0; i < 4; i++)
		le_writel(seckey[i], whc->base + WUSBSECKEY + 4*i);
	le_writel(setkeycmd, whc->base + WUSBSETSECKEYCMD);

	ret = whci_wait_for(&whc->umc->dev, whc->base + WUSBSETSECKEYCMD,
			    WUSBSETSECKEYCMD_SET, 0, 100, "set key");

	return ret;
}

/**
 * whc_set_ptk - set the PTK to use for a device.
 *
 * The index into the key table for this PTK is the same as the
 * device's port index.
 */
int whc_set_ptk(struct wusbhc *wusbhc, u8 port_idx, u32 tkid,
		const void *ptk, size_t key_size)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	struct di_buf_entry *di = &whc->di_buf[port_idx];
	int ret;

	mutex_lock(&whc->mutex);

	if (ptk) {
		ret = whc_set_key(whc, port_idx, tkid, ptk, key_size, false);
		if (ret)
			goto out;

		di->addr_sec_info &= ~WHC_DI_KEY_IDX_MASK;
		di->addr_sec_info |= WHC_DI_SECURE | WHC_DI_KEY_IDX(port_idx);
	} else
		di->addr_sec_info &= ~WHC_DI_SECURE;

	ret = whc_update_di(whc, port_idx);
out:
	mutex_unlock(&whc->mutex);
	return ret;
}

/**
 * whc_set_gtk - set the GTK for subsequent broadcast packets
 *
 * The GTK is stored in the last entry in the key table (the previous
 * N_DEVICES entries are for the per-device PTKs).
 */
int whc_set_gtk(struct wusbhc *wusbhc, u32 tkid,
		const void *gtk, size_t key_size)
{
	struct whc *whc = wusbhc_to_whc(wusbhc);
	int ret;

	mutex_lock(&whc->mutex);

	ret = whc_set_key(whc, whc->n_devices, tkid, gtk, key_size, true);

	mutex_unlock(&whc->mutex);

	return ret;
}

int whc_set_cluster_id(struct whc *whc, u8 bcid)
{
	whc_write_wusbcmd(whc, WUSBCMD_BCID_MASK, WUSBCMD_BCID(bcid));
	return 0;
}
