blob: 83afdc72a988cabe1569d0581bb197b94cea5d44 [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",
Matt Spinlerb6542342017-03-28 16:37:36 -050054 address, static_cast<int>(target->getPos()), errno);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060055 throw std::runtime_error(msg);
56 }
57
Edward A. James8316b772017-04-24 14:20:48 -050058 data = target->swapEndian(data);
59
Matt Spinlerc3bffed2017-03-10 09:05:30 -060060 rc = write(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060061 if (rc < 0)
62 {
63 //Future: use a different exception to create an error log
64 char msg[100];
65 sprintf(msg, "writeCFAMReg: Failed write to address 0x%X, "
66 "processor %d. errno = %d",
Matt Spinlerb6542342017-03-28 16:37:36 -050067 address, static_cast<int>(target->getPos()), errno);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060068 throw std::runtime_error(msg);
69 }
70}
71
72
73cfam_data_t readReg(const std::unique_ptr<Target>& target,
74 cfam_address_t address)
75{
Matt Spinler0c0eeff2017-02-28 10:06:56 -060076 cfam_data_t data = 0;
77
Matt Spinlerc3bffed2017-03-10 09:05:30 -060078 int rc = lseek(target->getCFAMFD(), makeOffset(address), SEEK_SET);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060079 if (rc < 0)
80 {
81 //Future: use a different exception to create an error log
82 char msg[100];
83 sprintf(msg, "readCFAMReg: Failed seek for address 0x%X, "
84 "processor %d. errno = %d",
Matt Spinlerb6542342017-03-28 16:37:36 -050085 address, static_cast<int>(target->getPos()), errno);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060086 throw std::runtime_error(msg);
87 }
88
Matt Spinlerc3bffed2017-03-10 09:05:30 -060089 rc = read(target->getCFAMFD(), &data, cfamRegSize);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060090 if (rc < 0)
91 {
92 //Future: use a different exception to create an error log
93 char msg[100];
94 sprintf(msg, "readCFAMReg: Failed read for address 0x%X, "
95 "processor %d. errno = %d",
Matt Spinlerb6542342017-03-28 16:37:36 -050096 address, static_cast<int>(target->getPos()), errno);
Matt Spinler0c0eeff2017-02-28 10:06:56 -060097 throw std::runtime_error(msg);
98 }
99
Edward A. James8316b772017-04-24 14:20:48 -0500100 return target->swapEndian(data);
Matt Spinler0c0eeff2017-02-28 10:06:56 -0600101}
102
103
104void writeRegWithMask(const std::unique_ptr<Target>& target,
105 cfam_address_t address,
106 cfam_data_t data,
107 cfam_mask_t mask)
108{
109 cfam_data_t readData = readReg(target, address);
110
111 readData &= ~mask;
112 readData |= (data & mask);
113
114 writeReg(target, address, readData);
115}
116
117}
118}
119}