Blame view

drivers/mfd/asic3.c 26.8 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
fa9ff4b18   Samuel Ortiz   ASIC3 driver
2
3
4
5
6
  /*
   * driver/mfd/asic3.c
   *
   * Compaq ASIC3 support.
   *
fa9ff4b18   Samuel Ortiz   ASIC3 driver
7
8
   * Copyright 2001 Compaq Computer Corporation.
   * Copyright 2004-2005 Phil Blundell
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
9
   * Copyright 2007-2008 OpenedHand Ltd.
fa9ff4b18   Samuel Ortiz   ASIC3 driver
10
11
12
   *
   * Authors: Phil Blundell <pb@handhelds.org>,
   *	    Samuel Ortiz <sameo@openedhand.com>
fa9ff4b18   Samuel Ortiz   ASIC3 driver
13
   */
fa9ff4b18   Samuel Ortiz   ASIC3 driver
14
  #include <linux/kernel.h>
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
15
  #include <linux/delay.h>
fa9ff4b18   Samuel Ortiz   ASIC3 driver
16
  #include <linux/irq.h>
5cd690a30   Linus Walleij   mfd: asic3: Inclu...
17
  #include <linux/gpio/driver.h>
5d4a357d8   Paul Gortmaker   mfd: Add export.h...
18
  #include <linux/export.h>
fa9ff4b18   Samuel Ortiz   ASIC3 driver
19
  #include <linux/io.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
20
  #include <linux/slab.h>
fa9ff4b18   Samuel Ortiz   ASIC3 driver
21
22
23
24
  #include <linux/spinlock.h>
  #include <linux/platform_device.h>
  
  #include <linux/mfd/asic3.h>
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
25
26
  #include <linux/mfd/core.h>
  #include <linux/mfd/ds1wm.h>
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
27
  #include <linux/mfd/tmio.h>
fa9ff4b18   Samuel Ortiz   ASIC3 driver
28

4eb1d7fcb   Robert Jarzmik   mfd: asic3: Fix b...
29
  #include <linux/mmc/host.h>
e956a2a87   Philipp Zabel   mfd: asic3: add c...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  enum {
  	ASIC3_CLOCK_SPI,
  	ASIC3_CLOCK_OWM,
  	ASIC3_CLOCK_PWM0,
  	ASIC3_CLOCK_PWM1,
  	ASIC3_CLOCK_LED0,
  	ASIC3_CLOCK_LED1,
  	ASIC3_CLOCK_LED2,
  	ASIC3_CLOCK_SD_HOST,
  	ASIC3_CLOCK_SD_BUS,
  	ASIC3_CLOCK_SMBUS,
  	ASIC3_CLOCK_EX0,
  	ASIC3_CLOCK_EX1,
  };
  
  struct asic3_clk {
  	int enabled;
  	unsigned int cdex;
  	unsigned long rate;
  };
  
  #define INIT_CDEX(_name, _rate)	\
  	[ASIC3_CLOCK_##_name] = {		\
  		.cdex = CLOCK_CDEX_##_name,	\
  		.rate = _rate,			\
  	}
59f2ad2e0   Mark Brown   mfd: Staticise un...
56
  static struct asic3_clk asic3_clk_init[] __initdata = {
e956a2a87   Philipp Zabel   mfd: asic3: add c...
57
58
59
60
61
62
63
64
65
66
67
68
69
  	INIT_CDEX(SPI, 0),
  	INIT_CDEX(OWM, 5000000),
  	INIT_CDEX(PWM0, 0),
  	INIT_CDEX(PWM1, 0),
  	INIT_CDEX(LED0, 0),
  	INIT_CDEX(LED1, 0),
  	INIT_CDEX(LED2, 0),
  	INIT_CDEX(SD_HOST, 24576000),
  	INIT_CDEX(SD_BUS, 12288000),
  	INIT_CDEX(SMBUS, 0),
  	INIT_CDEX(EX0, 32768),
  	INIT_CDEX(EX1, 24576000),
  };
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
70
71
72
73
74
  struct asic3 {
  	void __iomem *mapping;
  	unsigned int bus_shift;
  	unsigned int irq_nr;
  	unsigned int irq_base;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
75
  	raw_spinlock_t lock;
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
76
77
78
  	u16 irq_bothedge[4];
  	struct gpio_chip gpio;
  	struct device *dev;
64e8867ba   Ian Molton   mfd: tmio_mmc har...
79
  	void __iomem *tmio_cnf;
e956a2a87   Philipp Zabel   mfd: asic3: add c...
80
81
  
  	struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
82
83
84
  };
  
  static int asic3_gpio_get(struct gpio_chip *chip, unsigned offset);
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
85
  void asic3_write_register(struct asic3 *asic, unsigned int reg, u32 value)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
86
  {
b32661e06   Al Viro   mfd/asic3: ioread...
87
  	iowrite16(value, asic->mapping +
fa9ff4b18   Samuel Ortiz   ASIC3 driver
88
89
  		  (reg >> asic->bus_shift));
  }
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
90
  EXPORT_SYMBOL_GPL(asic3_write_register);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
91

13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
92
  u32 asic3_read_register(struct asic3 *asic, unsigned int reg)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
93
  {
b32661e06   Al Viro   mfd/asic3: ioread...
94
  	return ioread16(asic->mapping +
fa9ff4b18   Samuel Ortiz   ASIC3 driver
95
96
  			(reg >> asic->bus_shift));
  }
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
97
  EXPORT_SYMBOL_GPL(asic3_read_register);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
98

59f2ad2e0   Mark Brown   mfd: Staticise un...
99
  static void asic3_set_register(struct asic3 *asic, u32 reg, u32 bits, bool set)
6483c1b5e   Philipp Zabel   mfd: asic3: add a...
100
101
102
  {
  	unsigned long flags;
  	u32 val;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
103
  	raw_spin_lock_irqsave(&asic->lock, flags);
6483c1b5e   Philipp Zabel   mfd: asic3: add a...
104
105
106
107
108
109
  	val = asic3_read_register(asic, reg);
  	if (set)
  		val |= bits;
  	else
  		val &= ~bits;
  	asic3_write_register(asic, reg, val);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
110
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
6483c1b5e   Philipp Zabel   mfd: asic3: add a...
111
  }
