Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/mfd/htc-i2cpld.c
15111 views
1
/*
2
* htc-i2cpld.c
3
* Chip driver for an unknown CPLD chip found on omap850 HTC devices like
4
* the HTC Wizard and HTC Herald.
5
* The cpld is located on the i2c bus and acts as an input/output GPIO
6
* extender.
7
*
8
* Copyright (C) 2009 Cory Maccarrone <[email protected]>
9
*
10
* Based on work done in the linwizard project
11
* Copyright (C) 2008-2009 Angelo Arrifano <[email protected]>
12
*
13
* This program is free software; you can redistribute it and/or modify
14
* it under the terms of the GNU General Public License as published by
15
* the Free Software Foundation; either version 2 of the License, or
16
* (at your option) any later version.
17
*
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
* GNU General Public License for more details.
22
*
23
* You should have received a copy of the GNU General Public License
24
* along with this program; if not, write to the Free Software
25
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
*/
27
28
#include <linux/kernel.h>
29
#include <linux/init.h>
30
#include <linux/module.h>
31
#include <linux/interrupt.h>
32
#include <linux/platform_device.h>
33
#include <linux/i2c.h>
34
#include <linux/irq.h>
35
#include <linux/spinlock.h>
36
#include <linux/htcpld.h>
37
#include <linux/gpio.h>
38
#include <linux/slab.h>
39
40
struct htcpld_chip {
41
spinlock_t lock;
42
43
/* chip info */
44
u8 reset;
45
u8 addr;
46
struct device *dev;
47
struct i2c_client *client;
48
49
/* Output details */
50
u8 cache_out;
51
struct gpio_chip chip_out;
52
53
/* Input details */
54
u8 cache_in;
55
struct gpio_chip chip_in;
56
57
u16 irqs_enabled;
58
uint irq_start;
59
int nirqs;
60
61
unsigned int flow_type;
62
/*
63
* Work structure to allow for setting values outside of any
64
* possible interrupt context
65
*/
66
struct work_struct set_val_work;
67
};
68
69
struct htcpld_data {
70
/* irq info */
71
u16 irqs_enabled;
72
uint irq_start;
73
int nirqs;
74
uint chained_irq;
75
unsigned int int_reset_gpio_hi;
76
unsigned int int_reset_gpio_lo;
77
78
/* htcpld info */
79
struct htcpld_chip *chip;
80
unsigned int nchips;
81
};
82
83
/* There does not appear to be a way to proactively mask interrupts
84
* on the htcpld chip itself. So, we simply ignore interrupts that
85
* aren't desired. */
86
static void htcpld_mask(struct irq_data *data)
87
{
88
struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
89
chip->irqs_enabled &= ~(1 << (data->irq - chip->irq_start));
90
pr_debug("HTCPLD mask %d %04x\n", data->irq, chip->irqs_enabled);
91
}
92
static void htcpld_unmask(struct irq_data *data)
93
{
94
struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
95
chip->irqs_enabled |= 1 << (data->irq - chip->irq_start);
96
pr_debug("HTCPLD unmask %d %04x\n", data->irq, chip->irqs_enabled);
97
}
98
99
static int htcpld_set_type(struct irq_data *data, unsigned int flags)
100
{
101
struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
102
103
if (flags & ~IRQ_TYPE_SENSE_MASK)
104
return -EINVAL;
105
106
/* We only allow edge triggering */
107
if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
108
return -EINVAL;
109
110
chip->flow_type = flags;
111
return 0;
112
}
113
114
static struct irq_chip htcpld_muxed_chip = {
115
.name = "htcpld",
116
.irq_mask = htcpld_mask,
117
.irq_unmask = htcpld_unmask,
118
.irq_set_type = htcpld_set_type,
119
};
120
121
/* To properly dispatch IRQ events, we need to read from the
122
* chip. This is an I2C action that could possibly sleep
123
* (which is bad in interrupt context) -- so we use a threaded
124
* interrupt handler to get around that.
125
*/
126
static irqreturn_t htcpld_handler(int irq, void *dev)
127
{
128
struct htcpld_data *htcpld = dev;
129
unsigned int i;
130
unsigned long flags;
131
int irqpin;
132
133
if (!htcpld) {
134
pr_debug("htcpld is null in ISR\n");
135
return IRQ_HANDLED;
136
}
137
138
/*
139
* For each chip, do a read of the chip and trigger any interrupts
140
* desired. The interrupts will be triggered from LSB to MSB (i.e.
141
* bit 0 first, then bit 1, etc.)
142
*
143
* For chips that have no interrupt range specified, just skip 'em.
144
*/
145
for (i = 0; i < htcpld->nchips; i++) {
146
struct htcpld_chip *chip = &htcpld->chip[i];
147
struct i2c_client *client;
148
int val;
149
unsigned long uval, old_val;
150
151
if (!chip) {
152
pr_debug("chip %d is null in ISR\n", i);
153
continue;
154
}
155
156
if (chip->nirqs == 0)
157
continue;
158
159
client = chip->client;
160
if (!client) {
161
pr_debug("client %d is null in ISR\n", i);
162
continue;
163
}
164
165
/* Scan the chip */
166
val = i2c_smbus_read_byte_data(client, chip->cache_out);
167
if (val < 0) {
168
/* Throw a warning and skip this chip */
169
dev_warn(chip->dev, "Unable to read from chip: %d\n",
170
val);
171
continue;
172
}
173
174
uval = (unsigned long)val;
175
176
spin_lock_irqsave(&chip->lock, flags);
177
178
/* Save away the old value so we can compare it */
179
old_val = chip->cache_in;
180
181
/* Write the new value */
182
chip->cache_in = uval;
183
184
spin_unlock_irqrestore(&chip->lock, flags);
185
186
/*
187
* For each bit in the data (starting at bit 0), trigger
188
* associated interrupts.
189
*/
190
for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
191
unsigned oldb, newb, type = chip->flow_type;
192
193
irq = chip->irq_start + irqpin;
194
195
/* Run the IRQ handler, but only if the bit value
196
* changed, and the proper flags are set */
197
oldb = (old_val >> irqpin) & 1;
198
newb = (uval >> irqpin) & 1;
199
200
if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) ||
201
(oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) {
202
pr_debug("fire IRQ %d\n", irqpin);
203
generic_handle_irq(irq);
204
}
205
}
206
}
207
208
/*
209
* In order to continue receiving interrupts, the int_reset_gpio must
210
* be asserted.
211
*/
212
if (htcpld->int_reset_gpio_hi)
213
gpio_set_value(htcpld->int_reset_gpio_hi, 1);
214
if (htcpld->int_reset_gpio_lo)
215
gpio_set_value(htcpld->int_reset_gpio_lo, 0);
216
217
return IRQ_HANDLED;
218
}
219
220
/*
221
* The GPIO set routines can be called from interrupt context, especially if,
222
* for example they're attached to the led-gpio framework and a trigger is
223
* enabled. As such, we declared work above in the htcpld_chip structure,
224
* and that work is scheduled in the set routine. The kernel can then run
225
* the I2C functions, which will sleep, in process context.
226
*/
227
static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
228
{
229
struct i2c_client *client;
230
struct htcpld_chip *chip_data;
231
unsigned long flags;
232
233
chip_data = container_of(chip, struct htcpld_chip, chip_out);
234
if (!chip_data)
235
return;
236
237
client = chip_data->client;
238
if (client == NULL)
239
return;
240
241
spin_lock_irqsave(&chip_data->lock, flags);
242
if (val)
243
chip_data->cache_out |= (1 << offset);
244
else
245
chip_data->cache_out &= ~(1 << offset);
246
spin_unlock_irqrestore(&chip_data->lock, flags);
247
248
schedule_work(&(chip_data->set_val_work));
249
}
250
251
static void htcpld_chip_set_ni(struct work_struct *work)
252
{
253
struct htcpld_chip *chip_data;
254
struct i2c_client *client;
255
256
chip_data = container_of(work, struct htcpld_chip, set_val_work);
257
client = chip_data->client;
258
i2c_smbus_read_byte_data(client, chip_data->cache_out);
259
}
260
261
static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
262
{
263
struct htcpld_chip *chip_data;
264
int val = 0;
265
int is_input = 0;
266
267
/* Try out first */
268
chip_data = container_of(chip, struct htcpld_chip, chip_out);
269
if (!chip_data) {
270
/* Try in */
271
is_input = 1;
272
chip_data = container_of(chip, struct htcpld_chip, chip_in);
273
if (!chip_data)
274
return -EINVAL;
275
}
276
277
/* Determine if this is an input or output GPIO */
278
if (!is_input)
279
/* Use the output cache */
280
val = (chip_data->cache_out >> offset) & 1;
281
else
282
/* Use the input cache */
283
val = (chip_data->cache_in >> offset) & 1;
284
285
if (val)
286
return 1;
287
else
288
return 0;
289
}
290
291
static int htcpld_direction_output(struct gpio_chip *chip,
292
unsigned offset, int value)
293
{
294
htcpld_chip_set(chip, offset, value);
295
return 0;
296
}
297
298
static int htcpld_direction_input(struct gpio_chip *chip,
299
unsigned offset)
300
{
301
/*
302
* No-op: this function can only be called on the input chip.
303
* We do however make sure the offset is within range.
304
*/
305
return (offset < chip->ngpio) ? 0 : -EINVAL;
306
}
307
308
static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
309
{
310
struct htcpld_chip *chip_data;
311
312
chip_data = container_of(chip, struct htcpld_chip, chip_in);
313
314
if (offset < chip_data->nirqs)
315
return chip_data->irq_start + offset;
316
else
317
return -EINVAL;
318
}
319
320
static void htcpld_chip_reset(struct i2c_client *client)
321
{
322
struct htcpld_chip *chip_data = i2c_get_clientdata(client);
323
if (!chip_data)
324
return;
325
326
i2c_smbus_read_byte_data(
327
client, (chip_data->cache_out = chip_data->reset));
328
}
329
330
static int __devinit htcpld_setup_chip_irq(
331
struct platform_device *pdev,
332
int chip_index)
333
{
334
struct htcpld_data *htcpld;
335
struct device *dev = &pdev->dev;
336
struct htcpld_core_platform_data *pdata;
337
struct htcpld_chip *chip;
338
struct htcpld_chip_platform_data *plat_chip_data;
339
unsigned int irq, irq_end;
340
int ret = 0;
341
342
/* Get the platform and driver data */
343
pdata = dev->platform_data;
344
htcpld = platform_get_drvdata(pdev);
345
chip = &htcpld->chip[chip_index];
346
plat_chip_data = &pdata->chip[chip_index];
347
348
/* Setup irq handlers */
349
irq_end = chip->irq_start + chip->nirqs;
350
for (irq = chip->irq_start; irq < irq_end; irq++) {
351
irq_set_chip_and_handler(irq, &htcpld_muxed_chip,
352
handle_simple_irq);
353
irq_set_chip_data(irq, chip);
354
#ifdef CONFIG_ARM
355
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
356
#else
357
irq_set_probe(irq);
358
#endif
359
}
360
361
return ret;
362
}
363
364
static int __devinit htcpld_register_chip_i2c(
365
struct platform_device *pdev,
366
int chip_index)
367
{
368
struct htcpld_data *htcpld;
369
struct device *dev = &pdev->dev;
370
struct htcpld_core_platform_data *pdata;
371
struct htcpld_chip *chip;
372
struct htcpld_chip_platform_data *plat_chip_data;
373
struct i2c_adapter *adapter;
374
struct i2c_client *client;
375
struct i2c_board_info info;
376
377
/* Get the platform and driver data */
378
pdata = dev->platform_data;
379
htcpld = platform_get_drvdata(pdev);
380
chip = &htcpld->chip[chip_index];
381
plat_chip_data = &pdata->chip[chip_index];
382
383
adapter = i2c_get_adapter(pdata->i2c_adapter_id);
384
if (adapter == NULL) {
385
/* Eek, no such I2C adapter! Bail out. */
386
dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
387
plat_chip_data->addr, pdata->i2c_adapter_id);
388
return -ENODEV;
389
}
390
391
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
392
dev_warn(dev, "i2c adapter %d non-functional\n",
393
pdata->i2c_adapter_id);
394
return -EINVAL;
395
}
396
397
memset(&info, 0, sizeof(struct i2c_board_info));
398
info.addr = plat_chip_data->addr;
399
strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
400
info.platform_data = chip;
401
402
/* Add the I2C device. This calls the probe() function. */
403
client = i2c_new_device(adapter, &info);
404
if (!client) {
405
/* I2C device registration failed, contineu with the next */
406
dev_warn(dev, "Unable to add I2C device for 0x%x\n",
407
plat_chip_data->addr);
408
return -ENODEV;
409
}
410
411
i2c_set_clientdata(client, chip);
412
snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
413
chip->client = client;
414
415
/* Reset the chip */
416
htcpld_chip_reset(client);
417
chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
418
419
return 0;
420
}
421
422
static void __devinit htcpld_unregister_chip_i2c(
423
struct platform_device *pdev,
424
int chip_index)
425
{
426
struct htcpld_data *htcpld;
427
struct htcpld_chip *chip;
428
429
/* Get the platform and driver data */
430
htcpld = platform_get_drvdata(pdev);
431
chip = &htcpld->chip[chip_index];
432
433
if (chip->client)
434
i2c_unregister_device(chip->client);
435
}
436
437
static int __devinit htcpld_register_chip_gpio(
438
struct platform_device *pdev,
439
int chip_index)
440
{
441
struct htcpld_data *htcpld;
442
struct device *dev = &pdev->dev;
443
struct htcpld_core_platform_data *pdata;
444
struct htcpld_chip *chip;
445
struct htcpld_chip_platform_data *plat_chip_data;
446
struct gpio_chip *gpio_chip;
447
int ret = 0;
448
449
/* Get the platform and driver data */
450
pdata = dev->platform_data;
451
htcpld = platform_get_drvdata(pdev);
452
chip = &htcpld->chip[chip_index];
453
plat_chip_data = &pdata->chip[chip_index];
454
455
/* Setup the GPIO chips */
456
gpio_chip = &(chip->chip_out);
457
gpio_chip->label = "htcpld-out";
458
gpio_chip->dev = dev;
459
gpio_chip->owner = THIS_MODULE;
460
gpio_chip->get = htcpld_chip_get;
461
gpio_chip->set = htcpld_chip_set;
462
gpio_chip->direction_input = NULL;
463
gpio_chip->direction_output = htcpld_direction_output;
464
gpio_chip->base = plat_chip_data->gpio_out_base;
465
gpio_chip->ngpio = plat_chip_data->num_gpios;
466
467
gpio_chip = &(chip->chip_in);
468
gpio_chip->label = "htcpld-in";
469
gpio_chip->dev = dev;
470
gpio_chip->owner = THIS_MODULE;
471
gpio_chip->get = htcpld_chip_get;
472
gpio_chip->set = NULL;
473
gpio_chip->direction_input = htcpld_direction_input;
474
gpio_chip->direction_output = NULL;
475
gpio_chip->to_irq = htcpld_chip_to_irq;
476
gpio_chip->base = plat_chip_data->gpio_in_base;
477
gpio_chip->ngpio = plat_chip_data->num_gpios;
478
479
/* Add the GPIO chips */
480
ret = gpiochip_add(&(chip->chip_out));
481
if (ret) {
482
dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
483
plat_chip_data->addr, ret);
484
return ret;
485
}
486
487
ret = gpiochip_add(&(chip->chip_in));
488
if (ret) {
489
int error;
490
491
dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
492
plat_chip_data->addr, ret);
493
494
error = gpiochip_remove(&(chip->chip_out));
495
if (error)
496
dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error);
497
498
return ret;
499
}
500
501
return 0;
502
}
503
504
static int __devinit htcpld_setup_chips(struct platform_device *pdev)
505
{
506
struct htcpld_data *htcpld;
507
struct device *dev = &pdev->dev;
508
struct htcpld_core_platform_data *pdata;
509
int i;
510
511
/* Get the platform and driver data */
512
pdata = dev->platform_data;
513
htcpld = platform_get_drvdata(pdev);
514
515
/* Setup each chip's output GPIOs */
516
htcpld->nchips = pdata->num_chip;
517
htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
518
GFP_KERNEL);
519
if (!htcpld->chip) {
520
dev_warn(dev, "Unable to allocate memory for chips\n");
521
return -ENOMEM;
522
}
523
524
/* Add the chips as best we can */
525
for (i = 0; i < htcpld->nchips; i++) {
526
int ret;
527
528
/* Setup the HTCPLD chips */
529
htcpld->chip[i].reset = pdata->chip[i].reset;
530
htcpld->chip[i].cache_out = pdata->chip[i].reset;
531
htcpld->chip[i].cache_in = 0;
532
htcpld->chip[i].dev = dev;
533
htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
534
htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
535
536
INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
537
spin_lock_init(&(htcpld->chip[i].lock));
538
539
/* Setup the interrupts for the chip */
540
if (htcpld->chained_irq) {
541
ret = htcpld_setup_chip_irq(pdev, i);
542
if (ret)
543
continue;
544
}
545
546
/* Register the chip with I2C */
547
ret = htcpld_register_chip_i2c(pdev, i);
548
if (ret)
549
continue;
550
551
552
/* Register the chips with the GPIO subsystem */
553
ret = htcpld_register_chip_gpio(pdev, i);
554
if (ret) {
555
/* Unregister the chip from i2c and continue */
556
htcpld_unregister_chip_i2c(pdev, i);
557
continue;
558
}
559
560
dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
561
}
562
563
return 0;
564
}
565
566
static int __devinit htcpld_core_probe(struct platform_device *pdev)
567
{
568
struct htcpld_data *htcpld;
569
struct device *dev = &pdev->dev;
570
struct htcpld_core_platform_data *pdata;
571
struct resource *res;
572
int ret = 0;
573
574
if (!dev)
575
return -ENODEV;
576
577
pdata = dev->platform_data;
578
if (!pdata) {
579
dev_warn(dev, "Platform data not found for htcpld core!\n");
580
return -ENXIO;
581
}
582
583
htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
584
if (!htcpld)
585
return -ENOMEM;
586
587
/* Find chained irq */
588
ret = -EINVAL;
589
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
590
if (res) {
591
int flags;
592
htcpld->chained_irq = res->start;
593
594
/* Setup the chained interrupt handler */
595
flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
596
ret = request_threaded_irq(htcpld->chained_irq,
597
NULL, htcpld_handler,
598
flags, pdev->name, htcpld);
599
if (ret) {
600
dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
601
goto fail;
602
} else
603
device_init_wakeup(dev, 0);
604
}
605
606
/* Set the driver data */
607
platform_set_drvdata(pdev, htcpld);
608
609
/* Setup the htcpld chips */
610
ret = htcpld_setup_chips(pdev);
611
if (ret)
612
goto fail;
613
614
/* Request the GPIO(s) for the int reset and set them up */
615
if (pdata->int_reset_gpio_hi) {
616
ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
617
if (ret) {
618
/*
619
* If it failed, that sucks, but we can probably
620
* continue on without it.
621
*/
622
dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
623
htcpld->int_reset_gpio_hi = 0;
624
} else {
625
htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
626
gpio_set_value(htcpld->int_reset_gpio_hi, 1);
627
}
628
}
629
630
if (pdata->int_reset_gpio_lo) {
631
ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
632
if (ret) {
633
/*
634
* If it failed, that sucks, but we can probably
635
* continue on without it.
636
*/
637
dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
638
htcpld->int_reset_gpio_lo = 0;
639
} else {
640
htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
641
gpio_set_value(htcpld->int_reset_gpio_lo, 0);
642
}
643
}
644
645
dev_info(dev, "Initialized successfully\n");
646
return 0;
647
648
fail:
649
kfree(htcpld);
650
return ret;
651
}
652
653
/* The I2C Driver -- used internally */
654
static const struct i2c_device_id htcpld_chip_id[] = {
655
{ "htcpld-chip", 0 },
656
{ }
657
};
658
MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
659
660
661
static struct i2c_driver htcpld_chip_driver = {
662
.driver = {
663
.name = "htcpld-chip",
664
},
665
.id_table = htcpld_chip_id,
666
};
667
668
/* The Core Driver */
669
static struct platform_driver htcpld_core_driver = {
670
.driver = {
671
.name = "i2c-htcpld",
672
},
673
};
674
675
static int __init htcpld_core_init(void)
676
{
677
int ret;
678
679
/* Register the I2C Chip driver */
680
ret = i2c_add_driver(&htcpld_chip_driver);
681
if (ret)
682
return ret;
683
684
/* Probe for our chips */
685
return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
686
}
687
688
static void __exit htcpld_core_exit(void)
689
{
690
i2c_del_driver(&htcpld_chip_driver);
691
platform_driver_unregister(&htcpld_core_driver);
692
}
693
694
module_init(htcpld_core_init);
695
module_exit(htcpld_core_exit);
696
697
MODULE_AUTHOR("Cory Maccarrone <[email protected]>");
698
MODULE_DESCRIPTION("I2C HTC PLD Driver");
699
MODULE_LICENSE("GPL");
700
701
702