Semi-decennial update. 50% code inflation.
[cbaos.git] / drivers / i2c / lpc_i2c.c
blobf982ecf8c32dbb3100eb4f82bab6c16b2d9fcecf
1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
2 #include <stdio.h>
3 #include <errno.h>
4 #include <types.h>
5 #include <sem.h>
6 #include <interrupt.h>
7 #include <compiler.h>
8 #include <drivers/i2c.h>
9 #include <drivers/lpc_i2c.h>
13 #define CON_AA (1<<2)
14 #define CON_SI (1<<3)
15 #define CON_STO (1<<4)
16 #define CON_STA (1<<5)
17 #define CON_I2EN (1<<6)
20 static void lpc_i2c_init(struct i2c_master *master)
22 struct lpc_i2c *i2c_data = master->priv;
23 struct lpc_i2c_regs *i2c = i2c_data->regs;
24 int speed = master->speed;
26 i2c->CONCLR = CON_AA | CON_SI | CON_STA | CON_I2EN;
27 speed = i2c_data->pclk/speed/2;
28 if (speed < 4)
29 speed = 4;
30 if (speed > 0xffff)
31 speed = 0xffff;
33 i2c->SCLH = speed;
34 i2c->SCLL = speed;
35 i2c->CONSET = CON_I2EN; /* slave disabled */
39 static void lpc_i2c_handler(struct i2c_master *master)
41 struct lpc_i2c *i2c_data = master->priv;
42 struct lpc_i2c_regs *i2c = i2c_data->regs;
44 irq_ack(i2c_data->irq);
45 i2c_state_machine(master, i2c->STAT);
46 i2c->CONCLR = CON_SI;
49 /* TODO find some nicer way to do this */
50 #ifdef MACH_LPC21XX
51 static struct i2c_irq_data {
52 struct i2c_master *master;
53 } i2c_irq_data[2];
55 void __interrupt i2c0_handler()
57 lpc_i2c_handler(i2c_irq_data[0].master);
60 void __interrupt i2c1_handler()
62 lpc_i2c_handler(i2c_irq_data[1].master);
64 #endif
65 #ifdef MACH_LPC13XX
66 static struct i2c_irq_data {
67 struct i2c_master *master;
68 } i2c_irq_data[1];
70 void __interrupt i2c_irqhandler()
72 lpc_i2c_handler(i2c_irq_data[0].master);
74 #endif
76 static void lpc_i2c_start(struct i2c_master *master)
78 struct lpc_i2c *i2c_data = master->priv;
79 struct lpc_i2c_regs *i2c = i2c_data->regs;
80 i2c->CONSET = CON_STA;
83 static void lpc_i2c_restart(struct i2c_master *master)
85 struct lpc_i2c *i2c_data = master->priv;
86 struct lpc_i2c_regs *i2c = i2c_data->regs;
87 i2c->CONSET = CON_STA; /* user must clear it */
90 static void lpc_i2c_stop(struct i2c_master *master)
92 struct lpc_i2c *i2c_data = master->priv;
93 struct lpc_i2c_regs *i2c = i2c_data->regs;
94 i2c->CONCLR = CON_AA; /* clear ack bit / slave enabled bit */
95 i2c->CONSET = CON_STO; /* auto cleared */
98 static void lpc_i2c_ack(struct i2c_master *master, int ack)
100 struct lpc_i2c *i2c_data = master->priv;
101 struct lpc_i2c_regs *i2c = i2c_data->regs;
102 if (ack)
103 i2c->CONSET = CON_AA; /* set ack bit for next received byte */
104 else
105 i2c->CONCLR = CON_AA; /* clear ack bit for next received byte */
108 static void lpc_i2c_write(struct i2c_master *master, u8 data)
110 struct lpc_i2c *i2c_data = master->priv;
111 struct lpc_i2c_regs *i2c = i2c_data->regs;
112 i2c->CONCLR = CON_STA; /* clear start bit */
113 i2c->DAT = data;
116 static u8 lpc_i2c_read(struct i2c_master *master)
118 struct lpc_i2c *i2c_data = master->priv;
119 struct lpc_i2c_regs *i2c = i2c_data->regs;
120 i2c->CONCLR = CON_STA; /* clear start bit */
121 return i2c->DAT;
125 int lpc_i2c_register(struct i2c_master *master)
127 struct lpc_i2c *i2c_data = master->priv;
128 struct lpc_i2c_regs *i2c = i2c_data->regs;
130 i2c->CONCLR = CON_AA | CON_SI | CON_STA | CON_I2EN;
132 i2c_irq_data[i2c_data->bus].master = master;
133 irq_enable(i2c_data->irq);
135 master->init = lpc_i2c_init;
136 master->start = lpc_i2c_start;
137 master->restart = lpc_i2c_restart;
138 master->stop = lpc_i2c_stop;
139 master->ack = lpc_i2c_ack;
140 master->read = lpc_i2c_read;
141 master->write = lpc_i2c_write;
143 return 0;