blob: b6b29bcb31b3397ec56b042c4385504b9278a345 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass39f76112014-02-26 15:59:23 -07002/*
3 * Copyright (c) 2013 Google, Inc
Simon Glass39f76112014-02-26 15:59:23 -07004 */
5
6#include <common.h>
7#include <dm.h>
8#include <errno.h>
9#include <fdtdec.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060010#include <log.h>
Simon Glass39f76112014-02-26 15:59:23 -070011#include <malloc.h>
12#include <dm-demo.h>
Simon Glass401d1c42020-10-30 21:38:53 -060013#include <asm/global_data.h>
Simon Glass39f76112014-02-26 15:59:23 -070014#include <asm/io.h>
Simon Glassa02af4a2015-01-05 20:05:31 -070015#include <asm/gpio.h>
Simon Glass39f76112014-02-26 15:59:23 -070016
17DECLARE_GLOBAL_DATA_PTR;
18
19/* Shape size */
20#define WIDTH 8
21#define HEIGHT 6
22
23struct shape_data {
24 int num_chars; /* Number of non-space characters output so far */
Simon Glassa02af4a2015-01-05 20:05:31 -070025 struct gpio_desc gpio_desc[8];
26 int gpio_count;
Simon Glass39f76112014-02-26 15:59:23 -070027};
28
29/* Crazy little function to draw shapes on the console */
Heiko Schocher54c5d082014-05-22 12:43:05 +020030static int shape_hello(struct udevice *dev, int ch)
Simon Glass39f76112014-02-26 15:59:23 -070031{
Simon Glassc69cda22020-12-03 16:55:20 -070032 const struct dm_demo_pdata *pdata = dev_get_plat(dev);
Simon Glass39f76112014-02-26 15:59:23 -070033 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
Heiko Schocher54c5d082014-05-22 12:43:05 +020088static int shape_status(struct udevice *dev, int *status)
Simon Glass39f76112014-02-26 15:59:23 -070089{
90 struct shape_data *data = dev_get_priv(dev);
91
92 *status = data->num_chars;
93 return 0;
94}
95
Simon Glassa02af4a2015-01-05 20:05:31 -070096static 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
Simon Glass39f76112014-02-26 15:59:23 -0700137static const struct demo_ops shape_ops = {
138 .hello = shape_hello,
139 .status = shape_status,
Simon Glassa02af4a2015-01-05 20:05:31 -0700140 .get_light = get_light,
141 .set_light = set_light,
Simon Glass39f76112014-02-26 15:59:23 -0700142};
143
Simon Glassd1998a92020-12-03 16:55:21 -0700144static int shape_of_to_plat(struct udevice *dev)
Simon Glass39f76112014-02-26 15:59:23 -0700145{
Simon Glassc69cda22020-12-03 16:55:20 -0700146 struct dm_demo_pdata *pdata = dev_get_plat(dev);
Simon Glass39f76112014-02-26 15:59:23 -0700147 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 */
Simon Glasse160f7d2017-01-17 16:52:55 -0700155 pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
Simon Glass39f76112014-02-26 15:59:23 -0700156 "character", '@');
157
158 return 0;
159}
160
Simon Glassa02af4a2015-01-05 20:05:31 -0700161static 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
Simon Glassae7f4512014-06-11 23:29:45 -0600184static const struct udevice_id demo_shape_id[] = {
Simon Glass39f76112014-02-26 15:59:23 -0700185 { "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,
Simon Glassd1998a92020-12-03 16:55:21 -0700193 .of_to_plat = shape_of_to_plat,
Simon Glass39f76112014-02-26 15:59:23 -0700194 .ops = &shape_ops,
Simon Glassa02af4a2015-01-05 20:05:31 -0700195 .probe = dm_shape_probe,
196 .remove = dm_shape_remove,
Simon Glass41575d82020-12-03 16:55:17 -0700197 .priv_auto = sizeof(struct shape_data),
Simon Glasscaa4daa2020-12-03 16:55:18 -0700198 .plat_auto = sizeof(struct dm_demo_pdata),
Simon Glass39f76112014-02-26 15:59:23 -0700199};