/* * drivers/arisc/interfaces/arisc_dvfs.c * * Copyright (c) 2012 Allwinner. * 2012-10-01 Written by superm (superm@allwinnertech.com). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "../arisc_i.h" static int dvfs_err_cb(void *arg) { ARISC_ERR("dvfs error\n"); return 0; } /* * set specific pll target frequency. * @freq: target frequency to be set, based on KHZ; * @pll: which pll will be set * @mode: the attribute of message, whether syn or asyn; * @cb: callback handler; * @cb_arg: callback handler arguments; * * return: result, 0 - set frequency successed, * !0 - set frequency failed; */ int arisc_dvfs_set_cpufreq(uint32_t freq, uint32_t pll, uint32_t mode) { unsigned int msg_attr = 0; struct arisc_message *pmessage; int result = 0; if (mode & ARISC_DVFS_SYN) { msg_attr |= ARISC_MESSAGE_ATTR_HARDSYN; } /* allocate a message frame */ pmessage = arisc_message_allocate(msg_attr); if (pmessage == NULL) { ARISC_WRN("allocate message failed\n"); return -ENOMEM; } /* initialize message * * |paras[0]|paras[1]| * |freq |pll | */ pmessage->type = ARISC_CPUX_DVFS_REQ; pmessage->paras[0] = freq; pmessage->paras[1] = pll; pmessage->state = ARISC_MESSAGE_INITIALIZED; pmessage->cb.handler = dvfs_err_cb; pmessage->cb.arg = NULL; ARISC_INF("arisc dvfs request : %d\n", freq); arisc_hwmsgbox_send_message(pmessage, ARISC_SEND_MSG_TIMEOUT); /* dvfs mode : syn or not */ if (mode & ARISC_DVFS_SYN) { result = pmessage->result; arisc_message_free(pmessage); } return result; }