linux/drivers/rtc/rtc-armada38x.c

// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * RTC driver for the Armada 38x Marvell SoCs
 *
 * Copyright (C) 2015 Marvell
 *
 * Gregory Clement <[email protected]>
 */

#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>

#define RTC_STATUS
#define RTC_STATUS_ALARM1
#define RTC_STATUS_ALARM2
#define RTC_IRQ1_CONF
#define RTC_IRQ2_CONF
#define RTC_IRQ_AL_EN
#define RTC_IRQ_FREQ_EN
#define RTC_IRQ_FREQ_1HZ
#define RTC_CCR
#define RTC_CCR_MODE
#define RTC_CONF_TEST
#define RTC_NOMINAL_TIMING

#define RTC_TIME
#define RTC_ALARM1
#define RTC_ALARM2

/* Armada38x SoC registers  */
#define RTC_38X_BRIDGE_TIMING_CTL
#define RTC_38X_PERIOD_OFFS
#define RTC_38X_PERIOD_MASK
#define RTC_38X_READ_DELAY_OFFS
#define RTC_38X_READ_DELAY_MASK

/* Armada 7K/8K registers  */
#define RTC_8K_BRIDGE_TIMING_CTL0
#define RTC_8K_WRCLK_PERIOD_OFFS
#define RTC_8K_WRCLK_PERIOD_MASK
#define RTC_8K_WRCLK_SETUP_OFFS
#define RTC_8K_WRCLK_SETUP_MASK
#define RTC_8K_BRIDGE_TIMING_CTL1
#define RTC_8K_READ_DELAY_OFFS
#define RTC_8K_READ_DELAY_MASK

#define RTC_8K_ISR
#define RTC_8K_IMR
#define RTC_8K_ALARM2

#define SOC_RTC_INTERRUPT
#define SOC_RTC_ALARM1
#define SOC_RTC_ALARM2
#define SOC_RTC_ALARM1_MASK
#define SOC_RTC_ALARM2_MASK

#define SAMPLE_NR

struct value_to_freq {};

struct armada38x_rtc {};

#define ALARM1
#define ALARM2

#define ALARM_REG(base, alarm)

struct armada38x_rtc_data {};

/*
 * According to the datasheet, the OS should wait 5us after every
 * register write to the RTC hard macro so that the required update
 * can occur without holding off the system bus
 * According to errata RES-3124064, Write to any RTC register
 * may fail. As a workaround, before writing to RTC
 * register, issue a dummy write of 0x0 twice to RTC Status
 * register.
 */

static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
{}

/* Update RTC-MBUS bridge timing parameters */
static void rtc_update_38x_mbus_timing_params(struct armada38x_rtc *rtc)
{}

static void rtc_update_8k_mbus_timing_params(struct armada38x_rtc *rtc)
{}

static u32 read_rtc_register(struct armada38x_rtc *rtc, u8 rtc_reg)
{}

static u32 read_rtc_register_38x_wa(struct armada38x_rtc *rtc, u8 rtc_reg)
{}

static void armada38x_clear_isr(struct armada38x_rtc *rtc)
{}

static void armada38x_unmask_interrupt(struct armada38x_rtc *rtc)
{}

static void armada8k_clear_isr(struct armada38x_rtc *rtc)
{}

static void armada8k_unmask_interrupt(struct armada38x_rtc *rtc)
{}

static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{}

static void armada38x_rtc_reset(struct armada38x_rtc *rtc)
{}

static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{}

static int armada38x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{}

static int armada38x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{}

static int armada38x_rtc_alarm_irq_enable(struct device *dev,
					 unsigned int enabled)
{}

static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
{}

/*
 * The information given in the Armada 388 functional spec is complex.
 * They give two different formulas for calculating the offset value,
 * but when considering "Offset" as an 8-bit signed integer, they both
 * reduce down to (we shall rename "Offset" as "val" here):
 *
 *   val = (f_ideal / f_measured - 1) / resolution   where f_ideal = 32768
 *
 * Converting to time, f = 1/t:
 *   val = (t_measured / t_ideal - 1) / resolution   where t_ideal = 1/32768
 *
 *   =>  t_measured / t_ideal = val * resolution + 1
 *
 * "offset" in the RTC interface is defined as:
 *   t = t0 * (1 + offset * 1e-9)
 * where t is the desired period, t0 is the measured period with a zero
 * offset, which is t_measured above. With t0 = t_measured and t = t_ideal,
 *   offset = (t_ideal / t_measured - 1) / 1e-9
 *
 *   => t_ideal / t_measured = offset * 1e-9 + 1
 *
 * so:
 *
 *   offset * 1e-9 + 1 = 1 / (val * resolution + 1)
 *
 * We want "resolution" to be an integer, so resolution = R * 1e-9, giving
 *   offset = 1e18 / (val * R + 1e9) - 1e9
 *   val = (1e18 / (offset + 1e9) - 1e9) / R
 * with a common transformation:
 *   f(x) = 1e18 / (x + 1e9) - 1e9
 *   offset = f(val * R)
 *   val = f(offset) / R
 *
 * Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb).
 */
static long armada38x_ppb_convert(long ppb)
{}

static int armada38x_rtc_read_offset(struct device *dev, long *offset)
{}

static int armada38x_rtc_set_offset(struct device *dev, long offset)
{}

static const struct rtc_class_ops armada38x_rtc_ops =;

static const struct armada38x_rtc_data armada38x_data =;

static const struct armada38x_rtc_data armada8k_data =;

static const struct of_device_id armada38x_rtc_of_match_table[] =;
MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);

static __init int armada38x_rtc_probe(struct platform_device *pdev)
{}

#ifdef CONFIG_PM_SLEEP
static int armada38x_rtc_suspend(struct device *dev)
{}

static int armada38x_rtc_resume(struct device *dev)
{}
#endif

static SIMPLE_DEV_PM_OPS(armada38x_rtc_pm_ops,
			 armada38x_rtc_suspend, armada38x_rtc_resume);

static struct platform_driver armada38x_rtc_driver =;

module_platform_driver_probe();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_LICENSE();