Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: rockchip: power-domain: support qos save and restore

support qos save and restore when power domain on/off.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>

authored by

Elaine Zhang and committed by
Heiko Stuebner
074c6a42 71daabca

+102 -3
+102 -3
drivers/soc/rockchip/pm_domains.c
··· 46 46 const struct rockchip_domain_info *domain_info; 47 47 }; 48 48 49 + #define MAX_QOS_REGS_NUM 5 50 + #define QOS_PRIORITY 0x08 51 + #define QOS_MODE 0x0c 52 + #define QOS_BANDWIDTH 0x10 53 + #define QOS_SATURATION 0x14 54 + #define QOS_EXTCONTROL 0x18 55 + 49 56 struct rockchip_pm_domain { 50 57 struct generic_pm_domain genpd; 51 58 const struct rockchip_domain_info *info; 52 59 struct rockchip_pmu *pmu; 60 + int num_qos; 61 + struct regmap **qos_regmap; 62 + u32 *qos_save_regs[MAX_QOS_REGS_NUM]; 53 63 int num_clks; 54 64 struct clk *clks[]; 55 65 }; ··· 128 118 return 0; 129 119 } 130 120 121 + static int rockchip_pmu_save_qos(struct rockchip_pm_domain *pd) 122 + { 123 + int i; 124 + 125 + for (i = 0; i < pd->num_qos; i++) { 126 + regmap_read(pd->qos_regmap[i], 127 + QOS_PRIORITY, 128 + &pd->qos_save_regs[0][i]); 129 + regmap_read(pd->qos_regmap[i], 130 + QOS_MODE, 131 + &pd->qos_save_regs[1][i]); 132 + regmap_read(pd->qos_regmap[i], 133 + QOS_BANDWIDTH, 134 + &pd->qos_save_regs[2][i]); 135 + regmap_read(pd->qos_regmap[i], 136 + QOS_SATURATION, 137 + &pd->qos_save_regs[3][i]); 138 + regmap_read(pd->qos_regmap[i], 139 + QOS_EXTCONTROL, 140 + &pd->qos_save_regs[4][i]); 141 + } 142 + return 0; 143 + } 144 + 145 + static int rockchip_pmu_restore_qos(struct rockchip_pm_domain *pd) 146 + { 147 + int i; 148 + 149 + for (i = 0; i < pd->num_qos; i++) { 150 + regmap_write(pd->qos_regmap[i], 151 + QOS_PRIORITY, 152 + pd->qos_save_regs[0][i]); 153 + regmap_write(pd->qos_regmap[i], 154 + QOS_MODE, 155 + pd->qos_save_regs[1][i]); 156 + regmap_write(pd->qos_regmap[i], 157 + QOS_BANDWIDTH, 158 + pd->qos_save_regs[2][i]); 159 + regmap_write(pd->qos_regmap[i], 160 + QOS_SATURATION, 161 + pd->qos_save_regs[3][i]); 162 + regmap_write(pd->qos_regmap[i], 163 + QOS_EXTCONTROL, 164 + pd->qos_save_regs[4][i]); 165 + } 166 + 167 + return 0; 168 + } 169 + 131 170 static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd) 132 171 { 133 172 struct rockchip_pmu *pmu = pd->pmu; ··· 220 161 clk_enable(pd->clks[i]); 221 162 222 163 if (!power_on) { 223 - /* FIXME: add code to save AXI_QOS */ 164 + rockchip_pmu_save_qos(pd); 224 165 225 166 /* if powering down, idle request to NIU first */ 226 167 rockchip_pmu_set_idle_request(pd, true); ··· 232 173 /* if powering up, leave idle mode */ 233 174 rockchip_pmu_set_idle_request(pd, false); 234 175 235 - /* FIXME: add code to restore AXI_QOS */ 176 + rockchip_pmu_restore_qos(pd); 236 177 } 237 178 238 179 for (i = pd->num_clks - 1; i >= 0; i--) ··· 300 241 { 301 242 const struct rockchip_domain_info *pd_info; 302 243 struct rockchip_pm_domain *pd; 244 + struct device_node *qos_node; 303 245 struct clk *clk; 304 246 int clk_cnt; 305 - int i; 247 + int i, j; 306 248 u32 id; 307 249 int error; 308 250 ··· 361 301 362 302 dev_dbg(pmu->dev, "added clock '%pC' to domain '%s'\n", 363 303 clk, node->name); 304 + } 305 + 306 + pd->num_qos = of_count_phandle_with_args(node, "pm_qos", 307 + NULL); 308 + 309 + if (pd->num_qos > 0) { 310 + pd->qos_regmap = devm_kcalloc(pmu->dev, pd->num_qos, 311 + sizeof(*pd->qos_regmap), 312 + GFP_KERNEL); 313 + if (!pd->qos_regmap) { 314 + error = -ENOMEM; 315 + goto err_out; 316 + } 317 + 318 + for (j = 0; j < MAX_QOS_REGS_NUM; j++) { 319 + pd->qos_save_regs[j] = devm_kcalloc(pmu->dev, 320 + pd->num_qos, 321 + sizeof(u32), 322 + GFP_KERNEL); 323 + if (!pd->qos_save_regs[j]) { 324 + error = -ENOMEM; 325 + goto err_out; 326 + } 327 + } 328 + 329 + for (j = 0; j < pd->num_qos; j++) { 330 + qos_node = of_parse_phandle(node, "pm_qos", j); 331 + if (!qos_node) { 332 + error = -ENODEV; 333 + goto err_out; 334 + } 335 + pd->qos_regmap[j] = syscon_node_to_regmap(qos_node); 336 + if (IS_ERR(pd->qos_regmap[j])) { 337 + error = -ENODEV; 338 + of_node_put(qos_node); 339 + goto err_out; 340 + } 341 + of_node_put(qos_node); 342 + } 364 343 } 365 344 366 345 error = rockchip_pd_power(pd, true);