| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1 | /* | 
|  | 2 | *  i2c_adap_pxa.c | 
|  | 3 | * | 
|  | 4 | *  I2C adapter for the PXA I2C bus access. | 
|  | 5 | * | 
|  | 6 | *  Copyright (C) 2002 Intrinsyc Software Inc. | 
|  | 7 | *  Copyright (C) 2004-2005 Deep Blue Solutions Ltd. | 
|  | 8 | * | 
|  | 9 | *  This program is free software; you can redistribute it and/or modify | 
|  | 10 | *  it under the terms of the GNU General Public License version 2 as | 
|  | 11 | *  published by the Free Software Foundation. | 
|  | 12 | * | 
|  | 13 | *  History: | 
|  | 14 | *    Apr 2002: Initial version [CS] | 
| Daniel Mack | 3ad2f3f | 2010-02-03 08:01:28 +0800 | [diff] [blame] | 15 | *    Jun 2002: Properly separated algo/adap [FB] | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 16 | *    Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] | 
|  | 17 | *    Jan 2003: added limited signal handling [Kai-Uwe Bloem] | 
|  | 18 | *    Sep 2004: Major rework to ensure efficient bus handling [RMK] | 
|  | 19 | *    Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood] | 
|  | 20 | *    Feb 2005: Rework slave mode handling [RMK] | 
|  | 21 | */ | 
|  | 22 | #include <linux/kernel.h> | 
|  | 23 | #include <linux/module.h> | 
|  | 24 | #include <linux/i2c.h> | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 25 | #include <linux/init.h> | 
|  | 26 | #include <linux/time.h> | 
|  | 27 | #include <linux/sched.h> | 
|  | 28 | #include <linux/delay.h> | 
|  | 29 | #include <linux/errno.h> | 
|  | 30 | #include <linux/interrupt.h> | 
|  | 31 | #include <linux/i2c-pxa.h> | 
| Sebastian Andrzej Siewior | baa8cab | 2011-02-23 12:38:20 +0100 | [diff] [blame] | 32 | #include <linux/of_i2c.h> | 
| Russell King | d052d1b | 2005-10-29 19:07:23 +0100 | [diff] [blame] | 33 | #include <linux/platform_device.h> | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 34 | #include <linux/err.h> | 
|  | 35 | #include <linux/clk.h> | 
| Tejun Heo | 5a0e3ad | 2010-03-24 17:04:11 +0900 | [diff] [blame] | 36 | #include <linux/slab.h> | 
| H Hartley Sweeten | 2178218 | 2010-05-21 18:41:01 +0200 | [diff] [blame] | 37 | #include <linux/io.h> | 
| Sebastian Andrzej Siewior | b459396 | 2011-02-23 12:38:16 +0100 | [diff] [blame] | 38 | #include <linux/i2c/pxa-i2c.h> | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 39 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 40 | #include <asm/irq.h> | 
| Eric Miao | 283afa0 | 2008-09-08 14:15:08 +0800 | [diff] [blame] | 41 |  | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 42 | #ifndef CONFIG_HAVE_CLK | 
|  | 43 | #define clk_get(dev, id)	NULL | 
|  | 44 | #define clk_put(clk)		do { } while (0) | 
|  | 45 | #define clk_disable(clk)	do { } while (0) | 
|  | 46 | #define clk_enable(clk)		do { } while (0) | 
|  | 47 | #endif | 
|  | 48 |  | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 49 | struct pxa_reg_layout { | 
|  | 50 | u32 ibmr; | 
|  | 51 | u32 idbr; | 
|  | 52 | u32 icr; | 
|  | 53 | u32 isr; | 
|  | 54 | u32 isar; | 
|  | 55 | }; | 
|  | 56 |  | 
|  | 57 | enum pxa_i2c_types { | 
|  | 58 | REGS_PXA2XX, | 
|  | 59 | REGS_PXA3XX, | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 60 | REGS_CE4100, | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 61 | }; | 
|  | 62 |  | 
| Eric Miao | 283afa0 | 2008-09-08 14:15:08 +0800 | [diff] [blame] | 63 | /* | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 64 | * I2C registers definitions | 
| Eric Miao | f23d491 | 2009-04-13 14:43:25 +0800 | [diff] [blame] | 65 | */ | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 66 | static struct pxa_reg_layout pxa_reg_layout[] = { | 
|  | 67 | [REGS_PXA2XX] = { | 
|  | 68 | .ibmr =	0x00, | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 69 | .idbr =	0x08, | 
|  | 70 | .icr =	0x10, | 
|  | 71 | .isr =	0x18, | 
|  | 72 | .isar =	0x20, | 
|  | 73 | }, | 
| Vasily Khoruzhick | 23e74a8 | 2011-03-13 15:53:28 +0200 | [diff] [blame] | 74 | [REGS_PXA3XX] = { | 
|  | 75 | .ibmr =	0x00, | 
|  | 76 | .idbr =	0x04, | 
|  | 77 | .icr =	0x08, | 
|  | 78 | .isr =	0x0c, | 
|  | 79 | .isar =	0x10, | 
|  | 80 | }, | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 81 | [REGS_CE4100] = { | 
|  | 82 | .ibmr =	0x14, | 
|  | 83 | .idbr =	0x0c, | 
|  | 84 | .icr =	0x00, | 
|  | 85 | .isr =	0x04, | 
|  | 86 | /* no isar register */ | 
|  | 87 | }, | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 88 | }; | 
| Eric Miao | f23d491 | 2009-04-13 14:43:25 +0800 | [diff] [blame] | 89 |  | 
|  | 90 | static const struct platform_device_id i2c_pxa_id_table[] = { | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 91 | { "pxa2xx-i2c",		REGS_PXA2XX }, | 
|  | 92 | { "pxa3xx-pwri2c",	REGS_PXA3XX }, | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 93 | { "ce4100-i2c",		REGS_CE4100 }, | 
| Eric Miao | f23d491 | 2009-04-13 14:43:25 +0800 | [diff] [blame] | 94 | { }, | 
|  | 95 | }; | 
|  | 96 | MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); | 
|  | 97 |  | 
|  | 98 | /* | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 99 | * I2C bit definitions | 
| Eric Miao | 283afa0 | 2008-09-08 14:15:08 +0800 | [diff] [blame] | 100 | */ | 
| Eric Miao | 283afa0 | 2008-09-08 14:15:08 +0800 | [diff] [blame] | 101 |  | 
|  | 102 | #define ICR_START	(1 << 0)	   /* start bit */ | 
|  | 103 | #define ICR_STOP	(1 << 1)	   /* stop bit */ | 
|  | 104 | #define ICR_ACKNAK	(1 << 2)	   /* send ACK(0) or NAK(1) */ | 
|  | 105 | #define ICR_TB		(1 << 3)	   /* transfer byte bit */ | 
|  | 106 | #define ICR_MA		(1 << 4)	   /* master abort */ | 
|  | 107 | #define ICR_SCLE	(1 << 5)	   /* master clock enable */ | 
|  | 108 | #define ICR_IUE		(1 << 6)	   /* unit enable */ | 
|  | 109 | #define ICR_GCD		(1 << 7)	   /* general call disable */ | 
|  | 110 | #define ICR_ITEIE	(1 << 8)	   /* enable tx interrupts */ | 
|  | 111 | #define ICR_IRFIE	(1 << 9)	   /* enable rx interrupts */ | 
|  | 112 | #define ICR_BEIE	(1 << 10)	   /* enable bus error ints */ | 
|  | 113 | #define ICR_SSDIE	(1 << 11)	   /* slave STOP detected int enable */ | 
|  | 114 | #define ICR_ALDIE	(1 << 12)	   /* enable arbitration interrupt */ | 
|  | 115 | #define ICR_SADIE	(1 << 13)	   /* slave address detected int enable */ | 
|  | 116 | #define ICR_UR		(1 << 14)	   /* unit reset */ | 
|  | 117 | #define ICR_FM		(1 << 15)	   /* fast mode */ | 
|  | 118 |  | 
|  | 119 | #define ISR_RWM		(1 << 0)	   /* read/write mode */ | 
|  | 120 | #define ISR_ACKNAK	(1 << 1)	   /* ack/nak status */ | 
|  | 121 | #define ISR_UB		(1 << 2)	   /* unit busy */ | 
|  | 122 | #define ISR_IBB		(1 << 3)	   /* bus busy */ | 
|  | 123 | #define ISR_SSD		(1 << 4)	   /* slave stop detected */ | 
|  | 124 | #define ISR_ALD		(1 << 5)	   /* arbitration loss detected */ | 
|  | 125 | #define ISR_ITE		(1 << 6)	   /* tx buffer empty */ | 
|  | 126 | #define ISR_IRF		(1 << 7)	   /* rx buffer full */ | 
|  | 127 | #define ISR_GCAD	(1 << 8)	   /* general call address detected */ | 
|  | 128 | #define ISR_SAD		(1 << 9)	   /* slave address detected */ | 
|  | 129 | #define ISR_BED		(1 << 10)	   /* bus error no ACK/NAK */ | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 130 |  | 
|  | 131 | struct pxa_i2c { | 
|  | 132 | spinlock_t		lock; | 
|  | 133 | wait_queue_head_t	wait; | 
|  | 134 | struct i2c_msg		*msg; | 
|  | 135 | unsigned int		msg_num; | 
|  | 136 | unsigned int		msg_idx; | 
|  | 137 | unsigned int		msg_ptr; | 
|  | 138 | unsigned int		slave_addr; | 
|  | 139 |  | 
|  | 140 | struct i2c_adapter	adap; | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 141 | struct clk		*clk; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 142 | #ifdef CONFIG_I2C_PXA_SLAVE | 
|  | 143 | struct i2c_slave_client *slave; | 
|  | 144 | #endif | 
|  | 145 |  | 
|  | 146 | unsigned int		irqlogidx; | 
|  | 147 | u32			isrlog[32]; | 
|  | 148 | u32			icrlog[32]; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 149 |  | 
|  | 150 | void __iomem		*reg_base; | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 151 | void __iomem		*reg_ibmr; | 
|  | 152 | void __iomem		*reg_idbr; | 
|  | 153 | void __iomem		*reg_icr; | 
|  | 154 | void __iomem		*reg_isr; | 
|  | 155 | void __iomem		*reg_isar; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 156 |  | 
|  | 157 | unsigned long		iobase; | 
|  | 158 | unsigned long		iosize; | 
|  | 159 |  | 
|  | 160 | int			irq; | 
| Jonathan Cameron | c46c948 | 2008-10-03 15:07:36 +0100 | [diff] [blame] | 161 | unsigned int		use_pio :1; | 
|  | 162 | unsigned int		fast_mode :1; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 163 | }; | 
|  | 164 |  | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 165 | #define _IBMR(i2c)	((i2c)->reg_ibmr) | 
|  | 166 | #define _IDBR(i2c)	((i2c)->reg_idbr) | 
|  | 167 | #define _ICR(i2c)	((i2c)->reg_icr) | 
|  | 168 | #define _ISR(i2c)	((i2c)->reg_isr) | 
|  | 169 | #define _ISAR(i2c)	((i2c)->reg_isar) | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 170 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 171 | /* | 
|  | 172 | * I2C Slave mode address | 
|  | 173 | */ | 
|  | 174 | #define I2C_PXA_SLAVE_ADDR      0x1 | 
|  | 175 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 176 | #ifdef DEBUG | 
|  | 177 |  | 
|  | 178 | struct bits { | 
|  | 179 | u32	mask; | 
|  | 180 | const char *set; | 
|  | 181 | const char *unset; | 
|  | 182 | }; | 
| Jiri Slaby | ed11399 | 2007-10-18 23:40:28 -0700 | [diff] [blame] | 183 | #define PXA_BIT(m, s, u)	{ .mask = m, .set = s, .unset = u } | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 184 |  | 
|  | 185 | static inline void | 
|  | 186 | decode_bits(const char *prefix, const struct bits *bits, int num, u32 val) | 
|  | 187 | { | 
|  | 188 | printk("%s %08x: ", prefix, val); | 
|  | 189 | while (num--) { | 
|  | 190 | const char *str = val & bits->mask ? bits->set : bits->unset; | 
|  | 191 | if (str) | 
|  | 192 | printk("%s ", str); | 
|  | 193 | bits++; | 
|  | 194 | } | 
|  | 195 | } | 
|  | 196 |  | 
|  | 197 | static const struct bits isr_bits[] = { | 
| Jiri Slaby | ed11399 | 2007-10-18 23:40:28 -0700 | [diff] [blame] | 198 | PXA_BIT(ISR_RWM,	"RX",		"TX"), | 
|  | 199 | PXA_BIT(ISR_ACKNAK,	"NAK",		"ACK"), | 
|  | 200 | PXA_BIT(ISR_UB,		"Bsy",		"Rdy"), | 
|  | 201 | PXA_BIT(ISR_IBB,	"BusBsy",	"BusRdy"), | 
|  | 202 | PXA_BIT(ISR_SSD,	"SlaveStop",	NULL), | 
|  | 203 | PXA_BIT(ISR_ALD,	"ALD",		NULL), | 
|  | 204 | PXA_BIT(ISR_ITE,	"TxEmpty",	NULL), | 
|  | 205 | PXA_BIT(ISR_IRF,	"RxFull",	NULL), | 
|  | 206 | PXA_BIT(ISR_GCAD,	"GenCall",	NULL), | 
|  | 207 | PXA_BIT(ISR_SAD,	"SlaveAddr",	NULL), | 
|  | 208 | PXA_BIT(ISR_BED,	"BusErr",	NULL), | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 209 | }; | 
|  | 210 |  | 
|  | 211 | static void decode_ISR(unsigned int val) | 
|  | 212 | { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 213 | decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 214 | printk("\n"); | 
|  | 215 | } | 
|  | 216 |  | 
|  | 217 | static const struct bits icr_bits[] = { | 
| Jiri Slaby | ed11399 | 2007-10-18 23:40:28 -0700 | [diff] [blame] | 218 | PXA_BIT(ICR_START,  "START",	NULL), | 
|  | 219 | PXA_BIT(ICR_STOP,   "STOP",	NULL), | 
|  | 220 | PXA_BIT(ICR_ACKNAK, "ACKNAK",	NULL), | 
|  | 221 | PXA_BIT(ICR_TB,     "TB",	NULL), | 
|  | 222 | PXA_BIT(ICR_MA,     "MA",	NULL), | 
|  | 223 | PXA_BIT(ICR_SCLE,   "SCLE",	"scle"), | 
|  | 224 | PXA_BIT(ICR_IUE,    "IUE",	"iue"), | 
|  | 225 | PXA_BIT(ICR_GCD,    "GCD",	NULL), | 
|  | 226 | PXA_BIT(ICR_ITEIE,  "ITEIE",	NULL), | 
|  | 227 | PXA_BIT(ICR_IRFIE,  "IRFIE",	NULL), | 
|  | 228 | PXA_BIT(ICR_BEIE,   "BEIE",	NULL), | 
|  | 229 | PXA_BIT(ICR_SSDIE,  "SSDIE",	NULL), | 
|  | 230 | PXA_BIT(ICR_ALDIE,  "ALDIE",	NULL), | 
|  | 231 | PXA_BIT(ICR_SADIE,  "SADIE",	NULL), | 
|  | 232 | PXA_BIT(ICR_UR,     "UR",		"ur"), | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 233 | }; | 
|  | 234 |  | 
| Holger Schurig | d6a7b5f | 2008-02-11 16:51:41 +0100 | [diff] [blame] | 235 | #ifdef CONFIG_I2C_PXA_SLAVE | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 236 | static void decode_ICR(unsigned int val) | 
|  | 237 | { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 238 | decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 239 | printk("\n"); | 
|  | 240 | } | 
| Holger Schurig | d6a7b5f | 2008-02-11 16:51:41 +0100 | [diff] [blame] | 241 | #endif | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 242 |  | 
|  | 243 | static unsigned int i2c_debug = DEBUG; | 
|  | 244 |  | 
|  | 245 | static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) | 
|  | 246 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 247 | dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, | 
|  | 248 | readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 249 | } | 
|  | 250 |  | 
| Harvey Harrison | 08882d2 | 2008-04-22 22:16:47 +0200 | [diff] [blame] | 251 | #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 252 |  | 
|  | 253 | static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) | 
|  | 254 | { | 
|  | 255 | unsigned int i; | 
| Frank Seidel | 154d22b | 2009-03-28 21:34:42 +0100 | [diff] [blame] | 256 | printk(KERN_ERR "i2c: error: %s\n", why); | 
|  | 257 | printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 258 | i2c->msg_num, i2c->msg_idx, i2c->msg_ptr); | 
| Frank Seidel | 154d22b | 2009-03-28 21:34:42 +0100 | [diff] [blame] | 259 | printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n", | 
|  | 260 | readl(_ICR(i2c)), readl(_ISR(i2c))); | 
|  | 261 | printk(KERN_DEBUG "i2c: log: "); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 262 | for (i = 0; i < i2c->irqlogidx; i++) | 
|  | 263 | printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); | 
|  | 264 | printk("\n"); | 
|  | 265 | } | 
|  | 266 |  | 
| Wolfram Sang | 0d813d9 | 2009-11-03 12:53:41 +0100 | [diff] [blame] | 267 | #else /* ifdef DEBUG */ | 
|  | 268 |  | 
|  | 269 | #define i2c_debug	0 | 
|  | 270 |  | 
|  | 271 | #define show_state(i2c) do { } while (0) | 
|  | 272 | #define decode_ISR(val) do { } while (0) | 
|  | 273 | #define decode_ICR(val) do { } while (0) | 
|  | 274 | #define i2c_pxa_scream_blue_murder(i2c, why) do { } while (0) | 
|  | 275 |  | 
|  | 276 | #endif /* ifdef DEBUG / else */ | 
|  | 277 |  | 
|  | 278 | static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); | 
|  | 279 | static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); | 
|  | 280 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 281 | static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) | 
|  | 282 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 283 | return !(readl(_ICR(i2c)) & ICR_SCLE); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 284 | } | 
|  | 285 |  | 
|  | 286 | static void i2c_pxa_abort(struct pxa_i2c *i2c) | 
|  | 287 | { | 
| Dmitry Baryshkov | 387fa6a | 2008-08-18 14:38:48 +0100 | [diff] [blame] | 288 | int i = 250; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 289 |  | 
|  | 290 | if (i2c_pxa_is_slavemode(i2c)) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 291 | dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 292 | return; | 
|  | 293 | } | 
|  | 294 |  | 
| Dmitry Baryshkov | 387fa6a | 2008-08-18 14:38:48 +0100 | [diff] [blame] | 295 | while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 296 | unsigned long icr = readl(_ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 297 |  | 
|  | 298 | icr &= ~ICR_START; | 
|  | 299 | icr |= ICR_ACKNAK | ICR_STOP | ICR_TB; | 
|  | 300 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 301 | writel(icr, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 302 |  | 
|  | 303 | show_state(i2c); | 
|  | 304 |  | 
| Dmitry Baryshkov | 387fa6a | 2008-08-18 14:38:48 +0100 | [diff] [blame] | 305 | mdelay(1); | 
|  | 306 | i --; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 307 | } | 
|  | 308 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 309 | writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP), | 
|  | 310 | _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 311 | } | 
|  | 312 |  | 
|  | 313 | static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) | 
|  | 314 | { | 
|  | 315 | int timeout = DEF_TIMEOUT; | 
|  | 316 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 317 | while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { | 
|  | 318 | if ((readl(_ISR(i2c)) & ISR_SAD) != 0) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 319 | timeout += 4; | 
|  | 320 |  | 
|  | 321 | msleep(2); | 
|  | 322 | show_state(i2c); | 
|  | 323 | } | 
|  | 324 |  | 
| Roel Kluin | d10db3a | 2009-04-23 16:27:39 +0200 | [diff] [blame] | 325 | if (timeout < 0) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 326 | show_state(i2c); | 
|  | 327 |  | 
| Roel Kluin | d10db3a | 2009-04-23 16:27:39 +0200 | [diff] [blame] | 328 | return timeout < 0 ? I2C_RETRY : 0; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 329 | } | 
|  | 330 |  | 
|  | 331 | static int i2c_pxa_wait_master(struct pxa_i2c *i2c) | 
|  | 332 | { | 
|  | 333 | unsigned long timeout = jiffies + HZ*4; | 
|  | 334 |  | 
|  | 335 | while (time_before(jiffies, timeout)) { | 
|  | 336 | if (i2c_debug > 1) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 337 | dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 338 | __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 339 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 340 | if (readl(_ISR(i2c)) & ISR_SAD) { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 341 | if (i2c_debug > 0) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 342 | dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 343 | goto out; | 
|  | 344 | } | 
|  | 345 |  | 
|  | 346 | /* wait for unit and bus being not busy, and we also do a | 
|  | 347 | * quick check of the i2c lines themselves to ensure they've | 
|  | 348 | * gone high... | 
|  | 349 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 350 | if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 351 | if (i2c_debug > 0) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 352 | dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 353 | return 1; | 
|  | 354 | } | 
|  | 355 |  | 
|  | 356 | msleep(1); | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | if (i2c_debug > 0) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 360 | dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 361 | out: | 
|  | 362 | return 0; | 
|  | 363 | } | 
|  | 364 |  | 
|  | 365 | static int i2c_pxa_set_master(struct pxa_i2c *i2c) | 
|  | 366 | { | 
|  | 367 | if (i2c_debug) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 368 | dev_dbg(&i2c->adap.dev, "setting to bus master\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 369 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 370 | if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 371 | dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 372 | if (!i2c_pxa_wait_master(i2c)) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 373 | dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 374 | return I2C_RETRY; | 
|  | 375 | } | 
|  | 376 | } | 
|  | 377 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 378 | writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 379 | return 0; | 
|  | 380 | } | 
|  | 381 |  | 
|  | 382 | #ifdef CONFIG_I2C_PXA_SLAVE | 
|  | 383 | static int i2c_pxa_wait_slave(struct pxa_i2c *i2c) | 
|  | 384 | { | 
|  | 385 | unsigned long timeout = jiffies + HZ*1; | 
|  | 386 |  | 
|  | 387 | /* wait for stop */ | 
|  | 388 |  | 
|  | 389 | show_state(i2c); | 
|  | 390 |  | 
|  | 391 | while (time_before(jiffies, timeout)) { | 
|  | 392 | if (i2c_debug > 1) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 393 | dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 394 | __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 395 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 396 | if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 || | 
|  | 397 | (readl(_ISR(i2c)) & ISR_SAD) != 0 || | 
|  | 398 | (readl(_ICR(i2c)) & ICR_SCLE) == 0) { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 399 | if (i2c_debug > 1) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 400 | dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 401 | return 1; | 
|  | 402 | } | 
|  | 403 |  | 
|  | 404 | msleep(1); | 
|  | 405 | } | 
|  | 406 |  | 
|  | 407 | if (i2c_debug > 0) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 408 | dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 409 | return 0; | 
|  | 410 | } | 
|  | 411 |  | 
|  | 412 | /* | 
|  | 413 | * clear the hold on the bus, and take of anything else | 
|  | 414 | * that has been configured | 
|  | 415 | */ | 
|  | 416 | static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode) | 
|  | 417 | { | 
|  | 418 | show_state(i2c); | 
|  | 419 |  | 
|  | 420 | if (errcode < 0) { | 
|  | 421 | udelay(100);   /* simple delay */ | 
|  | 422 | } else { | 
|  | 423 | /* we need to wait for the stop condition to end */ | 
|  | 424 |  | 
|  | 425 | /* if we where in stop, then clear... */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 426 | if (readl(_ICR(i2c)) & ICR_STOP) { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 427 | udelay(100); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 428 | writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 429 | } | 
|  | 430 |  | 
|  | 431 | if (!i2c_pxa_wait_slave(i2c)) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 432 | dev_err(&i2c->adap.dev, "%s: wait timedout\n", | 
|  | 433 | __func__); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 434 | return; | 
|  | 435 | } | 
|  | 436 | } | 
|  | 437 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 438 | writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c)); | 
|  | 439 | writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 440 |  | 
|  | 441 | if (i2c_debug) { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 442 | dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c))); | 
|  | 443 | decode_ICR(readl(_ICR(i2c))); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 444 | } | 
|  | 445 | } | 
|  | 446 | #else | 
|  | 447 | #define i2c_pxa_set_slave(i2c, err)	do { } while (0) | 
|  | 448 | #endif | 
|  | 449 |  | 
|  | 450 | static void i2c_pxa_reset(struct pxa_i2c *i2c) | 
|  | 451 | { | 
|  | 452 | pr_debug("Resetting I2C Controller Unit\n"); | 
|  | 453 |  | 
|  | 454 | /* abort any transfer currently under way */ | 
|  | 455 | i2c_pxa_abort(i2c); | 
|  | 456 |  | 
|  | 457 | /* reset according to 9.8 */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 458 | writel(ICR_UR, _ICR(i2c)); | 
|  | 459 | writel(I2C_ISR_INIT, _ISR(i2c)); | 
|  | 460 | writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 461 |  | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 462 | if (i2c->reg_isar) | 
|  | 463 | writel(i2c->slave_addr, _ISAR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 464 |  | 
|  | 465 | /* set control register values */ | 
| Jonathan Cameron | c46c948 | 2008-10-03 15:07:36 +0100 | [diff] [blame] | 466 | writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 467 |  | 
|  | 468 | #ifdef CONFIG_I2C_PXA_SLAVE | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 469 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 470 | writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 471 | #endif | 
|  | 472 |  | 
|  | 473 | i2c_pxa_set_slave(i2c, 0); | 
|  | 474 |  | 
|  | 475 | /* enable unit */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 476 | writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 477 | udelay(100); | 
|  | 478 | } | 
|  | 479 |  | 
|  | 480 |  | 
|  | 481 | #ifdef CONFIG_I2C_PXA_SLAVE | 
|  | 482 | /* | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 483 | * PXA I2C Slave mode | 
|  | 484 | */ | 
|  | 485 |  | 
|  | 486 | static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) | 
|  | 487 | { | 
|  | 488 | if (isr & ISR_BED) { | 
|  | 489 | /* what should we do here? */ | 
|  | 490 | } else { | 
| Russell King | 84b5abe | 2006-10-28 22:30:17 +0100 | [diff] [blame] | 491 | int ret = 0; | 
|  | 492 |  | 
|  | 493 | if (i2c->slave != NULL) | 
|  | 494 | ret = i2c->slave->read(i2c->slave->data); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 495 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 496 | writel(ret, _IDBR(i2c)); | 
|  | 497 | writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c));   /* allow next byte */ | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 498 | } | 
|  | 499 | } | 
|  | 500 |  | 
|  | 501 | static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) | 
|  | 502 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 503 | unsigned int byte = readl(_IDBR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 504 |  | 
|  | 505 | if (i2c->slave != NULL) | 
|  | 506 | i2c->slave->write(i2c->slave->data, byte); | 
|  | 507 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 508 | writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 509 | } | 
|  | 510 |  | 
|  | 511 | static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) | 
|  | 512 | { | 
|  | 513 | int timeout; | 
|  | 514 |  | 
|  | 515 | if (i2c_debug > 0) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 516 | dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n", | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 517 | (isr & ISR_RWM) ? 'r' : 't'); | 
|  | 518 |  | 
|  | 519 | if (i2c->slave != NULL) | 
|  | 520 | i2c->slave->event(i2c->slave->data, | 
|  | 521 | (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE); | 
|  | 522 |  | 
|  | 523 | /* | 
|  | 524 | * slave could interrupt in the middle of us generating a | 
|  | 525 | * start condition... if this happens, we'd better back off | 
|  | 526 | * and stop holding the poor thing up | 
|  | 527 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 528 | writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c)); | 
|  | 529 | writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 530 |  | 
|  | 531 | timeout = 0x10000; | 
|  | 532 |  | 
|  | 533 | while (1) { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 534 | if ((readl(_IBMR(i2c)) & 2) == 2) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 535 | break; | 
|  | 536 |  | 
|  | 537 | timeout--; | 
|  | 538 |  | 
|  | 539 | if (timeout <= 0) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 540 | dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 541 | break; | 
|  | 542 | } | 
|  | 543 | } | 
|  | 544 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 545 | writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 546 | } | 
|  | 547 |  | 
|  | 548 | static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) | 
|  | 549 | { | 
|  | 550 | if (i2c_debug > 2) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 551 | dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 552 |  | 
|  | 553 | if (i2c->slave != NULL) | 
|  | 554 | i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP); | 
|  | 555 |  | 
|  | 556 | if (i2c_debug > 2) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 557 | dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 558 |  | 
|  | 559 | /* | 
|  | 560 | * If we have a master-mode message waiting, | 
|  | 561 | * kick it off now that the slave has completed. | 
|  | 562 | */ | 
|  | 563 | if (i2c->msg) | 
|  | 564 | i2c_pxa_master_complete(i2c, I2C_RETRY); | 
|  | 565 | } | 
|  | 566 | #else | 
|  | 567 | static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) | 
|  | 568 | { | 
|  | 569 | if (isr & ISR_BED) { | 
|  | 570 | /* what should we do here? */ | 
|  | 571 | } else { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 572 | writel(0, _IDBR(i2c)); | 
|  | 573 | writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 574 | } | 
|  | 575 | } | 
|  | 576 |  | 
|  | 577 | static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) | 
|  | 578 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 579 | writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 580 | } | 
|  | 581 |  | 
|  | 582 | static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) | 
|  | 583 | { | 
|  | 584 | int timeout; | 
|  | 585 |  | 
|  | 586 | /* | 
|  | 587 | * slave could interrupt in the middle of us generating a | 
|  | 588 | * start condition... if this happens, we'd better back off | 
|  | 589 | * and stop holding the poor thing up | 
|  | 590 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 591 | writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c)); | 
|  | 592 | writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 593 |  | 
|  | 594 | timeout = 0x10000; | 
|  | 595 |  | 
|  | 596 | while (1) { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 597 | if ((readl(_IBMR(i2c)) & 2) == 2) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 598 | break; | 
|  | 599 |  | 
|  | 600 | timeout--; | 
|  | 601 |  | 
|  | 602 | if (timeout <= 0) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 603 | dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 604 | break; | 
|  | 605 | } | 
|  | 606 | } | 
|  | 607 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 608 | writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 609 | } | 
|  | 610 |  | 
|  | 611 | static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) | 
|  | 612 | { | 
|  | 613 | if (i2c->msg) | 
|  | 614 | i2c_pxa_master_complete(i2c, I2C_RETRY); | 
|  | 615 | } | 
|  | 616 | #endif | 
|  | 617 |  | 
|  | 618 | /* | 
|  | 619 | * PXA I2C Master mode | 
|  | 620 | */ | 
|  | 621 |  | 
|  | 622 | static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg) | 
|  | 623 | { | 
|  | 624 | unsigned int addr = (msg->addr & 0x7f) << 1; | 
|  | 625 |  | 
|  | 626 | if (msg->flags & I2C_M_RD) | 
|  | 627 | addr |= 1; | 
|  | 628 |  | 
|  | 629 | return addr; | 
|  | 630 | } | 
|  | 631 |  | 
|  | 632 | static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) | 
|  | 633 | { | 
|  | 634 | u32 icr; | 
|  | 635 |  | 
|  | 636 | /* | 
|  | 637 | * Step 1: target slave address into IDBR | 
|  | 638 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 639 | writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 640 |  | 
|  | 641 | /* | 
|  | 642 | * Step 2: initiate the write. | 
|  | 643 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 644 | icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE); | 
|  | 645 | writel(icr | ICR_START | ICR_TB, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 646 | } | 
|  | 647 |  | 
| Jean Delvare | 7d05481 | 2007-05-01 23:26:33 +0200 | [diff] [blame] | 648 | static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) | 
|  | 649 | { | 
|  | 650 | u32 icr; | 
|  | 651 |  | 
|  | 652 | /* | 
|  | 653 | * Clear the STOP and ACK flags | 
|  | 654 | */ | 
|  | 655 | icr = readl(_ICR(i2c)); | 
|  | 656 | icr &= ~(ICR_STOP | ICR_ACKNAK); | 
| Russell King | 0cfe61e | 2007-05-10 03:15:32 -0700 | [diff] [blame] | 657 | writel(icr, _ICR(i2c)); | 
| Jean Delvare | 7d05481 | 2007-05-01 23:26:33 +0200 | [diff] [blame] | 658 | } | 
|  | 659 |  | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 660 | static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) | 
|  | 661 | { | 
|  | 662 | /* make timeout the same as for interrupt based functions */ | 
|  | 663 | long timeout = 2 * DEF_TIMEOUT; | 
|  | 664 |  | 
|  | 665 | /* | 
|  | 666 | * Wait for the bus to become free. | 
|  | 667 | */ | 
|  | 668 | while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { | 
|  | 669 | udelay(1000); | 
|  | 670 | show_state(i2c); | 
|  | 671 | } | 
|  | 672 |  | 
| Roel Kluin | d10db3a | 2009-04-23 16:27:39 +0200 | [diff] [blame] | 673 | if (timeout < 0) { | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 674 | show_state(i2c); | 
|  | 675 | dev_err(&i2c->adap.dev, | 
|  | 676 | "i2c_pxa: timeout waiting for bus free\n"); | 
|  | 677 | return I2C_RETRY; | 
|  | 678 | } | 
|  | 679 |  | 
|  | 680 | /* | 
|  | 681 | * Set master mode. | 
|  | 682 | */ | 
|  | 683 | writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); | 
|  | 684 |  | 
|  | 685 | return 0; | 
|  | 686 | } | 
|  | 687 |  | 
|  | 688 | static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, | 
|  | 689 | struct i2c_msg *msg, int num) | 
|  | 690 | { | 
|  | 691 | unsigned long timeout = 500000; /* 5 seconds */ | 
|  | 692 | int ret = 0; | 
|  | 693 |  | 
|  | 694 | ret = i2c_pxa_pio_set_master(i2c); | 
|  | 695 | if (ret) | 
|  | 696 | goto out; | 
|  | 697 |  | 
|  | 698 | i2c->msg = msg; | 
|  | 699 | i2c->msg_num = num; | 
|  | 700 | i2c->msg_idx = 0; | 
|  | 701 | i2c->msg_ptr = 0; | 
|  | 702 | i2c->irqlogidx = 0; | 
|  | 703 |  | 
|  | 704 | i2c_pxa_start_message(i2c); | 
|  | 705 |  | 
| Roel Kluin | a746b57 | 2009-02-24 19:19:48 +0100 | [diff] [blame] | 706 | while (i2c->msg_num > 0 && --timeout) { | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 707 | i2c_pxa_handler(0, i2c); | 
|  | 708 | udelay(10); | 
|  | 709 | } | 
|  | 710 |  | 
|  | 711 | i2c_pxa_stop_message(i2c); | 
|  | 712 |  | 
|  | 713 | /* | 
|  | 714 | * We place the return code in i2c->msg_idx. | 
|  | 715 | */ | 
|  | 716 | ret = i2c->msg_idx; | 
|  | 717 |  | 
|  | 718 | out: | 
|  | 719 | if (timeout == 0) | 
|  | 720 | i2c_pxa_scream_blue_murder(i2c, "timeout"); | 
|  | 721 |  | 
|  | 722 | return ret; | 
|  | 723 | } | 
|  | 724 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 725 | /* | 
| Jean Delvare | 3fb9a65 | 2006-01-18 23:17:01 +0100 | [diff] [blame] | 726 | * We are protected by the adapter bus mutex. | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 727 | */ | 
|  | 728 | static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) | 
|  | 729 | { | 
|  | 730 | long timeout; | 
|  | 731 | int ret; | 
|  | 732 |  | 
|  | 733 | /* | 
|  | 734 | * Wait for the bus to become free. | 
|  | 735 | */ | 
|  | 736 | ret = i2c_pxa_wait_bus_not_busy(i2c); | 
|  | 737 | if (ret) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 738 | dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 739 | goto out; | 
|  | 740 | } | 
|  | 741 |  | 
|  | 742 | /* | 
|  | 743 | * Set master mode. | 
|  | 744 | */ | 
|  | 745 | ret = i2c_pxa_set_master(i2c); | 
|  | 746 | if (ret) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 747 | dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 748 | goto out; | 
|  | 749 | } | 
|  | 750 |  | 
|  | 751 | spin_lock_irq(&i2c->lock); | 
|  | 752 |  | 
|  | 753 | i2c->msg = msg; | 
|  | 754 | i2c->msg_num = num; | 
|  | 755 | i2c->msg_idx = 0; | 
|  | 756 | i2c->msg_ptr = 0; | 
|  | 757 | i2c->irqlogidx = 0; | 
|  | 758 |  | 
|  | 759 | i2c_pxa_start_message(i2c); | 
|  | 760 |  | 
|  | 761 | spin_unlock_irq(&i2c->lock); | 
|  | 762 |  | 
|  | 763 | /* | 
|  | 764 | * The rest of the processing occurs in the interrupt handler. | 
|  | 765 | */ | 
|  | 766 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | 
| Jean Delvare | 7d05481 | 2007-05-01 23:26:33 +0200 | [diff] [blame] | 767 | i2c_pxa_stop_message(i2c); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 768 |  | 
|  | 769 | /* | 
|  | 770 | * We place the return code in i2c->msg_idx. | 
|  | 771 | */ | 
|  | 772 | ret = i2c->msg_idx; | 
|  | 773 |  | 
| Sebastian Andrzej Siewior | 93c92cf | 2011-02-23 12:38:19 +0100 | [diff] [blame] | 774 | if (!timeout && i2c->msg_num) { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 775 | i2c_pxa_scream_blue_murder(i2c, "timeout"); | 
| Sebastian Andrzej Siewior | 93c92cf | 2011-02-23 12:38:19 +0100 | [diff] [blame] | 776 | ret = I2C_RETRY; | 
|  | 777 | } | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 778 |  | 
|  | 779 | out: | 
|  | 780 | return ret; | 
|  | 781 | } | 
|  | 782 |  | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 783 | static int i2c_pxa_pio_xfer(struct i2c_adapter *adap, | 
|  | 784 | struct i2c_msg msgs[], int num) | 
|  | 785 | { | 
|  | 786 | struct pxa_i2c *i2c = adap->algo_data; | 
|  | 787 | int ret, i; | 
|  | 788 |  | 
|  | 789 | /* If the I2C controller is disabled we need to reset it | 
|  | 790 | (probably due to a suspend/resume destroying state). We do | 
|  | 791 | this here as we can then avoid worrying about resuming the | 
|  | 792 | controller before its users. */ | 
|  | 793 | if (!(readl(_ICR(i2c)) & ICR_IUE)) | 
|  | 794 | i2c_pxa_reset(i2c); | 
|  | 795 |  | 
|  | 796 | for (i = adap->retries; i >= 0; i--) { | 
|  | 797 | ret = i2c_pxa_do_pio_xfer(i2c, msgs, num); | 
|  | 798 | if (ret != I2C_RETRY) | 
|  | 799 | goto out; | 
|  | 800 |  | 
|  | 801 | if (i2c_debug) | 
|  | 802 | dev_dbg(&adap->dev, "Retrying transmission\n"); | 
|  | 803 | udelay(100); | 
|  | 804 | } | 
|  | 805 | i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); | 
|  | 806 | ret = -EREMOTEIO; | 
|  | 807 | out: | 
|  | 808 | i2c_pxa_set_slave(i2c, ret); | 
|  | 809 | return ret; | 
|  | 810 | } | 
|  | 811 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 812 | /* | 
|  | 813 | * i2c_pxa_master_complete - complete the message and wake up. | 
|  | 814 | */ | 
|  | 815 | static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret) | 
|  | 816 | { | 
|  | 817 | i2c->msg_ptr = 0; | 
|  | 818 | i2c->msg = NULL; | 
|  | 819 | i2c->msg_idx ++; | 
|  | 820 | i2c->msg_num = 0; | 
|  | 821 | if (ret) | 
|  | 822 | i2c->msg_idx = ret; | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 823 | if (!i2c->use_pio) | 
|  | 824 | wake_up(&i2c->wait); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 825 | } | 
|  | 826 |  | 
|  | 827 | static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) | 
|  | 828 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 829 | u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 830 |  | 
|  | 831 | again: | 
|  | 832 | /* | 
|  | 833 | * If ISR_ALD is set, we lost arbitration. | 
|  | 834 | */ | 
|  | 835 | if (isr & ISR_ALD) { | 
|  | 836 | /* | 
|  | 837 | * Do we need to do anything here?  The PXA docs | 
|  | 838 | * are vague about what happens. | 
|  | 839 | */ | 
|  | 840 | i2c_pxa_scream_blue_murder(i2c, "ALD set"); | 
|  | 841 |  | 
|  | 842 | /* | 
|  | 843 | * We ignore this error.  We seem to see spurious ALDs | 
|  | 844 | * for seemingly no reason.  If we handle them as I think | 
|  | 845 | * they should, we end up causing an I2C error, which | 
|  | 846 | * is painful for some systems. | 
|  | 847 | */ | 
|  | 848 | return; /* ignore */ | 
|  | 849 | } | 
|  | 850 |  | 
|  | 851 | if (isr & ISR_BED) { | 
|  | 852 | int ret = BUS_ERROR; | 
|  | 853 |  | 
|  | 854 | /* | 
|  | 855 | * I2C bus error - either the device NAK'd us, or | 
|  | 856 | * something more serious happened.  If we were NAK'd | 
|  | 857 | * on the initial address phase, we can retry. | 
|  | 858 | */ | 
|  | 859 | if (isr & ISR_ACKNAK) { | 
|  | 860 | if (i2c->msg_ptr == 0 && i2c->msg_idx == 0) | 
|  | 861 | ret = I2C_RETRY; | 
|  | 862 | else | 
|  | 863 | ret = XFER_NAKED; | 
|  | 864 | } | 
|  | 865 | i2c_pxa_master_complete(i2c, ret); | 
|  | 866 | } else if (isr & ISR_RWM) { | 
|  | 867 | /* | 
|  | 868 | * Read mode.  We have just sent the address byte, and | 
|  | 869 | * now we must initiate the transfer. | 
|  | 870 | */ | 
|  | 871 | if (i2c->msg_ptr == i2c->msg->len - 1 && | 
|  | 872 | i2c->msg_idx == i2c->msg_num - 1) | 
|  | 873 | icr |= ICR_STOP | ICR_ACKNAK; | 
|  | 874 |  | 
|  | 875 | icr |= ICR_ALDIE | ICR_TB; | 
|  | 876 | } else if (i2c->msg_ptr < i2c->msg->len) { | 
|  | 877 | /* | 
|  | 878 | * Write mode.  Write the next data byte. | 
|  | 879 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 880 | writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 881 |  | 
|  | 882 | icr |= ICR_ALDIE | ICR_TB; | 
|  | 883 |  | 
|  | 884 | /* | 
|  | 885 | * If this is the last byte of the last message, send | 
|  | 886 | * a STOP. | 
|  | 887 | */ | 
|  | 888 | if (i2c->msg_ptr == i2c->msg->len && | 
|  | 889 | i2c->msg_idx == i2c->msg_num - 1) | 
|  | 890 | icr |= ICR_STOP; | 
|  | 891 | } else if (i2c->msg_idx < i2c->msg_num - 1) { | 
|  | 892 | /* | 
|  | 893 | * Next segment of the message. | 
|  | 894 | */ | 
|  | 895 | i2c->msg_ptr = 0; | 
|  | 896 | i2c->msg_idx ++; | 
|  | 897 | i2c->msg++; | 
|  | 898 |  | 
|  | 899 | /* | 
|  | 900 | * If we aren't doing a repeated start and address, | 
|  | 901 | * go back and try to send the next byte.  Note that | 
|  | 902 | * we do not support switching the R/W direction here. | 
|  | 903 | */ | 
|  | 904 | if (i2c->msg->flags & I2C_M_NOSTART) | 
|  | 905 | goto again; | 
|  | 906 |  | 
|  | 907 | /* | 
|  | 908 | * Write the next address. | 
|  | 909 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 910 | writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 911 |  | 
|  | 912 | /* | 
|  | 913 | * And trigger a repeated start, and send the byte. | 
|  | 914 | */ | 
|  | 915 | icr &= ~ICR_ALDIE; | 
|  | 916 | icr |= ICR_START | ICR_TB; | 
|  | 917 | } else { | 
|  | 918 | if (i2c->msg->len == 0) { | 
|  | 919 | /* | 
|  | 920 | * Device probes have a message length of zero | 
|  | 921 | * and need the bus to be reset before it can | 
|  | 922 | * be used again. | 
|  | 923 | */ | 
|  | 924 | i2c_pxa_reset(i2c); | 
|  | 925 | } | 
|  | 926 | i2c_pxa_master_complete(i2c, 0); | 
|  | 927 | } | 
|  | 928 |  | 
|  | 929 | i2c->icrlog[i2c->irqlogidx-1] = icr; | 
|  | 930 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 931 | writel(icr, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 932 | show_state(i2c); | 
|  | 933 | } | 
|  | 934 |  | 
|  | 935 | static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr) | 
|  | 936 | { | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 937 | u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 938 |  | 
|  | 939 | /* | 
|  | 940 | * Read the byte. | 
|  | 941 | */ | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 942 | i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 943 |  | 
|  | 944 | if (i2c->msg_ptr < i2c->msg->len) { | 
|  | 945 | /* | 
|  | 946 | * If this is the last byte of the last | 
|  | 947 | * message, send a STOP. | 
|  | 948 | */ | 
|  | 949 | if (i2c->msg_ptr == i2c->msg->len - 1) | 
|  | 950 | icr |= ICR_STOP | ICR_ACKNAK; | 
|  | 951 |  | 
|  | 952 | icr |= ICR_ALDIE | ICR_TB; | 
|  | 953 | } else { | 
|  | 954 | i2c_pxa_master_complete(i2c, 0); | 
|  | 955 | } | 
|  | 956 |  | 
|  | 957 | i2c->icrlog[i2c->irqlogidx-1] = icr; | 
|  | 958 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 959 | writel(icr, _ICR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 960 | } | 
|  | 961 |  | 
| Sebastian Andrzej Siewior | c66dc52 | 2011-02-23 12:38:18 +0100 | [diff] [blame] | 962 | #define VALID_INT_SOURCE	(ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \ | 
|  | 963 | ISR_SAD | ISR_BED) | 
| David Howells | 7d12e78 | 2006-10-05 14:55:46 +0100 | [diff] [blame] | 964 | static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 965 | { | 
|  | 966 | struct pxa_i2c *i2c = dev_id; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 967 | u32 isr = readl(_ISR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 968 |  | 
| Vasily Khoruzhick | 97491ba | 2011-03-13 15:53:29 +0200 | [diff] [blame] | 969 | if (!(isr & VALID_INT_SOURCE)) | 
| Sebastian Andrzej Siewior | c66dc52 | 2011-02-23 12:38:18 +0100 | [diff] [blame] | 970 | return IRQ_NONE; | 
|  | 971 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 972 | if (i2c_debug > 2 && 0) { | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 973 | dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 974 | __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c))); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 975 | decode_ISR(isr); | 
|  | 976 | } | 
|  | 977 |  | 
| Tobias Klauser | 7e3d7db | 2006-01-09 23:19:51 +0100 | [diff] [blame] | 978 | if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog)) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 979 | i2c->isrlog[i2c->irqlogidx++] = isr; | 
|  | 980 |  | 
|  | 981 | show_state(i2c); | 
|  | 982 |  | 
|  | 983 | /* | 
|  | 984 | * Always clear all pending IRQs. | 
|  | 985 | */ | 
| Vasily Khoruzhick | 97491ba | 2011-03-13 15:53:29 +0200 | [diff] [blame] | 986 | writel(isr & VALID_INT_SOURCE, _ISR(i2c)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 987 |  | 
|  | 988 | if (isr & ISR_SAD) | 
|  | 989 | i2c_pxa_slave_start(i2c, isr); | 
|  | 990 | if (isr & ISR_SSD) | 
|  | 991 | i2c_pxa_slave_stop(i2c); | 
|  | 992 |  | 
|  | 993 | if (i2c_pxa_is_slavemode(i2c)) { | 
|  | 994 | if (isr & ISR_ITE) | 
|  | 995 | i2c_pxa_slave_txempty(i2c, isr); | 
|  | 996 | if (isr & ISR_IRF) | 
|  | 997 | i2c_pxa_slave_rxfull(i2c, isr); | 
|  | 998 | } else if (i2c->msg) { | 
|  | 999 | if (isr & ISR_ITE) | 
|  | 1000 | i2c_pxa_irq_txempty(i2c, isr); | 
|  | 1001 | if (isr & ISR_IRF) | 
|  | 1002 | i2c_pxa_irq_rxfull(i2c, isr); | 
|  | 1003 | } else { | 
|  | 1004 | i2c_pxa_scream_blue_murder(i2c, "spurious irq"); | 
|  | 1005 | } | 
|  | 1006 |  | 
|  | 1007 | return IRQ_HANDLED; | 
|  | 1008 | } | 
|  | 1009 |  | 
|  | 1010 |  | 
|  | 1011 | static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | 
|  | 1012 | { | 
|  | 1013 | struct pxa_i2c *i2c = adap->algo_data; | 
|  | 1014 | int ret, i; | 
|  | 1015 |  | 
|  | 1016 | for (i = adap->retries; i >= 0; i--) { | 
|  | 1017 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | 
|  | 1018 | if (ret != I2C_RETRY) | 
|  | 1019 | goto out; | 
|  | 1020 |  | 
|  | 1021 | if (i2c_debug) | 
| Russell King | 6fd60fa | 2005-09-08 21:04:58 +0100 | [diff] [blame] | 1022 | dev_dbg(&adap->dev, "Retrying transmission\n"); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1023 | udelay(100); | 
|  | 1024 | } | 
|  | 1025 | i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); | 
|  | 1026 | ret = -EREMOTEIO; | 
|  | 1027 | out: | 
|  | 1028 | i2c_pxa_set_slave(i2c, ret); | 
|  | 1029 | return ret; | 
|  | 1030 | } | 
|  | 1031 |  | 
| Russell King | da16e32 | 2005-09-14 22:54:45 +0100 | [diff] [blame] | 1032 | static u32 i2c_pxa_functionality(struct i2c_adapter *adap) | 
|  | 1033 | { | 
|  | 1034 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | 
|  | 1035 | } | 
|  | 1036 |  | 
| Jean Delvare | 8f9082c | 2006-09-03 22:39:46 +0200 | [diff] [blame] | 1037 | static const struct i2c_algorithm i2c_pxa_algorithm = { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1038 | .master_xfer	= i2c_pxa_xfer, | 
| Russell King | da16e32 | 2005-09-14 22:54:45 +0100 | [diff] [blame] | 1039 | .functionality	= i2c_pxa_functionality, | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1040 | }; | 
|  | 1041 |  | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1042 | static const struct i2c_algorithm i2c_pxa_pio_algorithm = { | 
|  | 1043 | .master_xfer	= i2c_pxa_pio_xfer, | 
|  | 1044 | .functionality	= i2c_pxa_functionality, | 
|  | 1045 | }; | 
|  | 1046 |  | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1047 | static int i2c_pxa_probe(struct platform_device *dev) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1048 | { | 
| Enrico Scholz | 6776f3d | 2007-05-21 12:29:40 +0100 | [diff] [blame] | 1049 | struct pxa_i2c *i2c; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1050 | struct resource *res; | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1051 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 
| Marc Kleine-Budde | 21e2ecf | 2010-06-15 10:56:45 +0200 | [diff] [blame] | 1052 | const struct platform_device_id *id = platform_get_device_id(dev); | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 1053 | enum pxa_i2c_types i2c_type = id->driver_data; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1054 | int ret; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1055 | int irq; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1056 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1057 | res = platform_get_resource(dev, IORESOURCE_MEM, 0); | 
|  | 1058 | irq = platform_get_irq(dev, 0); | 
|  | 1059 | if (res == NULL || irq < 0) | 
|  | 1060 | return -ENODEV; | 
|  | 1061 |  | 
| Linus Walleij | c6ffdde | 2009-06-14 00:20:36 +0200 | [diff] [blame] | 1062 | if (!request_mem_region(res->start, resource_size(res), res->name)) | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1063 | return -ENOMEM; | 
|  | 1064 |  | 
| Enrico Scholz | 6776f3d | 2007-05-21 12:29:40 +0100 | [diff] [blame] | 1065 | i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1066 | if (!i2c) { | 
|  | 1067 | ret = -ENOMEM; | 
|  | 1068 | goto emalloc; | 
|  | 1069 | } | 
|  | 1070 |  | 
| Enrico Scholz | 6776f3d | 2007-05-21 12:29:40 +0100 | [diff] [blame] | 1071 | i2c->adap.owner   = THIS_MODULE; | 
| Enrico Scholz | 6776f3d | 2007-05-21 12:29:40 +0100 | [diff] [blame] | 1072 | i2c->adap.retries = 5; | 
|  | 1073 |  | 
|  | 1074 | spin_lock_init(&i2c->lock); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1075 | init_waitqueue_head(&i2c->wait); | 
| Enrico Scholz | 6776f3d | 2007-05-21 12:29:40 +0100 | [diff] [blame] | 1076 |  | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1077 | /* | 
|  | 1078 | * If "dev->id" is negative we consider it as zero. | 
|  | 1079 | * The reason to do so is to avoid sysfs names that only make | 
|  | 1080 | * sense when there are multiple adapters. | 
|  | 1081 | */ | 
| Grant Likely | 488bf31 | 2011-07-25 17:49:43 +0200 | [diff] [blame] | 1082 | i2c->adap.nr = dev->id; | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1083 | snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u", | 
|  | 1084 | i2c->adap.nr); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1085 |  | 
| Russell King | e0d8b13 | 2008-11-11 17:52:32 +0000 | [diff] [blame] | 1086 | i2c->clk = clk_get(&dev->dev, NULL); | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1087 | if (IS_ERR(i2c->clk)) { | 
|  | 1088 | ret = PTR_ERR(i2c->clk); | 
|  | 1089 | goto eclk; | 
|  | 1090 | } | 
|  | 1091 |  | 
| Linus Walleij | c6ffdde | 2009-06-14 00:20:36 +0200 | [diff] [blame] | 1092 | i2c->reg_base = ioremap(res->start, resource_size(res)); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1093 | if (!i2c->reg_base) { | 
|  | 1094 | ret = -EIO; | 
|  | 1095 | goto eremap; | 
|  | 1096 | } | 
| Sebastian Andrzej Siewior | d6668c7 | 2011-02-23 12:38:15 +0100 | [diff] [blame] | 1097 |  | 
|  | 1098 | i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr; | 
|  | 1099 | i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr; | 
|  | 1100 | i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr; | 
|  | 1101 | i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr; | 
| Sebastian Andrzej Siewior | 7e94dd1 | 2011-03-02 11:26:53 +0100 | [diff] [blame] | 1102 | if (i2c_type != REGS_CE4100) | 
|  | 1103 | i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar; | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1104 |  | 
|  | 1105 | i2c->iobase = res->start; | 
| Linus Walleij | c6ffdde | 2009-06-14 00:20:36 +0200 | [diff] [blame] | 1106 | i2c->iosize = resource_size(res); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1107 |  | 
|  | 1108 | i2c->irq = irq; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1109 |  | 
|  | 1110 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; | 
|  | 1111 |  | 
|  | 1112 | #ifdef CONFIG_I2C_PXA_SLAVE | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1113 | if (plat) { | 
|  | 1114 | i2c->slave_addr = plat->slave_addr; | 
| Russell King | beea494 | 2006-11-07 21:03:20 +0000 | [diff] [blame] | 1115 | i2c->slave = plat->slave; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1116 | } | 
|  | 1117 | #endif | 
|  | 1118 |  | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1119 | clk_enable(i2c->clk); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1120 |  | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1121 | if (plat) { | 
|  | 1122 | i2c->adap.class = plat->class; | 
|  | 1123 | i2c->use_pio = plat->use_pio; | 
| Jonathan Cameron | c46c948 | 2008-10-03 15:07:36 +0100 | [diff] [blame] | 1124 | i2c->fast_mode = plat->fast_mode; | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1125 | } | 
|  | 1126 |  | 
|  | 1127 | if (i2c->use_pio) { | 
|  | 1128 | i2c->adap.algo = &i2c_pxa_pio_algorithm; | 
|  | 1129 | } else { | 
|  | 1130 | i2c->adap.algo = &i2c_pxa_algorithm; | 
| Sebastian Andrzej Siewior | c66dc52 | 2011-02-23 12:38:18 +0100 | [diff] [blame] | 1131 | ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED, | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1132 | i2c->adap.name, i2c); | 
|  | 1133 | if (ret) | 
|  | 1134 | goto ereqirq; | 
|  | 1135 | } | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1136 |  | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1137 | i2c_pxa_reset(i2c); | 
|  | 1138 |  | 
|  | 1139 | i2c->adap.algo_data = i2c; | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1140 | i2c->adap.dev.parent = &dev->dev; | 
| Sebastian Andrzej Siewior | baa8cab | 2011-02-23 12:38:20 +0100 | [diff] [blame] | 1141 | #ifdef CONFIG_OF | 
|  | 1142 | i2c->adap.dev.of_node = dev->dev.of_node; | 
|  | 1143 | #endif | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1144 |  | 
| Grant Likely | 488bf31 | 2011-07-25 17:49:43 +0200 | [diff] [blame] | 1145 | ret = i2c_add_numbered_adapter(&i2c->adap); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1146 | if (ret < 0) { | 
|  | 1147 | printk(KERN_INFO "I2C: Failed to add bus\n"); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1148 | goto eadapt; | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1149 | } | 
| Sebastian Andrzej Siewior | baa8cab | 2011-02-23 12:38:20 +0100 | [diff] [blame] | 1150 | of_i2c_register_devices(&i2c->adap); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1151 |  | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1152 | platform_set_drvdata(dev, i2c); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1153 |  | 
|  | 1154 | #ifdef CONFIG_I2C_PXA_SLAVE | 
|  | 1155 | printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", | 
| Jean Delvare | 22e965c | 2009-01-07 14:29:16 +0100 | [diff] [blame] | 1156 | dev_name(&i2c->adap.dev), i2c->slave_addr); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1157 | #else | 
|  | 1158 | printk(KERN_INFO "I2C: %s: PXA I2C adapter\n", | 
| Jean Delvare | 22e965c | 2009-01-07 14:29:16 +0100 | [diff] [blame] | 1159 | dev_name(&i2c->adap.dev)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1160 | #endif | 
|  | 1161 | return 0; | 
|  | 1162 |  | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1163 | eadapt: | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1164 | if (!i2c->use_pio) | 
|  | 1165 | free_irq(irq, i2c); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1166 | ereqirq: | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1167 | clk_disable(i2c->clk); | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1168 | iounmap(i2c->reg_base); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1169 | eremap: | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1170 | clk_put(i2c->clk); | 
|  | 1171 | eclk: | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1172 | kfree(i2c); | 
|  | 1173 | emalloc: | 
| Linus Walleij | c6ffdde | 2009-06-14 00:20:36 +0200 | [diff] [blame] | 1174 | release_mem_region(res->start, resource_size(res)); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1175 | return ret; | 
|  | 1176 | } | 
|  | 1177 |  | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1178 | static int __exit i2c_pxa_remove(struct platform_device *dev) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1179 | { | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1180 | struct pxa_i2c *i2c = platform_get_drvdata(dev); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1181 |  | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1182 | platform_set_drvdata(dev, NULL); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1183 |  | 
|  | 1184 | i2c_del_adapter(&i2c->adap); | 
| Mike Rapoport | b7a3670 | 2008-01-27 18:14:50 +0100 | [diff] [blame] | 1185 | if (!i2c->use_pio) | 
|  | 1186 | free_irq(i2c->irq, i2c); | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1187 |  | 
|  | 1188 | clk_disable(i2c->clk); | 
|  | 1189 | clk_put(i2c->clk); | 
| Russell King | c3cef3f | 2007-08-20 10:19:10 +0100 | [diff] [blame] | 1190 |  | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1191 | iounmap(i2c->reg_base); | 
| Guennadi Liakhovetski | a7b4e55 | 2007-02-08 09:43:26 +0100 | [diff] [blame] | 1192 | release_mem_region(i2c->iobase, i2c->iosize); | 
|  | 1193 | kfree(i2c); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1194 |  | 
|  | 1195 | return 0; | 
|  | 1196 | } | 
|  | 1197 |  | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1198 | #ifdef CONFIG_PM | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1199 | static int i2c_pxa_suspend_noirq(struct device *dev) | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1200 | { | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1201 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 1202 | struct pxa_i2c *i2c = platform_get_drvdata(pdev); | 
|  | 1203 |  | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1204 | clk_disable(i2c->clk); | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1205 |  | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1206 | return 0; | 
|  | 1207 | } | 
|  | 1208 |  | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1209 | static int i2c_pxa_resume_noirq(struct device *dev) | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1210 | { | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1211 | struct platform_device *pdev = to_platform_device(dev); | 
|  | 1212 | struct pxa_i2c *i2c = platform_get_drvdata(pdev); | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1213 |  | 
|  | 1214 | clk_enable(i2c->clk); | 
|  | 1215 | i2c_pxa_reset(i2c); | 
|  | 1216 |  | 
|  | 1217 | return 0; | 
|  | 1218 | } | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1219 |  | 
| Alexey Dobriyan | 4714521 | 2009-12-14 18:00:08 -0800 | [diff] [blame] | 1220 | static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1221 | .suspend_noirq = i2c_pxa_suspend_noirq, | 
|  | 1222 | .resume_noirq = i2c_pxa_resume_noirq, | 
|  | 1223 | }; | 
|  | 1224 |  | 
|  | 1225 | #define I2C_PXA_DEV_PM_OPS (&i2c_pxa_dev_pm_ops) | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1226 | #else | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1227 | #define I2C_PXA_DEV_PM_OPS NULL | 
| Russell King | e7d48fa | 2008-08-26 10:40:50 +0100 | [diff] [blame] | 1228 | #endif | 
|  | 1229 |  | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1230 | static struct platform_driver i2c_pxa_driver = { | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1231 | .probe		= i2c_pxa_probe, | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1232 | .remove		= __exit_p(i2c_pxa_remove), | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1233 | .driver		= { | 
|  | 1234 | .name	= "pxa2xx-i2c", | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1235 | .owner	= THIS_MODULE, | 
| Magnus Damm | 57f4d4f | 2009-07-08 13:22:39 +0200 | [diff] [blame] | 1236 | .pm	= I2C_PXA_DEV_PM_OPS, | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1237 | }, | 
| Eric Miao | f23d491 | 2009-04-13 14:43:25 +0800 | [diff] [blame] | 1238 | .id_table	= i2c_pxa_id_table, | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1239 | }; | 
|  | 1240 |  | 
|  | 1241 | static int __init i2c_adap_pxa_init(void) | 
|  | 1242 | { | 
| Russell King | 3ae5eae | 2005-11-09 22:32:44 +0000 | [diff] [blame] | 1243 | return platform_driver_register(&i2c_pxa_driver); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1244 | } | 
|  | 1245 |  | 
| Wolfram Sang | a92b36e | 2008-02-24 20:03:42 +0100 | [diff] [blame] | 1246 | static void __exit i2c_adap_pxa_exit(void) | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1247 | { | 
| Holger Schurig | d6a7b5f | 2008-02-11 16:51:41 +0100 | [diff] [blame] | 1248 | platform_driver_unregister(&i2c_pxa_driver); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1249 | } | 
|  | 1250 |  | 
| Richard Purdie | ece5f7b | 2006-01-12 16:30:23 +0000 | [diff] [blame] | 1251 | MODULE_LICENSE("GPL"); | 
| Kay Sievers | add8eda | 2008-04-22 22:16:49 +0200 | [diff] [blame] | 1252 | MODULE_ALIAS("platform:pxa2xx-i2c"); | 
| Richard Purdie | ece5f7b | 2006-01-12 16:30:23 +0000 | [diff] [blame] | 1253 |  | 
| Uli Luckas | 47a9b13 | 2008-07-14 22:38:30 +0200 | [diff] [blame] | 1254 | subsys_initcall(i2c_adap_pxa_init); | 
| Russell King | b652b43 | 2005-06-15 12:38:14 +0100 | [diff] [blame] | 1255 | module_exit(i2c_adap_pxa_exit); |