aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2005-04-22 00:42:34 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-04-22 00:42:34 -0400
commitb4bca26c0160f48b4eb04f21d31a229832732013 (patch)
treeb4a6d736fcb8664753066df3e6a93ed24c0f409b
parentd7be828e03969ea7f922f299acb8daa0d8ce7006 (diff)
[SPARC]: Provide generic ioctls in Sparc RTC driver.
Provide support for drivers/char/rtc.c ioctls in the Mostek rtc driver as well as the Sparc specific RTCGET and RTCSET. This allows userspace to be much less messy. Currently util-linux and other spots jump through hoops trying various ioctl variants until it hits the right one whatever driver actually being used supports. Eventually all of this should move over to the genrtc.c driver, but not today... While we are here, fix up the register types for sparse. Thanks to Frans Pop for helping point out this issue. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--arch/sparc64/kernel/time.c37
-rw-r--r--drivers/sbus/char/rtc.c103
-rw-r--r--include/asm-sparc64/mostek.h6
3 files changed, 123 insertions, 23 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 6a717d4d2bc5..c60785c046be 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -48,7 +48,7 @@
48 48
49DEFINE_SPINLOCK(mostek_lock); 49DEFINE_SPINLOCK(mostek_lock);
50DEFINE_SPINLOCK(rtc_lock); 50DEFINE_SPINLOCK(rtc_lock);
51unsigned long mstk48t02_regs = 0UL; 51void * __iomem mstk48t02_regs = 0UL;
52#ifdef CONFIG_PCI 52#ifdef CONFIG_PCI
53unsigned long ds1287_regs = 0UL; 53unsigned long ds1287_regs = 0UL;
54#endif 54#endif
@@ -59,8 +59,8 @@ u64 jiffies_64 = INITIAL_JIFFIES;
59 59
60EXPORT_SYMBOL(jiffies_64); 60EXPORT_SYMBOL(jiffies_64);
61 61
62static unsigned long mstk48t08_regs = 0UL; 62static void * __iomem mstk48t08_regs;
63static unsigned long mstk48t59_regs = 0UL; 63static void * __iomem mstk48t59_regs;
64 64
65static int set_rtc_mmss(unsigned long); 65static int set_rtc_mmss(unsigned long);
66 66
@@ -520,7 +520,7 @@ void timer_tick_interrupt(struct pt_regs *regs)
520/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ 520/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
521static void __init kick_start_clock(void) 521static void __init kick_start_clock(void)
522{ 522{
523 unsigned long regs = mstk48t02_regs; 523 void * __iomem regs = mstk48t02_regs;
524 u8 sec, tmp; 524 u8 sec, tmp;
525 int i, count; 525 int i, count;
526 526
@@ -604,7 +604,7 @@ static void __init kick_start_clock(void)
604/* Return nonzero if the clock chip battery is low. */ 604/* Return nonzero if the clock chip battery is low. */
605static int __init has_low_battery(void) 605static int __init has_low_battery(void)
606{ 606{
607 unsigned long regs = mstk48t02_regs; 607 void * __iomem regs = mstk48t02_regs;
608 u8 data1, data2; 608 u8 data1, data2;
609 609
610 spin_lock_irq(&mostek_lock); 610 spin_lock_irq(&mostek_lock);
@@ -623,7 +623,7 @@ static int __init has_low_battery(void)
623static void __init set_system_time(void) 623static void __init set_system_time(void)
624{ 624{
625 unsigned int year, mon, day, hour, min, sec; 625 unsigned int year, mon, day, hour, min, sec;
626 unsigned long mregs = mstk48t02_regs; 626 void * __iomem mregs = mstk48t02_regs;
627#ifdef CONFIG_PCI 627#ifdef CONFIG_PCI
628 unsigned long dregs = ds1287_regs; 628 unsigned long dregs = ds1287_regs;
629#else 629#else
@@ -843,7 +843,8 @@ void __init clock_probe(void)
843 !strcmp(model, "m5823")) { 843 !strcmp(model, "m5823")) {
844 ds1287_regs = edev->resource[0].start; 844 ds1287_regs = edev->resource[0].start;
845 } else { 845 } else {
846 mstk48t59_regs = edev->resource[0].start; 846 mstk48t59_regs = (void * __iomem)
847 edev->resource[0].start;
847 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; 848 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
848 } 849 }
849 break; 850 break;
@@ -865,7 +866,8 @@ try_isa_clock:
865 !strcmp(model, "m5823")) { 866 !strcmp(model, "m5823")) {
866 ds1287_regs = isadev->resource.start; 867 ds1287_regs = isadev->resource.start;
867 } else { 868 } else {
868 mstk48t59_regs = isadev->resource.start; 869 mstk48t59_regs = (void * __iomem)
870 isadev->resource.start;
869 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; 871 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
870 } 872 }
871 break; 873 break;
@@ -893,21 +895,24 @@ try_isa_clock:
893 } 895 }
894 896
895 if(model[5] == '0' && model[6] == '2') { 897 if(model[5] == '0' && model[6] == '2') {
896 mstk48t02_regs = (((u64)clk_reg[0].phys_addr) | 898 mstk48t02_regs = (void * __iomem)
897 (((u64)clk_reg[0].which_io)<<32UL)); 899 (((u64)clk_reg[0].phys_addr) |
900 (((u64)clk_reg[0].which_io)<<32UL));
898 } else if(model[5] == '0' && model[6] == '8') { 901 } else if(model[5] == '0' && model[6] == '8') {
899 mstk48t08_regs = (((u64)clk_reg[0].phys_addr) | 902 mstk48t08_regs = (void * __iomem)
900 (((u64)clk_reg[0].which_io)<<32UL)); 903 (((u64)clk_reg[0].phys_addr) |
904 (((u64)clk_reg[0].which_io)<<32UL));
901 mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; 905 mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
902 } else { 906 } else {
903 mstk48t59_regs = (((u64)clk_reg[0].phys_addr) | 907 mstk48t59_regs = (void * __iomem)
904 (((u64)clk_reg[0].which_io)<<32UL)); 908 (((u64)clk_reg[0].phys_addr) |
909 (((u64)clk_reg[0].which_io)<<32UL));
905 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; 910 mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
906 } 911 }
907 break; 912 break;
908 } 913 }
909 914
910 if (mstk48t02_regs != 0UL) { 915 if (mstk48t02_regs != NULL) {
911 /* Report a low battery voltage condition. */ 916 /* Report a low battery voltage condition. */
912 if (has_low_battery()) 917 if (has_low_battery())
913 prom_printf("NVRAM: Low battery voltage!\n"); 918 prom_printf("NVRAM: Low battery voltage!\n");
@@ -1087,7 +1092,7 @@ unsigned long long sched_clock(void)
1087static int set_rtc_mmss(unsigned long nowtime) 1092static int set_rtc_mmss(unsigned long nowtime)
1088{ 1093{
1089 int real_seconds, real_minutes, chip_minutes; 1094 int real_seconds, real_minutes, chip_minutes;
1090 unsigned long mregs = mstk48t02_regs; 1095 void * __iomem mregs = mstk48t02_regs;
1091#ifdef CONFIG_PCI 1096#ifdef CONFIG_PCI
1092 unsigned long dregs = ds1287_regs; 1097 unsigned long dregs = ds1287_regs;
1093#else 1098#else
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c
index bf3273eb1c8b..49d1cd99d5ac 100644
--- a/drivers/sbus/char/rtc.c
+++ b/drivers/sbus/char/rtc.c
@@ -28,6 +28,42 @@
28 28
29static int rtc_busy = 0; 29static int rtc_busy = 0;
30 30
31/* This is the structure layout used by drivers/char/rtc.c, we
32 * support that driver's ioctls so that things are less messy in
33 * userspace.
34 */
35struct rtc_time_generic {
36 int tm_sec;
37 int tm_min;
38 int tm_hour;
39 int tm_mday;
40 int tm_mon;
41 int tm_year;
42 int tm_wday;
43 int tm_yday;
44 int tm_isdst;
45};
46#define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */
47#define RTC_AIE_OFF _IO('p', 0x02) /* ... off */
48#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */
49#define RTC_UIE_OFF _IO('p', 0x04) /* ... off */
50#define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */
51#define RTC_PIE_OFF _IO('p', 0x06) /* ... off */
52#define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */
53#define RTC_WIE_OFF _IO('p', 0x10) /* ... off */
54#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */
55#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */
56#define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */
57#define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */
58#define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */
59#define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */
60#define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */
61#define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */
62#define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/
63#define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/
64#define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
65#define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
66
31/* Retrieve the current date and time from the real time clock. */ 67/* Retrieve the current date and time from the real time clock. */
32static void get_rtc_time(struct rtc_time *t) 68static void get_rtc_time(struct rtc_time *t)
33{ 69{
@@ -82,29 +118,87 @@ void set_rtc_time(struct rtc_time *t)
82 spin_unlock_irq(&mostek_lock); 118 spin_unlock_irq(&mostek_lock);
83} 119}
84 120
121static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm)
122{
123 struct rtc_time_generic __user *utm = argp;
124
125 if (__put_user(tm->sec, &utm->tm_sec) ||
126 __put_user(tm->min, &utm->tm_min) ||
127 __put_user(tm->hour, &utm->tm_hour) ||
128 __put_user(tm->dom, &utm->tm_mday) ||
129 __put_user(tm->month, &utm->tm_mon) ||
130 __put_user(tm->year, &utm->tm_year) ||
131 __put_user(tm->dow, &utm->tm_wday) ||
132 __put_user(0, &utm->tm_yday) ||
133 __put_user(0, &utm->tm_isdst))
134 return -EFAULT;
135
136 return 0;
137}
138
139static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp)
140{
141 struct rtc_time_generic __user *utm = argp;
142
143 if (__get_user(tm->sec, &utm->tm_sec) ||
144 __get_user(tm->min, &utm->tm_min) ||
145 __get_user(tm->hour, &utm->tm_hour) ||
146 __get_user(tm->dom, &utm->tm_mday) ||
147 __get_user(tm->month, &utm->tm_mon) ||
148 __get_user(tm->year, &utm->tm_year) ||
149 __get_user(tm->dow, &utm->tm_wday))
150 return -EFAULT;
151
152 return 0;
153}
154
85static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 155static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
86 unsigned long arg) 156 unsigned long arg)
87{ 157{
88 struct rtc_time rtc_tm; 158 struct rtc_time rtc_tm;
89 void __user *argp = (void __user *)arg; 159 void __user *argp = (void __user *)arg;
90 160
91 switch (cmd) 161 switch (cmd) {
92 { 162 /* No interrupt support, return an error
163 * compatible with drivers/char/rtc.c
164 */
165 case RTC_AIE_OFF:
166 case RTC_AIE_ON:
167 case RTC_PIE_OFF:
168 case RTC_PIE_ON:
169 case RTC_UIE_OFF:
170 case RTC_UIE_ON:
171 case RTC_IRQP_READ:
172 case RTC_IRQP_SET:
173 case RTC_EPOCH_SET:
174 case RTC_EPOCH_READ:
175 return -EINVAL;
176
93 case RTCGET: 177 case RTCGET:
178 case RTC_RD_TIME:
94 memset(&rtc_tm, 0, sizeof(struct rtc_time)); 179 memset(&rtc_tm, 0, sizeof(struct rtc_time));
95 get_rtc_time(&rtc_tm); 180 get_rtc_time(&rtc_tm);
96 181
97 if (copy_to_user(argp, &rtc_tm, sizeof(struct rtc_time))) 182 if (cmd == RTCGET) {
183 if (copy_to_user(argp, &rtc_tm,
184 sizeof(struct rtc_time)))
185 return -EFAULT;
186 } else if (put_rtc_time_generic(argp, &rtc_tm))
98 return -EFAULT; 187 return -EFAULT;
99 188
100 return 0; 189 return 0;
101 190
102 191
103 case RTCSET: 192 case RTCSET:
193 case RTC_SET_TIME:
104 if (!capable(CAP_SYS_TIME)) 194 if (!capable(CAP_SYS_TIME))
105 return -EPERM; 195 return -EPERM;
106 196
107 if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time))) 197 if (cmd == RTCSET) {
198 if (copy_from_user(&rtc_tm, argp,
199 sizeof(struct rtc_time)))
200 return -EFAULT;
201 } else if (get_rtc_time_generic(&rtc_tm, argp))
108 return -EFAULT; 202 return -EFAULT;
109 203
110 set_rtc_time(&rtc_tm); 204 set_rtc_time(&rtc_tm);
@@ -164,6 +258,7 @@ static int __init rtc_sun_init(void)
164 printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); 258 printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n");
165 return error; 259 return error;
166 } 260 }
261 printk("rtc_sun_init: Registered Mostek RTC driver.\n");
167 262
168 return 0; 263 return 0;
169} 264}
diff --git a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
index ccf2f5f82d7f..1f9b1356a48e 100644
--- a/include/asm-sparc64/mostek.h
+++ b/include/asm-sparc64/mostek.h
@@ -38,7 +38,7 @@
38 * 38 *
39 * We now deal with physical addresses for I/O to the chip. -DaveM 39 * We now deal with physical addresses for I/O to the chip. -DaveM
40 */ 40 */
41static __inline__ u8 mostek_read(unsigned long addr) 41static __inline__ u8 mostek_read(void * __iomem addr)
42{ 42{
43 u8 ret; 43 u8 ret;
44 44
@@ -48,7 +48,7 @@ static __inline__ u8 mostek_read(unsigned long addr)
48 return ret; 48 return ret;
49} 49}
50 50
51static __inline__ void mostek_write(unsigned long addr, u8 val) 51static __inline__ void mostek_write(void * __iomem addr, u8 val)
52{ 52{
53 __asm__ __volatile__("stba %0, [%1] %2" 53 __asm__ __volatile__("stba %0, [%1] %2"
54 : /* no outputs */ 54 : /* no outputs */
@@ -67,7 +67,7 @@ static __inline__ void mostek_write(unsigned long addr, u8 val)
67#define MOSTEK_YEAR 0x07ffUL 67#define MOSTEK_YEAR 0x07ffUL
68 68
69extern spinlock_t mostek_lock; 69extern spinlock_t mostek_lock;
70extern unsigned long mstk48t02_regs; 70extern void *__iomem mstk48t02_regs;
71 71
72/* Control register values. */ 72/* Control register values. */
73#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ 73#define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */