1c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs/* 2c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * Copyright 2013 Red Hat Inc. 3c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * 4c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * copy of this software and associated documentation files (the "Software"), 6c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * to deal in the Software without restriction, including without limitation 7c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * Software is furnished to do so, subject to the following conditions: 10c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * 11c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * The above copyright notice and this permission notice shall be included in 12c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * all copies or substantial portions of the Software. 13c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * 14c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * 22c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * Authors: Ben Skeggs 23c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs */ 24c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 25c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs#include <subdev/volt.h> 26c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs#include <subdev/gpio.h> 27c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs#include <subdev/bios/gpio.h> 28c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 29c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsstatic const u8 tags[] = { 30c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs DCB_GPIO_VID0, DCB_GPIO_VID1, DCB_GPIO_VID2, DCB_GPIO_VID3, 31c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs DCB_GPIO_VID4, DCB_GPIO_VID5, DCB_GPIO_VID6, DCB_GPIO_VID7, 32c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs}; 33c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 34c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsint 35c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsnouveau_voltgpio_get(struct nouveau_volt *volt) 36c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs{ 37c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs struct nouveau_gpio *gpio = nouveau_gpio(volt); 38c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs u8 vid = 0; 39c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int i; 40c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 41c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs for (i = 0; i < ARRAY_SIZE(tags); i++) { 42c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (volt->vid_mask & (1 << i)) { 43c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int ret = gpio->get(gpio, 0, tags[i], 0xff); 44c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (ret < 0) 45c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return ret; 46c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs vid |= ret << i; 47c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 48c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 49c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 50c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return vid; 51c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs} 52c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 53c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsint 54c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsnouveau_voltgpio_set(struct nouveau_volt *volt, u8 vid) 55c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs{ 56c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs struct nouveau_gpio *gpio = nouveau_gpio(volt); 57c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int i; 58c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 59c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs for (i = 0; i < ARRAY_SIZE(tags); i++, vid >>= 1) { 60c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (volt->vid_mask & (1 << i)) { 61c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int ret = gpio->set(gpio, 0, tags[i], 0xff, vid & 1); 62c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (ret < 0) 63c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return ret; 64c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 65c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 66c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 67c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return 0; 68c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs} 69c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 70c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsint 71c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggsnouveau_voltgpio_init(struct nouveau_volt *volt) 72c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs{ 73c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs struct nouveau_gpio *gpio = nouveau_gpio(volt); 74c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs struct dcb_gpio_func func; 75c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int i; 76c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 77c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs /* check we have gpio function info for each vid bit. on some 78c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * boards (ie. nvs295) the vid mask has more bits than there 79c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * are valid gpio functions... from traces, nvidia appear to 80c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * just touch the existing ones, so let's mask off the invalid 81c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs * bits and continue with life 82c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs */ 83c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs for (i = 0; i < ARRAY_SIZE(tags); i++) { 84c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (volt->vid_mask & (1 << i)) { 85c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs int ret = gpio->find(gpio, 0, tags[i], 0xff, &func); 86c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (ret) { 87c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs if (ret != -ENOENT) 88c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return ret; 89c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs nv_debug(volt, "VID bit %d has no GPIO\n", i); 90c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs volt->vid_mask &= ~(1 << i); 91c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 92c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 93c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs } 94c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs 95c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs return 0; 96c9c0ccae48e27b767e98a4c120976e43195dd3a7Ben Skeggs} 97