1 #include <unistd.h> 2 3 #include <gpiod.hpp> 4 #include <phosphor-logging/log.hpp> 5 #include <registration.hpp> 6 7 #include <chrono> 8 #include <fstream> 9 #include <system_error> 10 #include <thread> 11 12 namespace openpower 13 { 14 namespace misc 15 { 16 17 constexpr auto cfamResetPath = "/sys/class/fsi-master/fsi0/device/cfam_reset"; 18 19 using namespace phosphor::logging; 20 21 /** 22 * @brief Reset the CFAM using the appropriate GPIO 23 * @return void 24 */ 25 void cfamReset() 26 { 27 28 // First look if system supports kernel sysfs based cfam reset 29 // If it does then write a 1 and let the kernel handle the reset 30 std::ofstream file; 31 file.open(cfamResetPath); 32 if (!file) 33 { 34 log<level::DEBUG>("system does not support kernel cfam reset, default " 35 "to using libgpiod"); 36 } 37 else 38 { 39 // Write a 1 to have kernel toggle the reset 40 file << "1"; 41 file.close(); 42 log<level::DEBUG>("cfam reset via sysfs complete"); 43 return; 44 } 45 46 // No kernel support so toggle gpio from userspace 47 const std::string cfamReset = {"cfam-reset"}; 48 auto line = gpiod::find_line(cfamReset); 49 if (!line) 50 { 51 log<level::ERR>("failed to find cfam-reset line"); 52 throw std::system_error(ENODEV, std::system_category()); 53 } 54 55 // Configure this app to own the gpio while doing the reset 56 gpiod::line_request conf; 57 conf.consumer = "cfamReset"; 58 conf.request_type = gpiod::line_request::DIRECTION_OUTPUT; 59 line.request(conf); 60 61 // Put chips into reset 62 line.set_value(0); 63 64 // Sleep one second to ensure reset processed 65 using namespace std::chrono_literals; 66 std::this_thread::sleep_for(1s); 67 68 // Take chips out of reset 69 line.set_value(1); 70 } 71 72 REGISTER_PROCEDURE("cfamReset", cfamReset) 73 74 } // namespace misc 75 } // namespace openpower 76