67e1aab580808247950c05c397f38e64e5f35ef1
[mw/milkymist.git] / software / libhal / vin.c
1 /*
2  * Milkymist VJ SoC (Software)
3  * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, version 3 of the License.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <hw/bt656cap.h>
19
20 static int i2c_started;
21
22 static int i2c_init()
23 {
24         unsigned int timeout;
25
26         i2c_started = 0;
27         CSR_BT656CAP_I2C = BT656CAP_I2C_SDC;
28         /* Check the I2C bus is ready */
29         timeout = 1000;
30         while((timeout > 0) && (!(CSR_BT656CAP_I2C & BT656CAP_I2C_SDAIN))) timeout--;
31
32         return timeout;
33 }
34
35 static void i2c_delay()
36 {
37         unsigned int i;
38
39         for(i=0;i<1000;i++) __asm__("nop");
40 }
41
42 /* I2C bit-banging functions from http://en.wikipedia.org/wiki/I2c */
43 static unsigned int i2c_read_bit()
44 {
45         unsigned int bit;
46
47         /* Let the slave drive data */
48         CSR_BT656CAP_I2C = 0;
49         i2c_delay();
50         CSR_BT656CAP_I2C = BT656CAP_I2C_SDC;
51         i2c_delay();
52         bit = CSR_BT656CAP_I2C & BT656CAP_I2C_SDAIN;
53         i2c_delay();
54         CSR_BT656CAP_I2C = 0;
55         return bit;
56 }
57
58 static void i2c_write_bit(unsigned int bit)
59 {
60         if(bit) {
61                 CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE|BT656CAP_I2C_SDAOUT;
62         } else {
63                 CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE;
64         }
65         i2c_delay();
66         /* Clock stretching */
67         CSR_BT656CAP_I2C |= BT656CAP_I2C_SDC;
68         i2c_delay();
69         CSR_BT656CAP_I2C &= ~BT656CAP_I2C_SDC;
70 }
71
72 static void i2c_start_cond(void)
73 {
74         if(i2c_started) {
75                 /* set SDA to 1 */
76                 CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE|BT656CAP_I2C_SDAOUT;
77                 i2c_delay();
78                 CSR_BT656CAP_I2C |= BT656CAP_I2C_SDC;
79         }
80         /* SCL is high, set SDA from 1 to 0 */
81         CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE|BT656CAP_I2C_SDC;
82         i2c_delay();
83         CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE;
84         i2c_started = 1;
85 }
86
87 static void i2c_stop_cond(void)
88 {
89         /* set SDA to 0 */
90         CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE;
91         i2c_delay();
92         /* Clock stretching */
93         CSR_BT656CAP_I2C = BT656CAP_I2C_SDAOE|BT656CAP_I2C_SDC;
94         /* SCL is high, set SDA from 0 to 1 */
95         CSR_BT656CAP_I2C = BT656CAP_I2C_SDC;
96         i2c_delay();
97         i2c_started = 0;
98 }
99
100 static unsigned int i2c_write(unsigned char byte)
101 {
102         unsigned int bit;
103         unsigned int ack;
104
105         for(bit = 0; bit < 8; bit++) {
106                 i2c_write_bit(byte & 0x80);
107                 byte <<= 1;
108         }
109         ack = !i2c_read_bit();
110         return ack;
111 }
112
113 static unsigned char i2c_read(int ack)
114 {
115         unsigned char byte = 0;
116         unsigned int bit;
117
118         for(bit = 0; bit < 8; bit++) {
119                 byte <<= 1;
120                 byte |= i2c_read_bit();
121         }
122         i2c_write_bit(!ack);
123         return byte;
124 }
125
126 static const char vreg_addr[] = {
127         0x15, 0x17, 0x1D, 0x0F, 0x3A, 0x3D, 0x3F, 0x50, 0xC3, 0xC4, 0x0E, 0x50, 0x52, 0x58, 0x77, 0x7C, 0x7D, 0x90, 0x91, 0x92, 0x93, 0x94, 0xCF, 0xD0, 0xD6, 0xE5, 0xD5, 0xD7, 0xE4, 0xEA, 0xE9, 0x0E
128 };
129
130 static const char vreg_dat[] = {
131         0x00, 0x41, 0x40, 0x40, 0x16, 0xC3, 0xE4, 0x04, 0x05, 0x80, 0x80, 0x20, 0x18, 0xED, 0xC5, 0x93, 0x00, 0xC9, 0x40, 0x3C, 0xCA, 0xD5, 0x50, 0x4E, 0xDD, 0x51, 0xA0, 0xEA, 0x3E, 0x0F, 0x3E, 0x00
132 };
133
134 void vin_init()
135 {
136         int i;
137         
138         if(i2c_init())
139                 printf("VIN: I2C bus initialized\n");
140         else
141                 printf("VIN: I2C bus initialization problem\n");
142         for(i=0;i<sizeof(vreg_addr);i++)
143                 vin_write_reg(vreg_addr[i], vreg_dat[i]);
144 }
145
146 unsigned char vin_read_reg(unsigned char addr)
147 {
148         unsigned char r;
149
150         i2c_start_cond();
151         i2c_write(0x40);
152         i2c_write(addr);
153         i2c_start_cond();
154         i2c_write(0x41);
155         r = i2c_read(0);
156         i2c_stop_cond();
157
158         return r;
159 }
160
161 void vin_write_reg(unsigned char addr, unsigned char val)
162 {
163         unsigned char r;
164
165         i2c_start_cond();
166         i2c_write(0x40);
167         i2c_write(addr);
168         i2c_write(val);
169         i2c_stop_cond();
170 }