2011-05-09 20:56:46 +04:00
/*
* Broadcom specific AMBA
* Bus scanning
*
* Licensed under the GNU / GPL . See COPYING for details .
*/
# include "scan.h"
# include "bcma_private.h"
# include <linux/bcma/bcma.h>
# include <linux/bcma/bcma_regs.h>
# include <linux/pci.h>
# include <linux/io.h>
# include <linux/dma-mapping.h>
# include <linux/slab.h>
struct bcma_device_id_name {
u16 id ;
const char * name ;
} ;
2012-05-05 08:56:31 +04:00
static const struct bcma_device_id_name bcma_arm_device_names [ ] = {
2012-07-11 11:23:43 +04:00
{ BCMA_CORE_4706_MAC_GBIT_COMMON , " BCM4706 GBit MAC Common " } ,
2012-05-05 08:56:31 +04:00
{ BCMA_CORE_ARM_1176 , " ARM 1176 " } ,
{ BCMA_CORE_ARM_7TDMI , " ARM 7TDMI " } ,
{ BCMA_CORE_ARM_CM3 , " ARM CM3 " } ,
} ;
static const struct bcma_device_id_name bcma_bcm_device_names [ ] = {
2011-05-09 20:56:46 +04:00
{ BCMA_CORE_OOB_ROUTER , " OOB Router " } ,
2012-06-26 00:12:20 +04:00
{ BCMA_CORE_4706_CHIPCOMMON , " BCM4706 ChipCommon " } ,
{ BCMA_CORE_4706_SOC_RAM , " BCM4706 SOC RAM " } ,
{ BCMA_CORE_4706_MAC_GBIT , " BCM4706 GBit MAC " } ,
2014-07-31 01:21:06 +04:00
{ BCMA_CORE_NS_PCIEG2 , " PCIe Gen 2 " } ,
{ BCMA_CORE_NS_DMA , " DMA " } ,
{ BCMA_CORE_NS_SDIO3 , " SDIO3 " } ,
{ BCMA_CORE_NS_USB20 , " USB 2.0 " } ,
{ BCMA_CORE_NS_USB30 , " USB 3.0 " } ,
{ BCMA_CORE_NS_A9JTAG , " ARM Cortex A9 JTAG " } ,
{ BCMA_CORE_NS_DDR23 , " Denali DDR2/DDR3 memory controller " } ,
{ BCMA_CORE_NS_ROM , " ROM " } ,
{ BCMA_CORE_NS_NAND , " NAND flash controller " } ,
{ BCMA_CORE_NS_QSPI , " SPI flash controller " } ,
{ BCMA_CORE_NS_CHIPCOMMON_B , " Chipcommon B " } ,
bcma: add some more core names
These cores were found on a BCM4708 (chipid 53010), this is a ARM SoC
with two Cortex A9 cores.
bcma: bus0: Found chip with id 0xCF12, rev 0x00 and package 0x02
bcma: bus0: Core 0 found: ChipCommon (manuf 0x4BF, id 0x800, rev 0x2A, class 0x0)
bcma: bus0: Core 1 found: DMA (manuf 0x4BF, id 0x502, rev 0x01, class 0x0)
bcma: bus0: Core 2 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 3 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 4 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 5 found: GBit MAC (manuf 0x4BF, id 0x82D, rev 0x04, class 0x0)
bcma: bus0: Core 6 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 7 found: PCIe Gen 2 (manuf 0x4BF, id 0x501, rev 0x01, class 0x0)
bcma: bus0: Core 8 found: ARM Cortex A9 core (ihost) (manuf 0x4BF, id 0x510, rev 0x01, class 0x0)
bcma: bus0: Core 9 found: USB 2.0 (manuf 0x4BF, id 0x504, rev 0x01, class 0x0)
bcma: bus0: Core 10 found: USB 3.0 (manuf 0x4BF, id 0x505, rev 0x01, class 0x0)
bcma: bus0: Core 11 found: SDIO3 (manuf 0x4BF, id 0x503, rev 0x01, class 0x0)
bcma: bus0: Core 12 found: ARM Cortex A9 JTAG (manuf 0x4BF, id 0x506, rev 0x01, class 0x0)
bcma: bus0: Core 13 found: Denali DDR2/DDR3 memory controller (manuf 0x4BF, id 0x507, rev 0x01, class 0x0)
bcma: bus0: Core 14 found: ROM (manuf 0x4BF, id 0x508, rev 0x01, class 0x0)
bcma: bus0: Core 15 found: NAND flash controller (manuf 0x4BF, id 0x509, rev 0x01, class 0x0)
bcma: bus0: Core 16 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0)
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2013-07-15 15:15:04 +04:00
{ BCMA_CORE_ARMCA9 , " ARM Cortex A9 core (ihost) " } ,
2012-06-26 00:12:20 +04:00
{ BCMA_CORE_AMEMC , " AMEMC (DDR) " } ,
{ BCMA_CORE_ALTA , " ALTA (I2S) " } ,
2011-05-09 20:56:46 +04:00
{ BCMA_CORE_INVALID , " Invalid " } ,
{ BCMA_CORE_CHIPCOMMON , " ChipCommon " } ,
{ BCMA_CORE_ILINE20 , " ILine 20 " } ,
{ BCMA_CORE_SRAM , " SRAM " } ,
{ BCMA_CORE_SDRAM , " SDRAM " } ,
{ BCMA_CORE_PCI , " PCI " } ,
{ BCMA_CORE_ETHERNET , " Fast Ethernet " } ,
{ BCMA_CORE_V90 , " V90 " } ,
{ BCMA_CORE_USB11_HOSTDEV , " USB 1.1 Hostdev " } ,
{ BCMA_CORE_ADSL , " ADSL " } ,
{ BCMA_CORE_ILINE100 , " ILine 100 " } ,
{ BCMA_CORE_IPSEC , " IPSEC " } ,
{ BCMA_CORE_UTOPIA , " UTOPIA " } ,
{ BCMA_CORE_PCMCIA , " PCMCIA " } ,
{ BCMA_CORE_INTERNAL_MEM , " Internal Memory " } ,
{ BCMA_CORE_MEMC_SDRAM , " MEMC SDRAM " } ,
{ BCMA_CORE_OFDM , " OFDM " } ,
{ BCMA_CORE_EXTIF , " EXTIF " } ,
{ BCMA_CORE_80211 , " IEEE 802.11 " } ,
{ BCMA_CORE_PHY_A , " PHY A " } ,
{ BCMA_CORE_PHY_B , " PHY B " } ,
{ BCMA_CORE_PHY_G , " PHY G " } ,
{ BCMA_CORE_USB11_HOST , " USB 1.1 Host " } ,
{ BCMA_CORE_USB11_DEV , " USB 1.1 Device " } ,
{ BCMA_CORE_USB20_HOST , " USB 2.0 Host " } ,
{ BCMA_CORE_USB20_DEV , " USB 2.0 Device " } ,
{ BCMA_CORE_SDIO_HOST , " SDIO Host " } ,
{ BCMA_CORE_ROBOSWITCH , " Roboswitch " } ,
{ BCMA_CORE_PARA_ATA , " PATA " } ,
{ BCMA_CORE_SATA_XORDMA , " SATA XOR-DMA " } ,
{ BCMA_CORE_ETHERNET_GBIT , " GBit Ethernet " } ,
{ BCMA_CORE_PCIE , " PCIe " } ,
{ BCMA_CORE_PHY_N , " PHY N " } ,
{ BCMA_CORE_SRAM_CTL , " SRAM Controller " } ,
{ BCMA_CORE_MINI_MACPHY , " Mini MACPHY " } ,
{ BCMA_CORE_PHY_LP , " PHY LP " } ,
{ BCMA_CORE_PMU , " PMU " } ,
{ BCMA_CORE_PHY_SSN , " PHY SSN " } ,
{ BCMA_CORE_SDIO_DEV , " SDIO Device " } ,
{ BCMA_CORE_PHY_HT , " PHY HT " } ,
{ BCMA_CORE_MAC_GBIT , " GBit MAC " } ,
{ BCMA_CORE_DDR12_MEM_CTL , " DDR1/DDR2 Memory Controller " } ,
{ BCMA_CORE_PCIE_RC , " PCIe Root Complex " } ,
{ BCMA_CORE_OCP_OCP_BRIDGE , " OCP to OCP Bridge " } ,
{ BCMA_CORE_SHARED_COMMON , " Common Shared " } ,
{ BCMA_CORE_OCP_AHB_BRIDGE , " OCP to AHB Bridge " } ,
{ BCMA_CORE_SPI_HOST , " SPI Host " } ,
{ BCMA_CORE_I2S , " I2S " } ,
{ BCMA_CORE_SDR_DDR1_MEM_CTL , " SDR/DDR1 Memory Controller " } ,
{ BCMA_CORE_SHIM , " SHIM " } ,
2013-05-09 23:24:24 +04:00
{ BCMA_CORE_PCIE2 , " PCIe Gen2 " } ,
{ BCMA_CORE_ARM_CR4 , " ARM CR4 " } ,
2016-01-16 02:48:52 +03:00
{ BCMA_CORE_GCI , " GCI " } ,
{ BCMA_CORE_CMEM , " CNDS DDR2/3 memory controller " } ,
{ BCMA_CORE_ARM_CA7 , " ARM CA7 " } ,
2011-05-09 20:56:46 +04:00
{ BCMA_CORE_DEFAULT , " Default " } ,
} ;
2012-05-05 08:56:31 +04:00
static const struct bcma_device_id_name bcma_mips_device_names [ ] = {
{ BCMA_CORE_MIPS , " MIPS " } ,
{ BCMA_CORE_MIPS_3302 , " MIPS 3302 " } ,
{ BCMA_CORE_MIPS_74K , " MIPS 74K " } ,
} ;
static const char * bcma_device_name ( const struct bcma_device_id * id )
2011-05-09 20:56:46 +04:00
{
2012-05-05 08:56:31 +04:00
const struct bcma_device_id_name * names ;
int size , i ;
2011-05-09 20:56:46 +04:00
2012-05-05 08:56:31 +04:00
/* search manufacturer specific names */
switch ( id - > manuf ) {
case BCMA_MANUF_ARM :
names = bcma_arm_device_names ;
size = ARRAY_SIZE ( bcma_arm_device_names ) ;
break ;
case BCMA_MANUF_BCM :
names = bcma_bcm_device_names ;
size = ARRAY_SIZE ( bcma_bcm_device_names ) ;
break ;
case BCMA_MANUF_MIPS :
names = bcma_mips_device_names ;
size = ARRAY_SIZE ( bcma_mips_device_names ) ;
break ;
default :
return " UNKNOWN " ;
2011-05-09 20:56:46 +04:00
}
2012-05-05 08:56:31 +04:00
for ( i = 0 ; i < size ; i + + ) {
if ( names [ i ] . id = = id - > id )
return names [ i ] . name ;
}
2011-05-09 20:56:46 +04:00
return " UNKNOWN " ;
}
static u32 bcma_scan_read32 ( struct bcma_bus * bus , u8 current_coreidx ,
u16 offset )
{
return readl ( bus - > mmio + offset ) ;
}
static void bcma_scan_switch_core ( struct bcma_bus * bus , u32 addr )
{
if ( bus - > hosttype = = BCMA_HOSTTYPE_PCI )
pci_write_config_dword ( bus - > host_pci , BCMA_PCI_BAR0_WIN ,
addr ) ;
}
2013-03-27 20:16:58 +04:00
static u32 bcma_erom_get_ent ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent = readl ( * eromptr ) ;
( * eromptr ) + + ;
return ent ;
}
2013-03-27 20:16:58 +04:00
static void bcma_erom_push_ent ( u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
( * eromptr ) - - ;
}
2013-03-27 20:16:58 +04:00
static s32 bcma_erom_get_ci ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent = bcma_erom_get_ent ( bus , eromptr ) ;
if ( ! ( ent & SCAN_ER_VALID ) )
return - ENOENT ;
if ( ( ent & SCAN_ER_TAG ) ! = SCAN_ER_TAG_CI )
return - ENOENT ;
return ent ;
}
2013-03-27 20:16:58 +04:00
static bool bcma_erom_is_end ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent = bcma_erom_get_ent ( bus , eromptr ) ;
bcma_erom_push_ent ( eromptr ) ;
return ( ent = = ( SCAN_ER_TAG_END | SCAN_ER_VALID ) ) ;
}
2013-03-27 20:16:58 +04:00
static bool bcma_erom_is_bridge ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent = bcma_erom_get_ent ( bus , eromptr ) ;
bcma_erom_push_ent ( eromptr ) ;
return ( ( ( ent & SCAN_ER_VALID ) ) & &
( ( ent & SCAN_ER_TAGX ) = = SCAN_ER_TAG_ADDR ) & &
( ( ent & SCAN_ADDR_TYPE ) = = SCAN_ADDR_TYPE_BRIDGE ) ) ;
}
2013-03-27 20:16:58 +04:00
static void bcma_erom_skip_component ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent ;
while ( 1 ) {
ent = bcma_erom_get_ent ( bus , eromptr ) ;
if ( ( ent & SCAN_ER_VALID ) & &
( ( ent & SCAN_ER_TAG ) = = SCAN_ER_TAG_CI ) )
break ;
if ( ent = = ( SCAN_ER_TAG_END | SCAN_ER_VALID ) )
break ;
}
bcma_erom_push_ent ( eromptr ) ;
}
2013-03-27 20:16:58 +04:00
static s32 bcma_erom_get_mst_port ( struct bcma_bus * bus , u32 __iomem * * eromptr )
2011-05-09 20:56:46 +04:00
{
u32 ent = bcma_erom_get_ent ( bus , eromptr ) ;
if ( ! ( ent & SCAN_ER_VALID ) )
return - ENOENT ;
if ( ( ent & SCAN_ER_TAG ) ! = SCAN_ER_TAG_MP )
return - ENOENT ;
return ent ;
}
2013-07-15 15:15:08 +04:00
static u32 bcma_erom_get_addr_desc ( struct bcma_bus * bus , u32 __iomem * * eromptr ,
2011-05-09 20:56:46 +04:00
u32 type , u8 port )
{
2020-07-21 11:39:35 +03:00
u32 addrl ;
2011-05-09 20:56:46 +04:00
u32 size ;
u32 ent = bcma_erom_get_ent ( bus , eromptr ) ;
if ( ( ! ( ent & SCAN_ER_VALID ) ) | |
( ( ent & SCAN_ER_TAGX ) ! = SCAN_ER_TAG_ADDR ) | |
( ( ent & SCAN_ADDR_TYPE ) ! = type ) | |
( ( ( ent & SCAN_ADDR_PORT ) > > SCAN_ADDR_PORT_SHIFT ) ! = port ) ) {
bcma_erom_push_ent ( eromptr ) ;
2013-07-15 15:15:08 +04:00
return ( u32 ) - EINVAL ;
2011-05-09 20:56:46 +04:00
}
addrl = ent & SCAN_ADDR_ADDR ;
if ( ent & SCAN_ADDR_AG32 )
2020-07-21 11:39:35 +03:00
bcma_erom_get_ent ( bus , eromptr ) ;
2011-05-09 20:56:46 +04:00
if ( ( ent & SCAN_ADDR_SZ ) = = SCAN_ADDR_SZ_SZD ) {
size = bcma_erom_get_ent ( bus , eromptr ) ;
if ( size & SCAN_SIZE_SG32 )
2020-07-21 11:39:35 +03:00
bcma_erom_get_ent ( bus , eromptr ) ;
2019-11-27 15:44:33 +03:00
}
2011-05-09 20:56:46 +04:00
return addrl ;
}
2011-07-23 03:20:07 +04:00
static struct bcma_device * bcma_find_core_by_index ( struct bcma_bus * bus ,
u16 index )
{
struct bcma_device * core ;
list_for_each_entry ( core , & bus - > cores , list ) {
if ( core - > core_index = = index )
return core ;
}
return NULL ;
}
2012-01-31 03:03:31 +04:00
static struct bcma_device * bcma_find_core_reverse ( struct bcma_bus * bus , u16 coreid )
{
struct bcma_device * core ;
list_for_each_entry_reverse ( core , & bus - > cores , list ) {
if ( core - > id . id = = coreid )
return core ;
}
return NULL ;
}
2013-09-07 19:02:49 +04:00
# define IS_ERR_VALUE_U32(x) ((x) >= (u32)-MAX_ERRNO)
2011-07-23 03:20:05 +04:00
static int bcma_get_next_core ( struct bcma_bus * bus , u32 __iomem * * eromptr ,
2011-07-23 03:20:07 +04:00
struct bcma_device_id * match , int core_num ,
2011-07-23 03:20:05 +04:00
struct bcma_device * core )
{
2013-07-15 15:15:08 +04:00
u32 tmp ;
2014-09-09 00:53:35 +04:00
u8 i , j , k ;
2011-07-23 03:20:05 +04:00
s32 cia , cib ;
u8 ports [ 2 ] , wrappers [ 2 ] ;
/* get CIs */
cia = bcma_erom_get_ci ( bus , eromptr ) ;
if ( cia < 0 ) {
bcma_erom_push_ent ( eromptr ) ;
if ( bcma_erom_is_end ( bus , eromptr ) )
return - ESPIPE ;
return - EILSEQ ;
}
cib = bcma_erom_get_ci ( bus , eromptr ) ;
if ( cib < 0 )
return - EILSEQ ;
/* parse CIs */
core - > id . class = ( cia & SCAN_CIA_CLASS ) > > SCAN_CIA_CLASS_SHIFT ;
core - > id . id = ( cia & SCAN_CIA_ID ) > > SCAN_CIA_ID_SHIFT ;
core - > id . manuf = ( cia & SCAN_CIA_MANUF ) > > SCAN_CIA_MANUF_SHIFT ;
ports [ 0 ] = ( cib & SCAN_CIB_NMP ) > > SCAN_CIB_NMP_SHIFT ;
ports [ 1 ] = ( cib & SCAN_CIB_NSP ) > > SCAN_CIB_NSP_SHIFT ;
wrappers [ 0 ] = ( cib & SCAN_CIB_NMW ) > > SCAN_CIB_NMW_SHIFT ;
wrappers [ 1 ] = ( cib & SCAN_CIB_NSW ) > > SCAN_CIB_NSW_SHIFT ;
core - > id . rev = ( cib & SCAN_CIB_REV ) > > SCAN_CIB_REV_SHIFT ;
if ( ( ( core - > id . manuf = = BCMA_MANUF_ARM ) & &
( core - > id . id = = 0xFFF ) ) | |
( ports [ 1 ] = = 0 ) ) {
bcma_erom_skip_component ( bus , eromptr ) ;
return - ENXIO ;
}
/* check if component is a core at all */
if ( wrappers [ 0 ] + wrappers [ 1 ] = = 0 ) {
2012-07-11 11:23:43 +04:00
/* Some specific cores don't need wrappers */
switch ( core - > id . id ) {
case BCMA_CORE_4706_MAC_GBIT_COMMON :
2014-09-09 00:53:36 +04:00
case BCMA_CORE_NS_CHIPCOMMON_B :
2016-01-16 02:48:53 +03:00
case BCMA_CORE_PMU :
case BCMA_CORE_GCI :
2012-07-11 11:23:43 +04:00
/* Not used yet: case BCMA_CORE_OOB_ROUTER: */
break ;
default :
bcma_erom_skip_component ( bus , eromptr ) ;
return - ENXIO ;
}
2011-07-23 03:20:05 +04:00
}
if ( bcma_erom_is_bridge ( bus , eromptr ) ) {
bcma_erom_skip_component ( bus , eromptr ) ;
return - ENXIO ;
}
2011-07-23 03:20:07 +04:00
if ( bcma_find_core_by_index ( bus , core_num ) ) {
bcma_erom_skip_component ( bus , eromptr ) ;
return - ENODEV ;
}
if ( match & & ( ( match - > manuf ! = BCMA_ANY_MANUF & &
match - > manuf ! = core - > id . manuf ) | |
( match - > id ! = BCMA_ANY_ID & & match - > id ! = core - > id . id ) | |
( match - > rev ! = BCMA_ANY_REV & & match - > rev ! = core - > id . rev ) | |
( match - > class ! = BCMA_ANY_CLASS & & match - > class ! = core - > id . class )
) ) {
bcma_erom_skip_component ( bus , eromptr ) ;
return - ENODEV ;
}
2011-07-23 03:20:05 +04:00
/* get & parse master ports */
for ( i = 0 ; i < ports [ 0 ] ; i + + ) {
2011-08-23 23:15:35 +04:00
s32 mst_port_d = bcma_erom_get_mst_port ( bus , eromptr ) ;
2011-07-23 03:20:05 +04:00
if ( mst_port_d < 0 )
return - EILSEQ ;
}
2012-03-16 02:49:56 +04:00
/* First Slave Address Descriptor should be port 0:
* the main register space for the core
*/
tmp = bcma_erom_get_addr_desc ( bus , eromptr , SCAN_ADDR_TYPE_SLAVE , 0 ) ;
2013-09-07 19:02:49 +04:00
if ( tmp = = 0 | | IS_ERR_VALUE_U32 ( tmp ) ) {
2012-03-16 02:49:56 +04:00
/* Try again to see if it is a bridge */
tmp = bcma_erom_get_addr_desc ( bus , eromptr ,
SCAN_ADDR_TYPE_BRIDGE , 0 ) ;
2013-09-07 19:02:49 +04:00
if ( tmp = = 0 | | IS_ERR_VALUE_U32 ( tmp ) ) {
2012-03-16 02:49:56 +04:00
return - EILSEQ ;
} else {
2012-07-06 00:07:32 +04:00
bcma_info ( bus , " Bridge found \n " ) ;
2012-03-16 02:49:56 +04:00
return - ENXIO ;
}
}
core - > addr = tmp ;
2011-07-23 03:20:05 +04:00
/* get & parse slave ports */
2014-09-09 00:53:35 +04:00
k = 0 ;
2011-07-23 03:20:05 +04:00
for ( i = 0 ; i < ports [ 1 ] ; i + + ) {
for ( j = 0 ; ; j + + ) {
tmp = bcma_erom_get_addr_desc ( bus , eromptr ,
SCAN_ADDR_TYPE_SLAVE , i ) ;
2013-09-07 19:02:49 +04:00
if ( IS_ERR_VALUE_U32 ( tmp ) ) {
2011-07-23 03:20:05 +04:00
/* no more entries for port _i_ */
/* pr_debug("erom: slave port %d "
* " has %d descriptors \n " , i , j ) ; */
break ;
2014-09-09 00:53:35 +04:00
} else if ( k < ARRAY_SIZE ( core - > addr_s ) ) {
core - > addr_s [ k ] = tmp ;
k + + ;
2011-07-23 03:20:05 +04:00
}
}
}
/* get & parse master wrappers */
for ( i = 0 ; i < wrappers [ 0 ] ; i + + ) {
for ( j = 0 ; ; j + + ) {
tmp = bcma_erom_get_addr_desc ( bus , eromptr ,
SCAN_ADDR_TYPE_MWRAP , i ) ;
2013-09-07 19:02:49 +04:00
if ( IS_ERR_VALUE_U32 ( tmp ) ) {
2011-07-23 03:20:05 +04:00
/* no more entries for port _i_ */
/* pr_debug("erom: master wrapper %d "
* " has %d descriptors \n " , i , j ) ; */
break ;
} else {
if ( i = = 0 & & j = = 0 )
core - > wrap = tmp ;
}
}
}
/* get & parse slave wrappers */
for ( i = 0 ; i < wrappers [ 1 ] ; i + + ) {
u8 hack = ( ports [ 1 ] = = 1 ) ? 0 : 1 ;
for ( j = 0 ; ; j + + ) {
tmp = bcma_erom_get_addr_desc ( bus , eromptr ,
SCAN_ADDR_TYPE_SWRAP , i + hack ) ;
2013-09-07 19:02:49 +04:00
if ( IS_ERR_VALUE_U32 ( tmp ) ) {
2011-07-23 03:20:05 +04:00
/* no more entries for port _i_ */
/* pr_debug("erom: master wrapper %d "
* has % d descriptors \ n " , i, j); */
break ;
} else {
if ( wrappers [ 0 ] = = 0 & & ! i & & ! j )
core - > wrap = tmp ;
}
}
}
2011-07-23 03:20:08 +04:00
if ( bus - > hosttype = = BCMA_HOSTTYPE_SOC ) {
2020-01-06 11:43:50 +03:00
core - > io_addr = ioremap ( core - > addr , BCMA_CORE_SIZE ) ;
2011-07-23 03:20:08 +04:00
if ( ! core - > io_addr )
return - ENOMEM ;
2014-08-22 10:44:52 +04:00
if ( core - > wrap ) {
2020-01-06 11:43:50 +03:00
core - > io_wrap = ioremap ( core - > wrap ,
2014-08-22 10:44:52 +04:00
BCMA_CORE_SIZE ) ;
if ( ! core - > io_wrap ) {
iounmap ( core - > io_addr ) ;
return - ENOMEM ;
}
2011-07-23 03:20:08 +04:00
}
}
2011-07-23 03:20:05 +04:00
return 0 ;
}
2015-01-16 22:59:39 +03:00
void bcma_detect_chip ( struct bcma_bus * bus )
2011-05-09 20:56:46 +04:00
{
s32 tmp ;
2012-02-01 03:13:54 +04:00
struct bcma_chipinfo * chipinfo = & ( bus - > chipinfo ) ;
2014-09-18 01:50:55 +04:00
char chip_id [ 8 ] ;
2011-05-09 20:56:46 +04:00
bcma_scan_switch_core ( bus , BCMA_ADDR_BASE ) ;
tmp = bcma_scan_read32 ( bus , 0 , BCMA_CC_ID ) ;
2012-02-01 03:13:54 +04:00
chipinfo - > id = ( tmp & BCMA_CC_ID_ID ) > > BCMA_CC_ID_ID_SHIFT ;
chipinfo - > rev = ( tmp & BCMA_CC_ID_REV ) > > BCMA_CC_ID_REV_SHIFT ;
chipinfo - > pkg = ( tmp & BCMA_CC_ID_PKG ) > > BCMA_CC_ID_PKG_SHIFT ;
2014-09-18 01:50:55 +04:00
snprintf ( chip_id , ARRAY_SIZE ( chip_id ) ,
( chipinfo - > id > 0x9999 ) ? " %d " : " 0x%04X " , chipinfo - > id ) ;
bcma_info ( bus , " Found chip with id %s, rev 0x%02X and package 0x%02X \n " ,
chip_id , chipinfo - > rev , chipinfo - > pkg ) ;
2011-07-23 03:20:06 +04:00
}
int bcma_bus_scan ( struct bcma_bus * bus )
{
u32 erombase ;
u32 __iomem * eromptr , * eromend ;
2011-07-23 03:20:07 +04:00
int err , core_num = 0 ;
2011-07-23 03:20:06 +04:00
2015-01-19 10:30:30 +03:00
/* Skip if bus was already scanned (e.g. during early register) */
if ( bus - > nr_cores )
return 0 ;
2011-05-09 20:56:46 +04:00
erombase = bcma_scan_read32 ( bus , 0 , BCMA_CC_EROM ) ;
2011-07-23 03:20:08 +04:00
if ( bus - > hosttype = = BCMA_HOSTTYPE_SOC ) {
2020-01-06 11:43:50 +03:00
eromptr = ioremap ( erombase , BCMA_CORE_SIZE ) ;
2011-07-23 03:20:08 +04:00
if ( ! eromptr )
return - ENOMEM ;
} else {
eromptr = bus - > mmio ;
}
2011-05-09 20:56:46 +04:00
eromend = eromptr + BCMA_CORE_SIZE / sizeof ( u32 ) ;
bcma_scan_switch_core ( bus , erombase ) ;
while ( eromptr < eromend ) {
2012-01-31 03:03:31 +04:00
struct bcma_device * other_core ;
2011-05-09 20:56:46 +04:00
struct bcma_device * core = kzalloc ( sizeof ( * core ) , GFP_KERNEL ) ;
2012-07-26 19:45:52 +04:00
if ( ! core ) {
err = - ENOMEM ;
goto out ;
}
2011-05-09 20:56:46 +04:00
INIT_LIST_HEAD ( & core - > list ) ;
core - > bus = bus ;
2011-07-23 03:20:07 +04:00
err = bcma_get_next_core ( bus , & eromptr , NULL , core_num , core ) ;
2012-01-30 00:34:04 +04:00
if ( err < 0 ) {
kfree ( core ) ;
if ( err = = - ENODEV ) {
core_num + + ;
continue ;
} else if ( err = = - ENXIO ) {
continue ;
} else if ( err = = - ESPIPE ) {
break ;
}
2012-07-26 19:45:52 +04:00
goto out ;
2012-01-30 00:34:04 +04:00
}
2011-05-09 20:56:46 +04:00
2011-07-23 03:20:07 +04:00
core - > core_index = core_num + + ;
bus - > nr_cores + + ;
2012-01-31 03:03:31 +04:00
other_core = bcma_find_core_reverse ( bus , core - > id . id ) ;
core - > core_unit = ( other_core = = NULL ) ? 0 : other_core - > core_unit + 1 ;
2014-10-03 19:00:24 +04:00
bcma_prepare_core ( bus , core ) ;
2011-07-23 03:20:07 +04:00
2012-07-06 00:07:32 +04:00
bcma_info ( bus , " Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X) \n " ,
core - > core_index , bcma_device_name ( & core - > id ) ,
core - > id . manuf , core - > id . id , core - > id . rev ,
core - > id . class ) ;
2011-05-09 20:56:46 +04:00
2012-07-11 14:37:00 +04:00
list_add_tail ( & core - > list , & bus - > cores ) ;
2011-05-09 20:56:46 +04:00
}
2012-07-26 19:45:52 +04:00
err = 0 ;
out :
2011-07-23 03:20:08 +04:00
if ( bus - > hosttype = = BCMA_HOSTTYPE_SOC )
iounmap ( eromptr ) ;
2012-07-26 19:45:52 +04:00
return err ;
2011-05-09 20:56:46 +04:00
}