OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [hal/] [powerpc/] [ppc40x/] [current/] [src/] [var_misc.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      var_misc.c
4
//
5
//      HAL implementation miscellaneous functions
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    jskov
43
// Contributors: jskov, gthomas
44
// Date:         2000-02-04
45
// Purpose:      HAL miscellaneous functions
46
// Description:  This file contains miscellaneous functions provided by the
47
//               HAL.
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/hal.h>
54
 
55
#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS
56
#include <cyg/hal/ppc_regs.h>
57
#include <cyg/infra/cyg_type.h>
58
#include <cyg/hal/hal_io.h>             // I/O macros
59
#include <cyg/hal/hal_if.h>             // Support (virtual vector)
60
#include <cyg/hal/hal_mem.h>
61
#include <cyg/infra/diag.h>
62
 
63
#ifdef CYGPKG_IO_PCI
64
externC void hal_ppc405_pci_init(void);
65
#endif
66
 
67
externC void hal_ppc40x_clock_initialize(cyg_uint32 period);
68
static  void hal_ppc405_i2c_init(void);
69
 
70
//--------------------------------------------------------------------------
71
void hal_variant_init(void)
72
{
73
    // Initialize I/O interfaces
74
    hal_if_init();
75
 
76
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
77
 
78
    // Initialize I2C controller
79
    hal_ppc405_i2c_init();
80
#endif
81
 
82
    // Initialize real-time clock (for delays, etc, even if kernel doesn't use it)
83
    hal_ppc40x_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
84
 
85
#ifdef CYGPKG_IO_PCI
86
    hal_ppc405_pci_init();
87
#endif
88
}
89
 
90
 
91
//--------------------------------------------------------------------------
92
// Variant specific idle thread action.
93
bool
94
hal_variant_idle_thread_action( cyg_uint32 count )
95
{
96
    // Let architecture idle thread action run
97
    return true;
98
}
99
 
100
//---------------------------------------------------------------------------
101
// Use MMU resources to map memory regions.  
102
// Takes and returns an int used to ID the MMU resource to use. This ID
103
// is increased as resources are used and should be used for subsequent
104
// invocations.
105
//
106
// The PPC4xx CPUs do not have BATs. Fortunately we don't currently
107
// use the MMU, so we can simulate BATs by using the TLBs.
108
int
109
cyg_hal_map_memory (int id, CYG_ADDRESS virt, CYG_ADDRESS phys,
110
                    cyg_int32 size, cyg_uint8 flags)
111
{
112
    cyg_uint32 epn, rpn;
113
    int sv, lv, max_tlbs;
114
 
115
    // There are 64 TLBs.
116
    max_tlbs = 64;
117
 
118
    // May need to use more than one slot since the TLB can only
119
    // map 16MB max.
120
 
121
    while (size > 0) {
122
        // Use the smallest "size" value which is big enough (round up)
123
        for (sv = 0, lv = 0x400;  sv < 7;  sv++, lv <<= 2) {
124
            if (lv >= size) break;
125
        }
126
 
127
        // Note: the process ID comes from the PID register (always 0)
128
        epn = (virt & M_EPN_EPNMASK) | M_EPN_EV | M_EPN_SIZE(sv);
129
        rpn = (phys & M_RPN_RPNMASK) | M_RPN_EX | M_RPN_WR;
130
 
131
        if (flags & CYGARC_MEMDESC_CI) {
132
            rpn |= M_RPN_I;
133
        }
134
#ifdef CYGSEM_HAL_DCACHE_STARTUP_MODE_WRITETHRU
135
        // Only for cache-enabled regions
136
        else {
137
            rpn |= M_RPN_W;
138
        }
139
#endif
140
 
141
        if (flags & CYGARC_MEMDESC_GUARDED)
142
            rpn |= M_RPN_G;
143
 
144
        CYGARC_TLBWE(id, epn, rpn);
145
        id++;
146
        size -= lv;
147
        virt += lv;
148
        phys += lv;
149
    }
150
 
151
    return id;
152
}
153
 
154
 
155
// Initialize MMU to a sane (NOP) state.
156
//
157
// Initialize TLBs with 0, Valid bits unset.
158
void
159
cyg_hal_clear_MMU (void)
160
{
161
    cyg_uint32 tlbhi = 0;
162
    cyg_uint32 tlblo = 0;
163
    int id, max_tlbs;
164
 
165
    // There are 64 TLBs.
166
    max_tlbs = 64;
167
 
168
    CYGARC_MTSPR (SPR_PID, 0);
169
 
170
    for (id = 0; id < max_tlbs; id++) {
171
        CYGARC_TLBWE(id, tlbhi, tlblo);
172
    }
173
}
174
 
175
//--------------------------------------------------------------------------
176
// Clock control - use the programmable (variable period) timer
177
 
178
static cyg_uint32 _period;
179
extern cyg_uint32 _hold_tcr;  // Shadow of TCR register which can't be read
180
 
181
void
182
hal_ppc40x_clock_initialize(cyg_uint32 period)
183
{
184
    cyg_uint32 tcr;
185
 
186
    // Enable auto-reload
187
    CYGARC_MFSPR(SPR_TCR, tcr);
188
    tcr = _hold_tcr;
189
    tcr |= TCR_ARE;
190
    CYGARC_MTSPR(SPR_TCR, tcr);
191
    _hold_tcr = tcr;
192
 
193
    // Set up the counter register
194
    _period = period;
195
    CYGARC_MTSPR(SPR_PIT, period);
196
}
197
 
198
// Returns the number of clocks since the last interrupt
199
externC void
200
hal_ppc40x_clock_read(cyg_uint32 *val)
201
{
202
    cyg_uint32 cur_val;
203
 
204
    CYGARC_MFSPR(SPR_PIT, cur_val);
205
    *val = _period - cur_val;
206
}
207
 
208
externC void
209
hal_ppc40x_clock_reset(cyg_uint32 vector, cyg_uint32 period)
210
{
211
    hal_ppc40x_clock_initialize(period);
212
}
213
 
214
//
215
// Delay for the specified number of microseconds.
216
// Assumption: _period has been set already and corresponds to the
217
// system clock frequency, normally 10ms.
218
//
219
 
220
externC void
221
hal_ppc40x_delay_us(int us)
222
{
223
    cyg_uint32 delay_period, delay, diff;
224
    cyg_uint32 pit_val1, pit_val2;
225
 
226
    delay_period = ((_period / ((CYGNUM_HAL_RTC_NUMERATOR/1000) / CYGNUM_HAL_RTC_DENOMINATOR)) * us);
227
    delay = 0;
228
    CYGARC_MFSPR(SPR_PIT, pit_val1);
229
    while (delay < delay_period) {
230
        // Wait for clock to "tick"
231
        while (true) {
232
            CYGARC_MFSPR(SPR_PIT, pit_val2);
233
            if (pit_val1 != pit_val2) break;
234
        }
235
        // The counter ticks down
236
        if (pit_val2 < pit_val1) {
237
            diff = pit_val1 - pit_val2;
238
        } else {
239
            diff = (_period - pit_val2) + pit_val1;
240
        }
241
        delay += diff;
242
        pit_val1 = pit_val2;
243
    }
244
}
245
 
246
#if defined(CYGHWR_HAL_POWERPC_PPC4XX_405) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405GP) || defined(CYGHWR_HAL_POWERPC_PPC4XX_405EP)
247
//----------------------------------------------------------------------
248
// I2C Support
249
static void
250
hal_ppc405_i2c_init(void)
251
{
252
    HAL_WRITE_UINT8(IIC0_CLKDIV, 6);  // 66MHz
253
    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));
