2008-02-19 14:41:30 +03:00
/*
* Sonics Silicon Backplane
* Embedded systems support code
*
* Copyright 2005 - 2008 , Broadcom Corporation
2011-07-04 22:50:05 +04:00
* Copyright 2006 - 2008 , Michael Buesch < m @ bues . ch >
2012-12-05 21:46:08 +04:00
* Copyright 2012 , Hauke Mehrtens < hauke @ hauke - m . de >
2008-02-19 14:41:30 +03:00
*
* Licensed under the GNU / GPL . See COPYING for details .
*/
2018-07-31 22:56:38 +03:00
# include "ssb_private.h"
2011-07-28 06:07:02 +04:00
# include <linux/export.h>
2012-12-05 21:46:08 +04:00
# include <linux/platform_device.h>
2008-02-19 14:41:30 +03:00
# include <linux/ssb/ssb.h>
# include <linux/ssb/ssb_embedded.h>
2008-02-29 13:36:12 +03:00
# include <linux/ssb/ssb_driver_pci.h>
# include <linux/ssb/ssb_driver_gige.h>
# include <linux/pci.h>
2008-02-19 14:41:30 +03:00
int ssb_watchdog_timer_set ( struct ssb_bus * bus , u32 ticks )
{
if ( ssb_chipco_available ( & bus - > chipco ) ) {
ssb_chipco_watchdog_timer_set ( & bus - > chipco , ticks ) ;
return 0 ;
}
if ( ssb_extif_available ( & bus - > extif ) ) {
ssb_extif_watchdog_timer_set ( & bus - > extif , ticks ) ;
return 0 ;
}
return - ENODEV ;
}
2009-05-23 00:25:04 +04:00
EXPORT_SYMBOL ( ssb_watchdog_timer_set ) ;
2008-02-19 18:22:50 +03:00
2012-12-05 21:46:08 +04:00
int ssb_watchdog_register ( struct ssb_bus * bus )
{
struct bcm47xx_wdt wdt = { } ;
struct platform_device * pdev ;
if ( ssb_chipco_available ( & bus - > chipco ) ) {
wdt . driver_data = & bus - > chipco ;
wdt . timer_set = ssb_chipco_watchdog_timer_set_wdt ;
wdt . timer_set_ms = ssb_chipco_watchdog_timer_set_ms ;
wdt . max_timer_ms = bus - > chipco . max_timer_ms ;
} else if ( ssb_extif_available ( & bus - > extif ) ) {
wdt . driver_data = & bus - > extif ;
wdt . timer_set = ssb_extif_watchdog_timer_set_wdt ;
wdt . timer_set_ms = ssb_extif_watchdog_timer_set_ms ;
wdt . max_timer_ms = SSB_EXTIF_WATCHDOG_MAX_TIMER_MS ;
} else {
return - ENODEV ;
}
pdev = platform_device_register_data ( NULL , " bcm47xx-wdt " ,
bus - > busnumber , & wdt ,
sizeof ( wdt ) ) ;
if ( IS_ERR ( pdev ) ) {
2018-07-31 22:56:38 +03:00
pr_debug ( " can not register watchdog device, err: %li \n " ,
PTR_ERR ( pdev ) ) ;
2012-12-05 21:46:08 +04:00
return PTR_ERR ( pdev ) ;
}
bus - > watchdog = pdev ;
return 0 ;
}
2008-02-19 18:22:50 +03:00
u32 ssb_gpio_in ( struct ssb_bus * bus , u32 mask )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_in ( & bus - > chipco , mask ) ;
else if ( ssb_extif_available ( & bus - > extif ) )
res = ssb_extif_gpio_in ( & bus - > extif , mask ) ;
else
2018-07-31 23:15:09 +03:00
WARN_ON ( 1 ) ;
2008-02-19 18:22:50 +03:00
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_in ) ;
u32 ssb_gpio_out ( struct ssb_bus * bus , u32 mask , u32 value )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_out ( & bus - > chipco , mask , value ) ;
else if ( ssb_extif_available ( & bus - > extif ) )
res = ssb_extif_gpio_out ( & bus - > extif , mask , value ) ;
else
2018-07-31 23:15:09 +03:00
WARN_ON ( 1 ) ;
2008-02-19 18:22:50 +03:00
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_out ) ;
u32 ssb_gpio_outen ( struct ssb_bus * bus , u32 mask , u32 value )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_outen ( & bus - > chipco , mask , value ) ;
else if ( ssb_extif_available ( & bus - > extif ) )
res = ssb_extif_gpio_outen ( & bus - > extif , mask , value ) ;
else
2018-07-31 23:15:09 +03:00
WARN_ON ( 1 ) ;
2008-02-19 18:22:50 +03:00
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_outen ) ;
u32 ssb_gpio_control ( struct ssb_bus * bus , u32 mask , u32 value )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_control ( & bus - > chipco , mask , value ) ;
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_control ) ;
u32 ssb_gpio_intmask ( struct ssb_bus * bus , u32 mask , u32 value )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_intmask ( & bus - > chipco , mask , value ) ;
else if ( ssb_extif_available ( & bus - > extif ) )
res = ssb_extif_gpio_intmask ( & bus - > extif , mask , value ) ;
else
2018-07-31 23:15:09 +03:00
WARN_ON ( 1 ) ;
2008-02-19 18:22:50 +03:00
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_intmask ) ;
u32 ssb_gpio_polarity ( struct ssb_bus * bus , u32 mask , u32 value )
{
unsigned long flags ;
u32 res = 0 ;
spin_lock_irqsave ( & bus - > gpio_lock , flags ) ;
if ( ssb_chipco_available ( & bus - > chipco ) )
res = ssb_chipco_gpio_polarity ( & bus - > chipco , mask , value ) ;
else if ( ssb_extif_available ( & bus - > extif ) )
res = ssb_extif_gpio_polarity ( & bus - > extif , mask , value ) ;
else
2018-07-31 23:15:09 +03:00
WARN_ON ( 1 ) ;
2008-02-19 18:22:50 +03:00
spin_unlock_irqrestore ( & bus - > gpio_lock , flags ) ;
return res ;
}
EXPORT_SYMBOL ( ssb_gpio_polarity ) ;
2008-02-29 13:36:12 +03:00
# ifdef CONFIG_SSB_DRIVER_GIGE
static int gige_pci_init_callback ( struct ssb_bus * bus , unsigned long data )
{
struct pci_dev * pdev = ( struct pci_dev * ) data ;
struct ssb_device * dev ;
unsigned int i ;
int res ;
for ( i = 0 ; i < bus - > nr_devices ; i + + ) {
dev = & ( bus - > devices [ i ] ) ;
if ( dev - > id . coreid ! = SSB_DEV_ETHERNET_GBIT )
continue ;
if ( ! dev - > dev | |
! dev - > dev - > driver | |
! device_is_registered ( dev - > dev ) )
continue ;
res = ssb_gige_pcibios_plat_dev_init ( dev , pdev ) ;
if ( res > = 0 )
return res ;
}
return - ENODEV ;
}
# endif /* CONFIG_SSB_DRIVER_GIGE */
int ssb_pcibios_plat_dev_init ( struct pci_dev * dev )
{
int err ;
err = ssb_pcicore_plat_dev_init ( dev ) ;
if ( ! err )
return 0 ;
# ifdef CONFIG_SSB_DRIVER_GIGE
err = ssb_for_each_bus_call ( ( unsigned long ) dev , gige_pci_init_callback ) ;
if ( err > = 0 )
return err ;
# endif
/* This is not a PCI device on any SSB device. */
return - ENODEV ;
}
# ifdef CONFIG_SSB_DRIVER_GIGE
static int gige_map_irq_callback ( struct ssb_bus * bus , unsigned long data )
{
const struct pci_dev * pdev = ( const struct pci_dev * ) data ;
struct ssb_device * dev ;
unsigned int i ;
int res ;
for ( i = 0 ; i < bus - > nr_devices ; i + + ) {
dev = & ( bus - > devices [ i ] ) ;
if ( dev - > id . coreid ! = SSB_DEV_ETHERNET_GBIT )
continue ;
if ( ! dev - > dev | |
! dev - > dev - > driver | |
! device_is_registered ( dev - > dev ) )
continue ;
res = ssb_gige_map_irq ( dev , pdev ) ;
if ( res > = 0 )
return res ;
}
return - ENODEV ;
}
# endif /* CONFIG_SSB_DRIVER_GIGE */
int ssb_pcibios_map_irq ( const struct pci_dev * dev , u8 slot , u8 pin )
{
int res ;
/* Check if this PCI device is a device on a SSB bus or device
* and return the IRQ number for it . */
res = ssb_pcicore_pcibios_map_irq ( dev , slot , pin ) ;
if ( res > = 0 )
return res ;
# ifdef CONFIG_SSB_DRIVER_GIGE
res = ssb_for_each_bus_call ( ( unsigned long ) dev , gige_map_irq_callback ) ;
if ( res > = 0 )
return res ;
# endif
/* This is not a PCI device on any SSB device. */
return - ENODEV ;
}