Merge tag 'armsoc-dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[deliverable/linux.git] / drivers / gpio / gpio-etraxfs.c
1 #include <linux/kernel.h>
2 #include <linux/init.h>
3 #include <linux/gpio.h>
4 #include <linux/of_gpio.h>
5 #include <linux/io.h>
6 #include <linux/platform_device.h>
7 #include <linux/basic_mmio_gpio.h>
8
9 #define ETRAX_FS_rw_pa_dout 0
10 #define ETRAX_FS_r_pa_din 4
11 #define ETRAX_FS_rw_pa_oe 8
12 #define ETRAX_FS_rw_intr_cfg 12
13 #define ETRAX_FS_rw_intr_mask 16
14 #define ETRAX_FS_rw_ack_intr 20
15 #define ETRAX_FS_r_intr 24
16 #define ETRAX_FS_rw_pb_dout 32
17 #define ETRAX_FS_r_pb_din 36
18 #define ETRAX_FS_rw_pb_oe 40
19 #define ETRAX_FS_rw_pc_dout 48
20 #define ETRAX_FS_r_pc_din 52
21 #define ETRAX_FS_rw_pc_oe 56
22 #define ETRAX_FS_rw_pd_dout 64
23 #define ETRAX_FS_r_pd_din 68
24 #define ETRAX_FS_rw_pd_oe 72
25 #define ETRAX_FS_rw_pe_dout 80
26 #define ETRAX_FS_r_pe_din 84
27 #define ETRAX_FS_rw_pe_oe 88
28
29 struct etraxfs_gpio_port {
30 const char *label;
31 unsigned int oe;
32 unsigned int dout;
33 unsigned int din;
34 unsigned int ngpio;
35 };
36
37 struct etraxfs_gpio_info {
38 unsigned int num_ports;
39 const struct etraxfs_gpio_port *ports;
40 };
41
42 static const struct etraxfs_gpio_port etraxfs_gpio_etraxfs_ports[] = {
43 {
44 .label = "A",
45 .ngpio = 8,
46 .oe = ETRAX_FS_rw_pa_oe,
47 .dout = ETRAX_FS_rw_pa_dout,
48 .din = ETRAX_FS_r_pa_din,
49 },
50 {
51 .label = "B",
52 .ngpio = 18,
53 .oe = ETRAX_FS_rw_pb_oe,
54 .dout = ETRAX_FS_rw_pb_dout,
55 .din = ETRAX_FS_r_pb_din,
56 },
57 {
58 .label = "C",
59 .ngpio = 18,
60 .oe = ETRAX_FS_rw_pc_oe,
61 .dout = ETRAX_FS_rw_pc_dout,
62 .din = ETRAX_FS_r_pc_din,
63 },
64 {
65 .label = "D",
66 .ngpio = 18,
67 .oe = ETRAX_FS_rw_pd_oe,
68 .dout = ETRAX_FS_rw_pd_dout,
69 .din = ETRAX_FS_r_pd_din,
70 },
71 {
72 .label = "E",
73 .ngpio = 18,
74 .oe = ETRAX_FS_rw_pe_oe,
75 .dout = ETRAX_FS_rw_pe_dout,
76 .din = ETRAX_FS_r_pe_din,
77 },
78 };
79
80 static const struct etraxfs_gpio_info etraxfs_gpio_etraxfs = {
81 .num_ports = ARRAY_SIZE(etraxfs_gpio_etraxfs_ports),
82 .ports = etraxfs_gpio_etraxfs_ports,
83 };
84
85 static int etraxfs_gpio_of_xlate(struct gpio_chip *gc,
86 const struct of_phandle_args *gpiospec,
87 u32 *flags)
88 {
89 /*
90 * Port numbers are A to E, and the properties are integers, so we
91 * specify them as 0xA - 0xE.
92 */
93 if (gc->label[0] - 'A' + 0xA != gpiospec->args[2])
94 return -EINVAL;
95
96 return of_gpio_simple_xlate(gc, gpiospec, flags);
97 }
98
99 static const struct of_device_id etraxfs_gpio_of_table[] = {
100 {
101 .compatible = "axis,etraxfs-gio",
102 .data = &etraxfs_gpio_etraxfs,
103 },
104 {},
105 };
106
107 static int etraxfs_gpio_probe(struct platform_device *pdev)
108 {
109 struct device *dev = &pdev->dev;
110 const struct etraxfs_gpio_info *info;
111 const struct of_device_id *match;
112 struct bgpio_chip *chips;
113 struct resource *res;
114 void __iomem *regs;
115 int ret;
116 int i;
117
118 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
119 regs = devm_ioremap_resource(dev, res);
120 if (!regs)
121 return -ENOMEM;
122
123 match = of_match_node(etraxfs_gpio_of_table, dev->of_node);
124 if (!match)
125 return -EINVAL;
126
127 info = match->data;
128
129 chips = devm_kzalloc(dev, sizeof(*chips) * info->num_ports, GFP_KERNEL);
130 if (!chips)
131 return -ENOMEM;
132
133 for (i = 0; i < info->num_ports; i++) {
134 struct bgpio_chip *bgc = &chips[i];
135 const struct etraxfs_gpio_port *port = &info->ports[i];
136
137 ret = bgpio_init(bgc, dev, 4,
138 regs + port->din, /* dat */
139 regs + port->dout, /* set */
140 NULL, /* clr */
141 regs + port->oe, /* dirout */
142 NULL, /* dirin */
143 BGPIOF_UNREADABLE_REG_SET);
144 if (ret)
145 return ret;
146
147 bgc->gc.ngpio = port->ngpio;
148 bgc->gc.label = port->label;
149
150 bgc->gc.of_node = dev->of_node;
151 bgc->gc.of_gpio_n_cells = 3;
152 bgc->gc.of_xlate = etraxfs_gpio_of_xlate;
153
154 ret = gpiochip_add(&bgc->gc);
155 if (ret)
156 dev_err(dev, "Unable to register port %s\n",
157 bgc->gc.label);
158 }
159
160 return 0;
161 }
162
163 static struct platform_driver etraxfs_gpio_driver = {
164 .driver = {
165 .name = "etraxfs-gpio",
166 .of_match_table = of_match_ptr(etraxfs_gpio_of_table),
167 },
168 .probe = etraxfs_gpio_probe,
169 };
170
171 static int __init etraxfs_gpio_init(void)
172 {
173 return platform_driver_register(&etraxfs_gpio_driver);
174 }
175
176 device_initcall(etraxfs_gpio_init);
This page took 0.07928 seconds and 5 git commands to generate.