/*
 * Copyright (c) 2015 Qualcomm Atheros, Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <linux/hw_random.h>
#include <linux/kthread.h>

#include "ath9k.h"
#include "hw.h"
#include "ar9003_phy.h"

static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
{
	int i, j;
	u32  v1, v2, rng_last = sc->rng_last;
	struct ath_hw *ah = sc->sc_ah;

	ath9k_ps_wakeup(sc);

	REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
	REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
	REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);

	for (i = 0, j = 0; i < buf_size; i++) {
		v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;
		v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;

		/* wait for data ready */
		if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff &&
		    v2 != 0xffff)
			buf[j++] = (v1 << 16) | v2;

		rng_last = v2;
	}

	ath9k_ps_restore(sc);

	sc->rng_last = rng_last;

	return j << 2;
}

static u32 ath9k_rng_delay_get(u32 fail_stats)
{
	u32 delay;

	if (fail_stats < 100)
		delay = 10;
	else if (fail_stats < 105)
		delay = 1000;
	else
		delay = 10000;

	return delay;
}

static int ath9k_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
{
	struct ath_softc *sc = container_of(rng, struct ath_softc, rng_ops);
	u32 fail_stats = 0, word;
	int bytes_read = 0;

	for (;;) {
		if (max & ~3UL)
			bytes_read = ath9k_rng_data_read(sc, buf, max >> 2);
		if ((max & 3UL) && ath9k_rng_data_read(sc, &word, 1)) {
			memcpy(buf + bytes_read, &word, max & 3UL);
			bytes_read += max & 3UL;
			memzero_explicit(&word, sizeof(word));
		}
		if (!wait || !max || likely(bytes_read) || fail_stats > 110)
			break;

		msleep_interruptible(ath9k_rng_delay_get(++fail_stats));
	}

	if (wait && !bytes_read && max)
		bytes_read = -EIO;
	return bytes_read;
}

void ath9k_rng_start(struct ath_softc *sc)
{
	static atomic_t serial = ATOMIC_INIT(0);
	struct ath_hw *ah = sc->sc_ah;

	if (sc->rng_ops.read)
		return;

	if (!AR_SREV_9300_20_OR_LATER(ah))
		return;

	snprintf(sc->rng_name, sizeof(sc->rng_name), "ath9k_%u",
		 (atomic_inc_return(&serial) - 1) & U16_MAX);
	sc->rng_ops.name = sc->rng_name;
	sc->rng_ops.read = ath9k_rng_read;
	sc->rng_ops.quality = 320;

	if (devm_hwrng_register(sc->dev, &sc->rng_ops))
		sc->rng_ops.read = NULL;
}

void ath9k_rng_stop(struct ath_softc *sc)
{
	if (sc->rng_ops.read) {
		devm_hwrng_unregister(sc->dev, &sc->rng_ops);
		sc->rng_ops.read = NULL;
	}
}
