1
2
3
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
17DECLARE_GLOBAL_DATA_PTR;
18
19
20#define WIDTH 8
21#define HEIGHT 6
22
23struct shape_data {
24 int num_chars;
25 struct gpio_desc gpio_desc[8];
26 int gpio_count;
27};
28
29
30static 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
88static 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
96static 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
115static 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
137static 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
144static int shape_of_to_plat(struct udevice *dev)
145{
146 struct dm_demo_pdata *pdata = dev_get_plat(dev);
147 int ret;
148
149
150 ret = demo_parse_dt(dev);
151 if (ret)
152 return ret;
153
154
155 pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
156 "character", '@');
157
158 return 0;
159}
160
161static 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
177static 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
184static const struct udevice_id demo_shape_id[] = {
185 { "demo-shape", 0 },
186 { },
187};
188
189U_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};
200