global: Migrate CONFIG_STACKBASE to CFG
[platform/kernel/u-boot.git] / drivers / demo / demo-shape.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2013 Google, Inc
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <fdtdec.h>
10 #include <log.h>
11 #include <malloc.h>
12 #include <dm-demo.h>
13 #include <asm/global_data.h>
14 #include <asm/io.h>
15 #include <asm/gpio.h>
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 /* Shape size */
20 #define WIDTH   8
21 #define HEIGHT  6
22
23 struct shape_data {
24         int num_chars;  /* Number of non-space characters output so far */
25         struct gpio_desc gpio_desc[8];
26         int gpio_count;
27 };
28
29 /* Crazy little function to draw shapes on the console */
30 static int shape_hello(struct udevice *dev, int ch)
31 {
32         const struct dm_demo_pdata *pdata = dev_get_plat(dev);
33         struct shape_data *data = dev_get_priv(dev);
34         static const struct shape {
35                 int start;
36                 int end;
37                 int dstart;
38                 int dend;
39         } shapes[3] = {
40                 { 0, 1, 0, 1 },
41                 { 0, WIDTH, 0, 0 },
42                 { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
43         };
44         struct shape shape;
45         unsigned int index;
46         int line, pos, inside;
47         const char *colour = pdata->colour;
48         int first = 0;
49
50         if (!ch)
51                 ch = pdata->default_char;
52         if (!ch)
53                 ch = '@';
54
55         index = (pdata->sides / 2) - 1;
56         if (index >= ARRAY_SIZE(shapes))
57                 return -EIO;
58         shape = shapes[index];
59
60         for (line = 0; line < HEIGHT; line++) {
61                 first = 1;
62                 for (pos = 0; pos < WIDTH; pos++) {
63                         inside = pos >= shape.start && pos < shape.end;
64                         if (inside) {
65                                 putc(first ? *colour++ : ch);
66                                 data->num_chars++;
67                                 first = 0;
68                                 if (!*colour)
69                                         colour = pdata->colour;
70                         } else {
71                                 putc(' ');
72                         }
73                 }
74                 putc('\n');
75                 shape.start += shape.dstart;
76                 shape.end += shape.dend;
77                 if (shape.start < 0) {
78                         shape.dstart = -shape.dstart;
79                         shape.dend = -shape.dend;
80                         shape.start += shape.dstart;
81                         shape.end += shape.dend;
82                 }
83         }
84
85         return 0;
86 }
87
88 static int shape_status(struct udevice *dev, int *status)
89 {
90         struct shape_data *data = dev_get_priv(dev);
91
92         *status = data->num_chars;
93         return 0;
94 }
95
96 static int set_light(struct udevice *dev, int light)
97 {
98         struct shape_data *priv = dev_get_priv(dev);
99         struct gpio_desc *desc;
100         int ret;
101         int i;
102
103         desc = priv->gpio_desc;
104         for (i = 0; i < priv->gpio_count; i++, desc++) {
105                 uint mask = 1 << i;
106
107                 ret = dm_gpio_set_value(desc, light & mask);
108                 if (ret < 0)
109                         return ret;
110         }
111
112         return 0;
113 }
114
115 static int get_light(struct udevice *dev)
116 {
117         struct shape_data *priv = dev_get_priv(dev);
118         struct gpio_desc *desc;
119         uint value = 0;
120         int ret;
121         int i;
122
123         desc = priv->gpio_desc;
124         for (i = 0; i < priv->gpio_count; i++, desc++) {
125                 uint mask = 1 << i;
126
127                 ret = dm_gpio_get_value(desc);
128                 if (ret < 0)
129                         return ret;
130                 if (ret)
131                         value |= mask;
132         }
133
134         return value;
135 }
136
137 static const struct demo_ops shape_ops = {
138         .hello = shape_hello,
139         .status = shape_status,
140         .get_light = get_light,
141         .set_light = set_light,
142 };
143
144 static int shape_of_to_plat(struct udevice *dev)
145 {
146         struct dm_demo_pdata *pdata = dev_get_plat(dev);
147         int ret;
148
149         /* Parse the data that is common with all demo devices */
150         ret = demo_parse_dt(dev);
151         if (ret)
152                 return ret;
153
154         /* Parse the data that only we need */
155         pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
156                                              "character", '@');
157
158         return 0;
159 }
160
161 static int dm_shape_probe(struct udevice *dev)
162 {
163         struct shape_data *priv = dev_get_priv(dev);
164         int ret;
165
166         ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
167                                         ARRAY_SIZE(priv->gpio_desc),
168                                         GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
169         if (ret < 0)
170                 return ret;
171         priv->gpio_count = ret;
172         debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
173
174         return 0;
175 }
176
177 static int dm_shape_remove(struct udevice *dev)
178 {
179         struct shape_data *priv = dev_get_priv(dev);
180
181         return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
182 }
183
184 static const struct udevice_id demo_shape_id[] = {
185         { "demo-shape", 0 },
186         { },
187 };
188
189 U_BOOT_DRIVER(demo_shape_drv) = {
190         .name   = "demo_shape_drv",
191         .of_match = demo_shape_id,
192         .id     = UCLASS_DEMO,
193         .of_to_plat = shape_of_to_plat,
194         .ops    = &shape_ops,
195         .probe = dm_shape_probe,
196         .remove = dm_shape_remove,
197         .priv_auto      = sizeof(struct shape_data),
198         .plat_auto      = sizeof(struct dm_demo_pdata),
199 };