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;
73
    while ((IICCON(bus) & 0x10) == 0) yield();
74
    if (address >= 0)
75
    {
76
        /* write address */
386 theseven 77
        while (IIC10(bus));
273 theseven 78
        IICDS(bus) = address;
386 theseven 79
        while (IIC10(bus));
273 theseven 80
        IICCON(bus) = 0xB7;
81
        while ((IICCON(bus) & 0x10) == 0) yield();
82
    }
83
    /* write data */
84
    while (length--)
85
    {
386 theseven 86
        while (IIC10(bus));
273 theseven 87
        IICDS(bus) = *data++;
386 theseven 88
        while (IIC10(bus));
273 theseven 89
        IICCON(bus) = 0xB7;
90
        while ((IICCON(bus) & 0x10) == 0) yield();
91
    }
92
    /* STOP */
386 theseven 93
    while (IIC10(bus));
273 theseven 94
    IICSTAT(bus) = 0xD0;
386 theseven 95
    while (IIC10(bus));
273 theseven 96
    IICCON(bus) = 0xB7;
97
    while ((IICSTAT(bus) & (1 << 5)) != 0) yield();
560 theseven 98
	i2c_off(bus);
273 theseven 99
    mutex_unlock(&i2cmutex);
100
}
101
 
102
void i2c_recv(uint32_t bus, uint32_t device, uint32_t address, uint8_t* data, uint32_t length)
103
{
104
    mutex_lock(&i2cmutex, TIMEOUT_BLOCK);
560 theseven 105
	i2c_on(bus);
273 theseven 106
    if (address >= 0)
107
    {
108
        /* START */
386 theseven 109
        while (IIC10(bus));
273 theseven 110
        IICDS(bus) = device & ~1;
386 theseven 111
        while (IIC10(bus));
273 theseven 112
        IICSTAT(bus) = 0xF0;
386 theseven 113
        while (IIC10(bus));
273 theseven 114
        IICCON(bus) = 0xB7;
115
        while ((IICCON(bus) & 0x10) == 0) yield();
116
        /* write address */
386 theseven 117
        while (IIC10(bus));
273 theseven 118
        IICDS(bus) = address;
386 theseven 119
        while (IIC10(bus));
273 theseven 120
        IICCON(bus) = 0xB7;
121
        while ((IICCON(bus) & 0x10) == 0) yield();
122
    }
123
    /* (repeated) START */
386 theseven 124
    while (IIC10(bus));
273 theseven 125
    IICDS(bus) = device | 1;
386 theseven 126
    while (IIC10(bus));
273 theseven 127
    IICSTAT(bus) = 0xB0;
386 theseven 128
    while (IIC10(bus));
273 theseven 129
    IICCON(bus) = 0xB7;
130
    while ((IICCON(bus) & 0x10) == 0) yield();
131
    while (length--)
132
    {
386 theseven 133
        while (IIC10(bus));
273 theseven 134
        IICCON(bus) = (length == 0) ? 0x37 : 0xB7; /* NACK or ACK */
135
        while ((IICCON(bus) & 0x10) == 0) yield();
136
        *data++ = IICDS(bus);
137
    }
138
    /* STOP */
386 theseven 139
    while (IIC10(bus));
273 theseven 140
    IICSTAT(bus) = 0x90;
386 theseven 141
    while (IIC10(bus));
273 theseven 142
    IICCON(bus) = 0xB7;
143
    while ((IICSTAT(bus) & (1 << 5)) != 0) yield();
560 theseven 144
	i2c_off(bus);
273 theseven 145
    mutex_unlock(&i2cmutex);
146
}
147
 
148
void i2c_sendbyte(uint32_t bus, uint32_t device, uint32_t address, uint32_t data)
149
{
150
    uint8_t buf[1];
151
    buf[0] = data;
152
    i2c_send(bus, device, address, buf, 1);
153
}
154
 
155
uint8_t i2c_recvbyte(uint32_t bus, uint32_t device, uint32_t address)
156
{
157
    uint8_t buf[1];
158
    i2c_recv(bus, device, address, buf, 1);
159
    return buf[0];
160
}