/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2009 Nathan Whitehorn4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR16* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES17* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.18* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,19* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,20* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED22* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*27*/2829#include <sys/param.h>30#include <sys/systm.h>31#include <sys/module.h>32#include <sys/bus.h>33#include <sys/conf.h>34#include <sys/cpu.h>35#include <sys/eventhandler.h>36#include <sys/kernel.h>37#include <sys/sysctl.h>3839#include <dev/ofw/ofw_bus.h>40#include <dev/ofw/openfirm.h>4142#include <powerpc/powermac/macgpiovar.h>4344static int vcoregpio_probe(device_t);45static int vcoregpio_attach(device_t);46static void vcoregpio_pre_change(device_t, const struct cf_level *level);47static void vcoregpio_post_change(device_t, const struct cf_level *level);4849static device_method_t vcoregpio_methods[] = {50/* Device interface */51DEVMETHOD(device_probe, vcoregpio_probe),52DEVMETHOD(device_attach, vcoregpio_attach),53{ 0, 0 },54};5556static driver_t vcoregpio_driver = {57"vcoregpio",58vcoregpio_methods,59060};6162DRIVER_MODULE(vcoregpio, macgpio, vcoregpio_driver, 0, 0);6364static int65vcoregpio_probe(device_t dev)66{67const char *name = ofw_bus_get_name(dev);6869if (strcmp(name, "cpu-vcore-select") != 0)70return (ENXIO);7172device_set_desc(dev, "CPU Core Voltage Control");73return (0);74}7576static int77vcoregpio_attach(device_t dev)78{79EVENTHANDLER_REGISTER(cpufreq_pre_change, vcoregpio_pre_change, dev,80EVENTHANDLER_PRI_ANY);81EVENTHANDLER_REGISTER(cpufreq_post_change, vcoregpio_post_change, dev,82EVENTHANDLER_PRI_ANY);8384return (0);85}8687static void88vcoregpio_pre_change(device_t dev, const struct cf_level *level)89{90if (level->rel_set[0].freq == 10000 /* max */) {91/*92* Make sure the CPU voltage is raised before we raise93* the clock.94*/95macgpio_write(dev, GPIO_DDR_OUTPUT | 1);96DELAY(1000);97}98}99100static void101vcoregpio_post_change(device_t dev, const struct cf_level *level)102{103if (level->rel_set[0].freq < 10000 /* max */) {104DELAY(1000);105/* We are safe to reduce CPU voltage now */106macgpio_write(dev, GPIO_DDR_OUTPUT | 0);107}108}109110111