diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index ab4affa..3283a30 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -9,3 +9,4 @@ obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \ obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o obj-$(CONFIG_PCI) += ip27-irq-pci.o obj-$(CONFIG_SMP) += ip27-smp.o +obj-$(CONFIG_RTC_DRV_M48T35) += ip27-rtc.o diff --git a/arch/mips/sgi-ip27/ip27-rtc.c b/arch/mips/sgi-ip27/ip27-rtc.c new file mode 100644 index 0000000..b14b026 --- /dev/null +++ b/arch/mips/sgi-ip27/ip27-rtc.c @@ -0,0 +1,143 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * ip27-rtc.c: RTC submodule for IOC3 metadriver for IP27. + * + * Copyright (C) 2014 Joshua Kinard + * + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * On IP27, the RTC is hidden behind the IOC3 device, attached to a generic + * ByteBus. Use klconfig routines to safely map to the start address of the + * RTC area in ByteBus DEV0. + */ +#define IP27_RTC_RES_START (XPHYSADDR( \ + KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base \ + + IOC3_BYTEBUS_DEV0)) +#define IP27_RTC_RES_END (IP27_RTC_RES_START + 32767) + +static struct ioc3_driver_data *ioc3; +static struct resource ip27_rtc_resources[1]; +static int ip27_rtc_probed = 0; + +/** + * ip27_rtc_read - read a value from an rtc register. + * @rtc: pointer to the m48t35 rtc structure. + * @reg: the register address to read. + */ +u8 +ip27_rtc_read(struct m48t35_priv *rtc, int reg) +{ + return readb(((u8 __iomem *)(((u64)(rtc->regs + reg)) ^ 3))); +} + +/** + * ip27_rtc_write - write a value to an rtc register. + * @rtc: pointer to the m48t35 rtc structure. + * @reg: the register address to write. + * @value: value to write to the register. + */ +void +ip27_rtc_write(struct m48t35_priv *rtc, int reg, u8 value) +{ + writeb(value, ((u8 __iomem *)(((u64)(rtc->regs + reg)) ^ 3))); +} + +static struct m48t35_rtc_platform_data +ip27_rtc_platform_data[] = { + { + /* + * XXX: set req_mem_region to true after ioc3 resource + * conflicts are resolved. + */ + .req_mem_region = false, + .plat_read = ip27_rtc_read, + .plat_write = ip27_rtc_write, + }, +}; + +static struct platform_device +ip27_rtc_device = { + .name = "rtc-m48t35", + .id = -1, + .dev = { + .platform_data = ip27_rtc_platform_data, + }, + .num_resources = ARRAY_SIZE(ip27_rtc_resources), + .resource = ip27_rtc_resources, +}; + + +/* IOC3 Metadriver probe/remove */ +static int +ip27_ioc3_rtc_probe(struct ioc3_submodule *is, struct ioc3_driver_data *idd) +{ + int ret; + + /* This code only applies to an Origin/Onyx2 */ + if (ioc3 || (idd->class != IOC3_CLASS_BASE_IP27)) + return 1; + + ioc3 = idd; + + if (ip27_rtc_probed) + return 0; + + ip27_rtc_resources[0].start = IP27_RTC_RES_START, + ip27_rtc_resources[0].end = IP27_RTC_RES_END, + ip27_rtc_resources[0].flags = IORESOURCE_MEM, + + ret = platform_device_register(&ip27_rtc_device); + ip27_rtc_probed = 1; + + return ret; +} + + +static int +ip27_ioc3_rtc_remove(struct ioc3_submodule *is, struct ioc3_driver_data *idd) +{ + if (ioc3 != idd) + return 1; + + platform_device_unregister(&ip27_rtc_device); + ioc3 = NULL; + + return 0; +} + + +/* entry/exit functions */ +static struct ioc3_submodule +ip27_ioc3_rtc_submodule = { + .name = "rtc", + .probe = ip27_ioc3_rtc_probe, + .remove = ip27_ioc3_rtc_remove, + .owner = THIS_MODULE, +}; + +ioc3_submodule_driver(ip27_ioc3_rtc_submodule); + +MODULE_AUTHOR("Joshua Kinard "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IP27 RTC Submodule for IOC3"); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 42d6cb9..864db4f 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -213,23 +213,3 @@ void hub_rtc_init(cnodeid_t cnode) LOCAL_HUB_S(PI_RT_PEND_B, 0); } } - -static int __init sgi_ip27_rtc_devinit(void) -{ - struct resource res; - - memset(&res, 0, sizeof(res)); - res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + - IOC3_BYTEBUS_DEV0); - res.end = res.start + 32767; - res.flags = IORESOURCE_MEM; - - return IS_ERR(platform_device_register_simple("rtc-m48t35", -1, - &res, 1)); -} - -/* - * kludge make this a device_initcall after ioc3 resource conflicts - * are resolved - */ -late_initcall(sgi_ip27_rtc_devinit);