2022-04-06 23:15:23 +03:00
// SPDX-License-Identifier: GPL-2.0
2022-05-23 20:55:20 +03:00
# include <linux/reboot.h>
2022-04-06 23:15:23 +03:00
# include <linux/serial_core.h>
# include <clocksource/timer-goldfish.h>
# include <asm/bootinfo.h>
# include <asm/bootinfo-virt.h>
# include <asm/byteorder.h>
# include <asm/machdep.h>
# include <asm/virt.h>
# include <asm/config.h>
struct virt_booter_data virt_bi_data ;
# define VIRT_CTRL_REG_FEATURES 0x00
# define VIRT_CTRL_REG_CMD 0x04
static struct resource ctrlres ;
enum {
CMD_NOOP ,
CMD_RESET ,
CMD_HALT ,
CMD_PANIC ,
} ;
static void virt_get_model ( char * str )
{
/* str is 80 characters long */
sprintf ( str , " QEMU Virtual M68K Machine (%u.%u.%u) " ,
( u8 ) ( virt_bi_data . qemu_version > > 24 ) ,
( u8 ) ( virt_bi_data . qemu_version > > 16 ) ,
( u8 ) ( virt_bi_data . qemu_version > > 8 ) ) ;
}
static void virt_halt ( void )
{
void __iomem * base = ( void __iomem * ) virt_bi_data . ctrl . mmio ;
iowrite32be ( CMD_HALT , base + VIRT_CTRL_REG_CMD ) ;
local_irq_disable ( ) ;
while ( 1 )
;
}
static void virt_reset ( void )
{
void __iomem * base = ( void __iomem * ) virt_bi_data . ctrl . mmio ;
iowrite32be ( CMD_RESET , base + VIRT_CTRL_REG_CMD ) ;
local_irq_disable ( ) ;
while ( 1 )
;
}
/*
* Parse a virtual - m68k - specific record in the bootinfo
*/
int __init virt_parse_bootinfo ( const struct bi_record * record )
{
int unknown = 0 ;
const void * data = record - > data ;
switch ( be16_to_cpu ( record - > tag ) ) {
case BI_VIRT_QEMU_VERSION :
virt_bi_data . qemu_version = be32_to_cpup ( data ) ;
break ;
case BI_VIRT_GF_PIC_BASE :
virt_bi_data . pic . mmio = be32_to_cpup ( data ) ;
data + = 4 ;
virt_bi_data . pic . irq = be32_to_cpup ( data ) ;
break ;
case BI_VIRT_GF_RTC_BASE :
virt_bi_data . rtc . mmio = be32_to_cpup ( data ) ;
data + = 4 ;
virt_bi_data . rtc . irq = be32_to_cpup ( data ) ;
break ;
case BI_VIRT_GF_TTY_BASE :
virt_bi_data . tty . mmio = be32_to_cpup ( data ) ;
data + = 4 ;
virt_bi_data . tty . irq = be32_to_cpup ( data ) ;
break ;
case BI_VIRT_CTRL_BASE :
virt_bi_data . ctrl . mmio = be32_to_cpup ( data ) ;
data + = 4 ;
virt_bi_data . ctrl . irq = be32_to_cpup ( data ) ;
break ;
case BI_VIRT_VIRTIO_BASE :
virt_bi_data . virtio . mmio = be32_to_cpup ( data ) ;
data + = 4 ;
virt_bi_data . virtio . irq = be32_to_cpup ( data ) ;
break ;
default :
unknown = 1 ;
break ;
}
return unknown ;
}
static void __init virt_sched_init ( void )
{
goldfish_timer_init ( virt_bi_data . rtc . irq ,
( void __iomem * ) virt_bi_data . rtc . mmio ) ;
}
void __init config_virt ( void )
{
char earlycon [ 24 ] ;
snprintf ( earlycon , sizeof ( earlycon ) , " early_gf_tty,0x%08x " ,
virt_bi_data . tty . mmio ) ;
setup_earlycon ( earlycon ) ;
ctrlres = ( struct resource )
DEFINE_RES_MEM_NAMED ( virt_bi_data . ctrl . mmio , 0x100 ,
" virtctrl " ) ;
if ( request_resource ( & iomem_resource , & ctrlres ) ) {
pr_err ( " Cannot allocate virt controller resource \n " ) ;
return ;
}
mach_init_IRQ = virt_init_IRQ ;
mach_sched_init = virt_sched_init ;
mach_get_model = virt_get_model ;
mach_reset = virt_reset ;
mach_halt = virt_halt ;
2022-05-23 20:55:20 +03:00
register_platform_power_off ( virt_halt ) ;
2022-04-06 23:15:23 +03:00
}