1 //==========================================================================
5 // HAL misc board support code for the tx27
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.
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.
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
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.
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.
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.
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 //========================================================================*/
45 #include <pkgconf/hal.h>
46 #include <pkgconf/system.h>
47 #include CYGBLD_HAL_PLATFORM_H
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
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 CYGBLD_HAL_PLF_DEFS_H // Platform specifics
61 #include <cyg/infra/diag.h> // diag_printf
63 // All the MM table layout is here:
64 #include <cyg/hal/hal_mm.h>
66 void hal_mmu_init(void)
68 unsigned long ttb_base = RAM_BANK0_BASE + 0x4000;
72 * Set the TTB register
74 asm volatile ("mcr p15,0,%0,c2,c0,0" : : "r"(ttb_base) /*:*/);
77 * Set the Domain Access Control Register
79 i = ARM_ACCESS_DACR_DEFAULT;
80 asm volatile ("mcr p15,0,%0,c3,c0,0" : : "r"(i) /*:*/);
83 * First clear all TT entries - ie Set them to Faulting
85 memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
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 */
103 static inline void set_reg(unsigned long addr, CYG_WORD32 set, CYG_WORD32 clr)
106 HAL_READ_UINT32(addr, val);
107 val = (val & ~clr) | set;
108 HAL_WRITE_UINT32(addr, val);
112 // Platform specific initialization
114 static void fec_gpio_init(void)
116 /* GPIOs to set up for TX27/Starterkit-5:
117 Function GPIO Dir act. FCT
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
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)))
138 * make sure the ETH PHY strap pins are pulled to the right voltage
139 * before deasserting the PHY reset GPIO
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);
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);
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);
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);
168 // Platform specific initialization
171 unsigned int g_clock_src;
172 unsigned int g_board_type = BOARD_TYPE_TX27KARO;
174 void plf_hardware_init(void)
176 g_clock_src = PLL_REF_CLK;
180 #define SOC_FBAC0_REG 0x10028800UL
182 extern int fuse_blow(int bank, int row, int bit);
184 #define SOC_I2C2_BASE UL(0x1001D000)
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 */
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
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
210 #define LP3972_SLAVE_ADDR 0x34
212 static inline cyg_uint8 i2c_addr(cyg_uint8 addr, int rw)
214 return (addr << 1) | !!rw;
217 static inline cyg_uint8 mx27_i2c_read(cyg_uint8 reg)
220 HAL_READ_UINT16(SOC_I2C2_BASE + reg, val);
224 static inline void mx27_i2c_write(cyg_uint8 reg, cyg_uint8 val)
226 HAL_WRITE_UINT16(SOC_I2C2_BASE + reg, val);
229 static inline void mx27_i2c_set_reg(cyg_uint8 reg, cyg_uint8 set, cyg_uint8 clr)
231 cyg_uint8 val = mx27_i2c_read(reg);
232 val = (val & ~clr) | set;
233 mx27_i2c_write(reg, val);
236 static void mx27_i2c_disable(void)
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));
244 static int mx27_i2c_init(void)
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));
252 /* enable I2C clock */
253 set_reg(SOC_CRM_PCCR0, (1 << 17), 0);
255 /* setup I2C clock divider */
256 mx27_i2c_write(MXC_IFDR, 0x2c);
257 mx27_i2c_write(MXC_I2SR, 0);
259 /* enable I2C controller in master mode */
260 mx27_i2c_write(MXC_I2CR, MXC_I2CR_IEN);
262 ret = mx27_i2c_read(MXC_I2SR);
263 if (ret & MXC_I2SR_IBB) {
264 diag_printf("I2C bus busy\n");
271 static int mx27_i2c_wait_busy(int set)
274 const int max_loops = 100;
275 int retries = max_loops;
277 cyg_uint8 mask = set ? MXC_I2SR_IBB : 0;
279 while ((ret = mask ^ (mx27_i2c_read(MXC_I2SR) & MXC_I2SR_IBB)) && --retries > 0) {
283 diag_printf("i2c: Waiting for IBB to %s timed out\n", set ? "set" : "clear");
289 static int mx27_i2c_wait_tc(void)
292 const int max_loops = 1000;
293 int retries = max_loops;
295 while (!((ret = mx27_i2c_read(MXC_I2SR)) & MXC_I2SR_IIF) && --retries > 0) {
298 mx27_i2c_write(MXC_I2SR, 0);
299 if (!(ret & MXC_I2SR_IIF)) {
300 diag_printf("i2c: Wait for transfer completion timed out\n");
303 if (ret & MXC_I2SR_ICF) {
304 if (mx27_i2c_read(MXC_I2CR) & MXC_I2CR_MTX) {
305 if (!(ret & MXC_I2SR_RXAK)) {
308 diag_printf("i2c: No ACK received after writing data\n");
316 static int mx27_i2c_stop(void)
320 mx27_i2c_set_reg(MXC_I2CR, 0, MXC_I2CR_MSTA | MXC_I2CR_MTX);
321 ret = mx27_i2c_wait_busy(0);
325 static int mx27_i2c_start(cyg_uint8 addr, int rw)
329 ret = mx27_i2c_init();
331 diag_printf("I2C bus init failed; cannot switch fuse programming voltage\n");
334 mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MSTA, 0);
335 ret = mx27_i2c_wait_busy(1);
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();
347 static int mx27_i2c_repeat_start(cyg_uint8 addr, int rw)
351 mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_RSTA, 0);
353 mx27_i2c_write(MXC_I2DR, i2c_addr(addr, rw));
354 ret = mx27_i2c_wait_tc();
361 static int mx27_i2c_read_byte(void)
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();
372 ret = mx27_i2c_read(MXC_I2DR);
376 static int mx27_i2c_write_byte(cyg_uint8 data, int last)
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) {
388 static int lp3972_reg_read(cyg_uint8 reg)
392 ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
396 ret = mx27_i2c_write_byte(reg, 0);
400 ret = mx27_i2c_repeat_start(LP3972_SLAVE_ADDR, 1);
404 ret = mx27_i2c_read_byte();
409 static int lp3972_reg_write(cyg_uint8 reg, cyg_uint8 val)
413 ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
417 ret = mx27_i2c_write_byte(reg, 0);
421 ret = mx27_i2c_write_byte(val, 1);
426 int tx27_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN])
431 for (i = 0; i < ETHER_ADDR_LEN; i++) {
432 unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
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]);
439 if (fuse != mac_addr[i]) {
446 ret = lp3972_reg_write(0x39, 0xf0);
448 diag_printf("Failed to switch fuse programming voltage\n");
451 ret = lp3972_reg_read(0x39);
453 diag_printf("Failed to switch fuse programming voltage\n");
456 for (i = 0; i < ETHER_ADDR_LEN; i++) {
458 unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
460 for (bit = 0; bit < 8; bit++) {
461 if (((mac_addr[i] >> bit) & 0x1) == 0)
463 if (((mac_addr[i] >> bit) & 1) == ((fuse >> bit) & 1)) {
466 if (fuse_blow(0, i + 5, bit)) {
467 diag_printf("Failed to blow fuse bank 0 row %d bit %d\n",
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);
477 lp3972_reg_write(0x39, 0);
481 #include CYGHWR_MEMORY_LAYOUT_H
483 typedef void code_fun(void);
485 void tx27_program_new_stack(void *func)
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;
494 stack_ptr = old_stack;
497 static void display_clock_src(void)
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");
506 diag_printf("Unknown clock input source. Something is wrong!\n");
510 #define WDOG_WRSR ((CYG_WORD16 *)0x10002004)
511 static void display_board_type(void)
516 diag_printf("\nBoard Type: Ka-Ro TX27\n");
517 HAL_READ_UINT16(WDOG_WRSR, wrsr);
520 reset_cause = "POWER_ON RESET";
523 reset_cause = "EXTERNAL RESET";
526 reset_cause = "WATCHDOG RESET";
529 reset_cause = "SOFT RESET";
532 reset_cause = "UNKNOWN";
534 diag_printf("Last RESET cause: %s\n", reset_cause);
537 static void display_board_info(void)
539 display_board_type();
543 RedBoot_init(display_board_info, RedBoot_INIT_LAST);