blob: 888eefcadb842de9beefebd8ddaa3136c8c1e785 [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 */
16#include <unistd.h>
Matt Spinler0c0eeff2017-02-28 10:06:56 -060017#include "cfam_access.hpp"
18#include "targeting.hpp"
19
20namespace openpower
21{
22namespace cfam
23{
24namespace access
25{
26
27constexpr auto cfamRegSize = 4;
28
29using namespace openpower::targeting;
Matt Spinlerc3bffed2017-03-10 09:05:30 -060030using namespace openpower::util;
Matt Spinler0c0eeff2017-02-28 10:06:56 -060031
32/**
33 * Converts the CFAM register address used by the calling
34 * code (because that's how it is in the spec) to the address
35 * required by the device driver.
36 */
37static inline cfam_address_t makeOffset(cfam_address_t address)
38{
39 return (address & 0xFC00) | ((address & 0x03FF) << 2);
40}
41
42
43void writeReg(const std::unique_ptr<Target>& target,
44 cfam_address_t address,
45 cfam_data_t data)
46{
Matt Spinlerc3bffed2017-03-10 09:05:30 -060047 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060048 if (rc < 0)
49 {
50 //Future: use a different exception to create an error log
51 char msg[100];
52 sprintf(msg, "writeCFAMReg: Failed seek for address 0x%X, "
53 "processor %d. errno = %d",
54 address, target->getPos(), errno);
55 throw std::runtime_error(msg);
56 }
57
Matt Spinlerc3bffed2017-03-10 09:05:30 -060058 rc = write(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060059 if (rc < 0)
60 {
61 //Future: use a different exception to create an error log
62 char msg[100];
63 sprintf(msg, "writeCFAMReg: Failed write to address 0x%X, "
64 "processor %d. errno = %d",
65 address, target->getPos(), errno);
66 throw std::runtime_error(msg);
67 }
68}
69
70
71cfam_data_t readReg(const std::unique_ptr<Target>& target,
72 cfam_address_t address)
73{
Matt Spinler0c0eeff2017-02-28 10:06:56 -060074 cfam_data_t data = 0;
75
Matt Spinlerc3bffed2017-03-10 09:05:30 -060076 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060077 if (rc < 0)
78 {
79 //Future: use a different exception to create an error log
80 char msg[100];
81 sprintf(msg, "readCFAMReg: Failed seek for address 0x%X, "
82 "processor %d. errno = %d",
83 address, target->getPos(), errno);
84 throw std::runtime_error(msg);
85 }
86
Matt Spinlerc3bffed2017-03-10 09:05:30 -060087 rc = read(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060088 if (rc < 0)
89 {
90 //Future: use a different exception to create an error log
91 char msg[100];
92 sprintf(msg, "readCFAMReg: Failed read for address 0x%X, "
93 "processor %d. errno = %d",
94 address, target->getPos(), errno);
95 throw std::runtime_error(msg);
96 }
97
98 return data;
99}
100
101
102void writeRegWithMask(const std::unique_ptr<Target>& target,
103 cfam_address_t address,
104 cfam_data_t data,
105 cfam_mask_t mask)
106{
107 cfam_data_t readData = readReg(target, address);
108
109 readData &= ~mask;
110 readData |= (data & mask);
111
112 writeReg(target, address, readData);
113}
114
115}
116}
117}