/*
 * Copyright (c) 2019 Intel Corp.
 * SPDX-License-Identifier: Apache-2.0
 *
 * This barebones driver enables the use of the PC AT-style RTC
 * (the so-called "CMOS" clock) as a primitive, 1Hz monotonic counter.
 *
 * Reading a reliable value from the RTC is a fairly slow process, because
 * we use legacy I/O ports and do a lot of iterations with spinlocks to read
 * the RTC state. Plus we have to read the state multiple times because we're
 * crossing clock domains (no pun intended). Use accordingly.
 */

#include <drivers/counter.h>
#include <device.h>
#include <soc.h>

/* The "CMOS" device is accessed via an address latch and data port. */

#define X86_CMOS_ADDR 0x70
#define X86_CMOS_DATA 0x71

/*
 * A snapshot of the RTC state, or at least the state we're
 * interested in. This struct should not be modified without
 * serious consideraton, for two reasons:
 *
 *	1. Order of the element is important, and must correlate
 *	   with addrs[] and NR_BCD_VALS (see below), and
 *	2. if it doesn't remain exactly 8 bytes long, the
 *	   type-punning to compare states will break.
 */

struct state {
	uint8_t second,
	     minute,
	     hour,
	     day,
	     month,
	     year,
	     status_a,
	     status_b;
};

/*
 * If the clock is in BCD mode, the first NR_BCD_VALS
 * valies in 'struct state' are BCD-encoded.
 */

#define NR_BCD_VALS 6

/*
 * Indices into the CMOS address space that correspond to
 * the members of 'struct state'.
 */

const uint8_t addrs[] = { 0, 2, 4, 7, 8, 9, 10, 11 };

/*
 * Interesting bits in 'struct state'.
 */

#define STATUS_B_24HR	0x02	/* 24-hour (vs 12-hour) mode */
#define STATUS_B_BIN	0x01	/* binary (vs BCD) mode */
#define HOUR_PM		0x80	/* high bit of hour set = PM */

/*
 * Read a value from the CMOS. Because of the address latch,
 * we have to spinlock to make the access atomic.
 */

static uint8_t read_register(uint8_t addr)
{
	static struct k_spinlock lock;
	k_spinlock_key_t k;
	uint8_t val;

	k = k_spin_lock(&lock);
	sys_out8(addr, X86_CMOS_ADDR);
	val = sys_in8(X86_CMOS_DATA);
	k_spin_unlock(&lock, k);

	return val;
}

/* Populate 'state' with current RTC state. */

void read_state(struct state *state)
{
	int i;
	uint8_t *p;

	p = (uint8_t *) state;
	for (i = 0; i < sizeof(*state); ++i) {
		*p++ = read_register(addrs[i]);
	}
}

/* Convert 8-bit (2-digit) BCD to binary equivalent. */

static inline uint8_t decode_bcd(uint8_t val)
{
	return (((val >> 4) & 0x0F) * 10) + (val & 0x0F);
}

/*
 * Hinnant's algorithm to calculate the number of days offset from the epoch.
 */

static uint32_t hinnant(int y, int m, int d)
{
	unsigned yoe;
	unsigned doy;
	unsigned doe;
	int era;

	y -= (m <= 2);
	era = ((y >= 0) ? y : (y - 399)) / 400;
	yoe = y - era * 400;
	doy = (153 * (m + ((m > 2) ? -3 : 9)) + 2)/5 + d - 1;
	doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;

	return era * 146097 + ((int) doe) - 719468;
}

/*
 * Get the Unix epoch time (assuming UTC) read from the CMOS RTC.
 * This function is long, but linear and easy to follow.
 */

int get_value(const struct device *dev, uint32_t *ticks)
{
	struct state state, state2;
	uint64_t *pun = (uint64_t *) &state;
	uint64_t *pun2 = (uint64_t *) &state2;
	bool pm;
	uint32_t epoch;

	ARG_UNUSED(dev);

	/*
	 * Read the state until we see the same state twice in a row.
	 */

	read_state(&state2);
	do {
		state = state2;
		read_state(&state2);
	} while (*pun != *pun2);

	/*
	 * Normalize the state; 12hr -> 24hr, BCD -> decimal.
	 * The order is a bit awkward because we need to interpret
	 * the HOUR_PM flag before we adjust for BCD.
	 */

	if ((state.status_b & STATUS_B_24HR) != 0U) {
		pm = false;
	} else {
		pm = ((state.hour & HOUR_PM) == HOUR_PM);
		state.hour &= ~HOUR_PM;
	}

	if ((state.status_b & STATUS_B_BIN) == 0U) {
		uint8_t *cp = (uint8_t *) &state;
		int i;

		for (i = 0; i < NR_BCD_VALS; ++i) {
			*cp = decode_bcd(*cp);
			++cp;
		}
	}

	if (pm) {
		state.hour = (state.hour + 12) % 24;
	}

	/*
	 * Convert date/time to epoch time. We don't care about
	 * timezones here, because we're just creating a mapping
	 * that results in a monotonic clock; the absolute value
	 * is irrelevant.
	 */

	epoch = hinnant(state.year + 2000, state.month, state.day);
	epoch *= 86400; /* seconds per day */
	epoch += state.hour * 3600; /* seconds per hour */
	epoch += state.minute * 60; /* seconds per minute */
	epoch += state.second;

	*ticks = epoch;
	return 0;
}

static int init(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

static const struct counter_config_info info = {
	.max_top_value = UINT_MAX,
	.freq = 1
};

static const struct counter_driver_api api = {
	.get_value = get_value
};

DEVICE_DEFINE(counter_cmos, "CMOS", init, NULL, NULL, &info,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &api);
