~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/rtc/imxdi.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * (C) Copyright 2009-2012 ADVANSEE
 
3
 * Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
 
4
 *
 
5
 * Based on the Linux rtc-imxdi.c driver, which is:
 
6
 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
 
7
 * Copyright 2010 Orex Computed Radiography
 
8
 *
 
9
 * SPDX-License-Identifier:     GPL-2.0+
 
10
 */
 
11
 
 
12
/*
 
13
 * Date & Time support for Freescale i.MX DryIce RTC
 
14
 */
 
15
 
 
16
#include <common.h>
 
17
#include <command.h>
 
18
#include <linux/compat.h>
 
19
#include <rtc.h>
 
20
 
 
21
#if defined(CONFIG_CMD_DATE)
 
22
 
 
23
#include <asm/io.h>
 
24
#include <asm/arch/imx-regs.h>
 
25
 
 
26
/* DryIce Register Definitions */
 
27
 
 
28
struct imxdi_regs {
 
29
        u32 dtcmr;                      /* Time Counter MSB Reg */
 
30
        u32 dtclr;                      /* Time Counter LSB Reg */
 
31
        u32 dcamr;                      /* Clock Alarm MSB Reg */
 
32
        u32 dcalr;                      /* Clock Alarm LSB Reg */
 
33
        u32 dcr;                        /* Control Reg */
 
34
        u32 dsr;                        /* Status Reg */
 
35
        u32 dier;                       /* Interrupt Enable Reg */
 
36
};
 
37
 
 
38
#define DCAMR_UNSET     0xFFFFFFFF      /* doomsday - 1 sec */
 
39
 
 
40
#define DCR_TCE         (1 << 3)        /* Time Counter Enable */
 
41
 
 
42
#define DSR_WBF         (1 << 10)       /* Write Busy Flag */
 
43
#define DSR_WNF         (1 << 9)        /* Write Next Flag */
 
44
#define DSR_WCF         (1 << 8)        /* Write Complete Flag */
 
45
#define DSR_WEF         (1 << 7)        /* Write Error Flag */
 
46
#define DSR_CAF         (1 << 4)        /* Clock Alarm Flag */
 
47
#define DSR_NVF         (1 << 1)        /* Non-Valid Flag */
 
48
#define DSR_SVF         (1 << 0)        /* Security Violation Flag */
 
49
 
 
50
#define DIER_WNIE       (1 << 9)        /* Write Next Interrupt Enable */
 
51
#define DIER_WCIE       (1 << 8)        /* Write Complete Interrupt Enable */
 
52
#define DIER_WEIE       (1 << 7)        /* Write Error Interrupt Enable */
 
53
#define DIER_CAIE       (1 << 4)        /* Clock Alarm Interrupt Enable */
 
54
 
 
55
/* Driver Private Data */
 
56
 
 
57
struct imxdi_data {
 
58
        struct imxdi_regs __iomem       *regs;
 
59
        int                             init_done;
 
60
};
 
61
 
 
62
static struct imxdi_data data;
 
63
 
 
64
/*
 
65
 * This function attempts to clear the dryice write-error flag.
 
66
 *
 
67
 * A dryice write error is similar to a bus fault and should not occur in
 
68
 * normal operation.  Clearing the flag requires another write, so the root
 
69
 * cause of the problem may need to be fixed before the flag can be cleared.
 
70
 */
 
71
static void clear_write_error(void)
 
72
{
 
73
        int cnt;
 
74
 
 
75
        puts("### Warning: RTC - Register write error!\n");
 
76
 
 
77
        /* clear the write error flag */
 
78
        __raw_writel(DSR_WEF, &data.regs->dsr);
 
79
 
 
80
        /* wait for it to take effect */
 
81
        for (cnt = 0; cnt < 1000; cnt++) {
 
82
                if ((__raw_readl(&data.regs->dsr) & DSR_WEF) == 0)
 
83
                        return;
 
84
                udelay(10);
 
85
        }
 
86
        puts("### Error: RTC - Cannot clear write-error flag!\n");
 
87
}
 
88
 
 
89
/*
 
90
 * Write a dryice register and wait until it completes.
 
91
 *
 
92
 * Use interrupt flags to determine when the write has completed.
 
93
 */
 
94
#define DI_WRITE_WAIT(val, reg)                                         \
 
