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> 14*a02af4aeSSimon 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 */ 24*a02af4aeSSimon Glass struct gpio_desc gpio_desc[8]; 25*a02af4aeSSimon Glass int gpio_count; 2639f7611fSSimon Glass }; 2739f7611fSSimon Glass 2839f7611fSSimon Glass /* Crazy little function to draw shapes on the console */ 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 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 95*a02af4aeSSimon Glass static int set_light(struct udevice *dev, int light) 96*a02af4aeSSimon Glass { 97*a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev); 98*a02af4aeSSimon Glass struct gpio_desc *desc; 99*a02af4aeSSimon Glass int ret; 100*a02af4aeSSimon Glass int i; 101*a02af4aeSSimon Glass 102*a02af4aeSSimon Glass desc = priv->gpio_desc; 103*a02af4aeSSimon Glass for (i = 0; i < priv->gpio_count; i++, desc++) { 104*a02af4aeSSimon Glass uint mask = 1 << i; 105*a02af4aeSSimon Glass 106*a02af4aeSSimon Glass ret = dm_gpio_set_value(desc, light & mask); 107*a02af4aeSSimon Glass if (ret < 0) 108*a02af4aeSSimon Glass return ret; 109*a02af4aeSSimon Glass } 110*a02af4aeSSimon Glass 111*a02af4aeSSimon Glass return 0; 112*a02af4aeSSimon Glass } 113*a02af4aeSSimon Glass 114*a02af4aeSSimon Glass static int get_light(struct udevice *dev) 115*a02af4aeSSimon Glass { 116*a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev); 117*a02af4aeSSimon Glass struct gpio_desc *desc; 118*a02af4aeSSimon Glass uint value = 0; 119*a02af4aeSSimon Glass int ret; 120*a02af4aeSSimon Glass int i; 121*a02af4aeSSimon Glass 122*a02af4aeSSimon Glass desc = priv->gpio_desc; 123*a02af4aeSSimon Glass for (i = 0; i < priv->gpio_count; i++, desc++) { 124*a02af4aeSSimon Glass uint mask = 1 << i; 125*a02af4aeSSimon Glass 126*a02af4aeSSimon Glass ret = dm_gpio_get_value(desc); 127*a02af4aeSSimon Glass if (ret < 0) 128*a02af4aeSSimon Glass return ret; 129*a02af4aeSSimon Glass if (ret) 130*a02af4aeSSimon Glass value |= mask; 131*a02af4aeSSimon Glass } 132*a02af4aeSSimon Glass 133*a02af4aeSSimon Glass return value; 134*a02af4aeSSimon Glass } 135*a02af4aeSSimon Glass 13639f7611fSSimon Glass static const struct demo_ops shape_ops = { 13739f7611fSSimon Glass .hello = shape_hello, 13839f7611fSSimon Glass .status = shape_status, 139*a02af4aeSSimon Glass .get_light = get_light, 140*a02af4aeSSimon Glass .set_light = set_light, 14139f7611fSSimon Glass }; 14239f7611fSSimon Glass 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 */ 15439f7611fSSimon Glass pdata->default_char = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 15539f7611fSSimon Glass "character", '@'); 15639f7611fSSimon Glass 15739f7611fSSimon Glass return 0; 15839f7611fSSimon Glass } 15939f7611fSSimon Glass 160*a02af4aeSSimon Glass static int dm_shape_probe(struct udevice *dev) 161*a02af4aeSSimon Glass { 162*a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev); 163*a02af4aeSSimon Glass int ret; 164*a02af4aeSSimon Glass 165*a02af4aeSSimon Glass ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc, 166*a02af4aeSSimon Glass ARRAY_SIZE(priv->gpio_desc), 167*a02af4aeSSimon Glass GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 168*a02af4aeSSimon Glass if (ret < 0) 169*a02af4aeSSimon Glass return ret; 170*a02af4aeSSimon Glass priv->gpio_count = ret; 171*a02af4aeSSimon Glass debug("%s: %d GPIOs\n", __func__, priv->gpio_count); 172*a02af4aeSSimon Glass 173*a02af4aeSSimon Glass return 0; 174*a02af4aeSSimon Glass } 175*a02af4aeSSimon Glass 176*a02af4aeSSimon Glass static int dm_shape_remove(struct udevice *dev) 177*a02af4aeSSimon Glass { 178*a02af4aeSSimon Glass struct shape_data *priv = dev_get_priv(dev); 179*a02af4aeSSimon Glass 180*a02af4aeSSimon Glass return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count); 181*a02af4aeSSimon Glass } 182*a02af4aeSSimon 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, 194*a02af4aeSSimon Glass .probe = dm_shape_probe, 195*a02af4aeSSimon 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