Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6457d9fc authored by Yoichi Yuasa's avatar Yoichi Yuasa Committed by Ralf Baechle
Browse files

[MIPS] DS1287: Add clockevent driver

parent 4247417d
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -81,6 +81,7 @@ config MIPS_COBALT
config MACH_DECSTATION
config MACH_DECSTATION
	bool "DECstations"
	bool "DECstations"
	select BOOT_ELF32
	select BOOT_ELF32
	select CEVT_DS1287
	select CEVT_R4K
	select CEVT_R4K
	select CSRC_IOASIC
	select CSRC_IOASIC
	select CSRC_R4K
	select CSRC_R4K
@@ -770,6 +771,9 @@ config BOOT_RAW
config CEVT_BCM1480
config CEVT_BCM1480
	bool
	bool


config CEVT_DS1287
	bool

config CEVT_GT641XX
config CEVT_GT641XX
	bool
	bool


+22 −47
Original line number Original line Diff line number Diff line
@@ -9,30 +9,15 @@
 *
 *
 */
 */
#include <linux/bcd.h>
#include <linux/bcd.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mc146818rtc.h>
#include <linux/mc146818rtc.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/param.h>
#include <linux/param.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/time.h>
#include <linux/types.h>

#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/sections.h>
#include <asm/time.h>


#include <asm/cpu-features.h>
#include <asm/ds1287.h>
#include <asm/time.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/machtype.h>
#include <asm/dec/machtype.h>


unsigned long read_persistent_clock(void)
unsigned long read_persistent_clock(void)
@@ -139,42 +124,32 @@ int rtc_mips_set_mmss(unsigned long nowtime)
	return retval;
	return retval;
}
}


static int dec_timer_state(void)
void __init plat_time_init(void)
{
{
	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
	u32 start, end;
}
	int i = HZ / 10;


static void dec_timer_ack(void)
	/* Set up the rate of periodic DS1287 interrupts. */
{
	ds1287_set_base_clock(HZ);
	CMOS_READ(RTC_REG_C);			/* Ack the RTC interrupt.  */
}


static cycle_t dec_ioasic_hpt_read(void)
	if (cpu_has_counter) {
{
		while (!ds1287_timer_state())
	/*
			;
	 * The free-running counter is 32-bit which is good for about
	 * 2 minutes, 50 seconds at possible count rates of up to 25MHz.
	 */
	return ioasic_read(IO_REG_FCTR);
}


		start = read_c0_count();


void __init plat_time_init(void)
		while (i--)
{
			while (!ds1287_timer_state())
	mips_timer_ack = dec_timer_ack;
				;


	if (!cpu_has_counter && IOASIC)
		end = read_c0_count();

		mips_hpt_frequency = (end - start) * 10;
		printk(KERN_INFO "MIPS counter frequency %dHz\n",
			mips_hpt_frequency);
	} else if (IOASIC)
		/* For pre-R4k systems we use the I/O ASIC's counter.  */
		/* For pre-R4k systems we use the I/O ASIC's counter.  */
		dec_ioasic_clocksource_init();
		dec_ioasic_clocksource_init();


	/* Set up the rate of periodic DS1287 interrupts.  */
	ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
	CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A);
}

void __init plat_timer_setup(struct irqaction *irq)
{
	setup_irq(dec_interrupt[DEC_IRQ_RTC], irq);

	/* Enable periodic DS1287 interrupts.  */
	CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B);
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -10,6 +10,7 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \


obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
obj-$(CONFIG_CEVT_BCM1480)	+= cevt-bcm1480.o
obj-$(CONFIG_CEVT_R4K)		+= cevt-r4k.o
obj-$(CONFIG_CEVT_R4K)		+= cevt-r4k.o
obj-$(CONFIG_CEVT_DS1287)	+= cevt-ds1287.o
obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o
obj-$(CONFIG_CEVT_GT641XX)	+= cevt-gt641xx.o
obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o
obj-$(CONFIG_CEVT_SB1250)	+= cevt-sb1250.o
obj-$(CONFIG_CEVT_TXX9)		+= cevt-txx9.o
obj-$(CONFIG_CEVT_TXX9)		+= cevt-txx9.o
+129 −0
Original line number Original line Diff line number Diff line
/*
 *  DS1287 clockevent driver
 *
 *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
 *
 *  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
 */
#include <linux/clockchips.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>

#include <asm/time.h>

int ds1287_timer_state(void)
{
	return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0;
}

int ds1287_set_base_clock(unsigned int hz)
{
	u8 rate;

	switch (hz) {
	case 128:
		rate = 0x9;
		break;
	case 256:
		rate = 0x8;
		break;
	case 1024:
		rate = 0x6;
		break;
	default:
		return -EINVAL;
	}

	CMOS_WRITE(RTC_REF_CLCK_32KHZ | rate, RTC_REG_A);

	return 0;
}

static int ds1287_set_next_event(unsigned long delta,
				 struct clock_event_device *evt)
{
	return -EINVAL;
}

static void ds1287_set_mode(enum clock_event_mode mode,
			    struct clock_event_device *evt)
{
	u8 val;

	spin_lock(&rtc_lock);

	val = CMOS_READ(RTC_REG_B);

	switch (mode) {
	case CLOCK_EVT_MODE_PERIODIC:
		val |= RTC_PIE;
		break;
	default:
		val &= ~RTC_PIE;
		break;
	}

	CMOS_WRITE(val, RTC_REG_B);

	spin_unlock(&rtc_lock);
}

static void ds1287_event_handler(struct clock_event_device *dev)
{
}

static struct clock_event_device ds1287_clockevent = {
	.name		= "ds1287",
	.features	= CLOCK_EVT_FEAT_PERIODIC,
	.cpumask	= CPU_MASK_CPU0,
	.set_next_event	= ds1287_set_next_event,
	.set_mode	= ds1287_set_mode,
	.event_handler	= ds1287_event_handler,
};

static irqreturn_t ds1287_interrupt(int irq, void *dev_id)
{
	struct clock_event_device *cd = &ds1287_clockevent;

	/* Ack the RTC interrupt. */
	CMOS_READ(RTC_REG_C);

	cd->event_handler(cd);

	return IRQ_HANDLED;
}

static struct irqaction ds1287_irqaction = {
	.handler	= ds1287_interrupt,
	.flags		= IRQF_DISABLED | IRQF_PERCPU,
	.name		= "ds1287",
};

int __init ds1287_clockevent_init(int irq)
{
	struct clock_event_device *cd;

	cd = &ds1287_clockevent;
	cd->rating = 100;
	cd->irq = irq;
	clockevent_set_clock(cd, 32768);
	cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd);
	cd->min_delta_ns = clockevent_delta2ns(0x300, cd);

	clockevents_register_device(&ds1287_clockevent);

	return setup_irq(irq, &ds1287_irqaction);
}
+27 −0
Original line number Original line Diff line number Diff line
/*
 *  DS1287 timer functions.
 *
 *  Copyright (C) 2008  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
 *
 *  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 __ASM_DS1287_H
#define __ASM_DS1287_H

extern int ds1287_timer_state(void);
extern void ds1287_set_base_clock(unsigned int clock);
extern int ds1287_clockevent_init(int irq);

#endif