11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 Linda Xie <lxie@us.ibm.com> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * All rights reserved. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * your option) any later version. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, but 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NON INFRINGEMENT. See the GNU General Public License for more 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * details. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send feedback to <lxie@us.ibm.com> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 264e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/string.h> 274e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/pci-bridge.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/rtas.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/machdep.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 324e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include "../pci.h" /* for pci_add_new_bus */ 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "rpaphp.h" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 35e06b80b78db96ca272db4ec0b26ce1092a1a9704Linas Vepstasint rpaphp_get_sensor_state(struct slot *slot, int *state) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int setlevel; 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc == -EFAULT || rc == -EEXIST) { 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: slot must be power up to get sensor-state\n", 4566bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47f7625980f5820edd1a73536e1a03bcbc1f889fecBjorn Helgaas /* some slots have to be powered up 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * before get-sensor will succeed. 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_set_power_level(slot->power_domain, POWER_ON, 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &setlevel); 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dbg("%s: power on slot[%s] failed rc=%d.\n", 5466bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, slot->name, rc); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = rtas_get_sensor(DR_ENTITY_SENSE, 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds slot->index, state); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (rc == -ENODEV) 6066bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison info("%s: slot is unusable\n", __func__); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 6266bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison err("%s failed to get sensor state\n", __func__); 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas/** 68fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * rpaphp_enable_slot - record slot state, config pci device 6926e6c66e47fe7f69ef6ddb078e312204a1f17823Randy Dunlap * @slot: target &slot 70fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * 71fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * Initialize values in the slot, and the hotplug_slot info 72fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * structures to indicate if there is a pci card plugged into 73fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * the slot. If the slot is not empty, run the pcibios routine 74fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas * to get pcibios stuff correctly set up. 75fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstas */ 76fea54b8cc9c8290b4c99d481c3e600c46eb18fd5Linas Vepstasint rpaphp_enable_slot(struct slot *slot) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 78bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas int rc, level, state; 79bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas struct pci_bus *bus; 80517d5a0417e19101eaa769039d1921d626ee546cLinas Vepstas struct hotplug_slot_info *info = slot->hotplug_slot->info; 81517d5a0417e19101eaa769039d1921d626ee546cLinas Vepstas 8203a667559138d47cea487823332c4712fc6fbec7Linas Vepstas info->adapter_status = NOT_VALID; 8303a667559138d47cea487823332c4712fc6fbec7Linas Vepstas slot->state = EMPTY; 8403a667559138d47cea487823332c4712fc6fbec7Linas Vepstas 85bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas /* Find out if the power is turned on for the slot */ 86427310ff02e80cc80826407c0121cec3694c9e7dLinas Vepstas rc = rtas_get_power_level(slot->power_domain, &level); 87427310ff02e80cc80826407c0121cec3694c9e7dLinas Vepstas if (rc) 88427310ff02e80cc80826407c0121cec3694c9e7dLinas Vepstas return rc; 89427310ff02e80cc80826407c0121cec3694c9e7dLinas Vepstas info->power_status = level; 90427310ff02e80cc80826407c0121cec3694c9e7dLinas Vepstas 91bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas /* Figure out if there is an adapter in the slot */ 92bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas rc = rpaphp_get_sensor_state(slot, &state); 93bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas if (rc) 94bf0af511fcc856649a2a39c627828695b580d124Linas Vepstas return rc; 95517d5a0417e19101eaa769039d1921d626ee546cLinas Vepstas 9603a667559138d47cea487823332c4712fc6fbec7Linas Vepstas bus = pcibios_find_pci_bus(slot->dn); 9703a667559138d47cea487823332c4712fc6fbec7Linas Vepstas if (!bus) { 9866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison err("%s: no pci_bus for dn %s\n", __func__, slot->dn->full_name); 9903a667559138d47cea487823332c4712fc6fbec7Linas Vepstas return -EINVAL; 100517d5a0417e19101eaa769039d1921d626ee546cLinas Vepstas } 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10203a667559138d47cea487823332c4712fc6fbec7Linas Vepstas info->adapter_status = EMPTY; 10303a667559138d47cea487823332c4712fc6fbec7Linas Vepstas slot->bus = bus; 10403a667559138d47cea487823332c4712fc6fbec7Linas Vepstas slot->pci_devs = &bus->devices; 10503a667559138d47cea487823332c4712fc6fbec7Linas Vepstas 10603a667559138d47cea487823332c4712fc6fbec7Linas Vepstas /* if there's an adapter in the slot, go add the pci devices */ 10703a667559138d47cea487823332c4712fc6fbec7Linas Vepstas if (state == PRESENT) { 10803a667559138d47cea487823332c4712fc6fbec7Linas Vepstas info->adapter_status = NOT_CONFIGURED; 10903a667559138d47cea487823332c4712fc6fbec7Linas Vepstas slot->state = NOT_CONFIGURED; 11003a667559138d47cea487823332c4712fc6fbec7Linas Vepstas 11103a667559138d47cea487823332c4712fc6fbec7Linas Vepstas /* non-empty slot has to have child */ 11203a667559138d47cea487823332c4712fc6fbec7Linas Vepstas if (!slot->dn->child) { 11303a667559138d47cea487823332c4712fc6fbec7Linas Vepstas err("%s: slot[%s]'s device_node doesn't have child for adapter\n", 11466bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison __func__, slot->name); 11503a667559138d47cea487823332c4712fc6fbec7Linas Vepstas return -EINVAL; 11603a667559138d47cea487823332c4712fc6fbec7Linas Vepstas } 11703a667559138d47cea487823332c4712fc6fbec7Linas Vepstas 11803a667559138d47cea487823332c4712fc6fbec7Linas Vepstas if (list_empty(&bus->devices)) 11903a667559138d47cea487823332c4712fc6fbec7Linas Vepstas pcibios_add_pci_devices(bus); 12003a667559138d47cea487823332c4712fc6fbec7Linas Vepstas 12103a667559138d47cea487823332c4712fc6fbec7Linas Vepstas if (!list_empty(&bus->devices)) { 12203a667559138d47cea487823332c4712fc6fbec7Linas Vepstas info->adapter_status = CONFIGURED; 12303a667559138d47cea487823332c4712fc6fbec7Linas Vepstas slot->state = CONFIGURED; 12403a667559138d47cea487823332c4712fc6fbec7Linas Vepstas } 125307ff12e35526cfab9f09cafcb17239286e6eb85Linas Vepstas 1265d9bc1fa47f0c1561f1d7c0bdff5e24860852b42Kristen Carlson Accardi if (rpaphp_debug) { 127307ff12e35526cfab9f09cafcb17239286e6eb85Linas Vepstas struct pci_dev *dev; 12866bef8c059015ba2b36bb5759080336feb01e680Harvey Harrison dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name); 129307ff12e35526cfab9f09cafcb17239286e6eb85Linas Vepstas list_for_each_entry (dev, &bus->devices, bus_list) 130307ff12e35526cfab9f09cafcb17239286e6eb85Linas Vepstas dbg("\t%s\n", pci_name(dev)); 131307ff12e35526cfab9f09cafcb17239286e6eb85Linas Vepstas } 13203a667559138d47cea487823332c4712fc6fbec7Linas Vepstas } 133517d5a0417e19101eaa769039d1921d626ee546cLinas Vepstas 1346f79eb749df7f1eea76c947f31603ade7d2b5f6dLinas Vepstas return 0; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 136