1 /* 2 * Copyright 2011 Freescale Semiconductor 3 * Author: Shengzhou Liu <Shengzhou.Liu@freescale.com> 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License as published by the Free 7 * Software Foundation; either version 2 of the License, or (at your option) 8 * any later version. 9 * 10 * This file provides support for the QIXIS of some Freescale reference boards. 11 * 12 */ 13 14 #include <common.h> 15 #include <command.h> 16 #include <asm/io.h> 17 #include <linux/time.h> 18 #include <i2c.h> 19 #include "qixis.h" 20 21 #ifdef CONFIG_SYS_I2C_FPGA_ADDR 22 u8 qixis_read_i2c(unsigned int reg) 23 { 24 return i2c_reg_read(CONFIG_SYS_I2C_FPGA_ADDR, reg); 25 } 26 27 void qixis_write_i2c(unsigned int reg, u8 value) 28 { 29 u8 val = value; 30 i2c_reg_write(CONFIG_SYS_I2C_FPGA_ADDR, reg, val); 31 } 32 #endif 33 34 u8 qixis_read(unsigned int reg) 35 { 36 void *p = (void *)QIXIS_BASE; 37 38 return in_8(p + reg); 39 } 40 41 void qixis_write(unsigned int reg, u8 value) 42 { 43 void *p = (void *)QIXIS_BASE; 44 45 out_8(p + reg, value); 46 } 47 48 u16 qixis_read_minor(void) 49 { 50 u16 minor; 51 52 /* this data is in little endian */ 53 QIXIS_WRITE(tagdata, 5); 54 minor = QIXIS_READ(tagdata); 55 QIXIS_WRITE(tagdata, 6); 56 minor += QIXIS_READ(tagdata) << 8; 57 58 return minor; 59 } 60 61 char *qixis_read_time(char *result) 62 { 63 time_t time = 0; 64 int i; 65 66 /* timestamp is in 32-bit big endian */ 67 for (i = 8; i <= 11; i++) { 68 QIXIS_WRITE(tagdata, i); 69 time = (time << 8) + QIXIS_READ(tagdata); 70 } 71 72 return ctime_r(&time, result); 73 } 74 75 char *qixis_read_tag(char *buf) 76 { 77 int i; 78 char tag, *ptr = buf; 79 80 for (i = 16; i <= 63; i++) { 81 QIXIS_WRITE(tagdata, i); 82 tag = QIXIS_READ(tagdata); 83 *(ptr++) = tag; 84 if (!tag) 85 break; 86 } 87 if (i > 63) 88 *ptr = '\0'; 89 90 return buf; 91 } 92 93 /* 94 * return the string of binary of u8 in the format of 95 * 1010 10_0. The masked bit is filled as underscore. 96 */ 97 const char *byte_to_binary_mask(u8 val, u8 mask, char *buf) 98 { 99 char *ptr; 100 int i; 101 102 ptr = buf; 103 for (i = 0x80; i > 0x08 ; i >>= 1, ptr++) 104 *ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0'); 105 *(ptr++) = ' '; 106 for (i = 0x08; i > 0 ; i >>= 1, ptr++) 107 *ptr = (val & i) ? '1' : ((mask & i) ? '_' : '0'); 108 109 *ptr = '\0'; 110 111 return buf; 112 } 113 114 void qixis_reset(void) 115 { 116 QIXIS_WRITE(rst_ctl, QIXIS_RST_CTL_RESET); 117 } 118 119 void qixis_bank_reset(void) 120 { 121 QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_IDLE); 122 QIXIS_WRITE(rcfg_ctl, QIXIS_RCFG_CTL_RECONFIG_START); 123 } 124 125 /* Set the boot bank to the power-on default bank */ 126 void clear_altbank(void) 127 { 128 u8 reg; 129 130 reg = QIXIS_READ(brdcfg[0]); 131 reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_DFLTBANK; 132 QIXIS_WRITE(brdcfg[0], reg); 133 } 134 135 /* Set the boot bank to the alternate bank */ 136 void set_altbank(void) 137 { 138 u8 reg; 139 140 reg = QIXIS_READ(brdcfg[0]); 141 reg = (reg & ~QIXIS_LBMAP_MASK) | QIXIS_LBMAP_ALTBANK; 142 QIXIS_WRITE(brdcfg[0], reg); 143 } 144 145 static void qixis_dump_regs(void) 146 { 147 int i; 148 149 printf("id = %02x\n", QIXIS_READ(id)); 150 printf("arch = %02x\n", QIXIS_READ(arch)); 151 printf("scver = %02x\n", QIXIS_READ(scver)); 152 printf("model = %02x\n", QIXIS_READ(model)); 153 printf("rst_ctl = %02x\n", QIXIS_READ(rst_ctl)); 154 printf("aux = %02x\n", QIXIS_READ(aux)); 155 for (i = 0; i < 16; i++) 156 printf("brdcfg%02d = %02x\n", i, QIXIS_READ(brdcfg[i])); 157 for (i = 0; i < 16; i++) 158 printf("dutcfg%02d = %02x\n", i, QIXIS_READ(dutcfg[i])); 159 printf("sclk = %02x%02x%02x\n", QIXIS_READ(sclk[0]), 160 QIXIS_READ(sclk[1]), QIXIS_READ(sclk[2])); 161 printf("dclk = %02x%02x%02x\n", QIXIS_READ(dclk[0]), 162 QIXIS_READ(dclk[1]), QIXIS_READ(dclk[2])); 163 printf("aux = %02x\n", QIXIS_READ(aux)); 164 printf("watch = %02x\n", QIXIS_READ(watch)); 165 printf("ctl_sys = %02x\n", QIXIS_READ(ctl_sys)); 166 printf("rcw_ctl = %02x\n", QIXIS_READ(rcw_ctl)); 167 printf("present = %02x\n", QIXIS_READ(present)); 168 printf("present2 = %02x\n", QIXIS_READ(present2)); 169 printf("clk_spd = %02x\n", QIXIS_READ(clk_spd)); 170 printf("stat_dut = %02x\n", QIXIS_READ(stat_dut)); 171 printf("stat_sys = %02x\n", QIXIS_READ(stat_sys)); 172 printf("stat_alrm = %02x\n", QIXIS_READ(stat_alrm)); 173 } 174 175 static void __qixis_dump_switch(void) 176 { 177 puts("Reverse engineering switch is not implemented for this board\n"); 178 } 179 180 void qixis_dump_switch(void) 181 __attribute__((weak, alias("__qixis_dump_switch"))); 182 183 int qixis_reset_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 184 { 185 int i; 186 187 if (argc <= 1) { 188 clear_altbank(); 189 qixis_reset(); 190 } else if (strcmp(argv[1], "altbank") == 0) { 191 set_altbank(); 192 qixis_bank_reset(); 193 } else if (strcmp(argv[1], "watchdog") == 0) { 194 static char *period[9] = {"2s", "4s", "8s", "16s", "32s", 195 "1min", "2min", "4min", "8min"}; 196 u8 rcfg = QIXIS_READ(rcfg_ctl); 197 198 if (argv[2] == NULL) { 199 printf("qixis watchdog <watchdog_period>\n"); 200 return 0; 201 } 202 for (i = 0; i < ARRAY_SIZE(period); i++) { 203 if (strcmp(argv[2], period[i]) == 0) { 204 /* disable watchdog */ 205 QIXIS_WRITE(rcfg_ctl, 206 rcfg & ~QIXIS_RCFG_CTL_WATCHDOG_ENBLE); 207 QIXIS_WRITE(watch, ((i<<2) - 1)); 208 QIXIS_WRITE(rcfg_ctl, rcfg); 209 return 0; 210 } 211 } 212 } else if (strcmp(argv[1], "dump") == 0) { 213 qixis_dump_regs(); 214 return 0; 215 } else if (strcmp(argv[1], "switch") == 0) { 216 qixis_dump_switch(); 217 return 0; 218 } else { 219 printf("Invalid option: %s\n", argv[1]); 220 return 1; 221 } 222 223 return 0; 224 } 225 226 U_BOOT_CMD( 227 qixis_reset, CONFIG_SYS_MAXARGS, 1, qixis_reset_cmd, 228 "Reset the board using the FPGA sequencer", 229 "- hard reset to default bank\n" 230 "qixis_reset altbank - reset to alternate bank\n" 231 "qixis watchdog <watchdog_period> - set the watchdog period\n" 232 " period: 1s 2s 4s 8s 16s 32s 1min 2min 4min 8min\n" 233 "qixis_reset dump - display the QIXIS registers\n" 234 "qixis_reset switch - display switch\n" 235 ); 236