From 50af9be8086dda5febc62f2e9f254720180a748b Mon Sep 17 00:00:00 2001 From: David Phillips Date: Sun, 16 May 2021 19:38:05 +1200 Subject: Add reset driver and consumer for debugging it --- cds9k-reset.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 cds9k-reset.c (limited to 'cds9k-reset.c') diff --git a/cds9k-reset.c b/cds9k-reset.c new file mode 100644 index 0000000..d90ed7e --- /dev/null +++ b/cds9k-reset.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +#define RESET_REG_0 0x0 + +struct cds9k_reset_priv { + struct reset_controller_dev rcdev; + struct regmap *regmap; + u32 base; +}; + +static int cds9k_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + struct cds9k_reset_priv *priv = container_of(rcdev, struct cds9k_reset_priv, rcdev); + + /* reset sequence: put 0xDEAD into reg 0 for 250 ms */ + struct reg_sequence reset_sequence[] = { + { RESET_REG_0, 0xDEAD, 250000 }, + { RESET_REG_0, 0x0000 }, + }; + + if (id != 0) + return -EINVAL; + + return regmap_multi_reg_write(priv->regmap, reset_sequence, ARRAY_SIZE(reset_sequence)); +} + +static int cds9k_reset_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *spec) +{ + /* single reset */ + return 0; +} + +const struct reset_control_ops cds9k_reset_ops = { + .reset = cds9k_reset_reset, +}; + +static int cds9k_reset_probe(struct platform_device *pdev) +{ + struct cds9k_reset_priv *priv; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + platform_set_drvdata(pdev, priv); + + ret = device_property_read_u32(&pdev->dev, "reg", &priv->base); + if (ret) + return -EINVAL; + + if (!pdev->dev.parent) + return -ENODEV; + + priv->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!priv->regmap) + return -ENODEV; + + priv->rcdev.ops = &cds9k_reset_ops; + priv->rcdev.owner = pdev->dev.driver->owner; + priv->rcdev.of_node = pdev->dev.of_node; + priv->rcdev.nr_resets = 1; + priv->rcdev.of_reset_n_cells = 0; + priv->rcdev.of_xlate = cds9k_reset_xlate; + + return devm_reset_controller_register(&pdev->dev, &priv->rcdev); +} + +static struct of_device_id cds9k_reset_of_match[] = { + { .compatible = "david,cds9k-reset" }, + {} +}; +MODULE_DEVICE_TABLE(of, cds9k_reset_of_match); + +static struct platform_driver cds9k_reset = { + .driver = { + .name = "cds9k-reset", + .of_match_table = cds9k_reset_of_match, + }, + .probe = cds9k_reset_probe +}; +module_platform_driver(cds9k_reset); + +MODULE_AUTHOR("David Phillips "); +MODULE_DESCRIPTION("Reset driver for the CDS9K board controller"); +MODULE_LICENSE("GPL v2"); -- cgit v1.1