static void macb_hw_init(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; struct at91_port *pioa = (struct at91_port *)ATMEL_BASE_PIOA; struct at91_rstc *rstc = (struct at91_rstc *)ATMEL_BASE_RSTC; unsigned long erstl; /* Enable clock */ writel(1 << ATMEL_ID_EMAC0, &pmc->pcer); /* Disable pull-ups to prevent PHY going into test mode */ writel(pin_to_mask(AT91_PIN_PA14) | pin_to_mask(AT91_PIN_PA15) | pin_to_mask(AT91_PIN_PA18), &pioa->pudr); /* Power down ethernet */ pca953x_set_dir(0x28, IO_EXP_ETH_POWER, PCA953X_DIR_OUT); pca953x_set_val(0x28, IO_EXP_ETH_POWER, 1); /* Hold ethernet in reset */ pca953x_set_dir(0x28, IO_EXP_ETH_RESET, PCA953X_DIR_OUT); pca953x_set_val(0x28, IO_EXP_ETH_RESET, 0); /* Enable ethernet power */ pca953x_set_val(0x28, IO_EXP_ETH_POWER, 0); /* Need to reset PHY -> 500ms reset */ erstl = readl(&rstc->mr) & AT91_RSTC_MR_ERSTL_MASK; writel(AT91_RSTC_KEY | AT91_RSTC_MR_ERSTL(13) | AT91_RSTC_MR_URSTEN, &rstc->mr); writel(AT91_RSTC_KEY | AT91_RSTC_CR_EXTRST, &rstc->cr); /* Wait for end hardware reset */ while (!(readl(&rstc->sr) & AT91_RSTC_SR_NRSTL)) ; /* Restore NRST value */ writel(AT91_RSTC_KEY | erstl | AT91_RSTC_MR_URSTEN, &rstc->mr); /* Bring the ethernet out of reset */ pca953x_set_val(0x28, IO_EXP_ETH_RESET, 1); /* The phy internal reset take 21ms */ udelay(21 * 1000); /* Re-enable pull-up */ writel(pin_to_mask(AT91_PIN_PA14) | pin_to_mask(AT91_PIN_PA15) | pin_to_mask(AT91_PIN_PA18), &pioa->puer); at91_macb_hw_init(); }
static void leds_on(void) { /* turn on all possible leds connected via GPIO expander */ i2c_set_bus_num(2); pca953x_set_dir(CONFIG_SYS_I2C_PCA953X_ADDR, 0xffff, PCA953X_DIR_OUT); pca953x_set_val(CONFIG_SYS_I2C_PCA953X_ADDR, 0xffff, 0x0); }
static int port_exp_direction_output(unsigned gpio, int value) { int ret; i2c_set_bus_num(2); ret = i2c_probe(PORTEXP_IO_TO_CHIP(gpio)); if (ret) return ret; ret = pca953x_set_dir(PORTEXP_IO_TO_CHIP(gpio), (1 << PORTEXP_IO_TO_PIN(gpio)), (PCA953X_DIR_OUT << PORTEXP_IO_TO_PIN(gpio))); if (ret) return ret; ret = pca953x_set_val(PORTEXP_IO_TO_CHIP(gpio), (1 << PORTEXP_IO_TO_PIN(gpio)), (value << PORTEXP_IO_TO_PIN(gpio))); if (ret) return ret; return 0; }
void board_mdio_init(void) { static const uint8_t buffer1[] = { 0x1e, 0x01, 0x08, 0x00, 0x00 }; static const uint8_t buffer2[] = { 0x1e, 0x01, 0x2c, 0x00, 0x00 }; octeon_board_phy_init(); if (gd->arch.board_desc.rev_major < 2) { /* We only need to use twsi for the small number of rev 1 * boards. * For production boards (rev 2 and later) the MDIO writes above * serve the same purpose. */ i2c_set_bus_num(1); i2c_write(0x40, 5, 1, (void *)buffer1, sizeof(buffer1)); i2c_write(0x40, 5, 1, (void *)buffer2, sizeof(buffer2)); i2c_set_bus_num(0); } else if (gd->arch.board_desc.rev_major >= 5) { /* TI PHY, need to set up GPIO */ /* While ideally this should be handled by the device tree * it's too much of a pain to do this in U-Boot where U-Boot * lacks proper GPIO asbstraction so we'll just do it here. */ /* All pins are inputs except 1 and 5 which are outputs */ pca953x_set_dir(CONFIG_SYS_I2C_PCA953X_BUS, CONFIG_SYS_I2C_PCA953X_ADDR, 0, 0xDD); /* Enable the transmit */ pca953x_set_val(CONFIG_SYS_I2C_PCA953X_BUS, CONFIG_SYS_I2C_PCA953X_ADDR, 0x22, 0x00); } }
int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { static uint8_t chip = CONFIG_SYS_I2C_PCA953X_ADDR; int val; ulong ul_arg2 = 0; ulong ul_arg3 = 0; cmd_tbl_t *c; c = find_cmd_tbl(argv[1], cmd_pca953x, ARRAY_SIZE(cmd_pca953x)); /* All commands but "device" require 'maxargs' arguments */ if (!c || !((argc == (c->maxargs)) || (((int)c->cmd == PCA953X_CMD_DEVICE) && (argc == (c->maxargs - 1))))) { cmd_usage(cmdtp); return 1; } /* arg2 used as chip number or pin number */ if (argc > 2) ul_arg2 = simple_strtoul(argv[2], NULL, 16); /* arg3 used as pin or invert value */ if (argc > 3) ul_arg3 = simple_strtoul(argv[3], NULL, 16) & 0x1; switch ((int)c->cmd) { #ifdef CONFIG_CMD_PCA953X_INFO case PCA953X_CMD_INFO: return pca953x_info(chip); #endif case PCA953X_CMD_DEVICE: if (argc == 3) chip = (uint8_t)ul_arg2; printf("Current device address: 0x%x\n", chip); return 0; case PCA953X_CMD_INPUT: pca953x_set_dir(chip, (1 << ul_arg2), PCA953X_DIR_IN << ul_arg2); val = (pca953x_get_val(chip) & (1 << ul_arg2)) != 0; printf("chip 0x%02x, pin 0x%lx = %d\n", chip, ul_arg2, val); return val; case PCA953X_CMD_OUTPUT: pca953x_set_dir(chip, (1 << ul_arg2), (PCA953X_DIR_OUT << ul_arg2)); return pca953x_set_val(chip, (1 << ul_arg2), (ul_arg3 << ul_arg2)); case PCA953X_CMD_INVERT: return pca953x_set_pol(chip, (1 << ul_arg2), (ul_arg3 << ul_arg2)); default: /* We should never get here */ return 1; } }
static void macb_hw_init(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; struct at91_port *pioa = (struct at91_port *)ATMEL_BASE_PIOA; /* Enable clock */ writel(1 << ATMEL_ID_EMAC0, &pmc->pcer); /* Disable pull-ups to prevent PHY going into test mode */ writel(pin_to_mask(AT91_PIN_PA14) | pin_to_mask(AT91_PIN_PA15) | pin_to_mask(AT91_PIN_PA18), &pioa->pudr); /* Power down ethernet */ pca953x_set_dir(0x28, IO_EXP_ETH_POWER, PCA953X_DIR_OUT); pca953x_set_val(0x28, IO_EXP_ETH_POWER, 1); /* Hold ethernet in reset */ pca953x_set_dir(0x28, IO_EXP_ETH_RESET, PCA953X_DIR_OUT); pca953x_set_val(0x28, IO_EXP_ETH_RESET, 0); /* Enable ethernet power */ pca953x_set_val(0x28, IO_EXP_ETH_POWER, 0); at91_phy_reset(); /* Bring the ethernet out of reset */ pca953x_set_val(0x28, IO_EXP_ETH_RESET, 1); /* The phy internal reset take 21ms */ udelay(21 * 1000); /* Re-enable pull-up */ writel(pin_to_mask(AT91_PIN_PA14) | pin_to_mask(AT91_PIN_PA15) | pin_to_mask(AT91_PIN_PA18), &pioa->puer); at91_macb_hw_init(); }
int last_stage_init(void) { int slaves; uint k; uchar mclink_controllers[] = { 0x3c, 0x3d, 0x3e }; u16 fpga_features; bool hw_type_cat = pca9698_get_value(0x20, 20); bool ch0_rgmii2_present; FPGA_GET_REG(0, fpga_features, &fpga_features); /* Turn on Parade DP501 */ pca9698_direction_output(0x20, 10, 1); pca9698_direction_output(0x20, 11, 1); ch0_rgmii2_present = !pca9698_get_value(0x20, 30); /* wait for FPGA done, then reset FPGA */ for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) { uint ctr = 0; if (i2c_probe(mclink_controllers[k])) continue; while (!(pca953x_get_val(mclink_controllers[k]) & MCFPGA_DONE)) { mdelay(100); if (ctr++ > 5) { printf("no done for mclink_controller %u\n", k); break; } } pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0); udelay(10); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, MCFPGA_RESET_N); } if (hw_type_cat) { uint mux_ch; int retval; struct mii_dev *mdiodev = mdio_alloc(); if (!mdiodev) return -ENOMEM; strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN); mdiodev->read = bb_miiphy_read; mdiodev->write = bb_miiphy_write; retval = mdio_register(mdiodev); if (retval < 0) return retval; for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) { if ((mux_ch == 1) && !ch0_rgmii2_present) continue; setup_88e1514(bb_miiphy_buses[0].name, mux_ch); } } /* give slave-PLLs and Parade DP501 some time to be up and running */ mdelay(500); mclink_fpgacount = CONFIG_SYS_MCLINK_MAX; slaves = mclink_probe(); mclink_fpgacount = 0; ioep_fpga_print_info(0); osd_probe(0); #ifdef CONFIG_SYS_OSD_DH osd_probe(4); #endif if (slaves <= 0) return 0; mclink_fpgacount = slaves; for (k = 1; k <= slaves; ++k) { FPGA_GET_REG(k, fpga_features, &fpga_features); ioep_fpga_print_info(k); osd_probe(k); #ifdef CONFIG_SYS_OSD_DH osd_probe(k + 4); #endif if (hw_type_cat) { int retval; struct mii_dev *mdiodev = mdio_alloc(); if (!mdiodev) return -ENOMEM; strncpy(mdiodev->name, bb_miiphy_buses[k].name, MDIO_NAME_LEN); mdiodev->read = bb_miiphy_read; mdiodev->write = bb_miiphy_write; retval = mdio_register(mdiodev); if (retval < 0) return retval; setup_88e1514(bb_miiphy_buses[k].name, 0); } } for (k = 0; k < ARRAY_SIZE(hrcon_fans); ++k) { i2c_set_bus_num(hrcon_fans[k].bus); init_fan_controller(hrcon_fans[k].addr); } return 0; }
int last_stage_init(void) { int slaves; unsigned int k; unsigned int mux_ch; unsigned char mclink_controllers[] = { 0x3c, 0x3d, 0x3e }; bool hw_type_cat = pca9698_get_value(0x20, 18); bool ch0_sgmii2_present = false; /* Turn on Analog Devices ADV7611 */ pca9698_direction_output(0x20, 8, 0); /* Turn on Parade DP501 */ pca9698_direction_output(0x20, 9, 1); ch0_sgmii2_present = !pca9698_get_value(0x20, 37); /* wait for FPGA done, then reset FPGA */ for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) { unsigned int ctr = 0; if (i2c_probe(mclink_controllers[k])) continue; while (!(pca953x_get_val(mclink_controllers[k]) & MCFPGA_DONE)) { udelay(100000); if (ctr++ > 5) { printf("no done for mclink_controller %d\n", k); break; } } pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0); udelay(10); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, MCFPGA_RESET_N); } if (hw_type_cat) { miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read, bb_miiphy_write); for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) { if ((mux_ch == 1) && !ch0_sgmii2_present) continue; setup_88e1514(bb_miiphy_buses[0].name, mux_ch); } } /* give slave-PLLs and Parade DP501 some time to be up and running */ udelay(500000); mclink_fpgacount = CONFIG_SYS_MCLINK_MAX; slaves = mclink_probe(); mclink_fpgacount = 0; ioep_fpga_print_info(0); if (!adv7611_probe(0)) printf(" Advantiv ADV7611 HDMI Receiver\n"); #ifdef CONFIG_STRIDER_CON if (ioep_fpga_has_osd(0)) osd_probe(0); #endif #ifdef CONFIG_STRIDER_CPU ch7301_probe(0, false); #endif if (slaves <= 0) return 0; mclink_fpgacount = slaves; for (k = 1; k <= slaves; ++k) { ioep_fpga_print_info(k); #ifdef CONFIG_STRIDER_CON if (ioep_fpga_has_osd(k)) osd_probe(k); #endif #ifdef CONFIG_STRIDER_CPU FPGA_SET_REG(k, extended_control, 0); /* enable video in*/ if (!adv7611_probe(k)) printf(" Advantiv ADV7611 HDMI Receiver\n"); ch7301_probe(k, false); #endif if (hw_type_cat) { miiphy_register(bb_miiphy_buses[k].name, bb_miiphy_read, bb_miiphy_write); setup_88e1514(bb_miiphy_buses[k].name, 0); } } for (k = 0; k < ARRAY_SIZE(strider_fans); ++k) { i2c_set_bus_num(strider_fans[k].bus); init_fan_controller(strider_fans[k].addr); } return 0; }
int early_board_init(void) { uint8_t val; /* Disable USB power */ gpio_direction_output(1, 1); gpio_direction_output(2, 1); gpio_direction_input(3); /* SD/MMC Write Protect */ gpio_direction_input(2); /* SD/MMC Card Detect */ mdelay(10); if (PCA953X_DIR_IN != 0) val = 0xff; else val = 0; /* Make all pins inputs */ pca953x_set_dir(0, 0x20, 0xff, val); /* Set output GPIOs 0-1, 4-7 */ val = (val & ~(1 << 0)) | PCA953X_DIR_OUT << 0; val = (val & ~(1 << 1)) | PCA953X_DIR_OUT << 1; val = (val & ~(1 << 2)) | PCA953X_DIR_IN << 2; val = (val & ~(1 << 3)) | PCA953X_DIR_IN << 3; val = (val & ~(1 << 4)) | PCA953X_DIR_OUT << 4; val = (val & ~(1 << 5)) | PCA953X_DIR_OUT << 5; val = (val & ~(1 << 6)) | PCA953X_DIR_OUT << 6; val = (val & ~(1 << 7)) | PCA953X_DIR_OUT << 7; pca953x_set_dir(0, 0x21, 0xff, val); /* Put PHYs in reset */ pca953x_set_val(0, 0x21, 1 << 4, 0x00); mdelay(10); /* Take PHY out of reset */ pca953x_set_val(0, 0x21, 1 << 4, 1 << 4); /* Populate global data from eeprom */ octeon_board_get_clock_info(SFF7000_DEF_DRAM_FREQ); octeon_board_get_descriptor(CVMX_BOARD_TYPE_SFF7000, 1, 0); /* Enable temperature and fan monitoring */ i2c_set_bus_num(CONFIG_SYS_DTT_BUS_NUM); val = i2c_reg_read(CONFIG_SYS_I2C_DTT_ADDR, 0); /* Invert output, turn on tach, 2-wire analog and enable monitoring */ val |= 0xd; i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 0, val); val = i2c_reg_read(CONFIG_SYS_I2C_DTT_ADDR, 1); /* Turn off tach 2 and remote 2 temperature sensor */ val &= ~0x48; i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 1, val); /* Enable fan filtering for fan 1 */ val = i2c_reg_read(CONFIG_SYS_I2C_DTT_ADDR, 0x23); val |= 1; i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 0x23, val); /* 800ms spin-up, 93.5KHz PWM, lowest speed 2647RPM */ val = 0x3b; i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 0x20, val); val = 0x63; /* CPU fan enable temp 48C, range starts at 40C */ i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 0x25, val); val = 0x52; /* PWM for fan 1 starts at 14%, 33% for fan 2 */ i2c_reg_write(CONFIG_SYS_I2C_DTT_ADDR, 0x25, val); /* CN63XX has a fixed 50 MHz reference clock */ gd->arch.ddr_ref_hertz = 50000000; octeon_board_get_mac_addr(); return 0; }
int last_stage_init(void) { int slaves; unsigned int k; unsigned int mux_ch; unsigned char mclink_controllers_dvi[] = { 0x3c, 0x3d, 0x3e }; #ifdef CONFIG_STRIDER_CPU unsigned char mclink_controllers_dp[] = { 0x24, 0x25, 0x26 }; #endif bool hw_type_cat = pca9698_get_value(0x20, 18); #ifdef CONFIG_STRIDER_CON_DP bool is_dh = pca9698_get_value(0x20, 25); #endif bool ch0_sgmii2_present = false; /* Turn on Analog Devices ADV7611 */ pca9698_direction_output(0x20, 8, 0); /* Turn on Parade DP501 */ pca9698_direction_output(0x20, 10, 1); pca9698_direction_output(0x20, 11, 1); ch0_sgmii2_present = !pca9698_get_value(0x20, 37); /* wait for FPGA done, then reset FPGA */ for (k = 0; k < ARRAY_SIZE(mclink_controllers_dvi); ++k) { unsigned int ctr = 0; unsigned char *mclink_controllers = mclink_controllers_dvi; #ifdef CONFIG_STRIDER_CPU if (i2c_probe(mclink_controllers[k])) { mclink_controllers = mclink_controllers_dp; if (i2c_probe(mclink_controllers[k])) continue; } #else if (i2c_probe(mclink_controllers[k])) continue; #endif while (!(pca953x_get_val(mclink_controllers[k]) & MCFPGA_DONE)) { udelay(100000); if (ctr++ > 5) { printf("no done for mclink_controller %d\n", k); break; } } pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0); udelay(10); pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, MCFPGA_RESET_N); } if (hw_type_cat) { int retval; struct mii_dev *mdiodev = mdio_alloc(); if (!mdiodev) return -ENOMEM; strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN); mdiodev->read = bb_miiphy_read; mdiodev->write = bb_miiphy_write; retval = mdio_register(mdiodev); if (retval < 0) return retval; for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) { if ((mux_ch == 1) && !ch0_sgmii2_present) continue; setup_88e1514(bb_miiphy_buses[0].name, mux_ch); } } /* give slave-PLLs and Parade DP501 some time to be up and running */ udelay(500000); mclink_fpgacount = CONFIG_SYS_MCLINK_MAX; slaves = mclink_probe(); mclink_fpgacount = 0; ioep_fpga_print_info(0); if (!adv7611_probe(0)) printf(" Advantiv ADV7611 HDMI Receiver\n"); #ifdef CONFIG_STRIDER_CON if (ioep_fpga_has_osd(0)) osd_probe(0); #endif #ifdef CONFIG_STRIDER_CON_DP if (ioep_fpga_has_osd(0)) { osd_probe(0); if (is_dh) osd_probe(4); } #endif #ifdef CONFIG_STRIDER_CPU ch7301_probe(0, false); dp501_probe(0, false); #endif if (slaves <= 0) return 0; mclink_fpgacount = slaves; #ifdef CONFIG_STRIDER_CPU /* get ADV7611 out of reset, power up DP501, give some time to wakeup */ for (k = 1; k <= slaves; ++k) FPGA_SET_REG(k, extended_control, 0x10); /* enable video */ udelay(500000); #endif for (k = 1; k <= slaves; ++k) { ioep_fpga_print_info(k); #ifdef CONFIG_STRIDER_CON if (ioep_fpga_has_osd(k)) osd_probe(k); #endif #ifdef CONFIG_STRIDER_CON_DP if (ioep_fpga_has_osd(k)) { osd_probe(k); if (is_dh) osd_probe(k + 4); } #endif #ifdef CONFIG_STRIDER_CPU if (!adv7611_probe(k)) printf(" Advantiv ADV7611 HDMI Receiver\n"); ch7301_probe(k, false); dp501_probe(k, false); #endif if (hw_type_cat) { int retval; struct mii_dev *mdiodev = mdio_alloc(); if (!mdiodev) return -ENOMEM; strncpy(mdiodev->name, bb_miiphy_buses[k].name, MDIO_NAME_LEN); mdiodev->read = bb_miiphy_read; mdiodev->write = bb_miiphy_write; retval = mdio_register(mdiodev); if (retval < 0) return retval; setup_88e1514(bb_miiphy_buses[k].name, 0); } } for (k = 0; k < ARRAY_SIZE(strider_fans); ++k) { i2c_set_bus_num(strider_fans[k].bus); init_fan_controller(strider_fans[k].addr); } return 0; }
int do_pca953x(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { static uint8_t chip = CONFIG_SYS_I2C_PCA953X_ADDR; int ret = CMD_RET_USAGE, val; ulong ul_arg2 = 0; ulong ul_arg3 = 0; cmd_tbl_t *c; c = find_cmd_tbl(argv[1], cmd_pca953x, ARRAY_SIZE(cmd_pca953x)); /* All commands but "device" require 'maxargs' arguments */ if (!c || !((argc == (c->maxargs)) || (((int)c->cmd == PCA953X_CMD_DEVICE) && (argc == (c->maxargs - 1))))) { return CMD_RET_USAGE; } /* arg2 used as chip number or pin number */ if (argc > 2) ul_arg2 = simple_strtoul(argv[2], NULL, 16); /* arg3 used as pin or invert value */ if (argc > 3) ul_arg3 = simple_strtoul(argv[3], NULL, 16) & 0x1; switch ((int)c->cmd) { #ifdef CONFIG_CMD_PCA953X_INFO case PCA953X_CMD_INFO: ret = pca953x_info(chip); if (ret) ret = CMD_RET_FAILURE; break; #endif case PCA953X_CMD_DEVICE: if (argc == 3) chip = (uint8_t)ul_arg2; printf("Current device address: 0x%x\n", chip); ret = CMD_RET_SUCCESS; break; case PCA953X_CMD_INPUT: ret = pca953x_set_dir(chip, (1 << ul_arg2), PCA953X_DIR_IN << ul_arg2); val = (pca953x_get_val(chip) & (1 << ul_arg2)) != 0; if (ret) ret = CMD_RET_FAILURE; else printf("chip 0x%02x, pin 0x%lx = %d\n", chip, ul_arg2, val); break; case PCA953X_CMD_OUTPUT: ret = pca953x_set_dir(chip, (1 << ul_arg2), (PCA953X_DIR_OUT << ul_arg2)); if (!ret) ret = pca953x_set_val(chip, (1 << ul_arg2), (ul_arg3 << ul_arg2)); if (ret) ret = CMD_RET_FAILURE; break; case PCA953X_CMD_INVERT: ret = pca953x_set_pol(chip, (1 << ul_arg2), (ul_arg3 << ul_arg2)); if (ret) ret = CMD_RET_FAILURE; break; } if (ret == CMD_RET_FAILURE) eprintf("Error talking to chip at 0x%x\n", chip); return ret; }