0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/module.h>
0014 #include <linux/rtc.h>
0015 #include <linux/slab.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/bcd.h>
0018 #include <linux/io.h>
0019 #include <linux/err.h>
0020
0021 struct m48t35_rtc {
0022 u8 pad[0x7ff8];
0023 #ifdef CONFIG_SGI_IP27
0024 u8 hour;
0025 u8 min;
0026 u8 sec;
0027 u8 control;
0028 u8 year;
0029 u8 month;
0030 u8 date;
0031 u8 day;
0032 #else
0033 u8 control;
0034 u8 sec;
0035 u8 min;
0036 u8 hour;
0037 u8 day;
0038 u8 date;
0039 u8 month;
0040 u8 year;
0041 #endif
0042 };
0043
0044 #define M48T35_RTC_SET 0x80
0045 #define M48T35_RTC_READ 0x40
0046
0047 struct m48t35_priv {
0048 struct rtc_device *rtc;
0049 struct m48t35_rtc __iomem *reg;
0050 size_t size;
0051 unsigned long baseaddr;
0052 spinlock_t lock;
0053 };
0054
0055 static int m48t35_read_time(struct device *dev, struct rtc_time *tm)
0056 {
0057 struct m48t35_priv *priv = dev_get_drvdata(dev);
0058 u8 control;
0059
0060
0061
0062
0063
0064
0065
0066 spin_lock_irq(&priv->lock);
0067 control = readb(&priv->reg->control);
0068 writeb(control | M48T35_RTC_READ, &priv->reg->control);
0069 tm->tm_sec = readb(&priv->reg->sec);
0070 tm->tm_min = readb(&priv->reg->min);
0071 tm->tm_hour = readb(&priv->reg->hour);
0072 tm->tm_mday = readb(&priv->reg->date);
0073 tm->tm_mon = readb(&priv->reg->month);
0074 tm->tm_year = readb(&priv->reg->year);
0075 writeb(control, &priv->reg->control);
0076 spin_unlock_irq(&priv->lock);
0077
0078 tm->tm_sec = bcd2bin(tm->tm_sec);
0079 tm->tm_min = bcd2bin(tm->tm_min);
0080 tm->tm_hour = bcd2bin(tm->tm_hour);
0081 tm->tm_mday = bcd2bin(tm->tm_mday);
0082 tm->tm_mon = bcd2bin(tm->tm_mon);
0083 tm->tm_year = bcd2bin(tm->tm_year);
0084
0085
0086
0087
0088
0089 tm->tm_year += 70;
0090 if (tm->tm_year <= 69)
0091 tm->tm_year += 100;
0092
0093 tm->tm_mon--;
0094 return 0;
0095 }
0096
0097 static int m48t35_set_time(struct device *dev, struct rtc_time *tm)
0098 {
0099 struct m48t35_priv *priv = dev_get_drvdata(dev);
0100 unsigned char mon, day, hrs, min, sec;
0101 unsigned int yrs;
0102 u8 control;
0103
0104 yrs = tm->tm_year + 1900;
0105 mon = tm->tm_mon + 1;
0106 day = tm->tm_mday;
0107 hrs = tm->tm_hour;
0108 min = tm->tm_min;
0109 sec = tm->tm_sec;
0110
0111 if (yrs < 1970)
0112 return -EINVAL;
0113
0114 yrs -= 1970;
0115 if (yrs > 255)
0116 return -EINVAL;
0117
0118 if (yrs > 169)
0119 return -EINVAL;
0120
0121 if (yrs >= 100)
0122 yrs -= 100;
0123
0124 sec = bin2bcd(sec);
0125 min = bin2bcd(min);
0126 hrs = bin2bcd(hrs);
0127 day = bin2bcd(day);
0128 mon = bin2bcd(mon);
0129 yrs = bin2bcd(yrs);
0130
0131 spin_lock_irq(&priv->lock);
0132 control = readb(&priv->reg->control);
0133 writeb(control | M48T35_RTC_SET, &priv->reg->control);
0134 writeb(yrs, &priv->reg->year);
0135 writeb(mon, &priv->reg->month);
0136 writeb(day, &priv->reg->date);
0137 writeb(hrs, &priv->reg->hour);
0138 writeb(min, &priv->reg->min);
0139 writeb(sec, &priv->reg->sec);
0140 writeb(control, &priv->reg->control);
0141 spin_unlock_irq(&priv->lock);
0142 return 0;
0143 }
0144
0145 static const struct rtc_class_ops m48t35_ops = {
0146 .read_time = m48t35_read_time,
0147 .set_time = m48t35_set_time,
0148 };
0149
0150 static int m48t35_probe(struct platform_device *pdev)
0151 {
0152 struct resource *res;
0153 struct m48t35_priv *priv;
0154
0155 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0156 if (!res)
0157 return -ENODEV;
0158 priv = devm_kzalloc(&pdev->dev, sizeof(struct m48t35_priv), GFP_KERNEL);
0159 if (!priv)
0160 return -ENOMEM;
0161
0162 priv->size = resource_size(res);
0163 if (!devm_request_mem_region(&pdev->dev, res->start, priv->size,
0164 pdev->name))
0165 return -EBUSY;
0166
0167 priv->baseaddr = res->start;
0168 priv->reg = devm_ioremap(&pdev->dev, priv->baseaddr, priv->size);
0169 if (!priv->reg)
0170 return -ENOMEM;
0171
0172 spin_lock_init(&priv->lock);
0173
0174 platform_set_drvdata(pdev, priv);
0175
0176 priv->rtc = devm_rtc_device_register(&pdev->dev, "m48t35",
0177 &m48t35_ops, THIS_MODULE);
0178 return PTR_ERR_OR_ZERO(priv->rtc);
0179 }
0180
0181 static struct platform_driver m48t35_platform_driver = {
0182 .driver = {
0183 .name = "rtc-m48t35",
0184 },
0185 .probe = m48t35_probe,
0186 };
0187
0188 module_platform_driver(m48t35_platform_driver);
0189
0190 MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
0191 MODULE_DESCRIPTION("M48T35 RTC driver");
0192 MODULE_LICENSE("GPL");
0193 MODULE_ALIAS("platform:rtc-m48t35");