]>
git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/rtc/m41t94.c
2 * Driver for ST M41T94 SPI RTC
4 * Taken from the Linux kernel drivier:
5 * Copyright (C) 2008 Kim B. Heino
7 * Adaptation for U-Boot:
9 * Albin Tonnerre, Free Electrons <albin.tonnerre@free-electrons.com>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
20 static struct spi_slave
*slave
;
22 #define M41T94_REG_SECONDS 0x01
23 #define M41T94_REG_MINUTES 0x02
24 #define M41T94_REG_HOURS 0x03
25 #define M41T94_REG_WDAY 0x04
26 #define M41T94_REG_DAY 0x05
27 #define M41T94_REG_MONTH 0x06
28 #define M41T94_REG_YEAR 0x07
29 #define M41T94_REG_HT 0x0c
31 #define M41T94_BIT_HALT 0x40
32 #define M41T94_BIT_STOP 0x80
33 #define M41T94_BIT_CB 0x40
34 #define M41T94_BIT_CEB 0x80
36 int rtc_set(struct rtc_time
*tm
)
38 u8 buf
[8]; /* write cmd + 7 registers */
42 slave
= spi_setup_slave(CONFIG_M41T94_SPI_BUS
,
43 CONFIG_M41T94_SPI_CS
, 1000000,
50 buf
[0] = 0x80 | M41T94_REG_SECONDS
; /* write time + date */
51 buf
[M41T94_REG_SECONDS
] = bin2bcd(tm
->tm_sec
);
52 buf
[M41T94_REG_MINUTES
] = bin2bcd(tm
->tm_min
);
53 buf
[M41T94_REG_HOURS
] = bin2bcd(tm
->tm_hour
);
54 buf
[M41T94_REG_WDAY
] = bin2bcd(tm
->tm_wday
+ 1);
55 buf
[M41T94_REG_DAY
] = bin2bcd(tm
->tm_mday
);
56 buf
[M41T94_REG_MONTH
] = bin2bcd(tm
->tm_mon
+ 1);
58 buf
[M41T94_REG_HOURS
] |= M41T94_BIT_CEB
;
59 if (tm
->tm_year
>= 100)
60 buf
[M41T94_REG_HOURS
] |= M41T94_BIT_CB
;
61 buf
[M41T94_REG_YEAR
] = bin2bcd(tm
->tm_year
% 100);
63 ret
= spi_xfer(slave
, 64, buf
, NULL
, SPI_XFER_BEGIN
| SPI_XFER_END
);
64 spi_release_bus(slave
);
68 int rtc_get(struct rtc_time
*tm
)
74 slave
= spi_setup_slave(CONFIG_M41T94_SPI_BUS
,
75 CONFIG_M41T94_SPI_CS
, 1000000,
82 /* clear halt update bit */
83 ret
= spi_w8r8(slave
, M41T94_REG_HT
);
86 if (ret
& M41T94_BIT_HALT
) {
87 buf
[0] = 0x80 | M41T94_REG_HT
;
88 buf
[1] = ret
& ~M41T94_BIT_HALT
;
89 spi_xfer(slave
, 16, buf
, NULL
, SPI_XFER_BEGIN
| SPI_XFER_END
);
93 ret
= spi_w8r8(slave
, M41T94_REG_SECONDS
);
96 if (ret
& M41T94_BIT_STOP
) {
97 buf
[0] = 0x80 | M41T94_REG_SECONDS
;
98 buf
[1] = ret
& ~M41T94_BIT_STOP
;
99 spi_xfer(slave
, 16, buf
, NULL
, SPI_XFER_BEGIN
| SPI_XFER_END
);
102 tm
->tm_sec
= bcd2bin(spi_w8r8(slave
, M41T94_REG_SECONDS
));
103 tm
->tm_min
= bcd2bin(spi_w8r8(slave
, M41T94_REG_MINUTES
));
104 hour
= spi_w8r8(slave
, M41T94_REG_HOURS
);
105 tm
->tm_hour
= bcd2bin(hour
& 0x3f);
106 tm
->tm_wday
= bcd2bin(spi_w8r8(slave
, M41T94_REG_WDAY
)) - 1;
107 tm
->tm_mday
= bcd2bin(spi_w8r8(slave
, M41T94_REG_DAY
));
108 tm
->tm_mon
= bcd2bin(spi_w8r8(slave
, M41T94_REG_MONTH
)) - 1;
109 tm
->tm_year
= bcd2bin(spi_w8r8(slave
, M41T94_REG_YEAR
));
110 if ((hour
& M41T94_BIT_CB
) || !(hour
& M41T94_BIT_CEB
))
113 spi_release_bus(slave
);
120 * Could not be tested as the reset pin is not wired on
121 * the sbc35-ag20 board