Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Allwinner SoCs Reset Controller driver
0004  *
0005  * Copyright 2013 Maxime Ripard
0006  *
0007  * Maxime Ripard <maxime.ripard@free-electrons.com>
0008  */
0009 
0010 #include <linux/err.h>
0011 #include <linux/io.h>
0012 #include <linux/init.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/reset-controller.h>
0017 #include <linux/reset/reset-simple.h>
0018 #include <linux/reset/sunxi.h>
0019 #include <linux/slab.h>
0020 #include <linux/spinlock.h>
0021 #include <linux/types.h>
0022 
0023 static int sunxi_reset_init(struct device_node *np)
0024 {
0025     struct reset_simple_data *data;
0026     struct resource res;
0027     resource_size_t size;
0028     int ret;
0029 
0030     data = kzalloc(sizeof(*data), GFP_KERNEL);
0031     if (!data)
0032         return -ENOMEM;
0033 
0034     ret = of_address_to_resource(np, 0, &res);
0035     if (ret)
0036         goto err_alloc;
0037 
0038     size = resource_size(&res);
0039     if (!request_mem_region(res.start, size, np->name)) {
0040         ret = -EBUSY;
0041         goto err_alloc;
0042     }
0043 
0044     data->membase = ioremap(res.start, size);
0045     if (!data->membase) {
0046         ret = -ENOMEM;
0047         goto err_alloc;
0048     }
0049 
0050     spin_lock_init(&data->lock);
0051 
0052     data->rcdev.owner = THIS_MODULE;
0053     data->rcdev.nr_resets = size * 8;
0054     data->rcdev.ops = &reset_simple_ops;
0055     data->rcdev.of_node = np;
0056     data->active_low = true;
0057 
0058     return reset_controller_register(&data->rcdev);
0059 
0060 err_alloc:
0061     kfree(data);
0062     return ret;
0063 };
0064 
0065 /*
0066  * These are the reset controller we need to initialize early on in
0067  * our system, before we can even think of using a regular device
0068  * driver for it.
0069  * The controllers that we can register through the regular device
0070  * model are handled by the simple reset driver directly.
0071  */
0072 static const struct of_device_id sunxi_early_reset_dt_ids[] __initconst = {
0073     { .compatible = "allwinner,sun6i-a31-ahb1-reset", },
0074     { /* sentinel */ },
0075 };
0076 
0077 void __init sun6i_reset_init(void)
0078 {
0079     struct device_node *np;
0080 
0081     for_each_matching_node(np, sunxi_early_reset_dt_ids)
0082         sunxi_reset_init(np);
0083 }