Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <linux/module.h>
  3#include <linux/smp.h>
  4#include <linux/time.h>
  5#include <linux/errno.h>
  6#include <linux/timex.h>
  7#include <linux/clocksource.h>
  8#include <linux/io.h>
  9
 10/* IBM Summit (EXA) Cyclone counter code*/
 11#define CYCLONE_CBAR_ADDR 0xFEB00CD0
 12#define CYCLONE_PMCC_OFFSET 0x51A0
 13#define CYCLONE_MPMC_OFFSET 0x51D0
 14#define CYCLONE_MPCS_OFFSET 0x51A8
 15#define CYCLONE_TIMER_FREQ 100000000
 16
 17int use_cyclone;
 18void __init cyclone_setup(void)
 19{
 20	use_cyclone = 1;
 21}
 22
 23static void __iomem *cyclone_mc;
 24
 25static u64 read_cyclone(struct clocksource *cs)
 26{
 27	return (u64)readq((void __iomem *)cyclone_mc);
 28}
 29
 30static struct clocksource clocksource_cyclone = {
 31        .name           = "cyclone",
 32        .rating         = 300,
 33        .read           = read_cyclone,
 34        .mask           = (1LL << 40) - 1,
 35        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 36};
 37
 38int __init init_cyclone_clock(void)
 39{
 40	u64 __iomem *reg;
 41	u64 base;	/* saved cyclone base address */
 42	u64 offset;	/* offset from pageaddr to cyclone_timer register */
 43	int i;
 44	u32 __iomem *cyclone_timer;	/* Cyclone MPMC0 register */
 45
 46	if (!use_cyclone)
 47		return 0;
 48
 49	printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
 50
 51	/* find base address */
 52	offset = (CYCLONE_CBAR_ADDR);
 53	reg = ioremap(offset, sizeof(u64));
 54	if(!reg){
 55		printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
 56				" register.\n");
 57		use_cyclone = 0;
 58		return -ENODEV;
 59	}
 60	base = readq(reg);
 61	iounmap(reg);
 62	if(!base){
 63		printk(KERN_ERR "Summit chipset: Could not find valid CBAR"
 64				" value.\n");
 65		use_cyclone = 0;
 66		return -ENODEV;
 67	}
 68
 69	/* setup PMCC */
 70	offset = (base + CYCLONE_PMCC_OFFSET);
 71	reg = ioremap(offset, sizeof(u64));
 72	if(!reg){
 73		printk(KERN_ERR "Summit chipset: Could not find valid PMCC"
 74				" register.\n");
 75		use_cyclone = 0;
 76		return -ENODEV;
 77	}
 78	writel(0x00000001,reg);
 79	iounmap(reg);
 80
 81	/* setup MPCS */
 82	offset = (base + CYCLONE_MPCS_OFFSET);
 83	reg = ioremap(offset, sizeof(u64));
 84	if(!reg){
 85		printk(KERN_ERR "Summit chipset: Could not find valid MPCS"
 86				" register.\n");
 87		use_cyclone = 0;
 88		return -ENODEV;
 89	}
 90	writel(0x00000001,reg);
 91	iounmap(reg);
 92
 93	/* map in cyclone_timer */
 94	offset = (base + CYCLONE_MPMC_OFFSET);
 95	cyclone_timer = ioremap(offset, sizeof(u32));
 96	if(!cyclone_timer){
 97		printk(KERN_ERR "Summit chipset: Could not find valid MPMC"
 98				" register.\n");
 99		use_cyclone = 0;
100		return -ENODEV;
101	}
102
103	/*quick test to make sure its ticking*/
104	for(i=0; i<3; i++){
105		u32 old = readl(cyclone_timer);
106		int stall = 100;
107		while(stall--) barrier();
108		if(readl(cyclone_timer) == old){
109			printk(KERN_ERR "Summit chipset: Counter not counting!"
110					" DISABLED\n");
111			iounmap(cyclone_timer);
112			cyclone_timer = NULL;
113			use_cyclone = 0;
114			return -ENODEV;
115		}
116	}
117	/* initialize last tick */
118	cyclone_mc = cyclone_timer;
119	clocksource_cyclone.archdata.fsys_mmio = cyclone_timer;
120	clocksource_register_hz(&clocksource_cyclone, CYCLONE_TIMER_FREQ);
121
122	return 0;
123}
124
125__initcall(init_cyclone_clock);