vserver 1.9.5.x5
[linux-2.6.git] / arch / ppc64 / kernel / pmac_low_i2c.c
index 52da757..f3f39e8 100644 (file)
  *  properties parser
  */
 
+#undef DEBUG
+
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/module.h>
 
 #define MAX_LOW_I2C_HOST       4
 
-#if 1
+#ifdef DEBUG
 #define DBG(x...) do {\
                printk(KERN_DEBUG "KW:" x);     \
        } while(0)
 #else
-#define DBGG(x...)
+#define DBG(x...)
 #endif
 
 struct low_i2c_host;
@@ -50,11 +51,11 @@ struct low_i2c_host
        struct device_node      *np;            /* OF device node */
        struct semaphore        mutex;          /* Access mutex for use by i2c-keywest */
        low_i2c_func_t          func;           /* Access function */
-       unsigned                is_open : 1;    /* Poor man's access control */
+       unsigned int            is_open : 1;    /* Poor man's access control */
        int                     mode;           /* Current mode */
        int                     channel;        /* Current channel */
        int                     num_channels;   /* Number of channels */
-       unsigned long           base;           /* For keywest-i2c, base address */
+       void __iomem            *base;          /* For keywest-i2c, base address */
        int                     bsteps;         /* And register stepping */
        int                     speed;          /* And speed */
 };
@@ -154,14 +155,12 @@ static const char *__kw_state_names[] = {
 
 static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg)
 {
-       return in_8(((volatile u8 *)host->base)
-               + (((unsigned)reg) << host->bsteps));
+       return readb(host->base + (((unsigned int)reg) << host->bsteps));
 }
 
 static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
 {
-       out_8(((volatile u8 *)host->base)
-               + (((unsigned)reg) << host->bsteps), val);
+       writeb(val, host->base + (((unsigned)reg) << host->bsteps));
        (void)__kw_read_reg(host, reg_subaddr);
 }
 
@@ -174,14 +173,19 @@ static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val)
  */
 static u8 kw_wait_interrupt(struct low_i2c_host* host)
 {
-       int i;
+       int i, j;
        u8 isr;
        
-       for (i = 0; i < 200000; i++) {
+       for (i = 0; i < 100000; i++) {
                isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK;
                if (isr != 0)
                        return isr;
-               udelay(1);
+
+               /* This code is used with the timebase frozen, we cannot rely
+                * on udelay ! For now, just use a bogus loop
+                */
+               for (j = 1; j < 10000; j++)
+                       mb();
        }
        return isr;
 }
@@ -190,6 +194,8 @@ static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int
 {
        u8 ack;
 
+       DBG("kw_handle_interrupt(%s, isr: %x)\n", __kw_state_names[state], isr);
+
        if (isr == 0) {
                if (state != state_stop) {
                        DBG("KW: Timeout !\n");
@@ -301,11 +307,9 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr,
                break;
        case pmac_low_i2c_mode_stdsub:
                mode_reg |= KW_I2C_MODE_STANDARDSUB;
-               kw_write_reg(reg_subaddr, subaddr);
                break;
        case pmac_low_i2c_mode_combined:
                mode_reg |= KW_I2C_MODE_COMBINED;
-               kw_write_reg(reg_subaddr, subaddr);
                break;
        }
 
@@ -317,6 +321,11 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr,
        /* Set up address and r/w bit */
        kw_write_reg(reg_addr, addr);
 
+       /* Set up the sub address */
+       if ((mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_STANDARDSUB
+           || (mode_reg & KW_I2C_MODE_MODE_MASK) == KW_I2C_MODE_COMBINED)
+               kw_write_reg(reg_subaddr, subaddr);
+
        /* Start sending address & disable interrupt*/
        kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/);
        kw_write_reg(reg_control, KW_I2C_CTL_XADDR);
@@ -333,7 +342,7 @@ static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr,
 static void keywest_low_i2c_add(struct device_node *np)
 {
        struct low_i2c_host     *host = find_low_i2c_host(NULL);
-       unsigned long           *psteps, *prate, steps, aoffset = 0;
+       u32                     *psteps, *prate, steps, aoffset = 0;
        struct device_node      *parent;
 
        if (host == NULL) {
@@ -345,7 +354,7 @@ static void keywest_low_i2c_add(struct device_node *np)
 
        init_MUTEX(&host->mutex);
        host->np = of_node_get(np);     
-       psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL);
+       psteps = (u32 *)get_property(np, "AAPL,address-step", NULL);
        steps = psteps ? (*psteps) : 0x10;
        for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++)
                steps >>= 1;
@@ -357,7 +366,7 @@ static void keywest_low_i2c_add(struct device_node *np)
        }
        /* Select interface rate */
        host->speed = KW_I2C_MODE_100KHZ;
-       prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL);
+       prate = (u32 *)get_property(np, "AAPL,i2c-rate", NULL);
        if (prate) switch(*prate) {
        case 100:
                host->speed = KW_I2C_MODE_100KHZ;
@@ -369,8 +378,9 @@ static void keywest_low_i2c_add(struct device_node *np)
                host->speed = KW_I2C_MODE_25KHZ;
                break;
        }       
+
        host->mode = pmac_low_i2c_mode_std;
-       host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset,
+       host->base = ioremap(np->addrs[0].address + aoffset,
                                                np->addrs[0].size);
        host->func = keywest_low_i2c_func;
 }