1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2008 4 * Gururaja Hebbar gururajakr@sanyo.co.in 5 * 6 * reference linux-2.6.20.6/drivers/rtc/rtc-pl031.c 7 */ 8 9 #include <common.h> 10 #include <command.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <rtc.h> 14 #include <asm/io.h> 15 #include <asm/types.h> 16 17 /* 18 * Register definitions 19 */ 20 #define RTC_DR 0x00 /* Data read register */ 21 #define RTC_MR 0x04 /* Match register */ 22 #define RTC_LR 0x08 /* Data load register */ 23 #define RTC_CR 0x0c /* Control register */ 24 #define RTC_IMSC 0x10 /* Interrupt mask and set register */ 25 #define RTC_RIS 0x14 /* Raw interrupt status register */ 26 #define RTC_MIS 0x18 /* Masked interrupt status register */ 27 #define RTC_ICR 0x1c /* Interrupt clear register */ 28 29 #define RTC_CR_START (1 << 0) 30 31 struct pl031_platdata { 32 phys_addr_t base; 33 }; 34 35 static inline u32 pl031_read_reg(struct udevice *dev, int reg) 36 { 37 struct pl031_platdata *pdata = dev_get_platdata(dev); 38 39 return readl(pdata->base + reg); 40 } 41 42 static inline u32 pl031_write_reg(struct udevice *dev, int reg, u32 value) 43 { 44 struct pl031_platdata *pdata = dev_get_platdata(dev); 45 46 return writel(value, pdata->base + reg); 47 } 48 49 /* 50 * Probe RTC device 51 */ 52 static int pl031_probe(struct udevice *dev) 53 { 54 /* Enable RTC Start in Control register*/ 55 pl031_write_reg(dev, RTC_CR, RTC_CR_START); 56 57 return 0; 58 } 59 60 /* 61 * Get the current time from the RTC 62 */ 63 static int pl031_get(struct udevice *dev, struct rtc_time *tm) 64 { 65 unsigned long tim; 66 67 if (!tm) 68 return -EINVAL; 69 70 tim = pl031_read_reg(dev, RTC_DR); 71 72 rtc_to_tm(tim, tm); 73 74 debug("Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 75 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, 76 tm->tm_hour, tm->tm_min, tm->tm_sec); 77 78 return 0; 79 } 80 81 /* 82 * Set the RTC 83 */ 84 static int pl031_set(struct udevice *dev, const struct rtc_time *tm) 85 { 86 unsigned long tim; 87 88 if (!tm) 89 return -EINVAL; 90 91 debug("Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", 92 tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_wday, 93 tm->tm_hour, tm->tm_min, tm->tm_sec); 94 95 /* Calculate number of seconds this incoming time represents */ 96 tim = rtc_mktime(tm); 97 98 pl031_write_reg(dev, RTC_LR, tim); 99 100 return 0; 101 } 102 103 /* 104 * Reset the RTC. We set the date back to 1970-01-01. 105 */ 106 static int pl031_reset(struct udevice *dev) 107 { 108 pl031_write_reg(dev, RTC_LR, 0); 109 110 return 0; 111 } 112 113 static const struct rtc_ops pl031_ops = { 114 .get = pl031_get, 115 .set = pl031_set, 116 .reset = pl031_reset, 117 }; 118 119 static const struct udevice_id pl031_ids[] = { 120 { .compatible = "arm,pl031" }, 121 { } 122 }; 123 124 static int pl031_ofdata_to_platdata(struct udevice *dev) 125 { 126 struct pl031_platdata *pdata = dev_get_platdata(dev); 127 128 pdata->base = dev_read_addr(dev); 129 130 return 0; 131 } 132 133 U_BOOT_DRIVER(rtc_pl031) = { 134 .name = "rtc-pl031", 135 .id = UCLASS_RTC, 136 .of_match = pl031_ids, 137 .probe = pl031_probe, 138 .ofdata_to_platdata = pl031_ofdata_to_platdata, 139 .platdata_auto_alloc_size = sizeof(struct pl031_platdata), 140 .ops = &pl031_ops, 141 }; 142