]> git.sur5r.net Git - u-boot/blob - drivers/gpio/altera_pio.c
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
[u-boot] / drivers / gpio / altera_pio.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015  Thomas Chou <thomas@wytron.com.tw>
4  * Copyright (C) 2011  Missing Link Electronics
5  *                     Joachim Foerster <joachim@missinglinkelectronics.com>
6  */
7 #include <common.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <malloc.h>
11 #include <fdtdec.h>
12 #include <asm/io.h>
13 #include <asm/gpio.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 struct altera_pio_regs {
18         u32     data;                   /* Data register */
19         u32     direction;              /* Direction register */
20 };
21
22 struct altera_pio_platdata {
23         struct altera_pio_regs *regs;
24         int gpio_count;
25         const char *bank_name;
26 };
27
28 static int altera_pio_direction_input(struct udevice *dev, unsigned pin)
29 {
30         struct altera_pio_platdata *plat = dev_get_platdata(dev);
31         struct altera_pio_regs *const regs = plat->regs;
32
33         clrbits_le32(&regs->direction, 1 << pin);
34
35         return 0;
36 }
37
38 static int altera_pio_direction_output(struct udevice *dev, unsigned pin,
39                                      int val)
40 {
41         struct altera_pio_platdata *plat = dev_get_platdata(dev);
42         struct altera_pio_regs *const regs = plat->regs;
43
44         if (val)
45                 setbits_le32(&regs->data, 1 << pin);
46         else
47                 clrbits_le32(&regs->data, 1 << pin);
48         /* change the data first, then the direction. to avoid glitch */
49         setbits_le32(&regs->direction, 1 << pin);
50
51         return 0;
52 }
53
54 static int altera_pio_get_value(struct udevice *dev, unsigned pin)
55 {
56         struct altera_pio_platdata *plat = dev_get_platdata(dev);
57         struct altera_pio_regs *const regs = plat->regs;
58
59         return readl(&regs->data) & (1 << pin);
60 }
61
62
63 static int altera_pio_set_value(struct udevice *dev, unsigned pin, int val)
64 {
65         struct altera_pio_platdata *plat = dev_get_platdata(dev);
66         struct altera_pio_regs *const regs = plat->regs;
67
68         if (val)
69                 setbits_le32(&regs->data, 1 << pin);
70         else
71                 clrbits_le32(&regs->data, 1 << pin);
72
73         return 0;
74 }
75
76 static int altera_pio_probe(struct udevice *dev)
77 {
78         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
79         struct altera_pio_platdata *plat = dev_get_platdata(dev);
80
81         uc_priv->gpio_count = plat->gpio_count;
82         uc_priv->bank_name = plat->bank_name;
83
84         return 0;
85 }
86
87 static int altera_pio_ofdata_to_platdata(struct udevice *dev)
88 {
89         struct altera_pio_platdata *plat = dev_get_platdata(dev);
90
91         plat->regs = map_physmem(devfdt_get_addr(dev),
92                                  sizeof(struct altera_pio_regs),
93                                  MAP_NOCACHE);
94         plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
95                 "altr,gpio-bank-width", 32);
96         plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
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 };