xref: /openbmc/linux/arch/m68k/hp300/config.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/arch/m68k/hp300/config.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  This file contains the HP300-specific initialisation code.  It gets
81da177e4SLinus Torvalds  *  called by setup.c.
91da177e4SLinus Torvalds  */
101da177e4SLinus Torvalds 
111da177e4SLinus Torvalds #include <linux/module.h>
121da177e4SLinus Torvalds #include <linux/init.h>
131da177e4SLinus Torvalds #include <linux/string.h>
141da177e4SLinus Torvalds #include <linux/kernel.h>
151da177e4SLinus Torvalds #include <linux/console.h>
16084b3600SArnd Bergmann #include <linux/rtc.h>
171da177e4SLinus Torvalds 
181da177e4SLinus Torvalds #include <asm/bootinfo.h>
194c3c522bSGeert Uytterhoeven #include <asm/bootinfo-hp300.h>
20abe48101SGeert Uytterhoeven #include <asm/byteorder.h>
211da177e4SLinus Torvalds #include <asm/machdep.h>
221da177e4SLinus Torvalds #include <asm/blinken.h>
231da177e4SLinus Torvalds #include <asm/io.h>                               /* readb() and writeb() */
241da177e4SLinus Torvalds #include <asm/hp300hw.h>
25*91d7b75aSLaurent Vivier #include <asm/config.h>
261da177e4SLinus Torvalds 
271da177e4SLinus Torvalds #include "time.h"
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds unsigned long hp300_model;
301da177e4SLinus Torvalds unsigned long hp300_uart_scode = -1;
31f808b865SGeert Uytterhoeven unsigned char hp300_ledstate;
32f808b865SGeert Uytterhoeven EXPORT_SYMBOL(hp300_ledstate);
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds static char s_hp330[] __initdata = "330";
351da177e4SLinus Torvalds static char s_hp340[] __initdata = "340";
361da177e4SLinus Torvalds static char s_hp345[] __initdata = "345";
371da177e4SLinus Torvalds static char s_hp360[] __initdata = "360";
381da177e4SLinus Torvalds static char s_hp370[] __initdata = "370";
391da177e4SLinus Torvalds static char s_hp375[] __initdata = "375";
401da177e4SLinus Torvalds static char s_hp380[] __initdata = "380";
411da177e4SLinus Torvalds static char s_hp385[] __initdata = "385";
421da177e4SLinus Torvalds static char s_hp400[] __initdata = "400";
431da177e4SLinus Torvalds static char s_hp425t[] __initdata = "425t";
441da177e4SLinus Torvalds static char s_hp425s[] __initdata = "425s";
451da177e4SLinus Torvalds static char s_hp425e[] __initdata = "425e";
461da177e4SLinus Torvalds static char s_hp433t[] __initdata = "433t";
471da177e4SLinus Torvalds static char s_hp433s[] __initdata = "433s";
481da177e4SLinus Torvalds static char *hp300_models[] __initdata = {
491da177e4SLinus Torvalds 	[HP_320]	= NULL,
501da177e4SLinus Torvalds 	[HP_330]	= s_hp330,
511da177e4SLinus Torvalds 	[HP_340]	= s_hp340,
521da177e4SLinus Torvalds 	[HP_345]	= s_hp345,
531da177e4SLinus Torvalds 	[HP_350]	= NULL,
541da177e4SLinus Torvalds 	[HP_360]	= s_hp360,
551da177e4SLinus Torvalds 	[HP_370]	= s_hp370,
561da177e4SLinus Torvalds 	[HP_375]	= s_hp375,
571da177e4SLinus Torvalds 	[HP_380]	= s_hp380,
581da177e4SLinus Torvalds 	[HP_385]	= s_hp385,
591da177e4SLinus Torvalds 	[HP_400]	= s_hp400,
601da177e4SLinus Torvalds 	[HP_425T]	= s_hp425t,
611da177e4SLinus Torvalds 	[HP_425S]	= s_hp425s,
621da177e4SLinus Torvalds 	[HP_425E]	= s_hp425e,
631da177e4SLinus Torvalds 	[HP_433T]	= s_hp433t,
641da177e4SLinus Torvalds 	[HP_433S]	= s_hp433s,
651da177e4SLinus Torvalds };
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds static char hp300_model_name[13] = "HP9000/";
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds extern void hp300_reset(void);
701da177e4SLinus Torvalds #ifdef CONFIG_SERIAL_8250_CONSOLE
711da177e4SLinus Torvalds extern int hp300_setup_serial_console(void) __init;
721da177e4SLinus Torvalds #endif
731da177e4SLinus Torvalds 
hp300_parse_bootinfo(const struct bi_record * record)741da177e4SLinus Torvalds int __init hp300_parse_bootinfo(const struct bi_record *record)
751da177e4SLinus Torvalds {
761da177e4SLinus Torvalds 	int unknown = 0;
77abe48101SGeert Uytterhoeven 	const void *data = record->data;
781da177e4SLinus Torvalds 
79abe48101SGeert Uytterhoeven 	switch (be16_to_cpu(record->tag)) {
801da177e4SLinus Torvalds 	case BI_HP300_MODEL:
81abe48101SGeert Uytterhoeven 		hp300_model = be32_to_cpup(data);
821da177e4SLinus Torvalds 		break;
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds 	case BI_HP300_UART_SCODE:
85abe48101SGeert Uytterhoeven 		hp300_uart_scode = be32_to_cpup(data);
861da177e4SLinus Torvalds 		break;
871da177e4SLinus Torvalds 
881da177e4SLinus Torvalds 	case BI_HP300_UART_ADDR:
891da177e4SLinus Torvalds 		/* serial port address: ignored here */
901da177e4SLinus Torvalds 		break;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	default:
931da177e4SLinus Torvalds 		unknown = 1;
941da177e4SLinus Torvalds 	}
951da177e4SLinus Torvalds 
961da177e4SLinus Torvalds 	return unknown;
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds 
991da177e4SLinus Torvalds #ifdef CONFIG_HEARTBEAT
hp300_pulse(int x)1001da177e4SLinus Torvalds static void hp300_pulse(int x)
1011da177e4SLinus Torvalds {
1021da177e4SLinus Torvalds 	if (x)
1031da177e4SLinus Torvalds 		blinken_leds(0x10, 0);
1041da177e4SLinus Torvalds 	else
1051da177e4SLinus Torvalds 		blinken_leds(0, 0x10);
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds #endif
1081da177e4SLinus Torvalds 
hp300_get_model(char * model)1091da177e4SLinus Torvalds static void hp300_get_model(char *model)
1101da177e4SLinus Torvalds {
1111da177e4SLinus Torvalds 	strcpy(model, hp300_model_name);
1121da177e4SLinus Torvalds }
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds #define RTCBASE			0xf0420000
1151da177e4SLinus Torvalds #define RTC_DATA		0x1
1161da177e4SLinus Torvalds #define RTC_CMD			0x3
1171da177e4SLinus Torvalds 
1181da177e4SLinus Torvalds #define	RTC_BUSY		0x02
1191da177e4SLinus Torvalds #define	RTC_DATA_RDY		0x01
1201da177e4SLinus Torvalds 
1211da177e4SLinus Torvalds #define rtc_busy()		(in_8(RTCBASE + RTC_CMD) & RTC_BUSY)
1221da177e4SLinus Torvalds #define rtc_data_available()	(in_8(RTCBASE + RTC_CMD) & RTC_DATA_RDY)
1231da177e4SLinus Torvalds #define rtc_status()		(in_8(RTCBASE + RTC_CMD))
1241da177e4SLinus Torvalds #define rtc_command(x)		out_8(RTCBASE + RTC_CMD, (x))
1251da177e4SLinus Torvalds #define rtc_read_data()		(in_8(RTCBASE + RTC_DATA))
1261da177e4SLinus Torvalds #define rtc_write_data(x)	out_8(RTCBASE + RTC_DATA, (x))
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds #define RTC_SETREG	0xe0
1291da177e4SLinus Torvalds #define RTC_WRITEREG	0xc2
1301da177e4SLinus Torvalds #define RTC_READREG	0xc3
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds #define RTC_REG_SEC2	0
1331da177e4SLinus Torvalds #define RTC_REG_SEC1	1
1341da177e4SLinus Torvalds #define RTC_REG_MIN2	2
1351da177e4SLinus Torvalds #define RTC_REG_MIN1	3
1361da177e4SLinus Torvalds #define RTC_REG_HOUR2	4
1371da177e4SLinus Torvalds #define RTC_REG_HOUR1	5
1381da177e4SLinus Torvalds #define RTC_REG_WDAY	6
1391da177e4SLinus Torvalds #define RTC_REG_DAY2	7
1401da177e4SLinus Torvalds #define RTC_REG_DAY1	8
1411da177e4SLinus Torvalds #define RTC_REG_MON2	9
1421da177e4SLinus Torvalds #define RTC_REG_MON1	10
1431da177e4SLinus Torvalds #define RTC_REG_YEAR2	11
1441da177e4SLinus Torvalds #define RTC_REG_YEAR1	12
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds #define RTC_HOUR1_24HMODE 0x8
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds #define RTC_STAT_MASK	0xf0
1491da177e4SLinus Torvalds #define RTC_STAT_RDY	0x40
1501da177e4SLinus Torvalds 
hp300_rtc_read(unsigned char reg)1511da177e4SLinus Torvalds static inline unsigned char hp300_rtc_read(unsigned char reg)
1521da177e4SLinus Torvalds {
1531da177e4SLinus Torvalds 	unsigned char s, ret;
1541da177e4SLinus Torvalds 	unsigned long flags;
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 	local_irq_save(flags);
1571da177e4SLinus Torvalds 
1581da177e4SLinus Torvalds 	while (rtc_busy());
1591da177e4SLinus Torvalds 	rtc_command(RTC_SETREG);
1601da177e4SLinus Torvalds 	while (rtc_busy());
1611da177e4SLinus Torvalds 	rtc_write_data(reg);
1621da177e4SLinus Torvalds 	while (rtc_busy());
1631da177e4SLinus Torvalds 	rtc_command(RTC_READREG);
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds 	do {
1661da177e4SLinus Torvalds 		while (!rtc_data_available());
1671da177e4SLinus Torvalds 		s = rtc_status();
1681da177e4SLinus Torvalds 		ret = rtc_read_data();
1691da177e4SLinus Torvalds 	} while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
1701da177e4SLinus Torvalds 
1711da177e4SLinus Torvalds 	local_irq_restore(flags);
1721da177e4SLinus Torvalds 
1731da177e4SLinus Torvalds 	return ret;
1741da177e4SLinus Torvalds }
1751da177e4SLinus Torvalds 
hp300_rtc_write(unsigned char reg,unsigned char val)1761da177e4SLinus Torvalds static inline unsigned char hp300_rtc_write(unsigned char reg,
1771da177e4SLinus Torvalds 					    unsigned char val)
1781da177e4SLinus Torvalds {
1791da177e4SLinus Torvalds 	unsigned char s, ret;
1801da177e4SLinus Torvalds 	unsigned long flags;
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds 	local_irq_save(flags);
1831da177e4SLinus Torvalds 
1841da177e4SLinus Torvalds 	while (rtc_busy());
1851da177e4SLinus Torvalds 	rtc_command(RTC_SETREG);
1861da177e4SLinus Torvalds 	while (rtc_busy());
1871da177e4SLinus Torvalds 	rtc_write_data((val << 4) | reg);
1881da177e4SLinus Torvalds 	while (rtc_busy());
1891da177e4SLinus Torvalds 	rtc_command(RTC_WRITEREG);
1901da177e4SLinus Torvalds 	while (rtc_busy());
1911da177e4SLinus Torvalds 	rtc_command(RTC_READREG);
1921da177e4SLinus Torvalds 
1931da177e4SLinus Torvalds 	do {
1941da177e4SLinus Torvalds 		while (!rtc_data_available());
1951da177e4SLinus Torvalds 		s = rtc_status();
1961da177e4SLinus Torvalds 		ret = rtc_read_data();
1971da177e4SLinus Torvalds 	} while ((s & RTC_STAT_MASK) != RTC_STAT_RDY);
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds 	local_irq_restore(flags);
2001da177e4SLinus Torvalds 
2011da177e4SLinus Torvalds 	return ret;
2021da177e4SLinus Torvalds }
2031da177e4SLinus Torvalds 
hp300_hwclk(int op,struct rtc_time * t)2041da177e4SLinus Torvalds static int hp300_hwclk(int op, struct rtc_time *t)
2051da177e4SLinus Torvalds {
2061da177e4SLinus Torvalds 	if (!op) { /* read */
2071da177e4SLinus Torvalds 		t->tm_sec  = hp300_rtc_read(RTC_REG_SEC1) * 10 +
2081da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_SEC2);
2091da177e4SLinus Torvalds 		t->tm_min  = hp300_rtc_read(RTC_REG_MIN1) * 10 +
2101da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_MIN2);
2111da177e4SLinus Torvalds 		t->tm_hour = (hp300_rtc_read(RTC_REG_HOUR1) & 3) * 10 +
2121da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_HOUR2);
2131da177e4SLinus Torvalds 		t->tm_wday = -1;
2141da177e4SLinus Torvalds 		t->tm_mday = hp300_rtc_read(RTC_REG_DAY1) * 10 +
2151da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_DAY2);
2161da177e4SLinus Torvalds 		t->tm_mon  = hp300_rtc_read(RTC_REG_MON1) * 10 +
2171da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_MON2) - 1;
2181da177e4SLinus Torvalds 		t->tm_year = hp300_rtc_read(RTC_REG_YEAR1) * 10 +
2191da177e4SLinus Torvalds 			hp300_rtc_read(RTC_REG_YEAR2);
2201da177e4SLinus Torvalds 		if (t->tm_year <= 69)
2211da177e4SLinus Torvalds 			t->tm_year += 100;
2221da177e4SLinus Torvalds 	} else {
2231da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_SEC1, t->tm_sec / 10);
2241da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_SEC2, t->tm_sec % 10);
2251da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_MIN1, t->tm_min / 10);
2261da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_MIN2, t->tm_min % 10);
2271da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_HOUR1,
2281da177e4SLinus Torvalds 				((t->tm_hour / 10) & 3) | RTC_HOUR1_24HMODE);
2291da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_HOUR2, t->tm_hour % 10);
2301da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_DAY1, t->tm_mday / 10);
2311da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_DAY2, t->tm_mday % 10);
2321da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_MON1, (t->tm_mon + 1) / 10);
2331da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_MON2, (t->tm_mon + 1) % 10);
2341da177e4SLinus Torvalds 		if (t->tm_year >= 100)
2351da177e4SLinus Torvalds 			t->tm_year -= 100;
2361da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_YEAR1, t->tm_year / 10);
2371da177e4SLinus Torvalds 		hp300_rtc_write(RTC_REG_YEAR2, t->tm_year % 10);
2381da177e4SLinus Torvalds 	}
2391da177e4SLinus Torvalds 
2401da177e4SLinus Torvalds 	return 0;
2411da177e4SLinus Torvalds }
2421da177e4SLinus Torvalds 
hp300_init_IRQ(void)24335353bb8SRoman Zippel static void __init hp300_init_IRQ(void)
24435353bb8SRoman Zippel {
24535353bb8SRoman Zippel }
24635353bb8SRoman Zippel 
config_hp300(void)2471da177e4SLinus Torvalds void __init config_hp300(void)
2481da177e4SLinus Torvalds {
2491da177e4SLinus Torvalds 	mach_sched_init      = hp300_sched_init;
2501da177e4SLinus Torvalds 	mach_init_IRQ        = hp300_init_IRQ;
2511da177e4SLinus Torvalds 	mach_get_model       = hp300_get_model;
2521da177e4SLinus Torvalds 	mach_hwclk	     = hp300_hwclk;
2531da177e4SLinus Torvalds 	mach_reset           = hp300_reset;
2541da177e4SLinus Torvalds #ifdef CONFIG_HEARTBEAT
2551da177e4SLinus Torvalds 	mach_heartbeat       = hp300_pulse;
2561da177e4SLinus Torvalds #endif
2571da177e4SLinus Torvalds 
258e8d6dc5aSFabian Frederick 	if (hp300_model >= HP_330 && hp300_model <= HP_433S &&
259e8d6dc5aSFabian Frederick 	    hp300_model != HP_350) {
260e8d6dc5aSFabian Frederick 		pr_info("Detected HP9000 model %s\n",
261e8d6dc5aSFabian Frederick 			hp300_models[hp300_model-HP_320]);
2621da177e4SLinus Torvalds 		strcat(hp300_model_name, hp300_models[hp300_model-HP_320]);
263e8d6dc5aSFabian Frederick 	} else {
2641da177e4SLinus Torvalds 		panic("Unknown HP9000 Model");
2651da177e4SLinus Torvalds 	}
2661da177e4SLinus Torvalds #ifdef CONFIG_SERIAL_8250_CONSOLE
2671da177e4SLinus Torvalds 	hp300_setup_serial_console();
2681da177e4SLinus Torvalds #endif
2691da177e4SLinus Torvalds }
270