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

Commit 29b503f1 authored by David S. Miller's avatar David S. Miller
Browse files

sparc64: Use generic BQ4802 RTC driver.

parent cca4c231
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ config SPARC64
	select RTC_CLASS
	select RTC_CLASS
	select RTC_DRV_M48T59
	select RTC_DRV_M48T59
	select RTC_DRV_CMOS
	select RTC_DRV_CMOS
	select RTC_DRV_BQ4802


config GENERIC_TIME
config GENERIC_TIME
	bool
	bool
+11 −190
Original line number Original line Diff line number Diff line
@@ -52,9 +52,6 @@
#include "entry.h"
#include "entry.h"


DEFINE_SPINLOCK(rtc_lock);
DEFINE_SPINLOCK(rtc_lock);
static void __iomem *bq4802_regs;

static int set_rtc_mmss(unsigned long);


#define TICK_PRIV_BIT	(1UL << 63)
#define TICK_PRIV_BIT	(1UL << 63)
#define TICKCMP_IRQ_BIT	(1UL << 63)
#define TICKCMP_IRQ_BIT	(1UL << 63)
@@ -403,50 +400,7 @@ int update_persistent_clock(struct timespec now)
	if (rtc)
	if (rtc)
		return rtc_set_mmss(rtc, now.tv_sec);
		return rtc_set_mmss(rtc, now.tv_sec);


	return set_rtc_mmss(now.tv_sec);
	return -1;
}

/* Probe for the real time clock chip. */
static void __init set_system_time(void)
{
	unsigned int year, mon, day, hour, min, sec;
	void __iomem *bregs = bq4802_regs;
	unsigned char val = readb(bregs + 0x0e);
	unsigned int century;

	if (!bregs) {
		prom_printf("Something wrong, clock regs not mapped yet.\n");
		prom_halt();
	}		

	/* BQ4802 RTC chip. */

	writeb(val | 0x08, bregs + 0x0e);

	sec  = readb(bregs + 0x00);
	min  = readb(bregs + 0x02);
	hour = readb(bregs + 0x04);
	day  = readb(bregs + 0x06);
	mon  = readb(bregs + 0x09);
	year = readb(bregs + 0x0a);
	century = readb(bregs + 0x0f);

	writeb(val, bregs + 0x0e);

	BCD_TO_BIN(sec);
	BCD_TO_BIN(min);
	BCD_TO_BIN(hour);
	BCD_TO_BIN(day);
	BCD_TO_BIN(mon);
	BCD_TO_BIN(year);
	BCD_TO_BIN(century);

	year += (century * 100);

	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
	set_normalized_timespec(&wall_to_monotonic,
 	                        -xtime.tv_sec, -xtime.tv_nsec);
}
}


/* davem suggests we keep this within the 4M locked kernel image */
/* davem suggests we keep this within the 4M locked kernel image */
@@ -575,24 +529,20 @@ static struct of_platform_driver rtc_driver = {
	},
	},
};
};


static struct platform_device rtc_bq4802_device = {
	.name		= "rtc-bq4802",
	.id		= -1,
	.num_resources	= 1,
};

static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match)
static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match)
{
{
	struct device_node *dp = op->node;
	unsigned long flags;

	bq4802_regs = of_ioremap(&op->resource[0], 0, resource_size(&op->resource[0]), "bq4802");
	if (!bq4802_regs)
		return -ENOMEM;


	printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, bq4802_regs);
	printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n",

	       op->node->full_name, op->resource[0].start);
	local_irq_save(flags);

	set_system_time();
	
	local_irq_restore(flags);


	return 0;
	rtc_bq4802_device.resource = &op->resource[0];
	return platform_device_register(&rtc_bq4802_device);
}
}


static struct of_device_id bq4802_match[] = {
static struct of_device_id bq4802_match[] = {
@@ -984,56 +934,6 @@ unsigned long long sched_clock(void)
		>> SPARC64_NSEC_PER_CYC_SHIFT;
		>> SPARC64_NSEC_PER_CYC_SHIFT;
}
}


static int set_rtc_mmss(unsigned long nowtime)
{
	int real_seconds, real_minutes, chip_minutes;
	void __iomem *bregs = bq4802_regs;
	unsigned long flags;
	unsigned char val;
	int retval = 0;

	/* 
	 * Not having a register set can lead to trouble.
	 * Also starfire doesn't have a tod clock.
	 */
	if (!bregs)
		return -1;

	spin_lock_irqsave(&rtc_lock, flags);

	val = readb(bregs + 0x0e);

	/* BQ4802 RTC chip. */

	writeb(val | 0x08, bregs + 0x0e);

	chip_minutes = readb(bregs + 0x02);
	BCD_TO_BIN(chip_minutes);
	real_seconds = nowtime % 60;
	real_minutes = nowtime / 60;
	if (((abs(real_minutes - chip_minutes) + 15)/30) & 1)
		real_minutes += 30;
	real_minutes %= 60;

	if (abs(real_minutes - chip_minutes) < 30) {
		BIN_TO_BCD(real_seconds);
		BIN_TO_BCD(real_minutes);
		writeb(real_seconds, bregs + 0x00);
		writeb(real_minutes, bregs + 0x02);
	} else {
		printk(KERN_WARNING
		       "set_rtc_mmss: can't update from %d to %d\n",
		       chip_minutes, real_minutes);
		retval = -1;
	}

	writeb(val, bregs + 0x0e);

	spin_unlock_irqrestore(&rtc_lock, flags);

	return retval;
}

