/*
 * This file is part of wl1271
 *
 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
 * Copyright (C) 2008-2010 Nokia Corporation
 *
 * Contact: Luciano Coelho <luciano.coelho@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.
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

#ifndef __IO_H__
#define __IO_H__

#include <linux/irqreturn.h>

#define HW_ACCESS_MEMORY_MAX_RANGE	0x1FFC0

#define HW_PARTITION_REGISTERS_ADDR     0x1FFC0
#define HW_PART0_SIZE_ADDR              (HW_PARTITION_REGISTERS_ADDR)
#define HW_PART0_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 4)
#define HW_PART1_SIZE_ADDR              (HW_PARTITION_REGISTERS_ADDR + 8)
#define HW_PART1_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 12)
#define HW_PART2_SIZE_ADDR              (HW_PARTITION_REGISTERS_ADDR + 16)
#define HW_PART2_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 20)
#define HW_PART3_START_ADDR             (HW_PARTITION_REGISTERS_ADDR + 24)

#define HW_ACCESS_REGISTER_SIZE         4

#define HW_ACCESS_PRAM_MAX_RANGE	0x3c000

struct wl1271;

void wlcore_disable_interrupts(struct wl1271 *wl);
void wlcore_disable_interrupts_nosync(struct wl1271 *wl);
void wlcore_enable_interrupts(struct wl1271 *wl);
void wlcore_synchronize_interrupts(struct wl1271 *wl);

void wl1271_io_reset(struct wl1271 *wl);
void wl1271_io_init(struct wl1271 *wl);
int wlcore_translate_addr(struct wl1271 *wl, int addr);

/* Raw target IO, address is not translated */
static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr,
						void *buf, size_t len,
						bool fixed)
{
	int ret;

	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
		return -EIO;

	ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed);
	if (ret && wl->state != WLCORE_STATE_OFF)
		set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);

	return ret;
}

static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr,
					       void *buf, size_t len,
					       bool fixed)
{
	int ret;

	if (test_bit(WL1271_FLAG_IO_FAILED, &wl->flags))
		return -EIO;

	ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed);
	if (ret && wl->state != WLCORE_STATE_OFF)
		set_bit(WL1271_FLAG_IO_FAILED, &wl->flags);

	return ret;
}

static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg,
						    void *buf, size_t len,
						    bool fixed)
{
	return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed);
}

static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg,
						     void *buf, size_t len,
						     bool fixed)
{
	return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed);
}

static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr,
						 u32 *val)
{
	int ret;

	ret = wlcore_raw_read(wl, addr, wl->buffer_32,
			      sizeof(*wl->buffer_32), false);
	if (ret < 0)
		return ret;

	if (val)
		*val = le32_to_cpu(*wl->buffer_32);

	return 0;
}

static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr,
						  u32 val)
{
	*wl->buffer_32 = cpu_to_le32(val);
	return wlcore_raw_write(wl, addr, wl->buffer_32,
				sizeof(*wl->buffer_32), false);
}

static inline int __must_check wlcore_read(struct wl1271 *wl, int addr,
					   void *buf, size_t len, bool fixed)
{
	int physical;

	physical = wlcore_translate_addr(wl, addr);

	return wlcore_raw_read(wl, physical, buf, len, fixed);
}

static inline int __must_check wlcore_write(struct wl1271 *wl, int addr,
					    void *buf, size_t len, bool fixed)
{
	int physical;

	physical = wlcore_translate_addr(wl, addr);

	return wlcore_raw_write(wl, physical, buf, len, fixed);
}

static inline int __must_check wlcore_write_data(struct wl1271 *wl, int reg,
						 void *buf, size_t len,
						 bool fixed)
{
	return wlcore_write(wl, wl->rtable[reg], buf, len, fixed);
}

static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg,
						void *buf, size_t len,
						bool fixed)
{
	return wlcore_read(wl, wl->rtable[reg], buf, len, fixed);
}

static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr,
						  void *buf, size_t len,
						  bool fixed)
{
	int physical;
	int addr;

	/* Convert from FW internal address which is chip arch dependent */
	addr = wl->ops->convert_hwaddr(wl, hwaddr);

	physical = wlcore_translate_addr(wl, addr);

	return wlcore_raw_read(wl, physical, buf, len, fixed);
}

static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr,
					     u32 *val)
{
	return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val);
}

static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr,
					      u32 val)
{
	return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val);
}

static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg,
					       u32 *val)
{
	return wlcore_raw_read32(wl,
				 wlcore_translate_addr(wl, wl->rtable[reg]),
				 val);
}

static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
						u32 val)
{
	return wlcore_raw_write32(wl,
				  wlcore_translate_addr(wl, wl->rtable[reg]),
				  val);
}

static inline void wl1271_power_off(struct wl1271 *wl)
{
	int ret;

	if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
		return;

	ret = wl->if_ops->power(wl->dev, false);
	if (!ret)
		clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}

static inline int wl1271_power_on(struct wl1271 *wl)
{
	int ret = wl->if_ops->power(wl->dev, true);
	if (ret == 0)
		set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);

	return ret;
}

int wlcore_set_partition(struct wl1271 *wl,
			 const struct wlcore_partition_set *p);

bool wl1271_set_block_size(struct wl1271 *wl);

/* Functions from wl1271_main.c */

int wl1271_tx_dummy_packet(struct wl1271 *wl);

#endif
