uboot/board/renesas/stout/cpld.c
<<
>>
Prefs
   1/*
   2 * Stout board CPLD access support
   3 *
   4 * Copyright (C) 2015 Renesas Electronics Europe GmbH
   5 * Copyright (C) 2015 Renesas Electronics Corporation
   6 * Copyright (C) 2015 Cogent Embedded, Inc.
   7 *
   8 * SPDX-License-Identifier: GPL-2.0
   9 */
  10
  11#include <common.h>
  12#include <asm/io.h>
  13#include <asm/gpio.h>
  14#include "cpld.h"
  15
  16#define SCLK                    GPIO_GP_3_24
  17#define SSTBZ                   GPIO_GP_3_25
  18#define MOSI                    GPIO_GP_3_26
  19#define MISO                    GPIO_GP_3_27
  20
  21#define CPLD_ADDR_MODE          0x00 /* RW */
  22#define CPLD_ADDR_MUX           0x01 /* RW */
  23#define CPLD_ADDR_HDMI          0x02 /* RW */
  24#define CPLD_ADDR_DIPSW         0x08 /* R */
  25#define CPLD_ADDR_RESET         0x80 /* RW */
  26#define CPLD_ADDR_VERSION       0xFF /* R */
  27
  28static u32 cpld_read(u8 addr)
  29{
  30        int i;
  31        u32 data = 0;
  32
  33        for (i = 0; i < 8; i++) {
  34                gpio_set_value(MOSI, addr & 0x80); /* MSB first */
  35                gpio_set_value(SCLK, 1);
  36                addr <<= 1;
  37                gpio_set_value(SCLK, 0);
  38        }
  39
  40        gpio_set_value(MOSI, 0); /* READ */
  41        gpio_set_value(SSTBZ, 0);
  42        gpio_set_value(SCLK, 1);
  43        gpio_set_value(SCLK, 0);
  44        gpio_set_value(SSTBZ, 1);
  45
  46        for (i = 0; i < 32; i++) {
  47                gpio_set_value(SCLK, 1);
  48                data <<= 1;
  49                data |= gpio_get_value(MISO); /* MSB first */
  50                gpio_set_value(SCLK, 0);
  51        }
  52
  53        return data;
  54}
  55
  56static void cpld_write(u8 addr, u32 data)
  57{
  58        int i;
  59
  60        for (i = 0; i < 32; i++) {
  61                gpio_set_value(MOSI, data & (1 << 31)); /* MSB first */
  62                gpio_set_value(SCLK, 1);
  63                data <<= 1;
  64                gpio_set_value(SCLK, 0);
  65        }
  66
  67        for (i = 0; i < 8; i++) {
  68                gpio_set_value(MOSI, addr & 0x80); /* MSB first */
  69                gpio_set_value(SCLK, 1);
  70                addr <<= 1;
  71                gpio_set_value(SCLK, 0);
  72        }
  73
  74        gpio_set_value(MOSI, 1); /* WRITE */
  75        gpio_set_value(SSTBZ, 0);
  76        gpio_set_value(SCLK, 1);
  77        gpio_set_value(SCLK, 0);
  78        gpio_set_value(SSTBZ, 1);
  79}
  80
  81/* LSI pin pull-up control */
  82#define PUPR3           0xe606010C
  83#define PUPR3_SD3_DAT1  (1 << 27)
  84
  85void cpld_init(void)
  86{
  87        u32 val;
  88
  89        /* PULL-UP on MISO line */
  90        val = readl(PUPR3);
  91        val |= PUPR3_SD3_DAT1;
  92        writel(val, PUPR3);
  93
  94        gpio_request(SCLK, NULL);
  95        gpio_request(SSTBZ, NULL);
  96        gpio_request(MOSI, NULL);
  97        gpio_request(MISO, NULL);
  98
  99        gpio_direction_output(SCLK, 0);
 100        gpio_direction_output(SSTBZ, 1);
 101        gpio_direction_output(MOSI, 0);
 102        gpio_direction_input(MISO);
 103
 104        /* dummy read */
 105        cpld_read(CPLD_ADDR_VERSION);
 106
 107        printf("CPLD version:              0x%08x\n",
 108               cpld_read(CPLD_ADDR_VERSION));
 109        printf("H2 Mode setting (MD0..28): 0x%08x\n",
 110               cpld_read(CPLD_ADDR_MODE));
 111        printf("Multiplexer settings:      0x%08x\n",
 112               cpld_read(CPLD_ADDR_MUX));
 113        printf("HDMI setting:              0x%08x\n",
 114               cpld_read(CPLD_ADDR_HDMI));
 115        printf("DIPSW (SW3):               0x%08x\n",
 116               cpld_read(CPLD_ADDR_DIPSW));
 117
 118#ifdef CONFIG_SH_SDHI
 119        /* switch MUX to SD0 */
 120        val = cpld_read(CPLD_ADDR_MUX);
 121        val &= ~MUX_MSK_SD0;
 122        val |= MUX_VAL_SD0;
 123        cpld_write(CPLD_ADDR_MUX, val);
 124#endif
 125}
 126
 127static int do_cpld(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 128{
 129        u32 addr, val;
 130
 131        if (argc < 3)
 132                return CMD_RET_USAGE;
 133
 134        addr = simple_strtoul(argv[2], NULL, 16);
 135        if (!(addr == CPLD_ADDR_VERSION || addr == CPLD_ADDR_MODE ||
 136              addr == CPLD_ADDR_MUX || addr == CPLD_ADDR_HDMI ||
 137              addr == CPLD_ADDR_DIPSW || addr == CPLD_ADDR_RESET)) {
 138                printf("cpld invalid addr\n");
 139                return CMD_RET_USAGE;
 140        }
 141
 142        if (argc == 3 && strcmp(argv[1], "read") == 0) {
 143                printf("0x%x\n", cpld_read(addr));
 144        } else if (argc == 4 && strcmp(argv[1], "write") == 0) {
 145                val = simple_strtoul(argv[3], NULL, 16);
 146                if (addr == CPLD_ADDR_MUX) {
 147                        /* never mask SCIFA0 console */
 148                        val &= ~MUX_MSK_SCIFA0_USB;
 149                        val |= MUX_VAL_SCIFA0_USB;
 150                }
 151                cpld_write(addr, val);
 152        }
 153
 154        return 0;
 155}
 156
 157U_BOOT_CMD(
 158        cpld, 4, 1, do_cpld,
 159        "CPLD access",
 160        "read addr\n"
 161        "cpld write addr val\n"
 162);
 163
 164void reset_cpu(ulong addr)
 165{
 166        cpld_write(CPLD_ADDR_RESET, 1);
 167}
 168