OSDN Git Service

drm/i915: Declare the swizzling unknown for L-shaped configurations
[uclinux-h8/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);