139f7611fSSimon Glass /*
239f7611fSSimon Glass * Copyright (c) 2013 Google, Inc
339f7611fSSimon Glass *
439f7611fSSimon Glass * SPDX-License-Identifier: GPL-2.0+
539f7611fSSimon Glass */
639f7611fSSimon Glass
739f7611fSSimon Glass #include <common.h>
839f7611fSSimon Glass #include <dm.h>
939f7611fSSimon Glass #include <errno.h>
1039f7611fSSimon Glass #include <fdtdec.h>
1139f7611fSSimon Glass #include <malloc.h>
1239f7611fSSimon Glass #include <dm-demo.h>
1339f7611fSSimon Glass #include <asm/io.h>
14a02af4aeSSimon Glass #include <asm/gpio.h>
1539f7611fSSimon Glass
1639f7611fSSimon Glass DECLARE_GLOBAL_DATA_PTR;
1739f7611fSSimon Glass
1839f7611fSSimon Glass /* Shape size */
1939f7611fSSimon Glass #define WIDTH 8
2039f7611fSSimon Glass #define HEIGHT 6
2139f7611fSSimon Glass
2239f7611fSSimon Glass struct shape_data {
2339f7611fSSimon Glass int num_chars; /* Number of non-space characters output so far */
24a02af4aeSSimon Glass struct gpio_desc gpio_desc[8];
25a02af4aeSSimon Glass int gpio_count;
2639f7611fSSimon Glass };
2739f7611fSSimon Glass
2839f7611fSSimon Glass /* Crazy little function to draw shapes on the console */
shape_hello(struct udevice * dev,int ch)2954c5d08aSHeiko Schocher static int shape_hello(struct udevice *dev, int ch)
3039f7611fSSimon Glass {
3139f7611fSSimon Glass const struct dm_demo_pdata *pdata = dev_get_platdata(dev);
3239f7611fSSimon Glass struct shape_data *data = dev_get_priv(dev);
3339f7611fSSimon Glass static const struct shape {
3439f7611fSSimon Glass int start;
3539f7611fSSimon Glass int end;
3639f7611fSSimon Glass int dstart;
3739f7611fSSimon Glass int dend;
3839f7611fSSimon Glass } shapes[3] = {
3939f7611fSSimon Glass { 0, 1, 0, 1 },
4039f7611fSSimon Glass { 0, WIDTH, 0, 0 },
4139f7611fSSimon Glass { HEIGHT / 2 - 1, WIDTH - HEIGHT / 2 + 1, -1, 1},
4239f7611fSSimon Glass };
4339f7611fSSimon Glass struct shape shape;
4439f7611fSSimon Glass unsigned int index;
4539f7611fSSimon Glass int line, pos, inside;
4639f7611fSSimon Glass const char *colour = pdata->colour;
4739f7611fSSimon Glass int first = 0;
4839f7611fSSimon Glass
4939f7611fSSimon Glass if (!ch)
5039f7611fSSimon Glass ch = pdata->default_char;
5139f7611fSSimon Glass if (!ch)
5239f7611fSSimon Glass ch = '@';
5339f7611fSSimon Glass
5439f7611fSSimon Glass index = (pdata->sides / 2) - 1;
5539f7611fSSimon Glass if (index >= ARRAY_SIZE(shapes))
5639f7611fSSimon Glass return -EIO;
5739f7611fSSimon Glass shape = shapes[index];
5839f7611fSSimon Glass
5939f7611fSSimon Glass for (line = 0; line < HEIGHT; line++) {
6039f7611fSSimon Glass first = 1;
6139f7611fSSimon Glass for (pos = 0; pos < WIDTH; pos++) {
6239f7611fSSimon Glass inside = pos >= shape.start && pos < shape.end;
6339f7611fSSimon Glass if (inside) {
6439f7611fSSimon Glass putc(first ? *colour++ : ch);
6539f7611fSSimon Glass data->num_chars++;
6639f7611fSSimon Glass first = 0;
6739f7611fSSimon Glass if (!*colour)
6839f7611fSSimon Glass colour = pdata->colour;
6939f7611fSSimon Glass } else {
7039f7611fSSimon Glass putc(' ');
7139f7611fSSimon Glass }
7239f7611fSSimon Glass }
7339f7611fSSimon Glass putc('\n');
7439f7611fSSimon Glass shape.start += shape.dstart;
7539f7611fSSimon Glass shape.end += shape.dend;
7639f7611fSSimon Glass if (shape.start < 0) {
7739f7611fSSimon Glass shape.dstart = -shape.dstart;
7839f7611fSSimon Glass shape.dend = -shape.dend;
7939f7611fSSimon Glass shape.start += shape.dstart;
8039f7611fSSimon Glass shape.end += shape.dend;
8139f7611fSSimon Glass }
8239f7611fSSimon Glass }
8339f7611fSSimon Glass
8439f7611fSSimon Glass return 0;
8539f7611fSSimon Glass }
8639f7611fSSimon Glass
shape_status(struct udevice * dev,int * status)8754c5d08aSHeiko Schocher static int shape_status(struct udevice *dev, int *status)
8839f7611fSSimon Glass {
8939f7611fSSimon Glass struct shape_data *data = dev_get_priv(dev);
9039f7611fSSimon Glass
9139f7611fSSimon Glass *status = data->num_chars;
9239f7611fSSimon Glass return 0;
9339f7611fSSimon Glass }
9439f7611fSSimon Glass
set_light(struct udevice * dev,int light)95a02af4aeSSimon Glass static int set_light(struct udevice *dev, int light)
96a02af4aeSSimon Glass {
97a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev);
98a02af4aeSSimon Glass struct gpio_desc *desc;
99a02af4aeSSimon Glass int ret;
100a02af4aeSSimon Glass int i;
101a02af4aeSSimon Glass
102a02af4aeSSimon Glass desc = priv->gpio_desc;
103a02af4aeSSimon Glass for (i = 0; i < priv->gpio_count; i++, desc++) {
104a02af4aeSSimon Glass uint mask = 1 << i;
105a02af4aeSSimon Glass
106a02af4aeSSimon Glass ret = dm_gpio_set_value(desc, light & mask);
107a02af4aeSSimon Glass if (ret < 0)
108a02af4aeSSimon Glass return ret;
109a02af4aeSSimon Glass }
110a02af4aeSSimon Glass
111a02af4aeSSimon Glass return 0;
112a02af4aeSSimon Glass }
113a02af4aeSSimon Glass
get_light(struct udevice * dev)114a02af4aeSSimon Glass static int get_light(struct udevice *dev)
115a02af4aeSSimon Glass {
116a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev);
117a02af4aeSSimon Glass struct gpio_desc *desc;
118a02af4aeSSimon Glass uint value = 0;
119a02af4aeSSimon Glass int ret;
120a02af4aeSSimon Glass int i;
121a02af4aeSSimon Glass
122a02af4aeSSimon Glass desc = priv->gpio_desc;
123a02af4aeSSimon Glass for (i = 0; i < priv->gpio_count; i++, desc++) {
124a02af4aeSSimon Glass uint mask = 1 << i;
125a02af4aeSSimon Glass
126a02af4aeSSimon Glass ret = dm_gpio_get_value(desc);
127a02af4aeSSimon Glass if (ret < 0)
128a02af4aeSSimon Glass return ret;
129a02af4aeSSimon Glass if (ret)
130a02af4aeSSimon Glass value |= mask;
131a02af4aeSSimon Glass }
132a02af4aeSSimon Glass
133a02af4aeSSimon Glass return value;
134a02af4aeSSimon Glass }
135a02af4aeSSimon Glass
13639f7611fSSimon Glass static const struct demo_ops shape_ops = {
13739f7611fSSimon Glass .hello = shape_hello,
13839f7611fSSimon Glass .status = shape_status,
139a02af4aeSSimon Glass .get_light = get_light,
140a02af4aeSSimon Glass .set_light = set_light,
14139f7611fSSimon Glass };
14239f7611fSSimon Glass
shape_ofdata_to_platdata(struct udevice * dev)14354c5d08aSHeiko Schocher static int shape_ofdata_to_platdata(struct udevice *dev)
14439f7611fSSimon Glass {
14539f7611fSSimon Glass struct dm_demo_pdata *pdata = dev_get_platdata(dev);
14639f7611fSSimon Glass int ret;
14739f7611fSSimon Glass
14839f7611fSSimon Glass /* Parse the data that is common with all demo devices */
14939f7611fSSimon Glass ret = demo_parse_dt(dev);
15039f7611fSSimon Glass if (ret)
15139f7611fSSimon Glass return ret;
15239f7611fSSimon Glass
15339f7611fSSimon Glass /* Parse the data that only we need */
154*e160f7d4SSimon Glass pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
15539f7611fSSimon Glass "character", '@');
15639f7611fSSimon Glass
15739f7611fSSimon Glass return 0;
15839f7611fSSimon Glass }
15939f7611fSSimon Glass
dm_shape_probe(struct udevice * dev)160a02af4aeSSimon Glass static int dm_shape_probe(struct udevice *dev)
161a02af4aeSSimon Glass {
162a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev);
163a02af4aeSSimon Glass int ret;
164a02af4aeSSimon Glass
165a02af4aeSSimon Glass ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
166a02af4aeSSimon Glass ARRAY_SIZE(priv->gpio_desc),
167a02af4aeSSimon Glass GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
168a02af4aeSSimon Glass if (ret < 0)
169a02af4aeSSimon Glass return ret;
170a02af4aeSSimon Glass priv->gpio_count = ret;
171a02af4aeSSimon Glass debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
172a02af4aeSSimon Glass
173a02af4aeSSimon Glass return 0;
174a02af4aeSSimon Glass }
175a02af4aeSSimon Glass
dm_shape_remove(struct udevice * dev)176a02af4aeSSimon Glass static int dm_shape_remove(struct udevice *dev)
177a02af4aeSSimon Glass {
178a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev);
179a02af4aeSSimon Glass
180a02af4aeSSimon Glass return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
181a02af4aeSSimon Glass }
182a02af4aeSSimon Glass
183ae7f4513SSimon Glass static const struct udevice_id demo_shape_id[] = {
18439f7611fSSimon Glass { "demo-shape", 0 },
18539f7611fSSimon Glass { },
18639f7611fSSimon Glass };
18739f7611fSSimon Glass
18839f7611fSSimon Glass U_BOOT_DRIVER(demo_shape_drv) = {
18939f7611fSSimon Glass .name = "demo_shape_drv",
19039f7611fSSimon Glass .of_match = demo_shape_id,
19139f7611fSSimon Glass .id = UCLASS_DEMO,
19239f7611fSSimon Glass .ofdata_to_platdata = shape_ofdata_to_platdata,
19339f7611fSSimon Glass .ops = &shape_ops,
194a02af4aeSSimon Glass .probe = dm_shape_probe,
195a02af4aeSSimon Glass .remove = dm_shape_remove,
19639f7611fSSimon Glass .priv_auto_alloc_size = sizeof(struct shape_data),
19739f7611fSSimon Glass .platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
19839f7611fSSimon Glass };
199