95
(                                                                       \
 
96
        /* do the register write */                                     \
 
97
        __raw_writel((val), &data.regs->reg),                           \
 
98
                                                                        \
 
99
        di_write_wait((val), #reg)                                      \
 
100
)
 
101
static int di_write_wait(u32 val, const char *reg)
 
102
{
 
103
        int cnt;
 
104
        int ret = 0;
 
105
        int rc = 0;
 
106
 
 
107
        /* wait for the write to finish */
 
108
        for (cnt = 0; cnt < 100; cnt++) {
 
109
                if ((__raw_readl(&data.regs->dsr) & (DSR_WCF | DSR_WEF)) != 0) {
 
110
                        ret = 1;
 
111
                        break;
 
112
                }
 
113
                udelay(10);
 
114
        }
 
115
        if (ret == 0)
 
116
                printf("### Warning: RTC - Write-wait timeout "
 
117
                                "val = 0x%.8x reg = %s\n", val, reg);
 
118
 
 
119
        /* check for write error */
 
120
        if (__raw_readl(&data.regs->dsr) & DSR_WEF) {
 
121
                clear_write_error();
 
122
                rc = -1;
 
123
        }
 
124
 
 
125
        return rc;
 
126
}
 
127
 
 
128
/*
 
129
 * Initialize dryice hardware
 
130
 */
 
131
static int di_init(void)
 
132
{
 
133
        int rc = 0;
 
134
 
 
135
        data.regs = (struct imxdi_regs __iomem *)IMX_DRYICE_BASE;
 
136
 
 
137
        /* mask all interrupts */
 
138
        __raw_writel(0, &data.regs->dier);
 
139
 
 
140
        /* put dryice into valid state */
 
141
        if (__raw_readl(&data.regs->dsr) & DSR_NVF) {
 
142
                rc = DI_WRITE_WAIT(DSR_NVF | DSR_SVF, dsr);
 
143
                if (rc)
 
144
                        goto err;
 
145
        }
 
146
 
 
147
        /* initialize alarm */
 
148
        rc = DI_WRITE_WAIT(DCAMR_UNSET, dcamr);
 
149
        if (rc)
 
150
                goto err;
 
151
        rc = DI_WRITE_WAIT(0, dcalr);
 
152
        if (rc)
 
153
                goto err;
 
154
 
 
155
        /* clear alarm flag */
 
156
        if (__raw_readl(&data.regs->dsr) & DSR_CAF) {
 
157
                rc = DI_WRITE_WAIT(DSR_CAF, dsr);
 
158
                if (rc)
 
159
                        goto err;
 
160
        }
 
161
 
 
162
        /* the timer won't count if it has never been written to */
 
163
        if (__raw_readl(&data.regs->dtcmr) == 0) {
 
164
                rc = DI_WRITE_WAIT(0, dtcmr);
 
165
                if (rc)
 
166
                        goto err;
 
167
        }
 
168
 
 
169
        /* start keeping time */
 
170
        if (!(__raw_readl(&data.regs->dcr) & DCR_TCE)) {
 
171
                rc = DI_WRITE_WAIT(__raw_readl(&data.regs->dcr) | DCR_TCE, dcr);
 
172
                if (rc)
 
173
                        goto err;
 
174
        }
 
175
 
 
176
        data.init_done = 1;
 
177
        return 0;
 
178
 
 
179
err:
 
180
        return rc;
 
181
}
 
182
 
 
183
int rtc_get(struct rtc_time *tmp)
 
184
{
 
185
        unsigned long now;
 
186
        int rc = 0;
 
187
 
 
188
        if (!data.init_done) {
 
189
                rc = di_init();
 
190
                if (rc)
 
191
                        goto err;
 
192
        }
 
193
 
 
194
        now = __raw_readl(&data.regs->dtcmr);
 
195
        to_tm(now, tmp);
 
196
 
 
197
err:
 
198
        return rc;
 
199
}
 
200
 
 
201
int rtc_set(struct rtc_time *tmp)
 
202
{
 
203
        unsigned long now;
 
204
        int rc;
 
205
 
 
206
        if (!data.init_done) {
 
207
                rc = di_init();
 
208
                if (rc)
 
209
                        goto err;
 
210
        }
 
211
 
 
212
        now = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
 
213
                     tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
 
214
        /* zero the fractional part first */
 
215
        rc = DI_WRITE_WAIT(0, dtclr);
 
216
        if (rc == 0)
 
217
                rc = DI_WRITE_WAIT(now, dtcmr);
 
218
 
 
219
err:
 
220
        return rc;
 
221
}
 
222
 
 
223
void rtc_reset(void)
 
224
{
 
225
        di_init();
 
226
}
 
227
 
 
228
#endif