/* USRP E310 FPGA driver * Copyright (C) 2014 Ettus Research * This file is part of the USRP E310 Firmware * The USRP E310 Firmware 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 2 of the License, or * (at your option) any later version. * The USRP E310 Firmware is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with the USRP E310 Firmware. If not, see . */ #include "eeprom.h" #include "fpga.h" #include "spi.h" #include "mcu_settings.h" #include "utils.h" #include #include #include typedef struct fpga_tx_mem_map0 { uint16_t battery_voltage; uint8_t battery_status; uint8_t charger_status; uint8_t unused[2]; uint8_t version; uint8_t type; } fpga_tx_mem_map0_t; typedef struct fpga_tx_mem_map1 { uint8_t status; uint16_t voltage; uint16_t temp; uint16_t charge; uint8_t type; } fpga_tx_mem_map1_t; typedef struct fpga_tx_mem_map2 { uint8_t unused[4]; uint8_t settings; uint16_t charge_last_full; uint8_t type; } fpga_tx_mem_map2_t; typedef struct fpga_rx_mem_map0 { uint8_t unused[2]; uint16_t value; uint8_t reg; uint8_t os_status; } fpga_rx_mem_map0_t; typedef struct fpga_rx_mem_map1 { uint8_t unused[3]; uint16_t value; uint8_t reg; } fpga_rx_mem_map1_t; typedef struct fpga_rx_mem_map { uint8_t valid; union { fpga_rx_mem_map0_t map0; fpga_rx_mem_map1_t map1; }; uint8_t type; } fpga_rx_mem_map_t; static bool shutdown = false; static bool write_charge = false; static bool write_settings = false; static volatile fpga_tx_mem_map0_t fpga_tx0; static volatile fpga_tx_mem_map1_t fpga_tx1; static volatile fpga_tx_mem_map2_t fpga_tx2; static volatile fpga_rx_mem_map_t fpga_rx; /* battery status */ static const uint8_t BATTERY_TEMP_ALERT_MASK = BIT(7) | BIT(6); static const uint8_t BATTERY_TEMP_ALERT_SHIFT = 6; static const uint8_t BATTERY_ONLINE_MASK = BIT(5); static const uint8_t BATTERY_ONLINE_SHIFT = 5; static const uint8_t BATTERY_HEALTH_MASK = BIT(4) | BIT(3) | BIT(2); static const uint8_t BATTERY_HEALTH_SHIFT = 2; static const uint8_t BATTERY_STATUS_MASK = BIT(1) | BIT(0); static const uint8_t BATTERY_STATUS_SHIFT = 0; /* charger_status */ static const uint8_t CHARGER_HEALTH_MASK = BIT(5) | BIT(4); static const uint8_t CHARGER_HEALTH_SHIFT = 4; static const uint8_t CHARGER_ONLINE_MASK = BIT(3); static const uint8_t CHARGER_ONLINE_SHIFT = 3; /* BIT(2) is unused */ static const uint8_t CHARGER_CHARGE_TYPE_MASK = BIT(1) | BIT(0); static const uint8_t CHARGER_CHARGE_TYPE_SHIFT = 0; void fpga_set_battery_voltage(uint16_t voltage) { fpga_tx0.battery_voltage = voltage; } void fpga_set_battery_temp_alert(uint8_t alert) { uint8_t status = fpga_tx0.battery_status; status &= ~BATTERY_TEMP_ALERT_MASK; status |= alert << BATTERY_TEMP_ALERT_SHIFT; fpga_tx0.battery_status = status; } void fpga_set_battery_online(bool online) { uint8_t status = fpga_tx0.battery_status; status &= ~BATTERY_ONLINE_MASK; status |= (online ? 1 : 0) << BATTERY_ONLINE_SHIFT; fpga_tx0.battery_status = status; } void fpga_set_battery_health(uint8_t health) { uint8_t status = fpga_tx0.battery_status; status &= ~BATTERY_HEALTH_MASK; status |= health << BATTERY_HEALTH_SHIFT; fpga_tx0.battery_status = status; } void fpga_set_battery_status(uint8_t st) { uint8_t status = fpga_tx0.battery_status; status &= ~BATTERY_STATUS_MASK; status |= st << BATTERY_STATUS_SHIFT; fpga_tx0.battery_status = status; } void fpga_set_charger_health(uint8_t health) { uint8_t status = fpga_tx0.charger_status; status &= ~CHARGER_HEALTH_MASK; status |= health << CHARGER_HEALTH_SHIFT; fpga_tx0.charger_status = status; } void fpga_set_charger_online(bool online) { uint8_t status = fpga_tx0.charger_status; status &= ~CHARGER_ONLINE_MASK; status |= (online ? 1 : 0) << CHARGER_ONLINE_SHIFT; fpga_tx0.charger_status = status; } void fpga_set_charger_charge_type(uint8_t type) { uint8_t status = fpga_tx0.charger_status; status &= ~CHARGER_CHARGE_TYPE_MASK; status |= type << CHARGER_CHARGE_TYPE_SHIFT; fpga_tx0.charger_status = status; } void fpga_set_gauge_charge(uint16_t charge) { fpga_tx1.charge = charge; } uint16_t fpga_get_gauge_charge(void) { return fpga_tx1.charge; } bool fpga_get_write_charge(void) { bool ret = false; if (write_charge) { ret = write_charge; write_charge = false; } return ret; } uint8_t fpga_get_settings(void) { return fpga_tx2.settings; } bool fpga_get_write_settings(void) { bool ret = false; if (write_settings) { ret = write_settings; write_settings = false; } return ret; } void fpga_set_gauge_charge_last_full(uint16_t charge) { fpga_tx2.charge_last_full = charge; } void fpga_set_gauge_temp(uint16_t temp) { fpga_tx1.temp = temp; } void fpga_set_gauge_voltage(uint16_t volt) { fpga_tx1.voltage = volt; } void fpga_set_gauge_status(uint8_t status) { fpga_tx1.status = status; } bool fpga_get_shutdown(void) { return shutdown; } void fpga_init(void) { memset((void *) &fpga_tx0, 0, sizeof(fpga_tx0)); memset((void *) &fpga_tx1, 0, sizeof(fpga_tx1)); memset((void *) &fpga_tx2, 0, sizeof(fpga_tx2)); fpga_tx0.type = 0; fpga_tx0.version = VERSION_MAJ << 4 | VERSION_MIN; fpga_tx1.type = 1; fpga_tx2.type = 2; /* get autoboot value from eeprom, keep TX reg on */ fpga_tx2.settings = BIT(1); fpga_tx2.settings |= eeprom_get_autoboot() ? BIT(0) : 0x0; memset((void *) &fpga_rx, 0, sizeof(fpga_rx)); shutdown = false; } void fpga_handle_write(uint8_t reg, uint16_t value) { if (reg == 0x10) { fpga_tx1.charge = value; write_charge = true; } else if (reg == 0x14) { fpga_tx1.status = value; } else if (reg == 0x1c) { fpga_tx2.settings = (uint8_t) value; write_settings = true; } } void fpga_sync(void) { fpga_rx_mem_map_t rx; spi_transact_buf((uint8_t *) &fpga_tx0, (uint8_t *) &rx, 8); if (rx.valid) { if (rx.type == 0 && rx.map0.os_status == 0x7a) shutdown = true; else if (rx.type == 1) fpga_handle_write(rx.map1.reg, rx.map1.value); } spi_transact_buf((uint8_t *) &fpga_tx1, (uint8_t *) &rx, 8); if (rx.valid) { if (rx.type == 0 && rx.map0.os_status == 0x7a) shutdown = true; else if (rx.type == 1) fpga_handle_write(rx.map1.reg, rx.map1.value); } spi_transact_buf((uint8_t *) &fpga_tx2, (uint8_t *) &rx, 8); if (rx.valid) { if (rx.type == 0 && rx.map0.os_status == 0x7a) shutdown = true; else if (rx.type == 1) fpga_handle_write(rx.map1.reg, rx.map1.value); } }