#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
#define RTC_IS_OPEN		0x01	/* means /dev/rtc is in use	*/
static unsigned char mini_rtc_status;	/* bitmapped status byte.	*/
static unsigned char mini_rtc_status;	/* bitmapped status byte.	*/


@@ -1155,78 +1055,6 @@ static int hypervisor_set_rtc_time(struct rtc_time *time)
	return hypervisor_set_time(seconds);
	return hypervisor_set_time(seconds);
}
}


static void bq4802_get_rtc_time(struct rtc_time *time)
{
	unsigned char val = readb(bq4802_regs + 0x0e);
	unsigned int century;

	writeb(val | 0x08, bq4802_regs + 0x0e);

	time->tm_sec = readb(bq4802_regs + 0x00);
	time->tm_min = readb(bq4802_regs + 0x02);
	time->tm_hour = readb(bq4802_regs + 0x04);
	time->tm_mday = readb(bq4802_regs + 0x06);
	time->tm_mon = readb(bq4802_regs + 0x09);
	time->tm_year = readb(bq4802_regs + 0x0a);
	time->tm_wday = readb(bq4802_regs + 0x08);
	century = readb(bq4802_regs + 0x0f);

	writeb(val, bq4802_regs + 0x0e);

	BCD_TO_BIN(time->tm_sec);
	BCD_TO_BIN(time->tm_min);
	BCD_TO_BIN(time->tm_hour);
	BCD_TO_BIN(time->tm_mday);
	BCD_TO_BIN(time->tm_mon);
	BCD_TO_BIN(time->tm_year);
	BCD_TO_BIN(time->tm_wday);
	BCD_TO_BIN(century);

	time->tm_year += (century * 100);
	time->tm_year -= 1900;

	time->tm_mon--;
}

static int bq4802_set_rtc_time(struct rtc_time *time)
{
	unsigned char val = readb(bq4802_regs + 0x0e);
	unsigned char sec, min, hrs, day, mon, yrs, century;
	unsigned int year;

	year = time->tm_year + 1900;
	century = year / 100;
	yrs = year % 100;

	mon = time->tm_mon + 1;   /* tm_mon starts at zero */
	day = time->tm_mday;
	hrs = time->tm_hour;
	min = time->tm_min;
	sec = time->tm_sec;

	BIN_TO_BCD(sec);
	BIN_TO_BCD(min);
	BIN_TO_BCD(hrs);
	BIN_TO_BCD(day);
	BIN_TO_BCD(mon);
	BIN_TO_BCD(yrs);
	BIN_TO_BCD(century);

	writeb(val | 0x08, bq4802_regs + 0x0e);

	writeb(sec, bq4802_regs + 0x00);
	writeb(min, bq4802_regs + 0x02);
	writeb(hrs, bq4802_regs + 0x04);
	writeb(day, bq4802_regs + 0x06);
	writeb(mon, bq4802_regs + 0x09);
	writeb(yrs, bq4802_regs + 0x0a);
	writeb(century, bq4802_regs + 0x0f);

	writeb(val, bq4802_regs + 0x0e);

	return 0;
}

struct mini_rtc_ops {
struct mini_rtc_ops {
	void (*get_rtc_time)(struct rtc_time *);
	void (*get_rtc_time)(struct rtc_time *);
	int (*set_rtc_time)(struct rtc_time *);
	int (*set_rtc_time)(struct rtc_time *);
@@ -1242,11 +1070,6 @@ static struct mini_rtc_ops hypervisor_rtc_ops = {
	.set_rtc_time = hypervisor_set_rtc_time,
	.set_rtc_time = hypervisor_set_rtc_time,
};
};


static struct mini_rtc_ops bq4802_rtc_ops = {
	.get_rtc_time = bq4802_get_rtc_time,
	.set_rtc_time = bq4802_set_rtc_time,
};

static struct mini_rtc_ops *mini_rtc_ops;
static struct mini_rtc_ops *mini_rtc_ops;


static inline void mini_get_rtc_time(struct rtc_time *time)
static inline void mini_get_rtc_time(struct rtc_time *time)
@@ -1373,8 +1196,6 @@ static int __init rtc_mini_init(void)
		mini_rtc_ops = &hypervisor_rtc_ops;
		mini_rtc_ops = &hypervisor_rtc_ops;
	else if (this_is_starfire)
	else if (this_is_starfire)
		mini_rtc_ops = &starfire_rtc_ops;
		mini_rtc_ops = &starfire_rtc_ops;
	else if (bq4802_regs)
		mini_rtc_ops = &bq4802_rtc_ops;
	else
	else
		return -ENODEV;
		return -ENODEV;