1*04150feeSXiaoDong Huang /* 2*04150feeSXiaoDong Huang * Copyright (c) 2024, Rockchip, Inc. All rights reserved. 3*04150feeSXiaoDong Huang * 4*04150feeSXiaoDong Huang * SPDX-License-Identifier: BSD-3-Clause 5*04150feeSXiaoDong Huang */ 6*04150feeSXiaoDong Huang 7*04150feeSXiaoDong Huang #include <drivers/scmi-msg.h> 8*04150feeSXiaoDong Huang #include <drivers/scmi.h> 9*04150feeSXiaoDong Huang 10*04150feeSXiaoDong Huang #include "scmi_clock.h" 11*04150feeSXiaoDong Huang 12*04150feeSXiaoDong Huang #pragma weak rockchip_scmi_clock_count 13*04150feeSXiaoDong Huang #pragma weak rockchip_scmi_get_clock 14*04150feeSXiaoDong Huang 15*04150feeSXiaoDong Huang size_t rockchip_scmi_clock_count(unsigned int agent_id __unused) 16*04150feeSXiaoDong Huang { 17*04150feeSXiaoDong Huang return 0; 18*04150feeSXiaoDong Huang } 19*04150feeSXiaoDong Huang 20*04150feeSXiaoDong Huang rk_scmi_clock_t *rockchip_scmi_get_clock(uint32_t agent_id __unused, 21*04150feeSXiaoDong Huang uint32_t scmi_id __unused) 22*04150feeSXiaoDong Huang { 23*04150feeSXiaoDong Huang return NULL; 24*04150feeSXiaoDong Huang } 25*04150feeSXiaoDong Huang 26*04150feeSXiaoDong Huang size_t plat_scmi_clock_count(unsigned int agent_id) 27*04150feeSXiaoDong Huang { 28*04150feeSXiaoDong Huang return rockchip_scmi_clock_count(agent_id); 29*04150feeSXiaoDong Huang } 30*04150feeSXiaoDong Huang 31*04150feeSXiaoDong Huang const char *plat_scmi_clock_get_name(unsigned int agent_id, 32*04150feeSXiaoDong Huang unsigned int scmi_id) 33*04150feeSXiaoDong Huang { 34*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 35*04150feeSXiaoDong Huang 36*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 37*04150feeSXiaoDong Huang if (clock == NULL) 38*04150feeSXiaoDong Huang return NULL; 39*04150feeSXiaoDong Huang 40*04150feeSXiaoDong Huang return clock->name; 41*04150feeSXiaoDong Huang } 42*04150feeSXiaoDong Huang 43*04150feeSXiaoDong Huang int32_t plat_scmi_clock_rates_array(unsigned int agent_id, 44*04150feeSXiaoDong Huang unsigned int scmi_id, 45*04150feeSXiaoDong Huang unsigned long *rates, 46*04150feeSXiaoDong Huang size_t *nb_elts, 47*04150feeSXiaoDong Huang uint32_t start_idx) 48*04150feeSXiaoDong Huang { 49*04150feeSXiaoDong Huang uint32_t i; 50*04150feeSXiaoDong Huang unsigned long *rate_table; 51*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 52*04150feeSXiaoDong Huang 53*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 54*04150feeSXiaoDong Huang if (clock == NULL) 55*04150feeSXiaoDong Huang return SCMI_NOT_FOUND; 56*04150feeSXiaoDong Huang 57*04150feeSXiaoDong Huang rate_table = clock->rate_table; 58*04150feeSXiaoDong Huang if (rate_table == NULL) 59*04150feeSXiaoDong Huang return SCMI_NOT_SUPPORTED; 60*04150feeSXiaoDong Huang 61*04150feeSXiaoDong Huang if (rates == 0) { 62*04150feeSXiaoDong Huang *nb_elts = clock->rate_cnt; 63*04150feeSXiaoDong Huang goto out; 64*04150feeSXiaoDong Huang } 65*04150feeSXiaoDong Huang 66*04150feeSXiaoDong Huang if (start_idx + *nb_elts > clock->rate_cnt) 67*04150feeSXiaoDong Huang return SCMI_OUT_OF_RANGE; 68*04150feeSXiaoDong Huang 69*04150feeSXiaoDong Huang for (i = 0; i < *nb_elts; i++) 70*04150feeSXiaoDong Huang rates[i] = rate_table[start_idx + i]; 71*04150feeSXiaoDong Huang 72*04150feeSXiaoDong Huang out: 73*04150feeSXiaoDong Huang return SCMI_SUCCESS; 74*04150feeSXiaoDong Huang } 75*04150feeSXiaoDong Huang 76*04150feeSXiaoDong Huang int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused, 77*04150feeSXiaoDong Huang unsigned int scmi_id __unused, 78*04150feeSXiaoDong Huang unsigned long *steps __unused) 79*04150feeSXiaoDong Huang { 80*04150feeSXiaoDong Huang return SCMI_NOT_SUPPORTED; 81*04150feeSXiaoDong Huang } 82*04150feeSXiaoDong Huang 83*04150feeSXiaoDong Huang unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, 84*04150feeSXiaoDong Huang unsigned int scmi_id) 85*04150feeSXiaoDong Huang { 86*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 87*04150feeSXiaoDong Huang unsigned long rate = 0; 88*04150feeSXiaoDong Huang 89*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 90*04150feeSXiaoDong Huang if (clock == NULL) 91*04150feeSXiaoDong Huang return 0; 92*04150feeSXiaoDong Huang 93*04150feeSXiaoDong Huang if (clock->clk_ops && clock->clk_ops->get_rate) 94*04150feeSXiaoDong Huang rate = clock->clk_ops->get_rate(clock); 95*04150feeSXiaoDong Huang 96*04150feeSXiaoDong Huang /* return cur_rate if no get_rate ops or get_rate return 0 */ 97*04150feeSXiaoDong Huang if (rate == 0) 98*04150feeSXiaoDong Huang rate = clock->cur_rate; 99*04150feeSXiaoDong Huang 100*04150feeSXiaoDong Huang return rate; 101*04150feeSXiaoDong Huang } 102*04150feeSXiaoDong Huang 103*04150feeSXiaoDong Huang int32_t plat_scmi_clock_set_rate(unsigned int agent_id, 104*04150feeSXiaoDong Huang unsigned int scmi_id, 105*04150feeSXiaoDong Huang unsigned long rate) 106*04150feeSXiaoDong Huang { 107*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 108*04150feeSXiaoDong Huang int32_t status = 0; 109*04150feeSXiaoDong Huang 110*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 111*04150feeSXiaoDong Huang if (clock == NULL) 112*04150feeSXiaoDong Huang return SCMI_NOT_FOUND; 113*04150feeSXiaoDong Huang 114*04150feeSXiaoDong Huang if (clock->clk_ops && clock->clk_ops->set_rate) { 115*04150feeSXiaoDong Huang status = clock->clk_ops->set_rate(clock, rate); 116*04150feeSXiaoDong Huang if (status == SCMI_SUCCESS) 117*04150feeSXiaoDong Huang clock->cur_rate = rate; 118*04150feeSXiaoDong Huang } else { 119*04150feeSXiaoDong Huang status = SCMI_NOT_SUPPORTED; 120*04150feeSXiaoDong Huang } 121*04150feeSXiaoDong Huang 122*04150feeSXiaoDong Huang return status; 123*04150feeSXiaoDong Huang } 124*04150feeSXiaoDong Huang 125*04150feeSXiaoDong Huang int32_t plat_scmi_clock_get_state(unsigned int agent_id, 126*04150feeSXiaoDong Huang unsigned int scmi_id) 127*04150feeSXiaoDong Huang { 128*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 129*04150feeSXiaoDong Huang 130*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 131*04150feeSXiaoDong Huang if (clock == NULL) 132*04150feeSXiaoDong Huang return 0; 133*04150feeSXiaoDong Huang 134*04150feeSXiaoDong Huang return clock->enable; 135*04150feeSXiaoDong Huang } 136*04150feeSXiaoDong Huang 137*04150feeSXiaoDong Huang int32_t plat_scmi_clock_set_state(unsigned int agent_id, 138*04150feeSXiaoDong Huang unsigned int scmi_id, 139*04150feeSXiaoDong Huang bool enable_not_disable) 140*04150feeSXiaoDong Huang { 141*04150feeSXiaoDong Huang rk_scmi_clock_t *clock; 142*04150feeSXiaoDong Huang int32_t status = 0; 143*04150feeSXiaoDong Huang 144*04150feeSXiaoDong Huang clock = rockchip_scmi_get_clock(agent_id, scmi_id); 145*04150feeSXiaoDong Huang if (clock == NULL) 146*04150feeSXiaoDong Huang return SCMI_NOT_FOUND; 147*04150feeSXiaoDong Huang 148*04150feeSXiaoDong Huang if (clock->clk_ops && clock->clk_ops->set_status) { 149*04150feeSXiaoDong Huang status = clock->clk_ops->set_status(clock, enable_not_disable); 150*04150feeSXiaoDong Huang if (status == SCMI_SUCCESS) 151*04150feeSXiaoDong Huang clock->enable = enable_not_disable; 152*04150feeSXiaoDong Huang } else { 153*04150feeSXiaoDong Huang status = SCMI_NOT_SUPPORTED; 154*04150feeSXiaoDong Huang } 155*04150feeSXiaoDong Huang 156*04150feeSXiaoDong Huang return status; 157*04150feeSXiaoDong Huang } 158