2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-16 15:20:36 -07:00
/*
* linux / arch / arm / mach - sa1100 / generic . c
*
* Author : Nicolas Pitre
*
* Code common to all SA11x0 machines .
*/
2011-07-26 10:53:52 +01:00
# include <linux/gpio.h>
2016-08-31 08:49:47 +01:00
# include <linux/gpio/machine.h>
2005-04-16 15:20:36 -07:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/delay.h>
2012-01-09 21:45:51 +00:00
# include <linux/dma-mapping.h>
2005-04-16 15:20:36 -07:00
# include <linux/pm.h>
# include <linux/cpufreq.h>
# include <linux/ioport.h>
2005-10-29 19:07:23 +01:00
# include <linux/platform_device.h>
2013-07-08 16:01:40 -07:00
# include <linux/reboot.h>
2016-08-31 08:49:47 +01:00
# include <linux/regulator/fixed.h>
# include <linux/regulator/machine.h>
2015-05-19 16:16:14 +01:00
# include <linux/irqchip/irq-sa11x0.h>
2005-04-16 15:20:36 -07:00
2012-01-14 11:50:04 +00:00
# include <video/sa1100fb.h>
2015-05-18 15:58:57 +01:00
# include <soc/sa1100/pwer.h>
2005-04-16 15:20:36 -07:00
# include <asm/div64.h>
# include <asm/mach/map.h>
2005-10-29 16:08:31 +01:00
# include <asm/mach/flash.h>
2005-04-16 15:20:36 -07:00
# include <asm/irq.h>
2012-03-28 18:30:01 +01:00
# include <asm/system_misc.h>
2005-04-16 15:20:36 -07:00
2012-02-24 00:06:51 +01:00
# include <mach/hardware.h>
# include <mach/irqs.h>
2016-08-19 16:34:45 +01:00
# include <mach/reset.h>
2012-02-24 00:06:51 +01:00
2005-04-16 15:20:36 -07:00
# include "generic.h"
2014-12-21 16:08:13 +01:00
# include <clocksource/pxa.h>
2005-04-16 15:20:36 -07:00
2008-07-29 14:26:00 +08:00
unsigned int reset_status ;
EXPORT_SYMBOL ( reset_status ) ;
2005-04-16 15:20:36 -07:00
# define NR_FREQS 16
/*
* This table is setup for a 3.6864 MHz Crystal .
*/
2013-09-16 18:56:32 +05:30
struct cpufreq_frequency_table sa11x0_freq_table [ NR_FREQS + 1 ] = {
{ . frequency = 59000 , /* 59.0 MHz */ } ,
{ . frequency = 73700 , /* 73.7 MHz */ } ,
{ . frequency = 88500 , /* 88.5 MHz */ } ,
{ . frequency = 103200 , /* 103.2 MHz */ } ,
{ . frequency = 118000 , /* 118.0 MHz */ } ,
{ . frequency = 132700 , /* 132.7 MHz */ } ,
{ . frequency = 147500 , /* 147.5 MHz */ } ,
{ . frequency = 162200 , /* 162.2 MHz */ } ,
{ . frequency = 176900 , /* 176.9 MHz */ } ,
{ . frequency = 191700 , /* 191.7 MHz */ } ,
{ . frequency = 206400 , /* 206.4 MHz */ } ,
{ . frequency = 221200 , /* 221.2 MHz */ } ,
{ . frequency = 235900 , /* 235.9 MHz */ } ,
{ . frequency = 250700 , /* 250.7 MHz */ } ,
{ . frequency = 265400 , /* 265.4 MHz */ } ,
{ . frequency = 280200 , /* 280.2 MHz */ } ,
{ . frequency = CPUFREQ_TABLE_END , } ,
2005-04-16 15:20:36 -07:00
} ;
unsigned int sa11x0_getspeed ( unsigned int cpu )
{
if ( cpu )
return 0 ;
2013-09-16 18:56:32 +05:30
return sa11x0_freq_table [ PPCR & 0xf ] . frequency ;
2005-04-16 15:20:36 -07:00
}
/*
* Default power - off for SA1100
*/
static void sa1100_power_off ( void )
{
mdelay ( 100 ) ;
local_irq_disable ( ) ;
/* disable internal oscillator, float CS lines */
PCFR = ( PCFR_OPDE | PCFR_FP | PCFR_FS ) ;
/* enable wake-up on GPIO0 (Assabet...) */
PWER = GFER = GRER = 1 ;
/*
* set scratchpad to zero , just in case it is used as a
* restart address by the bootloader .
*/
PSPR = 0 ;
/* enter sleep mode */
PMCR = PMCR_SF ;
}
2013-07-08 16:01:40 -07:00
void sa11x0_restart ( enum reboot_mode mode , const char * cmd )
2011-11-05 10:28:50 +00:00
{
2016-08-19 16:34:45 +01:00
clear_reset_status ( RESET_STATUS_ALL ) ;
2013-07-08 16:01:40 -07:00
if ( mode = = REBOOT_SOFT ) {
2011-11-05 10:28:50 +00:00
/* Jump into ROM at address 0 */
soft_restart ( 0 ) ;
} else {
/* Use on-chip reset capability */
RSRR = RSRR_SWR ;
}
}
2009-10-06 14:55:53 +01:00
static void sa11x0_register_device ( struct platform_device * dev , void * data )
{
int err ;
dev - > dev . platform_data = data ;
err = platform_device_register ( dev ) ;
if ( err )
printk ( KERN_ERR " Unable to register device %s: %d \n " ,
dev - > name , err ) ;
}
2005-04-16 15:20:36 -07:00
static struct resource sa11x0udc_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( __PREG ( Ser0UDCCR ) , SZ_64K ) ,
[ 1 ] = DEFINE_RES_IRQ ( IRQ_Ser0UDC ) ,
2005-04-16 15:20:36 -07:00
} ;
static u64 sa11x0udc_dma_mask = 0xffffffffUL ;
static struct platform_device sa11x0udc_device = {
. name = " sa11x0-udc " ,
. id = - 1 ,
. dev = {
. dma_mask = & sa11x0udc_dma_mask ,
. coherent_dma_mask = 0xffffffff ,
} ,
. num_resources = ARRAY_SIZE ( sa11x0udc_resources ) ,
. resource = sa11x0udc_resources ,
} ;
static struct resource sa11x0uart1_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( __PREG ( Ser1UTCR0 ) , SZ_64K ) ,
[ 1 ] = DEFINE_RES_IRQ ( IRQ_Ser1UART ) ,
2005-04-16 15:20:36 -07:00
} ;
static struct platform_device sa11x0uart1_device = {
. name = " sa11x0-uart " ,
. id = 1 ,
. num_resources = ARRAY_SIZE ( sa11x0uart1_resources ) ,
. resource = sa11x0uart1_resources ,
} ;
static struct resource sa11x0uart3_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( __PREG ( Ser3UTCR0 ) , SZ_64K ) ,
[ 1 ] = DEFINE_RES_IRQ ( IRQ_Ser3UART ) ,
2005-04-16 15:20:36 -07:00
} ;
static struct platform_device sa11x0uart3_device = {
. name = " sa11x0-uart " ,
. id = 3 ,
. num_resources = ARRAY_SIZE ( sa11x0uart3_resources ) ,
. resource = sa11x0uart3_resources ,
} ;
static struct resource sa11x0mcp_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( __PREG ( Ser4MCCR0 ) , SZ_64K ) ,
2012-03-25 23:56:30 +01:00
[ 1 ] = DEFINE_RES_MEM ( __PREG ( Ser4MCCR1 ) , 4 ) ,
[ 2 ] = DEFINE_RES_IRQ ( IRQ_Ser4MCP ) ,
2005-04-16 15:20:36 -07:00
} ;
static u64 sa11x0mcp_dma_mask = 0xffffffffUL ;
static struct platform_device sa11x0mcp_device = {
. name = " sa11x0-mcp " ,
. id = - 1 ,
. dev = {
. dma_mask = & sa11x0mcp_dma_mask ,
. coherent_dma_mask = 0xffffffff ,
} ,
. num_resources = ARRAY_SIZE ( sa11x0mcp_resources ) ,
. resource = sa11x0mcp_resources ,
} ;
2012-01-20 22:24:07 +00:00
void __init sa11x0_ppc_configure_mcp ( void )
{
/* Setup the PPC unit for the MCP */
PPDR & = ~ PPC_RXD4 ;
PPDR | = PPC_TXD4 | PPC_SCLK | PPC_SFRM ;
PSDR | = PPC_RXD4 ;
PSDR & = ~ ( PPC_TXD4 | PPC_SCLK | PPC_SFRM ) ;
PPSR & = ~ ( PPC_TXD4 | PPC_SCLK | PPC_SFRM ) ;
}
2009-10-06 14:55:53 +01:00
void sa11x0_register_mcp ( struct mcp_plat_data * data )
2005-08-18 10:10:46 +01:00
{
2009-10-06 14:55:53 +01:00
sa11x0_register_device ( & sa11x0mcp_device , data ) ;
2005-08-18 10:10:46 +01:00
}
2005-04-16 15:20:36 -07:00
static struct resource sa11x0ssp_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( 0x80070000 , SZ_64K ) ,
[ 1 ] = DEFINE_RES_IRQ ( IRQ_Ser4SSP ) ,
2005-04-16 15:20:36 -07:00
} ;
static u64 sa11x0ssp_dma_mask = 0xffffffffUL ;
static struct platform_device sa11x0ssp_device = {
. name = " sa11x0-ssp " ,
. id = - 1 ,
. dev = {
. dma_mask = & sa11x0ssp_dma_mask ,
. coherent_dma_mask = 0xffffffff ,
} ,
. num_resources = ARRAY_SIZE ( sa11x0ssp_resources ) ,
. resource = sa11x0ssp_resources ,
} ;
static struct resource sa11x0fb_resources [ ] = {
2012-01-12 10:25:29 +00:00
[ 0 ] = DEFINE_RES_MEM ( 0xb0100000 , SZ_64K ) ,
[ 1 ] = DEFINE_RES_IRQ ( IRQ_LCD ) ,
2005-04-16 15:20:36 -07:00
} ;
static struct platform_device sa11x0fb_device = {
. name = " sa11x0-fb " ,
. id = - 1 ,
. dev = {
. coherent_dma_mask = 0xffffffff ,
} ,
. num_resources = ARRAY_SIZE ( sa11x0fb_resources ) ,
. resource = sa11x0fb_resources ,
} ;
2012-01-14 11:50:04 +00:00
void sa11x0_register_lcd ( struct sa1100fb_mach_info * inf )
{
sa11x0_register_device ( & sa11x0fb_device , inf ) ;
}
2016-08-31 08:49:47 +01:00
void sa11x0_register_pcmcia ( int socket , struct gpiod_lookup_table * table )
{
if ( table )
gpiod_add_lookup_table ( table ) ;
platform_device_register_simple ( " sa11x0-pcmcia " , socket , NULL , 0 ) ;
}
2005-04-16 15:20:36 -07:00
static struct platform_device sa11x0mtd_device = {
2009-01-31 01:21:58 +01:00
. name = " sa1100-mtd " ,
2005-04-16 15:20:36 -07:00
. id = - 1 ,
} ;
2009-10-06 14:55:53 +01:00
void sa11x0_register_mtd ( struct flash_platform_data * flash ,
struct resource * res , int nr )
2005-04-16 15:20:36 -07:00
{
2005-10-29 16:08:31 +01:00
flash - > name = " sa1100 " ;
2005-04-16 15:20:36 -07:00
sa11x0mtd_device . resource = res ;
sa11x0mtd_device . num_resources = nr ;
2009-10-06 14:55:53 +01:00
sa11x0_register_device ( & sa11x0mtd_device , flash ) ;
2005-04-16 15:20:36 -07:00
}
static struct resource sa11x0ir_resources [ ] = {
2012-01-12 10:25:29 +00:00
DEFINE_RES_MEM ( __PREG ( Ser2UTCR0 ) , 0x24 ) ,
DEFINE_RES_MEM ( __PREG ( Ser2HSCR0 ) , 0x1c ) ,
DEFINE_RES_MEM ( __PREG ( Ser2HSCR2 ) , 0x04 ) ,
DEFINE_RES_IRQ ( IRQ_Ser2ICP ) ,
2005-04-16 15:20:36 -07:00
} ;
static struct platform_device sa11x0ir_device = {
. name = " sa11x0-ir " ,
. id = - 1 ,
. num_resources = ARRAY_SIZE ( sa11x0ir_resources ) ,
. resource = sa11x0ir_resources ,
} ;
2009-10-06 14:55:53 +01:00
void sa11x0_register_irda ( struct irda_platform_data * irda )
2005-04-16 15:20:36 -07:00
{
2009-10-06 14:55:53 +01:00
sa11x0_register_device ( & sa11x0ir_device , irda ) ;
2005-04-16 15:20:36 -07:00
}
2012-02-21 11:51:13 +08:00
static struct resource sa1100_rtc_resources [ ] = {
2012-04-14 10:26:19 +04:00
DEFINE_RES_MEM ( 0x90010000 , 0x40 ) ,
2012-02-21 11:51:13 +08:00
DEFINE_RES_IRQ_NAMED ( IRQ_RTC1Hz , " rtc 1Hz " ) ,
DEFINE_RES_IRQ_NAMED ( IRQ_RTCAlrm , " rtc alarm " ) ,
} ;
2006-03-27 01:16:46 -08:00
static struct platform_device sa11x0rtc_device = {
. name = " sa1100-rtc " ,
. id = - 1 ,
2012-02-21 11:51:13 +08:00
. num_resources = ARRAY_SIZE ( sa1100_rtc_resources ) ,
. resource = sa1100_rtc_resources ,
2006-03-27 01:16:46 -08:00
} ;
2012-01-09 21:45:51 +00:00
static struct resource sa11x0dma_resources [ ] = {
2012-01-14 16:57:02 +00:00
DEFINE_RES_MEM ( DMA_PHYS , DMA_SIZE ) ,
2012-01-09 21:45:51 +00:00
DEFINE_RES_IRQ ( IRQ_DMA0 ) ,
DEFINE_RES_IRQ ( IRQ_DMA1 ) ,
DEFINE_RES_IRQ ( IRQ_DMA2 ) ,
DEFINE_RES_IRQ ( IRQ_DMA3 ) ,
DEFINE_RES_IRQ ( IRQ_DMA4 ) ,
DEFINE_RES_IRQ ( IRQ_DMA5 ) ,
} ;
static u64 sa11x0dma_dma_mask = DMA_BIT_MASK ( 32 ) ;
static struct platform_device sa11x0dma_device = {
. name = " sa11x0-dma " ,
. id = - 1 ,
. dev = {
. dma_mask = & sa11x0dma_dma_mask ,
. coherent_dma_mask = 0xffffffff ,
} ,
. num_resources = ARRAY_SIZE ( sa11x0dma_resources ) ,
. resource = sa11x0dma_resources ,
} ;
2005-04-16 15:20:36 -07:00
static struct platform_device * sa11x0_devices [ ] __initdata = {
& sa11x0udc_device ,
& sa11x0uart1_device ,
& sa11x0uart3_device ,
& sa11x0ssp_device ,
2006-03-27 01:16:46 -08:00
& sa11x0rtc_device ,
2012-01-09 21:45:51 +00:00
& sa11x0dma_device ,
2005-04-16 15:20:36 -07:00
} ;
static int __init sa1100_init ( void )
{
pm_power_off = sa1100_power_off ;
2016-08-31 08:49:47 +01:00
regulator_has_full_constraints ( ) ;
2005-04-16 15:20:36 -07:00
return platform_add_devices ( sa11x0_devices , ARRAY_SIZE ( sa11x0_devices ) ) ;
}
arch_initcall ( sa1100_init ) ;
2012-04-26 21:22:45 +08:00
void __init sa11x0_init_late ( void )
{
sa11x0_pm_init ( ) ;
}
2005-04-16 15:20:36 -07:00
2016-08-31 08:49:47 +01:00
int __init sa11x0_register_fixed_regulator ( int n ,
struct fixed_voltage_config * cfg ,
2018-09-06 14:24:36 +02:00
struct regulator_consumer_supply * supplies , unsigned num_supplies ,
bool uses_gpio )
2016-08-31 08:49:47 +01:00
{
struct regulator_init_data * id ;
cfg - > init_data = id = kzalloc ( sizeof ( * cfg - > init_data ) , GFP_KERNEL ) ;
if ( ! cfg - > init_data )
return - ENOMEM ;
2018-09-06 14:24:36 +02:00
if ( ! uses_gpio )
2016-08-31 08:49:47 +01:00
id - > constraints . always_on = 1 ;
id - > constraints . name = cfg - > supply_name ;
id - > constraints . min_uV = cfg - > microvolts ;
id - > constraints . max_uV = cfg - > microvolts ;
id - > constraints . valid_modes_mask = REGULATOR_MODE_NORMAL ;
id - > constraints . valid_ops_mask = REGULATOR_CHANGE_STATUS ;
id - > consumer_supplies = supplies ;
id - > num_consumer_supplies = num_supplies ;
platform_device_register_resndata ( NULL , " reg-fixed-voltage " , n ,
NULL , 0 , cfg , sizeof ( * cfg ) ) ;
return 0 ;
}
2005-04-16 15:20:36 -07:00
/*
* Common I / O mapping :
*
* Typically , static virtual address mappings are as follow :
*
* 0xf0000000 - 0xf3ffffff : miscellaneous stuff ( CPLDs , etc . )
* 0xf4000000 - 0xf4ffffff : SA - 1111
* 0xf5000000 - 0xf5ffffff : reserved ( used by cache flushing area )
* 0xf6000000 - 0xfffeffff : reserved ( internal SA1100 IO defined above )
* 0xffff0000 - 0xffff0fff : SA1100 exception vectors
* 0xffff2000 - 0xffff2fff : Minicache copy_user_page area
*
* Below 0xe8000000 is reserved for vm allocation .
*
* The machine specific code must provide the extra mapping beside the
* default mapping provided here .
*/
static struct map_desc standard_io_desc [ ] __initdata = {
2008-09-29 17:09:10 +01:00
{ /* PCM */
2005-10-28 15:19:04 +01:00
. virtual = 0xf8000000 ,
. pfn = __phys_to_pfn ( 0x80000000 ) ,
. length = 0x00100000 ,
. type = MT_DEVICE
} , { /* SCM */
. virtual = 0xfa000000 ,
. pfn = __phys_to_pfn ( 0x90000000 ) ,
. length = 0x00100000 ,
. type = MT_DEVICE
} , { /* MER */
. virtual = 0xfc000000 ,
. pfn = __phys_to_pfn ( 0xa0000000 ) ,
. length = 0x00100000 ,
. type = MT_DEVICE
} , { /* LCD + DMA */
. virtual = 0xfe000000 ,
. pfn = __phys_to_pfn ( 0xb0000000 ) ,
. length = 0x00200000 ,
. type = MT_DEVICE
} ,
2005-04-16 15:20:36 -07:00
} ;
void __init sa1100_map_io ( void )
{
iotable_init ( standard_io_desc , ARRAY_SIZE ( standard_io_desc ) ) ;
}
2014-12-21 16:08:13 +01:00
void __init sa1100_timer_init ( void )
{
2016-09-19 21:12:13 +02:00
pxa_timer_nodt_init ( IRQ_OST0 , io_p2v ( 0x90000000 ) ) ;
2014-12-21 16:08:13 +01:00
}
2015-05-19 16:16:14 +01:00
static struct resource irq_resource =
DEFINE_RES_MEM_NAMED ( 0x90050000 , SZ_64K , " irqs " ) ;
void __init sa1100_init_irq ( void )
{
request_resource ( & iomem_resource , & irq_resource ) ;
sa11x0_init_irq_nodt ( IRQ_GPIO0_SC , irq_resource . start ) ;
sa1100_init_gpio ( ) ;
2016-08-19 12:47:54 +01:00
sa11xx_clk_init ( ) ;
2015-05-19 16:16:14 +01:00
}
2005-04-16 15:20:36 -07:00
/*
* Disable the memory bus request / grant signals on the SA1110 to
* ensure that we don ' t receive spurious memory requests . We set
* the MBGNT signal false to ensure the SA1111 doesn ' t own the
* SDRAM bus .
*/
2012-02-03 18:16:45 +00:00
void sa1110_mb_disable ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
local_irq_save ( flags ) ;
PGSR & = ~ GPIO_MBGNT ;
GPCR = GPIO_MBGNT ;
GPDR = ( GPDR & ~ GPIO_MBREQ ) | GPIO_MBGNT ;
GAFR & = ~ ( GPIO_MBGNT | GPIO_MBREQ ) ;
local_irq_restore ( flags ) ;
}
/*
* If the system is going to use the SA - 1111 DMA engines , set up
* the memory bus request / grant pins .
*/
2012-02-03 18:16:45 +00:00
void sa1110_mb_enable ( void )
2005-04-16 15:20:36 -07:00
{
unsigned long flags ;
local_irq_save ( flags ) ;
PGSR & = ~ GPIO_MBGNT ;
GPCR = GPIO_MBGNT ;
GPDR = ( GPDR & ~ GPIO_MBREQ ) | GPIO_MBGNT ;
GAFR | = ( GPIO_MBGNT | GPIO_MBREQ ) ;
TUCR | = TUCR_MR ;
local_irq_restore ( flags ) ;
}
2015-05-18 15:58:57 +01:00
int sa11x0_gpio_set_wake ( unsigned int gpio , unsigned int on )
{
if ( on )
PWER | = BIT ( gpio ) ;
else
PWER & = ~ BIT ( gpio ) ;
return 0 ;
}
int sa11x0_sc_set_wake ( unsigned int irq , unsigned int on )
{
if ( BIT ( irq ) ! = IC_RTCAlrm )
return - EINVAL ;
if ( on )
PWER | = PWER_RTC ;
else
PWER & = ~ PWER_RTC ;
return 0 ;
}