fa9ff4b18   Samuel Ortiz   ASIC3 driver
112
113
  /* IRQs */
  #define MAX_ASIC_ISR_LOOPS    20
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
114
115
  #define ASIC3_GPIO_BASE_INCR \
  	(ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
116
117
118
119
120
121
  
  static void asic3_irq_flip_edge(struct asic3 *asic,
  				u32 base, int bit)
  {
  	u16 edge;
  	unsigned long flags;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
122
  	raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
123
  	edge = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
124
  				   base + ASIC3_GPIO_EDGE_TRIGGER);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
125
126
  	edge ^= bit;
  	asic3_write_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
127
  			     base + ASIC3_GPIO_EDGE_TRIGGER, edge);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
128
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
129
  }
bd0b9ac40   Thomas Gleixner   genirq: Remove ir...
130
  static void asic3_irq_demux(struct irq_desc *desc)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
131
  {
52a7d6077   Thomas Gleixner   mfd: asic3: Clean...
132
133
  	struct asic3 *asic = irq_desc_get_handler_data(desc);
  	struct irq_data *data = irq_desc_get_irq_data(desc);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
134
135
  	int iter, i;
  	unsigned long flags;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
136

a09aee8b6   Axel Lin   mfd: Fix asic3 bu...
137
  	data->chip->irq_ack(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
138
139
140
141
  
  	for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
  		u32 status;
  		int bank;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
142
  		raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
143
  		status = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
144
  					     ASIC3_OFFSET(INTR, P_INT_STAT));
93ad44719   Julia Cartwright   mfd: asic3: Make ...
145
  		raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
146
147
148
149
150
151
152
153
154
  
  		/* Check all ten register bits */
  		if ((status & 0x3ff) == 0)
  			break;
  
  		/* Handle GPIO IRQs */
  		for (bank = 0; bank < ASIC3_NUM_GPIO_BANKS; bank++) {
  			if (status & (1 << bank)) {
  				unsigned long base, istat;
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
155
156
  				base = ASIC3_GPIO_A_BASE
  				       + bank * ASIC3_GPIO_BASE_INCR;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
157
  				raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
158
159
  				istat = asic3_read_register(asic,
  							    base +
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
160
  							    ASIC3_GPIO_INT_STATUS);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
161
162
163
  				/* Clearing IntStatus */
  				asic3_write_register(asic,
  						     base +
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
164
  						     ASIC3_GPIO_INT_STATUS, 0);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
165
  				raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
166
167
168
169
170
171
172
173
174
175
176
  
  				for (i = 0; i < ASIC3_GPIOS_PER_BANK; i++) {
  					int bit = (1 << i);
  					unsigned int irqnr;
  
  					if (!(istat & bit))
  						continue;
  
  					irqnr = asic->irq_base +
  						(ASIC3_GPIOS_PER_BANK * bank)
  						+ i;
52a7d6077   Thomas Gleixner   mfd: asic3: Clean...
177
  					generic_handle_irq(irqnr);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
178
179
180
181
182
183
184
185
186
187
  					if (asic->irq_bothedge[bank] & bit)
  						asic3_irq_flip_edge(asic, base,
  								    bit);
  				}
  			}
  		}
  
  		/* Handle remaining IRQs in the status register */
  		for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
  			/* They start at bit 4 and go up */
52a7d6077   Thomas Gleixner   mfd: asic3: Clean...
188
189
  			if (status & (1 << (i - ASIC3_NUM_GPIOS + 4)))
  				generic_handle_irq(asic->irq_base + i);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
190
191
192
193
  		}
  	}
  
  	if (iter >= MAX_ASIC_ISR_LOOPS)
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
194
195
  		dev_err(asic->dev, "interrupt processing overrun
  ");
fa9ff4b18   Samuel Ortiz   ASIC3 driver
196
197
198
199
200
201
202
  }
  
  static inline int asic3_irq_to_bank(struct asic3 *asic, int irq)
  {
  	int n;
  
  	n = (irq - asic->irq_base) >> 4;
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
203
  	return (n * (ASIC3_GPIO_B_BASE - ASIC3_GPIO_A_BASE));
fa9ff4b18   Samuel Ortiz   ASIC3 driver
204
205
206
207
208
209
  }
  
  static inline int asic3_irq_to_index(struct asic3 *asic, int irq)
  {
  	return (irq - asic->irq_base) & 0xf;
  }
0f76aaebe   Mark Brown   mfd: Convert ASIC...
210
  static void asic3_mask_gpio_irq(struct irq_data *data)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
211
  {
0f76aaebe   Mark Brown   mfd: Convert ASIC...
212
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
213
214
  	u32 val, bank, index;
  	unsigned long flags;
0f76aaebe   Mark Brown   mfd: Convert ASIC...
215
216
  	bank = asic3_irq_to_bank(asic, data->irq);
  	index = asic3_irq_to_index(asic, data->irq);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
217

93ad44719   Julia Cartwright   mfd: asic3: Make ...
218
  	raw_spin_lock_irqsave(&asic->lock, flags);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
219
  	val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
220
  	val |= 1 << index;
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
221
  	asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
222
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
223
  }
0f76aaebe   Mark Brown   mfd: Convert ASIC...
224
  static void asic3_mask_irq(struct irq_data *data)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
225
  {
0f76aaebe   Mark Brown   mfd: Convert ASIC...
226
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
227
228
  	int regval;
  	unsigned long flags;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
229
  	raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
230
  	regval = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
231
232
  				     ASIC3_INTR_BASE +
  				     ASIC3_INTR_INT_MASK);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
233
234
  
  	regval &= ~(ASIC3_INTMASK_MASK0 <<
0f76aaebe   Mark Brown   mfd: Convert ASIC...
235
  		    (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
fa9ff4b18   Samuel Ortiz   ASIC3 driver
236
237
  
  	asic3_write_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
238
239
  			     ASIC3_INTR_BASE +
  			     ASIC3_INTR_INT_MASK,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
240
  			     regval);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
241
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
242
  }
0f76aaebe   Mark Brown   mfd: Convert ASIC...
243
  static void asic3_unmask_gpio_irq(struct irq_data *data)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
244
  {
0f76aaebe   Mark Brown   mfd: Convert ASIC...
245
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
246
247
  	u32 val, bank, index;
  	unsigned long flags;
0f76aaebe   Mark Brown   mfd: Convert ASIC...
248
249
  	bank = asic3_irq_to_bank(asic, data->irq);
  	index = asic3_irq_to_index(asic, data->irq);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
250

93ad44719   Julia Cartwright   mfd: asic3: Make ...
251
  	raw_spin_lock_irqsave(&asic->lock, flags);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
252
  	val = asic3_read_register(asic, bank + ASIC3_GPIO_MASK);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
253
  	val &= ~(1 << index);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
254
  	asic3_write_register(asic, bank + ASIC3_GPIO_MASK, val);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
255
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
256
  }
