summaryrefslogtreecommitdiffstats
path: root/src/occ_gpe0/firdata/fsi.c
blob: 4bf105a6fd8090d32196b6d2ca23f1263bc5bc65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/occ/firdata/fsi.C $                                       */
/*                                                                        */
/* OpenPOWER OnChipController Project                                     */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015                             */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#include <fsi.h>
#include <scom_util.h>
#include <native.h>

#define OPB_REG_CMD   0x00020010
#define OPB_REG_STAT  0x00020011
#define OPB_REG_RES   0x00020014
#define OPB_STAT_BUSY  0x0001000000000000 /**< 15 is the Busy bit */
#define NS_PER_MSEC (1000000ull)


void fsi_recovery()
{
    int32_t rc = SUCCESS;

    /* Clear out OPB error */
    uint64_t scom_data = 0;
    scom_data = 0x8000000000000000; /*0=Unit Reset*/
    rc |= xscom_write( OPB_REG_RES,  scom_data );
    rc |= xscom_write( OPB_REG_STAT, scom_data );

    /* Check if we have any errors left */
    rc |= xscom_read( OPB_REG_STAT, &scom_data );

    TRACFCOMP( "PIB2OPB Status after cleanup = %08X%08X (rc=%d)",
               (uint32_t)(scom_data >> 32), (uint32_t)scom_data, rc );
}

/**
 * @brief  Poll for completion of a FSI operation, return data on read
 */
int32_t poll_for_complete( uint32_t * o_val )
{
    int32_t rc = SUCCESS;

    enum { MAX_OPB_TIMEOUT_NS = 10*NS_PER_MSEC }; /*=10ms */

    *o_val = 0;

    uint64_t read_data = 0;
    uint64_t elapsed_time_ns = 0;
    do
    {
        rc = xscom_read( OPB_REG_STAT, &read_data );
        if ( SUCCESS != rc )
        {
            fsi_recovery(); /* Try to recover the engine. */
            return rc;
        }

        /* Check for completion. Note: not checking for FSI errors. */
        if ( (read_data & OPB_STAT_BUSY) == 0 ) break; /* Not busy */

        sleep( 10000 ); /* sleep for 10,000 ns */
        elapsed_time_ns += 10000;

    } while ( elapsed_time_ns <= MAX_OPB_TIMEOUT_NS );

    if ( MAX_OPB_TIMEOUT_NS < elapsed_time_ns )
    {
        TRAC_ERR( "[poll_for_complete] FSI request timed out." );
        return FAIL;
    }

    *o_val = (uint32_t)read_data; /* Data in the bottom half. */

    return rc;
}

/**
 * @brief Read a FSI register
 */
int32_t getfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t * o_val )
{
    int32_t rc = SUCCESS;

    uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr;

    /* setup the OPB command register */
    /*  only supporting 4-byte access */
    uint64_t fsi_cmd = fsi_addr | 0x60000000; /* 011=Read Full Word */
    fsi_cmd <<= 32; /* Command is in the upper word of the scom */

    /* Write the OPB command register to trigger the read */
    rc = xscom_write( OPB_REG_CMD, fsi_cmd );
    if ( SUCCESS != rc )
    {
        fsi_recovery(); /* Try to recover the engine. */
        return rc;
    }

    /* Poll for complete and get the data back. */
    rc = poll_for_complete( o_val );

    return rc;
}

/**
 * @brief Write a FSI register
 */
int32_t putfsi( SCOM_Trgt_t i_trgt, uint32_t i_addr, uint32_t i_val )
{
    int32_t rc = SUCCESS;

    uint32_t fsi_addr = i_trgt.fsiBaseAddr | i_addr;

    /* setup the OPB command register */
    /*  only supporting 4-byte access */
    uint64_t fsi_cmd = fsi_addr | 0xE0000000; /* 111=Write Full Word */
    fsi_cmd <<= 32;   /* Command is in the upper word of the scom */
    fsi_cmd |= i_val; /* Data is in the bottom 32-bits */

    /* Write the OPB command register to trigger the read */
    rc = xscom_write( OPB_REG_CMD, fsi_cmd );
    if ( SUCCESS != rc )
    {
        fsi_recovery(); /* Try to recover the engine. */
        return rc;
    }

    /* Poll for complete */
    uint32_t junk = 0; // Not used.
    rc = poll_for_complete( &junk );

    return rc;
}

OpenPOWER on IntegriCloud