#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[] = { { priv->base + RESET_REG_0, 0xDEAD, 1500 }, { priv->base + 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; } static 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");