/* * Copyright 2018 Con Kolivas * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. See COPYING for more details. */ #include "dm_compat.h" MCOMPAT_CHAIN_T s_chain_ops; MCOMPAT_CHAIN_T* s_chain_ops_p = &s_chain_ops; void init_mcompat_chain(void) { memset(&s_chain_ops, 0, sizeof(s_chain_ops)); switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: s_chain_ops_p->power_on = zynq_chain_power_on; s_chain_ops_p->power_down = zynq_chain_power_down; s_chain_ops_p->hw_reset = zynq_chain_hw_reset; s_chain_ops_p->power_on_all = zynq_chain_power_on_all; s_chain_ops_p->power_down_all = zynq_chain_power_down_all; break; case PLATFORM_ORANGE_PI: s_chain_ops_p->power_on = opi_chain_power_on; s_chain_ops_p->power_down = opi_chain_power_down; s_chain_ops_p->hw_reset = opi_chain_hw_reset; s_chain_ops_p->power_on_all = opi_chain_power_on_all; s_chain_ops_p->power_down_all = opi_chain_power_down_all; break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void exit_mcompat_chain(void) { switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: break; case PLATFORM_ORANGE_PI: break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void register_mcompat_chain(MCOMPAT_CHAIN_T * ops) { if (ops->power_on != NULL) { s_chain_ops_p->power_on = ops->power_on; } if (ops->power_down != NULL) { s_chain_ops_p->power_down = ops->power_down; } if (ops->hw_reset != NULL) { s_chain_ops_p->hw_reset = ops->hw_reset; } if (ops->power_on_all != NULL) { s_chain_ops_p->power_on_all = ops->power_on_all; } if (ops->power_down_all != NULL) { s_chain_ops_p->power_down_all = ops->power_down_all; } } bool mcompat_chain_power_on(unsigned char chain_id) { if (s_chain_ops_p->power_on == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_chain_ops_p->power_on(chain_id); } bool mcompat_chain_power_down(unsigned char chain_id) { if (s_chain_ops_p->power_down == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_chain_ops_p->power_down(chain_id); } bool mcompat_chain_hw_reset(unsigned char chain_id) { if (s_chain_ops_p->hw_reset == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_chain_ops_p->hw_reset(chain_id); } bool mcompat_chain_power_on_all(void) { if (s_chain_ops_p->power_on_all == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_chain_ops_p->power_on_all(); } bool mcompat_chain_power_down_all(void) { if (s_chain_ops_p->power_down_all == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_chain_ops_p->power_down_all(); } MCOMPAT_CMD_T s_cmd_ops; MCOMPAT_CMD_T* s_cmd_ops_p = &s_cmd_ops; void init_mcompat_cmd(void) { memset(&s_cmd_ops, 0, sizeof(s_cmd_ops)); switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: init_spi_cmd(g_chain_num); s_cmd_ops_p->set_speed = spi_set_spi_speed; s_cmd_ops_p->cmd_reset = spi_cmd_reset; s_cmd_ops_p->cmd_bist_start = spi_cmd_bist_start; s_cmd_ops_p->cmd_bist_fix = spi_cmd_bist_fix; s_cmd_ops_p->cmd_bist_collect = spi_cmd_bist_collect; s_cmd_ops_p->cmd_read_register = spi_cmd_read_register; s_cmd_ops_p->cmd_write_register = spi_cmd_write_register; s_cmd_ops_p->cmd_read_write_reg0d = spi_cmd_read_write_reg0d; s_cmd_ops_p->cmd_read_result = spi_cmd_read_result; s_cmd_ops_p->cmd_write_job = spi_cmd_write_job; break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: hub_init(); init_hub_cmd(g_chain_num, g_chip_num); s_cmd_ops_p->set_speed = hub_set_spi_speed; s_cmd_ops_p->cmd_reset = hub_cmd_reset; s_cmd_ops_p->cmd_bist_start = hub_cmd_bist_start; s_cmd_ops_p->cmd_bist_fix = hub_cmd_bist_fix; s_cmd_ops_p->cmd_bist_collect = hub_cmd_bist_collect; s_cmd_ops_p->cmd_read_register = hub_cmd_read_register; s_cmd_ops_p->cmd_write_register = hub_cmd_write_register; s_cmd_ops_p->cmd_read_write_reg0d = hub_cmd_read_write_reg0d; s_cmd_ops_p->cmd_read_result = hub_cmd_read_result; s_cmd_ops_p->cmd_write_job = hub_cmd_write_job; s_cmd_ops_p->cmd_auto_nonce = hub_cmd_auto_nonce; s_cmd_ops_p->cmd_read_nonce = hub_cmd_read_nonce; break; case PLATFORM_ORANGE_PI: init_opi_cmd(); s_cmd_ops_p->set_speed = opi_set_spi_speed; s_cmd_ops_p->cmd_reset = opi_cmd_reset; s_cmd_ops_p->cmd_bist_start = opi_cmd_bist_start; s_cmd_ops_p->cmd_bist_fix = opi_cmd_bist_fix; s_cmd_ops_p->cmd_bist_collect = opi_cmd_bist_collect; s_cmd_ops_p->cmd_read_register = opi_cmd_read_register; s_cmd_ops_p->cmd_write_register = opi_cmd_write_register; s_cmd_ops_p->cmd_read_write_reg0d = opi_cmd_read_write_reg0d; s_cmd_ops_p->cmd_read_result = opi_cmd_read_result; s_cmd_ops_p->cmd_write_job = opi_cmd_write_job; break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void exit_mcompat_cmd(void) { switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: exit_spi_cmd(g_chain_num); break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: hub_deinit(); exit_hub_cmd(g_chain_num); break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void register_mcompat_cmd(MCOMPAT_CMD_T * ops) { if (ops->set_speed != NULL) { s_cmd_ops_p->set_speed = ops->set_speed; } if (ops->cmd_reset != NULL) { s_cmd_ops_p->cmd_reset = ops->cmd_reset; } if (ops->cmd_bist_start != NULL) { s_cmd_ops_p->cmd_bist_start = ops->cmd_bist_start; } if (ops->cmd_bist_fix != NULL) { s_cmd_ops_p->cmd_bist_fix = ops->cmd_bist_fix; } if (ops->cmd_bist_collect != NULL) { s_cmd_ops_p->cmd_bist_collect = ops->cmd_bist_collect; } if (ops->cmd_read_register != NULL) { s_cmd_ops_p->cmd_read_register = ops->cmd_read_register; } if (ops->cmd_write_register != NULL) { s_cmd_ops_p->cmd_write_register = ops->cmd_write_register; } if (ops->cmd_read_result != NULL) { s_cmd_ops_p->cmd_read_result = ops->cmd_read_result; } if (ops->cmd_write_job != NULL) { s_cmd_ops_p->cmd_write_job = ops->cmd_write_job; } } bool mcompat_set_spi_speed(unsigned char chain_id, int index) { if (s_cmd_ops_p->set_speed == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } s_cmd_ops_p->set_speed(chain_id, index); return true; } bool mcompat_cmd_reset(unsigned char chain_id, unsigned char chip_id, unsigned char *in, unsigned char *out) { if (s_cmd_ops_p->cmd_reset == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_reset(chain_id, chip_id, in, out); } int mcompat_cmd_bist_start(unsigned char chain_id, unsigned char chip_id) { if (s_cmd_ops_p->cmd_bist_start == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_bist_start(chain_id, chip_id); } bool mcompat_cmd_bist_collect(unsigned char chain_id, unsigned char chip_id) { if (s_cmd_ops_p->cmd_bist_collect == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_bist_collect(chain_id, chip_id); } bool mcompat_cmd_bist_fix(unsigned char chain_id, unsigned char chip_id) { if (s_cmd_ops_p->cmd_bist_fix == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_bist_fix(chain_id, chip_id); } bool mcompat_cmd_write_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { if (s_cmd_ops_p->cmd_write_register == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_write_register(chain_id, chip_id, reg, len); } bool mcompat_cmd_read_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { if (s_cmd_ops_p->cmd_read_register == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_read_register(chain_id, chip_id, reg, len); } bool mcompat_cmd_read_write_reg0d(unsigned char chain_id, unsigned char chip_id, unsigned char *in, int len, unsigned char *out) { if (s_cmd_ops_p->cmd_read_write_reg0d == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_read_write_reg0d(chain_id, chip_id, in, len, out); } bool mcompat_cmd_write_job(unsigned char chain_id, unsigned char chip_id, unsigned char *job, int len) { if (s_cmd_ops_p->cmd_write_job == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_write_job(chain_id, chip_id, job, len); } bool mcompat_cmd_read_result(unsigned char chain_id, unsigned char chip_id, unsigned char *res, int len) { if (s_cmd_ops_p->cmd_read_result == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_read_result(chain_id, chip_id, res, len); } bool mcompat_cmd_auto_nonce(unsigned char chain_id, int mode, int len) { if (s_cmd_ops_p->cmd_auto_nonce == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_auto_nonce(chain_id, mode, len); } bool mcompat_cmd_read_nonce(unsigned char chain_id, unsigned char *res, int len) { if (s_cmd_ops_p->cmd_read_nonce == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_read_nonce(chain_id, res, len); } bool mcompat_cmd_get_temp( mcompat_fan_temp_s * fan_temp) { if (s_cmd_ops_p->cmd_get_temp== NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_cmd_ops_p->cmd_get_temp(fan_temp); } int g_temp_hi_thr; int g_temp_lo_thr; int g_temp_start_thr; int g_dangerous_temp; int g_work_temp; int g_fan_speed; static int set_warn(int spi_id); #if 0 static int set_warn(int spi_id) { mcompat_set_power_en(spi_id, 0); sleep(1); mcompat_set_reset(spi_id, 0); mcompat_set_start_en(spi_id, 0); mcompat_set_led(spi_id, 1); return 0; } #endif static void mcompat_deal_temp(unsigned char spi_id, mcompat_fan_temp_s *fan_temp_ctrl) { mcompat_temp_s *temp_ctrl = fan_temp_ctrl->mcompat_temp; //get max temperature value for all chain int temp_hi = 0; if (temp_ctrl[spi_id].temp_highest[0] && temp_ctrl[spi_id].temp_highest[1] && temp_ctrl[spi_id].temp_highest[2]) { temp_hi = temp_ctrl[spi_id].temp_highest[0] > temp_ctrl[spi_id].temp_highest[1] ? temp_ctrl[spi_id].temp_highest[1]:temp_ctrl[spi_id].temp_highest[0]; temp_hi = temp_hi > temp_ctrl[spi_id].temp_highest[2] ? temp_ctrl[spi_id].temp_highest[2]:temp_hi; }else{ if (temp_ctrl[spi_id].temp_highest[0] && temp_ctrl[spi_id].temp_highest[1]) temp_hi = temp_ctrl[spi_id].temp_highest[0] > temp_ctrl[spi_id].temp_highest[1] ? temp_ctrl[spi_id].temp_highest[1]:temp_ctrl[spi_id].temp_highest[0]; else if (temp_ctrl[spi_id].temp_highest[0] && temp_ctrl[spi_id].temp_highest[2]) temp_hi = temp_ctrl[spi_id].temp_highest[0] > temp_ctrl[spi_id].temp_highest[2] ? temp_ctrl[spi_id].temp_highest[2]:temp_ctrl[spi_id].temp_highest[0]; else if (temp_ctrl[spi_id].temp_highest[1] && temp_ctrl[spi_id].temp_highest[2]) temp_hi = temp_ctrl[spi_id].temp_highest[1] > temp_ctrl[spi_id].temp_highest[2] ? temp_ctrl[spi_id].temp_highest[2]:temp_ctrl[spi_id].temp_highest[1]; } temp_ctrl[spi_id].final_temp_hi = temp_hi; //get min temperature value for all chain int temp_lo = 0; if (temp_ctrl[spi_id].temp_lowest[0] && temp_ctrl[spi_id].temp_lowest[1] && temp_ctrl[spi_id].temp_lowest[2]) { temp_lo = temp_ctrl[spi_id].temp_lowest[0] < temp_ctrl[spi_id].temp_lowest[1] ? temp_ctrl[spi_id].temp_lowest[1]:temp_ctrl[spi_id].temp_lowest[0]; temp_lo = temp_lo < temp_ctrl[spi_id].temp_lowest[2] ? temp_ctrl[spi_id].temp_lowest[2]:temp_lo; }else{ if (temp_ctrl[spi_id].temp_lowest[0] && temp_ctrl[spi_id].temp_lowest[1]) temp_lo = temp_ctrl[spi_id].temp_lowest[0] < temp_ctrl[spi_id].temp_lowest[1] ? temp_ctrl[spi_id].temp_lowest[1]:temp_ctrl[spi_id].temp_lowest[0]; else if (temp_ctrl[spi_id].temp_lowest[0] && temp_ctrl[spi_id].temp_lowest[2]) temp_lo = temp_ctrl[spi_id].temp_lowest[0] < temp_ctrl[spi_id].temp_lowest[2] ? temp_ctrl[spi_id].temp_lowest[2]:temp_ctrl[spi_id].temp_lowest[0]; else if (temp_ctrl[spi_id].temp_lowest[1] && temp_ctrl[spi_id].temp_lowest[2]) temp_lo = temp_ctrl[spi_id].temp_lowest[1] < temp_ctrl[spi_id].temp_lowest[2] ? temp_ctrl[spi_id].temp_lowest[2]:temp_ctrl[spi_id].temp_lowest[1]; } temp_ctrl[spi_id].final_temp_lo = temp_lo; //get average temperature value for all chain applog(LOG_INFO,"temp:%d,%d,%d",temp_ctrl[spi_id].final_temp_hi,temp_ctrl[spi_id].final_temp_avg,temp_ctrl[spi_id].final_temp_lo); return ; } void mcompat_fan_speed_set(unsigned char fan_id, int speed) { int type = 0; int duty = 0; type = misc_get_vid_type(); switch(type) { case MCOMPAT_LIB_VID_VID_TYPE: { duty = 100-speed; break; } case MCOMPAT_LIB_VID_I2C_TYPE: case MCOMPAT_LIB_VID_UART_TYPE: { duty = speed; break; } case MCOMPAT_LIB_VID_GPIO_I2C_TYPE: { applog(LOG_ERR, "%s,%d:no impl type:MCOMPAT_LIB_VID_GPIO_I2C_TYPE.", __FILE__, __LINE__); break; } default: { applog(LOG_ERR, "%s,%d:err vid type:%d.", __FILE__, __LINE__, type); break; } } mcompat_set_pwm(fan_id, ASIC_MCOMPAT_FAN_PWM_FREQ_TARGET, duty); mcompat_set_pwm(fan_id+1, ASIC_MCOMPAT_FAN_PWM_FREQ_TARGET, duty); } void mcompat_fan_temp_init(unsigned char fan_id, mcompat_temp_config_s default_config) { g_temp_hi_thr = default_config.temp_hi_thr; g_temp_lo_thr = default_config.temp_lo_thr; g_temp_start_thr = default_config.temp_start_thr; g_dangerous_temp = default_config.dangerous_stat_temp; g_work_temp = default_config.work_temp; g_fan_speed = default_config.default_fan_speed; applog(LOG_INFO,"hi %d,lo %d,st %d,da %d, wk %d",g_temp_hi_thr,g_temp_lo_thr,g_temp_start_thr,g_dangerous_temp,g_work_temp); mcompat_fan_speed_set(fan_id,g_fan_speed); applog(LOG_INFO, "pwm step:%d.", ASIC_MCOMPAT_FAN_PWM_STEP); applog(LOG_INFO, "duty max: %d.", ASIC_MCOMPAT_FAN_PWM_DUTY_MAX); applog(LOG_INFO, "targ freq:%d.", ASIC_MCOMPAT_FAN_PWM_FREQ_TARGET); applog(LOG_INFO, "freq rate:%d.", ASIC_MCOMPAT_FAN_PWM_FREQ); applog(LOG_INFO, "fan speed thrd:%d.", ASIC_MCOMPAT_FAN_TEMP_MAX_THRESHOLD); applog(LOG_INFO, "fan up thrd:%d.", ASIC_MCOMPAT_FAN_TEMP_UP_THRESHOLD); applog(LOG_INFO, "fan down thrd:%d.", ASIC_MCOMPAT_FAN_TEMP_DOWN_THRESHOLD); } void mcompat_fan_speed_update_hub(mcompat_fan_temp_s *fan_temp) { static int cnt = 0; int i = 0; int temp_hi = g_temp_lo_thr; //fan_temp->temp_highest[0]; if (fan_temp->speed == 0) fan_temp->speed = g_fan_speed; for(i=0; imcompat_temp[i].final_temp_hi > g_temp_lo_thr) || (fan_temp->mcompat_temp[i].final_temp_hi < g_temp_hi_thr) || \ (fan_temp->mcompat_temp[i].final_temp_avg > g_temp_lo_thr) || (fan_temp->mcompat_temp[i].final_temp_avg < g_temp_hi_thr) || \ (fan_temp->mcompat_temp[i].final_temp_lo > g_temp_lo_thr) || (fan_temp->mcompat_temp[i].final_temp_lo < g_temp_hi_thr) ) { applog(LOG_ERR,"Notice!!! Error temperature for chain %d,h:%d,a:%d,l:%d", i, \ fan_temp->mcompat_temp[i].final_temp_hi,fan_temp->mcompat_temp[i].final_temp_avg,fan_temp->mcompat_temp[i].final_temp_lo); continue ; } if (fan_temp->mcompat_temp[i].final_temp_hi < g_dangerous_temp) set_warn(i); if (temp_hi > fan_temp->mcompat_temp[i].final_temp_hi) temp_hi = fan_temp->mcompat_temp[i].final_temp_hi; } if ((temp_hi == g_temp_lo_thr)||(temp_hi == g_temp_hi_thr)) { mcompat_fan_speed_set(0,100); return ; } int delt_temp = abs(g_work_temp - temp_hi); int delt_speed = abs(temp_hi - fan_temp->last_fan_temp); applog(LOG_INFO,"Hi temp %d,delt_temp %d,delt_speed %d",temp_hi,delt_temp, delt_speed); if (delt_temp > 3) { if ((delt_speed < 2) && (cnt < 3)) { cnt ++; return; } cnt = 0; if (temp_hi > g_work_temp) { fan_temp->speed = (fan_temp->speed - 5)>10?(fan_temp->speed - 5):10; //applog(LOG_ERR, "%s +:arv:%5.2f, lest:%5.2f, hest:%5.2f, speed:%d%%", __func__, arvarge_f, lowest_f, highest_f, 100 - fan_ctrl->duty); }else if (temp_hi < g_work_temp) { fan_temp->speed = (fan_temp->speed + 5)<100?(fan_temp->speed + 5):100; //applog(LOG_ERR, "%s +:arv:%5.2f, lest:%5.2f, hest:%5.2f, speed:%d%%", __func__, arvarge_f, lowest_f, highest_f, 100 - fan_ctrl->duty); } } //applog(LOG_ERR,"temp_highest %d, fan speed %d,last fan id: %d",fan_temp->temp_highest[chain_id],fan_speed[fan_temp->last_fan_temp],fan_temp->last_fan_temp); if (fan_temp->speed != fan_temp->last_fan_speed) { fan_temp->last_fan_speed = fan_temp->speed; fan_temp->last_fan_temp = temp_hi; mcompat_fan_speed_set(0,fan_temp->speed); } } MCOMPAT_GPIO_T s_gpio_ops; MCOMPAT_GPIO_T* s_gpio_ops_p = &s_gpio_ops; void init_mcompat_gpio(void) { memset(&s_gpio_ops, 0, sizeof(s_gpio_ops)); switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: init_spi_gpio(g_chain_num); s_gpio_ops_p->set_power_en = spi_set_power_en; s_gpio_ops_p->set_start_en = spi_set_start_en; s_gpio_ops_p->set_reset = spi_set_reset; s_gpio_ops_p->set_led = spi_set_led; s_gpio_ops_p->get_plug = spi_get_plug; s_gpio_ops_p->set_vid = spi_set_vid; break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: init_hub_gpio(); s_gpio_ops_p->set_power_en = hub_set_power_en; s_gpio_ops_p->set_start_en = hub_set_start_en; s_gpio_ops_p->set_reset = hub_set_reset; s_gpio_ops_p->set_led = hub_set_led; s_gpio_ops_p->get_plug = hub_get_plug; s_gpio_ops_p->set_vid = hub_set_vid; s_gpio_ops_p->get_button = hub_get_button; s_gpio_ops_p->set_green_led = hub_set_green_led; s_gpio_ops_p->set_red_led = hub_set_red_led; break; case PLATFORM_ORANGE_PI: s_gpio_ops_p->set_power_en = opi_set_power_en; s_gpio_ops_p->set_start_en = opi_set_start_en; s_gpio_ops_p->set_reset = opi_set_reset; s_gpio_ops_p->set_led = opi_set_led; s_gpio_ops_p->get_plug = opi_get_plug; s_gpio_ops_p->set_vid = opi_set_vid; break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void exit_mcompat_gpio(void) { switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: exit_spi_gpio(g_chain_num); break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void register_mcompat_gpio(MCOMPAT_GPIO_T * ops) { if (ops->set_power_en != NULL) { s_gpio_ops_p->set_power_en = ops->set_power_en; } if (ops->set_start_en != NULL) { s_gpio_ops_p->set_start_en = ops->set_start_en; } if (ops->set_reset != NULL) { s_gpio_ops_p->set_reset = ops->set_reset; } if (ops->set_led != NULL) { s_gpio_ops_p->set_led = ops->set_led; } if (ops->get_plug != NULL) { s_gpio_ops_p->get_plug = ops->get_plug; } if (ops->get_button != NULL) { s_gpio_ops_p->get_button = ops->get_button; } if (ops->set_green_led != NULL) { s_gpio_ops_p->set_green_led = ops->set_green_led; } if (ops->set_red_led != NULL) { s_gpio_ops_p->set_red_led = ops->set_red_led; } } void mcompat_set_power_en(unsigned char chain_id, int val) { if (s_gpio_ops_p->set_power_en == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } s_gpio_ops_p->set_power_en(chain_id, val); } void mcompat_set_start_en(unsigned char chain_id, int val) { if (s_gpio_ops_p->set_start_en == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } s_gpio_ops_p->set_start_en(chain_id, val); } bool mcompat_set_reset(unsigned char chain_id, int val) { if (s_gpio_ops_p->set_reset == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } return s_gpio_ops_p->set_reset(chain_id, val); } void mcompat_set_led(unsigned char chain_id, int val) { if (s_gpio_ops_p->set_led == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } s_gpio_ops_p->set_led(chain_id, val); } int mcompat_get_plug(unsigned char chain_id) { if (s_gpio_ops_p->get_plug == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return -1; } return s_gpio_ops_p->get_plug(chain_id); } bool mcompat_set_vid(unsigned char chain_id, int val) { if (s_gpio_ops_p->set_vid == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return false; } applog(LOG_DEBUG, "set chain %d vid value %d", chain_id, val); return s_gpio_ops_p->set_vid(chain_id, val); } bool mcompat_set_vid_by_step(unsigned char chain_id, int start_vid, int target_vid) { int i; if (target_vid > VID_MAX) target_vid = VID_MAX; else if( target_vid < VID_MIN) target_vid = VID_MIN; if (target_vid > start_vid) { // increase vid step by step for (i = start_vid + 1; i <= target_vid; ++i) { mcompat_set_vid(chain_id, i); applog(LOG_NOTICE, "set_vid_value_G19: %d", i); } } else if (target_vid < start_vid) { // decrease vid step by step for (i = start_vid - 1; i >= target_vid; --i) { mcompat_set_vid(chain_id, i); applog(LOG_NOTICE, "set_vid_value_G19: %d", i); } } return true; } int mcompat_get_button(void) { if (s_gpio_ops_p->get_button == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return -1; } return s_gpio_ops_p->get_button(); } void mcompat_set_green_led(int mode) { if (s_gpio_ops_p->set_green_led == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } s_gpio_ops_p->set_green_led(mode); } void mcompat_set_red_led(int mode) { if (s_gpio_ops_p->set_red_led == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } s_gpio_ops_p->set_red_led(mode); } MCOMPAT_PWM_T s_pwm_ops; MCOMPAT_PWM_T* s_pwm_ops_p = &s_pwm_ops; void init_mcompat_pwm(void) { memset(&s_pwm_ops, 0, sizeof(s_pwm_ops)); switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: s_pwm_ops_p->set_pwm = zynq_set_pwm; break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: s_pwm_ops_p->set_pwm = hub_set_pwm; break; case PLATFORM_ORANGE_PI: s_pwm_ops_p->set_pwm = opi_set_pwm; break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void exit_mcompat_pwm(void) { switch(g_platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: break; case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: break; default: applog(LOG_ERR, "the platform is undefined !!!"); break; } } void register_mcompat_pwm(MCOMPAT_PWM_T * ops) { if (ops->set_pwm != NULL) { s_pwm_ops_p->set_pwm = ops->set_pwm; } } void mcompat_set_pwm(unsigned char fan_id, int frequency, int duty) { if (s_pwm_ops_p->set_pwm == NULL) { applog(LOG_ERR, "%s not register !", __FUNCTION__); return; } applog(LOG_INFO, "set fan[%d] pwm freq[%d] duty[%d] ", fan_id, frequency, duty); s_pwm_ops_p->set_pwm(fan_id, frequency, duty); } int mcompat_temp_to_centigrade(int temp) { // return 0 if temp is a invalid value // if (temp == 0) // return 0; switch(g_miner_type) { case MCOMPAT_LIB_MINER_TYPE_T1: return (588.0f - temp) * 2 / 3 + 0.5f; // T1 case MCOMPAT_LIB_MINER_TYPE_T3: case MCOMPAT_LIB_MINER_TYPE_D11: case MCOMPAT_LIB_MINER_TYPE_D12: default: return (595.0f - temp) * 2 / 3 + 0.5f; // T3 D11 D12 } } bool mcompat_get_chain_temp(unsigned char chain_id, c_temp *chain_tmp) { uint32_t reg_val; uint32_t tmp_val0; uint32_t tmp_val1; uint32_t tmp_val2; int timeout = 1000; // enable auto 0a enable_auto_cmd0a(chain_id, 100, 33, 24, 0, 0); do { reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP * chain_id + AUTO_CMD0A_REG4_ADDR); timeout--; cgsleep_ms(1); // usleep(1); } while(timeout && !((reg_val >> 24) & 0x1)); if(!timeout) return false; // temp_lo: reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP * chain_id + AUTO_CMD0A_REG2_ADDR); tmp_val0 = mcompat_temp_to_centigrade(reg_val & 0x3ff); tmp_val1 = mcompat_temp_to_centigrade((reg_val >> 10) & 0x3ff); tmp_val2 = mcompat_temp_to_centigrade((reg_val >> 20) & 0x3ff); // applog(LOG_DEBUG, "REG2: %d, %d, %d", tmp_val0, tmp_val1, tmp_val2); chain_tmp->tmp_lo = (tmp_val0 + tmp_val1 + tmp_val2) / 3; // chain_tmp->tmp_lo = tmp_val1; // temp_hi: reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP * chain_id + AUTO_CMD0A_REG3_ADDR); tmp_val0 = mcompat_temp_to_centigrade(reg_val & 0x3ff); tmp_val1 = mcompat_temp_to_centigrade((reg_val >> 10) & 0x3ff); tmp_val2 = mcompat_temp_to_centigrade((reg_val >> 20) & 0x3ff); // applog(LOG_DEBUG, "REG3: %d, %d, %d", tmp_val0, tmp_val1, tmp_val2); chain_tmp->tmp_hi = (tmp_val0 + tmp_val1 + tmp_val2) / 3; // chain_tmp->tmp_hi = tmp_val1; // temp_avg: reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP * chain_id + AUTO_CMD0A_REG4_ADDR); tmp_val1 = mcompat_temp_to_centigrade(2 * (reg_val & 0xffff) / g_chip_num); // applog(LOG_DEBUG, "REG4: %d / %d", tmp_val1, g_chip_num); chain_tmp->tmp_avg = tmp_val1; // disable auto 0a disable_auto_cmd0a(chain_id, 100, 33, 24, 0, 0); timeout = 1000; do { reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP * chain_id + AUTO_CMD0A_REG4_ADDR); timeout--; cgsleep_ms(1); // usleep(1); } while(timeout && !((reg_val >> 24) & 0x1)); if(!timeout) return false; return true; } void mcompat_get_chip_temp(int chain_id, int *chip_temp) { int chip_id; unsigned char reg[REG_LENGTH] = {0}; for (chip_id = 1; chip_id <= g_chip_num; chip_id++) { if (!mcompat_cmd_read_register(chain_id, chip_id, reg, REG_LENGTH)) { applog(LOG_ERR, "failed to read temperature for chain%d chip%d", chain_id, chip_id); chip_temp[chip_id - 1] = mcompat_temp_to_centigrade(0); break; } else chip_temp[chip_id - 1] = mcompat_temp_to_centigrade(0x000003ff & ((reg[7] << 8) | reg[8])); } } #define MCOMPAT_WATCHDOG_DEV ("/dev/watchdog0") static int s_watchdog_fd = 0; void mcompat_watchdog_keep_alive(void) { int dummy = 0; ioctl(s_watchdog_fd, WDIOC_KEEPALIVE, &dummy); } void mcompat_watchdog_open(void) { s_watchdog_fd = open(MCOMPAT_WATCHDOG_DEV, O_WRONLY); if (-1 == s_watchdog_fd) { applog(LOG_ERR, "%s watchdog device can't be enabled.", MCOMPAT_WATCHDOG_DEV); } } void mcompat_watchdog_set_timeout(int timeout) { ioctl(s_watchdog_fd, WDIOC_SETTIMEOUT, &timeout); } void mcompat_watchdog_close(void) { close(s_watchdog_fd); } #define SOCK_SIZE (65535) #define SOCK_ERR_MSG strerror(errno) #define MUL_COEF (1248) int mcompat_get_shell_cmd_rst(char *cmd, char *result, int size) { char buffer[1024] = {0}; int offset = 0; int len; FILE *fp = NULL; fp = popen(cmd, "r"); if (NULL == fp) { applog(LOG_ERR, "failed to open pipe for command %s", cmd); return 0; } while(fgets(buffer, sizeof(buffer), fp) != NULL) { len = strlen(buffer); if (offset + len < size) { strcpy(result + offset, buffer); offset += len; } else { strncpy(result + offset, buffer, size - offset); offset = size; break; } } applog(LOG_DEBUG, "command result(%d): %s", offset, result); return offset; } int misc_call_api(char *command, char *host, short int port) { struct sockaddr_in serv; int sock = 0; int ret = 0; int n = 0; char *buf = NULL; size_t len = SOCK_SIZE; size_t p = 0; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { printf("Socket initialisation failed: %s", SOCK_ERR_MSG); return -1; } memset(&serv, 0, sizeof(serv)); serv.sin_family = AF_INET; serv.sin_addr.s_addr = inet_addr(host); serv.sin_port = htons(port); if (connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr)) < 0) { printf("Socket connect failed: %s", SOCK_ERR_MSG); return -1; } n = send(sock, command, strlen(command), 0); if (n < 0) { printf("Send failed: %s", SOCK_ERR_MSG); ret = -1; } else { buf = malloc(len+1); if (!buf) { printf("Err: OOM (%d)", (int)(len+1)); return -1; } while(1) { if ((len - p) < 1) { len += SOCK_SIZE; buf = realloc(buf, len+1); if (!buf) { printf("Err: OOM (%d)", (int)(len+1)); return -1; } } n = recv(sock, &buf[p], len - p , 0); if (n < 0) { printf("Recv failed: %s", SOCK_ERR_MSG); ret = -1; break; } if (0 == n) { break; } p += n; } buf[p] = '\0'; printf("%s", buf); free(buf); buf = NULL; } close(sock); return ret; } bool misc_tcp_is_ok(char *host, short int port) { struct sockaddr_in serv; int sock = 0; int mode = 0; bool ret = false; sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { printf("Socket initialisation failed: %s", SOCK_ERR_MSG); return -1; } ioctl(sock, FIONBIO, &mode); memset(&serv, 0, sizeof(serv)); serv.sin_family = AF_INET; serv.sin_addr.s_addr = inet_addr(host); serv.sin_port = htons(port); ret = false; if (0 == connect(sock, (struct sockaddr *)&serv, sizeof(struct sockaddr))) { ret = true; } close(sock); return ret; } char *misc_trim(char *str) { char *ptr; while (isspace(*str)) { str++; } ptr = strchr(str, '\0'); while (ptr-- > str) { if (isspace(*ptr)) { *ptr = '\0'; } } return str; } int misc_get_board_version(void) { FILE* fd = NULL; char buffer[64] = {'\0'}; int version = MCOMPAT_LIB_HARDWARE_VERSION_ERR; fd = fopen(MCOMPAT_LIB_HARDWARE_VERSION_FILE, "r"); if (fd == NULL) { applog(LOG_ERR, "open hwver file:%s failed! ", MCOMPAT_LIB_HARDWARE_VERSION_FILE); } memset(buffer, 0, sizeof(buffer)); FREAD(buffer, 8, 1, fd); fclose(fd); if (strstr(buffer, "G9") != NULL) { version = MCOMPAT_LIB_HARDWARE_VERSION_G9; applog(LOG_INFO, "hardware version is G9 "); } else if (strstr(buffer, "G19") != 0) { version = MCOMPAT_LIB_HARDWARE_VERSION_G19; applog(LOG_INFO, "hardware version is G19 "); } else { applog(LOG_ERR, "unknown hardware version:%s! ", buffer); } return version; } int misc_get_miner_type(void) { FILE *fd = NULL; char buffer[64] = {'\0'}; int miner_type = MCOMPAT_LIB_MINER_TYPE_ERR; fd = fopen(MCOMPAT_LIB_MINER_TYPE_FILE, "r"); if (fd == NULL) { applog(LOG_ERR, "open miner type file:%s failed!", MCOMPAT_LIB_MINER_TYPE_FILE); } memset(buffer, 0, sizeof(buffer)); FREAD(buffer, 8, 1, fd); fclose(fd); if (strstr(buffer, "T1") != NULL) { miner_type = MCOMPAT_LIB_MINER_TYPE_T1; applog(LOG_INFO, "miner type is T1 "); } else if (strstr(buffer, "T2") != NULL) { miner_type = MCOMPAT_LIB_MINER_TYPE_T2; applog(LOG_INFO, "miner type is T2 "); } else if (strstr(buffer, "T3") != NULL) { miner_type = MCOMPAT_LIB_MINER_TYPE_T3; applog(LOG_INFO, "miner type is T3 "); } else if (strstr(buffer, "T4") != NULL) { miner_type = MCOMPAT_LIB_MINER_TYPE_T4; applog(LOG_INFO, "miner type is T4 "); } else { applog(LOG_ERR, "unknown miner type:%s! ", buffer); } return miner_type; } int misc_get_vid_type(void) { int val_b9 = 0; int val_a10 = 0; int val = 0; int type = 0; zynq_gpio_init(MCOMPAT_CONFIG_B9_GPIO, 1); zynq_gpio_init(MCOMPAT_CONFIG_A10_GPIO, 1); val_b9 = zynq_gpio_read(MCOMPAT_CONFIG_B9_GPIO); val_a10 = zynq_gpio_read(MCOMPAT_CONFIG_A10_GPIO); val = val_a10 << 1 | val_b9; #if 1 applog(LOG_INFO, "b9 pin:%d,a10 pin:%d", MCOMPAT_CONFIG_B9_GPIO, MCOMPAT_CONFIG_A10_GPIO); applog(LOG_INFO, "b9:%d,a10:%d,val:0x%08x", val_b9, val_a10, val); #endif switch(val) { /* xhn */ case 0x00000003: { type = MCOMPAT_LIB_VID_VID_TYPE; applog(LOG_INFO, "cow vid vid"); break; } /* zle*/ case 0x00000002: { type = MCOMPAT_LIB_VID_UART_TYPE; applog(LOG_INFO, "zl uart vid"); break; } /* hnd */ case 0x00000000: { type = MCOMPAT_LIB_VID_I2C_TYPE; applog(LOG_INFO, "hnd iic vid"); break; } /* unused */ case 0x00000001: default: { type = MCOMPAT_LIB_VID_ERR_TYPE; applog(LOG_ERR, "err vid type:b9:%d,a10:%d,val:0x%08x", val_b9, val_a10, val); break; } } #if 0 type = MCOMPAT_LIB_VID_UART_TYPE; type = MCOMPAT_LIB_VID_I2C_TYPE; #endif zynq_gpio_exit(MCOMPAT_CONFIG_B9_GPIO); zynq_gpio_exit(MCOMPAT_CONFIG_A10_GPIO); return type; } void misc_system(const char *cmd, char *rst_buf, int buf_size) { int i = 0; FILE *fp = NULL; char *go_ptr = NULL; char c = 0; if (NULL == cmd || NULL == rst_buf || buf_size < 0) { applog(LOG_ERR, "param error:%s,%s,%d.", cmd, rst_buf, buf_size); } fp = popen(cmd, "r"); if (NULL == fp) { applog(LOG_ERR, "popen error:%s,%s,%d.", cmd, rst_buf, buf_size); } else { go_ptr = rst_buf; memset(go_ptr, 0, buf_size); for(i = 0; i < buf_size; i++) { c = fgetc(fp); if (isprint(c)) { *go_ptr++ = c; fprintf(stderr, "%s,%d: %c", __FILE__, __LINE__, c); } else { break; } } rst_buf[buf_size-1] = '\0'; pclose(fp); } } void mcompat_get_chip_volt(int chain_id, int *chip_volt) { int chip_id; unsigned char reg[REG_LENGTH] = {0}; unsigned int volt = 0; for (chip_id = 1; chip_id <= g_chip_num; chip_id++) { if(!mcompat_cmd_read_register(chain_id, chip_id, reg, REG_LENGTH)) { applog(LOG_ERR, "failed to read voltage for chain%d chip%d", chain_id, chip_id); chip_volt[chip_id - 1] = 0; continue; } else { cgsleep_ms(2); volt = 0x000003ff & ((reg[7] << 8) | reg[8]); chip_volt[chip_id - 1] = (volt * MUL_COEF) >> 10; } } } void mcompat_configure_tvsensor(int chain_id, int chip_id, bool is_tsensor) { unsigned char tmp_reg[REG_LENGTH] = {0}; unsigned char src_reg[REG_LENGTH] = {0}; unsigned char reg[REG_LENGTH] = {0}; mcompat_cmd_read_register(chain_id, 0x01, reg,REG_LENGTH); memcpy(src_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,src_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); if (is_tsensor)//configure for tsensor { reg[7] = (src_reg[7]&0x7f); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); reg[7] = (src_reg[7]|0x80); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); reg[6] = (src_reg[6]|0x04); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step6: high tsadc_en reg[7] = (src_reg[7]|0x20); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step7: tsadc_ana_reg_9 = 0;tsadc_ana_reg_8 = 0 reg[5] = (src_reg[5]&0xfc); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step8: tsadc_ana_reg_7 = 1;tsadc_ana_reg_1 = 0 reg[6] = (src_reg[6]&0x7d); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); } else { //configure for vsensor reg[7] = (src_reg[7]&0x7f); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); reg[7] = (src_reg[7]|0x80); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); reg[6] = (src_reg[6]|0x04); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step6: high tsadc_en reg[7] = (src_reg[7]|0x20); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step7: tsadc_ana_reg_9 = 0;tsadc_ana_reg_8 = 0 reg[5] = ((src_reg[5]|0x01)&0xfd); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); //Step8: tsadc_ana_reg_7 = 1;tsadc_ana_reg_1 = 0 reg[6] = ((src_reg[6]|0x02)&0x7f); memcpy(tmp_reg,reg,REG_LENGTH); mcompat_cmd_write_register(chain_id,chip_id,tmp_reg,REG_LENGTH); cgsleep_ms(1); //usleep(200); } } void mcompat_cfg_tsadc_divider(int chain_id,unsigned int pll_clk) { unsigned int tsadc_divider_tmp; unsigned char tsadc_divider; unsigned char buffer[64] = {0x02,0x50,0xa0,0x06,0x28,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; unsigned char readbuf[32] = {0}; tsadc_divider_tmp = (pll_clk/2)*1000/16/650; tsadc_divider = (unsigned char)(tsadc_divider_tmp & 0xff); buffer[5] = 0x00 | tsadc_divider; if (!mcompat_cmd_read_write_reg0d(chain_id, 0x00, buffer, REG_LENGTH, readbuf)) { applog(LOG_DEBUG,"Write t/v sensor Value Failed!"); } else { applog(LOG_DEBUG,"Write t/v sensor Value Success!"); } } double mcompat_get_average_volt(int *volt, int size) { int i; int count = 0; int total = 0, max = 0, min = 1000; for (i = 0; i < size; i++) { if (volt[i] > 0) { total += volt[i]; max = MAX(max, volt[i]); min = MIN(min, volt[i]); count++; } } if (count > 2) return (double) (total - max - min) / (count - 2); else return 0; } /* Adjust vid till we are just above volt_target. We should have already set * vid_start before calling this function. */ int mcompat_find_chain_vid(int chain_id, int chip_num, int vid_start, double volt_target) { int chip_volt[MCOMPAT_CONFIG_MAX_CHIP_NUM] = {0}; int vid = vid_start; double volt_avg; mcompat_cfg_tsadc_divider(chain_id, 120); cgsleep_ms(1); mcompat_configure_tvsensor(chain_id, CMD_ADDR_BROADCAST, 0); cgsleep_ms(1); applog(LOG_NOTICE, "chain%d find_chain_vid: start_vid = %d, target_volt = %.1f", chain_id, vid_start, volt_target); mcompat_get_chip_volt(chain_id, chip_volt); volt_avg = mcompat_get_average_volt(chip_volt, chip_num); applog(LOG_NOTICE, "Chain %d VID %d voltage %.1f", chain_id, vid, volt_avg); /* Go down voltage till we're below the target */ while (volt_avg >= volt_target) { if (vid >= VID_MAX) { applog(LOG_WARNING, "Chain %d unable to get below target voltage %.1f by VID %d", chain_id, volt_target, vid); break; } vid++; mcompat_set_vid(chain_id, vid); mcompat_get_chip_volt(chain_id, chip_volt); volt_avg = mcompat_get_average_volt(chip_volt, chip_num); applog(LOG_NOTICE, "Chain %d VID %d voltage %.1f", chain_id, vid, volt_avg); } cgsleep_ms(500); mcompat_get_chip_volt(chain_id, chip_volt); volt_avg = mcompat_get_average_volt(chip_volt, chip_num); applog(LOG_NOTICE, "Chain %d VID %d voltage %.1f", chain_id, vid, volt_avg); /* Now go down VID till we're above the target, final point should * be closest without going below voltage */ while (volt_avg < volt_target) { if (vid <= VID_MIN) { applog(LOG_WARNING, "Chain %d unable to get above target voltage %.1f by VID %d", chain_id, volt_target, vid); break; } vid--; mcompat_set_vid(chain_id, vid); cgsleep_ms(500); mcompat_get_chip_volt(chain_id, chip_volt); volt_avg = mcompat_get_average_volt(chip_volt, chip_num); applog(LOG_NOTICE, "Chain %d VID %d voltage %.1f", chain_id, vid, volt_avg); } mcompat_configure_tvsensor(chain_id, CMD_ADDR_BROADCAST, 1); return vid; } #define IOCTL_SET_VAL_0 _IOR(MAGIC_NUM, 0, char *) #define IOCTL_SET_VALUE_0 _IOR(MAGIC_NUM, 0, char *) #define IOCTL_SET_CHAIN_0 _IOR(MAGIC_NUM, 1, char *) #define BUF_MAX (256) #define SYSFS_GPIO_EXPORT ("/sys/class/gpio/export") #define SYSFS_GPIO_DIR_STR ("/sys/class/gpio/gpio%d/direction") #define SYSFS_GPIO_VAL_STR ("/sys/class/gpio/gpio%d/value") #define SYSFS_GPIO_DIR_OUT ("out") #define SYSFS_GPIO_DIR_IN ("in") #define SYSFS_GPIO_VAL_LOW ("0") #define SYSFS_GPIO_VAL_HIGH ("1") void zynq_gpio_init(int pin, int dir) { int fd = 0; ssize_t write_bytes = 0; char fvalue[BUF_MAX] = {'\0'}; char fpath[BUF_MAX] = {'\0'}; fd = open(SYSFS_GPIO_EXPORT, O_WRONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } memset(fvalue, 0, sizeof(fvalue)); sprintf(fvalue, "%d", pin); write_bytes = write(fd, fvalue, strlen(fvalue)); if (-1 == write_bytes) { if (EBUSY == errno) { close(fd); return; } else { applog(LOG_ERR, "%s,%d: %d,%s.", __FILE__, __LINE__, errno, strerror(errno)); } } close(fd); memset(fpath, 0, sizeof(fpath)); sprintf(fpath, SYSFS_GPIO_DIR_STR, pin); fd = open(fpath, O_WRONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (0 == dir) { write_bytes = write(fd, SYSFS_GPIO_DIR_OUT, sizeof(SYSFS_GPIO_DIR_OUT)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } } else { write_bytes = write(fd, SYSFS_GPIO_DIR_IN, sizeof(SYSFS_GPIO_DIR_IN)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } } close(fd); return; } static bool zynq_gpio_write(int pin, int val) { int fd = 0; ssize_t write_bytes = 0; char fpath[BUF_MAX] = {'\0'}; bool ret = false; memset(fpath, 0, sizeof(fpath)); sprintf(fpath, SYSFS_GPIO_VAL_STR, pin); fd = open(fpath, O_WRONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); goto out; } if (0 == val) { write_bytes = write(fd, SYSFS_GPIO_VAL_LOW, sizeof(SYSFS_GPIO_VAL_LOW)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); goto out_close; } } else { write_bytes = write(fd, SYSFS_GPIO_VAL_HIGH, sizeof(SYSFS_GPIO_VAL_HIGH)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s,%s.", __FILE__, __LINE__, fpath, strerror(errno)); goto out_close; } } ret = true; out_close: close(fd); out: return ret; } int zynq_gpio_read(int pin) { int fd = 0; int val = 0; ssize_t read_bytes = 0; char fpath[BUF_MAX] = {'\0'}; char fvalue[BUF_MAX] = {'\0'}; memset(fpath, 0, sizeof(fpath)); sprintf(fpath, SYSFS_GPIO_VAL_STR, pin); fd = open(fpath, O_RDONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } memset(fvalue, 0, sizeof(fvalue)); read_bytes = read(fd, fvalue, 1); if (-1 == read_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(fd); if ('0' == fvalue[0]) { val = 0; } else if ('1' == fvalue[0]) { val = 1; } else { val = -1; } return val; } void zynq_gpio_exit(int __maybe_unused pin) { return; } pthread_mutex_t s_pwm_lock; void zynq_set_pwm(unsigned char fan_id, int frequency, int duty) { int fd = 0; int duty_driver = 0; duty_driver = frequency / 100 * (100 - duty); //pthread_mutex_lock(&s_pwm_lock); fd = open(SYSFS_PWM_DEV, O_RDWR); if (fd < 0) { applog(LOG_ERR, "open %s fail", SYSFS_PWM_DEV); //pthread_mutex_unlock(&s_pwm_lock); return; } if (ioctl(fd, IOCTL_SET_PWM_FREQ(fan_id), frequency) < 0) { applog(LOG_ERR,"set fan%d frequency fail ", fan_id); close(fd); //pthread_mutex_unlock(&s_pwm_lock); return ; } if (ioctl(fd, IOCTL_SET_PWM_DUTY(fan_id), duty_driver) < 0) { applog(LOG_ERR,"set fan%d duty fail ", fan_id); close(fd); //pthread_mutex_unlock(&s_pwm_lock); return ; } close(fd); //pthread_mutex_unlock(&s_pwm_lock); return; } #define BUF_MAX (256) #define DEV_TEMPLATE ("/dev/spidev%d.%d") #define SYSFS_EXPORT ("/sys/devices/soc0/amba/f8007000.devcfg/fclk_export") #define SYSFS_VAL_STR ("/sys/devices/soc0/amba/f8007000.devcfg/fclk/fclk1/set_rate") static void zynq_spi_clock_init(void); void zynq_spi_init(ZYNQ_SPI_T *spi, int bus) { char dev_fname[BUF_MAX] = {'\0'}; int fd = 0; uint8_t mode = MCOMPAT_CONFIG_SPI_DEFAULT_MODE; uint32_t speed = MCOMPAT_CONFIG_SPI_DEFAULT_SPEED; uint8_t bits = MCOMPAT_CONFIG_SPI_DEFAULT_BITS_PER_WORD; zynq_spi_clock_init(); zynq_set_spi_speed(MCOMPAT_CONFIG_SPI_DEFAULT_SPEED); sprintf(dev_fname, DEV_TEMPLATE, bus, MCOMPAT_CONFIG_SPI_DEFAULT_CS_LINE); fd = open(dev_fname, O_RDWR); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_WR_MODE, &mode) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } spi->fd = fd; pthread_mutex_init(&(spi->lock), NULL); applog(LOG_DEBUG, "SPI '%s': mode=%hhu, bits=%hhu, speed=%u ", dev_fname, MCOMPAT_CONFIG_SPI_DEFAULT_MODE, MCOMPAT_CONFIG_SPI_DEFAULT_BITS_PER_WORD, MCOMPAT_CONFIG_SPI_DEFAULT_SPEED); return; } void zynq_spi_exit(ZYNQ_SPI_T *spi) { if (NULL == spi) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(spi->fd); return; } void zynq_spi_write(ZYNQ_SPI_T *spi, uint8_t *txbuf, int len) { pthread_mutex_lock(&(spi->lock)); if ((len <= 0) || (txbuf == NULL)) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (write(spi->fd, txbuf, len) <= 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } pthread_mutex_unlock(&spi->lock); return; } void zynq_spi_read(ZYNQ_SPI_T *spi, uint8_t *rxbuf, int len) { pthread_mutex_lock(&(spi->lock)); if ((len <= 0) || (rxbuf == NULL)) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (read(spi->fd, rxbuf, len) <= 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } pthread_mutex_unlock(&spi->lock); return; } void zynq_spi_clock_init(void) { int fd = 0; ssize_t write_bytes = 0; char fvalue[BUF_MAX] = {'\0'}; fd = access(SYSFS_VAL_STR, F_OK); if (0 == fd) { return; } fd = open(SYSFS_EXPORT, O_WRONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } memset(fvalue, 0, sizeof(fvalue)); sprintf(fvalue, "%s", "fclk1"); write_bytes = write(fd, fvalue, strlen(fvalue)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(fd); return; } void zynq_set_spi_speed(int speed) { int fd = 0; ssize_t write_bytes = 0; char fvalue[BUF_MAX] = {'\0'}; applog(LOG_DEBUG, "set spi speed %d ", speed); fd = open(SYSFS_VAL_STR, O_WRONLY); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } memset(fvalue, 0, sizeof(fvalue)); sprintf(fvalue, "%d", speed * 16); write_bytes = write(fd, fvalue, strlen(fvalue)); if (-1 == write_bytes) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(fd); return; } int zynq_gpio_g9_vid_set(int level) { int fd = 0; fd = open(SYSFS_VID_DEV, O_RDWR); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, IOCTL_SET_VAL_0, 0x0100 | level) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(fd); return 0; } int zynq_gpio_g19_vid_set(int chain_id, int level) { int fd = 0; fd = open(SYSFS_VID_DEV, O_RDWR); if (-1 == fd) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, IOCTL_SET_CHAIN_0, chain_id) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } if (ioctl(fd, IOCTL_SET_VALUE_0, 0x100 | level) < 0) { applog(LOG_ERR, "%s,%d: %s.", __FILE__, __LINE__, strerror(errno)); } close(fd); return 0; } /* DUPES, FIXME THIS ONE IS USED */ typedef struct HUB_DEV_TAG { volatile uint8_t *vir_base; uint32_t phy_addr; uint32_t mem_size; const char *name; } HUB_DEV_T; static HUB_DEV_T s_dev_list[] = { {NULL, 0x43C30000, 0x2000, "spi"}, {NULL, 0x43C00000, 0x1000, "peripheral"}, //{NULL, 0x43C32000, 0x1000, "sha256"}, }; #if 0 /* DUPES FIXME THIS ONE ISN'T USED */ typedef struct HUB_DEV_TAG { volatile uint8_t *vir_base; uint32_t phy_addr; const char *name; } HUB_DEV_T; static HUB_DEV_T s_dev_list[] = { {NULL, 0x43C30000, "spi"}, {NULL, 0x43C10000, "peripheral"}, {NULL, 0x43C00000, "fans"}, {NULL, 0x41200000, "gpio"}, {NULL, 0x43C32000, "sha256"}, }; #endif void hub_hardware_init(void) { int fd = 0; int i = 0; int iMax = sizeof(s_dev_list) / sizeof(s_dev_list[0]); applog(LOG_INFO, "max range: 0x%x.", _MAX_MEM_RANGE); fd = open("/dev/mem", O_RDWR | O_SYNC); if (-1 == fd) { applog(LOG_ERR, "open /dev/mem:"); return; } applog(LOG_INFO, "total: %d dev will mmap.", iMax); for(i = 0; i < iMax; i++) { s_dev_list[i].vir_base = mmap(NULL, _MAX_MEM_RANGE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, s_dev_list[i].phy_addr); if (MAP_FAILED == s_dev_list[i].vir_base) { close(fd); applog(LOG_ERR, "mmap %s:phy:0x%08x => vir:%p fail.", s_dev_list[i].name, s_dev_list[i].phy_addr, s_dev_list[i].vir_base); return; } applog(LOG_INFO, "mmap %s:phy:0x%08x => vir:%p ok.", s_dev_list[i].name, s_dev_list[i].phy_addr, s_dev_list[i].vir_base); } applog(LOG_INFO, "total: %d dev mmap done.", iMax); close(fd); } void hub_hardware_deinit(void) { int i = 0; int iMax = sizeof(s_dev_list) / sizeof(s_dev_list[0]); for(i = 0; i < iMax; i++) { munmap((void *)s_dev_list[i].vir_base, _MAX_MEM_RANGE); applog(LOG_INFO, "unmap %s:vir:%p.", s_dev_list[i].name, s_dev_list[i].vir_base); } } /* vid, iic, uart */ // compatible values for different vid types static int s_vid_map[][3] = { {0, 1608, 54}, {1, 1599, 60}, {2, 1590, 67}, {3, 1581, 73}, {4, 1572, 80}, {5, 1563, 86}, {6, 1554, 93}, {7, 1545, 99}, {8, 1536, 106}, {9, 1527, 112}, {10, 1518, 119}, {11, 1509, 125}, {12, 1500, 132}, {13, 1491, 138}, {14, 1482, 145}, {15, 1473, 151}, {16, 1464, 158}, {17, 1455, 164}, {18, 1446, 171}, {19, 1437, 177}, {20, 1428, 184}, {21, 1419, 190}, {22, 1410, 197}, {23, 1401, 203}, {24, 1392, 210}, {25, 1383, 216}, {26, 1374, 223}, {27, 1365, 229}, {28, 1356, 236}, {29, 1347, 242}, {30, 1338, 248}, {31, 1329, 255}, }; static bool hub_set_vid_i2c(uint8_t chain_id, int vid); static bool hub_set_vid_uart(uint8_t chain_id, int vid); static void send_uart(const char *path, char byte); static bool set_vol_on_i2c(int chain, int vol); static bool set_power_on_i2c(int chain, int val); bool hub_set_vid(uint8_t chain_id, int vol) { int type = 0; type = misc_get_vid_type(); switch(type) { case MCOMPAT_LIB_VID_VID_TYPE: { hub_set_vid_vid(chain_id, vol); return true; } case MCOMPAT_LIB_VID_I2C_TYPE: { if (hub_set_vid_i2c(chain_id, vol)) { return true; } else { return false; } } case MCOMPAT_LIB_VID_UART_TYPE: { if (hub_set_vid_uart(chain_id, vol)) { return true; } else { return false; } } case MCOMPAT_LIB_VID_GPIO_I2C_TYPE: { applog(LOG_ERR, "%s,%d:no impl type:MCOMPAT_LIB_VID_GPIO_I2C_TYPE.", __FILE__, __LINE__); break; } default: { applog(LOG_ERR, "%s,%d:err vid type:%d.", __FILE__, __LINE__, type); break; } } return true; } static bool hub_set_vid_i2c(uint8_t chan_id, int vid) { int vol = s_vid_map[vid][1]; set_vol_on_i2c(chan_id + 1 , vol); return true; } static bool hub_set_vid_uart(uint8_t chain_id, int vid) { char byte = 0; byte = (char)s_vid_map[vid][2]; hub_set_vid_uart_select(chain_id); send_uart("/dev/ttyPS1", byte); return true; } static void hub_set_power_en_i2c(uint8_t chain_id,int value) { set_power_on_i2c(chain_id + 1, value); } bool set_timeout_on_i2c(int time) { int i; int fd; int sum = 0; unsigned char buffer[10] = {0}; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; fd = open(I2C_DEVICE_NAME, O_RDWR); if(fd < 0) { applog(LOG_ERR, "%s,%d:open %s failled: %d.", __FILE__, __LINE__, I2C_DEVICE_NAME, errno); return false; } buffer[0] = 0x00; buffer[1] = 0xab; buffer[2] = 0x00; buffer[3] = 0x70; buffer[4] = 0x00; buffer[5] = 0x01; buffer[6] = (time/30); for (i = 0; i < 7; i++) sum = sum + buffer[i]; buffer[7] = sum & 0xff; buffer[8] = 0xcd; messages[0].addr = I2C_SLAVE_ADDR; messages[0].flags = I2C_M_IGNORE_NAK; messages[0].len = sizeof(buffer); messages[0].buf = buffer; packets.msgs = messages; packets.nmsgs = 1; if(ioctl(fd, I2C_RDWR, &packets) < 0) { applog(LOG_ERR, "%s,%d:write iic failled: %d.", __FILE__, __LINE__, errno); close(fd); return false; } close(fd); return true; } static bool set_power_on_i2c(int chain, int val) { int i; int fd; int sum = 0; unsigned char buffer[10] = {0}; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; fd = open(I2C_DEVICE_NAME, O_RDWR); if(fd < 0) { applog(LOG_ERR, "%s,%d:open %s failled: %d.", __FILE__, __LINE__, I2C_DEVICE_NAME, errno); return false; } buffer[0] = 0x00; buffer[1] = 0xab; buffer[2] = 0x00; buffer[3] = 0x85; buffer[4] = 0x00; buffer[5] = 0x02; buffer[6] = chain; if(val != 0) buffer[7] = 0x01; else buffer[7] = 0x02; for (i = 0; i < 8; i++) sum = sum + buffer[i]; buffer[8] = sum & 0xff; buffer[9] = 0xcd; messages[0].addr = I2C_SLAVE_ADDR; messages[0].flags = I2C_M_IGNORE_NAK; messages[0].len = sizeof(buffer); messages[0].buf = buffer; packets.msgs = messages; packets.nmsgs = 1; if(ioctl(fd, I2C_RDWR, &packets) < 0) { applog(LOG_ERR, "%s,%d:write iic failled: %d.", __FILE__, __LINE__, errno); close(fd); return false; } close(fd); return true; } static bool set_vol_on_i2c(int chain, int vol) { int i; int fd; int sum = 0; unsigned char buffer[12] = {0}; struct i2c_rdwr_ioctl_data packets; struct i2c_msg messages[2]; fd = open(I2C_DEVICE_NAME, O_RDWR); if (fd < 0) { applog(LOG_ERR, "%s,%d:open %s failled: %d.", __FILE__, __LINE__, I2C_DEVICE_NAME, errno); return false; } buffer[0] = 0x00; buffer[1] = 0xab; buffer[2] = 0x00; buffer[3] = 0x83; buffer[4] = 0x00; buffer[5] = 0x04; buffer[6] = chain; buffer[7] = 0x00; buffer[8] = ((vol >> 0) & 0xff); buffer[9] = ((vol >> 8) & 0xff); for(i=0; i<10; i++){ sum = sum + buffer[i]; } buffer[10] = sum & 0xff; buffer[11] = 0xcd; messages[0].addr = I2C_SLAVE_ADDR; messages[0].flags = I2C_M_IGNORE_NAK; messages[0].len = sizeof(buffer); messages[0].buf = buffer; packets.msgs = messages; packets.nmsgs = 1; if (ioctl(fd, I2C_RDWR, &packets) < 0) { applog(LOG_ERR, "%s,%d:write iic failled: %d.", __FILE__, __LINE__, errno); close(fd); return false; } close(fd); return true; } static void send_uart(const char *path, char byte) { int tty_fd = 0; int rst = 0; char buf[5] = {0}; tty_fd = open(path, O_WRONLY); if (-1 == tty_fd) { applog(LOG_ERR, "%s,%d:open %s failled: %d.", __FILE__, __LINE__, path, errno); } /* applog(LOG_DEBUG, "%s,%d.", __FILE__, __LINE__); */ buf[0] = 0xaa; buf[1] = 0x2; buf[2] = 0x1; buf[3] = byte; buf[4] = (~(buf[1]+buf[2]+buf[3]))+1; rst = write(tty_fd, &buf, 5); if (-1 == rst) { close(tty_fd); applog(LOG_ERR, "%s,%d:write tty failled: %d.", __FILE__, __LINE__, errno); } /* for debug */ #if 0 int i = 0; applog(LOG_DEBUG, "uart %s send:", path); for(i = 0; i < 5; i++) { applog(LOG_DEBUG, "%02X,", buf[i]); } applog(LOG_DEBUG, ""); #endif close(tty_fd); return; } #if 0 #ifdef SYSTEM_LINUX static void hub_hardware_init(void) { int fd = 0; int i = 0; int iMax = sizeof(s_dev_list) / sizeof(s_dev_list[0]); applog(LOG_INFO, "max range: 0x%x.", PAGE_SIZE); fd = open("/dev/mem", O_RDWR | O_SYNC); if (-1 == fd) { applog(LOG_ERR, "open /dev/mem:"); return; } applog(LOG_INFO, "total: %d dev will mmap.", iMax); for(i = 0; i < iMax; i++) { s_dev_list[i].vir_base = mmap(NULL, s_dev_list[i].mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, s_dev_list[i].phy_addr); if (MAP_FAILED == s_dev_list[i].vir_base) { close(fd); applog(LOG_ERR, "mmap %s:phy:0x%08x => vir:%p size:0x%x fail.", s_dev_list[i].name, s_dev_list[i].phy_addr, s_dev_list[i].vir_base, s_dev_list[i].mem_size); return; } applog(LOG_INFO, "mmap %s:phy:0x%08x => vir:%p size:0x%x ok.", s_dev_list[i].name, s_dev_list[i].phy_addr, s_dev_list[i].vir_base, s_dev_list[i].mem_size); } applog(LOG_INFO, "total: %d dev mmap done.", iMax); close(fd); } static void hub_hardware_deinit(void) { int i = 0; int iMax = sizeof(s_dev_list) / sizeof(s_dev_list[0]); for(i = 0; i < iMax; i++) { munmap((void *)s_dev_list[i].vir_base, s_dev_list[i].mem_size); applog(LOG_INFO, "unmap %s:vir:%p.", s_dev_list[i].name, s_dev_list[i].vir_base); } } #endif #endif void hub_init(void) { hub_hardware_init(); } void hub_deinit(void) { hub_hardware_deinit(); } #define INDEX_SPI 0 #define INDEX_PERIPHERAL 1 #define INDEX_SHA256 2 // for peripheral ip void Xil_Peripheral_Out32(uint32_t phyaddr, uint32_t val) { uint32_t pgoffset = phyaddr & ((uint32_t)(s_dev_list[INDEX_PERIPHERAL].mem_size -1)); pgoffset = phyaddr; #ifdef SYSTEM_LINUX // for software team *(volatile uint32_t *)(s_dev_list[INDEX_PERIPHERAL].vir_base + pgoffset) = val; #else // for digit team *(volatile uint32_t *)(s_dev_list[INDEX_PERIPHERAL].phy_addr + pgoffset) = val; #endif } int Xil_Peripheral_In32(uint32_t phyaddr) { uint32_t val; uint32_t pgoffset = phyaddr & ((uint32_t)(s_dev_list[INDEX_PERIPHERAL].mem_size -1)); pgoffset = phyaddr; #ifdef SYSTEM_LINUX // for software team val = *(volatile uint32_t *)(s_dev_list[INDEX_PERIPHERAL].vir_base + pgoffset); #else // for digit team val = *(volatile uint32_t *)(s_dev_list[INDEX_PERIPHERAL].phy_addr + pgoffset); #endif return val; } // for spi ip void Xil_SPI_Out32(uint32_t phyaddr, uint32_t val) { uint32_t pgoffset = phyaddr & ((uint32_t)(s_dev_list[INDEX_SPI].mem_size -1)); #ifdef SYSTEM_LINUX // for software team *(volatile uint32_t *)(s_dev_list[INDEX_SPI].vir_base + pgoffset) = val; #else // for digit team *(volatile uint32_t *)(s_dev_list[INDEX_SPI].phy_addr + pgoffset) = val; #endif } int Xil_SPI_In32(uint32_t phyaddr) { uint32_t val; uint32_t pgoffset = phyaddr & ((uint32_t)(s_dev_list[INDEX_SPI].mem_size -1)); #ifdef SYSTEM_LINUX // for software team val = *(volatile uint32_t *)(s_dev_list[INDEX_SPI].vir_base + pgoffset); #else // for digit team val = *(volatile uint32_t *)(s_dev_list[INDEX_SPI].phy_addr + pgoffset); #endif return val; } void set_led(uint8_t spi_id, uint32_t mode, uint32_t led_delay) { uint32_t reg_val; if (mode == LED_ON){ reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_ON & 0x1) << spi_id)); } else if (mode == LED_OFF){ reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_OFF & 0x1) << spi_id)); } else if (mode == LED_BLING_ON){ reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_OFF & 0x1) << spi_id)); cgsleep_us(led_delay*1000); reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_ON & 0x1) << spi_id)); cgsleep_us(led_delay*1000); } else if (mode == LED_BLING_OFF){ reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_ON & 0x1) << spi_id)); cgsleep_us(led_delay*1000); reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,(reg_val & (0xffffffff ^ ( 1 << spi_id)) ) | ((LED_OFF & 0x1) << spi_id)); cgsleep_us(led_delay*1000); } } // --------------------------------------------------------------------------- // For check status // --------------------------------------------------------------------------- int clear_wait_st_idle(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t data_buf; uint32_t cmd_status = 0; for(i=0; i= timeout_us){ applog(LOG_WARNING, "clear_wait_st_idle Wait SPI status clear timeout! i=%0d status=%8x ", i, cmd_status); return XST_FAILURE; } else { return XST_SUCCESS; } } int wait_cmd_done(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status = 0; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i++){ // polling cmd_done cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); applog(LOG_DEBUG, "Read SPI CMD_CTRL_REG2_ADDR: %08x ", cmd_status); //getchar(); // for debug if ((cmd_status&0xF0000000) != 0){ // spi fsm not idle } if ((cmd_status&0x00000001) == 1){ applog(LOG_DEBUG, "CMD done, status: %08x! ", cmd_status); break; } cgsleep_ms(1); //usleep(10); } if (i > timeout){ applog(LOG_WARNING, "SPI polling cmd done timeout! i=%0d ", i); return XST_FAILURE; } else { return XST_SUCCESS; } } int wait_phy_idle(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status = 0; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i++){ cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if ((cmd_status&0x00000040)==0x00000000) { cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); break; // state=0 cmd_done=1 } cgsleep_ms(1); // usleep(1); } if (i >= timeout_us){ applog(LOG_WARNING, "Wait SPI status clear timeout! i=%0d status=%8x ", i, cmd_status); return XST_FAILURE; } else { return XST_SUCCESS; } } int wait_spi_idle(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status = 0; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i ++){ cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if ((cmd_status&0xFF000040)==0) return XST_SUCCESS; cgsleep_ms(1); // usleep(20); } applog(LOG_DEBUG, "Wait SPI(%0d) idle timeout! time=%0d us, status=%8x ", spi_id, timeout_us, cmd_status); return XST_FAILURE; } int wait_write_buf_empty(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status = 0; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i++){ cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if ((cmd_status&0x03000000)==0) return XST_SUCCESS; cgsleep_ms(1); // usleep(10); // polling interval } //printf("Wait command write queue empty timeout!spi=%0d i=%0d status=%8x ",spi_id, i, cmd_status); return XST_FAILURE; } int check_cmd_status(uint8_t spi_id) { uint32_t cmd_status = 0; cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if (cmd_status & 0x00000004){ return XST_CRC_ERROR; } return XST_SUCCESS; } void reset_rx_buffer(uint8_t spi_id) { uint32_t cmd_status = 0; uint32_t write_data = 0; cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG1_ADDR); write_data = cmd_status & (~0x00000004); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG1_ADDR, write_data); cgsleep_ms(1); write_data = cmd_status | 0x00000004; Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG1_ADDR, write_data); } // --------------------------------------------------------------------------- // Below function is for new SPI design's nonce/receive queue // --------------------------------------------------------------------------- void read_rx_buffer(uint8_t spi_id, uint8_t* buf8, uint32_t len_cfg) { uint32_t i; uint8_t rx_len; rx_len = ((len_cfg & 0x0000FF00) >> 8)*2; // Get nonce data for(i = 0; i < rx_len; i+=4){ *(uint32_t*)(buf8+i) = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_READ_REG0_ADDR+i); } Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, 0x00000800); // tell hw one nonce is fetched } void fill_tx_buffer(uint8_t spi_id, uint8_t* buf8, uint32_t byte_len) { uint32_t i; for(i = 0; i < byte_len; i+=4) { Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_WRITE_REG01_ADDR+i, *(uint32_t*)(buf8+i)); } } // --------------------------------------------------------------------------- // Below function is for new SPI design's send queue // --------------------------------------------------------------------------- // SPI bypass = 0 int push_one_cmd(uint8_t spi_id, uint8_t* tx_buf8, uint32_t len_cfg, uint32_t last_job) { //uint32_t i; uint8_t byte_len; //uint32_t cmd_status; uint16_t cmd_header; byte_len = (len_cfg >> 24)*2; // Not include ending zeros cmd_header = (tx_buf8[1] << 8) | tx_buf8[0]; // wait command write queue empty if (wait_write_buf_empty(spi_id, 10000) == XST_FAILURE) return XST_FAILURE; if (wait_spi_idle(spi_id, 10000) == XST_FAILURE) return XST_FAILURE; // write header to buffer Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_WRITE_HEAD_ADDR, cmd_header); // write data to buffer fill_tx_buffer(spi_id, tx_buf8+2, byte_len-2); // Not include tx // send command execution Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG0_ADDR, len_cfg); if (last_job) Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, 0x00000001 | CHK_CMD | CHK_HY | CHK_LN); else Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, 0x00000011 | CHK_CMD | CHK_HY | CHK_LN); return XST_SUCCESS; } /***************************************/ // interface /***************************************/ void hub_spi_reset(uint8_t spi_id) { Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG1_ADDR,0x00000010); cgsleep_us(1); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG1_ADDR,0x0000001F); } int hub_spi_init(uint8_t spi_id, uint8_t chip_num) { uint32_t Status; //uint32_t i; Status = Xil_SPI_In32(SPI_RESET_REG); // reset Xil_SPI_Out32(SPI_RESET_REG,(Status & ~(1 << spi_id))); cgsleep_ms(1); // usleep(1); Status = Xil_SPI_In32(SPI_RESET_REG); // release reset Xil_SPI_Out32(SPI_RESET_REG,(Status | (1 << spi_id))); Status = Xil_SPI_In32(SPI_RESET_REG); hub_spi_reset(spi_id); // config max chip number Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR,0x00041004|(chip_num<<24)); // config not check header // Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG3_ADDR,0x000F00FF); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG3_ADDR, 0x000F0000 & chip_num); // config mask of each interrupt Xil_SPI_Out32(MAIN_CFG_REG2_ADDR, 0x00000); return XST_SUCCESS; } void hub_spi_clean_chain(uint32_t spi_id) { uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH] = {0}; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH] = {0}; spi_tx[0] = CMD_RESET; spi_tx[1] = CMD_ADDR_BROADCAST; spi_tx[2] = 0xff; spi_tx[3] = 0xff; do_spi_cmd(spi_id, spi_tx, spi_rx, 0x10001000); hub_spi_reset(spi_id); } void hub_set_spi_speed(uint8_t spi_id, int select) { uint32_t cfg[] = {0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200100, 0x00330100}; //float mcu_spi_clk[] = {0.39062, 0.78125, 1.5625, 3.125, 6.25, 9.96}; uint32_t read_data; read_data = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR,(read_data&0xFF00FFFF)|cfg[select]); read_data = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR); } // ----------- send job ------------ int send_job_queue(uint8_t spi_id, uint8_t* tx_buf8, uint8_t __maybe_unused *rx_buf8, uint32_t len_cfg, uint32_t last_job) { // push tx data to send buffer and start command if (push_one_cmd(spi_id, tx_buf8, len_cfg, last_job) != XST_SUCCESS) return XST_FAILURE; // wait all jobs are sent to chip if (last_job){ if (wait_spi_idle(spi_id, 100000) == XST_FAILURE) return XST_FAILURE; } // Clear status. Not mandatory but suggest if (last_job) clear_wait_st_idle(spi_id, 100000); // usleep(100); return XST_SUCCESS; } int send_one_cmd_split(uint8_t spi_id, uint8_t* tx_buf8, uint32_t len_cfg, uint32_t last_job, uint8_t cs_low) { uint32_t byte_len; uint16_t cmd_header; uint32_t cfg_reg0; byte_len = (len_cfg >> 24)*2; // Not include ending zeros cmd_header = (tx_buf8[1] << 8) | tx_buf8[0]; // change ext_zero to 0 cfg_reg0 = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR,(cfg_reg0&0xFFFFFF00)); // wait command write queue empty if (wait_write_buf_empty(spi_id, 10000) == XST_FAILURE) return XST_FAILURE; // write header to buffer Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_WRITE_HEAD_ADDR, cmd_header); // write data to buffer fill_tx_buffer(spi_id, tx_buf8+2, byte_len-2); // Not include tx // send command execution Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG0_ADDR, len_cfg); if (last_job) Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, (0x00000001 | CHK_HY | CHK_LN | cs_low<<14) ); else Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, (0x00000011 | CHK_HY | CHK_LN | cs_low<<14) ); // // check send queue full // cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); // if ((cmd_status&0x02000000)==0) { // DBGERROR("After push one command, send queue is not full!"); // return XST_FAILURE; // } // For half command application, can not use queue wait_cmd_done(spi_id, 10000); // change back ext_zero Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+MAIN_CFG_REG0_ADDR,cfg_reg0); return XST_SUCCESS; } bool rece_queue_ready_check(uint8_t spi_id, uint32_t len, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i++){ cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if (((cmd_status&0x00000010)==0x00000010) && ((((cmd_status&0x0000FF00)>>8)>=(len)))) return true; // wait nonce_ready = 1, cmd_done = 1 // if (((spi_tr.cmd_status&0x0000FF00)>>8)>=(len)) return true; // if ((spi_tr.cmd_status&0x00000010)==0x00000010) return true; cgsleep_ms(1); // usleep(10); } return false; } // Check receive queue empty. true: empty bool rece_queue_empty_check(uint8_t spi_id, uint32_t timeout_us) { uint32_t i; uint32_t cmd_status; uint32_t timeout = timeout_us / 1000 + 1; for(i = 0; i <= timeout; i++){ cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if ((cmd_status & 0x0000ff10)==0x00000000) { return true; // wait nonce_ready = 0, cmd_done = 1 } cgsleep_ms(1); // usleep(10); } return false; } bool rece_queue_has_nonce(uint8_t spi_id, uint32_t __maybe_unused timeout_us) { //uint32_t i; uint32_t cmd_status; cmd_status = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG2_ADDR); if ( ((cmd_status&0x0000ff00) >= 0x00000600) && ((cmd_status&0x00000010) == 0x00000010) ) { return true; // wait nonce_ready = 0, cmd_done = 1 } return false; } void read_nonce_buffer(uint8_t spi_id, uint8_t* buf8, uint32_t len_cfg) { uint32_t i; uint8_t rx_len; rx_len = (len_cfg & 0x0000FF00) >> 8; // Get nonce data for(i = 0; i < rx_len*2; i+=4){ *(uint32_t*)(buf8+i) = Xil_SPI_In32(SPI_BASEADDR_GAP*spi_id+CMD_READ_REG0_ADDR+i); } /* * if (buf8[0] == 00) * { * dump_spi_last_tr(spi_id); } */ Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, 0x00000B00); // tell hw one nonce is fetched, keep auto get nonce enable cgsleep_ms(1); // usleep(1); } int pop_one_rece(uint8_t spi_id, uint8_t* rx_buf8, uint32_t len_cfg) { //uint32_t i; uint32_t len = (len_cfg & 0x0000ff00) >> 8; // wait receive queue ready if (rece_queue_ready_check(spi_id, len, 50000) == false) { applog(LOG_INFO, "chain%d check receive buffer ready timeout!", spi_id); return XST_FAILURE; } /* * if (check_crc_status(spi_id) != XST_SUCCESS) { * applog(LOG_WARNING, "crc error "); * return XST_CRC_ERROR; * } */ // read back rx data read_rx_buffer(spi_id, rx_buf8, len_cfg); return XST_SUCCESS; } int do_spi_cmd(uint8_t spi_id, uint8_t* tx_buf8, uint8_t* rx_buf8, uint32_t len_cfg) { // reset_rx_buffer(spi_id); // push tx data to send buffer and start command if (push_one_cmd(spi_id, tx_buf8, len_cfg, 1) != XST_SUCCESS) { applog(LOG_ERR, "ERROR - failed to send spi cmd"); return XST_FAILURE; } // read back rx data if (pop_one_rece(spi_id, rx_buf8, len_cfg) != XST_SUCCESS) { applog(LOG_ERR, "ERROR - failed to recv spi data"); return XST_FAILURE; } if ((tx_buf8[0] & 0x0f) != (rx_buf8[0] & 0x0f)) { //hexdump_error("ERROR - recvbuf:", rx_buf8, 16); return XST_FAILURE; } // Clear status. Not mandatory but suggest clear_wait_st_idle(spi_id, 200); return XST_SUCCESS; } void enable_auto_cmd0a(uint8_t spi_id, uint32_t threshold, uint32_t msb, uint32_t lsb, uint32_t large_en, uint32_t mode )//mode : 1 only cmd0a;0 cmd08 follows cmd0a { uint32_t val; Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+CMD_CTRL_REG1_ADDR, 0x00000000 | CHK_CMD); val = ((msb << 24) & 0xff000000) | ((lsb << 16) & 0xff0000) | ((mode & 0x1) << 14) | ((large_en & 0x1) << 13) | (0x1 << 12) | ( threshold & 0xfff ); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+AUTO_CMD0A_REG0_ADDR, val); } void disable_auto_cmd0a(uint8_t spi_id, uint32_t threshold, uint32_t msb, uint32_t lsb, uint32_t large_en, uint32_t mode )//mode : 1 only cmd0a;0 cmd08 follows cmd0a { uint32_t val; val = ((msb << 24) & 0xff000000) | ((lsb << 16) & 0xff0000) | ((mode & 0x1) << 14) | ((large_en & 0x1) << 13) | (0x0 << 12) | ( threshold & 0xfff ); Xil_SPI_Out32(SPI_BASEADDR_GAP*spi_id+AUTO_CMD0A_REG0_ADDR, val); } int enable_auto_nonce(uint8_t spi_id, uint16_t cmd08_cmd, uint32_t len_cfg) { uint8_t send_buf8[12] = {0}; // wait all previous command done //clear_wait_st_idle(spi_id, 1000000); wait_spi_idle(spi_id, 10000); // set auto get nonce //for(i=0; i> chain_id) & 0x01); } #ifdef SYSTEM_LINUX static int set_warn(int spi_id) { mcompat_set_power_en(spi_id, 0); sleep(1); mcompat_set_reset(spi_id, 0); mcompat_set_start_en(spi_id, 0); do { mcompat_set_led(spi_id, 1); sleep(1); mcompat_set_led(spi_id, 0); sleep(1); }while(1); return 0; } static void hub_get_hitemp_stat(uint8_t chain_id,mcompat_temp_s *temp_ctrl) { bool over_temp = false; int reg_val; int tmp_val; reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP*chain_id+AUTO_CMD0A_REG3_ADDR); tmp_val = ((reg_val ) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_highest[0] = tmp_val; if ((temp_ctrl->temp_highest[0]) &&(temp_ctrl->temp_highest[0] < g_dangerous_temp)) over_temp = true; tmp_val = ((reg_val >> 10) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val >> 10) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_highest[1] = tmp_val; if ((temp_ctrl->temp_highest[1]) &&(temp_ctrl->temp_highest[1] < g_dangerous_temp)) over_temp = true; tmp_val = ((reg_val >> 20) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val >> 20) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_highest[2] = (reg_val >> 20 ) & 0x3ff; if ((temp_ctrl->temp_highest[2]) &&(temp_ctrl->temp_highest[2] < g_dangerous_temp)) over_temp = true; if (over_temp == true) set_warn(chain_id); applog(LOG_INFO,"chain %d,Hi: %d,%d,%d",chain_id,temp_ctrl->temp_highest[0],temp_ctrl->temp_highest[1],temp_ctrl->temp_highest[2]); } static void hub_get_lotemp_stat(uint8_t chain_id,mcompat_temp_s *temp_ctrl) { int reg_val; int tmp_val; reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP*chain_id+AUTO_CMD0A_REG2_ADDR); tmp_val = ((reg_val) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_lowest[0] = tmp_val; tmp_val = ((reg_val >> 10) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val >> 10) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_lowest[1] = tmp_val; tmp_val = ((reg_val >> 20) & 0x3ff) < g_temp_hi_thr ? 0x0:((reg_val >> 20) & 0x3ff); tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->temp_lowest[2] = tmp_val; applog(LOG_INFO,"chain %d,lo: %d,%d,%d",chain_id,temp_ctrl->temp_lowest[0],temp_ctrl->temp_lowest[1],temp_ctrl->temp_lowest[2]); } static void hub_get_avgtemp_stat(uint8_t chain_id,mcompat_temp_s *temp_ctrl) { int reg_val; int tmp_val; reg_val = Xil_SPI_In32(SPI_BASEADDR_GAP*chain_id+AUTO_CMD0A_REG4_ADDR); tmp_val = 2 * ((reg_val ) & 0xffff) / g_chip_num; tmp_val = tmp_val < g_temp_hi_thr ? 0x0:tmp_val; tmp_val = tmp_val > g_temp_lo_thr ? 0x0:tmp_val; temp_ctrl->final_temp_avg = tmp_val; applog(LOG_INFO,"chain %d,avg: %d",chain_id,temp_ctrl->final_temp_avg); } #endif void hub_set_vid_vid(uint8_t chain_id, int vid) { uint32_t reg_val = 0; int i = 0; uint8_t vid_binary[16] = {0}; for(i = 0; i < 8; i ++) { vid_binary[i] = ((vid >> i) & 0x1) ? 7 : 1; vid_binary[8+i] = (vid_binary[i] == 1) ? 7 : 1; } Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG32_OFFSET, 25000); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG33_OFFSET, (vid_binary[3] << 28) | (vid_binary[2] << 24) | (vid_binary[1] << 20) | (vid_binary[0] << 16) | 0xff); reg_val = 0; for(i = 0; i < 8; i ++) { reg_val = (vid_binary[i+4] << (i*4)) | reg_val; } Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG34_OFFSET, reg_val); reg_val = 0; for(i = 0; i < 4; i ++) { reg_val = (vid_binary[i+12] << (i*4)) | reg_val; } Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG35_OFFSET, reg_val); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG39_OFFSET, 80 | (4 << 16)); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG4_OFFSET, 0x1 << chain_id); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG3_OFFSET, 0x1 ); cgsleep_ms(100); } void hub_set_vid_uart_select(uint8_t spi_id) { Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG4_OFFSET, (0x1 << 16) | (0x1 << spi_id)); } void hub_set_pwm(uint8_t fan_id, int frequency, int duty) { #if 0 int duty_driver = 0; unsigned int value; duty_driver = frequency / 100 * duty; value = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG16_OFFSET + fan_id*8); value = value | (1<> 16) & 0x1)); } void hub_set_green_led(int mode) { uint32_t reg_val,SetRedRegValue; reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); if (LED_ON == mode) { SetRedRegValue = reg_val | 0x200; } else { SetRedRegValue = reg_val & (~0x200); } Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,SetRedRegValue); } void hub_set_red_led(int mode) { uint32_t reg_val,SetRedRegValue; reg_val = Xil_Peripheral_In32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET); if (LED_ON == mode) { SetRedRegValue = reg_val | 0x400; } else { SetRedRegValue = reg_val & (~0x400); } Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG9_OFFSET,SetRedRegValue); } void init_hub_gpio(void) { Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG1_OFFSET, 0); sleep(1); Xil_Peripheral_Out32(MCOMPAT_PERIPHERAL_S00_AXI_SLV_REG1_OFFSET, 3); } void flush_spi(uint8_t chain_id) { uint16_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint16_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); opi_spi_transfer(chain_id, spi_tx, spi_rx, MCOMPAT_CONFIG_MAX_CMD_LENGTH); } bool opi_spi_read_write(uint8_t chain_id, uint8_t *txbuf, uint8_t *rxbuf, int len) { int i; bool ret; int len16 = len / 2; uint16_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint16_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if (rxbuf == NULL) { applog(LOG_ERR, "%s,%s() %d: para erro! ", __FILE__, __func__, __LINE__); } memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); if (txbuf == NULL) { ret = opi_spi_transfer(chain_id, NULL, spi_rx, len16); } else { for(i = 0; i < len16; i++) { spi_tx[i] = OPI_MAKE_WORD(txbuf[2*i], txbuf[(2*i)+1]); } ret = opi_spi_transfer(chain_id, spi_tx, spi_rx, len16); } if (!ret) { return false; } for(i = 0; i < len16; i++) { rxbuf[2*i] = OPI_HI_BYTE(spi_rx[i]); rxbuf[(2*i)+1] = OPI_LO_BYTE(spi_rx[i]); } return true; } bool opi_send_command(uint8_t chain_id, uint8_t cmd, uint8_t chip_id, uint8_t *buff, int len) { int tx_len; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if (buff == NULL) { applog(LOG_ERR, "%s,%s() %d: para erro! ", __FILE__, __func__, __LINE__); } memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = OPI_HI_BYTE(AX_CMD_SYNC_HEAD); spi_tx[1] = OPI_LO_BYTE(AX_CMD_SYNC_HEAD); spi_tx[2] = cmd; spi_tx[3] = chip_id; if (len > 0) { memcpy(spi_tx + 4, buff, len); } tx_len = (4 + len + 1) & ~1; if (opi_spi_read_write(chain_id, spi_tx, spi_rx, tx_len)) { return true; } else { applog(LOG_ERR, "send command fail !"); return false; } } bool opi_poll_result(uint8_t chain_id, uint8_t cmd, uint8_t __maybe_unused chip_id, uint8_t *buff, int len) { int i; int tx_len; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if (buff == NULL) { applog(LOG_ERR, "%s,%s() %d: para erro! ", __FILE__, __func__, __LINE__); } memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); tx_len = g_chip_num * 4; for(i = 0; i < tx_len; i++) { cgsleep_ms(1); // usleep(1); if (opi_spi_read_write(chain_id, NULL, spi_rx, 2)) { break; } } if (i >= tx_len) { applog(LOG_ERR, "%s,%d: poll fail !", __FILE__, __LINE__); return false; } if ((spi_rx[0] != OPI_HI_BYTE(AX_CMD_SYNC_HEAD)) || (spi_rx[1] != OPI_LO_BYTE(AX_CMD_SYNC_HEAD))) { return false; } opi_spi_read_write(chain_id, NULL, spi_rx, 2); if (spi_rx[1] != OPI_STATUS_SUC) { return false; } opi_spi_read_write(chain_id, NULL, spi_rx, 2); if ((spi_rx[0] & 0x0f) != cmd) { return false; } if (len > 0) { opi_spi_read_write(chain_id, NULL, spi_rx+2, len); } memcpy(buff, spi_rx, len+2); return true; } bool opi_send_cmd(uint8_t chain_id, uint8_t cmd, uint8_t *buff, int len) { int tx_len; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if ((buff == NULL) && (len != 0)) { applog(LOG_ERR, "%s,%s() %d: para erro! ", __FILE__, __func__, __LINE__); } memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = OPI_HI_BYTE(CUSTOM_SYNC_HEAD); spi_tx[1] = OPI_LO_BYTE(CUSTOM_SYNC_HEAD); spi_tx[2] = cmd; spi_tx[3] = 0; if (len > 0) { memcpy(spi_tx + 4, buff, len); } tx_len = (4 + len + 1) & ~1; if (opi_spi_read_write(chain_id, spi_tx, spi_rx, tx_len)) { return true; } else { applog(LOG_ERR, "send command fail !"); return false; } } bool opi_poll_rslt(uint8_t chain_id, uint8_t __maybe_unused cmd, uint8_t *buff, int len) { int i; int tx_len; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if ((buff == NULL) && (len != 0)) { applog(LOG_ERR, "%s,%s() %d: para erro! ", __FILE__, __func__, __LINE__); } memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); tx_len = g_chip_num * 4; for(i = 0; i < tx_len; i++) { cgsleep_ms(1); // usleep(1); if (opi_spi_read_write(chain_id, NULL, spi_rx, 2)) { break; } } if (i >= tx_len) { applog(LOG_ERR, "%s,%d: poll fail !", __FILE__, __LINE__); return false; } if ((spi_rx[0] != OPI_HI_BYTE(CUSTOM_SYNC_HEAD)) || (spi_rx[1] != OPI_LO_BYTE(CUSTOM_SYNC_HEAD))) { return false; } opi_spi_read_write(chain_id, NULL, spi_rx, 2); if (spi_rx[1] != OPI_STATUS_SUC) { return false; } if (len > 0) { opi_spi_read_write(chain_id, NULL, spi_rx+2, len); memcpy(buff, spi_rx+2, len); } return true; } void opi_set_power_en(unsigned char chain_id, int val) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (val >> 0) & 0xff; tx_buf[1] = (val >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_POWER_EN, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return; } if (!opi_poll_rslt(chain_id, OPI_SET_POWER_EN, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return; } } void opi_set_start_en(unsigned char chain_id, int val) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (val >> 0) & 0xff; tx_buf[1] = (val >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_STARR_EN, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return; } if (!opi_poll_rslt(chain_id, OPI_SET_STARR_EN, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return; } } bool opi_set_reset(unsigned char chain_id, int val) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (val >> 0) & 0xff; tx_buf[1] = (val >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_RESET, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } if (!opi_poll_rslt(chain_id, OPI_SET_RESET, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } void opi_set_led(unsigned char chain_id, int val) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (val >> 0) & 0xff; tx_buf[1] = (val >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_LED, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return; } if (!opi_poll_rslt(chain_id, OPI_SET_LED, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return; } } int opi_get_plug(unsigned char chain_id) { unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!opi_send_cmd(chain_id, OPI_SET_LED, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return -1; } memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_rslt(chain_id, OPI_SET_LED, rx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return -1; } return (int)(rx_buf[0]); } bool opi_set_vid(unsigned char chain_id, int vid) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (vid >> 0) & 0xff; tx_buf[1] = (vid >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_VID, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } if (!opi_poll_rslt(chain_id, OPI_SET_VID, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } void opi_set_pwm(unsigned char fan_id, int frequency, int duty) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = fan_id; tx_buf[1] = 0x00; tx_buf[2] = (frequency >> 0) & 0xff; tx_buf[3] = (frequency >> 8) & 0xff; tx_buf[4] = (frequency >> 16) & 0xff; tx_buf[5] = (frequency >> 24) & 0xff; tx_buf[6] = (duty >> 0) & 0xff; tx_buf[7] = (duty >> 8) & 0xff; if (!opi_send_cmd(0, OPI_SET_PWM, tx_buf, 8)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return; } if (!opi_poll_rslt(0, OPI_SET_PWM, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return; } } bool opi_chain_power_on(unsigned char chain_id) { applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!opi_send_cmd(chain_id, OPI_POWER_ON, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } if (!opi_poll_rslt(chain_id, OPI_POWER_ON, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_chain_power_down(unsigned char chain_id) { applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!opi_send_cmd(chain_id, OPI_POWER_DOWN, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } if (!opi_poll_rslt(chain_id, OPI_POWER_DOWN, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_chain_hw_reset(unsigned char chain_id) { applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!opi_send_cmd(chain_id, OPI_POWER_RESET, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } if (!opi_poll_rslt(chain_id, OPI_POWER_RESET, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_chain_power_on_all(void) { int i; for(i = 0; i < g_chain_num; i++) { opi_chain_power_on(i); } return true; } bool opi_chain_power_down_all(void) { int i; for(i = 0; i < g_chain_num; i++) { opi_chain_power_down(i); } return true; } void opi_set_spi_speed(unsigned char chain_id, int index) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); tx_buf[0] = (index >> 0) & 0xff; tx_buf[1] = (index >> 8) & 0xff; if (!opi_send_cmd(chain_id, OPI_SET_SPI_SPEED, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return; } if (!opi_poll_rslt(chain_id, OPI_SET_SPI_SPEED, NULL, 0)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return; } } const int pin_power_en[] = { MCOMPAT_CONFIG_CHAIN0_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN1_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN2_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN3_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN4_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN5_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN6_POWER_EN_GPIO, MCOMPAT_CONFIG_CHAIN7_POWER_EN_GPIO }; const int pin_start_en[] = { MCOMPAT_CONFIG_CHAIN0_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN1_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN2_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN3_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN4_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN5_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN6_START_EN_GPIO, MCOMPAT_CONFIG_CHAIN7_START_EN_GPIO }; const int pin_reset[] = { MCOMPAT_CONFIG_CHAIN0_RESET_GPIO, MCOMPAT_CONFIG_CHAIN1_RESET_GPIO, MCOMPAT_CONFIG_CHAIN2_RESET_GPIO, MCOMPAT_CONFIG_CHAIN3_RESET_GPIO, MCOMPAT_CONFIG_CHAIN4_RESET_GPIO, MCOMPAT_CONFIG_CHAIN5_RESET_GPIO, MCOMPAT_CONFIG_CHAIN6_RESET_GPIO, MCOMPAT_CONFIG_CHAIN7_RESET_GPIO }; const int pin_plug[] = { MCOMPAT_CONFIG_CHAIN0_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN1_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN2_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN3_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN4_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN5_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN6_PLUG_GPIO, MCOMPAT_CONFIG_CHAIN7_PLUG_GPIO }; const int pin_led[] = { MCOMPAT_CONFIG_CHAIN0_LED_GPIO, MCOMPAT_CONFIG_CHAIN1_LED_GPIO, MCOMPAT_CONFIG_CHAIN2_LED_GPIO, MCOMPAT_CONFIG_CHAIN3_LED_GPIO, MCOMPAT_CONFIG_CHAIN4_LED_GPIO, MCOMPAT_CONFIG_CHAIN5_LED_GPIO, MCOMPAT_CONFIG_CHAIN6_LED_GPIO, MCOMPAT_CONFIG_CHAIN7_LED_GPIO }; void spi_send_data_in_word(ZYNQ_SPI_T *spi, unsigned char *buf, int len) { int i; for(i = 0; i < len; i = i + 2) { zynq_spi_write(spi, buf + i, 2); } } void spi_recv_data_in_word(ZYNQ_SPI_T *spi, unsigned char *buf, int len) { int i; for(i = 0; i < len; i = i + 2) { zynq_spi_read(spi, buf + i, 2); } } void spi_send_data(ZYNQ_SPI_T *spi, unsigned char *buf, int len) { zynq_spi_write(spi, buf, len); } void spi_recv_data(ZYNQ_SPI_T *spi, unsigned char *buf, int len) { zynq_spi_read(spi, buf, len); } bool spi_send_command(ZYNQ_SPI_T *spi, unsigned char cmd, unsigned char chip_id, unsigned char *buff, int len) { int tx_len; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; if ((len > 0) && (buff == NULL)) { applog(LOG_ERR, "%s,%d: para error !", __FILE__, __LINE__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); tx_buf[0] = cmd; tx_buf[1] = chip_id; if (len > 0) { memcpy(tx_buf + 2, buff, len); } tx_len = (2 + len + 1) & ~1; //spi_send_data_in_word(spi, tx_buf, tx_len); spi_send_data(spi, tx_buf, tx_len); return true; } bool spi_poll_result(ZYNQ_SPI_T *spi, unsigned char cmd, unsigned char __maybe_unused chip_id, unsigned char *buff, int len) { int i; int max_len; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { spi_recv_data(spi, rx_buf, 2); if ((rx_buf[0] & 0x0f) == cmd) { break; } } if (i >= max_len) { applog(LOG_ERR, "%s,%d: poll fail !", __FILE__, __LINE__); return false; } spi_recv_data_in_word(spi, rx_buf+2, len); memcpy(buff, rx_buf, len+2); return true; } void init_spi_gpio(int chain_num) { int i; for(i = 0; i < chain_num; i++) { zynq_gpio_init(pin_power_en[i], 0); zynq_gpio_init(pin_start_en[i], 0); zynq_gpio_init(pin_reset[i], 0); zynq_gpio_init(pin_led[i], 0); zynq_gpio_init(pin_plug[i], 1); } } void exit_spi_gpio(int chain_num) { int i; for(i = 0; i < chain_num; i++) { zynq_gpio_exit(pin_power_en[i]); zynq_gpio_exit(pin_start_en[i]); zynq_gpio_exit(pin_reset[i]); zynq_gpio_exit(pin_led[i]); zynq_gpio_exit(pin_plug[i]); } } void spi_set_power_en(unsigned char chain_id, int val) { zynq_gpio_write(pin_power_en[chain_id], val); } void spi_set_start_en(unsigned char chain_id, int val) { zynq_gpio_write(pin_start_en[chain_id], val); } bool spi_set_reset(unsigned char chain_id, int val) { return zynq_gpio_write(pin_reset[chain_id], val); } void spi_set_led(unsigned char chain_id, int val) { zynq_gpio_write(pin_led[chain_id], val); } int spi_get_plug(unsigned char chain_id) { return zynq_gpio_read(pin_plug[chain_id]); } static int s_vid = 0; bool spi_set_vid(unsigned char chain_id, int vid) { if (g_platform == PLATFORM_ZYNQ_SPI_G19) { zynq_gpio_g19_vid_set(chain_id, vid); } else if (g_platform == PLATFORM_ZYNQ_SPI_G9) { if (s_vid != vid) { zynq_gpio_g9_vid_set(vid); } } else { applog(LOG_ERR, "platform[%d] error in set vid ", g_platform); return false; } return true; } void spi_set_spi_speed(unsigned char __maybe_unused chain_id, int index) { uint32_t cfg[] = {390625, 781250, 1562500, 3125000, 6250000, 9960000}; zynq_set_spi_speed(cfg[index]); } bool zynq_chain_power_on(unsigned char chain_id) { if (mcompat_get_plug(chain_id) != 0) { applog(LOG_NOTICE, "chain %d >>> the board not inserted !!!", chain_id); return false; } mcompat_set_power_en(chain_id, 1); sleep(5); mcompat_set_reset(chain_id, 1); sleep(1); mcompat_set_start_en(chain_id, 1); return true; } bool zynq_chain_power_down(unsigned char chain_id) { mcompat_set_power_en(chain_id, 0); sleep(1); mcompat_set_reset(chain_id, 0); mcompat_set_start_en(chain_id, 0); mcompat_set_led(chain_id, 1); return true; } bool zynq_chain_hw_reset(unsigned char chain_id) { mcompat_set_reset(chain_id, 0); sleep(1); mcompat_set_reset(chain_id, 1); sleep(1); return true; } bool zynq_chain_power_on_all(void) { int i; for(i = 0; i < g_chain_num; i++) { if (mcompat_get_plug(i) != 0) { applog(LOG_NOTICE, "chain %d >>> the board not inserted !!! ", i); } } for(i = 0; i < g_chain_num; i++) { mcompat_set_power_en(i, 1); cgsleep_ms(5); } sleep(5); for(i = 0; i < g_chain_num; i++) { mcompat_set_reset(i, 1); cgsleep_ms(5); } sleep(1); for(i = 0; i < g_chain_num; i++) { mcompat_set_start_en(i, 1); cgsleep_ms(5); } return true; } bool zynq_chain_power_down_all(void) { int i; for(i = 0; i < g_chain_num; i++) { mcompat_set_power_en(i, 0); } sleep(1); for(i = 0; i < g_chain_num; i++) { mcompat_set_reset(i, 0); mcompat_set_start_en(i, 0); mcompat_set_led(i, 1); } return true; } bool init_hub_cmd(int chain_num, int chip_num) { int i; for(i = 0; i < chain_num; i++) { hub_spi_init(i, chip_num); } return true; } bool exit_hub_cmd(int __maybe_unused chain_num) { return true; } bool hub_cmd_reset(unsigned char chain_id, unsigned char chip_id, unsigned char *in, unsigned char *out) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_RESET; spi_tx[1] = chip_id; spi_tx[2] = in[0]; spi_tx[3] = in[1]; //cfg_len = 0x03000200; cfg_len += (0x03) << 24; cfg_len += (0x00) << 16; cfg_len += (0x02) << 8; cfg_len += (0x00) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } //print_data_hex("tx:", spi_tx, 8); //print_data_hex("rx:", spi_rx, 8); memcpy(out, spi_rx, 4); return true; } int hub_cmd_bist_start(unsigned char chain_id, unsigned char chip_id) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_BIST_START; spi_tx[1] = chip_id; //cfg_len = 0x02000200; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (0x02) << 8; cfg_len += (0x00) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return -1; } //print_data_hex("tx:", spi_tx, 8); //print_data_hex("rx:", spi_rx, 8); return spi_rx[3];; } bool hub_cmd_bist_collect(unsigned char chain_id, unsigned char chip_id) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_BIST_COLLECT; spi_tx[1] = chip_id; //cfg_len = 0x02000200; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (0x02) << 8; cfg_len += (0x00) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } return true; } bool hub_cmd_bist_fix(unsigned char chain_id, unsigned char chip_id) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_BIST_FIX; spi_tx[1] = chip_id; //cfg_len = 0x02000200; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (0x02) << 8; cfg_len += (0x00) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } return true; } bool hub_cmd_write_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_WRITE_REG; spi_tx[1] = chip_id; memcpy(spi_tx + 2, reg, len); //cfg_len = 0x09070807; cfg_len += (((len / 2) + 2) & 0xff) << 24; cfg_len += (((len / 2) + 1) & 0xff) << 16; cfg_len += (((len / 2) + 2) & 0xff) << 8; cfg_len += (((len / 2) + 1) & 0xff) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } return true; } bool hub_cmd_read_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; int i; unsigned short crc1, crc2; uint8_t tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_READ_REG; spi_tx[1] = chip_id; //cfg_len = 0x02000807; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (((len / 2) + 2) & 0xff) << 8; cfg_len += (((len / 2) + 1) & 0xff) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = spi_rx[i + 1]; tmp_buf[i + 1] = spi_rx[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (spi_rx[2 + len + 0] << 8) + (spi_rx[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(reg, spi_rx + 2, len); return true; } bool hub_cmd_read_write_reg0d(unsigned char chain_id, unsigned char chip_id, unsigned char *in, int len, unsigned char *out) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; int i; unsigned short crc1, crc2; uint8_t tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_WRITE_REG0d; spi_tx[1] = chip_id; memcpy(spi_tx + 2, in, len); //cfg_len = 0x09070807; cfg_len += (((len / 2) + 2) & 0xff) << 24; cfg_len += (((len / 2) + 1) & 0xff) << 16; cfg_len += (((len / 2) + 2) & 0xff) << 8; cfg_len += (((len / 2) + 1) & 0xff) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) { return false; } for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = spi_rx[i + 1]; tmp_buf[i + 1] = spi_rx[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (spi_rx[2 + len + 0] << 8) + (spi_rx[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(out, spi_rx + 2, len); return true; } bool hub_cmd_write_job(unsigned char chain_id, unsigned char chip_id, unsigned char *job, int len) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); memcpy(spi_tx, job, len); //cfg_len = 0x504f0000; cfg_len += (((len / 2) + 1) & 0xff) << 24; cfg_len += (((len / 2) - 1) & 0xff) << 16; cfg_len += (0x00) << 8; cfg_len += (0x00) << 0; if (send_job_queue(chain_id, spi_tx, spi_rx, cfg_len, (chip_id == 1)) == XST_FAILURE) { return false; } return true; } bool hub_cmd_read_result(unsigned char chain_id, unsigned char chip_id, unsigned char *res, int len) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; int i; unsigned short crc1, crc2; uint8_t tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); spi_tx[0] = CMD_READ_RESULT; spi_tx[1] = chip_id; // cfg_len = 0x02000605; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (((len / 2) + 3) & 0xff) << 8; cfg_len += (((len / 2) + 2) & 0xff) << 0; if (do_spi_cmd(chain_id, spi_tx, spi_rx, cfg_len) == XST_FAILURE) return false; if (spi_rx[1] == 0) return false; for (i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = spi_rx[i + 1]; tmp_buf[i + 1] = spi_rx[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (spi_rx[2 + len + 0] << 8) + (spi_rx[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(res, spi_rx, len + 2); return true; } bool hub_cmd_auto_nonce(unsigned char chain_id, int mode, int len) { uint16_t cmd08 = 0x0800; uint32_t cfg_len = 0; // cfg_len = 0x02000605; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (((len / 2) + 3) & 0xff) << 8; cfg_len += (((len / 2) + 2) & 0xff) << 0; if (mode == 0) disable_auto_nonce(chain_id); else enable_auto_nonce(chain_id, cmd08, cfg_len); return true; } bool hub_cmd_read_nonce(unsigned char chain_id, unsigned char *res, int len) { uint32_t cfg_len = 0; uint8_t spi_tx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; uint8_t spi_rx[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; memset(spi_tx, 0, sizeof(spi_tx)); memset(spi_rx, 0, sizeof(spi_rx)); // cfg_len = 0x02000605; cfg_len += (0x02) << 24; cfg_len += (0x00) << 16; cfg_len += (((len / 2) + 3) & 0xff) << 8; cfg_len += (((len / 2) + 2) & 0xff) << 0; if (!rece_queue_has_nonce(chain_id, 1000)) return false; read_nonce_buffer(chain_id, spi_rx, cfg_len); if (spi_rx[1] == 0) return false; //print_data_hex("read_nonce rx:", spi_rx, len + 2); memcpy(res, spi_rx, len + 2); return true; } bool hub_cmd_get_temp(mcompat_fan_temp_s *fan_temp_ctrl,unsigned char chain_id) { uint32_t val; if (hub_get_plug(chain_id)) return false; enable_auto_cmd0a(chain_id,g_dangerous_temp,33,24,0,0); mcompat_temp_s *temp_ctrl = &fan_temp_ctrl->mcompat_temp[chain_id]; do{ val = Xil_SPI_In32(SPI_AXIBASE + SPI_BASEADDR_GAP*chain_id+AUTO_CMD0A_REG4_ADDR); }while(!((val >> 24) & 0x1)); hub_get_hitemp_stat(chain_id,temp_ctrl); hub_get_lotemp_stat(chain_id,temp_ctrl); hub_get_avgtemp_stat(chain_id,temp_ctrl); disable_auto_cmd0a(chain_id,g_dangerous_temp,33,24,0,0); return true; } bool init_opi_cmd(void) { opi_spi_init(); return true; } bool exit_opi_cmd(void) { opi_spi_exit(); return true; } bool opi_cmd_reset(unsigned char chain_id, unsigned char chip_id, unsigned char *in, unsigned char *out) { unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!opi_send_command(chain_id, CMD_RESET, chip_id, in, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_result(chain_id, CMD_RESET, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memcpy(out, rx_buf, 4); return true; } int opi_cmd_bist_start(unsigned char chain_id, unsigned char chip_id) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!opi_send_command(chain_id, CMD_BIST_START, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return -1; } memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_result(chain_id, CMD_BIST_START, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return -1; } return rx_buf[3]; } bool opi_cmd_bist_collect(unsigned char chain_id, unsigned char chip_id) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!opi_send_command(chain_id, CMD_BIST_COLLECT, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_result(chain_id, CMD_BIST_COLLECT, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_cmd_bist_fix(unsigned char chain_id, unsigned char chip_id) { unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!opi_send_command(chain_id, CMD_BIST_FIX, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_result(chain_id, CMD_BIST_FIX, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_cmd_write_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { int i; unsigned short crc; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (reg == NULL) { applog(LOG_ERR, "%s,%d: %s para error !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); tx_buf[0] = OPI_HI_BYTE(AX_CMD_SYNC_HEAD); tx_buf[1] = OPI_LO_BYTE(AX_CMD_SYNC_HEAD); tx_buf[2] = CMD_WRITE_REG; tx_buf[3] = chip_id; memcpy(tx_buf + 4, reg, len); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = tx_buf[i + 1 + 2]; tmp_buf[i + 1] = tx_buf[i + 0 + 2]; } crc = CRC16_2(tmp_buf, len + 2); tx_buf[4 + len + 0] = (unsigned char)((crc >> 8) & 0xff); tx_buf[4 + len + 1] = (unsigned char)((crc >> 0) & 0xff); opi_spi_read_write(chain_id, tx_buf, rx_buf, len + 6); memset(rx_buf, 0, sizeof(rx_buf)); if (!opi_poll_result(chain_id, CMD_WRITE_REG, chip_id, rx_buf, len)) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } return true; } bool opi_cmd_read_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { int i; int max_len; unsigned short crc1, crc2; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (reg == NULL) { applog(LOG_ERR, "%s,%d: %s para error !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); if (!opi_send_command(chain_id, CMD_READ_REG, chip_id, tx_buf, 0)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { opi_spi_read_write(chain_id, NULL, rx_buf, 2); if ((rx_buf[0] & 0x0f) == CMD_READ_REG) { break; } } if (i >= max_len) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } opi_spi_read_write(chain_id, NULL, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s,%d: %s crc fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memcpy(reg, rx_buf + 2, len); return true; } bool opi_cmd_read_write_reg0d(unsigned char chain_id, unsigned char chip_id, unsigned char *in, int len, unsigned char *out) { int i; int max_len; unsigned short crc; unsigned short crc1, crc2; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if ((in == NULL) || (out == NULL)) { applog(LOG_ERR, "%s,%d: %s para error !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); tx_buf[0] = OPI_HI_BYTE(AX_CMD_SYNC_HEAD); tx_buf[1] = OPI_LO_BYTE(AX_CMD_SYNC_HEAD); tx_buf[2] = CMD_WRITE_REG0d; tx_buf[3] = chip_id; memcpy(tx_buf + 4, in, len); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = tx_buf[i + 1 + 2]; tmp_buf[i + 1] = tx_buf[i + 0 + 2]; } crc = CRC16_2(tmp_buf, len + 2); tx_buf[4 + len + 0] = (unsigned char)((crc >> 8) & 0xff); tx_buf[4 + len + 1] = (unsigned char)((crc >> 0) & 0xff); opi_spi_read_write(chain_id, tx_buf, rx_buf, len + 6); max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { opi_spi_read_write(chain_id, NULL, rx_buf, 2); if ((rx_buf[0] & 0x0f) == CMD_WRITE_REG0d) { break; } } if (i >= max_len) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } opi_spi_read_write(chain_id, NULL, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s,%d: %s crc fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memcpy(out, rx_buf + 2, len); return true; } bool opi_cmd_read_result(unsigned char chain_id, unsigned char chip_id, unsigned char *res, int len) { int i; int max_len; unsigned short crc1, crc2; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (res == NULL) { applog(LOG_ERR, "%s,%d: %s para error !", __FILE__, __LINE__, __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); if (!opi_send_command(chain_id, CMD_READ_RESULT, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s,%d: %s send fail !", __FILE__, __LINE__, __FUNCTION__); return false; } max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { opi_spi_read_write(chain_id, NULL, rx_buf, 2); if (((rx_buf[0] & 0x0f) == CMD_READ_RESULT) && (rx_buf[1] != 0)) { break; } } if (i >= max_len) { applog(LOG_WARNING, "%s,%d: %s poll fail !", __FILE__, __LINE__, __FUNCTION__); return false; } opi_spi_read_write(chain_id, NULL, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s,%d: %s crc fail !", __FILE__, __LINE__, __FUNCTION__); return false; } memcpy(res, rx_buf, len + 2); return true; } bool opi_cmd_write_job(unsigned char chain_id, unsigned char chip_id, unsigned char *job, int len) { applog(LOG_DEBUG, "%s,%d: %s(%d, %d, %p, %d)", __FILE__, __LINE__, __FUNCTION__, chain_id, chip_id, job, len); if (job == NULL) { applog(LOG_ERR, "%s,%d: %s para error !", __FILE__, __LINE__, __FUNCTION__); return false; } return opi_spi_read_write(chain_id, NULL, job, len); } ZYNQ_SPI_T s_spi[MCOMPAT_CONFIG_MAX_CHAIN_NUM]; bool init_spi_cmd(int chain_num) { int i; for(i = 0; i < chain_num; i++) { memset((void*)&s_spi[i], 0, sizeof(ZYNQ_SPI_T)); zynq_spi_init(&s_spi[i], i); } return true; } bool exit_spi_cmd(int chain_num) { int i; for(i = 0; i < chain_num; i++) { zynq_spi_exit(&s_spi[i]); } return true; } bool spi_cmd_reset(unsigned char chain_id, unsigned char chip_id, unsigned char *in, unsigned char *out) { ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (!spi_send_command(spi, CMD_RESET, chip_id, in, 2)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!spi_poll_result(spi, CMD_RESET, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } memcpy(out, rx_buf, 4); return true; } int spi_cmd_bist_start(unsigned char chain_id, unsigned char chip_id) { ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!spi_send_command(spi, CMD_BIST_START, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return -1; } memset(rx_buf, 0, sizeof(rx_buf)); if (!spi_poll_result(spi, CMD_BIST_START, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return -1; } return rx_buf[3]; } bool spi_cmd_bist_collect(unsigned char chain_id, unsigned char chip_id) { ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!spi_send_command(spi, CMD_BIST_COLLECT, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!spi_poll_result(spi, CMD_BIST_COLLECT, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } return true; } bool spi_cmd_bist_fix(unsigned char chain_id, unsigned char chip_id) { ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); memset(tx_buf, 0, sizeof(tx_buf)); if (!spi_send_command(spi, CMD_BIST_FIX, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return false; } memset(rx_buf, 0, sizeof(rx_buf)); if (!spi_poll_result(spi, CMD_BIST_FIX, chip_id, rx_buf, 2)) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } return true; } bool spi_cmd_write_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { int i; unsigned short crc; ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (reg == NULL) { applog(LOG_ERR, "%s para error !", __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); tx_buf[0] = CMD_WRITE_REG; tx_buf[1] = chip_id; memcpy(tx_buf + 2, reg, len); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = tx_buf[i + 1]; tmp_buf[i + 1] = tx_buf[i + 0]; } crc = CRC16_2(tmp_buf, len + 2); tx_buf[2 + len + 0] = (unsigned char)((crc >> 8) & 0xff); tx_buf[2 + len + 1] = (unsigned char)((crc >> 0) & 0xff); spi_send_data(spi, tx_buf, len + 4); memset(rx_buf, 0, sizeof(rx_buf)); if (!spi_poll_result(spi, CMD_WRITE_REG, chip_id, rx_buf, len)) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } return true; } bool spi_cmd_read_register(unsigned char chain_id, unsigned char chip_id, unsigned char *reg, int len) { int i; int max_len; unsigned short crc1, crc2; ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (reg == NULL) { applog(LOG_ERR, "%s para error !", __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); if (!spi_send_command(spi, CMD_READ_REG, chip_id, tx_buf, 0)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return false; } max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { spi_recv_data(spi, rx_buf, 2); if (rx_buf[0] == RESP_READ_REG) { break; } } if (i >= max_len) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } spi_recv_data_in_word(spi, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(reg, rx_buf + 2, len); return true; } bool spi_cmd_read_write_reg0d(unsigned char chain_id, unsigned char chip_id, unsigned char *in, int len, unsigned char *out) { int i; int max_len; unsigned short crc; unsigned short crc1, crc2; ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if ((in == NULL) || (out == NULL)) { applog(LOG_ERR, "%s para error !", __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); tx_buf[0] = CMD_WRITE_REG0d; tx_buf[1] = chip_id; memcpy(tx_buf + 2, in, len); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = tx_buf[i + 1]; tmp_buf[i + 1] = tx_buf[i + 0]; } crc = CRC16_2(tmp_buf, len + 2); tx_buf[2 + len + 0] = (unsigned char)((crc >> 8) & 0xff); tx_buf[2 + len + 1] = (unsigned char)((crc >> 0) & 0xff); spi_send_data(spi, tx_buf, len + 4); max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { spi_recv_data(spi, rx_buf, 2); if ((rx_buf[0] & 0x0f) == CMD_WRITE_REG0d) { break; } } if (i >= max_len) { applog(LOG_WARNING, "%s poll fail !", __FUNCTION__); return false; } spi_recv_data_in_word(spi, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(out, rx_buf + 2, len); return true; } bool spi_cmd_read_result(unsigned char chain_id, unsigned char chip_id, unsigned char *res, int len) { int i; int max_len; unsigned short crc1, crc2; ZYNQ_SPI_T *spi = &s_spi[chain_id]; unsigned char tx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char rx_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; unsigned char tmp_buf[MCOMPAT_CONFIG_MAX_CMD_LENGTH]; applog(LOG_DEBUG, "%s,%d: %s ", __FILE__, __LINE__, __FUNCTION__); if (res == NULL) { applog(LOG_ERR, "%s para error !", __FUNCTION__); return false; } memset(tx_buf, 0, sizeof(tx_buf)); if (!spi_send_command(spi, CMD_READ_RESULT, chip_id, tx_buf, 2)) { applog(LOG_WARNING, "%s send fail !", __FUNCTION__); return false; } max_len = g_chip_num * 4; memset(rx_buf, 0, sizeof(rx_buf)); for(i = 0; i < max_len; i = i + 2) { spi_recv_data(spi, rx_buf, 2); if (((rx_buf[0] & 0x0f) == CMD_READ_RESULT) && (rx_buf[1] != 0)) { break; } } if (i >= max_len) { return false; } spi_recv_data_in_word(spi, rx_buf + 2, len + 2); for(i = 0; i < len + 2; i = i + 2) { tmp_buf[i + 0] = rx_buf[i + 1]; tmp_buf[i + 1] = rx_buf[i + 0]; } crc1 = CRC16_2(tmp_buf, len + 2); crc2 = (rx_buf[2 + len + 0] << 8) + (rx_buf[2 + len + 1] << 0); if (crc1 != crc2) { applog(LOG_WARNING, "%s crc error !", __FUNCTION__); return false; } memcpy(res, rx_buf, len + 2); return true; } bool spi_cmd_write_job(unsigned char chain_id, unsigned char chip_id, unsigned char *job, int len) { ZYNQ_SPI_T *spi = &s_spi[chain_id]; applog(LOG_DEBUG, "%s,%d: %s(%d, %d, %p, %d)", __FILE__, __LINE__, __FUNCTION__, chain_id, chip_id, job, len); if (job == NULL) { applog(LOG_ERR, "%s para error !", __FUNCTION__); return false; } spi_send_data(spi, job, len); return true; } const unsigned short wCRCTalbeAbs[] = { 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, }; unsigned short CRC16_2(unsigned char* pchMsg, unsigned short wDataLen) { volatile unsigned short wCRC = 0xFFFF; unsigned short i; unsigned char chChar; for (i = 0; i < wDataLen; i++) { chChar = *pchMsg++; wCRC = wCRCTalbeAbs[(chChar ^ wCRC) & 15] ^ (wCRC >> 4); wCRC = wCRCTalbeAbs[((chChar >> 4) ^ wCRC) & 15] ^ (wCRC >> 4); } return wCRC; } void print_data_hex(char *arg, unsigned char *buff, int len) { int i = 0; printf("%s ", arg); for(i = 0; i < len; i++) { printf("0x%02x ", buff[i]); if ((i % 16) == 15) { //printf(""); } } if ((len % 16) != 0) { //printf(""); } } unsigned int SUNXI_IO_BASE = 0; /******************************************************************************************* * GPIO *******************************************************************************************/ int gpio_init(void) { int fd; unsigned int addr_start, addr_offset, PageSize, PageMask; void *pc; fd = open("/dev/mem", O_RDWR); if (fd < 0) return -1; PageSize = sysconf(_SC_PAGESIZE); PageMask = (~(PageSize - 1)); addr_start = SW_PORTC_IO_BASE & PageMask; addr_offset = SW_PORTC_IO_BASE & ~PageMask; pc = (void *)mmap(0, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start); if (pc == MAP_FAILED) return -1; SUNXI_IO_BASE = (unsigned int) pc; SUNXI_IO_BASE += addr_offset; close(fd); return 0; } int gpio_setcfg(unsigned int pin, unsigned int p1) { unsigned int cfg; unsigned int bank = GPIO_BANK(pin); unsigned int index = GPIO_CFG_INDEX(pin); unsigned int offset = GPIO_CFG_OFFSET(pin); if (SUNXI_IO_BASE == 0) return -1; struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_IO_BASE)->gpio_bank[bank]; cfg = *(&pio->cfg[0] + index); cfg &= ~(0xf << offset); cfg |= p1 << offset; *(&pio->cfg[0] + index) = cfg; return 0; } int gpio_getcfg(unsigned int pin) { unsigned int cfg; unsigned int bank = GPIO_BANK(pin); unsigned int index = GPIO_CFG_INDEX(pin); unsigned int offset = GPIO_CFG_OFFSET(pin); if (SUNXI_IO_BASE == 0) return -0; struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_IO_BASE)->gpio_bank[bank]; cfg = *(&pio->cfg[0] + index); cfg >>= offset; return (cfg & 0xf); } int gpio_output(unsigned int pin, unsigned int p1) { unsigned int bank = GPIO_BANK(pin); unsigned int num = GPIO_NUM(pin); if (SUNXI_IO_BASE == 0) return -1; struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_IO_BASE)->gpio_bank[bank]; if (p1) *(&pio->dat) |= 1 << num; else *(&pio->dat) &= ~(1 << num); return 0; } int gpio_pullup(unsigned int pin, unsigned int p1) { unsigned int cfg; unsigned int bank = GPIO_BANK(pin); unsigned int index = GPIO_PUL_INDEX(pin); unsigned int offset = GPIO_PUL_OFFSET(pin); if (SUNXI_IO_BASE == 0) return -1; struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_IO_BASE)->gpio_bank[bank]; cfg = *(&pio->pull[0] + index); cfg &= ~(0x3 << offset); cfg |= p1 << offset; *(&pio->pull[0] + index) = cfg; return 0; } int gpio_input(unsigned int pin) { unsigned int dat; unsigned int bank = GPIO_BANK(pin); unsigned int num = GPIO_NUM(pin); if (SUNXI_IO_BASE == 0) return -1; struct sunxi_gpio *pio = &((struct sunxi_gpio_reg *) SUNXI_IO_BASE)->gpio_bank[bank]; dat = *(&pio->dat); dat >>= num; return (dat & 0x1); } /******************************************************************************************* * I2C *******************************************************************************************/ int i2c_open(char *dev, uint8_t address) { int fd; int ret; fd = open(dev, O_RDWR); if (fd < 0) return fd; ret = ioctl(fd, I2C_SLAVE_FORCE, address); if (ret < 0) return ret; return fd; } int i2c_close(int fd) { return (close(fd)); } int i2c_send(int fd, uint8_t *buf, uint8_t num_bytes) { return (write(fd, buf, num_bytes)); } int i2c_read(int fd, uint8_t *buf, uint8_t num_bytes) { return (write(fd, buf, num_bytes)); } /******************************************************************************************* * spi *******************************************************************************************/ int spi_open(char *dev, spi_config_t config) { int fd; fd = open(dev, O_RDWR); if (fd < 0) return fd; /* Set SPI_POL and SPI_PHA */ if (ioctl(fd, SPI_IOC_WR_MODE, &config.mode) < 0) return -1; if (ioctl(fd, SPI_IOC_RD_MODE, &config.mode) < 0) return -1; /* Set bits per word*/ if (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config.bits) < 0) return -1; if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &config.bits) < 0) return -1; /* Set SPI speed*/ if (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config.speed) < 0) return -1; if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &config.speed) < 0) return -1; return fd; } int spi_close(int fd) { return (close(fd)); } int spi_xfer(int fd, uint8_t *tx_buf, uint8_t tx_len, uint8_t *rx_buf, uint8_t rx_len) { struct spi_ioc_transfer spi_message[2]; memset(spi_message, 0, sizeof(spi_message)); spi_message[0].rx_buf = (unsigned long)tx_buf; spi_message[0].len = tx_len; spi_message[1].tx_buf = (unsigned long)rx_buf; spi_message[1].len = rx_len; return ioctl(fd, SPI_IOC_MESSAGE(2), spi_message); } int spi_read(int fd, uint8_t *rx_buf, uint8_t rx_len) { struct spi_ioc_transfer spi_message[1]; memset(spi_message, 0, sizeof(spi_message)); spi_message[0].rx_buf = (unsigned long)rx_buf; spi_message[0].len = rx_len; return ioctl(fd, SPI_IOC_MESSAGE(1), spi_message); } int spi_write(int fd, uint8_t *tx_buffer, uint8_t tx_len) { struct spi_ioc_transfer spi_message[1]; memset(spi_message, 0, sizeof(spi_message)); spi_message[0].tx_buf = (unsigned long)tx_buffer; spi_message[0].len = tx_len; return ioctl(fd, SPI_IOC_MESSAGE(1), spi_message); } /******************************************************************************************* * time *******************************************************************************************/ void delay(unsigned int howLong) { struct timespec sleeper, dummy ; sleeper.tv_sec = (time_t)(howLong / 1000) ; sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ; nanosleep (&sleeper, &dummy) ; } static int opi_spi_fd = 0; static pthread_mutex_t opi_spi_lock; static struct spi_config opi_spi_config = { .bus = DEFAULT_SPI_BUS, .cs_line = DEFAULT_SPI_CS_LINE, .mode = DEFAULT_SPI_MODE, .speed = DEFAULT_SPI_SPEED, .bits = DEFAULT_SPI_BITS_PER_WORD, .delay = DEFAULT_SPI_DELAY_USECS, }; void opi_spi_gpio_init(void) { if (gpio_init() == -1) { printf("gpio initial fail"); } gpio_setcfg(PIN_SPI_E1, OUTPUT); gpio_output(PIN_SPI_E1, HIGH); gpio_setcfg(PIN_SPI_A0, OUTPUT); gpio_output(PIN_SPI_A0, HIGH); gpio_setcfg(PIN_SPI_A1, OUTPUT); gpio_output(PIN_SPI_A1, HIGH); gpio_setcfg(PIN_SPI_A2, OUTPUT); gpio_output(PIN_SPI_A2, HIGH); } void opi_spi_cs_enable(int id) { if (id & 01) { gpio_output(PIN_SPI_A0, HIGH); } else { gpio_output(PIN_SPI_A0, LOW); } if (id & 02) { gpio_output(PIN_SPI_A1, HIGH); } else { gpio_output(PIN_SPI_A1, LOW); } if (id & 04) { gpio_output(PIN_SPI_A2, HIGH); } else { gpio_output(PIN_SPI_A2, LOW); } gpio_output(PIN_SPI_E1, LOW); } void opi_spi_cs_disable(void) { gpio_output(PIN_SPI_E1, HIGH); } void opi_spi_init(void) { char dev_fname[PATH_MAX]; struct spi_config *config = &opi_spi_config; pthread_mutex_init(&opi_spi_lock, NULL); opi_spi_gpio_init(); sprintf(dev_fname, SPI_DEVICE_TEMPLATE, config->bus, config->cs_line); int fd = open(dev_fname, O_RDWR); if (fd < 0) { applog(LOG_ERR, "SPI: Can not open SPI device %s ", dev_fname); } if ((ioctl(fd, SPI_IOC_WR_MODE, &config->mode) < 0) || (ioctl(fd, SPI_IOC_RD_MODE, &config->mode) < 0) || (ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &config->bits) < 0) || (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &config->bits) < 0) || (ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &config->speed) < 0) || (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &config->speed) < 0)) { close(fd); applog(LOG_ERR, "SPI: ioctl error on SPI device %s", dev_fname); } opi_spi_fd = fd; applog(LOG_INFO, "SPI '%s': mode=%hhu, bits=%hhu, speed=%u ", dev_fname, config->mode, config->bits, config->speed); } void opi_spi_exit(void) { close(opi_spi_fd); } /* * void opi_set_spi_speed(uint32_t speed) * { * pthread_mutex_lock(&opi_spi_lock); * * if ((ioctl(opi_spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, speed) < 0) || * (ioctl(opi_spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, speed) < 0)) { * applog(LOG_ERR, "SPI: ioctl error on SPI device"); * } * * opi_spi_config.speed = speed; * * pthread_mutex_unlock(&opi_spi_lock); * } */ bool opi_spi_transfer(uint8_t id, uint16_t *txbuf, uint16_t *rxbuf, int len) { struct spi_ioc_transfer xfr; int ret; if (rxbuf != NULL) { memset(rxbuf, 0xff, len); } pthread_mutex_lock(&opi_spi_lock); opi_spi_cs_enable(id); cgsleep_ms(1); // usleep(1); ret = len; xfr.tx_buf = (unsigned long)txbuf; xfr.rx_buf = (unsigned long)rxbuf; xfr.len = len; xfr.speed_hz = opi_spi_config.speed; xfr.delay_usecs = opi_spi_config.delay; xfr.bits_per_word = opi_spi_config.bits; xfr.cs_change = 0; xfr.pad = 0; ret = ioctl(opi_spi_fd, SPI_IOC_MESSAGE(1), &xfr); if (ret < 1) { applog(LOG_ERR, "SPI: ioctl error on SPI device: %d", ret); } cgsleep_ms(1); // usleep(1); opi_spi_cs_disable(); pthread_mutex_unlock(&opi_spi_lock); return ret > 0; } int g_platform; int g_miner_type; int g_chain_num; int g_chip_num; bool sys_platform_init(int platform, int miner_type, int chain_num, int chip_num) { applog(LOG_NOTICE, "sys : platform[%d] miner_type[%d] chain_num[%d] chip_num[%d] ", platform, miner_type, chain_num, chip_num); switch(platform) { case PLATFORM_ZYNQ_SPI_G9: case PLATFORM_ZYNQ_SPI_G19: case PLATFORM_ZYNQ_HUB_G9: case PLATFORM_ZYNQ_HUB_G19: case PLATFORM_SOC: break; default: applog(LOG_ERR, "the platform is undefined !!! "); break; } if (chain_num > MCOMPAT_CONFIG_MAX_CHAIN_NUM) { applog(LOG_ERR, "the chain_num is error !!! "); return false; } if (chip_num > MCOMPAT_CONFIG_MAX_CHIP_NUM) { applog(LOG_ERR, "the chip_num is error !!! "); return false; } g_platform = platform; g_miner_type = miner_type; g_chain_num = chain_num; g_chip_num = chip_num; init_mcompat_cmd(); init_mcompat_gpio(); init_mcompat_pwm(); init_mcompat_chain(); return true; } bool sys_platform_exit(void) { exit_mcompat_cmd(); exit_mcompat_gpio(); exit_mcompat_pwm(); exit_mcompat_chain(); return true; }