uboot/board/sandisk/sansa_fuze_plus/sfp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * SanDisk Sansa Fuze Plus board
   4 *
   5 * Copyright (C) 2013 Marek Vasut <marex@denx.de>
   6 *
   7 * Hardware investigation done by:
   8 *
   9 * Amaury Pouly <amaury.pouly@gmail.com>
  10 */
  11
  12#include <common.h>
  13#include <errno.h>
  14#include <asm/gpio.h>
  15#include <asm/io.h>
  16#include <asm/arch/iomux-mx23.h>
  17#include <asm/arch/imx-regs.h>
  18#include <asm/arch/clock.h>
  19#include <asm/arch/sys_proto.h>
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23/*
  24 * Functions
  25 */
  26int board_early_init_f(void)
  27{
  28        /* IO0 clock at 480MHz */
  29        mxs_set_ioclk(MXC_IOCLK0, 480000);
  30
  31        /* SSP0 clock at 96MHz */
  32        mxs_set_sspclk(MXC_SSPCLK0, 96000, 0);
  33
  34        return 0;
  35}
  36
  37int dram_init(void)
  38{
  39        return mxs_dram_init();
  40}
  41
  42#ifdef  CONFIG_CMD_MMC
  43static int xfi3_mmc_cd(int id)
  44{
  45        switch (id) {
  46        case 0:
  47                /* The SSP_DETECT is inverted on this board. */
  48                return gpio_get_value(MX23_PAD_SSP1_DETECT__GPIO_2_1);
  49        case 1:
  50                /* Internal eMMC always present */
  51                return 1;
  52        default:
  53                return 0;
  54        }
  55}
  56
  57int board_mmc_init(bd_t *bis)
  58{
  59        int ret;
  60
  61        /* MicroSD slot */
  62        gpio_direction_input(MX23_PAD_SSP1_DETECT__GPIO_2_1);
  63        gpio_direction_output(MX23_PAD_GPMI_D08__GPIO_0_8, 0);
  64        ret = mxsmmc_initialize(bis, 0, NULL, xfi3_mmc_cd);
  65        if (ret)
  66                return ret;
  67
  68        /* Internal eMMC */
  69        gpio_direction_output(MX23_PAD_PWM3__GPIO_1_29, 0);
  70        ret = mxsmmc_initialize(bis, 1, NULL, xfi3_mmc_cd);
  71
  72        return ret;
  73}
  74#endif
  75
  76#ifdef CONFIG_VIDEO_MXS
  77#define MUX_CONFIG_LCD  (MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL)
  78const iomux_cfg_t iomux_lcd_gpio[] = {
  79        MX23_PAD_LCD_D00__GPIO_1_0 | MUX_CONFIG_LCD,
  80        MX23_PAD_LCD_D01__GPIO_1_1 | MUX_CONFIG_LCD,
  81        MX23_PAD_LCD_D02__GPIO_1_2 | MUX_CONFIG_LCD,
  82        MX23_PAD_LCD_D03__GPIO_1_3 | MUX_CONFIG_LCD,
  83        MX23_PAD_LCD_D04__GPIO_1_4 | MUX_CONFIG_LCD,
  84        MX23_PAD_LCD_D05__GPIO_1_5 | MUX_CONFIG_LCD,
  85        MX23_PAD_LCD_D06__GPIO_1_6 | MUX_CONFIG_LCD,
  86        MX23_PAD_LCD_D07__GPIO_1_7 | MUX_CONFIG_LCD,
  87        MX23_PAD_LCD_D08__GPIO_1_8 | MUX_CONFIG_LCD,
  88        MX23_PAD_LCD_D09__GPIO_1_9 | MUX_CONFIG_LCD,
  89        MX23_PAD_LCD_D10__GPIO_1_10 | MUX_CONFIG_LCD,
  90        MX23_PAD_LCD_D11__GPIO_1_11 | MUX_CONFIG_LCD,
  91        MX23_PAD_LCD_D12__GPIO_1_12 | MUX_CONFIG_LCD,
  92        MX23_PAD_LCD_D13__GPIO_1_13 | MUX_CONFIG_LCD,
  93        MX23_PAD_LCD_D14__GPIO_1_14 | MUX_CONFIG_LCD,
  94        MX23_PAD_LCD_D15__GPIO_1_15 | MUX_CONFIG_LCD,
  95        MX23_PAD_LCD_D16__GPIO_1_16 | MUX_CONFIG_LCD,
  96        MX23_PAD_LCD_D17__GPIO_1_17 | MUX_CONFIG_LCD,
  97        MX23_PAD_LCD_RESET__GPIO_1_18 | MUX_CONFIG_LCD,
  98        MX23_PAD_LCD_RS__GPIO_1_19 | MUX_CONFIG_LCD,
  99        MX23_PAD_LCD_WR__GPIO_1_20 | MUX_CONFIG_LCD,
 100        MX23_PAD_LCD_CS__GPIO_1_21 | MUX_CONFIG_LCD,
 101        MX23_PAD_LCD_ENABLE__GPIO_1_23 | MUX_CONFIG_LCD,
 102};
 103
 104const iomux_cfg_t iomux_lcd_lcd[] = {
 105        MX23_PAD_LCD_D00__LCD_D00 | MUX_CONFIG_LCD,
 106        MX23_PAD_LCD_D01__LCD_D01 | MUX_CONFIG_LCD,
 107        MX23_PAD_LCD_D02__LCD_D02 | MUX_CONFIG_LCD,
 108        MX23_PAD_LCD_D03__LCD_D03 | MUX_CONFIG_LCD,
 109        MX23_PAD_LCD_D04__LCD_D04 | MUX_CONFIG_LCD,
 110        MX23_PAD_LCD_D05__LCD_D05 | MUX_CONFIG_LCD,
 111        MX23_PAD_LCD_D06__LCD_D06 | MUX_CONFIG_LCD,
 112        MX23_PAD_LCD_D07__LCD_D07 | MUX_CONFIG_LCD,
 113        MX23_PAD_LCD_D08__LCD_D08 | MUX_CONFIG_LCD,
 114        MX23_PAD_LCD_D09__LCD_D09 | MUX_CONFIG_LCD,
 115        MX23_PAD_LCD_D10__LCD_D10 | MUX_CONFIG_LCD,
 116        MX23_PAD_LCD_D11__LCD_D11 | MUX_CONFIG_LCD,
 117        MX23_PAD_LCD_D12__LCD_D12 | MUX_CONFIG_LCD,
 118        MX23_PAD_LCD_D13__LCD_D13 | MUX_CONFIG_LCD,
 119        MX23_PAD_LCD_D14__LCD_D14 | MUX_CONFIG_LCD,
 120        MX23_PAD_LCD_D15__LCD_D15 | MUX_CONFIG_LCD,
 121        MX23_PAD_LCD_D16__LCD_D16 | MUX_CONFIG_LCD,
 122        MX23_PAD_LCD_D17__LCD_D17 | MUX_CONFIG_LCD,
 123        MX23_PAD_LCD_RESET__LCD_RESET | MUX_CONFIG_LCD,
 124        MX23_PAD_LCD_RS__LCD_RS | MUX_CONFIG_LCD,
 125        MX23_PAD_LCD_WR__LCD_WR | MUX_CONFIG_LCD,
 126        MX23_PAD_LCD_CS__LCD_CS | MUX_CONFIG_LCD,
 127        MX23_PAD_LCD_ENABLE__LCD_ENABLE | MUX_CONFIG_LCD,
 128        MX23_PAD_LCD_VSYNC__LCD_VSYNC | MUX_CONFIG_LCD,
 129};
 130
 131static int mxsfb_read_register(uint32_t reg, uint32_t *value)
 132{
 133        iomux_cfg_t mux;
 134        uint32_t val = 0;
 135        int i;
 136
 137        /* Mangle the register offset. */
 138        reg = ((reg & 0xff) << 1) | (((reg >> 8) & 0xff) << 10);
 139
 140        /*
 141         * The SmartLCD interface on MX233 can only do WRITE operation
 142         * via the LCDIF controller. Implement the READ operation by
 143         * fiddling with bits.
 144         */
 145        mxs_iomux_setup_multiple_pads(iomux_lcd_gpio,
 146                ARRAY_SIZE(iomux_lcd_gpio));
 147
 148        gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 1);
 149        gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 1);
 150        gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 1);
 151        gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
 152
 153        for (i = 0; i < 18; i++) {
 154                mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
 155                gpio_direction_output(mux, 0);
 156        }
 157
 158        udelay(2);
 159        gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 0);
 160        udelay(1);
 161        gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 0);
 162        udelay(1);
 163        gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 0);
 164        udelay(1);
 165
 166        for (i = 0; i < 18; i++) {
 167                mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
 168                gpio_direction_output(mux, (reg >> i) & 1);
 169        }
 170        udelay(1);
 171
 172        gpio_direction_output(MX23_PAD_LCD_WR__GPIO_1_20, 1);
 173        udelay(3);
 174
 175        for (i = 0; i < 18; i++) {
 176                mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
 177                gpio_direction_input(mux);
 178        }
 179        udelay(2);
 180
 181        gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 0);
 182        udelay(1);
 183        gpio_direction_output(MX23_PAD_LCD_RS__GPIO_1_19, 1);
 184        udelay(1);
 185        gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
 186        udelay(3);
 187        gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 0);
 188        udelay(2);
 189
 190        for (i = 0; i < 18; i++) {
 191                mux = MXS_IOMUX_PAD_NAKED(1, i, PAD_MUXSEL_GPIO);
 192                val |= !!gpio_get_value(mux) << i;
 193        }
 194        udelay(1);
 195
 196        gpio_direction_output(MX23_PAD_LCD_ENABLE__GPIO_1_23, 1);
 197        udelay(1);
 198        gpio_direction_output(MX23_PAD_LCD_CS__GPIO_1_21, 1);
 199        udelay(1);
 200
 201        mxs_iomux_setup_multiple_pads(iomux_lcd_lcd,
 202                ARRAY_SIZE(iomux_lcd_lcd));
 203
 204        /* Demangle the register value. */
 205        *value = ((val >> 1) & 0xff) | ((val >> 2) & 0xff00);
 206
 207        writel(val, 0x2000);
 208        return 0;
 209}
 210
 211static int mxsfb_write_byte(uint32_t payload, const unsigned int data)
 212{
 213        struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 214        const unsigned int timeout = 0x10000;
 215
 216        /* What is going on here I do not know. FIXME */
 217        payload = ((payload & 0xff) << 1) | (((payload >> 8) & 0xff) << 10);
 218
 219        if (mxs_wait_mask_clr(&regs->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN,
 220                              timeout))
 221                return -ETIMEDOUT;
 222
 223        writel((1 << LCDIF_TRANSFER_COUNT_V_COUNT_OFFSET) |
 224                (1 << LCDIF_TRANSFER_COUNT_H_COUNT_OFFSET),
 225                &regs->hw_lcdif_transfer_count);
 226
 227        writel(LCDIF_CTRL_DATA_SELECT | LCDIF_CTRL_RUN,
 228                &regs->hw_lcdif_ctrl_clr);
 229
 230        if (data)
 231                writel(LCDIF_CTRL_DATA_SELECT, &regs->hw_lcdif_ctrl_set);
 232
 233        writel(LCDIF_CTRL_RUN, &regs->hw_lcdif_ctrl_set);
 234
 235        if (mxs_wait_mask_clr(&regs->hw_lcdif_lcdif_stat_reg, 1 << 29,
 236                              timeout))
 237                return -ETIMEDOUT;
 238
 239        writel(payload, &regs->hw_lcdif_data);
 240        return mxs_wait_mask_clr(&regs->hw_lcdif_ctrl_reg, LCDIF_CTRL_RUN,
 241                                 timeout);
 242}
 243
 244static void mxsfb_write_register(uint32_t reg, uint32_t data)
 245{
 246        mxsfb_write_byte(reg, 0);
 247        mxsfb_write_byte(data, 1);
 248}
 249
 250static const struct {
 251        uint8_t         reg;
 252        uint8_t         delay;
 253        uint16_t        val;
 254} lcd_regs[] = {
 255        { 0xe5, 0  , 0x78f0 },
 256        { 0xe3, 0  , 0x3008 },
 257        { 0xe7, 0  , 0x0012 },
 258        { 0xef, 0  , 0x1231 },
 259        { 0x00, 0  , 0x0001 },
 260        { 0x01, 0  , 0x0100 },
 261        { 0x02, 0  , 0x0700 },
 262        { 0x03, 0  , 0x1030 },
 263        { 0x04, 0  , 0x0000 },
 264        { 0x08, 0  , 0x0207 },
 265        { 0x09, 0  , 0x0000 },
 266        { 0x0a, 0  , 0x0000 },
 267        { 0x0c, 0  , 0x0000 },
 268        { 0x0d, 0  , 0x0000 },
 269        { 0x0f, 0  , 0x0000 },
 270        { 0x10, 0  , 0x0000 },
 271        { 0x11, 0  , 0x0007 },
 272        { 0x12, 0  , 0x0000 },
 273        { 0x13, 20 , 0x0000 },
 274        /* Wait 20 mS here. */
 275        { 0x10, 0  , 0x1290 },
 276        { 0x11, 50 , 0x0007 },
 277        /* Wait 50 mS here. */
 278        { 0x12, 50 , 0x0019 },
 279        /* Wait 50 mS here. */
 280        { 0x13, 0  , 0x1700 },
 281        { 0x29, 50 , 0x0014 },
 282        /* Wait 50 mS here. */
 283        { 0x20, 0  , 0x0000 },
 284        { 0x21, 0  , 0x0000 },
 285        { 0x30, 0  , 0x0504 },
 286        { 0x31, 0  , 0x0007 },
 287        { 0x32, 0  , 0x0006 },
 288        { 0x35, 0  , 0x0106 },
 289        { 0x36, 0  , 0x0202 },
 290        { 0x37, 0  , 0x0504 },
 291        { 0x38, 0  , 0x0500 },
 292        { 0x39, 0  , 0x0706 },
 293        { 0x3c, 0  , 0x0204 },
 294        { 0x3d, 0  , 0x0202 },
 295        { 0x50, 0  , 0x0000 },
 296        { 0x51, 0  , 0x00ef },
 297        { 0x52, 0  , 0x0000 },
 298        { 0x53, 0  , 0x013f },
 299        { 0x60, 0  , 0xa700 },
 300        { 0x61, 0  , 0x0001 },
 301        { 0x6a, 0  , 0x0000 },
 302        { 0x2b, 50 , 0x000d },
 303        /* Wait 50 mS here. */
 304        { 0x90, 0  , 0x0011 },
 305        { 0x92, 0  , 0x0600 },
 306        { 0x93, 0  , 0x0003 },
 307        { 0x95, 0  , 0x0110 },
 308        { 0x97, 0  , 0x0000 },
 309        { 0x98, 0  , 0x0000 },
 310        { 0x07, 0  , 0x0173 },
 311};
 312
 313void board_mxsfb_system_setup(void)
 314{
 315        struct mxs_lcdif_regs *regs = (struct mxs_lcdif_regs *)MXS_LCDIF_BASE;
 316        uint32_t id;
 317        int i;
 318
 319        /* Switch the LCDIF into System-Mode */
 320        writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DOTCLK_MODE |
 321                LCDIF_CTRL_BYPASS_COUNT, &regs->hw_lcdif_ctrl_clr);
 322
 323        /* To program the LCD, switch to 18bit bus + 18bit data. */
 324        clrsetbits_le32(&regs->hw_lcdif_ctrl,
 325                LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK,
 326                LCDIF_CTRL_WORD_LENGTH_18BIT |
 327                LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT);
 328
 329        mxsfb_read_register(0, &id);
 330        writel(id, 0x2004);
 331
 332        /* Restart the SmartLCD controller */
 333        mdelay(50);
 334        writel(1, &regs->hw_lcdif_ctrl1_set);
 335        mdelay(50);
 336        writel(1, &regs->hw_lcdif_ctrl1_clr);
 337        mdelay(50);
 338        writel(1, &regs->hw_lcdif_ctrl1_set);
 339        mdelay(50);
 340
 341        /* Program the SmartLCD controller */
 342        writel(LCDIF_CTRL1_RECOVER_ON_UNDERFLOW, &regs->hw_lcdif_ctrl1_set);
 343
 344        writel((0x02 << LCDIF_TIMING_CMD_HOLD_OFFSET) |
 345               (0x02 << LCDIF_TIMING_CMD_SETUP_OFFSET) |
 346               (0x02 << LCDIF_TIMING_DATA_HOLD_OFFSET) |
 347               (0x01 << LCDIF_TIMING_DATA_SETUP_OFFSET),
 348               &regs->hw_lcdif_timing);
 349
 350        /*
 351         * ILI9325 init and configuration sequence.
 352         */
 353        for (i = 0; i < ARRAY_SIZE(lcd_regs); i++) {
 354                mxsfb_write_register(lcd_regs[i].reg, lcd_regs[i].val);
 355                if (lcd_regs[i].delay)
 356                        mdelay(lcd_regs[i].delay);
 357        }
 358        /* Turn on Framebuffer Upload Mode */
 359        mxsfb_write_byte(0x22, 0);
 360
 361        writel(LCDIF_CTRL_LCDIF_MASTER | LCDIF_CTRL_DATA_SELECT,
 362                &regs->hw_lcdif_ctrl_set);
 363
 364        /* Operate the framebuffer in 16bit mode. */
 365        clrsetbits_le32(&regs->hw_lcdif_ctrl,
 366                LCDIF_CTRL_WORD_LENGTH_MASK | LCDIF_CTRL_LCD_DATABUS_WIDTH_MASK,
 367                LCDIF_CTRL_WORD_LENGTH_16BIT |
 368                LCDIF_CTRL_LCD_DATABUS_WIDTH_18BIT);
 369}
 370#endif
 371
 372int board_init(void)
 373{
 374        /* Adress of boot parameters */
 375        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
 376
 377        /* Turn on PWM backlight */
 378        gpio_direction_output(MX23_PAD_PWM2__GPIO_1_28, 1);
 379
 380        return 0;
 381}
 382
 383int board_eth_init(bd_t *bis)
 384{
 385        usb_eth_initialize(bis);
 386        return 0;
 387}
 388