2019-05-27 09:55:05 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-07-26 13:19:06 +04:00
/*
* Versatile board support using the device tree
*
* Copyright ( C ) 2010 Secret Lab Technologies Ltd .
* Copyright ( C ) 2009 Jeremy Kerr < jeremy . kerr @ canonical . com >
* Copyright ( C ) 2004 ARM Limited
* Copyright ( C ) 2000 Deep Blue Solutions Ltd
*/
# include <linux/init.h>
2015-12-08 23:44:15 +03:00
# include <linux/io.h>
# include <linux/of.h>
# include <linux/of_address.h>
2011-07-26 13:19:06 +04:00
# include <linux/of_irq.h>
# include <linux/of_platform.h>
2015-12-08 23:44:15 +03:00
# include <linux/slab.h>
2015-12-08 23:44:17 +03:00
# include <linux/amba/bus.h>
# include <linux/amba/mmci.h>
2011-07-26 13:19:06 +04:00
# include <asm/mach-types.h>
# include <asm/mach/arch.h>
2015-12-08 23:44:17 +03:00
# include <asm/mach/map.h>
2011-07-26 13:19:06 +04:00
2015-12-08 23:44:17 +03:00
/* macro to get at MMIO space when running virtually */
# define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
# define __io_address(n) ((void __iomem __force *)IO_ADDRESS(n))
2011-07-26 13:19:06 +04:00
2015-12-08 23:44:17 +03:00
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Versatile Registers
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
2015-12-08 23:44:15 +03:00
# define VERSATILE_SYS_PCICTL_OFFSET 0x44
2015-12-08 23:44:17 +03:00
# define VERSATILE_SYS_MCI_OFFSET 0x48
/*
* VERSATILE peripheral addresses
*/
# define VERSATILE_MMCI0_BASE 0x10005000 /* MMC interface */
# define VERSATILE_MMCI1_BASE 0x1000B000 /* MMC Interface */
# define VERSATILE_SCTL_BASE 0x101E0000 /* System controller */
/*
* System controller bit assignment
*/
# define VERSATILE_REFCLK 0
# define VERSATILE_TIMCLK 1
# define VERSATILE_TIMER1_EnSel 15
# define VERSATILE_TIMER2_EnSel 17
# define VERSATILE_TIMER3_EnSel 19
# define VERSATILE_TIMER4_EnSel 21
2015-12-08 23:44:15 +03:00
static void __iomem * versatile_sys_base ;
2015-12-08 23:44:17 +03:00
unsigned int mmc_status ( struct device * dev )
{
struct amba_device * adev = container_of ( dev , struct amba_device , dev ) ;
u32 mask ;
if ( adev - > res . start = = VERSATILE_MMCI0_BASE )
mask = 1 ;
else
mask = 2 ;
return readl ( versatile_sys_base + VERSATILE_SYS_MCI_OFFSET ) & mask ;
}
static struct mmci_platform_data mmc0_plat_data = {
. ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 ,
. status = mmc_status ,
} ;
static struct mmci_platform_data mmc1_plat_data = {
. ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 ,
. status = mmc_status ,
} ;
/*
* Lookup table for attaching a specific name and platform_data pointer to
* devices as they get created by of_platform_populate ( ) . Ideally this table
* would not exist , but the current clock implementation depends on some devices
* having a specific name .
*/
struct of_dev_auxdata versatile_auxdata_lookup [ ] __initdata = {
OF_DEV_AUXDATA ( " arm,primecell " , VERSATILE_MMCI0_BASE , " fpga:05 " , & mmc0_plat_data ) ,
OF_DEV_AUXDATA ( " arm,primecell " , VERSATILE_MMCI1_BASE , " fpga:0b " , & mmc1_plat_data ) ,
{ }
} ;
static struct map_desc versatile_io_desc [ ] __initdata __maybe_unused = {
{
. virtual = IO_ADDRESS ( VERSATILE_SCTL_BASE ) ,
. pfn = __phys_to_pfn ( VERSATILE_SCTL_BASE ) ,
. length = SZ_4K * 9 ,
. type = MT_DEVICE
}
} ;
static void __init versatile_map_io ( void )
{
debug_ll_io_init ( ) ;
iotable_init ( versatile_io_desc , ARRAY_SIZE ( versatile_io_desc ) ) ;
}
static void __init versatile_init_early ( void )
{
u32 val ;
/*
* set clock frequency :
* VERSATILE_REFCLK is 32 KHz
* VERSATILE_TIMCLK is 1 MHz
*/
val = readl ( __io_address ( VERSATILE_SCTL_BASE ) ) ;
writel ( ( VERSATILE_TIMCLK < < VERSATILE_TIMER1_EnSel ) |
( VERSATILE_TIMCLK < < VERSATILE_TIMER2_EnSel ) |
( VERSATILE_TIMCLK < < VERSATILE_TIMER3_EnSel ) |
( VERSATILE_TIMCLK < < VERSATILE_TIMER4_EnSel ) | val ,
__io_address ( VERSATILE_SCTL_BASE ) ) ;
}
2015-12-08 23:44:15 +03:00
static void __init versatile_dt_pci_init ( void )
{
u32 val ;
struct device_node * np ;
struct property * newprop ;
np = of_find_compatible_node ( NULL , NULL , " arm,versatile-pci " ) ;
if ( ! np )
return ;
/* Check if PCI backplane is detected */
val = readl ( versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET ) ;
if ( val & 1 ) {
/*
* Enable PCI accesses . Note that the documentaton is
* inconsistent whether or not this is needed , but the old
* driver had it so we will keep it .
*/
writel ( 1 , versatile_sys_base + VERSATILE_SYS_PCICTL_OFFSET ) ;
2019-03-01 11:56:52 +03:00
goto out_put_node ;
2015-12-08 23:44:15 +03:00
}
newprop = kzalloc ( sizeof ( * newprop ) , GFP_KERNEL ) ;
if ( ! newprop )
2019-03-01 11:56:52 +03:00
goto out_put_node ;
2015-12-08 23:44:15 +03:00
newprop - > name = kstrdup ( " status " , GFP_KERNEL ) ;
newprop - > value = kstrdup ( " disabled " , GFP_KERNEL ) ;
newprop - > length = sizeof ( " disabled " ) ;
of_update_property ( np , newprop ) ;
pr_info ( " Not plugged into PCI backplane! \n " ) ;
2019-03-01 11:56:52 +03:00
out_put_node :
of_node_put ( np ) ;
2015-12-08 23:44:15 +03:00
}
2011-07-26 13:19:06 +04:00
static void __init versatile_dt_init ( void )
{
2015-12-08 23:44:15 +03:00
struct device_node * np ;
np = of_find_compatible_node ( NULL , NULL , " arm,core-module-versatile " ) ;
if ( np )
versatile_sys_base = of_iomap ( np , 0 ) ;
WARN_ON ( ! versatile_sys_base ) ;
versatile_dt_pci_init ( ) ;
2016-06-01 09:53:05 +03:00
of_platform_default_populate ( NULL , versatile_auxdata_lookup , NULL ) ;
2011-07-26 13:19:06 +04:00
}
2015-02-18 23:01:45 +03:00
static const char * const versatile_dt_match [ ] __initconst = {
2011-07-26 13:19:06 +04:00
" arm,versatile-ab " ,
" arm,versatile-pb " ,
NULL ,
} ;
DT_MACHINE_START ( VERSATILE_PB , " ARM-Versatile (Device Tree Support) " )
. map_io = versatile_map_io ,
. init_early = versatile_init_early ,
. init_machine = versatile_dt_init ,
. dt_compat = versatile_dt_match ,
MACHINE_END