0f76aaebe   Mark Brown   mfd: Convert ASIC...
257
  static void asic3_unmask_irq(struct irq_data *data)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
258
  {
0f76aaebe   Mark Brown   mfd: Convert ASIC...
259
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
260
261
  	int regval;
  	unsigned long flags;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
262
  	raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
263
  	regval = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
264
265
  				     ASIC3_INTR_BASE +
  				     ASIC3_INTR_INT_MASK);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
266
267
  
  	regval |= (ASIC3_INTMASK_MASK0 <<
0f76aaebe   Mark Brown   mfd: Convert ASIC...
268
  		   (data->irq - (asic->irq_base + ASIC3_NUM_GPIOS)));
fa9ff4b18   Samuel Ortiz   ASIC3 driver
269
270
  
  	asic3_write_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
271
272
  			     ASIC3_INTR_BASE +
  			     ASIC3_INTR_INT_MASK,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
273
  			     regval);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
274
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
275
  }
0f76aaebe   Mark Brown   mfd: Convert ASIC...
276
  static int asic3_gpio_irq_type(struct irq_data *data, unsigned int type)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
277
  {
0f76aaebe   Mark Brown   mfd: Convert ASIC...
278
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
279
280
281
  	u32 bank, index;
  	u16 trigger, level, edge, bit;
  	unsigned long flags;
0f76aaebe   Mark Brown   mfd: Convert ASIC...
282
283
  	bank = asic3_irq_to_bank(asic, data->irq);
  	index = asic3_irq_to_index(asic, data->irq);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
284
  	bit = 1<<index;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
285
  	raw_spin_lock_irqsave(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
286
  	level = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
287
  				    bank + ASIC3_GPIO_LEVEL_TRIGGER);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
288
  	edge = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
289
  				   bank + ASIC3_GPIO_EDGE_TRIGGER);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
290
  	trigger = asic3_read_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
291
  				      bank + ASIC3_GPIO_TRIGGER_TYPE);
0f76aaebe   Mark Brown   mfd: Convert ASIC...
292
  	asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] &= ~bit;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
293

6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
294
  	if (type == IRQ_TYPE_EDGE_RISING) {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
295
296
  		trigger |= bit;
  		edge |= bit;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
297
  	} else if (type == IRQ_TYPE_EDGE_FALLING) {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
298
299
  		trigger |= bit;
  		edge &= ~bit;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
300
  	} else if (type == IRQ_TYPE_EDGE_BOTH) {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
301
  		trigger |= bit;
0f76aaebe   Mark Brown   mfd: Convert ASIC...
302
  		if (asic3_gpio_get(&asic->gpio, data->irq - asic->irq_base))
fa9ff4b18   Samuel Ortiz   ASIC3 driver
303
304
305
  			edge &= ~bit;
  		else
  			edge |= bit;
0f76aaebe   Mark Brown   mfd: Convert ASIC...
306
  		asic->irq_bothedge[(data->irq - asic->irq_base) >> 4] |= bit;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
307
  	} else if (type == IRQ_TYPE_LEVEL_LOW) {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
308
309
  		trigger &= ~bit;
  		level &= ~bit;
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
310
  	} else if (type == IRQ_TYPE_LEVEL_HIGH) {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
311
312
313
314
  		trigger &= ~bit;
  		level |= bit;
  	} else {
  		/*
6cab48602   Dmitry Eremin-Solenikov   [ARM] 5179/1: Rep...
315
  		 * if type == IRQ_TYPE_NONE, we should mask interrupts, but
fa9ff4b18   Samuel Ortiz   ASIC3 driver
316
317
318
  		 * be careful to not unmask them if mask was also called.
  		 * Probably need internal state for mask.
  		 */
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
319
320
  		dev_notice(asic->dev, "irq type not changed
  ");
fa9ff4b18   Samuel Ortiz   ASIC3 driver
321
  	}
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
322
  	asic3_write_register(asic, bank + ASIC3_GPIO_LEVEL_TRIGGER,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
323
  			     level);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
324
  	asic3_write_register(asic, bank + ASIC3_GPIO_EDGE_TRIGGER,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
325
  			     edge);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
326
  	asic3_write_register(asic, bank + ASIC3_GPIO_TRIGGER_TYPE,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
327
  			     trigger);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
328
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
329
330
  	return 0;
  }
2fe372fc2   Paul Parsons   mfd: Avoid unbala...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  static int asic3_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
  {
  	struct asic3 *asic = irq_data_get_irq_chip_data(data);
  	u32 bank, index;
  	u16 bit;
  
  	bank = asic3_irq_to_bank(asic, data->irq);
  	index = asic3_irq_to_index(asic, data->irq);
  	bit = 1<<index;
  
  	asic3_set_register(asic, bank + ASIC3_GPIO_SLEEP_MASK, bit, !on);
  
  	return 0;
  }
fa9ff4b18   Samuel Ortiz   ASIC3 driver
345
346
  static struct irq_chip asic3_gpio_irq_chip = {
  	.name		= "ASIC3-GPIO",
0f76aaebe   Mark Brown   mfd: Convert ASIC...
347
348
349
350
  	.irq_ack	= asic3_mask_gpio_irq,
  	.irq_mask	= asic3_mask_gpio_irq,
  	.irq_unmask	= asic3_unmask_gpio_irq,
  	.irq_set_type	= asic3_gpio_irq_type,
2fe372fc2   Paul Parsons   mfd: Avoid unbala...
351
  	.irq_set_wake	= asic3_gpio_irq_set_wake,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
352
353
354
355
  };
  
  static struct irq_chip asic3_irq_chip = {
  	.name		= "ASIC3",
0f76aaebe   Mark Brown   mfd: Convert ASIC...
356
357
358
  	.irq_ack	= asic3_mask_irq,
  	.irq_mask	= asic3_mask_irq,
  	.irq_unmask	= asic3_unmask_irq,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
359
  };
065032f61   Philipp Zabel   mfd: move asic3 p...
360
  static int __init asic3_irq_probe(struct platform_device *pdev)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
