Linux 3.17-rc4
[deliverable/linux.git] / drivers / pinctrl / pinctrl-baytrail.c
CommitLineData
a5d811bb
MN
1/*
2 * Pinctrl GPIO driver for Intel Baytrail
3 * Copyright (c) 2012-2013, Intel Corporation.
4 *
5 * Author: Mathias Nyman <mathias.nyman@linux.intel.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 */
21
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/init.h>
25#include <linux/types.h>
26#include <linux/bitops.h>
27#include <linux/interrupt.h>
a5d811bb 28#include <linux/gpio.h>
a5d811bb 29#include <linux/acpi.h>
a5d811bb
MN
30#include <linux/platform_device.h>
31#include <linux/seq_file.h>
32#include <linux/io.h>
33#include <linux/pm_runtime.h>
34#include <linux/pinctrl/pinctrl.h>
35
36/* memory mapped register offsets */
37#define BYT_CONF0_REG 0x000
38#define BYT_CONF1_REG 0x004
39#define BYT_VAL_REG 0x008
40#define BYT_DFT_REG 0x00c
41#define BYT_INT_STAT_REG 0x800
42
43/* BYT_CONF0_REG register bits */
3ff95885 44#define BYT_IODEN BIT(31)
ff998356 45#define BYT_DIRECT_IRQ_EN BIT(27)
a5d811bb
MN
46#define BYT_TRIG_NEG BIT(26)
47#define BYT_TRIG_POS BIT(25)
48#define BYT_TRIG_LVL BIT(24)
3ff95885
MW
49#define BYT_PULL_STR_SHIFT 9
50#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT)
51#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT)
52#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT)
53#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT)
54#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT)
55#define BYT_PULL_ASSIGN_SHIFT 7
56#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT)
57#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT)
58#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT)
a5d811bb
MN
59#define BYT_PIN_MUX 0x07
60
61/* BYT_VAL_REG register bits */
62#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/
63#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/
64#define BYT_LEVEL BIT(0)
65
66#define BYT_DIR_MASK (BIT(1) | BIT(2))
67#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24))
68
69#define BYT_NGPIO_SCORE 102
70#define BYT_NGPIO_NCORE 28
71#define BYT_NGPIO_SUS 44
72
42bd0070
CKH
73#define BYT_SCORE_ACPI_UID "1"
74#define BYT_NCORE_ACPI_UID "2"
75#define BYT_SUS_ACPI_UID "3"
76
a5d811bb
MN
77/*
78 * Baytrail gpio controller consist of three separate sub-controllers called
79 * SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID.
80 *
81 * GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does
82 * _not_ correspond to the first gpio register at controller's gpio base.
83 * There is no logic or pattern in mapping gpio numbers to registers (pads) so
84 * each sub-controller needs to have its own mapping table
85 */
86
87/* score_pins[gpio_nr] = pad_nr */
88
89static unsigned const score_pins[BYT_NGPIO_SCORE] = {
90 85, 89, 93, 96, 99, 102, 98, 101, 34, 37,
91 36, 38, 39, 35, 40, 84, 62, 61, 64, 59,
92 54, 56, 60, 55, 63, 57, 51, 50, 53, 47,
93 52, 49, 48, 43, 46, 41, 45, 42, 58, 44,
94 95, 105, 70, 68, 67, 66, 69, 71, 65, 72,
95 86, 90, 88, 92, 103, 77, 79, 83, 78, 81,
96 80, 82, 13, 12, 15, 14, 17, 18, 19, 16,
97 2, 1, 0, 4, 6, 7, 9, 8, 33, 32,
98 31, 30, 29, 27, 25, 28, 26, 23, 21, 20,
99 24, 22, 5, 3, 10, 11, 106, 87, 91, 104,
100 97, 100,
101};
102
103static unsigned const ncore_pins[BYT_NGPIO_NCORE] = {
104 19, 18, 17, 20, 21, 22, 24, 25, 23, 16,
105 14, 15, 12, 26, 27, 1, 4, 8, 11, 0,
106 3, 6, 10, 13, 2, 5, 9, 7,
107};
108
109static unsigned const sus_pins[BYT_NGPIO_SUS] = {
110 29, 33, 30, 31, 32, 34, 36, 35, 38, 37,
111 18, 7, 11, 20, 17, 1, 8, 10, 19, 12,
112 0, 2, 23, 39, 28, 27, 22, 21, 24, 25,
113 26, 51, 56, 54, 49, 55, 48, 57, 50, 58,
114 52, 53, 59, 40,
115};
116
117static struct pinctrl_gpio_range byt_ranges[] = {
118 {
42bd0070 119 .name = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */
a5d811bb
MN
120 .npins = BYT_NGPIO_SCORE,
121 .pins = score_pins,
122 },
123 {
42bd0070 124 .name = BYT_NCORE_ACPI_UID,
a5d811bb
MN
125 .npins = BYT_NGPIO_NCORE,
126 .pins = ncore_pins,
127 },
128 {
42bd0070 129 .name = BYT_SUS_ACPI_UID,
a5d811bb
MN
130 .npins = BYT_NGPIO_SUS,
131 .pins = sus_pins,
132 },
133 {
134 },
135};
136
137struct byt_gpio {
138 struct gpio_chip chip;
a5d811bb
MN
139 struct platform_device *pdev;
140 spinlock_t lock;
141 void __iomem *reg_base;
142 struct pinctrl_gpio_range *range;
143};
144
17e52464
AS
145#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip)
146
a5d811bb
MN
147static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset,
148 int reg)
149{
17e52464 150 struct byt_gpio *vg = to_byt_gpio(chip);
a5d811bb 151 u32 reg_offset;
a5d811bb
MN
152
153 if (reg == BYT_INT_STAT_REG)
154 reg_offset = (offset / 32) * 4;
155 else
156 reg_offset = vg->range->pins[offset] * 16;
157
9c5b6557 158 return vg->reg_base + reg_offset + reg;
a5d811bb
MN
159}
160
42bd0070
CKH
161static bool is_special_pin(struct byt_gpio *vg, unsigned offset)
162{
163 /* SCORE pin 92-93 */
164 if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) &&
165 offset >= 92 && offset <= 93)
166 return true;
167
168 /* SUS pin 11-21 */
169 if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) &&
170 offset >= 11 && offset <= 21)
171 return true;
172
173 return false;
174}
175
a5d811bb
MN
176static int byt_gpio_request(struct gpio_chip *chip, unsigned offset)
177{
17e52464 178 struct byt_gpio *vg = to_byt_gpio(chip);
42bd0070
CKH
179 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG);
180 u32 value;
181 bool special;
182
183 /*
184 * In most cases, func pin mux 000 means GPIO function.
185 * But, some pins may have func pin mux 001 represents
186 * GPIO function. Only allow user to export pin with
187 * func pin mux preset as GPIO function by BIOS/FW.
188 */
189 value = readl(reg) & BYT_PIN_MUX;
190 special = is_special_pin(vg, offset);
191 if ((special && value != 1) || (!special && value)) {
192 dev_err(&vg->pdev->dev,
193 "pin %u cannot be used as GPIO.\n", offset);
194 return -EINVAL;
195 }
a5d811bb
MN
196
197 pm_runtime_get(&vg->pdev->dev);
198
199 return 0;
200}
201
202static void byt_gpio_free(struct gpio_chip *chip, unsigned offset)
203{
17e52464 204 struct byt_gpio *vg = to_byt_gpio(chip);
a5d811bb
MN
205 void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
206 u32 value;
207
208 /* clear interrupt triggering */
209 value = readl(reg);
210 value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
211 writel(value, reg);
212
213 pm_runtime_put(&vg->pdev->dev);
214}
215
216static int byt_irq_type(struct irq_data *d, unsigned type)
217{
e1ee5c57 218 struct byt_gpio *vg = to_byt_gpio(irq_data_get_irq_chip_data(d));
a5d811bb
MN
219 u32 offset = irqd_to_hwirq(d);
220 u32 value;
221 unsigned long flags;
222 void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG);
223
224 if (offset >= vg->chip.ngpio)
225 return -EINVAL;
226
227 spin_lock_irqsave(&vg->lock, flags);
228 value = readl(reg);
229
230 /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits
231 * are used to indicate high and low level triggering
232 */
233 value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
234
235 switch (type) {
236 case IRQ_TYPE_LEVEL_HIGH:
237 value |= BYT_TRIG_LVL;
238 case IRQ_TYPE_EDGE_RISING:
239 value |= BYT_TRIG_POS;
240 break;
241 case IRQ_TYPE_LEVEL_LOW:
242 value |= BYT_TRIG_LVL;
243 case IRQ_TYPE_EDGE_FALLING:
244 value |= BYT_TRIG_NEG;
245 break;
246 case IRQ_TYPE_EDGE_BOTH:
247 value |= (BYT_TRIG_NEG | BYT_TRIG_POS);
248 break;
249 }
250 writel(value, reg);
251
252 spin_unlock_irqrestore(&vg->lock, flags);
253
254 return 0;
255}
256
257static int byt_gpio_get(struct gpio_chip *chip, unsigned offset)
258{
259 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
260 return readl(reg) & BYT_LEVEL;
261}
262
263static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
264{
17e52464 265 struct byt_gpio *vg = to_byt_gpio(chip);
a5d811bb
MN
266 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
267 unsigned long flags;
268 u32 old_val;
269
270 spin_lock_irqsave(&vg->lock, flags);
271
272 old_val = readl(reg);
273
274 if (value)
275 writel(old_val | BYT_LEVEL, reg);
276 else
277 writel(old_val & ~BYT_LEVEL, reg);
278
279 spin_unlock_irqrestore(&vg->lock, flags);
280}
281
282static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
283{
17e52464 284 struct byt_gpio *vg = to_byt_gpio(chip);
a5d811bb
MN
285 void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG);
286 unsigned long flags;
287 u32 value;
288
289 spin_lock_irqsave(&vg->lock, flags);
290
291 value = readl(reg) | BYT_DIR_MASK;
496940c1 292 value &= ~BYT_INPUT_EN; /* active low */
a5d811bb
MN
293 writel(value, reg);
294
295 spin_unlock_irqrestore(&vg->lock, flags);
296
297 return 0;
298}
299
300static int byt_gpio_direction_output(struct gpio_chip *chip,
301 unsigned gpio, int value)
302{
17e52464 303 struct byt_gpio *vg = to_byt_gpio(chip);
ff998356 304 void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG);
a5d811bb
MN
305 void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG);
306 unsigned long flags;
307 u32 reg_val;
308
309 spin_lock_irqsave(&vg->lock, flags);
310
ff998356
EE
311 /*
312 * Before making any direction modifications, do a check if gpio
313 * is set for direct IRQ. On baytrail, setting GPIO to output does
314 * not make sense, so let's at least warn the caller before they shoot
315 * themselves in the foot.
316 */
317 WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN,
318 "Potential Error: Setting GPIO with direct_irq_en to output");
319
496940c1
AS
320 reg_val = readl(reg) | BYT_DIR_MASK;
321 reg_val &= ~BYT_OUTPUT_EN;
322
323 if (value)
324 writel(reg_val | BYT_LEVEL, reg);
325 else
326 writel(reg_val & ~BYT_LEVEL, reg);
a5d811bb
MN
327
328 spin_unlock_irqrestore(&vg->lock, flags);
329
330 return 0;
331}
332
333static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
334{
17e52464 335 struct byt_gpio *vg = to_byt_gpio(chip);
a5d811bb
MN
336 int i;
337 unsigned long flags;
338 u32 conf0, val, offs;
339
340 spin_lock_irqsave(&vg->lock, flags);
341
342 for (i = 0; i < vg->chip.ngpio; i++) {
3ff95885
MW
343 const char *pull_str = NULL;
344 const char *pull = NULL;
a4d8d6da 345 const char *label;
a5d811bb
MN
346 offs = vg->range->pins[i] * 16;
347 conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG);
348 val = readl(vg->reg_base + offs + BYT_VAL_REG);
349
a4d8d6da
MN
350 label = gpiochip_is_requested(chip, i);
351 if (!label)
352 label = "Unrequested";
353
3ff95885
MW
354 switch (conf0 & BYT_PULL_ASSIGN_MASK) {
355 case BYT_PULL_ASSIGN_UP:
356 pull = "up";
357 break;
358 case BYT_PULL_ASSIGN_DOWN:
359 pull = "down";
360 break;
361 }
362
363 switch (conf0 & BYT_PULL_STR_MASK) {
364 case BYT_PULL_STR_2K:
365 pull_str = "2k";
366 break;
367 case BYT_PULL_STR_10K:
368 pull_str = "10k";
369 break;
370 case BYT_PULL_STR_20K:
371 pull_str = "20k";
372 break;
373 case BYT_PULL_STR_40K:
374 pull_str = "40k";
375 break;
376 }
377
a5d811bb 378 seq_printf(s,
3ff95885 379 " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s",
a5d811bb 380 i,
a4d8d6da 381 label,
a5d811bb
MN
382 val & BYT_INPUT_EN ? " " : "in",
383 val & BYT_OUTPUT_EN ? " " : "out",
384 val & BYT_LEVEL ? "hi" : "lo",
385 vg->range->pins[i], offs,
386 conf0 & 0x7,
3ff95885
MW
387 conf0 & BYT_TRIG_NEG ? " fall" : " ",
388 conf0 & BYT_TRIG_POS ? " rise" : " ",
389 conf0 & BYT_TRIG_LVL ? " level" : " ");
390
391 if (pull && pull_str)
392 seq_printf(s, " %-4s %-3s", pull, pull_str);
393 else
394 seq_puts(s, " ");
395
396 if (conf0 & BYT_IODEN)
397 seq_puts(s, " open-drain");
398
399 seq_puts(s, "\n");
a5d811bb
MN
400 }
401 spin_unlock_irqrestore(&vg->lock, flags);
402}
403
a5d811bb
MN
404static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
405{
406 struct irq_data *data = irq_desc_get_irq_data(desc);
e1ee5c57 407 struct byt_gpio *vg = to_byt_gpio(irq_desc_get_handler_data(desc));
a5d811bb
MN
408 struct irq_chip *chip = irq_data_get_irq_chip(data);
409 u32 base, pin, mask;
410 void __iomem *reg;
411 u32 pending;
412 unsigned virq;
413 int looplimit = 0;
414
415 /* check from GPIO controller which pin triggered the interrupt */
416 for (base = 0; base < vg->chip.ngpio; base += 32) {
417
418 reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
419
420 while ((pending = readl(reg))) {
421 pin = __ffs(pending);
422 mask = BIT(pin);
423 /* Clear before handling so we can't lose an edge */
424 writel(mask, reg);
425
e1ee5c57 426 virq = irq_find_mapping(vg->chip.irqdomain, base + pin);
a5d811bb
MN
427 generic_handle_irq(virq);
428
429 /* In case bios or user sets triggering incorretly a pin
430 * might remain in "interrupt triggered" state.
431 */
432 if (looplimit++ > 32) {
433 dev_err(&vg->pdev->dev,
434 "Gpio %d interrupt flood, disabling\n",
435 base + pin);
436
437 reg = byt_gpio_reg(&vg->chip, base + pin,
438 BYT_CONF0_REG);
439 mask = readl(reg);
440 mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS |
441 BYT_TRIG_LVL);
442 writel(mask, reg);
443 mask = readl(reg); /* flush */
444 break;
445 }
446 }
447 }
448 chip->irq_eoi(data);
449}
450
451static void byt_irq_unmask(struct irq_data *d)
452{
453}
454
455static void byt_irq_mask(struct irq_data *d)
456{
457}
458
459static struct irq_chip byt_irqchip = {
460 .name = "BYT-GPIO",
461 .irq_mask = byt_irq_mask,
462 .irq_unmask = byt_irq_unmask,
463 .irq_set_type = byt_irq_type,
464};
465
466static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
467{
468 void __iomem *reg;
469 u32 base, value;
470
471 /* clear interrupt status trigger registers */
472 for (base = 0; base < vg->chip.ngpio; base += 32) {
473 reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG);
474 writel(0xffffffff, reg);
475 /* make sure trigger bits are cleared, if not then a pin
476 might be misconfigured in bios */
477 value = readl(reg);
478 if (value)
479 dev_err(&vg->pdev->dev,
480 "GPIO interrupt error, pins misconfigured\n");
481 }
482}
483
a5d811bb
MN
484static int byt_gpio_probe(struct platform_device *pdev)
485{
486 struct byt_gpio *vg;
487 struct gpio_chip *gc;
488 struct resource *mem_rc, *irq_rc;
489 struct device *dev = &pdev->dev;
490 struct acpi_device *acpi_dev;
491 struct pinctrl_gpio_range *range;
492 acpi_handle handle = ACPI_HANDLE(dev);
a5d811bb
MN
493 int ret;
494
495 if (acpi_bus_get_device(handle, &acpi_dev))
496 return -ENODEV;
497
498 vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL);
499 if (!vg) {
500 dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n");
501 return -ENOMEM;
502 }
503
504 for (range = byt_ranges; range->name; range++) {
505 if (!strcmp(acpi_dev->pnp.unique_id, range->name)) {
506 vg->chip.ngpio = range->npins;
507 vg->range = range;
508 break;
509 }
510 }
511
512 if (!vg->chip.ngpio || !vg->range)
513 return -ENODEV;
514
515 vg->pdev = pdev;
516 platform_set_drvdata(pdev, vg);
517
518 mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0);
519 vg->reg_base = devm_ioremap_resource(dev, mem_rc);
520 if (IS_ERR(vg->reg_base))
521 return PTR_ERR(vg->reg_base);
522
523 spin_lock_init(&vg->lock);
524
525 gc = &vg->chip;
526 gc->label = dev_name(&pdev->dev);
527 gc->owner = THIS_MODULE;
528 gc->request = byt_gpio_request;
529 gc->free = byt_gpio_free;
530 gc->direction_input = byt_gpio_direction_input;
531 gc->direction_output = byt_gpio_direction_output;
532 gc->get = byt_gpio_get;
533 gc->set = byt_gpio_set;
534 gc->dbg_show = byt_gpio_dbg_show;
535 gc->base = -1;
9fb1f39e 536 gc->can_sleep = false;
a5d811bb
MN
537 gc->dev = dev;
538
e1ee5c57
MW
539 ret = gpiochip_add(gc);
540 if (ret) {
541 dev_err(&pdev->dev, "failed adding byt-gpio chip\n");
542 return ret;
543 }
544
a5d811bb
MN
545 /* set up interrupts */
546 irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
547 if (irq_rc && irq_rc->start) {
a5d811bb 548 byt_gpio_irq_init_hw(vg);
e1ee5c57
MW
549 ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
550 handle_simple_irq, IRQ_TYPE_NONE);
551 if (ret) {
552 dev_err(dev, "failed to add irqchip\n");
553 gpiochip_remove(gc);
554 return ret;
555 }
a5d811bb 556
e1ee5c57
MW
557 gpiochip_set_chained_irqchip(gc, &byt_irqchip,
558 (unsigned)irq_rc->start,
559 byt_gpio_irq_handler);
605a7bca
JY
560 }
561
a5d811bb
MN
562 pm_runtime_enable(dev);
563
564 return 0;
565}
566
567static int byt_gpio_runtime_suspend(struct device *dev)
568{
569 return 0;
570}
571
572static int byt_gpio_runtime_resume(struct device *dev)
573{
574 return 0;
575}
576
577static const struct dev_pm_ops byt_gpio_pm_ops = {
578 .runtime_suspend = byt_gpio_runtime_suspend,
579 .runtime_resume = byt_gpio_runtime_resume,
580};
581
582static const struct acpi_device_id byt_gpio_acpi_match[] = {
583 { "INT33B2", 0 },
20482d32 584 { "INT33FC", 0 },
a5d811bb
MN
585 { }
586};
587MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match);
588
589static int byt_gpio_remove(struct platform_device *pdev)
590{
591 struct byt_gpio *vg = platform_get_drvdata(pdev);
ec243320 592
a5d811bb 593 pm_runtime_disable(&pdev->dev);
b4e7c55d 594 gpiochip_remove(&vg->chip);
a5d811bb
MN
595
596 return 0;
597}
598
599static struct platform_driver byt_gpio_driver = {
600 .probe = byt_gpio_probe,
601 .remove = byt_gpio_remove,
602 .driver = {
603 .name = "byt_gpio",
604 .owner = THIS_MODULE,
605 .pm = &byt_gpio_pm_ops,
606 .acpi_match_table = ACPI_PTR(byt_gpio_acpi_match),
607 },
608};
609
610static int __init byt_gpio_init(void)
611{
612 return platform_driver_register(&byt_gpio_driver);
613}
614
615subsys_initcall(byt_gpio_init);
This page took 0.097101 seconds and 5 git commands to generate.