/*
* i2c_adap_pxa.c
*
* I2C adapter for the PXA I2C bus access.
*
* Copyright (C) 2002 Intrinsyc Software Inc.
* Copyright (C) 2004-2005 Deep Blue Solutions Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* History:
* Apr 2002: Initial version [CS]
* Jun 2002: Properly seperated algo/adap [FB]
* Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem]
* Jan 2003: added limited signal handling [Kai-Uwe Bloem]
* Sep 2004: Major rework to ensure efficient bus handling [RMK]
* Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood]
* Feb 2005: Rework slave mode handling [RMK]
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/init.h>
#include <linux/time.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/i2c-pxa.h>
#include <linux/platform_device.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/arch/i2c.h>
#include <asm/arch/pxa-regs.h>
struct pxa_i2c {
spinlock_t lock;
wait_queue_head_t wait;
struct i2c_msg *msg;
unsigned int msg_num;
unsigned int msg_idx;
unsigned int msg_ptr;
unsigned int slave_addr;
struct i2c_adapter adap;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_slave_client *slave;
#endif
unsigned int irqlogidx;
u32 isrlog[32];
u32 icrlog[32];
};
/*
* I2C Slave mode address
*/
#define I2C_PXA_SLAVE_ADDR 0x1
#ifdef DEBUG
struct bits {
u32 mask;
const char *set;
const char *unset;
};
#define BIT(m, s, u) { .mask = m, .set = s, .unset = u }
static inline void
decode_bits(const char *prefix, const struct bits *bits, int num, u32 val)
{
printk("%s %08x: ", prefix, val);
while (num--) {
const char *str = val & bits->mask ? bits->set : bits->unset;
if (str)
printk("%s ", str);
bits++;
}
}
static const struct bits isr_bits[] = {
BIT(ISR_RWM, "RX", "TX"),
BIT(ISR_ACKNAK, "NAK", "ACK"),
BIT(ISR_UB, "Bsy", "Rdy"),
BIT(ISR_IBB, "BusBsy", "BusRdy"),
BIT(ISR_SSD, "SlaveStop", NULL),
BIT(ISR_ALD, "ALD", NULL),
BIT(ISR_ITE, "TxEmpty", NULL),
BIT(ISR_IRF, "RxFull", NULL),
BIT(ISR_GCAD, "GenCall", NULL),
BIT(ISR_SAD, "SlaveAddr", NULL),
BIT(ISR_BED, "BusErr", NULL),
};
static void decode_ISR(unsigned int val)
{
decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val);
printk("\n");
}
static const struct bits icr_bits[] = {
BIT(ICR_START, "START", NULL),
BIT(ICR_STOP, "STOP", NULL),
BIT(ICR_ACKNAK, "ACKNAK", NULL),
BIT(ICR_TB, "TB", NULL),
BIT(ICR_MA, "MA", NULL),
BIT(ICR_SCLE, "SCLE", "scle"),
BIT(ICR_IUE, "IUE", "iue"),
BIT(ICR_GCD, "GCD", NULL),
BIT(ICR_ITEIE, "ITEIE", NULL),
BIT(ICR_IRFIE, "IRFIE", NULL),
BIT(ICR_BEIE, "BEIE", NULL),
BIT(ICR_SSDIE, "SSDIE", NULL),
BIT(ICR_ALDIE, "ALDIE", NULL),
BIT(ICR_SADIE, "SADIE", NULL),
BIT(ICR_UR, "UR", "ur"),
};
static void decode_ICR(unsigned int val)
{
decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val);
printk("\n");
}
static unsigned int i2c_debug = DEBUG;
static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
{
dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR);
}
#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__)
#else
#define i2c_debug 0
#define show_state(i2c) do { } while (0)
#define decode_ISR(val) do { } while (0)
#define decode_ICR(val) do { } while (0)