361
362
363
364
  {
  	struct asic3 *asic = platform_get_drvdata(pdev);
  	unsigned long clksel = 0;
  	unsigned int irq, irq_base;
c491b2ffa   Roel Kluin   asic3: platform_g...
365
  	int ret;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
366

c491b2ffa   Roel Kluin   asic3: platform_g...
367
368
369
370
  	ret = platform_get_irq(pdev, 0);
  	if (ret < 0)
  		return ret;
  	asic->irq_nr = ret;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
371
372
373
374
375
376
377
378
379
380
  
  	/* turn on clock to IRQ controller */
  	clksel |= CLOCK_SEL_CX;
  	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
  			     clksel);
  
  	irq_base = asic->irq_base;
  
  	for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
  		if (irq < asic->irq_base + ASIC3_NUM_GPIOS)
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
381
  			irq_set_chip(irq, &asic3_gpio_irq_chip);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
382
  		else
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
383
  			irq_set_chip(irq, &asic3_irq_chip);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
384

d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
385
386
  		irq_set_chip_data(irq, asic);
  		irq_set_handler(irq, handle_level_irq);
9bd09f345   Rob Herring   mfd: Kill off set...
387
  		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
388
  	}
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
389
  	asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK),
fa9ff4b18   Samuel Ortiz   ASIC3 driver
390
  			     ASIC3_INTMASK_GINTMASK);
c30e30478   Thomas Gleixner   mfd/asic3: Fix ra...
391
  	irq_set_chained_handler_and_data(asic->irq_nr, asic3_irq_demux, asic);
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
392
  	irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
393
394
395
396
397
398
399
400
401
402
403
404
  
  	return 0;
  }
  
  static void asic3_irq_remove(struct platform_device *pdev)
  {
  	struct asic3 *asic = platform_get_drvdata(pdev);
  	unsigned int irq, irq_base;
  
  	irq_base = asic->irq_base;
  
  	for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
9bd09f345   Rob Herring   mfd: Kill off set...
405
  		irq_set_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
d6f7ce9f7   Thomas Gleixner   mfd: Fold irq_set...
406
  		irq_set_chip_and_handler(irq, NULL, NULL);
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
407
  		irq_set_chip_data(irq, NULL);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
408
  	}
d5bb12216   Thomas Gleixner   mfd: Cleanup irq ...
409
  	irq_set_chained_handler(asic->irq_nr, NULL);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
410
411
412
  }
  
  /* GPIOs */
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
413
414
415
416
417
418
419
  static int asic3_gpio_direction(struct gpio_chip *chip,
  				unsigned offset, int out)
  {
  	u32 mask = ASIC3_GPIO_TO_MASK(offset), out_reg;
  	unsigned int gpio_base;
  	unsigned long flags;
  	struct asic3 *asic;
082cc4683   Linus Walleij   mfd: asic3: Use g...
420
  	asic = gpiochip_get_data(chip);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
421
  	gpio_base = ASIC3_GPIO_TO_BASE(offset);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
422
  	if (gpio_base > ASIC3_GPIO_D_BASE) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
423
424
425
  		dev_err(asic->dev, "Invalid base (0x%x) for gpio %d
  ",
  			gpio_base, offset);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
426
427
  		return -EINVAL;
  	}
93ad44719   Julia Cartwright   mfd: asic3: Make ...
428
  	raw_spin_lock_irqsave(&asic->lock, flags);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
429

3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
430
  	out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_DIRECTION);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
431
432
433
434
435
436
  
  	/* Input is 0, Output is 1 */
  	if (out)
  		out_reg |= mask;
  	else
  		out_reg &= ~mask;
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
437
  	asic3_write_register(asic, gpio_base + ASIC3_GPIO_DIRECTION, out_reg);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
438

93ad44719   Julia Cartwright   mfd: asic3: Make ...
439
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
  
  	return 0;
  
  }
  
  static int asic3_gpio_direction_input(struct gpio_chip *chip,
  				      unsigned offset)
  {
  	return asic3_gpio_direction(chip, offset, 0);
  }
  
  static int asic3_gpio_direction_output(struct gpio_chip *chip,
  				       unsigned offset, int value)
  {
  	return asic3_gpio_direction(chip, offset, 1);
  }
  
  static int asic3_gpio_get(struct gpio_chip *chip,
  			  unsigned offset)
  {
  	unsigned int gpio_base;
  	u32 mask = ASIC3_GPIO_TO_MASK(offset);
  	struct asic3 *asic;
082cc4683   Linus Walleij   mfd: asic3: Use g...
463
  	asic = gpiochip_get_data(chip);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
464
  	gpio_base = ASIC3_GPIO_TO_BASE(offset);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
465
  	if (gpio_base > ASIC3_GPIO_D_BASE) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
466
467
468
  		dev_err(asic->dev, "Invalid base (0x%x) for gpio %d
  ",
  			gpio_base, offset);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
469
470
  		return -EINVAL;
  	}
f8e3a514b   Linus Walleij   mfd: asic3: Be su...
471
472
  	return !!(asic3_read_register(asic,
  				      gpio_base + ASIC3_GPIO_STATUS) & mask);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
473
474
475
476
477
478
479
480
481
  }
  
  static void asic3_gpio_set(struct gpio_chip *chip,
  			   unsigned offset, int value)
  {
  	u32 mask, out_reg;
  	unsigned int gpio_base;
  	unsigned long flags;
  	struct asic3 *asic;
082cc4683   Linus Walleij   mfd: asic3: Use g...
482
  	asic = gpiochip_get_data(chip);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
483
  	gpio_base = ASIC3_GPIO_TO_BASE(offset);
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
484
  	if (gpio_base > ASIC3_GPIO_D_BASE) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
485
486
487
  		dev_err(asic->dev, "Invalid base (0x%x) for gpio %d
  ",
  			gpio_base, offset);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
488
489
490
491
  		return;
  	}
  
  	mask = ASIC3_GPIO_TO_MASK(offset);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
492
  	raw_spin_lock_irqsave(&asic->lock, flags);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
493

3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
494
  	out_reg = asic3_read_register(asic, gpio_base + ASIC3_GPIO_OUT);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
495
496
497
498
499
  
  	if (value)
  		out_reg |= mask;
  	else
  		out_reg &= ~mask;
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
500
  	asic3_write_register(asic, gpio_base + ASIC3_GPIO_OUT, out_reg);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
501

93ad44719   Julia Cartwright   mfd: asic3: Make ...
502
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
503
  }
