]> git.sur5r.net Git - u-boot/blob - drivers/gpio/altera_pio.c
dm: core: Replace of_offset with accessor
[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 = map_physmem(dev_get_addr(dev),
93                                  sizeof(struct altera_pio_regs),
94                                  MAP_NOCACHE);
95         plat->gpio_count = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
96                 "altr,gpio-bank-width", 32);
97         plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev),
98                 "gpio-bank-name", NULL);
99
100         return 0;
101 }
102
103 static const struct dm_gpio_ops altera_pio_ops = {
104         .direction_input        = altera_pio_direction_input,
105         .direction_output       = altera_pio_direction_output,
106         .get_value              = altera_pio_get_value,
107         .set_value              = altera_pio_set_value,
108 };
109
110 static const struct udevice_id altera_pio_ids[] = {
111         { .compatible = "altr,pio-1.0" },
112         { }
113 };
114
115 U_BOOT_DRIVER(altera_pio) = {
116         .name           = "altera_pio",
117         .id             = UCLASS_GPIO,
118         .of_match       = altera_pio_ids,
119         .ops            = &altera_pio_ops,
120         .ofdata_to_platdata = altera_pio_ofdata_to_platdata,
121         .platdata_auto_alloc_size = sizeof(struct altera_pio_platdata),
122         .probe          = altera_pio_probe,
123 };