| /** | 
 |  * Copyright (C) 2017 IBM Corporation | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 | #include "cfam_access.hpp" | 
 | #include "p9_cfam.hpp" | 
 | #include "registration.hpp" | 
 | #include "targeting.hpp" | 
 |  | 
 | #include <phosphor-logging/log.hpp> | 
 |  | 
 | namespace openpower | 
 | { | 
 | namespace p9 | 
 | { | 
 |  | 
 | using namespace phosphor::logging; | 
 | using namespace openpower::cfam::access; | 
 | using namespace openpower::cfam::p9; | 
 | using namespace openpower::targeting; | 
 |  | 
 | /** | 
 |  * @brief Performs the 'VCS Workaround' on all P9s in the system. | 
 |  * @return void | 
 |  */ | 
 | void vcsWorkaround() | 
 | { | 
 |     Targeting targets; | 
 |     const auto& master = *(targets.begin()); | 
 |  | 
 |     // First determine if we need to run this workaround (not needed on chips | 
 |     // which are not DD1.0) | 
 |     // Mixing DD1.0 parts with other levels is not allowed so just look | 
 |     // at the first chip | 
 |     auto chipID = readReg(master, P9_FSI2PIB_CHIPID); | 
 |     if (chipID != P9_DD10_CHIPID) | 
 |     { | 
 |         log<level::INFO>("P9 procedure vcsWorkaround not needed", | 
 |                          entry("CHIPID=0x%08X", chipID)); | 
 |         return; | 
 |     } | 
 |  | 
 |     log<level::INFO>("Running P9 procedure vcsWorkaround", | 
 |                      entry("NUM_PROCS=%d", targets.size())); | 
 |  | 
 |     // Set asynchronous clock mode | 
 |     writeReg(master, P9_LL_MODE_REG, 0x00000001); | 
 |  | 
 |     for (const auto& t : targets) | 
 |     { | 
 |         // Unfence PLL controls | 
 |         writeRegWithMask(t, P9_ROOT_CTRL0, 0x00000000, 0x00010000); | 
 |  | 
 |         // Assert Perv chiplet endpoint reset | 
 |         writeRegWithMask(t, P9_PERV_CTRL0, 0x40000000, 0x40000000); | 
 |  | 
 |         // Enable Nest PLL | 
 |         writeRegWithMask(t, P9_PERV_CTRL0, 0x00000001, 0x00000001); | 
 |     } | 
 | } | 
 |  | 
 | REGISTER_PROCEDURE("vcsWorkaround", vcsWorkaround); | 
 |  | 
 | } // namespace p9 | 
 | } // namespace openpower |