450b11510   Paul Parsons   mfd: Add to_irq()...
504
505
  static int asic3_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
  {
082cc4683   Linus Walleij   mfd: asic3: Use g...
506
  	struct asic3 *asic = gpiochip_get_data(chip);
02269ab10   Dmitry Artamonow   mfd: Fix asic3_gp...
507

12693f6c1   Samuel Ortiz   mfd: No need to c...
508
  	return asic->irq_base + offset;
450b11510   Paul Parsons   mfd: Add to_irq()...
509
  }
065032f61   Philipp Zabel   mfd: move asic3 p...
510
511
  static __init int asic3_gpio_probe(struct platform_device *pdev,
  				   u16 *gpio_config, int num)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
512
  {
fa9ff4b18   Samuel Ortiz   ASIC3 driver
513
  	struct asic3 *asic = platform_get_drvdata(pdev);
3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
514
515
516
517
  	u16 alt_reg[ASIC3_NUM_GPIO_BANKS];
  	u16 out_reg[ASIC3_NUM_GPIO_BANKS];
  	u16 dir_reg[ASIC3_NUM_GPIO_BANKS];
  	int i;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
518

59f0cb0fd   Russell King   [ARM] remove memz...
519
520
521
  	memset(alt_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
  	memset(out_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
  	memset(dir_reg, 0, ASIC3_NUM_GPIO_BANKS * sizeof(u16));
3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
522
523
  
  	/* Enable all GPIOs */
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
524
525
526
527
  	asic3_write_register(asic, ASIC3_GPIO_OFFSET(A, MASK), 0xffff);
  	asic3_write_register(asic, ASIC3_GPIO_OFFSET(B, MASK), 0xffff);
  	asic3_write_register(asic, ASIC3_GPIO_OFFSET(C, MASK), 0xffff);
  	asic3_write_register(asic, ASIC3_GPIO_OFFSET(D, MASK), 0xffff);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
528

3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
  	for (i = 0; i < num; i++) {
  		u8 alt, pin, dir, init, bank_num, bit_num;
  		u16 config = gpio_config[i];
  
  		pin = ASIC3_CONFIG_GPIO_PIN(config);
  		alt = ASIC3_CONFIG_GPIO_ALT(config);
  		dir = ASIC3_CONFIG_GPIO_DIR(config);
  		init = ASIC3_CONFIG_GPIO_INIT(config);
  
  		bank_num = ASIC3_GPIO_TO_BANK(pin);
  		bit_num = ASIC3_GPIO_TO_BIT(pin);
  
  		alt_reg[bank_num] |= (alt << bit_num);
  		out_reg[bank_num] |= (init << bit_num);
  		dir_reg[bank_num] |= (dir << bit_num);
  	}
  
  	for (i = 0; i < ASIC3_NUM_GPIO_BANKS; i++) {
  		asic3_write_register(asic,
  				     ASIC3_BANK_TO_BASE(i) +
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
549
  				     ASIC3_GPIO_DIRECTION,
3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
550
551
  				     dir_reg[i]);
  		asic3_write_register(asic,
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
552
  				     ASIC3_BANK_TO_BASE(i) + ASIC3_GPIO_OUT,
3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
553
554
555
  				     out_reg[i]);
  		asic3_write_register(asic,
  				     ASIC3_BANK_TO_BASE(i) +
3b8139f8b   Samuel Ortiz   mfd: Use uppercas...
556
  				     ASIC3_GPIO_ALT_FUNCTION,
3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
557
  				     alt_reg[i]);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
558
  	}
082cc4683   Linus Walleij   mfd: asic3: Use g...
559
  	return gpiochip_add_data(&asic->gpio, asic);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
560
  }
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
561
  static int asic3_gpio_remove(struct platform_device *pdev)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
562
  {
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
563
  	struct asic3 *asic = platform_get_drvdata(pdev);
88d5e520a   abdoulaye berthe   driver:gpio remov...
564
565
  	gpiochip_remove(&asic->gpio);
  	return 0;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
566
  }
c29a81270   Paul Parsons   mfd: Make asic3_c...
567
  static void asic3_clk_enable(struct asic3 *asic, struct asic3_clk *clk)
e956a2a87   Philipp Zabel   mfd: asic3: add c...
568
569
570
  {
  	unsigned long flags;
  	u32 cdex;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
571
  	raw_spin_lock_irqsave(&asic->lock, flags);
e956a2a87   Philipp Zabel   mfd: asic3: add c...
572
573
574
575
576
  	if (clk->enabled++ == 0) {
  		cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
  		cdex |= clk->cdex;
  		asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
  	}
93ad44719   Julia Cartwright   mfd: asic3: Make ...
577
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
e956a2a87   Philipp Zabel   mfd: asic3: add c...
578
579
580
581
582
583
584
585
  }
  
  static void asic3_clk_disable(struct asic3 *asic, struct asic3_clk *clk)
  {
  	unsigned long flags;
  	u32 cdex;
  
  	WARN_ON(clk->enabled == 0);
93ad44719   Julia Cartwright   mfd: asic3: Make ...
586
  	raw_spin_lock_irqsave(&asic->lock, flags);
e956a2a87   Philipp Zabel   mfd: asic3: add c...
587
588
589
590
591
  	if (--clk->enabled == 0) {
  		cdex = asic3_read_register(asic, ASIC3_OFFSET(CLOCK, CDEX));
  		cdex &= ~clk->cdex;
  		asic3_write_register(asic, ASIC3_OFFSET(CLOCK, CDEX), cdex);
  	}
93ad44719   Julia Cartwright   mfd: asic3: Make ...
592
  	raw_spin_unlock_irqrestore(&asic->lock, flags);
e956a2a87   Philipp Zabel   mfd: asic3: add c...
593
  }
fa9ff4b18   Samuel Ortiz   ASIC3 driver
594

9461f65a8   Philipp Zabel   mfd: asic3: enabl...
595
596
597
  /* MFD cells (SPI, PWM, LED, DS1WM, MMC) */
  static struct ds1wm_driver_data ds1wm_pdata = {
  	.active_high = 1,
f607e7fc5   Jean-François Dagenais   w1: ds1wm: add a ...
598
  	.reset_recover_delay = 1,
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
599
600
601
602
603
604
605
606
607
608
  };
  
  static struct resource ds1wm_resources[] = {
  	{
  		.start = ASIC3_OWM_BASE,
  		.end   = ASIC3_OWM_BASE + 0x13,
  		.flags = IORESOURCE_MEM,
  	},
  	{
  		.start = ASIC3_IRQ_OWM,
fe421425d   Mark Brown   mfd: Correct ASIC...
609
  		.end   = ASIC3_IRQ_OWM,
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
610
611
612
613
614
615
616
617
618
619
620
621
  		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
  	},
  };
  
  static int ds1wm_enable(struct platform_device *pdev)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	/* Turn on external clocks and the OWM clock */
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
622
  	usleep_range(1000, 5000);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
623
624
625
626
  
  	/* Reset and enable DS1WM */
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
  			   ASIC3_EXTCF_OWM_RESET, 1);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
627
  	usleep_range(1000, 5000);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
628
629
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, RESET),
  			   ASIC3_EXTCF_OWM_RESET, 0);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
