summaryrefslogtreecommitdiff
path: root/board/MAI/AmigaOneG3SE/smbus.c
blob: 616005ea9398881bacaf4122f87b7d4bebc3f28c (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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "memio.h"
#include "articiaS.h"

#ifndef FALSE
#define FALSE 0
#endif

#ifndef TRUE
#define TRUE 1
#endif


void sm_write_mode(void)
{
    out_byte(0xA539, 0x00);
    out_byte(0xA53A, 0x03);
}

void sm_read_mode(void)
{
    out_byte(0xA53A, 0x02);
    out_byte(0xA539, 0x02);
}

void sm_write_byte(uint8 writeme)
{
    int i;
    int level;
    
    out_byte(0xA539, 0x00);

    level = 0;

    for (i=0; i<8; i++)
    {
	if ((writeme & 0x80) == (level<<7)) 
        {
	    /* Bit did not change, rewrite strobe */
	    out_byte(0xA539, level | 0x02);
	    out_byte(0xA539, level); 
	}
	else
	{
	    /* Bit changed, set bit, then strobe */
	    level = (writeme & 0x80) >> 7;
	    out_byte(0xA539, level);
	    out_byte(0xA539, level | 0x02);
	    out_byte(0xA539, level);
	}
	writeme <<= 1;
    }
    out_byte(0xA539, 0x00);
}

uint8 sm_read_byte(void)
{
    uint8 retme, r;
    int i;

    retme = 0;
    for (i=0; i<8; i++)
    {
	retme <<= 1;
	out_byte(0xA539, 0x00);
	out_byte(0xA539, 0x02);
	r = in_byte(0xA538) & 0x01;
	retme |= r;
    }

    return retme;
} 

int sm_get_ack(void)
{
    uint8 r;
    r = in_byte(0xA538);
    if ((r&0x01) == 0) return TRUE;
    else return FALSE;
}

void sm_write_ack(void)
{
    out_byte(0xA539, 0x00);
    out_byte(0xA539, 0x02);
    out_byte(0xA539, 0x00);
}

void sm_write_nack(void)
{
    out_byte(0xA539, 0x01);
    out_byte(0xA539, 0x03);
    out_byte(0xA539, 0x01);
}

void sm_send_start(void)
{
    out_byte(0xA539, 0x03);
    out_byte(0xA539, 0x02);
}

void sm_send_stop(void)
{
    out_byte(0xA539, 0x02);
    out_byte(0xA539, 0x03);
}

int sm_read_byte_from_device(uint8 addr, uint8 reg, uint8 *storage)
{
    // S Addr Wr
    sm_write_mode();
    sm_send_start();
    sm_write_byte((addr<<1));
    
    // [A]
    sm_read_mode();
    if (sm_get_ack() == FALSE) return FALSE;

    // Comm
    sm_write_mode();
    sm_write_byte(reg);
    
    // [A]
    sm_read_mode();
    if (sm_get_ack() == FALSE) return FALSE;

    // S Addr Rd
    sm_write_mode();
    sm_send_start();
    sm_write_byte((addr<<1)|1);
    
    // [A]
    sm_read_mode();
    if (sm_get_ack() == FALSE) return FALSE;

    // [Data]
    *storage = sm_read_byte();
    
    // NA
    sm_write_mode();
    sm_write_nack();
    sm_send_stop();

    return TRUE;
}

void sm_init(void)
{  
    /* Switch to PMC mode */
    pci_write_cfg_byte(0, 0, REG_GROUP, (uint8)(REG_GROUP_SPECIAL|REG_GROUP_POWER));
 
    /* Set GPIO Base */
    pci_write_cfg_long(0, 0, 0x40, 0xa500);

    /* Enable GPIO */
    pci_write_cfg_byte(0, 0, 0x44, 0x11);

    /* Set both GPIO 0 and 1 as output */
    out_byte(0xA53A, 0x03); 
}


void sm_term(void)
{  
    /* Switch to normal mode */
    pci_write_cfg_byte(0, 0, REG_GROUP, 0);
}


int sm_get_data(uint8 *DataArray, int dimm_socket)
{
    int j;

#if 0
    /* Switch to PMC mode */
    pci_write_cfg_byte(0, 0, REG_GROUP, (uint8)(REG_GROUP_SPECIAL|REG_GROUP_POWER));
 
    /* Set GPIO Base */
    pci_write_cfg_long(0, 0, 0x40, 0xa500);

    /* Enable GPIO */
    pci_write_cfg_byte(0, 0, 0x44, 0x11);

    /* Set both GPIO 0 and 1 as output */
    out_byte(0xA53A, 0x03); 
#endif

    sm_init();
    /* Start reading the rom */

    j = 0;

    do
    {
	if (sm_read_byte_from_device(dimm_socket, (uint8)j, DataArray) == FALSE)
	{
	    sm_term();
	    return FALSE;
	}

	DataArray++;
	j++;
    } while (j < 128);

    sm_term();
    return TRUE;
}