//####ECOSGPLCOPYRIGHTEND####
//========================================================================*/
+#include <stdlib.h>
#include <redboot.h>
#include <string.h>
#include <pkgconf/hal.h>
*/
memset((void *)ttb_base, 0, ARM_FIRST_LEVEL_PAGE_TABLE_SIZE);
- /* Actual Virtual Size Attributes Function */
+ /* Physical Virtual Size Attributes Function */
/* Base Base MB cached? buffered? access permissions */
/* xxx00000 xxx00000 */
X_ARM_MMU_SECTION(0x000, 0xF00, 0x001, ARM_CACHEABLE, ARM_BUFFERABLE, ARM_ACCESS_PERM_RW_RW); /* Boot Rom */
fec_gpio_init();
}
-static void tx27_raise_voltage(void)
+#define SOC_FBAC0_REG 0x10028800UL
+
+extern int fuse_blow(int bank, int row, int bit);
+
+#define SOC_I2C2_BASE UL(0x1001D000)
+
+/* Address offsets of the I2C registers */
+#define MXC_IADR 0x00 /* Address Register */
+#define MXC_IFDR 0x04 /* Freq div register */
+#define MXC_I2CR 0x08 /* Control regsiter */
+#define MXC_I2SR 0x0C /* Status register */
+#define MXC_I2DR 0x10 /* Data I/O register */
+
+/* Bit definitions of I2CR */
+#define MXC_I2CR_IEN 0x0080
+#define MXC_I2CR_IIEN 0x0040
+#define MXC_I2CR_MSTA 0x0020
+#define MXC_I2CR_MTX 0x0010
+#define MXC_I2CR_TXAK 0x0008
+#define MXC_I2CR_RSTA 0x0004
+
+/* Bit definitions of I2SR */
+#define MXC_I2SR_ICF 0x0080
+#define MXC_I2SR_IAAS 0x0040
+#define MXC_I2SR_IBB 0x0020
+#define MXC_I2SR_IAL 0x0010
+#define MXC_I2SR_SRW 0x0004
+#define MXC_I2SR_IIF 0x0002
+#define MXC_I2SR_RXAK 0x0001
+
+#define LP3972_SLAVE_ADDR 0x34
+
+static inline cyg_uint8 i2c_addr(cyg_uint8 addr, int rw)
+{
+ return (addr << 1) | !!rw;
+}
+
+static inline cyg_uint8 mx27_i2c_read(cyg_uint8 reg)
+{
+ cyg_uint16 val;
+ HAL_READ_UINT16(SOC_I2C2_BASE + reg, val);
+ return val;
+}
+
+static inline void mx27_i2c_write(cyg_uint8 reg, cyg_uint8 val)
+{
+ HAL_WRITE_UINT16(SOC_I2C2_BASE + reg, val);
+}
+
+static inline void mx27_i2c_set_reg(cyg_uint8 reg, cyg_uint8 set, cyg_uint8 clr)
+{
+ cyg_uint8 val = mx27_i2c_read(reg);
+ val = (val & ~clr) | set;
+ mx27_i2c_write(reg, val);
+}
+
+static void mx27_i2c_disable(void)
+{
+ /* disable I2C controller */
+ mx27_i2c_set_reg(MXC_I2CR, 0, MXC_I2CR_IEN);
+ /* disable I2C clock */
+ set_reg(SOC_CRM_PCCR0, 0, (1 << 17));
+}
+
+static int mx27_i2c_init(void)
+{
+ int ret;
+
+ /* configure PC5,PC6 as Primary Function */
+ set_reg(SOC_GPIOC_BASE + GPIO_GPR, 0, GPR_MASK(5) | GPR_MASK(6));
+ set_reg(SOC_GPIOC_BASE + GPIO_GIUS, 0, GPR_MASK(5) | GPR_MASK(6));
+
+ /* enable I2C clock */
+ set_reg(SOC_CRM_PCCR0, (1 << 17), 0);
+
+ /* setup I2C clock divider */
+ mx27_i2c_write(MXC_IFDR, 0x2c);
+ mx27_i2c_write(MXC_I2SR, 0);
+
+ /* enable I2C controller in master mode */
+ mx27_i2c_write(MXC_I2CR, MXC_I2CR_IEN);
+
+ ret = mx27_i2c_read(MXC_I2SR);
+ if (ret & MXC_I2SR_IBB) {
+ diag_printf("I2C bus busy\n");
+ mx27_i2c_disable();
+ return -EIO;
+ }
+ return 0;
+}
+
+static int mx27_i2c_wait_busy(int set)
+{
+ int ret;
+ const int max_loops = 100;
+ int retries = max_loops;
+
+ cyg_uint8 mask = set ? MXC_I2SR_IBB : 0;
+
+ while ((ret = mask ^ (mx27_i2c_read(MXC_I2SR) & MXC_I2SR_IBB)) && --retries > 0) {
+ HAL_DELAY_US(3);
+ }
+ if (ret != 0) {
+ diag_printf("i2c: Waiting for IBB to %s timed out\n", set ? "set" : "clear");
+ return -ETIMEDOUT;
+ }
+ return ret;
+}
+
+static int mx27_i2c_wait_tc(void)
+{
+ int ret;
+ const int max_loops = 1000;
+ int retries = max_loops;
+
+ while (!((ret = mx27_i2c_read(MXC_I2SR)) & MXC_I2SR_IIF) && --retries > 0) {
+ HAL_DELAY_US(3);
+ }
+ mx27_i2c_write(MXC_I2SR, 0);
+ if (!(ret & MXC_I2SR_IIF)) {
+ diag_printf("i2c: Wait for transfer completion timed out\n");
+ return -ETIMEDOUT;
+ }
+ if (ret & MXC_I2SR_ICF) {
+ if (mx27_i2c_read(MXC_I2CR) & MXC_I2CR_MTX) {
+ if (!(ret & MXC_I2SR_RXAK)) {
+ ret = 0;
+ } else {
+ diag_printf("i2c: No ACK received after writing data\n");
+ return -ENXIO;
+ }
+ }
+ }
+ return ret;
+}
+
+static int mx27_i2c_stop(void)
+{
+ int ret;
+
+ mx27_i2c_set_reg(MXC_I2CR, 0, MXC_I2CR_MSTA | MXC_I2CR_MTX);
+ ret = mx27_i2c_wait_busy(0);
+ return ret;
+}
+
+static int mx27_i2c_start(cyg_uint8 addr, int rw)
+{
+ int ret;
+
+ ret = mx27_i2c_init();
+ if (ret < 0) {
+ diag_printf("I2C bus init failed; cannot switch fuse programming voltage\n");
+ return ret;
+ }
+ mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MSTA, 0);
+ ret = mx27_i2c_wait_busy(1);
+ if (ret == 0) {
+ mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MTX, 0);
+ mx27_i2c_write(MXC_I2DR, i2c_addr(addr, rw));
+ ret = mx27_i2c_wait_tc();
+ if (ret < 0) {
+ mx27_i2c_stop();
+ }
+ }
+ return ret;
+}
+
+static int mx27_i2c_repeat_start(cyg_uint8 addr, int rw)
+{
+ int ret;
+
+ mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_RSTA, 0);
+ HAL_DELAY_US(3);
+ mx27_i2c_write(MXC_I2DR, i2c_addr(addr, rw));
+ ret = mx27_i2c_wait_tc();
+ if (ret < 0) {
+ mx27_i2c_stop();
+ }
+ return ret;
+}
+
+static int mx27_i2c_read_byte(void)
+{
+ int ret;
+
+ mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_TXAK, MXC_I2CR_MTX);
+ (void)mx27_i2c_read(MXC_I2DR); /* dummy read after address cycle */
+ ret = mx27_i2c_wait_tc();
+ mx27_i2c_stop();
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_read(MXC_I2DR);
+ return ret;
+}
+
+static int mx27_i2c_write_byte(cyg_uint8 data, int last)
+{
+ int ret;
+
+ mx27_i2c_set_reg(MXC_I2CR, MXC_I2CR_MTX, 0);
+ mx27_i2c_write(MXC_I2DR, data);
+ if ((ret = mx27_i2c_wait_tc()) < 0 || last) {
+ mx27_i2c_stop();
+ }
+ return ret;
+}
+
+static int lp3972_reg_read(cyg_uint8 reg)
+{
+ int ret;
+
+ ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_write_byte(reg, 0);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_repeat_start(LP3972_SLAVE_ADDR, 1);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_read_byte();
+ mx27_i2c_disable();
+ return ret;
+}
+
+static int lp3972_reg_write(cyg_uint8 reg, cyg_uint8 val)
{
-#if defined (CLOCK_399_133_66)
- /* Increase core voltage to 1.45 */
- setCoreVoltage(0x16);
-#endif
+ int ret;
+
+ ret = mx27_i2c_start(LP3972_SLAVE_ADDR, 0);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_write_byte(reg, 0);
+ if (ret < 0) {
+ return ret;
+ }
+ ret = mx27_i2c_write_byte(val, 1);
+ mx27_i2c_disable();
+ return ret;
}
-RedBoot_init(tx27_raise_voltage, RedBoot_INIT_PRIO(101));
+int tx27_mac_addr_program(unsigned char mac_addr[ETHER_ADDR_LEN])
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
+
+ if ((fuse | mac_addr[i]) != mac_addr[i]) {
+ diag_printf("MAC address fuse cannot be programmed: fuse[%d]=0x%02x -> 0x%02x\n",
+ i, fuse, mac_addr[i]);
+ return -1;
+ }
+ if (fuse != mac_addr[i]) {
+ ret = 1;
+ }
+ }
+ if (ret == 0) {
+ return ret;
+ }
+ ret = lp3972_reg_write(0x39, 0xf0);
+ if (ret < 0) {
+ diag_printf("Failed to switch fuse programming voltage\n");
+ return ret;
+ }
+ ret = lp3972_reg_read(0x39);
+ if (ret != 0xf0) {
+ diag_printf("Failed to switch fuse programming voltage\n");
+ return ret;
+ }
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ int bit;
+ unsigned char fuse = readl(SOC_FEC_MAC_BASE2 + (i << 2));
+
+ for (bit = 0; bit < 8; bit++) {
+ if (((mac_addr[i] >> bit) & 0x1) == 0)
+ continue;
+ if (((mac_addr[i] >> bit) & 1) == ((fuse >> bit) & 1)) {
+ continue;
+ }
+ if (fuse_blow(0, i + 5, bit)) {
+ diag_printf("Failed to blow fuse bank 0 row %d bit %d\n",
+ i, bit);
+ ret = -1;
+ goto out;
+ }
+ }
+ }
+ /* would like to blow the MAC_ADDR_LOCK fuse, but that's not available on MX27 */
+ //fuse_blow(0, 0, SOC_MAC_ADDR_LOCK_BIT);
+out:
+ lp3972_reg_write(0x39, 0);
+ return ret;
+}
#include CYGHWR_MEMORY_LAYOUT_H
}
}
+static unsigned long random;
+extern unsigned int hal_timer_count(void);
+/* provide at least _some_ sort of randomness */
+static void random_init(void)
+{
+ do {
+ srand(random + hal_timer_count());
+ random = rand();
+ } while ((hal_timer_count() < 5) || (hal_timer_count() & 0x47110815));
+}
+RedBoot_init(random_init, RedBoot_INIT_FIRST);
+
+#define WDOG_WRSR ((CYG_WORD16 *)0x10002004)
static void display_board_type(void)
{
+ char *reset_cause;
+ CYG_WORD16 wrsr;
+
diag_printf("\nBoard Type: Ka-Ro TX27\n");
+ HAL_READ_UINT16(WDOG_WRSR, wrsr);
+ switch (wrsr) {
+ case (1 << 4):
+ reset_cause = "POWER_ON RESET";
+ break;
+ case (1 << 3):
+ reset_cause = "EXTERNAL RESET";
+ break;
+ case (1 << 1):
+ reset_cause = "WATCHDOG RESET";
+ break;
+ case (1 << 0):
+ reset_cause = "SOFT RESET";
+ break;
+ default:
+ reset_cause = "UNKNOWN";
+ }
+ diag_printf("Last RESET cause: %s\n", reset_cause);
}
static void display_board_info(void)
}
RedBoot_init(display_board_info, RedBoot_INIT_LAST);
-// ------------------------------------------------------------------------