Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
273 theseven 1
//
2
//
3
//    Copyright 2010 TheSeven
4
//
5
//
427 farthen 6
//    This file is part of emCORE.
273 theseven 7
//
427 farthen 8
//    emCORE is free software: you can redistribute it and/or
273 theseven 9
//    modify it under the terms of the GNU General Public License as
10
//    published by the Free Software Foundation, either version 2 of the
11
//    License, or (at your option) any later version.
12
//
427 farthen 13
//    emCORE is distributed in the hope that it will be useful,
273 theseven 14
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
//    See the GNU General Public License for more details.
17
//
18
//    You should have received a copy of the GNU General Public License along
427 farthen 19
//    with emCORE.  If not, see <http://www.gnu.org/licenses/>.
273 theseven 20
//
21
//
22
 
23
 
24
#include "global.h"
25
#include "i2c.h"
26
#include "thread.h"
27
#include "s5l8702.h"
814 theseven 28
#include "clockgates.h"
273 theseven 29
 
30
 
31
static struct mutex i2cmutex;
32
 
33
 
560 theseven 34
static void i2c_on(int bus)
35
{
36
    /* enable I2C clock */
37
    clockgate_enable(CLOCKGATE_I2C(bus), true);
38
 
39
    IICCON(bus) = (1 << 7) | /* ACK_GEN */
40
                  (0 << 6) | /* CLKSEL = PCLK/16 */
41
                  (1 << 5) | /* INT_EN */
42
                  (1 << 4) | /* IRQ clear */
43
                  (7 << 0);  /* CK_REG */
44
 
45
    /* serial output on */
46
    IICSTAT(bus) = (1 << 4);
47
}
48
 
49
static void i2c_off(int bus)
50
{
51
    /* serial output off */
52
    IICSTAT(bus) = 0;
53
 
54
    /* disable I2C clock */
55
    clockgate_enable(CLOCKGATE_I2C(bus), false);
56
}
57
 
273 theseven 58
void i2c_init()
59
{
60
    mutex_init(&i2cmutex);
61
}
62
 
63
void i2c_send(uint32_t bus, uint32_t device, uint32_t address, const uint8_t* data, uint32_t length)
64
{
65
    mutex_lock(&i2cmutex, TIMEOUT_BLOCK);
560 theseven 66
	i2c_on(bus);
386 theseven 67
    while (IIC10(bus));
273 theseven 68
    IICDS(bus) = device & ~1;
386 theseven 69
    while (IIC10(bus));
273 theseven 70
    IICSTAT(bus) = 0xF0;
386 theseven 71
    while (IIC10(bus));
273 theseven 72
    IICCON(bus) = 0xB7;
877 theseven 73
    while (IIC10(bus));
273 theseven 74
    while ((IICCON(bus) & 0x10) == 0) yield();
75
    if (address >= 0)
76
    {
77
        /* write address */
386 theseven 78
        while (IIC10(bus));
273 theseven 79
        IICDS(bus) = address;
386 theseven 80
        while (IIC10(bus));
273 theseven 81
        IICCON(bus) = 0xB7;
877 theseven 82
        while (IIC10(bus));
273 theseven 83
        while ((IICCON(bus) & 0x10) == 0) yield();
84
    }
85
    /* write data */
86
    while (length--)
87
    {
386 theseven 88
        while (IIC10(bus));
273 theseven 89
        IICDS(bus) = *data++;
386 theseven 90
        while (IIC10(bus));
273 theseven 91
        IICCON(bus) = 0xB7;
877 theseven 92
        while (IIC10(bus));
273 theseven 93
        while ((IICCON(bus) & 0x10) == 0) yield();
94
    }
95
    /* STOP */
386 theseven 96
    while (IIC10(bus));
273 theseven 97
    IICSTAT(bus) = 0xD0;
386 theseven 98
    while (IIC10(bus));
273 theseven 99
    IICCON(bus) = 0xB7;
100
    while ((IICSTAT(bus) & (1 << 5)) != 0) yield();
560 theseven 101
	i2c_off(bus);
273 theseven 102
    mutex_unlock(&i2cmutex);
103
}
104
 
105
void i2c_recv(uint32_t bus, uint32_t device, uint32_t address, uint8_t* data, uint32_t length)
106
{
107
    mutex_lock(&i2cmutex, TIMEOUT_BLOCK);
560 theseven 108
	i2c_on(bus);
273 theseven 109
    if (address >= 0)
110
    {
111
        /* START */
386 theseven 112
        while (IIC10(bus));
273 theseven 113
        IICDS(bus) = device & ~1;
386 theseven 114
        while (IIC10(bus));
273 theseven 115
        IICSTAT(bus) = 0xF0;
386 theseven 116
        while (IIC10(bus));
273 theseven 117
        IICCON(bus) = 0xB7;
877 theseven 118
        while (IIC10(bus));
273 theseven 119
        while ((IICCON(bus) & 0x10) == 0) yield();
120
        /* write address */
386 theseven 121
        while (IIC10(bus));
273 theseven 122
        IICDS(bus) = address;
386 theseven 123
        while (IIC10(bus));
273 theseven 124
        IICCON(bus) = 0xB7;
877 theseven 125
        while (IIC10(bus));
273 theseven 126
        while ((IICCON(bus) & 0x10) == 0) yield();
127
    }
128
    /* (repeated) START */
386 theseven 129
    while (IIC10(bus));
273 theseven 130
    IICDS(bus) = device | 1;
386 theseven 131
    while (IIC10(bus));
273 theseven 132
    IICSTAT(bus) = 0xB0;
386 theseven 133
    while (IIC10(bus));
273 theseven 134
    IICCON(bus) = 0xB7;
877 theseven 135
    while (IIC10(bus));
273 theseven 136
    while ((IICCON(bus) & 0x10) == 0) yield();
137
    while (length--)
138
    {
386 theseven 139
        while (IIC10(bus));
273 theseven 140
        IICCON(bus) = (length == 0) ? 0x37 : 0xB7; /* NACK or ACK */
877 theseven 141
        while (IIC10(bus));
273 theseven 142
        while ((IICCON(bus) & 0x10) == 0) yield();
143
        *data++ = IICDS(bus);
144
    }
145
    /* STOP */
386 theseven 146
    while (IIC10(bus));
273 theseven 147
    IICSTAT(bus) = 0x90;
386 theseven 148
    while (IIC10(bus));
273 theseven 149
    IICCON(bus) = 0xB7;
877 theseven 150
    while (IIC10(bus));
273 theseven 151
    while ((IICSTAT(bus) & (1 << 5)) != 0) yield();
560 theseven 152
	i2c_off(bus);
273 theseven 153
    mutex_unlock(&i2cmutex);
154
}
155
 
156
void i2c_sendbyte(uint32_t bus, uint32_t device, uint32_t address, uint32_t data)
157
{
158
    uint8_t buf[1];
159
    buf[0] = data;
160
    i2c_send(bus, device, address, buf, 1);
161
}
162
 
163
uint8_t i2c_recvbyte(uint32_t bus, uint32_t device, uint32_t address)
164
{
165
    uint8_t buf[1];
166
    i2c_recv(bus, device, address, buf, 1);
167
    return buf[0];
168
}