]> git.sur5r.net Git - u-boot/blob - drivers/gpio/altera_pio.c
imx: hab: rework unified rom section for mx7
[u-boot] / drivers / gpio / altera_pio.c
1 /*
2  * Copyright (C) 2015  Thomas Chou <thomas@wytron.com.tw>
3  * Copyright (C) 2011  Missing Link Electronics
4  *                     Joachim Foerster <joachim@missinglinkelectronics.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8 #include <common.h>
9 #include <dm.h>
10 #include <errno.h>
11 #include <malloc.h>
12 #include <fdtdec.h>
13 #include <asm/io.h>
14 #include <asm/gpio.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 struct altera_pio_regs {
19         u32     data;                   /* Data register */
20         u32     direction;              /* Direction register */
21 };
22
23 struct altera_pio_platdata {
24         struct altera_pio_regs *regs;
25         int gpio_count;
26         const char *bank_name;
27 };
28
29 static int altera_pio_direction_input(struct udevice *dev, unsigned pin)
30 {
31         struct altera_pio_platdata *plat = dev_get_platdata(dev);
32         struct altera_pio_regs *const regs = plat->regs;
33
34         clrbits_le32(&regs->direction, 1 << pin);
35
36         return 0;
37 }
38
39 static int altera_pio_direction_output(struct udevice *dev, unsigned pin,
40                                      int val)
41 {
42         struct altera_pio_platdata *plat = dev_get_platdata(dev);
43         struct altera_pio_regs *const regs = plat->regs;
44
45         if (val)
46                 setbits_le32(&regs->data, 1 << pin);
47         else
48                 clrbits_le32(&regs->data, 1 << pin);
49         /* change the data first, then the direction. to avoid glitch */
50         setbits_le32(&regs->direction, 1 << pin);
51
52         return 0;
53 }
54
55 static int altera_pio_get_value(struct udevice *dev, unsigned pin)
56 {
57         struct altera_pio_platdata *plat = dev_get_platdata(dev);
58         struct altera_pio_regs *const regs = plat->regs;
59
60         return readl(&regs->data) & (1 << pin);
61 }
62
63
64 static int altera_pio_set_value(struct udevice *dev, unsigned pin, int val)
65 {
66         struct altera_pio_platdata *plat = dev_get_platdata(dev);
67         struct altera_pio_regs *const regs = plat->regs;
68
69         if (val)
70                 setbits_le32(&regs->data, 1 << pin);
71         else
72                 clrbits_le32(&regs->data, 1 << pin);
73
74         return 0;
75 }
76
77 static int altera_pio_probe(struct udevice *dev)
78 {
79         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
80         struct altera_pio_platdata *plat = dev_get_platdata(dev);
81
82         uc_priv->gpio_count = plat->gpio_count;
83         uc_priv->bank_name = plat->bank_name;
84
85         return 0;
86 }
87
88 static int altera_pio_ofdata_to_platdata(struct udevice *dev)
89 {
90         struct altera_pio_platdata *plat = dev_get_platdata(dev);
91
92         plat->regs = ioremap(dev_get_addr(dev),
93                 sizeof(struct altera_pio_regs));
94         plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
95                 "altr,gpio-bank-width", 32);
96         plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
97                 "gpio-bank-name", NULL);
98
99         return 0;
100 }
101
102 static const struct dm_gpio_ops altera_pio_ops = {
103         .direction_input        = altera_pio_direction_input,
104         .direction_output       = altera_pio_direction_output,
105         .get_value              = altera_pio_get_value,
106         .set_value              = altera_pio_set_value,
107 };
108
109 static const struct udevice_id altera_pio_ids[] = {
110         { .compatible = "altr,pio-1.0" },
111         { }
112 };
113
114 U_BOOT_DRIVER(altera_pio) = {
115         .name           = "altera_pio",
116         .id             = UCLASS_GPIO,
117         .of_match       = altera_pio_ids,
118         .ops            = &altera_pio_ops,
119         .ofdata_to_platdata = altera_pio_ofdata_to_platdata,
120         .platdata_auto_alloc_size = sizeof(struct altera_pio_platdata),
121         .probe          = altera_pio_probe,
122 };