/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2003 Atheros Communications, Inc.,  All Rights Reserved.
 * Copyright (C) 2006 FON Technology, SL.
 * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org>
 * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org>
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/irq_cpu.h>
#include <asm/reboot.h>
#include <asm/bootinfo.h>
#include <asm/time.h>

#include <ath25_platform.h>
#include "devices.h"
#include "ar5312.h"
#include "ar2315.h"

void (*ath25_irq_dispatch)(void);

static inline bool check_radio_magic(const void __iomem *addr)
{
	addr += 0x7a; /* offset for flash magic */
	return (__raw_readb(addr) == 0x5a) && (__raw_readb(addr + 1) == 0xa5);
}

static inline bool check_notempty(const void __iomem *addr)
{
	return __raw_readl(addr) != 0xffffffff;
}

static inline bool check_board_data(const void __iomem *addr, bool broken)
{
	/* config magic found */
	if (__raw_readl(addr) == ATH25_BD_MAGIC)
		return true;

	if (!broken)
		return false;

	/* broken board data detected, use radio data to find the
	 * offset, user will fix this */

	if (check_radio_magic(addr + 0x1000))
		return true;
	if (check_radio_magic(addr + 0xf8))
		return true;

	return false;
}

static const void __iomem * __init find_board_config(const void __iomem *limit,
						     const bool broken)
{
	const void __iomem *addr;
	const void __iomem *begin = limit - 0x1000;
	const void __iomem *end = limit - 0x30000;

	for (addr = begin; addr >= end; addr -= 0x1000)
		if (check_board_data(addr, broken))
			return addr;

	return NULL;
}

static const void __iomem * __init find_radio_config(const void __iomem *limit,
						     const void __iomem *bcfg)
{
	const void __iomem *rcfg, *begin, *end;

	/*
	 * Now find the start of Radio Configuration data, using heuristics:
	 * Search forward from Board Configuration data by 0x1000 bytes
	 * at a time until we find non-0xffffffff.
	 */
	begin = bcfg + 0x1000;
	end = limit;
	for (rcfg = begin; rcfg < end; rcfg += 0x1000)
		if (check_notempty(rcfg) && check_radio_magic(rcfg))
			return rcfg;

	/* AR2316 relocates radio config to new location */
	begin = bcfg + 0xf8;
	end = limit - 0x1000 + 0xf8;
	for (rcfg = begin; rcfg < end; rcfg += 0x1000)
		if (check_notempty(rcfg) && check_radio_magic(rcfg))
			return rcfg;

	return NULL;
}

/*
 * NB: Search region size could be larger than the actual flash size,
 * but this shouldn't be a problem here, because the flash
 * will simply be mapped multiple times.
 */
int __init ath25_find_config(phys_addr_t base, unsigned long size)
{
	const void __iomem *flash_base, *flash_limit;
	struct ath25_boarddata *config;
	unsigned int rcfg_size;
	int broken_boarddata = 0;
	const void __iomem *bcfg, *rcfg;
	u8 *board_data;
	u8 *radio_data;
	u8 *mac_addr;
	u32 offset;

	flash_base = ioremap(base, size);
	flash_limit = flash_base + size;

	ath25_board.config = NULL;
	ath25_board.radio = NULL;

	/* Copy the board and radio data to RAM, because accessing the mapped
	 * memory of the flash directly after booting is not safe */

	/* Try to find valid board and radio data */
	bcfg = find_board_config(flash_limit, false);

	/* If that fails, try to at least find valid radio data */
	if (!bcfg) {
		bcfg = find_board_config(flash_limit, true);
		broken_boarddata = 1;
	}

	if (!bcfg) {
		pr_warn("WARNING: No board configuration data found!\n");
		goto error;
	}

	board_data = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL);
	if (!board_data)
		goto error;
	ath25_board.config = (struct ath25_boarddata *)board_data;
	memcpy_fromio(board_data, bcfg, 0x100);
	if (broken_boarddata) {
		pr_warn("WARNING: broken board data detected\n");
		config = ath25_board.config;
		if (is_zero_ether_addr(config->enet0_mac)) {
			pr_info("Fixing up empty mac addresses\n");
			config->reset_config_gpio = 0xffff;
			config->sys_led_gpio = 0xffff;
			eth_random_addr(config->wlan0_mac);
			config->wlan0_mac[0] &= ~0x06;
			eth_random_addr(config->enet0_mac);
			eth_random_addr(config->enet1_mac);
		}
	}

	/* Radio config starts 0x100 bytes after board config, regardless
	 * of what the physical layout on the flash chip looks like */

	rcfg = find_radio_config(flash_limit, bcfg);
	if (!rcfg) {
		pr_warn("WARNING: Could not find Radio Configuration data\n");
		goto error;
	}

	radio_data = board_data + 0x100 + ((rcfg - bcfg) & 0xfff);
	ath25_board.radio = radio_data;
	offset = radio_data - board_data;
	pr_info("Radio config found at offset 0x%x (0x%x)\n", rcfg - bcfg,
		offset);
	rcfg_size = BOARD_CONFIG_BUFSZ - offset;
	memcpy_fromio(radio_data, rcfg, rcfg_size);

	mac_addr = &radio_data[0x1d * 2];
	if (is_broadcast_ether_addr(mac_addr)) {
		pr_info("Radio MAC is blank; using board-data\n");
		ether_addr_copy(mac_addr, ath25_board.config->wlan0_mac);
	}

	iounmap(flash_base);

	return 0;

error:
	iounmap(flash_base);
	return -ENODEV;
}

static void ath25_halt(void)
{
	local_irq_disable();
	unreachable();
}

void __init plat_mem_setup(void)
{
	_machine_halt = ath25_halt;
	pm_power_off = ath25_halt;

	if (is_ar5312())
		ar5312_plat_mem_setup();
	else
		ar2315_plat_mem_setup();

	/* Disable data watchpoints */
	write_c0_watchlo0(0);
}

asmlinkage void plat_irq_dispatch(void)
{
	ath25_irq_dispatch();
}

void __init plat_time_init(void)
{
	if (is_ar5312())
		ar5312_plat_time_init();
	else
		ar2315_plat_time_init();
}

unsigned int get_c0_compare_int(void)
{
	return CP0_LEGACY_COMPARE_IRQ;
}

void __init arch_init_irq(void)
{
	clear_c0_status(ST0_IM);
	mips_cpu_irq_init();

	/* Initialize interrupt controllers */
	if (is_ar5312())
		ar5312_arch_init_irq();
	else
		ar2315_arch_init_irq();
}
