/*
* 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 separated 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 <linux/err.h>
#include <linux/clk.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <plat/i2c.h>
/*
* I2C register offsets will be shifted 0 or 1 bit left, depending on
* different SoCs
*/
#define REG_SHIFT_0 (0 << 0)
#define REG_SHIFT_1 (1 << 0)
#define REG_SHIFT(d) ((d) & 0x1)
static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REG_SHIFT_1 },
{ "pxa3xx-pwri2c", REG_SHIFT_0 },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
/*
* I2C registers and bit definitions
*/
#define IBMR (0x00)
#define IDBR (0x08)
#define ICR (0x10)
#define ISR (0x18)
#define ISAR (0x20)
#define ICR_START (1 << 0) /* start bit */
#define ICR_STOP (1 << 1) /* stop bit */
#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */
#define ICR_TB (1 << 3) /* transfer byte bit */
#define ICR_MA (1 << 4) /* master abort */
#define ICR_SCLE (1 << 5) /* master clock enable */
#define ICR_IUE (1 << 6) /* unit enable */
#define ICR_GCD (1 << 7) /* general call disable */
#define ICR_ITEIE (1 << 8) /* enable tx interrupts */
#define ICR_IRFIE (1 << 9) /* enable rx interrupts */
#define ICR_BEIE (1 << 10) /* enable bus error ints */
#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */
#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */
#define ICR_SADIE (1 << 13) /* slave address detected int enable */
#define ICR_UR (1 << 14) /* unit reset */
#define ICR_FM (1 << 15) /* fast mode */
#define ISR_RWM (1 << 0) /* read/write mode */
#define ISR_ACKNAK (1 << 1) /* ack/nak status */
#define ISR_UB (1 << 2) /* unit busy */
#define ISR_IBB (1 << 3) /* bus busy */
#define ISR_SSD (1 << 4) /* slave stop detected */
#define ISR_ALD (1 << 5) /* arbitration loss detected */
#define ISR_ITE (1 << 6) /* tx buffer empty */
#define ISR_IRF (1 << 7) /* rx buffer full */
#define ISR_GCAD (1 << 8) /* general call address detected */
#define ISR_SAD (1 << 9) /* slave address detected */
#define ISR_BED (1 << 10) /* bus error no ACK/NAK */
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;
struct clk *clk;
#ifdef CONFIG_I2C_PXA_SLAVE
struct i2c_slave_client *slave;
#endif
unsigned int irqlogidx;
u32 isrlog[32];
u32 icrlog[32];
void __iomem *reg_base;
unsigned int reg_shift;
unsigned long iobase;
unsigned long iosize;
int irq;
unsigned int use_pio :1;
unsigned int fast_mode :1;
};
#define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift))
#define _IDBR(i2c) ((i2c)->reg_base + (0x4 << (i2c)->reg_shift))
#define _ICR(i2c) ((i2c)->reg_base + (0x8 << (i2c)->reg_shift))
#define _ISR(i2c) ((i2c)->reg_base + (0xc << (i2c)->reg_shift))
#define _ISAR(i2c) ((i2c)->reg_base + (0x10 << (i2c)->reg_shift))
/*
* I2C Slave mode address
*/
#define I2C_PXA_SLAVE_ADDR 0x1
#ifdef DEBUG
struct bits {
u32 mask;
const char *set;
const char *unset;
};
#define PXA_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 "