630
  	usleep_range(1000, 5000);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
631
632
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  			   ASIC3_EXTCF_OWM_EN, 1);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
633
  	usleep_range(1000, 5000);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  
  	return 0;
  }
  
  static int ds1wm_disable(struct platform_device *pdev)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  			   ASIC3_EXTCF_OWM_EN, 0);
  
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_OWM]);
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
  
  	return 0;
  }
5ac98553a   Geert Uytterhoeven   mfd: Constify str...
651
  static const struct mfd_cell asic3_cell_ds1wm = {
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
652
653
654
  	.name          = "ds1wm",
  	.enable        = ds1wm_enable,
  	.disable       = ds1wm_disable,
121ea573a   Samuel Ortiz   w1: Use device pl...
655
656
  	.platform_data = &ds1wm_pdata,
  	.pdata_size    = sizeof(ds1wm_pdata),
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
657
658
659
  	.num_resources = ARRAY_SIZE(ds1wm_resources),
  	.resources     = ds1wm_resources,
  };
64e8867ba   Ian Molton   mfd: tmio_mmc har...
660
661
662
663
664
665
666
667
668
669
670
671
672
  static void asic3_mmc_pwr(struct platform_device *pdev, int state)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state);
  }
  
  static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state);
  }
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
673
  static struct tmio_mmc_data asic3_mmc_data = {
64e8867ba   Ian Molton   mfd: tmio_mmc har...
674
  	.hclk           = 24576000,
4eb1d7fcb   Robert Jarzmik   mfd: asic3: Fix b...
675
  	.ocr_mask	= MMC_VDD_32_33 | MMC_VDD_33_34,
64e8867ba   Ian Molton   mfd: tmio_mmc har...
676
677
  	.set_pwr        = asic3_mmc_pwr,
  	.set_clk_div    = asic3_mmc_clk_div,
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
678
679
680
681
682
683
684
685
686
  };
  
  static struct resource asic3_mmc_resources[] = {
  	{
  		.start = ASIC3_SD_CTRL_BASE,
  		.end   = ASIC3_SD_CTRL_BASE + 0x3ff,
  		.flags = IORESOURCE_MEM,
  	},
  	{
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
  		.start = 0,
  		.end   = 0,
  		.flags = IORESOURCE_IRQ,
  	},
  };
  
  static int asic3_mmc_enable(struct platform_device *pdev)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	/* Not sure if it must be done bit by bit, but leaving as-is */
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_LEVCD, 1);
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_LEVWP, 1);
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_SUSPEND, 0);
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_PCLR, 0);
  
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
  	/* CLK32 used for card detection and for interruption detection
  	 * when HCLK is stopped.
  	 */
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
712
  	usleep_range(1000, 5000);
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
713
714
715
716
717
718
719
  
  	/* HCLK 24.576 MHz, BCLK 12.288 MHz: */
  	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL),
  		CLOCK_SEL_CX | CLOCK_SEL_SD_HCLK_SEL);
  
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
  	asic3_clk_enable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
720
  	usleep_range(1000, 5000);
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
721
722
723
724
725
726
727
  
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  			   ASIC3_EXTCF_SD_MEM_ENABLE, 1);
  
  	/* Enable SD card slot 3.3V power supply */
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_SDPWR, 1);
64e8867ba   Ian Molton   mfd: tmio_mmc har...
728
729
730
  	/* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */
  	tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift,
  			     ASIC3_SD_CTRL_BASE >> 1);
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  	return 0;
  }
  
  static int asic3_mmc_disable(struct platform_device *pdev)
  {
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	/* Put in suspend mode */
  	asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
  			   ASIC3_SDHWCTRL_SUSPEND, 1);
  
  	/* Disable clocks */
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_HOST]);
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_SD_BUS]);
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX0]);
  	asic3_clk_disable(asic, &asic->clocks[ASIC3_CLOCK_EX1]);
  	return 0;
  }
5ac98553a   Geert Uytterhoeven   mfd: Constify str...
749
  static const struct mfd_cell asic3_cell_mmc = {
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
750
751
752
  	.name          = "tmio-mmc",
  	.enable        = asic3_mmc_enable,
  	.disable       = asic3_mmc_disable,
3c6e36537   Paul Parsons   mfd: Fix asic3 ba...
753
754
  	.suspend       = asic3_mmc_disable,
  	.resume        = asic3_mmc_enable,
ec71974f2   Samuel Ortiz   mmc: Use device p...
755
756
  	.platform_data = &asic3_mmc_data,
  	.pdata_size    = sizeof(asic3_mmc_data),
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
757
758
759
  	.num_resources = ARRAY_SIZE(asic3_mmc_resources),
  	.resources     = asic3_mmc_resources,
  };
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  static const int clock_ledn[ASIC3_NUM_LEDS] = {
  	[0] = ASIC3_CLOCK_LED0,
  	[1] = ASIC3_CLOCK_LED1,
  	[2] = ASIC3_CLOCK_LED2,
  };
  
  static int asic3_leds_enable(struct platform_device *pdev)
  {
  	const struct mfd_cell *cell = mfd_get_cell(pdev);
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	asic3_clk_enable(asic, &asic->clocks[clock_ledn[cell->id]]);
  
  	return 0;
  }
  
  static int asic3_leds_disable(struct platform_device *pdev)
  {
  	const struct mfd_cell *cell = mfd_get_cell(pdev);
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
  
  	return 0;
  }
