From 6aa773b7a68839fa7f997eab5fb09521dce17853 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Fri, 25 Dec 2020 22:00:39 -0700 Subject: [PATCH] WIP FPC-III support --- arch/riscv/configs/fpc_defconfig | 70 ++++++++++++++++++ arch/riscv/include/asm/set_memory.h | 17 +++-- arch/riscv/kernel/setup.c | 8 +- drivers/input/keyboard/Kconfig | 9 +++ drivers/input/keyboard/Makefile | 1 + drivers/input/keyboard/fpckbd.c | 143 ++++++++++++++++++++++++++++++++++++ drivers/video/console/Kconfig | 9 +++ drivers/video/console/Makefile | 1 + drivers/video/console/fpccon.c | 134 +++++++++++++++++++++++++++++++++ include/linux/console.h | 1 + 10 files changed, 384 insertions(+), 9 deletions(-) create mode 100644 arch/riscv/configs/fpc_defconfig create mode 100644 drivers/input/keyboard/fpckbd.c create mode 100644 drivers/video/console/fpccon.c diff --git a/arch/riscv/configs/fpc_defconfig b/arch/riscv/configs/fpc_defconfig new file mode 100644 index 000000000000..93ea860d0389 --- /dev/null +++ b/arch/riscv/configs/fpc_defconfig @@ -0,0 +1,70 @@ +CONFIG_DEFAULT_HOSTNAME="fpc" +# CONFIG_UTS_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_ARCH_RV32I=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +# CONFIG_RISCV_ISA_C is not set +# CONFIG_FPU is not set +# CONFIG_EFI is not set +# CONFIG_STRICT_KERNEL_RWX is not set +CONFIG_NET=y +CONFIG_INET=y +# CONFIG_WIRELESS is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_SPI_NOR=y +CONFIG_SPI_FLASH_LITEX=y +CONFIG_NETDEVICES=y +CONFIG_LITEX_LITEETH=y +# CONFIG_WLAN is not set +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_FPC=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_SERIAL_LITEUART=y +CONFIG_SERIAL_LITEUART_CONSOLE=y +CONFIG_HVC_RISCV_SBI=y +# CONFIG_HW_RANDOM is not set +CONFIG_SPI=y +CONFIG_SPI_LITESPI=y +CONFIG_SPI_SPIDEV=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_LITEX=y +# CONFIG_HWMON is not set +# CONFIG_VGA_CONSOLE is not set +CONFIG_FPC_CONSOLE=y +# CONFIG_HID is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_MMC=y +CONFIG_MMC_SPI=y +CONFIG_MMC_LITEX=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +# CONFIG_SURFACE_PLATFORMS is not set +CONFIG_COMMON_CLK_LITEX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_LITEX_SOC_CONTROLLER=y +CONFIG_SIFIVE_PLIC=y +CONFIG_LITEX_VEXRISCV_INTC=y +CONFIG_FPGA=y +CONFIG_FPGA_MGR_LITEX=y +CONFIG_EXT4_FS=y +CONFIG_OVERLAY_FS=y +CONFIG_OVERLAY_FS_INDEX=y +CONFIG_OVERLAY_FS_METACOPY=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_NFS_FS=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +# CONFIG_CRYPTO_HW is not set +CONFIG_PRINTK_TIME=y diff --git a/arch/riscv/include/asm/set_memory.h b/arch/riscv/include/asm/set_memory.h index 211eb8244a45..13512c6c4657 100644 --- a/arch/riscv/include/asm/set_memory.h +++ b/arch/riscv/include/asm/set_memory.h @@ -32,14 +32,15 @@ bool kernel_page_present(struct page *page); #endif /* __ASSEMBLY__ */ -#ifdef CONFIG_ARCH_HAS_STRICT_KERNEL_RWX -#ifdef CONFIG_64BIT -#define SECTION_ALIGN (1 << 21) -#else -#define SECTION_ALIGN (1 << 22) -#endif -#else /* !CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */ +//#ifdef CONFIG_ARCH_HAS_STRICT_KERNEL_RWX +//#ifdef CONFIG_64BIT +//#define SECTION_ALIGN (1 << 21) +//#else +//#define SECTION_ALIGN (1 << 22) +//#endif +//#else /* !CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */ +//#define SECTION_ALIGN L1_CACHE_BYTES +//#endif /* CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */ #define SECTION_ALIGN L1_CACHE_BYTES -#endif /* CONFIG_ARCH_HAS_STRICT_KERNEL_RWX */ #endif /* _ASM_RISCV_SET_MEMORY_H */ diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c index 1d85e9bf783c..af52b037bccd 100644 --- a/arch/riscv/kernel/setup.c +++ b/arch/riscv/kernel/setup.c @@ -264,6 +264,12 @@ void __init setup_arch(char **cmdline_p) kasan_init(); #endif +#if IS_ENABLED(CONFIG_VT) +#if IS_ENABLED(CONFIG_FPC_CONSOLE) + conswitchp = &fpc_con; +#endif +#endif + #ifdef CONFIG_SMP setup_smp(); #endif @@ -291,6 +297,6 @@ void free_initmem(void) unsigned long init_begin = (unsigned long)__init_begin; unsigned long init_end = (unsigned long)__init_end; - set_memory_rw_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT); +// set_memory_rw_nx(init_begin, (init_end - init_begin) >> PAGE_SHIFT); free_initmem_default(POISON_FREE_INITMEM); } diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 2b321c17054a..9b8c3186d6ab 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -791,4 +791,13 @@ config KEYBOARD_MTK_PMIC To compile this driver as a module, choose M here: the module will be called pmic-keys. +config KEYBOARD_FPC + tristate "FPC-III keyboard" + help + Say Y here to enable the FPC-III keyboard driver. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called fpckbd. endif diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 1d689fdd5c00..a4c650911a88 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_KEYBOARD_CROS_EC) += cros_ec_keyb.o obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o obj-$(CONFIG_KEYBOARD_DLINK_DIR685) += dlink-dir685-touchkeys.o obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o +obj-$(CONFIG_KEYBOARD_FPC) += fpckbd.o obj-$(CONFIG_KEYBOARD_GOLDFISH_EVENTS) += goldfish_events.o obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o obj-$(CONFIG_KEYBOARD_GPIO_POLLED) += gpio_keys_polled.o diff --git a/drivers/input/keyboard/fpckbd.c b/drivers/input/keyboard/fpckbd.c new file mode 100644 index 000000000000..515b2ccdc6fe --- /dev/null +++ b/drivers/input/keyboard/fpckbd.c @@ -0,0 +1,143 @@ +/* + * fpckbd.c + * + * Copyright 2020, Gary Wong + * + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this file. If not, see . + */ + +#include +#include +#include +#include + +MODULE_AUTHOR( "Gary Wong " ); +MODULE_DESCRIPTION( "FPC-III keyboard driver" ); +MODULE_LICENSE( "GPL" ); + +#define FPCKBD_BASE 0xA0000000 + +static struct timer_list timer; +static struct input_dev *fpc_dev; +static unsigned char __iomem *report; +static unsigned char last_rep[ 8 ]; + +static const unsigned char code_trans[ 0x66 ] = { + 0, 0, 0, 0, KEY_A, KEY_B, KEY_C, KEY_D, + KEY_E, KEY_F, KEY_G, KEY_H, KEY_I, KEY_J, KEY_K, KEY_L, + KEY_M, KEY_N, KEY_O, KEY_P, KEY_Q, KEY_R, KEY_S, KEY_T, + KEY_U, KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z, KEY_1, KEY_2, + KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, KEY_0, + KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, + KEY_SPACE, KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, + KEY_RIGHTBRACE, KEY_BACKSLASH, 0, KEY_SEMICOLON, + KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA, KEY_DOT, + KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2, + KEY_F3, KEY_F4, KEY_F5, KEY_F6, + KEY_F7, KEY_F8, KEY_F9, KEY_F10, + KEY_F11, KEY_F12, KEY_SYSRQ, KEY_SCROLLLOCK, + KEY_PAUSE, KEY_INSERT, KEY_HOME, KEY_PAGEUP, + KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT, + KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK, + KEY_KPSLASH, KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, + KEY_KPENTER, KEY_KP1, KEY_KP2, KEY_KP3, + KEY_KP4, KEY_KP5, KEY_KP6, KEY_KP7, + KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT, + 0, KEY_COMPOSE +}; + +static const unsigned char mod_trans[ 8 ] = { + KEY_LEFTCTRL, KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, + KEY_RIGHTCTRL, KEY_RIGHTSHIFT, KEY_RIGHTALT, KEY_RIGHTMETA +}; + +static void fpckbd_timer( struct timer_list *t ) { + + int i, j; + unsigned char new_rep[ 8 ]; + + memcpy_fromio( new_rep, report, 8 ); + + for( i = 0; i < 8; i++ ) + if( ( new_rep[ 0 ] ^ last_rep[ 0 ] ) & ( 1 << i ) ) + input_report_key( fpc_dev, mod_trans[ i ], + new_rep[ 0 ] & ( 1 << i ) ); + + for( i = 2; i < 8; i++ ) + if( last_rep[ i ] ) { + for( j = 2; j < 8; j++ ) + if( new_rep[ j ] == last_rep[ i ] ) + goto ignore_old; + + if( last_rep[ i ] < 0x66 && code_trans[ last_rep[ i ] ] ) + input_report_key( fpc_dev, code_trans[ last_rep[ i ] ], 0 ); + ignore_old: + ; + } + + for( i = 2; i < 8; i++ ) + if( new_rep[ i ] ) { + for( j = 2; j < 8; j++ ) + if( last_rep[ j ] == new_rep[ i ] ) + goto ignore_new; + + if( new_rep[ i ] < 0x66 && code_trans[ new_rep[ i ] ] ) + input_report_key( fpc_dev, code_trans[ new_rep[ i ] ], 1 ); + ignore_new: + ; + } + + input_sync( fpc_dev ); + + memcpy( last_rep, new_rep, 8 ); + + mod_timer( &timer, jiffies + HZ / 100 + 1 ); +} + +static int __init fpckbd_init( void ) { + + int i, err; + + if( !( fpc_dev = input_allocate_device() ) ) + return -ENOMEM; + + // FIXME use platform device to get address + if( !( report = ioremap( FPCKBD_BASE, 0x10000 ) ) ) + return -ENOMEM; + + fpc_dev->evbit[ 0 ] = BIT_MASK( EV_KEY ) | BIT_MASK( EV_REP ); + + for( i = 1; i < 0x80; i++ ) + __set_bit( i, fpc_dev->keybit ); + + if( ( err = input_register_device( fpc_dev ) ) ) + return err; + + timer_setup( &timer, fpckbd_timer, 0 ); + mod_timer( &timer, jiffies + HZ / 100 + 1 ); + + return 0; +} + +static void __exit fpckbd_exit( void ) { + + del_timer_sync( &timer ); + + input_unregister_device( fpc_dev ); + + // FIXME iounmap +} + +module_init( fpckbd_init ); +module_exit( fpckbd_exit ); diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index ee33b8ec62bb..75a58250d0a0 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -126,5 +126,14 @@ config STI_CONSOLE machines. Say Y here to build support for it into your kernel. The alternative is to use your primary serial port as a console. +config FPC_CONSOLE + bool "FPC-III text console" + default n + help + Say Y here to enable text console support for the HDMI output + of the FPC-III. + + If unsure, say N. + endmenu diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index db07b784bd2c..e43065260872 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -8,5 +8,6 @@ obj-$(CONFIG_SGI_NEWPORT_CONSOLE) += newport_con.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o +obj-$(CONFIG_FPC_CONSOLE) += fpccon.o obj-$(CONFIG_FB_STI) += sticore.o diff --git a/drivers/video/console/fpccon.c b/drivers/video/console/fpccon.c new file mode 100644 index 000000000000..9c04f73f498e --- /dev/null +++ b/drivers/video/console/fpccon.c @@ -0,0 +1,134 @@ +/* + * fpccon.c + * + * Copyright 2020, Gary Wong + * + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this file. If not, see . + */ + +#include +#include +#include +#include +#include + +static u16 *fpc_videochar_base; + +#define FPCCON_ROWS 28 +#define FPCCON_COLS 100 +#define FPCCON_MEMBASE 0x30000000 +#define FPCCON_MEMSIZE 0x4000 + +#define VIDEOCHAR( y, x ) ( fpc_videochar_base[ ( (y) << 7 ) | (x) ] ) + +static const char *fpccon_startup( void ) { + + fpc_videochar_base = memremap( FPCCON_MEMBASE, FPCCON_MEMSIZE, + MEMREMAP_WB ); + + return "FPC"; +} + +static void fpccon_init( struct vc_data *c, int init ) { + + c->vc_cols = FPCCON_COLS; + c->vc_rows = FPCCON_ROWS; + c->vc_can_do_color = 1; + c->vc_complement_mask = 0x7700; + c->vc_hi_font_mask = 0; +} + +static void fpccon_deinit( struct vc_data *c ) { +} + +static void fpccon_clear( struct vc_data *c, int y, int x, + int height, int width ) { + int row, col; + + for( row = y; row < y + height; row++ ) + for( col = x; col < x + width; col++ ) + VIDEOCHAR( row, col ) = c->vc_video_erase_char; +} + +static void fpccon_putc( struct vc_data *c, int ch, int y, int x ) { + + VIDEOCHAR( y, x ) = ( c->vc_attr << 8 ) | ch; +} + +static void fpccon_putcs( struct vc_data *c, const unsigned short *s, + int count, int y, int x ) { + + u16 *p = &VIDEOCHAR( y, x ); + + while( count ) { + *p++ = ( c->vc_attr << 8 ) | ( *s++ & 0xFF ); + count--; + } +} + +static void fpccon_cursor( struct vc_data *c, int mode ) { +} + +static bool fpccon_scroll( struct vc_data *c, unsigned int top, + unsigned int bottom, enum con_scroll dir, + unsigned int lines ) { + int y; + + if( dir == SM_UP ) { + for( y = top; y < bottom - lines; y++ ) + memcpy( &VIDEOCHAR( y, 0 ), &VIDEOCHAR( y + lines, 0 ), + c->vc_cols << 1 ); + for( ; y < bottom; y++ ) + memset32( (uint32_t *) &VIDEOCHAR( y, 0 ), + ( c->vc_video_erase_char << 16 ) | + c->vc_video_erase_char, c->vc_cols >> 1 ); + } else { + for( y = bottom - 1; y >= top + lines; y-- ) + memcpy( &VIDEOCHAR( y, 0 ), &VIDEOCHAR( y - lines, 0 ), + c->vc_cols << 1 ); + for( ; y >= top; y-- ) + memset32( (uint32_t *) &VIDEOCHAR( y, 0 ), + ( c->vc_video_erase_char << 16 ) | + c->vc_video_erase_char, c->vc_cols >> 1 ); + } + + return 0; +} + +static int fpccon_switch( struct vc_data *c ) { + + return 1; /* need redraw */ +} + +static int fpccon_blank( struct vc_data *c, int blank, int mode_switch ) { + + return 0; /* should probably add hardware support for blanking */ +} + +const struct consw fpc_con = { + .owner = THIS_MODULE, + .con_startup = fpccon_startup, + .con_init = fpccon_init, + .con_deinit = fpccon_deinit, + .con_clear = fpccon_clear, + .con_putc = fpccon_putc, + .con_putcs = fpccon_putcs, + .con_cursor = fpccon_cursor, + .con_scroll = fpccon_scroll, + .con_switch = fpccon_switch, + .con_blank = fpccon_blank +}; +EXPORT_SYMBOL( fpc_con ); + +MODULE_LICENSE( "GPL" ); diff --git a/include/linux/console.h b/include/linux/console.h index 20874db50bc8..87850575dcca 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -97,6 +97,7 @@ extern const struct consw *conswitchp; extern const struct consw dummy_con; /* dummy console buffer */ extern const struct consw vga_con; /* VGA text console */ extern const struct consw newport_con; /* SGI Newport console */ +extern const struct consw fpc_con; /* FPC-III text console */ int con_is_bound(const struct consw *csw); int do_unregister_con_driver(const struct consw *csw); -- 2.11.4.GIT