summaryrefslogtreecommitdiff
path: root/firmware/drivers/i2c-pp5020.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/i2c-pp5020.c')
-rw-r--r--firmware/drivers/i2c-pp5020.c80
1 files changed, 52 insertions, 28 deletions
diff --git a/firmware/drivers/i2c-pp5020.c b/firmware/drivers/i2c-pp5020.c
index 522ddbed77..77671e79d8 100644
--- a/firmware/drivers/i2c-pp5020.c
+++ b/firmware/drivers/i2c-pp5020.c
@@ -57,42 +57,48 @@ static int ipod_i2c_wait_not_busy(void)
57 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) { 57 if (!(inb(IPOD_I2C_STATUS) & IPOD_I2C_BUSY)) {
58 return 0; 58 return 0;
59 } 59 }
60 yield();
60 } 61 }
61 62
62 return -1; 63 return -1;
63} 64}
64 65
65 66
66/* Public functions */ 67static int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
67
68int ipod_i2c_read_byte(unsigned int addr, unsigned int *data)
69{ 68{
70 if (ipod_i2c_wait_not_busy() < 0) 69 if (ipod_i2c_wait_not_busy() < 0)
71 { 70 {
72 return -1; 71 return -1;
73 } 72 }
74 73
75 /* clear top 15 bits, left shift 1, or in 0x1 for a read */ 74 {
76 outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR); 75 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
77 76
78 outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL); 77 /* clear top 15 bits, left shift 1, or in 0x1 for a read */
78 outb(((addr << 17) >> 16) | 0x1, IPOD_I2C_ADDR);
79 79
80 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 80 outb(inb(IPOD_I2C_CTRL) | 0x20, IPOD_I2C_CTRL);
81 81
82 if (ipod_i2c_wait_not_busy() < 0) 82 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
83 {
84 return -1;
85 }
86 83
87 if (data) 84 set_irq_level(old_irq_level);
88 { 85
89 *data = inb(IPOD_I2C_DATA0); 86 if (data)
87 {
88 if (ipod_i2c_wait_not_busy() < 0)
89 {
90 return -1;
91 }
92 old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
93 *data = inb(IPOD_I2C_DATA0);
94 set_irq_level(old_irq_level);
95 }
90 } 96 }
91 97
92 return 0; 98 return 0;
93} 99}
94 100
95int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data) 101static int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data)
96{ 102{
97 int data_addr; 103 int data_addr;
98 unsigned int i; 104 unsigned int i;
@@ -107,26 +113,32 @@ int ipod_i2c_send_bytes(unsigned int addr, unsigned int len, unsigned char *data
107 return -2; 113 return -2;
108 } 114 }
109 115
110 /* clear top 15 bits, left shift 1 */ 116 {
111 outb((addr << 17) >> 16, IPOD_I2C_ADDR); 117 int old_irq_level = set_irq_level(HIGHEST_IRQ_LEVEL);
112 118
113 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL); 119 /* clear top 15 bits, left shift 1 */
120 outb((addr << 17) >> 16, IPOD_I2C_ADDR);
114 121
115 data_addr = IPOD_I2C_DATA0; 122 outb(inb(IPOD_I2C_CTRL) & ~0x20, IPOD_I2C_CTRL);
116 for ( i = 0; i < len; i++ ) 123
117 { 124 data_addr = IPOD_I2C_DATA0;
118 outb(*data++, data_addr); 125 for ( i = 0; i < len; i++ )
119 data_addr += 4; 126 {
120 } 127 outb(*data++, data_addr);
128 data_addr += 4;
129 }
121 130
122 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL); 131 outb((inb(IPOD_I2C_CTRL) & ~0x26) | ((len-1) << 1), IPOD_I2C_CTRL);
123 132
124 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL); 133 outb(inb(IPOD_I2C_CTRL) | IPOD_I2C_SEND, IPOD_I2C_CTRL);
134
135 set_irq_level(old_irq_level);
136 }
125 137
126 return 0x0; 138 return 0x0;
127} 139}
128 140
129int ipod_i2c_send_byte(unsigned int addr, int data0) 141static int ipod_i2c_send_byte(unsigned int addr, int data0)
130{ 142{
131 unsigned char data[1]; 143 unsigned char data[1];
132 144
@@ -135,25 +147,35 @@ int ipod_i2c_send_byte(unsigned int addr, int data0)
135 return ipod_i2c_send_bytes(addr, 1, data); 147 return ipod_i2c_send_bytes(addr, 1, data);
136} 148}
137 149
150/* Public functions */
151static struct mutex i2c_mutex;
138 152
139int i2c_readbyte(unsigned int dev_addr, int addr) 153int i2c_readbyte(unsigned int dev_addr, int addr)
140{ 154{
155 int retval;
141 int data; 156 int data;
142 157
158 mutex_lock(&i2c_mutex);
143 ipod_i2c_send_byte(dev_addr, addr); 159 ipod_i2c_send_byte(dev_addr, addr);
144 ipod_i2c_read_byte(dev_addr, &data); 160 ipod_i2c_read_byte(dev_addr, &data);
161 mutex_unlock(&i2c_mutex);
145 162
146 return data; 163 return data;
147} 164}
148 165
149int ipod_i2c_send(unsigned int addr, int data0, int data1) 166int ipod_i2c_send(unsigned int addr, int data0, int data1)
150{ 167{
168 int retval;
151 unsigned char data[2]; 169 unsigned char data[2];
152 170
153 data[0] = data0; 171 data[0] = data0;
154 data[1] = data1; 172 data[1] = data1;
155 173
156 return ipod_i2c_send_bytes(addr, 2, data); 174 mutex_lock(&i2c_mutex);
175 retval = ipod_i2c_send_bytes(addr, 2, data);
176 mutex_unlock(&i2c_mutex);
177
178 return retval;
157} 179}
158 180
159void i2c_init(void) 181void i2c_init(void)
@@ -175,5 +197,7 @@ void i2c_init(void)
175 outl(0x0, 0x600060a4); 197 outl(0x0, 0x600060a4);
176 outl(0x80 | (0 << 8), 0x600060a4); 198 outl(0x80 | (0 << 8), 0x600060a4);
177 199
200 mutex_init(&i2c_mutex);
201
178 i2c_readbyte(0x8, 0); 202 i2c_readbyte(0x8, 0);
179} 203}