blob: 810a28191591fa944043cca2ff34685b5fc77205 [file] [log] [blame]
Matt Spinler0c0eeff2017-02-28 10:06:56 -06001/**
Patrick Venturee84b4dd2018-11-01 16:06:31 -07002 * Copyright (C) 2017 IBM Corporation
Matt Spinler0c0eeff2017-02-28 10:06:56 -06003 *
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 */
Patrick Venturef78d9042018-11-01 15:39:53 -070016#include "cfam_access.hpp"
17
18#include "targeting.hpp"
19
20#include <unistd.h>
21
Matt Spinlera231ceb2017-10-04 11:26:09 -050022#include <phosphor-logging/elog-errors.hpp>
Patrick Venturef78d9042018-11-01 15:39:53 -070023#include <phosphor-logging/elog.hpp>
Matt Spinlera231ceb2017-10-04 11:26:09 -050024#include <xyz/openbmc_project/Common/Device/error.hpp>
25#include <xyz/openbmc_project/Common/File/error.hpp>
Matt Spinler0c0eeff2017-02-28 10:06:56 -060026
27namespace openpower
28{
29namespace cfam
30{
31namespace access
32{
33
34constexpr auto cfamRegSize = 4;
35
36using namespace openpower::targeting;
Matt Spinlerc3bffed2017-03-10 09:05:30 -060037using namespace openpower::util;
Patrick Venturef78d9042018-11-01 15:39:53 -070038namespace file_error = sdbusplus::xyz::openbmc_project::Common::File::Error;
39namespace device_error = sdbusplus::xyz::openbmc_project::Common::Device::Error;
Matt Spinler0c0eeff2017-02-28 10:06:56 -060040
41/**
42 * Converts the CFAM register address used by the calling
43 * code (because that's how it is in the spec) to the address
44 * required by the device driver.
45 */
46static inline cfam_address_t makeOffset(cfam_address_t address)
47{
48 return (address & 0xFC00) | ((address & 0x03FF) << 2);
49}
50
Patrick Venturef78d9042018-11-01 15:39:53 -070051void writeReg(const std::unique_ptr<Target>& target, cfam_address_t address,
Matt Spinler0c0eeff2017-02-28 10:06:56 -060052 cfam_data_t data)
53{
Dhruvaraj Subhashchandran18b07862017-04-26 07:13:35 -050054 using namespace phosphor::logging;
Matt Spinlerc3bffed2017-03-10 09:05:30 -060055 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060056 if (rc < 0)
57 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050058 log<level::ERR>("Failed seeking on a processor CFAM",
Patrick Venturef78d9042018-11-01 15:39:53 -070059 entry("CFAM_ADDRESS=0x%X", address));
Matt Spinlera231ceb2017-10-04 11:26:09 -050060
61 using metadata = xyz::openbmc_project::Common::File::Seek;
62
Patrick Venturef78d9042018-11-01 15:39:53 -070063 elog<file_error::Seek>(metadata::OFFSET(makeOffset(address)),
64 metadata::WHENCE(SEEK_SET),
65 metadata::ERRNO(errno),
66 metadata::PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -060067 }
68
Joel Stanleyafa1d222019-09-27 15:35:04 +093069 data = htobe32(data);
Edward A. James8316b772017-04-24 14:20:48 -050070
Matt Spinlerc3bffed2017-03-10 09:05:30 -060071 rc = write(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060072 if (rc < 0)
73 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050074 using metadata = xyz::openbmc_project::Common::Device::WriteFailure;
75
76 elog<device_error::WriteFailure>(
Patrick Venturef78d9042018-11-01 15:39:53 -070077 metadata::CALLOUT_ERRNO(errno),
78 metadata::CALLOUT_DEVICE_PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -060079 }
80}
81
Matt Spinler0c0eeff2017-02-28 10:06:56 -060082cfam_data_t readReg(const std::unique_ptr<Target>& target,
83 cfam_address_t address)
84{
Dhruvaraj Subhashchandran18b07862017-04-26 07:13:35 -050085 using namespace phosphor::logging;
86
Matt Spinler0c0eeff2017-02-28 10:06:56 -060087 cfam_data_t data = 0;
88
Matt Spinlerc3bffed2017-03-10 09:05:30 -060089 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060090 if (rc < 0)
91 {
Matt Spinlera231ceb2017-10-04 11:26:09 -050092 log<level::ERR>("Failed seeking on a processor CFAM",
Patrick Venturef78d9042018-11-01 15:39:53 -070093 entry("CFAM_ADDRESS=0x%X", address));
Matt Spinlera231ceb2017-10-04 11:26:09 -050094
95 using metadata = xyz::openbmc_project::Common::File::Seek;
96
Patrick Venturef78d9042018-11-01 15:39:53 -070097 elog<file_error::Seek>(metadata::OFFSET(makeOffset(address)),
98 metadata::WHENCE(SEEK_SET),
99 metadata::ERRNO(errno),
100 metadata::PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600101 }
102
Matt Spinlerc3bffed2017-03-10 09:05:30 -0600103 rc = read(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600104 if (rc < 0)
105 {
Matt Spinlera231ceb2017-10-04 11:26:09 -0500106 using metadata = xyz::openbmc_project::Common::Device::ReadFailure;
107
108 elog<device_error::ReadFailure>(
109 metadata::CALLOUT_ERRNO(errno),
110 metadata::CALLOUT_DEVICE_PATH(target->getCFAMPath().c_str()));
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600111 }
112
Joel Stanleyafa1d222019-09-27 15:35:04 +0930113 return be32toh(data);
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600114}
115
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600116void writeRegWithMask(const std::unique_ptr<Target>& target,
Patrick Venturef78d9042018-11-01 15:39:53 -0700117 cfam_address_t address, cfam_data_t data,
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600118 cfam_mask_t mask)
119{
120 cfam_data_t readData = readReg(target, address);
121
122 readData &= ~mask;
123 readData |= (data & mask);
124
125 writeReg(target, address, readData);
126}
127
Patrick Venturef78d9042018-11-01 15:39:53 -0700128} // namespace access
129} // namespace cfam
130} // namespace openpower