e0b13b5b6   Paul Parsons   mfd: Add asic3 ba...
785
786
787
788
789
790
  static int asic3_leds_suspend(struct platform_device *pdev)
  {
  	const struct mfd_cell *cell = mfd_get_cell(pdev);
  	struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
  
  	while (asic3_gpio_get(&asic->gpio, ASIC3_GPIO(C, cell->id)) != 0)
d43c4290f   Lee Jones   mfd: asic3: Fix a...
791
  		usleep_range(1000, 5000);
e0b13b5b6   Paul Parsons   mfd: Add asic3 ba...
792
793
794
795
796
  
  	asic3_clk_disable(asic, &asic->clocks[clock_ledn[cell->id]]);
  
  	return 0;
  }
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
797
798
799
800
801
802
  static struct mfd_cell asic3_cell_leds[ASIC3_NUM_LEDS] = {
  	[0] = {
  		.name          = "leds-asic3",
  		.id            = 0,
  		.enable        = asic3_leds_enable,
  		.disable       = asic3_leds_disable,
e0b13b5b6   Paul Parsons   mfd: Add asic3 ba...
803
804
  		.suspend       = asic3_leds_suspend,
  		.resume        = asic3_leds_enable,
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
805
806
807
808
809
810
  	},
  	[1] = {
  		.name          = "leds-asic3",
  		.id            = 1,
  		.enable        = asic3_leds_enable,
  		.disable       = asic3_leds_disable,
e0b13b5b6   Paul Parsons   mfd: Add asic3 ba...
811
812
  		.suspend       = asic3_leds_suspend,
  		.resume        = asic3_leds_enable,
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
813
814
815
816
817
818
  	},
  	[2] = {
  		.name          = "leds-asic3",
  		.id            = 2,
  		.enable        = asic3_leds_enable,
  		.disable       = asic3_leds_disable,
e0b13b5b6   Paul Parsons   mfd: Add asic3 ba...
819
820
  		.suspend       = asic3_leds_suspend,
  		.resume        = asic3_leds_enable,
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
821
822
  	},
  };
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
823
  static int __init asic3_mfd_probe(struct platform_device *pdev,
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
824
  				  struct asic3_platform_data *pdata,
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
825
826
827
  				  struct resource *mem)
  {
  	struct asic3 *asic = platform_get_drvdata(pdev);
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
828
829
830
831
832
833
834
835
836
837
838
839
  	struct resource *mem_sdio;
  	int irq, ret;
  
  	mem_sdio = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  	if (!mem_sdio)
  		dev_dbg(asic->dev, "no SDIO MEM resource
  ");
  
  	irq = platform_get_irq(pdev, 1);
  	if (irq < 0)
  		dev_dbg(asic->dev, "no SDIO IRQ resource
  ");
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
840
841
842
843
844
845
846
  
  	/* DS1WM */
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  			   ASIC3_EXTCF_OWM_SMB, 0);
  
  	ds1wm_resources[0].start >>= asic->bus_shift;
  	ds1wm_resources[0].end   >>= asic->bus_shift;
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
847
  	/* MMC */
44b61a9f2   Sachin Kamat   mfd: asic3: Fix p...
848
  	if (mem_sdio) {
d43c4290f   Lee Jones   mfd: asic3: Fix a...
849
850
  		asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >>
  					  asic->bus_shift) + mem_sdio->start,
74e32d1b6   Paul Parsons   mfd: Fix ASIC3 SD...
851
  				 ASIC3_SD_CONFIG_SIZE >> asic->bus_shift);
44b61a9f2   Sachin Kamat   mfd: asic3: Fix p...
852
853
854
855
856
857
  		if (!asic->tmio_cnf) {
  			ret = -ENOMEM;
  			dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG
  ");
  			goto out;
  		}
64e8867ba   Ian Molton   mfd: tmio_mmc har...
858
  	}
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
859
860
  	asic3_mmc_resources[0].start >>= asic->bus_shift;
  	asic3_mmc_resources[0].end   >>= asic->bus_shift;
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
861

4f304245b   Paul Parsons   mfd: Set asic3 DS...
862
863
864
  	if (pdata->clock_rate) {
  		ds1wm_pdata.clock_rate = pdata->clock_rate;
  		ret = mfd_add_devices(&pdev->dev, pdev->id,
0848c94fb   Mark Brown   mfd: core: Push i...
865
  			&asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
4f304245b   Paul Parsons   mfd: Set asic3 DS...
866
867
868
  		if (ret < 0)
  			goto out;
  	}
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
869

13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
870
  	if (mem_sdio && (irq >= 0)) {
09f05ce85   Philipp Zabel   mfd: asic3: enabl...
871
  		ret = mfd_add_devices(&pdev->dev, pdev->id,
0848c94fb   Mark Brown   mfd: core: Push i...
872
  			&asic3_cell_mmc, 1, mem_sdio, irq, NULL);
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
873
874
875
  		if (ret < 0)
  			goto out;
  	}
b2f0fa828   Arnd Bergmann   mfd/asic3: fix as...
876
  	ret = 0;
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
877
878
879
880
881
882
883
884
  	if (pdata->leds) {
  		int i;
  
  		for (i = 0; i < ASIC3_NUM_LEDS; ++i) {
  			asic3_cell_leds[i].platform_data = &pdata->leds[i];
  			asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);
  		}
  		ret = mfd_add_devices(&pdev->dev, 0,
0848c94fb   Mark Brown   mfd: core: Push i...
885
  			asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
886
  	}
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
887

09f05ce85   Philipp Zabel   mfd: asic3: enabl...
888
   out:
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
889
890
891
892
893
  	return ret;
  }
  
  static void asic3_mfd_remove(struct platform_device *pdev)
  {
64e8867ba   Ian Molton   mfd: tmio_mmc har...
894
  	struct asic3 *asic = platform_get_drvdata(pdev);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
895
  	mfd_remove_devices(&pdev->dev);
64e8867ba   Ian Molton   mfd: tmio_mmc har...
896
  	iounmap(asic->tmio_cnf);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
897
  }
fa9ff4b18   Samuel Ortiz   ASIC3 driver
898
  /* Core */
065032f61   Philipp Zabel   mfd: move asic3 p...
899
  static int __init asic3_probe(struct platform_device *pdev)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
900
  {
334a41ce9   Jingoo Han   mfd: Use dev_get_...
901
  	struct asic3_platform_data *pdata = dev_get_platdata(&pdev->dev);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
902
903
904
  	struct asic3 *asic;
  	struct resource *mem;
  	unsigned long clksel;
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
905
  	int ret = 0;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
906

1cee87fdf   Lee Jones   mfd: asic3: Conve...
907
908
  	asic = devm_kzalloc(&pdev->dev,
  			    sizeof(struct asic3), GFP_KERNEL);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
909
  	if (!asic)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
910
  		return -ENOMEM;
93ad44719   Julia Cartwright   mfd: asic3: Make ...
911
  	raw_spin_lock_init(&asic->lock);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
912
913
914
915
916
  	platform_set_drvdata(pdev, asic);
  	asic->dev = &pdev->dev;
  
  	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!mem) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
