dm: demo: Add a simple GPIO demonstration
Add a new 'demo light' command which uses GPIOs to control imaginary lights. Each light is assigned a bit number in the overall value. This provides an example driver for using the new GPIO API. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
5d1c17e9a5
commit
a02af4aeec
@ -19,6 +19,7 @@
|
||||
colour = "cyan";
|
||||
sides = <3>;
|
||||
character = <83>;
|
||||
light-gpios = <&gpio_a 2>, <&gpio_b 6 0>;
|
||||
};
|
||||
square {
|
||||
compatible = "demo-shape";
|
||||
@ -126,7 +127,7 @@
|
||||
0x070b0067 0x070c0069>;
|
||||
};
|
||||
|
||||
gpio_a: gpios {
|
||||
gpio_a: gpios@0 {
|
||||
gpio-controller;
|
||||
compatible = "sandbox,gpio";
|
||||
#gpio-cells = <1>;
|
||||
@ -134,6 +135,14 @@
|
||||
num-gpios = <20>;
|
||||
};
|
||||
|
||||
gpio_b: gpios@1 {
|
||||
gpio-controller;
|
||||
compatible = "sandbox,gpio";
|
||||
#gpio-cells = <2>;
|
||||
gpio-bank-name = "b";
|
||||
num-gpios = <10>;
|
||||
};
|
||||
|
||||
i2c@0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -39,6 +39,26 @@ static int do_demo_status(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_demo_light(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
int light;
|
||||
int ret;
|
||||
|
||||
if (argc) {
|
||||
light = simple_strtoul(argv[0], NULL, 16);
|
||||
ret = demo_set_light(demo_dev, light);
|
||||
} else {
|
||||
ret = demo_get_light(demo_dev);
|
||||
if (ret >= 0) {
|
||||
printf("Light: %x\n", ret);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct udevice *dev;
|
||||
@ -61,6 +81,7 @@ int do_demo_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
static cmd_tbl_t demo_commands[] = {
|
||||
U_BOOT_CMD_MKENT(list, 0, 1, do_demo_list, "", ""),
|
||||
U_BOOT_CMD_MKENT(hello, 2, 1, do_demo_hello, "", ""),
|
||||
U_BOOT_CMD_MKENT(light, 2, 1, do_demo_light, "", ""),
|
||||
U_BOOT_CMD_MKENT(status, 1, 1, do_demo_status, "", ""),
|
||||
};
|
||||
|
||||
@ -86,6 +107,10 @@ static int do_demo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
return cmd_process_error(cmdtp, ret);
|
||||
argc--;
|
||||
argv++;
|
||||
} else {
|
||||
demo_dev = NULL;
|
||||
if (demo_cmd->cmd != do_demo_list)
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
ret = demo_cmd->cmd(demo_cmd, flag, argc, argv);
|
||||
@ -98,5 +123,7 @@ U_BOOT_CMD(
|
||||
"Driver model (dm) demo operations",
|
||||
"list List available demo devices\n"
|
||||
"demo hello <num> [<char>] Say hello\n"
|
||||
"demo status <num> Get demo device status"
|
||||
"demo light [<num>] Set or get the lights\n"
|
||||
"demo status <num> Get demo device status\n"
|
||||
"demo list List available demo devices"
|
||||
);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <malloc.h>
|
||||
#include <dm-demo.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
@ -20,6 +21,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
struct shape_data {
|
||||
int num_chars; /* Number of non-space characters output so far */
|
||||
struct gpio_desc gpio_desc[8];
|
||||
int gpio_count;
|
||||
};
|
||||
|
||||
/* Crazy little function to draw shapes on the console */
|
||||
@ -89,9 +92,52 @@ static int shape_status(struct udevice *dev, int *status)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_light(struct udevice *dev, int light)
|
||||
{
|
||||
struct shape_data *priv = dev_get_priv(dev);
|
||||
struct gpio_desc *desc;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
desc = priv->gpio_desc;
|
||||
for (i = 0; i < priv->gpio_count; i++, desc++) {
|
||||
uint mask = 1 << i;
|
||||
|
||||
ret = dm_gpio_set_value(desc, light & mask);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_light(struct udevice *dev)
|
||||
{
|
||||
struct shape_data *priv = dev_get_priv(dev);
|
||||
struct gpio_desc *desc;
|
||||
uint value = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
desc = priv->gpio_desc;
|
||||
for (i = 0; i < priv->gpio_count; i++, desc++) {
|
||||
uint mask = 1 << i;
|
||||
|
||||
ret = dm_gpio_get_value(desc);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret)
|
||||
value |= mask;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const struct demo_ops shape_ops = {
|
||||
.hello = shape_hello,
|
||||
.status = shape_status,
|
||||
.get_light = get_light,
|
||||
.set_light = set_light,
|
||||
};
|
||||
|
||||
static int shape_ofdata_to_platdata(struct udevice *dev)
|
||||
@ -111,6 +157,29 @@ static int shape_ofdata_to_platdata(struct udevice *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm_shape_probe(struct udevice *dev)
|
||||
{
|
||||
struct shape_data *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = gpio_request_list_by_name(dev, "light-gpios", priv->gpio_desc,
|
||||
ARRAY_SIZE(priv->gpio_desc),
|
||||
GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
priv->gpio_count = ret;
|
||||
debug("%s: %d GPIOs\n", __func__, priv->gpio_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dm_shape_remove(struct udevice *dev)
|
||||
{
|
||||
struct shape_data *priv = dev_get_priv(dev);
|
||||
|
||||
return gpio_free_list(dev, priv->gpio_desc, priv->gpio_count);
|
||||
}
|
||||
|
||||
static const struct udevice_id demo_shape_id[] = {
|
||||
{ "demo-shape", 0 },
|
||||
{ },
|
||||
@ -122,6 +191,8 @@ U_BOOT_DRIVER(demo_shape_drv) = {
|
||||
.id = UCLASS_DEMO,
|
||||
.ofdata_to_platdata = shape_ofdata_to_platdata,
|
||||
.ops = &shape_ops,
|
||||
.probe = dm_shape_probe,
|
||||
.remove = dm_shape_remove,
|
||||
.priv_auto_alloc_size = sizeof(struct shape_data),
|
||||
.platdata_auto_alloc_size = sizeof(struct dm_demo_pdata),
|
||||
};
|
||||
|
@ -43,6 +43,26 @@ int demo_status(struct udevice *dev, int *status)
|
||||
return ops->status(dev, status);
|
||||
}
|
||||
|
||||
int demo_get_light(struct udevice *dev)
|
||||
{
|
||||
const struct demo_ops *ops = device_get_ops(dev);
|
||||
|
||||
if (!ops->get_light)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->get_light(dev);
|
||||
}
|
||||
|
||||
int demo_set_light(struct udevice *dev, int light)
|
||||
{
|
||||
const struct demo_ops *ops = device_get_ops(dev);
|
||||
|
||||
if (!ops->set_light)
|
||||
return -ENOSYS;
|
||||
|
||||
return ops->set_light(dev, light);
|
||||
}
|
||||
|
||||
int demo_parse_dt(struct udevice *dev)
|
||||
{
|
||||
struct dm_demo_pdata *pdata = dev_get_platdata(dev);
|
||||
|
@ -25,10 +25,14 @@ struct dm_demo_pdata {
|
||||
struct demo_ops {
|
||||
int (*hello)(struct udevice *dev, int ch);
|
||||
int (*status)(struct udevice *dev, int *status);
|
||||
int (*set_light)(struct udevice *dev, int light);
|
||||
int (*get_light)(struct udevice *dev);
|
||||
};
|
||||
|
||||
int demo_hello(struct udevice *dev, int ch);
|
||||
int demo_status(struct udevice *dev, int *status);
|
||||
int demo_set_light(struct udevice *dev, int light);
|
||||
int demo_get_light(struct udevice *dev);
|
||||
int demo_list(void);
|
||||
|
||||
int demo_parse_dt(struct udevice *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user