blob: 4a3ca4b2737c6fd27b5e716d75e10a6c24b9cc33 [file] [log] [blame]
Kuiying Wang64ff7ce2018-08-15 11:17:06 +08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#include "power_control.hpp"
17
James Feist676d2c32019-02-14 10:07:27 -080018bool PowerControl::forcePowerOff()
Kuiying Wang80f6d922018-11-13 16:34:07 +080019{
James Feist676d2c32019-02-14 10:07:27 -080020 return true;
Kuiying Wang80f6d922018-11-13 16:34:07 +080021}
22
Kuiying Wang6ce6ab42019-01-29 11:10:13 +080023int32_t PowerControl::triggerReset()
Kuiying Wang64ff7ce2018-08-15 11:17:06 +080024{
25 int ret = 0;
26 int count = 0;
27 char buf = '0';
28
Kuiying Wang6ce6ab42019-01-29 11:10:13 +080029 phosphor::logging::log<phosphor::logging::level::DEBUG>("triggerReset");
30
31 ret = ::lseek(reset_out_fd, 0, SEEK_SET);
32 if (ret < 0)
33 {
34 phosphor::logging::log<phosphor::logging::level::ERR>("lseek error!");
35 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
36 IOError();
37 }
38
39 buf = '0';
40
41 ret = ::write(reset_out_fd, &buf, sizeof(buf));
42 if (ret < 0)
43 {
44 phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
45 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
46 IOError();
47 }
48
49 std::this_thread::sleep_for(std::chrono::milliseconds(RESET_PULSE_TIME_MS));
50
51 buf = '1';
52 ret = ::write(reset_out_fd, &buf, sizeof(buf));
53 if (ret < 0)
54 {
55 phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
56 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
57 IOError();
58 }
59 return 0;
60}
61
62int32_t PowerControl::setPowerState(int newState)
63{
64 int ret = 0;
65 int count = 0;
66 char buf = '0';
67
68 if (newState < 0 || newState >= powerStateMax)
69 {
70 phosphor::logging::log<phosphor::logging::level::ERR>(
71 "error! invalid parameter!");
72 return -1;
73 }
74
Kuiying Wang64ff7ce2018-08-15 11:17:06 +080075 phosphor::logging::log<phosphor::logging::level::DEBUG>(
76 "setPowerState", phosphor::logging::entry("NEWSTATE=%d", newState));
77
Kuiying Wang6ce6ab42019-01-29 11:10:13 +080078 if (powerStateReset == newState)
79 {
80 phosphor::logging::log<phosphor::logging::level::DEBUG>(
81 "setPowerState system reset");
82 triggerReset();
83 return 0;
84 }
85
Kuiying Wang64ff7ce2018-08-15 11:17:06 +080086 if (state() == newState)
87 {
88 phosphor::logging::log<phosphor::logging::level::WARNING>(
89 "Same powerstate",
90 phosphor::logging::entry("NEWSTATE=%d", newState));
91 return 0;
92 }
Patrick Venture8fbed2e2018-11-01 19:25:31 -070093
Kuiying Wang6ce6ab42019-01-29 11:10:13 +080094 state(newState);
95
Kuiying Wang64ff7ce2018-08-15 11:17:06 +080096 ret = ::lseek(power_up_fd, 0, SEEK_SET);
97 if (ret < 0)
98 {
Patrick Venture8fbed2e2018-11-01 19:25:31 -070099 phosphor::logging::log<phosphor::logging::level::ERR>("lseek error!");
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800100 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
101 IOError();
102 }
103
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800104 buf = '0';
Kuiying Wang6ce6ab42019-01-29 11:10:13 +0800105
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800106 ret = ::write(power_up_fd, &buf, sizeof(buf));
107 if (ret < 0)
108 {
Kuiying Wang6ce6ab42019-01-29 11:10:13 +0800109 phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800110 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
111 IOError();
112 }
113
Kuiying Wang6ce6ab42019-01-29 11:10:13 +0800114 phosphor::logging::log<phosphor::logging::level::DEBUG>(
115 "setPowerState power on");
116 std::this_thread::sleep_for(std::chrono::milliseconds(POWER_PULSE_TIME_MS));
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800117
118 buf = '1';
119 ret = ::write(power_up_fd, &buf, sizeof(buf));
120 if (ret < 0)
121 {
Kuiying Wang6ce6ab42019-01-29 11:10:13 +0800122 phosphor::logging::log<phosphor::logging::level::ERR>("write error!");
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800123 throw sdbusplus::xyz::openbmc_project::Chassis::Common::Error::
124 IOError();
125 }
126
Kuiying Wang6ce6ab42019-01-29 11:10:13 +0800127 if (0 == newState)
128 {
129 /*
130 * For power off, currently there is a known issue, the "long-press"
131 * power button cannot power off the host, a workaround is perform force
132 * power off after waitting for a while
133 */
134 std::this_thread::sleep_for(
135 std::chrono::milliseconds(POWER_PULSE_TIME_MS));
136 if (1 == pGood())
137 { // still on, force off!
138 phosphor::logging::log<phosphor::logging::level::DEBUG>(
139 "Perform force power off");
140 count = 0;
141 do
142 {
143 if (count++ > 5)
144 {
145 phosphor::logging::log<phosphor::logging::level::ERR>(
146 "forcePowerOff error!");
147 throw sdbusplus::xyz::openbmc_project::Chassis::Common::
148 Error::IOError();
149 }
150 ret = forcePowerOff();
151 std::this_thread::sleep_for(
152 std::chrono::milliseconds(POLLING_INTERVAL_MS));
153 } while (ret != 0);
154 }
155 }
Kuiying Wang64ff7ce2018-08-15 11:17:06 +0800156 return 0;
157}