aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2015-02-26 22:28:00 -0500
committerMax Filippov <jcmvbkbc@gmail.com>2015-02-26 23:55:29 -0500
commit4949009eb8d40a441dcddcd96e101e77d31cf1b2 (patch)
tree8ce5900ef60e24168c654174cefaf47b02837fbe /arch/xtensa
parentbfa76d49576599a4b9f9b7a71f23d73d6dcff735 (diff)
xtensa: xtfpga: fix hardware lockup caused by LCD driver
LCD driver is always built for the XTFPGA platform, but its base address is not configurable, and is wrong for ML605/KC705. Its initialization locks up KC705 board hardware. Make the whole driver optional, and its base address and bus width configurable. Implement 4-bit bus access method. Cc: stable@vger.kernel.org Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/Kconfig30
-rw-r--r--arch/xtensa/platforms/xtfpga/Makefile3
-rw-r--r--arch/xtensa/platforms/xtfpga/include/platform/hardware.h3
-rw-r--r--arch/xtensa/platforms/xtfpga/include/platform/lcd.h15
-rw-r--r--arch/xtensa/platforms/xtfpga/lcd.c55
5 files changed, 81 insertions, 25 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index e31d4949124a..87be10e8b57a 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -428,6 +428,36 @@ config DEFAULT_MEM_SIZE
428 428
429 If unsure, leave the default value here. 429 If unsure, leave the default value here.
430 430
431config XTFPGA_LCD
432 bool "Enable XTFPGA LCD driver"
433 depends on XTENSA_PLATFORM_XTFPGA
434 default n
435 help
436 There's a 2x16 LCD on most of XTFPGA boards, kernel may output
437 progress messages there during bootup/shutdown. It may be useful
438 during board bringup.
439
440 If unsure, say N.
441
442config XTFPGA_LCD_BASE_ADDR
443 hex "XTFPGA LCD base address"
444 depends on XTFPGA_LCD
445 default "0x0d0c0000"
446 help
447 Base address of the LCD controller inside KIO region.
448 Different boards from XTFPGA family have LCD controller at different
449 addresses. Please consult prototyping user guide for your board for
450 the correct address. Wrong address here may lead to hardware lockup.
451
452config XTFPGA_LCD_8BIT_ACCESS
453 bool "Use 8-bit access to XTFPGA LCD"
454 depends on XTFPGA_LCD
455 default n
456 help
457 LCD may be connected with 4- or 8-bit interface, 8-bit access may
458 only be used with 8-bit interface. Please consult prototyping user
459 guide for your board for the correct interface width.
460
431endmenu 461endmenu
432 462
433menu "Executable file formats" 463menu "Executable file formats"
diff --git a/arch/xtensa/platforms/xtfpga/Makefile b/arch/xtensa/platforms/xtfpga/Makefile
index b9ae206340cd..7839d38b2337 100644
--- a/arch/xtensa/platforms/xtfpga/Makefile
+++ b/arch/xtensa/platforms/xtfpga/Makefile
@@ -6,4 +6,5 @@
6# 6#
7# Note 2! The CFLAGS definitions are in the main makefile... 7# Note 2! The CFLAGS definitions are in the main makefile...
8 8
9obj-y = setup.o lcd.o 9obj-y += setup.o
10obj-$(CONFIG_XTFPGA_LCD) += lcd.o
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
index 6edd20bb4565..4e0af2662a21 100644
--- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
+++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
@@ -40,9 +40,6 @@
40 40
41/* UART */ 41/* UART */
42#define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020) 42#define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020)
43/* LCD instruction and data addresses. */
44#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000))
45#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004))
46 43
47/* Misc. */ 44/* Misc. */
48#define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000) 45#define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000)
diff --git a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
index 0e435645af5a..4c8541ed1139 100644
--- a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
+++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
@@ -11,10 +11,25 @@
11#ifndef __XTENSA_XTAVNET_LCD_H 11#ifndef __XTENSA_XTAVNET_LCD_H
12#define __XTENSA_XTAVNET_LCD_H 12#define __XTENSA_XTAVNET_LCD_H
13 13
14#ifdef CONFIG_XTFPGA_LCD
14/* Display string STR at position POS on the LCD. */ 15/* Display string STR at position POS on the LCD. */
15void lcd_disp_at_pos(char *str, unsigned char pos); 16void lcd_disp_at_pos(char *str, unsigned char pos);
16 17
17/* Shift the contents of the LCD display left or right. */ 18/* Shift the contents of the LCD display left or right. */
18void lcd_shiftleft(void); 19void lcd_shiftleft(void);
19void lcd_shiftright(void); 20void lcd_shiftright(void);
21#else
22static inline void lcd_disp_at_pos(char *str, unsigned char pos)
23{
24}
25
26static inline void lcd_shiftleft(void)
27{
28}
29
30static inline void lcd_shiftright(void)
31{
32}
33#endif
34
20#endif 35#endif
diff --git a/arch/xtensa/platforms/xtfpga/lcd.c b/arch/xtensa/platforms/xtfpga/lcd.c
index 2872301598df..4dc0c1b43f4b 100644
--- a/arch/xtensa/platforms/xtfpga/lcd.c
+++ b/arch/xtensa/platforms/xtfpga/lcd.c
@@ -1,50 +1,63 @@
1/* 1/*
2 * Driver for the LCD display on the Tensilica LX60 Board. 2 * Driver for the LCD display on the Tensilica XTFPGA board family.
3 * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
3 * 4 *
4 * This file is subject to the terms and conditions of the GNU General Public 5 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive 6 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 7 * for more details.
7 * 8 *
8 * Copyright (C) 2001, 2006 Tensilica Inc. 9 * Copyright (C) 2001, 2006 Tensilica Inc.
10 * Copyright (C) 2015 Cadence Design Systems Inc.
9 */ 11 */
10 12
11/* 13#include <linux/delay.h>
12 *
13 * FIXME: this code is from the examples from the LX60 user guide.
14 *
15 * The lcd_pause function does busy waiting, which is probably not
16 * great. Maybe the code could be changed to use kernel timers, or
17 * change the hardware to not need to wait.
18 */
19
20#include <linux/init.h> 14#include <linux/init.h>
21#include <linux/io.h> 15#include <linux/io.h>
22 16
23#include <platform/hardware.h> 17#include <platform/hardware.h>
24#include <platform/lcd.h> 18#include <platform/lcd.h>
25#include <linux/delay.h>
26 19
27#define LCD_PAUSE_ITERATIONS 4000 20/* LCD instruction and data addresses. */
21#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
22#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4)
23
28#define LCD_CLEAR 0x1 24#define LCD_CLEAR 0x1
29#define LCD_DISPLAY_ON 0xc 25#define LCD_DISPLAY_ON 0xc
30 26
31/* 8bit and 2 lines display */ 27/* 8bit and 2 lines display */
32#define LCD_DISPLAY_MODE8BIT 0x38 28#define LCD_DISPLAY_MODE8BIT 0x38
29#define LCD_DISPLAY_MODE4BIT 0x28
33#define LCD_DISPLAY_POS 0x80 30#define LCD_DISPLAY_POS 0x80
34#define LCD_SHIFT_LEFT 0x18 31#define LCD_SHIFT_LEFT 0x18
35#define LCD_SHIFT_RIGHT 0x1c 32#define LCD_SHIFT_RIGHT 0x1c
36 33
34static void lcd_put_byte(u8 *addr, u8 data)
35{
36#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
37 ACCESS_ONCE(*addr) = data;
38#else
39 ACCESS_ONCE(*addr) = data & 0xf0;
40 ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
41#endif
42}
43
37static int __init lcd_init(void) 44static int __init lcd_init(void)
38{ 45{
39 *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; 46 ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
40 mdelay(5); 47 mdelay(5);
41 *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; 48 ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
42 udelay(200); 49 udelay(200);
43 *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT; 50 ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
51 udelay(50);
52#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
53 ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
54 udelay(50);
55 lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
44 udelay(50); 56 udelay(50);
45 *LCD_INSTR_ADDR = LCD_DISPLAY_ON; 57#endif
58 lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
46 udelay(50); 59 udelay(50);
47 *LCD_INSTR_ADDR = LCD_CLEAR; 60 lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
48 mdelay(10); 61 mdelay(10);
49 lcd_disp_at_pos("XTENSA LINUX", 0); 62 lcd_disp_at_pos("XTENSA LINUX", 0);
50 return 0; 63 return 0;
@@ -52,10 +65,10 @@ static int __init lcd_init(void)
52 65
53void lcd_disp_at_pos(char *str, unsigned char pos) 66void lcd_disp_at_pos(char *str, unsigned char pos)
54{ 67{
55 *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos; 68 lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
56 udelay(100); 69 udelay(100);
57 while (*str != 0) { 70 while (*str != 0) {
58 *LCD_DATA_ADDR = *str; 71 lcd_put_byte(LCD_DATA_ADDR, *str);
59 udelay(200); 72 udelay(200);
60 str++; 73 str++;
61 } 74 }
@@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned char pos)
63 76
64void lcd_shiftleft(void) 77void lcd_shiftleft(void)
65{ 78{
66 *LCD_INSTR_ADDR = LCD_SHIFT_LEFT; 79 lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
67 udelay(50); 80 udelay(50);
68} 81}
69 82
70void lcd_shiftright(void) 83void lcd_shiftright(void)
71{ 84{
72 *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT; 85 lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
73 udelay(50); 86 udelay(50);
74} 87}
75 88