2 * arch/ppc/platforms/pmac_low_i2c.c
4 * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 * This file contains some low-level i2c access routines that
12 * need to be used by various bits of the PowerMac platform code
13 * at times where the real asynchronous & interrupt driven driver
14 * cannot be used. The API borrows some semantics from the darwin
15 * driver in order to ease the implementation of the platform
21 #include <linux/config.h>
22 #include <linux/types.h>
23 #include <linux/sched.h>
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/adb.h>
27 #include <linux/pmu.h>
28 #include <asm/keylargo.h>
29 #include <asm/uninorth.h>
32 #include <asm/machdep.h>
33 #include <asm/pmac_low_i2c.h>
35 #define MAX_LOW_I2C_HOST 4
38 #define DBG(x...) do {\
39 printk(KERN_DEBUG "KW:" x); \
47 typedef int (*low_i2c_func_t
)(struct low_i2c_host
*host
, u8 addr
, u8 sub
, u8
*data
, int len
);
51 struct device_node
*np
; /* OF device node */
52 struct semaphore mutex
; /* Access mutex for use by i2c-keywest */
53 low_i2c_func_t func
; /* Access function */
54 unsigned int is_open
: 1; /* Poor man's access control */
55 int mode
; /* Current mode */
56 int channel
; /* Current channel */
57 int num_channels
; /* Number of channels */
58 void __iomem
*base
; /* For keywest-i2c, base address */
59 int bsteps
; /* And register stepping */
60 int speed
; /* And speed */
63 static struct low_i2c_host low_i2c_hosts
[MAX_LOW_I2C_HOST
];
65 /* No locking is necessary on allocation, we are running way before
66 * anything can race with us
68 static struct low_i2c_host
*find_low_i2c_host(struct device_node
*np
)
72 for (i
= 0; i
< MAX_LOW_I2C_HOST
; i
++)
73 if (low_i2c_hosts
[i
].np
== np
)
74 return &low_i2c_hosts
[i
];
80 * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's)
85 * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h,
86 * should be moved somewhere in include/asm-ppc/
88 /* Register indices */
102 #define KW_I2C_MODE_100KHZ 0x00
103 #define KW_I2C_MODE_50KHZ 0x01
104 #define KW_I2C_MODE_25KHZ 0x02
105 #define KW_I2C_MODE_DUMB 0x00
106 #define KW_I2C_MODE_STANDARD 0x04
107 #define KW_I2C_MODE_STANDARDSUB 0x08
108 #define KW_I2C_MODE_COMBINED 0x0C
109 #define KW_I2C_MODE_MODE_MASK 0x0C
110 #define KW_I2C_MODE_CHAN_MASK 0xF0
112 /* Control register */
113 #define KW_I2C_CTL_AAK 0x01
114 #define KW_I2C_CTL_XADDR 0x02
115 #define KW_I2C_CTL_STOP 0x04
116 #define KW_I2C_CTL_START 0x08
118 /* Status register */
119 #define KW_I2C_STAT_BUSY 0x01
120 #define KW_I2C_STAT_LAST_AAK 0x02
121 #define KW_I2C_STAT_LAST_RW 0x04
122 #define KW_I2C_STAT_SDA 0x08
123 #define KW_I2C_STAT_SCL 0x10
125 /* IER & ISR registers */
126 #define KW_I2C_IRQ_DATA 0x01
127 #define KW_I2C_IRQ_ADDR 0x02
128 #define KW_I2C_IRQ_STOP 0x04
129 #define KW_I2C_IRQ_START 0x08
130 #define KW_I2C_IRQ_MASK 0x0F
132 /* State machine states */
142 #define WRONG_STATE(name) do {\
143 printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \
144 name, __kw_state_names[state], isr); \
147 static const char *__kw_state_names
[] = {
156 static inline u8
__kw_read_reg(struct low_i2c_host
*host
, reg_t reg
)
158 return readb(host
->base
+ (((unsigned int)reg
) << host
->bsteps
));
161 static inline void __kw_write_reg(struct low_i2c_host
*host
, reg_t reg
, u8 val
)
163 writeb(val
, host
->base
+ (((unsigned)reg
) << host
->bsteps
));
164 (void)__kw_read_reg(host
, reg_subaddr
);
167 #define kw_write_reg(reg, val) __kw_write_reg(host, reg, val)
168 #define kw_read_reg(reg) __kw_read_reg(host, reg)
171 /* Don't schedule, the g5 fan controller is too
174 static u8
kw_wait_interrupt(struct low_i2c_host
* host
)
179 for (i
= 0; i
< 100000; i
++) {
180 isr
= kw_read_reg(reg_isr
) & KW_I2C_IRQ_MASK
;
184 /* This code is used with the timebase frozen, we cannot rely
185 * on udelay ! For now, just use a bogus loop
187 for (j
= 1; j
< 10000; j
++)
193 static int kw_handle_interrupt(struct low_i2c_host
*host
, int state
, int rw
, int *rc
, u8
**data
, int *len
, u8 isr
)
197 DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names
[state
], isr
);
200 if (state
!= state_stop
) {
201 DBG("KW: Timeout !\n");
205 if (state
== state_stop
) {
206 ack
= kw_read_reg(reg_status
);
207 if (!(ack
& KW_I2C_STAT_BUSY
)) {
209 kw_write_reg(reg_ier
, 0x00);
215 if (isr
& KW_I2C_IRQ_ADDR
) {
216 ack
= kw_read_reg(reg_status
);
217 if (state
!= state_addr
) {
218 kw_write_reg(reg_isr
, KW_I2C_IRQ_ADDR
);
219 WRONG_STATE("KW_I2C_IRQ_ADDR");
223 if ((ack
& KW_I2C_STAT_LAST_AAK
) == 0) {
225 DBG("KW: NAK on address\n");
231 kw_write_reg(reg_control
, KW_I2C_CTL_AAK
);
234 kw_write_reg(reg_data
, **data
);
238 kw_write_reg(reg_isr
, KW_I2C_IRQ_ADDR
);
241 if (isr
& KW_I2C_IRQ_DATA
) {
242 if (state
== state_read
) {
243 **data
= kw_read_reg(reg_data
);
245 kw_write_reg(reg_isr
, KW_I2C_IRQ_DATA
);
248 else if ((*len
) == 1)
249 kw_write_reg(reg_control
, 0);
250 } else if (state
== state_write
) {
251 ack
= kw_read_reg(reg_status
);
252 if ((ack
& KW_I2C_STAT_LAST_AAK
) == 0) {
253 DBG("KW: nack on data write\n");
257 kw_write_reg(reg_data
, **data
);
260 kw_write_reg(reg_control
, KW_I2C_CTL_STOP
);
264 kw_write_reg(reg_isr
, KW_I2C_IRQ_DATA
);
266 kw_write_reg(reg_isr
, KW_I2C_IRQ_DATA
);
267 WRONG_STATE("KW_I2C_IRQ_DATA");
268 if (state
!= state_stop
) {
275 if (isr
& KW_I2C_IRQ_STOP
) {
276 kw_write_reg(reg_isr
, KW_I2C_IRQ_STOP
);
277 if (state
!= state_stop
) {
278 WRONG_STATE("KW_I2C_IRQ_STOP");
284 if (isr
& KW_I2C_IRQ_START
)
285 kw_write_reg(reg_isr
, KW_I2C_IRQ_START
);
290 kw_write_reg(reg_control
, KW_I2C_CTL_STOP
);
294 static int keywest_low_i2c_func(struct low_i2c_host
*host
, u8 addr
, u8 subaddr
, u8
*data
, int len
)
296 u8 mode_reg
= host
->speed
;
297 int state
= state_addr
;
300 /* Setup mode & subaddress if any */
302 case pmac_low_i2c_mode_dumb
:
303 printk(KERN_ERR
"low_i2c: Dumb mode not supported !\n");
305 case pmac_low_i2c_mode_std
:
306 mode_reg
|= KW_I2C_MODE_STANDARD
;
308 case pmac_low_i2c_mode_stdsub
:
309 mode_reg
|= KW_I2C_MODE_STANDARDSUB
;
311 case pmac_low_i2c_mode_combined
:
312 mode_reg
|= KW_I2C_MODE_COMBINED
;
316 /* Setup channel & clear pending irqs */
317 kw_write_reg(reg_isr
, kw_read_reg(reg_isr
));
318 kw_write_reg(reg_mode
, mode_reg
| (host
->channel
<< 4));
319 kw_write_reg(reg_status
, 0);
321 /* Set up address and r/w bit */
322 kw_write_reg(reg_addr
, addr
);
324 /* Set up the sub address */
325 if ((mode_reg
& KW_I2C_MODE_MODE_MASK
) == KW_I2C_MODE_STANDARDSUB
326 || (mode_reg
& KW_I2C_MODE_MODE_MASK
) == KW_I2C_MODE_COMBINED
)
327 kw_write_reg(reg_subaddr
, subaddr
);
329 /* Start sending address & disable interrupt*/
330 kw_write_reg(reg_ier
, 0 /*KW_I2C_IRQ_MASK*/);
331 kw_write_reg(reg_control
, KW_I2C_CTL_XADDR
);
333 /* State machine, to turn into an interrupt handler */
334 while(state
!= state_idle
) {
335 u8 isr
= kw_wait_interrupt(host
);
336 state
= kw_handle_interrupt(host
, state
, addr
& 1, &rc
, &data
, &len
, isr
);
342 static void keywest_low_i2c_add(struct device_node
*np
)
344 struct low_i2c_host
*host
= find_low_i2c_host(NULL
);
345 u32
*psteps
, *prate
, steps
, aoffset
= 0;
346 struct device_node
*parent
;
349 printk(KERN_ERR
"low_i2c: Can't allocate host for %s\n",
353 memset(host
, 0, sizeof(*host
));
355 init_MUTEX(&host
->mutex
);
356 host
->np
= of_node_get(np
);
357 psteps
= (u32
*)get_property(np
, "AAPL,address-step", NULL
);
358 steps
= psteps
? (*psteps
) : 0x10;
359 for (host
->bsteps
= 0; (steps
& 0x01) == 0; host
->bsteps
++)
361 parent
= of_get_parent(np
);
362 host
->num_channels
= 1;
363 if (parent
&& parent
->name
[0] == 'u') {
364 host
->num_channels
= 2;
367 /* Select interface rate */
368 host
->speed
= KW_I2C_MODE_100KHZ
;
369 prate
= (u32
*)get_property(np
, "AAPL,i2c-rate", NULL
);
370 if (prate
) switch(*prate
) {
372 host
->speed
= KW_I2C_MODE_100KHZ
;
375 host
->speed
= KW_I2C_MODE_50KHZ
;
378 host
->speed
= KW_I2C_MODE_25KHZ
;
382 host
->mode
= pmac_low_i2c_mode_std
;
383 host
->base
= ioremap(np
->addrs
[0].address
+ aoffset
,
385 host
->func
= keywest_low_i2c_func
;
395 #ifdef CONFIG_ADB_PMU
397 static int pmu_low_i2c_func(struct low_i2c_host
*host
, u8 addr
, u8 sub
, u8
*data
, int len
)
403 static void pmu_low_i2c_add(struct device_node
*np
)
405 struct low_i2c_host
*host
= find_low_i2c_host(NULL
);
408 printk(KERN_ERR
"low_i2c: Can't allocate host for %s\n",
412 memset(host
, 0, sizeof(*host
));
414 init_MUTEX(&host
->mutex
);
415 host
->np
= of_node_get(np
);
416 host
->num_channels
= 3;
417 host
->mode
= pmac_low_i2c_mode_std
;
418 host
->func
= pmu_low_i2c_func
;
421 #endif /* CONFIG_ADB_PMU */
423 void __init
pmac_init_low_i2c(void)
425 struct device_node
*np
;
427 /* Probe keywest-i2c busses */
428 np
= of_find_compatible_node(NULL
, "i2c", "keywest-i2c");
430 keywest_low_i2c_add(np
);
431 np
= of_find_compatible_node(np
, "i2c", "keywest-i2c");
434 #ifdef CONFIG_ADB_PMU
435 /* Probe PMU busses */
436 np
= of_find_node_by_name(NULL
, "via-pmu");
439 #endif /* CONFIG_ADB_PMU */
441 /* TODO: Add CUDA support as well */
444 int pmac_low_i2c_lock(struct device_node
*np
)
446 struct low_i2c_host
*host
= find_low_i2c_host(np
);
453 EXPORT_SYMBOL(pmac_low_i2c_lock
);
455 int pmac_low_i2c_unlock(struct device_node
*np
)
457 struct low_i2c_host
*host
= find_low_i2c_host(np
);
464 EXPORT_SYMBOL(pmac_low_i2c_unlock
);
467 int pmac_low_i2c_open(struct device_node
*np
, int channel
)
469 struct low_i2c_host
*host
= find_low_i2c_host(np
);
474 if (channel
>= host
->num_channels
)
479 host
->channel
= channel
;
483 EXPORT_SYMBOL(pmac_low_i2c_open
);
485 int pmac_low_i2c_close(struct device_node
*np
)
487 struct low_i2c_host
*host
= find_low_i2c_host(np
);
497 EXPORT_SYMBOL(pmac_low_i2c_close
);
499 int pmac_low_i2c_setmode(struct device_node
*np
, int mode
)
501 struct low_i2c_host
*host
= find_low_i2c_host(np
);
505 WARN_ON(!host
->is_open
);
510 EXPORT_SYMBOL(pmac_low_i2c_setmode
);
512 int pmac_low_i2c_xfer(struct device_node
*np
, u8 addrdir
, u8 subaddr
, u8
*data
, int len
)
514 struct low_i2c_host
*host
= find_low_i2c_host(np
);
518 WARN_ON(!host
->is_open
);
520 return host
->func(host
, addrdir
, subaddr
, data
, len
);
522 EXPORT_SYMBOL(pmac_low_i2c_xfer
);