* 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;
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 */
};
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);
}
*/
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;
}
{
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");
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;
}
/* 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);
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) {
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;
}
/* 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;
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;
}