lkml.org 
[lkml]   [2015]   [May]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.14 66/92] xtensa: xtfpga: fix hardware lockup caused by LCD driver
    Date
    3.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Max Filippov <jcmvbkbc@gmail.com>

    commit 4949009eb8d40a441dcddcd96e101e77d31cf1b2 upstream.

    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.

    Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/xtensa/Kconfig | 30 ++++++++
    arch/xtensa/platforms/xtfpga/Makefile | 3
    arch/xtensa/platforms/xtfpga/include/platform/hardware.h | 3
    arch/xtensa/platforms/xtfpga/include/platform/lcd.h | 15 ++++
    arch/xtensa/platforms/xtfpga/lcd.c | 55 +++++++++------
    5 files changed, 81 insertions(+), 25 deletions(-)

    --- a/arch/xtensa/Kconfig
    +++ b/arch/xtensa/Kconfig
    @@ -336,6 +336,36 @@ menu "Executable file formats"

    source "fs/Kconfig.binfmt"

    +config XTFPGA_LCD
    + bool "Enable XTFPGA LCD driver"
    + depends on XTENSA_PLATFORM_XTFPGA
    + default n
    + help
    + There's a 2x16 LCD on most of XTFPGA boards, kernel may output
    + progress messages there during bootup/shutdown. It may be useful
    + during board bringup.
    +
    + If unsure, say N.
    +
    +config XTFPGA_LCD_BASE_ADDR
    + hex "XTFPGA LCD base address"
    + depends on XTFPGA_LCD
    + default "0x0d0c0000"
    + help
    + Base address of the LCD controller inside KIO region.
    + Different boards from XTFPGA family have LCD controller at different
    + addresses. Please consult prototyping user guide for your board for
    + the correct address. Wrong address here may lead to hardware lockup.
    +
    +config XTFPGA_LCD_8BIT_ACCESS
    + bool "Use 8-bit access to XTFPGA LCD"
    + depends on XTFPGA_LCD
    + default n
    + help
    + LCD may be connected with 4- or 8-bit interface, 8-bit access may
    + only be used with 8-bit interface. Please consult prototyping user
    + guide for your board for the correct interface width.
    +
    endmenu

    source "net/Kconfig"
    --- a/arch/xtensa/platforms/xtfpga/Makefile
    +++ b/arch/xtensa/platforms/xtfpga/Makefile
    @@ -6,4 +6,5 @@
    #
    # Note 2! The CFLAGS definitions are in the main makefile...

    -obj-y = setup.o lcd.o
    +obj-y += setup.o
    +obj-$(CONFIG_XTFPGA_LCD) += lcd.o
    --- a/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
    +++ b/arch/xtensa/platforms/xtfpga/include/platform/hardware.h
    @@ -40,9 +40,6 @@

    /* UART */
    #define DUART16552_PADDR (XCHAL_KIO_PADDR + 0x0D050020)
    -/* LCD instruction and data addresses. */
    -#define LCD_INSTR_ADDR ((char *)IOADDR(0x0D040000))
    -#define LCD_DATA_ADDR ((char *)IOADDR(0x0D040004))

    /* Misc. */
    #define XTFPGA_FPGAREGS_VADDR IOADDR(0x0D020000)
    --- a/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
    +++ b/arch/xtensa/platforms/xtfpga/include/platform/lcd.h
    @@ -11,10 +11,25 @@
    #ifndef __XTENSA_XTAVNET_LCD_H
    #define __XTENSA_XTAVNET_LCD_H

    +#ifdef CONFIG_XTFPGA_LCD
    /* Display string STR at position POS on the LCD. */
    void lcd_disp_at_pos(char *str, unsigned char pos);

    /* Shift the contents of the LCD display left or right. */
    void lcd_shiftleft(void);
    void lcd_shiftright(void);
    +#else
    +static inline void lcd_disp_at_pos(char *str, unsigned char pos)
    +{
    +}
    +
    +static inline void lcd_shiftleft(void)
    +{
    +}
    +
    +static inline void lcd_shiftright(void)
    +{
    +}
    +#endif
    +
    #endif
    --- a/arch/xtensa/platforms/xtfpga/lcd.c
    +++ b/arch/xtensa/platforms/xtfpga/lcd.c
    @@ -1,50 +1,63 @@
    /*
    - * Driver for the LCD display on the Tensilica LX60 Board.
    + * Driver for the LCD display on the Tensilica XTFPGA board family.
    + * http://www.mytechcorp.com/cfdata/productFile/File1/MOC-16216B-B-A0A04.pdf
    *
    * This file is subject to the terms and conditions of the GNU General Public
    * License. See the file "COPYING" in the main directory of this archive
    * for more details.
    *
    * Copyright (C) 2001, 2006 Tensilica Inc.
    + * Copyright (C) 2015 Cadence Design Systems Inc.
    */

    -/*
    - *
    - * FIXME: this code is from the examples from the LX60 user guide.
    - *
    - * The lcd_pause function does busy waiting, which is probably not
    - * great. Maybe the code could be changed to use kernel timers, or
    - * change the hardware to not need to wait.
    - */
    -
    +#include <linux/delay.h>
    #include <linux/init.h>
    #include <linux/io.h>

    #include <platform/hardware.h>
    #include <platform/lcd.h>
    -#include <linux/delay.h>

    -#define LCD_PAUSE_ITERATIONS 4000
    +/* LCD instruction and data addresses. */
    +#define LCD_INSTR_ADDR ((char *)IOADDR(CONFIG_XTFPGA_LCD_BASE_ADDR))
    +#define LCD_DATA_ADDR (LCD_INSTR_ADDR + 4)
    +
    #define LCD_CLEAR 0x1
    #define LCD_DISPLAY_ON 0xc

    /* 8bit and 2 lines display */
    #define LCD_DISPLAY_MODE8BIT 0x38
    +#define LCD_DISPLAY_MODE4BIT 0x28
    #define LCD_DISPLAY_POS 0x80
    #define LCD_SHIFT_LEFT 0x18
    #define LCD_SHIFT_RIGHT 0x1c

    +static void lcd_put_byte(u8 *addr, u8 data)
    +{
    +#ifdef CONFIG_XTFPGA_LCD_8BIT_ACCESS
    + ACCESS_ONCE(*addr) = data;
    +#else
    + ACCESS_ONCE(*addr) = data & 0xf0;
    + ACCESS_ONCE(*addr) = (data << 4) & 0xf0;
    +#endif
    +}
    +
    static int __init lcd_init(void)
    {
    - *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
    + ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
    mdelay(5);
    - *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
    + ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
    udelay(200);
    - *LCD_INSTR_ADDR = LCD_DISPLAY_MODE8BIT;
    + ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE8BIT;
    + udelay(50);
    +#ifndef CONFIG_XTFPGA_LCD_8BIT_ACCESS
    + ACCESS_ONCE(*LCD_INSTR_ADDR) = LCD_DISPLAY_MODE4BIT;
    + udelay(50);
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_MODE4BIT);
    udelay(50);
    - *LCD_INSTR_ADDR = LCD_DISPLAY_ON;
    +#endif
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_ON);
    udelay(50);
    - *LCD_INSTR_ADDR = LCD_CLEAR;
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_CLEAR);
    mdelay(10);
    lcd_disp_at_pos("XTENSA LINUX", 0);
    return 0;
    @@ -52,10 +65,10 @@ static int __init lcd_init(void)

    void lcd_disp_at_pos(char *str, unsigned char pos)
    {
    - *LCD_INSTR_ADDR = LCD_DISPLAY_POS | pos;
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_DISPLAY_POS | pos);
    udelay(100);
    while (*str != 0) {
    - *LCD_DATA_ADDR = *str;
    + lcd_put_byte(LCD_DATA_ADDR, *str);
    udelay(200);
    str++;
    }
    @@ -63,13 +76,13 @@ void lcd_disp_at_pos(char *str, unsigned

    void lcd_shiftleft(void)
    {
    - *LCD_INSTR_ADDR = LCD_SHIFT_LEFT;
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_LEFT);
    udelay(50);
    }

    void lcd_shiftright(void)
    {
    - *LCD_INSTR_ADDR = LCD_SHIFT_RIGHT;
    + lcd_put_byte(LCD_INSTR_ADDR, LCD_SHIFT_RIGHT);
    udelay(50);
    }




    \
     
     \ /
      Last update: 2015-05-02 22:41    [W:4.157 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site