dm: core: Create a new header file for 'compat' features
[oweals/u-boot.git] / drivers / power / domain / imx8m-power-domain.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2017 NXP
4  */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <malloc.h>
9 #include <power-domain-uclass.h>
10 #include <asm/io.h>
11 #include <asm/arch/power-domain.h>
12 #include <asm/mach-imx/sys_proto.h>
13 #include <dm/device-internal.h>
14 #include <dm/device.h>
15 #include <imx_sip.h>
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 static int imx8m_power_domain_request(struct power_domain *power_domain)
20 {
21         return 0;
22 }
23
24 static int imx8m_power_domain_free(struct power_domain *power_domain)
25 {
26         return 0;
27 }
28
29 static int imx8m_power_domain_on(struct power_domain *power_domain)
30 {
31         struct udevice *dev = power_domain->dev;
32         struct imx8m_power_domain_platdata *pdata;
33         pdata = dev_get_platdata(dev);
34
35         if (pdata->resource_id < 0)
36                 return -EINVAL;
37
38         if (pdata->has_pd)
39                 power_domain_on(&pdata->pd);
40
41         call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
42                      pdata->resource_id, 1, 0);
43
44         return 0;
45 }
46
47 static int imx8m_power_domain_off(struct power_domain *power_domain)
48 {
49         struct udevice *dev = power_domain->dev;
50         struct imx8m_power_domain_platdata *pdata;
51         pdata = dev_get_platdata(dev);
52
53         if (pdata->resource_id < 0)
54                 return -EINVAL;
55
56         call_imx_sip(IMX_SIP_GPC, IMX_SIP_GPC_PM_DOMAIN,
57                      pdata->resource_id, 0, 0);
58
59         if (pdata->has_pd)
60                 power_domain_off(&pdata->pd);
61
62         return 0;
63 }
64
65 static int imx8m_power_domain_of_xlate(struct power_domain *power_domain,
66                                       struct ofnode_phandle_args *args)
67 {
68         return 0;
69 }
70
71 static int imx8m_power_domain_bind(struct udevice *dev)
72 {
73         int offset;
74         const char *name;
75         int ret = 0;
76
77         offset = dev_of_offset(dev);
78         for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
79              offset = fdt_next_subnode(gd->fdt_blob, offset)) {
80                 /* Bind the subnode to this driver */
81                 name = fdt_get_name(gd->fdt_blob, offset, NULL);
82
83                 ret = device_bind_with_driver_data(dev, dev->driver, name,
84                                                    dev->driver_data,
85                                                    offset_to_ofnode(offset),
86                                                    NULL);
87
88                 if (ret == -ENODEV)
89                         printf("Driver '%s' refuses to bind\n",
90                                dev->driver->name);
91
92                 if (ret)
93                         printf("Error binding driver '%s': %d\n",
94                                dev->driver->name, ret);
95         }
96
97         return 0;
98 }
99
100 static int imx8m_power_domain_probe(struct udevice *dev)
101 {
102         return 0;
103 }
104
105 static int imx8m_power_domain_ofdata_to_platdata(struct udevice *dev)
106 {
107         struct imx8m_power_domain_platdata *pdata = dev_get_platdata(dev);
108
109         pdata->resource_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
110                                             "reg", -1);
111
112         if (!power_domain_get(dev, &pdata->pd))
113                 pdata->has_pd = 1;
114
115         return 0;
116 }
117
118 static const struct udevice_id imx8m_power_domain_ids[] = {
119         { .compatible = "fsl,imx8mq-gpc" },
120         { }
121 };
122
123 struct power_domain_ops imx8m_power_domain_ops = {
124         .request = imx8m_power_domain_request,
125         .rfree = imx8m_power_domain_free,
126         .on = imx8m_power_domain_on,
127         .off = imx8m_power_domain_off,
128         .of_xlate = imx8m_power_domain_of_xlate,
129 };
130
131 U_BOOT_DRIVER(imx8m_power_domain) = {
132         .name = "imx8m_power_domain",
133         .id = UCLASS_POWER_DOMAIN,
134         .of_match = imx8m_power_domain_ids,
135         .bind = imx8m_power_domain_bind,
136         .probe = imx8m_power_domain_probe,
137         .ofdata_to_platdata = imx8m_power_domain_ofdata_to_platdata,
138         .platdata_auto_alloc_size = sizeof(struct imx8m_power_domain_platdata),
139         .ops = &imx8m_power_domain_ops,
140 };