Merge branch 'master' of git://git.denx.de/u-boot-spi
[platform/kernel/u-boot.git] / board / synopsys / emsdp / emsdp.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
4  */
5
6 #include <common.h>
7 #include <dwmmc.h>
8 #include <malloc.h>
9
10 #include <asm/arcregs.h>
11
12 DECLARE_GLOBAL_DATA_PTR;
13
14 #define ARC_PERIPHERAL_BASE             0xF0000000
15
16 #define CGU_ARC_FMEAS_ARC               (void *)(ARC_PERIPHERAL_BASE + 0x84)
17 #define CGU_ARC_FMEAS_ARC_START         BIT(31)
18 #define CGU_ARC_FMEAS_ARC_DONE          BIT(30)
19 #define CGU_ARC_FMEAS_ARC_CNT_MASK      GENMASK(14, 0)
20 #define CGU_ARC_FMEAS_ARC_RCNT_OFFSET   0
21 #define CGU_ARC_FMEAS_ARC_FCNT_OFFSET   15
22
23 #define SDIO_BASE                       (void *)(ARC_PERIPHERAL_BASE + 0x10000)
24
25 int mach_cpu_init(void)
26 {
27         int rcnt, fcnt;
28         u32 data;
29
30         /* Start frequency measurement */
31         writel(CGU_ARC_FMEAS_ARC_START, CGU_ARC_FMEAS_ARC);
32
33         /* Poll DONE bit */
34         do {
35                 data = readl(CGU_ARC_FMEAS_ARC);
36         } while (!(data & CGU_ARC_FMEAS_ARC_DONE));
37
38         /* Amount of reference 100 MHz clocks */
39         rcnt = ((data >> CGU_ARC_FMEAS_ARC_RCNT_OFFSET) &
40                CGU_ARC_FMEAS_ARC_CNT_MASK);
41
42         /* Amount of CPU clocks */
43         fcnt = ((data >> CGU_ARC_FMEAS_ARC_FCNT_OFFSET) &
44                CGU_ARC_FMEAS_ARC_CNT_MASK);
45
46         gd->cpu_clk = ((100 * fcnt) / rcnt) * 1000000;
47
48         return 0;
49 }
50
51 int board_mmc_init(bd_t *bis)
52 {
53         struct dwmci_host *host = NULL;
54
55         host = malloc(sizeof(struct dwmci_host));
56         if (!host) {
57                 printf("dwmci_host malloc fail!\n");
58                 return 1;
59         }
60
61         memset(host, 0, sizeof(struct dwmci_host));
62         host->name = "Synopsys Mobile storage";
63         host->ioaddr = SDIO_BASE;
64         host->buswidth = 4;
65         host->dev_index = 0;
66         host->bus_hz = 50000000;
67
68         add_dwmci(host, host->bus_hz / 2, 400000);
69
70         return 0;
71 }
72
73 int board_mmc_getcd(struct mmc *mmc)
74 {
75         struct dwmci_host *host = mmc->priv;
76
77         return !(dwmci_readl(host, DWMCI_CDETECT) & 1);
78 }
79
80 #define CREG_BASE               0xF0001000
81 #define CREG_BOOT               (void *)(CREG_BASE + 0x0FF0)
82 #define CREG_IP_SW_RESET        (void *)(CREG_BASE + 0x0FF0)
83 #define CREG_IP_VERSION         (void *)(CREG_BASE + 0x0FF8)
84
85 /* Bits in CREG_BOOT register */
86 #define CREG_BOOT_WP_BIT        BIT(8)
87
88 void reset_cpu(ulong addr)
89 {
90         writel(1, CREG_IP_SW_RESET);
91         while (1)
92                 ; /* loop forever till reset */
93 }
94
95 static int do_emsdp_rom(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
96 {
97         u32 creg_boot = readl(CREG_BOOT);
98
99         if (!strcmp(argv[1], "unlock"))
100                 creg_boot &= ~CREG_BOOT_WP_BIT;
101         else if (!strcmp(argv[1], "lock"))
102                 creg_boot |= CREG_BOOT_WP_BIT;
103         else
104                 return CMD_RET_USAGE;
105
106         writel(creg_boot, CREG_BOOT);
107
108         return CMD_RET_SUCCESS;
109 }
110
111 cmd_tbl_t cmd_emsdp[] = {
112         U_BOOT_CMD_MKENT(rom, 2, 0, do_emsdp_rom, "", ""),
113 };
114
115 static int do_emsdp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
116 {
117         cmd_tbl_t *c;
118
119         c = find_cmd_tbl(argv[1], cmd_emsdp, ARRAY_SIZE(cmd_emsdp));
120
121         /* Strip off leading 'emsdp' command */
122         argc--;
123         argv++;
124
125         if (c == NULL || argc > c->maxargs)
126                 return CMD_RET_USAGE;
127
128         return c->cmd(cmdtp, flag, argc, argv);
129 }
130
131 U_BOOT_CMD(
132         emsdp, CONFIG_SYS_MAXARGS, 0, do_emsdp,
133         "Synopsys EMSDP specific commands",
134         "rom unlock - Unlock non-volatile memory for writing\n"
135         "emsdp rom lock - Lock non-volatile memory to prevent writing\n"
136 );
137
138 int checkboard(void)
139 {
140         int version = readl(CREG_IP_VERSION);
141
142         printf("Board: ARC EM Software Development Platform v%d.%d\n",
143                (version >> 16) & 0xff, version & 0xff);
144         return 0;
145 };