1 /* 2 * Copyright (c) 2016, NVIDIA CORPORATION. 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <misc.h> 10 #include <power-domain-uclass.h> 11 #include <asm/arch-tegra/bpmp_abi.h> 12 13 #define UPDATE BIT(0) 14 #define ON BIT(1) 15 16 static int tegra186_power_domain_common(struct power_domain *power_domain, 17 bool on) 18 { 19 struct mrq_pg_update_state_request req; 20 int on_state = on ? ON : 0; 21 int ret; 22 23 req.partition_id = power_domain->id; 24 req.logic_state = UPDATE | on_state; 25 req.sram_state = UPDATE | on_state; 26 /* 27 * Drivers manage their own clocks so they don't get out of sync, and 28 * since some power domains have many clocks, only a subset of which 29 * are actually needed depending on use-case. 30 */ 31 req.clock_state = UPDATE; 32 33 ret = misc_call(power_domain->dev->parent, MRQ_PG_UPDATE_STATE, &req, 34 sizeof(req), NULL, 0); 35 if (ret < 0) 36 return ret; 37 38 return 0; 39 } 40 41 static int tegra186_power_domain_on(struct power_domain *power_domain) 42 { 43 debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__, 44 power_domain, power_domain->dev, power_domain->id); 45 46 return tegra186_power_domain_common(power_domain, true); 47 } 48 49 static int tegra186_power_domain_off(struct power_domain *power_domain) 50 { 51 debug("%s(power_domain=%p) (dev=%p, id=%lu)\n", __func__, 52 power_domain, power_domain->dev, power_domain->id); 53 54 return tegra186_power_domain_common(power_domain, false); 55 } 56 57 struct power_domain_ops tegra186_power_domain_ops = { 58 .on = tegra186_power_domain_on, 59 .off = tegra186_power_domain_off, 60 }; 61 62 U_BOOT_DRIVER(tegra186_power_domain) = { 63 .name = "tegra186_power_domain", 64 .id = UCLASS_POWER_DOMAIN, 65 .ops = &tegra186_power_domain_ops, 66 }; 67