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 // First look if system supports kernel sysfs based cfam reset 28 // If it does then write a 1 and let the kernel handle the reset 29 std::ofstream file; 30 file.open(cfamResetPath); 31 if (!file) 32 { 33 log<level::DEBUG>("system does not support kernel cfam reset, default " 34 "to using libgpiod"); 35 } 36 else 37 { 38 // Write a 1 to have kernel toggle the reset 39 file << "1"; 40 file.close(); 41 log<level::DEBUG>("cfam reset via sysfs complete"); 42 return; 43 } 44 45 // No kernel support so toggle gpio from userspace 46 const std::string cfamReset = {"cfam-reset"}; 47 auto line = gpiod::find_line(cfamReset); 48 if (!line) 49 { 50 log<level::ERR>("failed to find cfam-reset line"); 51 throw std::system_error(ENODEV, std::system_category()); 52 } 53 54 // Configure this app to own the gpio while doing the reset 55 gpiod::line_request conf; 56 conf.consumer = "cfamReset"; 57 conf.request_type = gpiod::line_request::DIRECTION_OUTPUT; 58 line.request(conf); 59 60 // Put chips into reset 61 line.set_value(0); 62 63 // Sleep one second to ensure reset processed 64 using namespace std::chrono_literals; 65 std::this_thread::sleep_for(1s); 66 67 // Take chips out of reset 68 line.set_value(1); 69 } 70 71 REGISTER_PROCEDURE("cfamReset", cfamReset) 72 73 } // namespace misc 74 } // namespace openpower 75