unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mx27 / karo / v1_0 / src / tx27_misc.c
1 //==========================================================================
2 //
3 //      tx27_misc.c
4 //
5 //      HAL misc board support code for the tx27
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 Red Hat, 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 version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //========================================================================*/
41
42 #include <stdlib.h>
43 #include <redboot.h>
44 #include <string.h>
45 #include <pkgconf/hal.h>
46 #include <pkgconf/system.h>
47 #include CYGBLD_HAL_PLATFORM_H
48
49 #include <cyg/infra/cyg_type.h>         // base types
50 #include <cyg/infra/cyg_trac.h>         // tracing macros
51 #include <cyg/infra/cyg_ass.h>          // assertion macros
52
53 #include <cyg/hal/hal_io.h>             // IO macros
54 #include <cyg/hal/hal_arch.h>           // Register state info
55 #include <cyg/hal/hal_diag.h>
56 #include <cyg/hal/hal_intr.h>           // Interrupt names
57 #include <cyg/hal/hal_cache.h>
58 #include <cyg/hal/hal_soc.h>            // Hardware definitions
59 #include <cyg/hal/karo_tx27.h>          // Platform specifics
60
61 #include <cyg/infra/diag.h>             // diag_printf
62
63 // All the MM table layout is here:
64 #include <cyg/hal/hal_mm.h>
65
66 void hal_mmu_init(void)
67 {
68         unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
69         unsigned long i;
70
71         /*
72          * Set the TTB register
73          */
74         asm volatile ("mcr  p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
75
76         /*
77          * Set the Domain Access Control Register
78          */
79         i = ARM_ACCESS_DACR_DEFAULT;
80         asm volatile ("mcr  p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
81
82         /*
83          * First clear all TT entries - ie Set them to Faulting
84          */
85         memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
86
87         /*             Physical  Virtual Size   Attributes                                                    Function   */
88         /*             Base      Base     MB     cached?           buffered?        access permissions                  */
89         /*             xxx00000  xxx00000                                                                                */
90         X_ARM_MMU_SECTION(0x000, 0xF00, 0x001, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* Boot Rom */
91         X_ARM_MMU_SECTION(0x100, 0x100, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* Internal Registers */
92         X_ARM_MMU_SECTION(0x800, 0x800, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* CSI/ATA Registers */
93         X_ARM_MMU_SECTION(0xA00, 0x000, TX27_SDRAM_SIZE >> 20,  ARM_CACHEABLE,    ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
94         X_ARM_MMU_SECTION(0xA00, 0xA00, TX27_SDRAM_SIZE >> 20,  ARM_CACHEABLE,    ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* SDRAM */
95         X_ARM_MMU_SECTION(0xA00, 0xA80, TX27_SDRAM_SIZE >> 20,  ARM_UNCACHEABLE,  ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* SDRAM */
96 //      X_ARM_MMU_SECTION(0xC00, 0xC00, 0x020, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* Flash */
97         X_ARM_MMU_SECTION(0xD40, 0xD40, 0x020, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* CS4 for External I/O */
98         X_ARM_MMU_SECTION(0xD60, 0xD60, 0x020, ARM_CACHEABLE,   ARM_BUFFERABLE,   ARM_ACCESS_PERM_RW_RW); /* CS5 PSRAM */
99         X_ARM_MMU_SECTION(0xD80, 0xD80, 0x100, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* EMI control/PCMCIA */
100         X_ARM_MMU_SECTION(0xFFF, 0xFFF, 0x001, ARM_UNCACHEABLE, ARM_UNBUFFERABLE, ARM_ACCESS_PERM_RW_RW);   /* VRAM */
101 }
102
103 static inline void set_reg(unsigned long addr, CYG_WORD32 set, CYG_WORD32 clr)
104 {
105         CYG_WORD32 val;
106         HAL_READ_UINT32(addr, val);
107         val = (val & ~clr) | set;
108         HAL_WRITE_UINT32(addr, val);
109 }
110
111 //
112 // Platform specific initialization
113 //
114 static void fec_gpio_init(void)
115 {
116         /* GPIOs to set up for TX27/Starterkit-5:
117            Function       GPIO  Dir  act.  FCT
118                                      Lvl   
119            FEC_RESET      PB30  OUT  LOW   GPIO
120            FEC_ENABLE     PB27  OUT  HIGH  GPIO
121            OSCM26_ENABLE  PB22  OUT  HIGH  GPIO
122            EXT_WAKEUP     PB24  IN   HIGH  GPIO
123            FEC_TXEN       PF23  OUT  OUT   AIN
124            FEC_TXCLK      PD11  OUT  IN    AOUT
125            ...
126          */
127 #define OCR_SHIFT(bit)          (((bit) * 2) % 32)
128 #define OCR_MASK(bit)           (3 << (OCR_SHIFT(bit)))
129 #define OCR_VAL(bit,val)        (((val) << (OCR_SHIFT(bit))) & (OCR_MASK(bit)))
130 #define GPR_SHIFT(bit)          (bit)
131 #define GPR_MASK(bit)           (1 << (GPR_SHIFT(bit)))
132 #define GPR_VAL(bit,val)        (((val) << (GPR_SHIFT(bit))) & (GPR_MASK(bit)))
133 #define ICONF_SHIFT(bit)        (((bit) * 2) % 32)
134 #define ICONF_MASK(bit)         (3 << (ICONF_SHIFT(bit)))
135 #define ICONF_VAL(bit,val)      (((val) << (ICONF_SHIFT(bit))) & (ICONF_MASK(bit)))
136
137         /*
138          * make sure the ETH PHY strap pins are pulled to the right voltage
139          * before deasserting the PHY reset GPIO
140          */
141         // deassert PD0-15
142         set_reg(SOC_GPIOD_BASE + GPIO_OCR1, 0xffffffff, 0);
143         set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, 0xffff);
144         set_reg(SOC_GPIOD_BASE + GPIO_DDIR, 0xffff, 0);
145         set_reg(SOC_GPIOD_BASE + GPIO_GIUS, 0xffff, 0);
146
147         // deassert PD16
148         set_reg(SOC_GPIOD_BASE + GPIO_OCR2, OCR_MASK(16), 0);
149         set_reg(SOC_GPIOD_BASE + GPIO_DR, 0, GPR_MASK(16));
150         set_reg(SOC_GPIOD_BASE + GPIO_DDIR, GPR_MASK(16), 0);
151         set_reg(SOC_GPIOD_BASE + GPIO_GIUS, GPR_MASK(16), 0);
152
153         // deassert PF23
154         set_reg(SOC_GPIOF_BASE + GPIO_OCR2, OCR_MASK(23), 0);
155         set_reg(SOC_GPIOF_BASE + GPIO_DR, 0, GPR_MASK(23));
156         set_reg(SOC_GPIOF_BASE + GPIO_DDIR, GPR_MASK(23), 0);
157         set_reg(SOC_GPIOF_BASE + GPIO_GIUS, GPR_MASK(23), 0);
158
159         // assert FEC PHY Reset (PB30) and switch PHY power off
160         /* PB22, PB27, PB30 => GPIO out */
161         set_reg(SOC_GPIOB_BASE + GPIO_OCR2, OCR_MASK(27) | OCR_MASK(30), 0);
162         set_reg(SOC_GPIOB_BASE + GPIO_DR, 0, GPR_MASK(27) | GPR_MASK(30));
163         set_reg(SOC_GPIOB_BASE + GPIO_DDIR, GPR_MASK(27) | GPR_MASK(30), 0);
164         set_reg(SOC_GPIOB_BASE + GPIO_GIUS, GPR_MASK(27) | GPR_MASK(30), 0);
165 }
166
167 //
168 // Platform specific initialization
169 //
170
171 unsigned int g_clock_src;
172 unsigned int g_board_type = BOARD_TYPE_TX27KARO;
173
174 void plf_hardware_init(void)
175 {
176         g_clock_src = PLL_REF_CLK;
177         fec_gpio_init();
178 }
179
180 #define SOC_FBAC0_REG           0x10028800UL
181
182 extern int fuse_blow(int bank, int row, int bit);
183
184 #define SOC_I2C2_BASE           UL(0x1001D000)
185
186 /* Address offsets of the I2C registers */
187 #define MXC_IADR                0x00    /* Address Register */
188 #define MXC_IFDR                0x04    /* Freq div register */
189 #define MXC_I2CR                0x08    /* Control regsiter */
190 #define MXC_I2SR                0x0C    /* Status register */
191 #define MXC_I2DR                0x10    /* Data I/O register */
192
193 /* Bit definitions of I2CR */
194 #define MXC_I2CR_IEN            0x0080
195 #define MXC_I2CR_IIEN           0x0040
196 #define MXC_I2CR_MSTA           0x0020
197 #define MXC_I2CR_MTX            0x0010
198 #define MXC_I2CR_TXAK           0x0008
199 #define MXC_I2CR_RSTA           0x0004
200
201 /* Bit definitions of I2SR */
202 #define MXC_I2SR_ICF            0x0080
203 #define MXC_I2SR_IAAS           0x0040
204 #define MXC_I2SR_IBB            0x0020
205 #define MXC_I2SR_IAL            0x0010
206 #define MXC_I2SR_SRW            0x0004
207 #define MXC_I2SR_IIF            0x0002
208 #define MXC_I2SR_RXAK           0x0001
209
210 #define LP3972_SLAVE_ADDR       0x34
211
212 static inline cyg_uint8 i2c_addr(cyg_uint8 addr, int rw)
213 {
214         return (addr << 1) | !!rw;
215 }
216
217 static inline cyg_uint8 mx27_i2c_read(cyg_uint8 reg)
218 {
219         cyg_uint16 val;
220         HAL_READ_UINT16(SOC_I2C2_BASE + reg, val);
221         return val;
222 }
223
224 static inline void mx27_i2c_write(cyg_uint8 reg, cyg_uint8 val)
225 {
226         HAL_WRITE_UINT16(SOC_I2C2_BASE + reg, val);
227 }
228
229 static inline void mx27_i2c_set_reg(cyg_uint8 reg, cyg_uint8 set, cyg_uint8 clr)
230 {
231         cyg_uint8 val = mx27_i2c_read(reg);
232         val = (val & ~clr) | set;
233         mx27_i2c_write(reg, val);
234 }
235
236 static void mx27_i2c_disable(void)
237 {
238         /* disable I2C controller */
239         mx27_i2c_set_reg(MXC_I2CR, 0, MXC_I2CR_IEN);
240         /* disable I2C clock */
241         set_reg(SOC_CRM_PCCR0, 0, (1 << 17));
242 }
243
244 static int mx27_i2c_init(void)
245 {
246         int ret;
247
248         /* configure PC5,PC6 as Primary Function */
249         set_reg(SOC_GPIOC_BASE + GPIO_GPR, 0, GPR_MASK(5) | GPR_MASK(6));
250         set_reg(SOC_GPIOC_BASE + GPIO_GIUS, 0, GPR_MASK(5) | GPR_MASK(6));
251
252         /* enable I2C clock */
253         set_reg(SOC_CRM_PCCR0, (1 << 17), 0);
254
255         /* setup I2C clock divider */
256         mx27_i2c_write(MXC_IFDR, 0x2c);
257         mx27_i2c_write(MXC_I2SR, 0);
258
259         /* enable I2C controller in master mode */
260         mx27_i2c_write(MXC_I2CR, MXC_I2CR_IEN);
261
262         ret = mx27_i2c_read(MXC_I2SR);
263         if (ret & MXC_I2SR_IBB) {
264                 diag_printf("I2C bus busy\n");
265                 mx27_i2c_disable();
266                 return -EIO;
267         }
268         return 0;
269 }
270
271 static int mx27_i2c_wait_busy(int set)
272 {
273         int ret;
274         const int max_loops = 100;
275         int retries = max_loops;
276
277         cyg_uint8 mask = set ? MXC_I2SR_IBB : 0;
278
279         while ((ret = mask ^ (mx27_i2c_read(MXC_I2SR) & MXC_I2SR_IBB)) && --retries > 0) {
280                 HAL_DELAY_US(3);
281         }
282         if (ret != 0) {
283                 diag_printf("i2c: Waiting for IBB to %s timed out\n", set ? "set" : "clear");
284                 return -ETIMEDOUT;
285         }
286         return ret;
287 }
288
289 static int mx27_i2c_wait_tc(void)
290 {
291         int ret;
292         const int max_loops = 1000;
293         int retries = max_loops;
294
295         while (!((ret = mx27_i2c_read(MXC_I2SR)) & MXC_I2SR_IIF) && --retries > 0) {
296                 HAL_DELAY_US(3);
297         }
298         mx27_i2c_write(MXC_I2SR, 0);
299         if (!(ret & MXC_I2SR_IIF)) {
300                 diag_printf("i2c: Wait for transfer completion timed out\n");
301                 return -ETIMEDOUT;
302         }
303         if (ret & MXC_I2SR_ICF) {
304                 if (mx27_i2c_read(MXC_I2CR) & MXC_I2CR_MTX) {
305                         if (!(ret & MXC_I2SR_RXAK)) {
306                                 ret = 0;
307                         } else {
308                                 diag_printf("i2c: No ACK received after writing data\n");
309                                 return -ENXIO;
310                         }
311                 }
312         }
313         return ret;
314 }
315
316 static int mx27_i2c_stop(void)
317 {
318         int ret;
319
320         mx27_i2c_set_reg(MXC_I2CR, 0, MXC_I2CR_MSTA | MXC_I2CR_MTX);
321         ret = mx27_i2c_wait_busy(0);
322         return ret;
323 }
324
325 static int mx27_i2c_start(cyg_uint8 addr, int rw)
326 {
327         int ret;
328
329         ret = mx27_i2c_init();
330         if (ret < 0) {
331                 diag_printf("I2C bus init failed; cannot switch fuse programming voltage\n");
332                 return ret;
333         }
334         mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MSTA, 0);
335         ret = mx27_i2c_wait_busy(1);
336         if (ret == 0) {
337                 mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MTX, 0);
338                 mx27_i2c_write(MXC_I2DR, i2c_addr(addr, rw));
339                 ret = mx27_i2c_wait_tc();
340                 if (ret < 0) {
341                         mx27_i2c_stop();
342                 }
343         }
344         return ret;
345 }
346
347 static int mx27_i2c_repeat_start(cyg_uint8 addr, int rw)
348 {
349         int ret;
350
351         mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_RSTA, 0);
352         HAL_DELAY_US(3);
353         mx27_i2c_write(MXC_I2DR, i2c_addr(addr, rw));
354         ret = mx27_i2c_wait_tc();
355         if (ret < 0) {
356                 mx27_i2c_stop();
357         }
358         return ret;
359 }
360
361 static int mx27_i2c_read_byte(void)
362 {
363         int ret;
364
365         mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_TXAK, MXC_I2CR_MTX);
366         (void)mx27_i2c_read(MXC_I2DR); /* dummy read after address cycle */
367         ret = mx27_i2c_wait_tc();
368         mx27_i2c_stop();
369         if (ret < 0) {
370                 return ret;
371         }
372         ret = mx27_i2c_read(MXC_I2DR);
373         return ret;
374 }
375
376 static int mx27_i2c_write_byte(cyg_uint8 data, int last)
377 {
378         int ret;
379
380         mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MTX, 0);
381         mx27_i2c_write(MXC_I2DR, data);
382         if ((ret = mx27_i2c_wait_tc()) < 0 || last) {
383                 mx27_i2c_stop();
384         }
385         return ret;
386 }
387
388 static int lp3972_reg_read(cyg_uint8 reg)
389 {
390         int ret;
391
392         ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
393         if (ret < 0) {
394                 return ret;
395         }
396         ret = mx27_i2c_write_byte(reg, 0);
397         if (ret < 0) {
398                 return ret;
399         }
400         ret = mx27_i2c_repeat_start(LP3972_SLAVE_ADDR, 1);
401         if (ret < 0) {
402                 return ret;
403         }
404         ret = mx27_i2c_read_byte();
405         mx27_i2c_disable();
406         return ret;
407 }
408
409 static int lp3972_reg_write(cyg_uint8 reg, cyg_uint8 val)
410 {
411         int ret;
412
413         ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
414         if (ret < 0) {
415                 return ret;
416         }
417         ret = mx27_i2c_write_byte(reg, 0);
418         if (ret < 0) {
419                 return ret;
420         }
421         ret = mx27_i2c_write_byte(val, 1);
422         mx27_i2c_disable();
423         return ret;
424 }
425
426 int tx27_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN])
427 {
428         int ret = 0;
429         int i;
430
431         for (i = 0; i < ETHER_ADDR_LEN; i++) {
432                 unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
433
434                 if ((fuse | mac_addr[i]) != mac_addr[i]) {
435                         diag_printf("MAC address fuse cannot be programmed: fuse[%d]=0x%02x -> 0x%02x\n",
436                                     i, fuse, mac_addr[i]);
437                         return -1;
438                 }
439                 if (fuse != mac_addr[i]) {
440                         ret = 1;
441                 }
442         }
443         if (ret == 0) {
444                 return ret;
445         }
446         ret = lp3972_reg_write(0x39, 0xf0);
447         if (ret < 0) {
448                 diag_printf("Failed to switch fuse programming voltage\n");
449                 return ret;
450         }
451         ret = lp3972_reg_read(0x39);
452         if (ret != 0xf0) {
453                 diag_printf("Failed to switch fuse programming voltage\n");
454                 return ret;
455         }
456         for (i = 0; i < ETHER_ADDR_LEN; i++) {
457                 int bit;
458                 unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
459
460                 for (bit = 0; bit < 8; bit++) {
461                         if (((mac_addr[i] >> bit) & 0x1) == 0)
462                                 continue;
463                         if (((mac_addr[i] >> bit) & 1) == ((fuse >> bit) & 1)) {
464                                 continue;
465                         }
466                         if (fuse_blow(0, i + 5, bit)) {
467                                 diag_printf("Failed to blow fuse bank 0 row %d bit %d\n",
468                                             i, bit);
469                                 ret = -1;
470                                 goto out;
471                         }
472                 }
473         }
474         /* would like to blow the MAC_ADDR_LOCK fuse, but that's not available on MX27 */
475         //fuse_blow(0, 0, SOC_MAC_ADDR_LOCK_BIT);
476 out:
477         lp3972_reg_write(0x39, 0);
478         return ret;
479 }
480
481 #include CYGHWR_MEMORY_LAYOUT_H
482
483 typedef void code_fun(void);
484
485 void tx27_program_new_stack(void *func)
486 {
487         register CYG_ADDRESS stack_ptr asm("sp");
488         register CYG_ADDRESS old_stack asm("r4");
489         register code_fun *new_func asm("r0");
490         old_stack = stack_ptr;
491         stack_ptr = CYGMEM_REGION_ram + CYGMEM_REGION_ram_SIZE - sizeof(CYG_ADDRESS);
492         new_func = (code_fun*)func;
493         new_func();
494         stack_ptr = old_stack;
495 }
496
497 static void display_clock_src(void)
498 {
499         if (g_clock_src == FREQ_32000HZ) {
500                 diag_printf("Clock input: 32kHz\n");
501         } else if (g_clock_src == FREQ_26MHZ) {
502                 diag_printf("Clock input: 26MHz\n");
503         } else if (g_clock_src == FREQ_32768HZ) {
504                 diag_printf("Clock input: 32.768kHz\n");
505         } else {
506                 diag_printf("Unknown clock input source. Something is wrong!\n");
507         }
508 }
509
510 static unsigned long random;
511 extern unsigned int hal_timer_count(void);
512 /* provide at least _some_ sort of randomness */
513 static void random_init(void)
514 {
515         do {
516                 srand(random + hal_timer_count());
517                 random = rand();
518         } while ((hal_timer_count() < 5) || (hal_timer_count() & 0x47110815));
519 }
520 RedBoot_init(random_init, RedBoot_INIT_FIRST);
521
522 #define WDOG_WRSR       ((CYG_WORD16 *)0x10002004)
523 static void display_board_type(void)
524 {
525         char *reset_cause;
526         CYG_WORD16 wrsr;
527
528         diag_printf("\nBoard Type: Ka-Ro TX27\n");
529         HAL_READ_UINT16(WDOG_WRSR, wrsr);
530         switch (wrsr) {
531         case (1 << 4):
532                 reset_cause = "POWER_ON RESET";
533                 break;
534         case (1 << 3):
535                 reset_cause = "EXTERNAL RESET";
536                 break;
537         case (1 << 1):
538                 reset_cause = "WATCHDOG RESET";
539                 break;
540         case (1 << 0):
541                 reset_cause = "SOFT RESET";
542                 break;
543         default:
544                 reset_cause = "UNKNOWN";
545         }
546         diag_printf("Last RESET cause: %s\n", reset_cause);
547 }
548
549 static void display_board_info(void)
550 {
551         display_board_type();
552         display_clock_src();
553 }
554
555 RedBoot_init(display_board_info, RedBoot_INIT_LAST);