blob: e764c863cf97f22fe4785c743082379bf3910ba1 [file] [log] [blame]
Matt Spinler0c0eeff2017-02-28 10:06:56 -06001/**
2 * Copyright © 2017 IBM 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 */
Matt Spinlera231ceb2017-10-04 11:26:09 -050016#include <phosphor-logging/elog.hpp>
17#include <phosphor-logging/elog-errors.hpp>
18#include <xyz/openbmc_project/Common/Device/error.hpp>
19#include <xyz/openbmc_project/Common/File/error.hpp>
Matt Spinler0c0eeff2017-02-28 10:06:56 -060020#include <unistd.h>
Matt Spinler0c0eeff2017-02-28 10:06:56 -060021#include "cfam_access.hpp"
22#include "targeting.hpp"
23
24namespace openpower
25{
26namespace cfam
27{
28namespace access
29{
30
31constexpr auto cfamRegSize = 4;
32
33using namespace openpower::targeting;
Matt Spinlerc3bffed2017-03-10 09:05:30 -060034using namespace openpower::util;
Matt Spinlera231ceb2017-10-04 11:26:09 -050035namespace file_error = sdbusplus::xyz::openbmc_project::
36 Common::File::Error;
37namespace device_error = sdbusplus::xyz::openbmc_project::
38 Common::Device::Error;
Matt Spinler0c0eeff2017-02-28 10:06:56 -060039
40/**
41 * Converts the CFAM register address used by the calling
42 * code (because that's how it is in the spec) to the address
43 * required by the device driver.
44 */
45static inline cfam_address_t makeOffset(cfam_address_t address)
46{
47 return (address & 0xFC00) | ((address & 0x03FF) << 2);
48}
49
50
51void writeReg(const std::unique_ptr<Target>& target,
52 cfam_address_t address,
53 cfam_data_t data)
54{
Dhruvaraj Subhashchandran18b07862017-04-26 07:13:35 -050055 using namespace phosphor::logging;
Matt Spinlerc3bffed2017-03-10 09:05:30 -060056 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060057 if (rc < 0)
58 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050059 log<level::ERR>("Failed seeking on a processor CFAM",
60 entry("CFAM_ADDRESS=0x%X", address));
61
62 using metadata = xyz::openbmc_project::Common::File::Seek;
63
64 elog<file_error::Seek>(
65 metadata::OFFSET(makeOffset(address)),
66 metadata::WHENCE(SEEK_SET),
67 metadata::ERRNO(errno),
68 metadata::PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -060069 }
70
Edward A. James8316b772017-04-24 14:20:48 -050071 data = target->swapEndian(data);
72
Matt Spinlerc3bffed2017-03-10 09:05:30 -060073 rc = write(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060074 if (rc < 0)
75 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050076 using metadata = xyz::openbmc_project::Common::Device::WriteFailure;
77
78 elog<device_error::WriteFailure>(
79 metadata::CALLOUT_ERRNO(errno),
80 metadata::CALLOUT_DEVICE_PATH(
81 target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -060082 }
83}
84
85
86cfam_data_t readReg(const std::unique_ptr<Target>& target,
87 cfam_address_t address)
88{
Dhruvaraj Subhashchandran18b07862017-04-26 07:13:35 -050089 using namespace phosphor::logging;
90
Matt Spinler0c0eeff2017-02-28 10:06:56 -060091 cfam_data_t data = 0;
92
Matt Spinlerc3bffed2017-03-10 09:05:30 -060093 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060094 if (rc < 0)
95 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050096 log<level::ERR>("Failed seeking on a processor CFAM",
97 entry("CFAM_ADDRESS=0x%X", address));
98
99 using metadata = xyz::openbmc_project::Common::File::Seek;
100
101 elog<file_error::Seek>(
102 metadata::OFFSET(makeOffset(address)),
103 metadata::WHENCE(SEEK_SET),
104 metadata::ERRNO(errno),
105 metadata::PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600106 }
107
Matt Spinlerc3bffed2017-03-10 09:05:30 -0600108 rc = read(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600109 if (rc < 0)
110 {
Matt Spinlera231ceb2017-10-04 11:26:09 -0500111 using metadata = xyz::openbmc_project::Common::Device::ReadFailure;
112
113 elog<device_error::ReadFailure>(
114 metadata::CALLOUT_ERRNO(errno),
115 metadata::CALLOUT_DEVICE_PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600116 }
117
Edward A. James8316b772017-04-24 14:20:48 -0500118 return target->swapEndian(data);
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600119}
120
121
122void writeRegWithMask(const std::unique_ptr<Target>& target,
123 cfam_address_t address,
124 cfam_data_t data,
125 cfam_mask_t mask)
126{
127 cfam_data_t readData = readReg(target, address);
128
129 readData &= ~mask;
130 readData |= (data & mask);
131
132 writeReg(target, address, readData);
133}
134
135}
136}
137}