1*d9fd7008SStephen Warren /* 2*d9fd7008SStephen Warren * Copyright (c) 2016, NVIDIA CORPORATION. 3*d9fd7008SStephen Warren * 4*d9fd7008SStephen Warren * SPDX-License-Identifier: GPL-2.0 5*d9fd7008SStephen Warren */ 6*d9fd7008SStephen Warren 7*d9fd7008SStephen Warren #include <common.h> 8*d9fd7008SStephen Warren #include <clk-uclass.h> 9*d9fd7008SStephen Warren #include <dm.h> 10*d9fd7008SStephen Warren #include <misc.h> 11*d9fd7008SStephen Warren #include <asm/arch-tegra/bpmp_abi.h> 12*d9fd7008SStephen Warren 13*d9fd7008SStephen Warren static ulong tegra186_clk_get_rate(struct clk *clk) 14*d9fd7008SStephen Warren { 15*d9fd7008SStephen Warren struct mrq_clk_request req; 16*d9fd7008SStephen Warren struct mrq_clk_response resp; 17*d9fd7008SStephen Warren int ret; 18*d9fd7008SStephen Warren 19*d9fd7008SStephen Warren debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev, 20*d9fd7008SStephen Warren clk->id); 21*d9fd7008SStephen Warren 22*d9fd7008SStephen Warren req.cmd_and_id = (CMD_CLK_GET_RATE << 24) | clk->id; 23*d9fd7008SStephen Warren 24*d9fd7008SStephen Warren ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp, 25*d9fd7008SStephen Warren sizeof(resp)); 26*d9fd7008SStephen Warren if (ret < 0) 27*d9fd7008SStephen Warren return ret; 28*d9fd7008SStephen Warren 29*d9fd7008SStephen Warren return resp.clk_get_rate.rate; 30*d9fd7008SStephen Warren } 31*d9fd7008SStephen Warren 32*d9fd7008SStephen Warren static ulong tegra186_clk_set_rate(struct clk *clk, ulong rate) 33*d9fd7008SStephen Warren { 34*d9fd7008SStephen Warren struct mrq_clk_request req; 35*d9fd7008SStephen Warren struct mrq_clk_response resp; 36*d9fd7008SStephen Warren int ret; 37*d9fd7008SStephen Warren 38*d9fd7008SStephen Warren debug("%s(clk=%p, rate=%lu) (dev=%p, id=%lu)\n", __func__, clk, rate, 39*d9fd7008SStephen Warren clk->dev, clk->id); 40*d9fd7008SStephen Warren 41*d9fd7008SStephen Warren req.cmd_and_id = (CMD_CLK_SET_RATE << 24) | clk->id; 42*d9fd7008SStephen Warren req.clk_set_rate.rate = rate; 43*d9fd7008SStephen Warren 44*d9fd7008SStephen Warren ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp, 45*d9fd7008SStephen Warren sizeof(resp)); 46*d9fd7008SStephen Warren if (ret < 0) 47*d9fd7008SStephen Warren return ret; 48*d9fd7008SStephen Warren 49*d9fd7008SStephen Warren return resp.clk_set_rate.rate; 50*d9fd7008SStephen Warren } 51*d9fd7008SStephen Warren 52*d9fd7008SStephen Warren static int tegra186_clk_en_dis(struct clk *clk, 53*d9fd7008SStephen Warren enum mrq_reset_commands cmd) 54*d9fd7008SStephen Warren { 55*d9fd7008SStephen Warren struct mrq_clk_request req; 56*d9fd7008SStephen Warren struct mrq_clk_response resp; 57*d9fd7008SStephen Warren int ret; 58*d9fd7008SStephen Warren 59*d9fd7008SStephen Warren req.cmd_and_id = (cmd << 24) | clk->id; 60*d9fd7008SStephen Warren 61*d9fd7008SStephen Warren ret = misc_call(clk->dev->parent, MRQ_CLK, &req, sizeof(req), &resp, 62*d9fd7008SStephen Warren sizeof(resp)); 63*d9fd7008SStephen Warren if (ret < 0) 64*d9fd7008SStephen Warren return ret; 65*d9fd7008SStephen Warren 66*d9fd7008SStephen Warren return 0; 67*d9fd7008SStephen Warren } 68*d9fd7008SStephen Warren 69*d9fd7008SStephen Warren static int tegra186_clk_enable(struct clk *clk) 70*d9fd7008SStephen Warren { 71*d9fd7008SStephen Warren debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev, 72*d9fd7008SStephen Warren clk->id); 73*d9fd7008SStephen Warren 74*d9fd7008SStephen Warren return tegra186_clk_en_dis(clk, CMD_CLK_ENABLE); 75*d9fd7008SStephen Warren } 76*d9fd7008SStephen Warren 77*d9fd7008SStephen Warren static int tegra186_clk_disable(struct clk *clk) 78*d9fd7008SStephen Warren { 79*d9fd7008SStephen Warren debug("%s(clk=%p) (dev=%p, id=%lu)\n", __func__, clk, clk->dev, 80*d9fd7008SStephen Warren clk->id); 81*d9fd7008SStephen Warren 82*d9fd7008SStephen Warren return tegra186_clk_en_dis(clk, CMD_CLK_DISABLE); 83*d9fd7008SStephen Warren } 84*d9fd7008SStephen Warren 85*d9fd7008SStephen Warren static struct clk_ops tegra186_clk_ops = { 86*d9fd7008SStephen Warren .get_rate = tegra186_clk_get_rate, 87*d9fd7008SStephen Warren .set_rate = tegra186_clk_set_rate, 88*d9fd7008SStephen Warren .enable = tegra186_clk_enable, 89*d9fd7008SStephen Warren .disable = tegra186_clk_disable, 90*d9fd7008SStephen Warren }; 91*d9fd7008SStephen Warren 92*d9fd7008SStephen Warren static int tegra186_clk_probe(struct udevice *dev) 93*d9fd7008SStephen Warren { 94*d9fd7008SStephen Warren debug("%s(dev=%p)\n", __func__, dev); 95*d9fd7008SStephen Warren 96*d9fd7008SStephen Warren return 0; 97*d9fd7008SStephen Warren } 98*d9fd7008SStephen Warren 99*d9fd7008SStephen Warren U_BOOT_DRIVER(tegra186_clk) = { 100*d9fd7008SStephen Warren .name = "tegra186_clk", 101*d9fd7008SStephen Warren .id = UCLASS_CLK, 102*d9fd7008SStephen Warren .probe = tegra186_clk_probe, 103*d9fd7008SStephen Warren .ops = &tegra186_clk_ops, 104*d9fd7008SStephen Warren }; 105