1193156Snwhitehorn/*- 2193156Snwhitehorn * Copyright (c) 2009 Nathan Whitehorn 3193156Snwhitehorn * All rights reserved. 4193156Snwhitehorn * 5193156Snwhitehorn * Redistribution and use in source and binary forms, with or without 6193156Snwhitehorn * modification, are permitted provided that the following conditions 7193156Snwhitehorn * are met: 8193156Snwhitehorn * 1. Redistributions of source code must retain the above copyright 9193156Snwhitehorn * notice, this list of conditions and the following disclaimer. 10193156Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 11193156Snwhitehorn * notice, this list of conditions and the following disclaimer in the 12193156Snwhitehorn * documentation and/or other materials provided with the distribution. 13193156Snwhitehorn * 14193156Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15193156Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16193156Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17193156Snwhitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18193156Snwhitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19193156Snwhitehorn * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20193156Snwhitehorn * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21193156Snwhitehorn * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22193156Snwhitehorn * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23193156Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24193156Snwhitehorn * SUCH DAMAGE. 25193156Snwhitehorn * 26193156Snwhitehorn */ 27193156Snwhitehorn 28193156Snwhitehorn#include <sys/cdefs.h> 29193156Snwhitehorn__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/powermac/vcoregpio.c 193156 2009-05-31 09:01:23Z nwhitehorn $"); 30193156Snwhitehorn 31193156Snwhitehorn#include <sys/param.h> 32193156Snwhitehorn#include <sys/systm.h> 33193156Snwhitehorn#include <sys/module.h> 34193156Snwhitehorn#include <sys/bus.h> 35193156Snwhitehorn#include <sys/conf.h> 36193156Snwhitehorn#include <sys/cpu.h> 37193156Snwhitehorn#include <sys/kernel.h> 38193156Snwhitehorn#include <sys/sysctl.h> 39193156Snwhitehorn 40193156Snwhitehorn#include <dev/ofw/ofw_bus.h> 41193156Snwhitehorn#include <dev/ofw/openfirm.h> 42193156Snwhitehorn 43193156Snwhitehorn#include <powerpc/powermac/macgpiovar.h> 44193156Snwhitehorn 45193156Snwhitehornstatic int vcoregpio_probe(device_t); 46193156Snwhitehornstatic int vcoregpio_attach(device_t); 47193156Snwhitehornstatic void vcoregpio_pre_change(device_t, const struct cf_level *level); 48193156Snwhitehornstatic void vcoregpio_post_change(device_t, const struct cf_level *level); 49193156Snwhitehorn 50193156Snwhitehornstatic device_method_t vcoregpio_methods[] = { 51193156Snwhitehorn /* Device interface */ 52193156Snwhitehorn DEVMETHOD(device_probe, vcoregpio_probe), 53193156Snwhitehorn DEVMETHOD(device_attach, vcoregpio_attach), 54193156Snwhitehorn { 0, 0 }, 55193156Snwhitehorn}; 56193156Snwhitehorn 57193156Snwhitehornstatic driver_t vcoregpio_driver = { 58193156Snwhitehorn "vcoregpio", 59193156Snwhitehorn vcoregpio_methods, 60193156Snwhitehorn 0 61193156Snwhitehorn}; 62193156Snwhitehorn 63193156Snwhitehornstatic devclass_t vcoregpio_devclass; 64193156Snwhitehorn 65193156SnwhitehornDRIVER_MODULE(vcoregpio, macgpio, vcoregpio_driver, vcoregpio_devclass, 0, 0); 66193156Snwhitehorn 67193156Snwhitehornstatic int 68193156Snwhitehornvcoregpio_probe(device_t dev) 69193156Snwhitehorn{ 70193156Snwhitehorn const char *name = ofw_bus_get_name(dev); 71193156Snwhitehorn 72193156Snwhitehorn if (strcmp(name, "cpu-vcore-select") != 0) 73193156Snwhitehorn return (ENXIO); 74193156Snwhitehorn 75193156Snwhitehorn device_set_desc(dev, "CPU Core Voltage Control"); 76193156Snwhitehorn return (0); 77193156Snwhitehorn} 78193156Snwhitehorn 79193156Snwhitehornstatic int 80193156Snwhitehornvcoregpio_attach(device_t dev) 81193156Snwhitehorn{ 82193156Snwhitehorn EVENTHANDLER_REGISTER(cpufreq_pre_change, vcoregpio_pre_change, dev, 83193156Snwhitehorn EVENTHANDLER_PRI_ANY); 84193156Snwhitehorn EVENTHANDLER_REGISTER(cpufreq_post_change, vcoregpio_post_change, dev, 85193156Snwhitehorn EVENTHANDLER_PRI_ANY); 86193156Snwhitehorn 87193156Snwhitehorn return (0); 88193156Snwhitehorn} 89193156Snwhitehorn 90193156Snwhitehornstatic void 91193156Snwhitehornvcoregpio_pre_change(device_t dev, const struct cf_level *level) 92193156Snwhitehorn{ 93193156Snwhitehorn if (level->rel_set[0].freq == 10000 /* max */) { 94193156Snwhitehorn /* 95193156Snwhitehorn * Make sure the CPU voltage is raised before we raise 96193156Snwhitehorn * the clock. 97193156Snwhitehorn */ 98193156Snwhitehorn macgpio_write(dev, GPIO_DDR_OUTPUT | 1); 99193156Snwhitehorn DELAY(1000); 100193156Snwhitehorn } 101193156Snwhitehorn} 102193156Snwhitehorn 103193156Snwhitehornstatic void 104193156Snwhitehornvcoregpio_post_change(device_t dev, const struct cf_level *level) 105193156Snwhitehorn{ 106193156Snwhitehorn if (level->rel_set[0].freq < 10000 /* max */) { 107193156Snwhitehorn DELAY(1000); 108193156Snwhitehorn /* We are safe to reduce CPU voltage now */ 109193156Snwhitehorn macgpio_write(dev, GPIO_DDR_OUTPUT | 0); 110193156Snwhitehorn } 111193156Snwhitehorn} 112193156Snwhitehorn 113