2005-04-16 15:20:36 -07:00
/*
* PCI Hot Plug Controller Driver for RPA - compliant PPC64 platform .
* Copyright ( C ) 2003 Linda Xie < lxie @ us . ibm . com >
*
* All rights reserved .
*
* 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 , GOOD TITLE or
* NON INFRINGEMENT . 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 . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
* Send feedback to < lxie @ us . ibm . com >
*
*/
# include <linux/pci.h>
2005-10-30 15:03:48 -08:00
# include <linux/string.h>
2005-04-16 15:20:36 -07:00
# include <asm/pci-bridge.h>
# include <asm/rtas.h>
# include <asm/machdep.h>
2005-10-30 15:03:48 -08:00
# include "../pci.h" /* for pci_add_new_bus */
2005-04-16 15:20:36 -07:00
# include "rpaphp.h"
2006-01-12 18:28:22 -06:00
int rpaphp_get_sensor_state ( struct slot * slot , int * state )
2005-04-16 15:20:36 -07:00
{
int rc ;
int setlevel ;
rc = rtas_get_sensor ( DR_ENTITY_SENSE , slot - > index , state ) ;
if ( rc < 0 ) {
if ( rc = = - EFAULT | | rc = = - EEXIST ) {
dbg ( " %s: slot must be power up to get sensor-state \n " ,
2008-03-03 19:09:46 -08:00
__func__ ) ;
2005-04-16 15:20:36 -07:00
/* some slots have to be powered up
* before get - sensor will succeed .
*/
rc = rtas_set_power_level ( slot - > power_domain , POWER_ON ,
& setlevel ) ;
if ( rc < 0 ) {
dbg ( " %s: power on slot[%s] failed rc=%d. \n " ,
2008-03-03 19:09:46 -08:00
__func__ , slot - > name , rc ) ;
2005-04-16 15:20:36 -07:00
} else {
rc = rtas_get_sensor ( DR_ENTITY_SENSE ,
slot - > index , state ) ;
}
} else if ( rc = = - ENODEV )
2008-03-03 19:09:46 -08:00
info ( " %s: slot is unusable \n " , __func__ ) ;
2005-04-16 15:20:36 -07:00
else
2008-03-03 19:09:46 -08:00
err ( " %s failed to get sensor state \n " , __func__ ) ;
2005-04-16 15:20:36 -07:00
}
return rc ;
}
2007-04-13 15:34:20 -07:00
/**
* rpaphp_enable_slot - record slot state , config pci device
2007-11-28 09:04:30 -08:00
* @ slot : target & slot
2007-04-13 15:34:20 -07:00
*
* Initialize values in the slot , and the hotplug_slot info
* structures to indicate if there is a pci card plugged into
* the slot . If the slot is not empty , run the pcibios routine
* to get pcibios stuff correctly set up .
*/
int rpaphp_enable_slot ( struct slot * slot )
2005-04-16 15:20:36 -07:00
{
2007-04-13 15:34:14 -07:00
int rc , level , state ;
struct pci_bus * bus ;
2007-04-13 15:34:12 -07:00
struct hotplug_slot_info * info = slot - > hotplug_slot - > info ;
2007-04-13 15:34:16 -07:00
info - > adapter_status = NOT_VALID ;
slot - > state = EMPTY ;
2007-04-13 15:34:14 -07:00
/* Find out if the power is turned on for the slot */
2007-04-13 15:34:13 -07:00
rc = rtas_get_power_level ( slot - > power_domain , & level ) ;
if ( rc )
return rc ;
info - > power_status = level ;
2007-04-13 15:34:14 -07:00
/* Figure out if there is an adapter in the slot */
rc = rpaphp_get_sensor_state ( slot , & state ) ;
if ( rc )
return rc ;
2007-04-13 15:34:12 -07:00
2007-04-13 15:34:16 -07:00
bus = pcibios_find_pci_bus ( slot - > dn ) ;
if ( ! bus ) {
2008-03-03 19:09:46 -08:00
err ( " %s: no pci_bus for dn %s \n " , __func__ , slot - > dn - > full_name ) ;
2007-04-13 15:34:16 -07:00
return - EINVAL ;
2007-04-13 15:34:12 -07:00
}
2005-04-16 15:20:36 -07:00
2007-04-13 15:34:16 -07:00
info - > adapter_status = EMPTY ;
slot - > bus = bus ;
slot - > pci_devs = & bus - > devices ;
/* if there's an adapter in the slot, go add the pci devices */
if ( state = = PRESENT ) {
info - > adapter_status = NOT_CONFIGURED ;
slot - > state = NOT_CONFIGURED ;
/* non-empty slot has to have child */
if ( ! slot - > dn - > child ) {
err ( " %s: slot[%s]'s device_node doesn't have child for adapter \n " ,
2008-03-03 19:09:46 -08:00
__func__ , slot - > name ) ;
2007-04-13 15:34:16 -07:00
return - EINVAL ;
}
if ( list_empty ( & bus - > devices ) )
pcibios_add_pci_devices ( bus ) ;
if ( ! list_empty ( & bus - > devices ) ) {
info - > adapter_status = CONFIGURED ;
slot - > state = CONFIGURED ;
}
2007-04-13 15:34:17 -07:00
2008-10-13 09:59:12 -07:00
if ( rpaphp_debug ) {
2007-04-13 15:34:17 -07:00
struct pci_dev * dev ;
2008-03-03 19:09:46 -08:00
dbg ( " %s: pci_devs of slot[%s] \n " , __func__ , slot - > dn - > full_name ) ;
2007-04-13 15:34:17 -07:00
list_for_each_entry ( dev , & bus - > devices , bus_list )
dbg ( " \t %s \n " , pci_name ( dev ) ) ;
}
2007-04-13 15:34:16 -07:00
}
2007-04-13 15:34:12 -07:00
2007-04-13 15:34:19 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
}