254
    HAL_WRITE_UINT8(IIC0_LMADR, 0);  // Clear interface
255
    HAL_WRITE_UINT8(IIC0_HMADR, 0);
256
    HAL_WRITE_UINT8(IIC0_LSADR, 0);
257
    HAL_WRITE_UINT8(IIC0_HSADR, 0);
258
    HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD));
259
    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB|IIC0_MDCNTL_EUBS));
260
}
261
 
262
externC bool
263
hal_ppc405_i2c_put_bytes(int addr, cyg_uint8 *val, int len)
264
{
265
    cyg_uint8 stat, extstat, xfrcnt, cmd, size;
266
    int i, j;
267
 
268
    // The hardware can only move up to 4 bytes in a single operation
269
    // This code breaks the request down into chunks of up to 4 bytes
270
    // and checks the status after each chunk.
271
    // Note: the actual device may impose additional size restrictions,
272
    // e.g. some EEPROM devices may limit a single write to 32 bytes.
273
    for (i = 0;  i < len;  i += size) {
274
        HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));
275
        HAL_WRITE_UINT8(IIC0_EXTSTS, (IIC0_EXTSTS_IRQP|IIC0_EXTSTS_IRQD));
276
        HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));
277
        cmd = IIC0_CNTL_RW_WRITE|IIC0_CNTL_PT;
