/*
   fd2110_reg.h - register definitions for SoftLab-NSK FD2110 board

   Copyright (C) 2017 - 2023 Konstantin Oblaukhov <oblaukhov@sl.iae.nsk.su>

   This program is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.

   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 Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

#ifndef FD2110_REG_H
#define FD2110_REG_H

#include <linux/types.h>
#include <linux/io.h>

#define __read_reg(csr, addr) ioread32(&csr[addr])
#define __write_reg(csr, addr, v) iowrite32(v, &csr[addr])

typedef struct _FD2110_VideoConfig {
	uint32_t io0 : 1;
	uint32_t io1 : 1;
	uint32_t io2 : 1;
	uint32_t io3 : 1;
	uint32_t _unused3104 : 28;
} __attribute__((packed)) FD2110_VideoConfig;

#define FD2110_VideoConfig_A (0x03)

FD2110_VideoConfig __always_inline FD2110_VideoConfig_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_VideoConfig_A);
	return *((FD2110_VideoConfig *)&r);
}

void __always_inline FD2110_VideoConfig_W(uint32_t *csr, FD2110_VideoConfig v)
{
	__write_reg(csr, FD2110_VideoConfig_A, *((uint32_t *)&v));
}

typedef struct _FD2110_IRQEnable {
	uint32_t _unused1100 : 12;
	uint32_t sync0IRQ : 1;
	uint32_t _unused1313 : 1;
	uint32_t sync1IRQ : 1;
	uint32_t _unused1515 : 1;
	uint32_t sync2IRQ : 1;
	uint32_t _unused1717 : 1;
	uint32_t sync3IRQ : 1;
	uint32_t _unused3119 : 13;
} __attribute__((packed)) FD2110_IRQEnable;

#define FD2110_IRQEnable_A (0x04)

FD2110_IRQEnable __always_inline FD2110_IRQEnable_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_IRQEnable_A);
	return *((FD2110_IRQEnable *)&r);
}

void __always_inline FD2110_IRQEnable_W(uint32_t *csr, FD2110_IRQEnable v)
{
	__write_reg(csr, FD2110_IRQEnable_A, *((uint32_t *)&v));
}

typedef struct _FD2110_IRQFlags {
	uint32_t _unused1100 : 12;
	uint32_t sync0IRQ : 1;
	uint32_t sync0Field : 1;
	uint32_t sync1IRQ : 1;
	uint32_t sync1Field : 1;
	uint32_t sync2IRQ : 1;
	uint32_t sync2Field : 1;
	uint32_t sync3IRQ : 1;
	uint32_t sync3Field : 1;
	uint32_t _unused3120 : 12;
} __attribute__((packed)) FD2110_IRQFlags;

#define FD2110_IRQFlags_A (0x05)

FD2110_IRQFlags __always_inline FD2110_IRQFlags_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_IRQFlags_A);
	return *((FD2110_IRQFlags *)&r);
}

void __always_inline FD2110_IRQFlags_W(uint32_t *csr, FD2110_IRQFlags v)
{
	__write_reg(csr, FD2110_IRQFlags_A, *((uint32_t *)&v));
}

typedef struct _FD2110_VideoOutCS {
	uint32_t reset : 1;
	uint32_t mute : 1;
	uint32_t levelB : 1;
	uint32_t mode : 3;
	uint32_t clockM : 1;
	uint32_t freeRunning : 1;
	uint32_t progressive : 1;
	uint32_t audioCount : 2;
	uint32_t playback : 1;
	uint32_t playbackRaw : 1;
	uint32_t vbiTop : 1;
	uint32_t vbiBottom : 1;
	uint32_t vis10b : 1;
	uint32_t vbi10b : 1;
	uint32_t dataPresent : 1;
	uint32_t syncSource : 1;
	uint32_t _unused1919 : 1;
	uint32_t atcEnable : 1;
	uint32_t atcType : 2;
	uint32_t _unused2923 : 7;
	uint32_t clone : 1;
	uint32_t test : 1;
} __attribute__((packed)) FD2110_VideoOutCS;

#define FD2110_VideoOutCS_A(n) (0x40 + n * 16)

FD2110_VideoOutCS __always_inline FD2110_VideoOutCS_R(uint32_t *csr, unsigned int n)
{
	uint32_t r = __read_reg(csr, FD2110_VideoOutCS_A(n));
	return *((FD2110_VideoOutCS *)&r);
}

void __always_inline FD2110_VideoOutCS_W(uint32_t *csr, unsigned int n, FD2110_VideoOutCS v)
{
	__write_reg(csr, FD2110_VideoOutCS_A(n), *((uint32_t *)&v));
}

typedef struct _FD2110_MonitorStatus {
	uint32_t criticalOverheat : 1;
	uint32_t overheat : 1;
	uint32_t coreVoltageError : 1;
	uint32_t auxVoltageError : 1;
	uint32_t hisCriticalOverheat : 1;
	uint32_t hisOverheat : 1;
	uint32_t hisCoreVoltageError : 1;
	uint32_t hisAuxVoltageError : 1;
	uint32_t jtagPoison : 1;
	uint32_t _unused3109 : 23;
} __attribute__((packed)) FD2110_MonitorStatus;

#define FD2110_MonitorStatus_A (0x81)

FD2110_MonitorStatus __always_inline FD2110_MonitorStatus_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_MonitorStatus_A);
	return *((FD2110_MonitorStatus *)&r);
}

typedef struct _FD2110_TemperatureMonitor {
	uint32_t temperature : 10;
	uint32_t maxTemperature : 10;
	uint32_t minTemperature : 10;
	uint32_t _unused3130 : 2;
} __attribute__((packed)) FD2110_TemperatureMonitor;

#define FD2110_TemperatureMonitor_A (0x82)

FD2110_TemperatureMonitor __always_inline FD2110_TemperatureMonitor_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_TemperatureMonitor_A);
	return *((FD2110_TemperatureMonitor *)&r);
}

typedef struct _FD2110_VCoreMonitor {
	uint32_t voltage : 10;
	uint32_t maxVoltage : 10;
	uint32_t minVoltage : 10;
	uint32_t _unused3130 : 2;
} __attribute__((packed)) FD2110_VCoreMonitor;

#define FD2110_VCoreMonitor_A (0x83)

FD2110_VCoreMonitor __always_inline FD2110_VCoreMonitor_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_VCoreMonitor_A);
	return *((FD2110_VCoreMonitor *)&r);
}

typedef struct _FD2110_VAuxMonitor {
	uint32_t voltage : 10;
	uint32_t maxVoltage : 10;
	uint32_t minVoltage : 10;
	uint32_t _unused3130 : 2;
} __attribute__((packed)) FD2110_VAuxMonitor;

#define FD2110_VAuxMonitor_A (0x84)

FD2110_VAuxMonitor __always_inline FD2110_VAuxMonitor_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_VAuxMonitor_A);
	return *((FD2110_VAuxMonitor *)&r);
}

typedef struct _FD2110_SoftID {
	uint32_t id : 32;
} __attribute__((packed)) FD2110_SoftID;

#define FD2110_SoftID_A (0x8F)

FD2110_SoftID __always_inline FD2110_SoftID_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_SoftID_A);
	return *((FD2110_SoftID *)&r);
}

typedef struct _FD2110_StaticVersion {
	uint32_t revision : 16;
	uint32_t major : 8;
	uint32_t hwSubRevision : 2;
	uint32_t hwRevision : 3;
	uint32_t hwBoard : 3;
} __attribute__((packed)) FD2110_StaticVersion;

#define FD2110_StaticVersion_A (0xFF)

FD2110_StaticVersion __always_inline FD2110_StaticVersion_R(uint32_t *csr)
{
	uint32_t r = __read_reg(csr, FD2110_StaticVersion_A);
	return *((FD2110_StaticVersion *)&r);
}

#endif
