1 // SPDX-License-Identifier: GPL-2.0+
3 * Texas Instruments System Control Interface (TI SCI) power domain driver
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6 * Andreas Dannenberg <dannenberg@ti.com>
8 * Loosely based on Linux kernel ti_sci_pm_domains.c...
14 #include <power-domain-uclass.h>
15 #include <linux/soc/ti/ti_sci_protocol.h>
16 #include <dt-bindings/soc/ti,sci_pm_domain.h>
19 * struct ti_sci_power_domain_data - pm domain controller information structure
20 * @sci: TI SCI handle used for communication with system controller
22 struct ti_sci_power_domain_data
{
23 const struct ti_sci_handle
*sci
;
26 static int ti_sci_power_domain_probe(struct udevice
*dev
)
28 struct ti_sci_power_domain_data
*data
= dev_get_priv(dev
);
30 debug("%s(dev=%p)\n", __func__
, dev
);
35 /* Store handle for communication with the system controller */
36 data
->sci
= ti_sci_get_handle(dev
);
37 if (IS_ERR(data
->sci
))
38 return PTR_ERR(data
->sci
);
43 static int ti_sci_power_domain_request(struct power_domain
*pd
)
45 debug("%s(pd=%p)\n", __func__
, pd
);
49 static int ti_sci_power_domain_free(struct power_domain
*pd
)
51 debug("%s(pd=%p)\n", __func__
, pd
);
55 static int ti_sci_power_domain_on(struct power_domain
*pd
)
57 struct ti_sci_power_domain_data
*data
= dev_get_priv(pd
->dev
);
58 const struct ti_sci_handle
*sci
= data
->sci
;
59 const struct ti_sci_dev_ops
*dops
= &sci
->ops
.dev_ops
;
60 u8 flags
= (uintptr_t)pd
->priv
;
63 debug("%s(pd=%p)\n", __func__
, pd
);
65 if (flags
& TI_SCI_PD_EXCLUSIVE
)
66 ret
= dops
->get_device_exclusive(sci
, pd
->id
);
68 ret
= dops
->get_device(sci
, pd
->id
);
71 dev_err(pd
->dev
, "%s: get_device(%lu) failed (%d)\n",
72 __func__
, pd
->id
, ret
);
77 static int ti_sci_power_domain_off(struct power_domain
*pd
)
79 struct ti_sci_power_domain_data
*data
= dev_get_priv(pd
->dev
);
80 const struct ti_sci_handle
*sci
= data
->sci
;
81 const struct ti_sci_dev_ops
*dops
= &sci
->ops
.dev_ops
;
84 debug("%s(pd=%p)\n", __func__
, pd
);
86 ret
= dops
->put_device(sci
, pd
->id
);
88 dev_err(pd
->dev
, "%s: put_device(%lu) failed (%d)\n",
89 __func__
, pd
->id
, ret
);
94 static int ti_sci_power_domain_of_xlate(struct power_domain
*pd
,
95 struct ofnode_phandle_args
*args
)
99 debug("%s(power_domain=%p)\n", __func__
, pd
);
101 if (args
->args_count
< 1) {
102 debug("Invalid args_count: %d\n", args
->args_count
);
106 pd
->id
= args
->args
[0];
107 /* By default request for device exclusive */
108 flags
= TI_SCI_PD_EXCLUSIVE
;
109 if (args
->args_count
== 2)
110 flags
= args
->args
[1] & TI_SCI_PD_EXCLUSIVE
;
111 pd
->priv
= (void *)(uintptr_t)flags
;
116 static const struct udevice_id ti_sci_power_domain_of_match
[] = {
117 { .compatible
= "ti,sci-pm-domain" },
121 static struct power_domain_ops ti_sci_power_domain_ops
= {
122 .request
= ti_sci_power_domain_request
,
123 .free
= ti_sci_power_domain_free
,
124 .on
= ti_sci_power_domain_on
,
125 .off
= ti_sci_power_domain_off
,
126 .of_xlate
= ti_sci_power_domain_of_xlate
,
129 U_BOOT_DRIVER(ti_sci_pm_domains
) = {
130 .name
= "ti-sci-pm-domains",
131 .id
= UCLASS_POWER_DOMAIN
,
132 .of_match
= ti_sci_power_domain_of_match
,
133 .probe
= ti_sci_power_domain_probe
,
134 .priv_auto_alloc_size
= sizeof(struct ti_sci_power_domain_data
),
135 .ops
= &ti_sci_power_domain_ops
,