278
        size = (len - i);
279
        if (size > 4) {
280
            size = 4;
281
            cmd |= IIC0_CNTL_CHT;
282
        }
283
        cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT);
284
        for (j = 0;  j < size;  j++) {
285
            HAL_WRITE_UINT8(IIC0_MDBUF, val[i+j]);
286
        }
287
        HAL_WRITE_UINT8(IIC0_LMADR, addr);
288
        HAL_WRITE_UINT8(IIC0_CNTL, cmd);
289
        while (true) {
290
            CYGACC_CALL_IF_DELAY_US(10);   // 10us
291
            HAL_READ_UINT8(IIC0_STS, stat);
292
            if ((stat & IIC0_STS_PT) == 0) {
293
                if ((stat & IIC0_STS_ERR) != 0) {
294
                    // Some sort of error
295
                    HAL_READ_UINT8(IIC0_EXTSTS, extstat);
296
                    HAL_READ_UINT8(IIC0_XFRCNT, xfrcnt);
297
                    HAL_WRITE_UINT8(IIC0_EXTSTS, extstat);
298
                    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));
299
                    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));
300
                    diag_printf("%s addr: %x, len: %d, err: %x/%x, count: %d, cmd: %x\n",
301
                                __FUNCTION__, addr, len, stat, extstat, xfrcnt, cmd);
302
                    diag_printf("buf: ");
303
                    for (j = 0;  j < size;  j++) {
304
                        diag_printf("0x%02x ", val[i+j]);
305
                    }
306
                    diag_printf("\n");
307
                    return false;
308
                }
309
                break;
310
            }
311
        }
312
    }
313
    return true;
314
}
315
 
316
externC bool
317
hal_ppc405_i2c_get_bytes(int addr, cyg_uint8 *val, int len)
318
{
319
    cyg_uint8 stat, extstat, _val, cmd;
320
    int i, j, size;
321
 
322
    for (i = 0;  i < len;  i += size) {
323
        cmd = IIC0_CNTL_RW_READ|IIC0_CNTL_PT;
324
        size = (len - i);
325
        if (size > 4) {
326
            size = 4;
327
            cmd |= IIC0_CNTL_CHT;
328
        }
329
        cmd |= ((size-1)<<IIC0_CNTL_TCT_SHIFT);
330
        HAL_WRITE_UINT8(IIC0_LMADR, addr);
331
        HAL_WRITE_UINT8(IIC0_CNTL, cmd);
332
        while (true) {
333
            CYGACC_CALL_IF_DELAY_US(10);   // 10us
334
            HAL_READ_UINT8(IIC0_STS, stat);
335
            if ((stat & IIC0_STS_PT) == 0) {
336
                if ((stat & IIC0_STS_ERR) != 0) {
337
                    // Some sort of error
338
                    HAL_READ_UINT8(IIC0_EXTSTS, extstat);
339
                    HAL_WRITE_UINT8(IIC0_EXTSTS, extstat);
340
                    HAL_WRITE_UINT8(IIC0_MDCNTL, (IIC0_MDCNTL_FSDB|IIC0_MDCNTL_FMDB));
341
                    HAL_WRITE_UINT8(IIC0_STS, (IIC0_STS_SCMP|IIC0_STS_IRQA));
342
                    diag_printf("%s addr: %x, len: %d, err: %x/%x\n",
343
                                __FUNCTION__, addr, len, stat, extstat);
344
                    return false;
345
                }
346
                break;
347
            }
348
        }
349
        for (j = 0;  j < size;  j++) {
350
            HAL_READ_UINT8(IIC0_MDBUF, _val);
351
            val[i+j] = _val;
352
        }
353
    }
354
    return true;
355
}
356
#endif // 405
357
 
358
//--------------------------------------------------------------------------
359
// End of var_misc.c

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.