917
918
  		dev_err(asic->dev, "no MEM resource
  ");
1cee87fdf   Lee Jones   mfd: asic3: Conve...
919
  		return -ENOMEM;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
920
  	}
be584bd5a   Philipp Zabel   mfd: asic3: use r...
921
  	asic->mapping = ioremap(mem->start, resource_size(mem));
fa9ff4b18   Samuel Ortiz   ASIC3 driver
922
  	if (!asic->mapping) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
923
924
  		dev_err(asic->dev, "Couldn't ioremap
  ");
1cee87fdf   Lee Jones   mfd: asic3: Conve...
925
  		return -ENOMEM;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
926
927
928
  	}
  
  	asic->irq_base = pdata->irq_base;
99cdb0c8c   Philipp Zabel   mfd: let asic3 us...
929
  	/* calculate bus shift from mem resource */
be584bd5a   Philipp Zabel   mfd: asic3: use r...
930
  	asic->bus_shift = 2 - (resource_size(mem) >> 12);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
931
932
933
934
935
936
  
  	clksel = 0;
  	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), clksel);
  
  	ret = asic3_irq_probe(pdev);
  	if (ret < 0) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
937
938
  		dev_err(asic->dev, "Couldn't probe IRQs
  ");
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
939
940
  		goto out_unmap;
  	}
d8e4a88b7   Paul Parsons   mfd: Define asic3...
941
  	asic->gpio.label = "asic3";
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
942
943
944
945
946
947
  	asic->gpio.base = pdata->gpio_base;
  	asic->gpio.ngpio = ASIC3_NUM_GPIOS;
  	asic->gpio.get = asic3_gpio_get;
  	asic->gpio.set = asic3_gpio_set;
  	asic->gpio.direction_input = asic3_gpio_direction_input;
  	asic->gpio.direction_output = asic3_gpio_direction_output;
450b11510   Paul Parsons   mfd: Add to_irq()...
948
  	asic->gpio.to_irq = asic3_gpio_to_irq;
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
949

3b26bf172   Samuel Ortiz   mfd: New asic3 gp...
950
951
952
  	ret = asic3_gpio_probe(pdev,
  			       pdata->gpio_config,
  			       pdata->gpio_config_num);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
953
  	if (ret < 0) {
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
954
955
  		dev_err(asic->dev, "GPIO probe failed
  ");
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
956
  		goto out_irq;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
957
  	}
fa9ff4b18   Samuel Ortiz   ASIC3 driver
958

e956a2a87   Philipp Zabel   mfd: asic3: add c...
959
960
961
962
  	/* Making a per-device copy is only needed for the
  	 * theoretical case of multiple ASIC3s on one board:
  	 */
  	memcpy(asic->clocks, asic3_clk_init, sizeof(asic3_clk_init));
13ca4f661   Paul Parsons   mfd: Add ASIC3 LE...
963
  	asic3_mfd_probe(pdev, pdata, mem);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
964

f22a9c6fd   Paul Parsons   mfd: Add PCMCIA/C...
965
966
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  		(ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 1);
24f4f2eef   Samuel Ortiz   mfd: use dev_* ma...
967
968
  	dev_info(asic->dev, "ASIC3 Core driver
  ");
fa9ff4b18   Samuel Ortiz   ASIC3 driver
969
970
  
  	return 0;
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
971
972
973
974
   out_irq:
  	asic3_irq_remove(pdev);
  
   out_unmap:
fa9ff4b18   Samuel Ortiz   ASIC3 driver
975
  	iounmap(asic->mapping);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
976

fa9ff4b18   Samuel Ortiz   ASIC3 driver
977
978
  	return ret;
  }
4740f73fe   Bill Pemberton   mfd: remove use o...
979
  static int asic3_remove(struct platform_device *pdev)
fa9ff4b18   Samuel Ortiz   ASIC3 driver
980
  {
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
981
  	int ret;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
982
  	struct asic3 *asic = platform_get_drvdata(pdev);
f22a9c6fd   Paul Parsons   mfd: Add PCMCIA/C...
983
984
  	asic3_set_register(asic, ASIC3_OFFSET(EXTCF, SELECT),
  		(ASIC3_EXTCF_CF0_BUF_EN|ASIC3_EXTCF_CF0_PWAIT_EN), 0);
9461f65a8   Philipp Zabel   mfd: asic3: enabl...
985
  	asic3_mfd_remove(pdev);
6f2384c4b   Samuel Ortiz   mfd: asic3 gpioli...
986
987
988
  	ret = asic3_gpio_remove(pdev);
  	if (ret < 0)
  		return ret;
fa9ff4b18   Samuel Ortiz   ASIC3 driver
989
990
991
992
993
  	asic3_irq_remove(pdev);
  
  	asic3_write_register(asic, ASIC3_OFFSET(CLOCK, SEL), 0);
  
  	iounmap(asic->mapping);
fa9ff4b18   Samuel Ortiz   ASIC3 driver
994
995
996
997
998
999
1000
1001
1002
1003
1004
  	return 0;
  }
  
  static void asic3_shutdown(struct platform_device *pdev)
  {
  }
  
  static struct platform_driver asic3_device_driver = {
  	.driver		= {
  		.name	= "asic3",
  	},
84449216b   Bill Pemberton   mfd: remove use o...
1005
  	.remove		= asic3_remove,
fa9ff4b18   Samuel Ortiz   ASIC3 driver
1006
1007
1008
1009
1010
1011
  	.shutdown	= asic3_shutdown,
  };
  
  static int __init asic3_init(void)
  {
  	int retval = 0;
d43c4290f   Lee Jones   mfd: asic3: Fix a...
1012

065032f61   Philipp Zabel   mfd: move asic3 p...
1013
  	retval = platform_driver_probe(&asic3_device_driver, asic3_probe);
d43c4290f   Lee Jones   mfd: asic3: Fix a...
1014

fa9ff4b18   Samuel Ortiz   ASIC3 driver
1015
1016
1017
1018
  	return retval;
  }
  
  subsys_initcall(asic3_init);