/*
* SuperH Timer Support - CMT
*
* Copyright (C) 2008 Magnus Damm
*
* 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
*
* 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.
*/
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/sh_timer.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
struct sh_cmt_device;
/*
* The CMT comes in 5 different identified flavours, depending not only on the
* SoC but also on the particular instance. The following table lists the main
* characteristics of those flavours.
*
* 16B 32B 32B-F 48B 48B-2
* -----------------------------------------------------------------------------
* Channels 2 1/4 1 6 2/8
* Control Width 16 16 16 16 32
* Counter Width 16 32 32 32/48 32/48
* Shared Start/Stop Y Y Y Y N
*
* The 48-bit gen2 version has a per-channel start/stop register located in the
* channel registers block. All other versions have a shared start/stop register
* located in the global space.
*
* Channels are indexed from 0 to N-1 in the documentation. The channel index
* infers the start/stop bit position in the control register and the channel
* registers block address. Some CMT instances have a subset of channels
* available, in which case the index in the documentation doesn't match the
* "real" index as implemented in hardware. This is for instance the case with
* CMT0 on r8a7740, which is a 32-bit variant with a single channel numbered 0
* in the documentation but using start/stop bit 5 and having its registers
* block at 0x60.
*
* Similarly CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
* channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
*/
enum sh_cmt_model {
SH_CMT_16BIT,
SH_CMT_32BIT,
SH_CMT_32BIT_FAST,
SH_CMT_48BIT,
SH_CMT_48BIT_GEN2,
};
struct sh_cmt_info {
enum sh_cmt_model model;
unsigned long width; /* 16 or 32 bit version of hardware block */
unsigned long overflow_bit;
unsigned long clear_bits;
/* callbacks for CMSTR and CMCSR access */
unsigned long (*read_control)(void __iomem *base, unsigned long offs);
void (*write_control)(void __iomem *base, unsigned long offs,
unsigned long value);
/* callbacks for CMCNT and CMCOR access */
unsigned long (*read_count)(void __iomem *base, unsigned long offs);
void (*write_count)(void __iomem *base, unsigned long offs,
unsigned long value);
};
struct sh_cmt_channel {
struct sh_cmt_device *cmt;
unsigned int index; /* Index in the documentation */
unsigned int hwidx; /* Real hardware index */
void __iomem *iostart;
void __iomem *ioctrl;
unsigned int timer_bit;
unsigned long flags;
unsigned long match_value;
unsigned long next_match_value;
unsigned long max_match_value;
unsigned long rate;
raw_spinlock_t lock;
struct clock_event_device ced;
struct clocksource cs;
unsigned long total_cycles;
bool cs_enabled;
};
struct sh_cmt_device {
struct platform_device *pdev;
const struct sh_cmt_info *info;
bool legacy;
void __iomem *mapbase_ch;
void __iomem *mapbase;
struct clk *clk;
struct sh_cmt_channel *channels;
unsigned int num_channels;
bool has_clockevent;
bool has_clocksource;
};
#define SH_CMT16_CMCSR_CMF (1 << 7)
#define SH_CMT16_CMCSR_CMIE (1 << 6)
#define SH_CMT16_CMCSR_CKS8 (0 << 0)
#define SH_CMT16_CMCSR_CKS32 (1 << 0)
#define SH_CMT16_CMCSR_CKS128 (2 << 0)
#define SH_CMT16_CMCSR_CKS512 (3 << 0)
#define SH_CMT16_CMCSR_CKS_MASK (3 << 0)
#define SH_CMT32_CMCSR_CMF (1 << 15)
#define SH_CMT32_CMCSR_OVF (1 << 14)
#define SH_CMT32_CMCSR_WRFLG (1 << 13)
#define SH_CMT32_CMCSR_STTF (1 << 12)
#define SH_CMT32_CMCSR_STPF (1 << 11)
#define SH_CMT32_CMCSR_SSIE (1 << 10)
#define SH_CMT32_CMCSR_CMS (1 << 9)
#define SH_CMT32_CMCSR_CMM (1 << 8)
#define SH_CMT32_CMCSR_CMTOUT_IE (1 << 7)
#define SH_CMT32_CMCSR_CMR_NONE (0 << 4)
#define SH_CMT32_CMCSR_CMR_DMA (1 << 4)
#define SH_CMT32_CMCSR_CMR_IRQ (2 << 4)
#define SH_CMT32_CMCSR_CMR_MASK (3 << 4)
#define SH_CMT32_CMCSR_DBGIVD (1 << 3)
#define SH_CMT32_CMCSR_CKS_RCLK8 (4 << 0)
#define SH_CMT32_CMCSR_CKS_RCLK32 (5 << 0)
#define SH_CMT32_CMCSR_CKS_RCLK128 (6 << 0)
#define SH_CMT32_CMCSR_CKS_RCLK1 (7 << 0)
#define SH_CMT32_CMCSR_CKS_MASK (7 << 0)
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
{
return ioread16(base + (offs << 1));
}
static