1adc9b09aSAlexey Brodkin // SPDX-License-Identifier: GPL-2.0+
2adc9b09aSAlexey Brodkin /*
3adc9b09aSAlexey Brodkin * Copyright (C) 2018 Synopsys, Inc. All rights reserved.
4adc9b09aSAlexey Brodkin */
5adc9b09aSAlexey Brodkin
6adc9b09aSAlexey Brodkin #include <common.h>
7adc9b09aSAlexey Brodkin #include <dwmmc.h>
8adc9b09aSAlexey Brodkin #include <malloc.h>
9adc9b09aSAlexey Brodkin
104e86c7e3SAlexey Brodkin #include <asm/arcregs.h>
114e86c7e3SAlexey Brodkin
12adc9b09aSAlexey Brodkin DECLARE_GLOBAL_DATA_PTR;
13adc9b09aSAlexey Brodkin
14adc9b09aSAlexey Brodkin #define ARC_PERIPHERAL_BASE 0xF0000000
154e86c7e3SAlexey Brodkin
164e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC (void *)(ARC_PERIPHERAL_BASE + 0x84)
174e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC_START BIT(31)
184e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC_DONE BIT(30)
194e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC_CNT_MASK GENMASK(14, 0)
204e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC_RCNT_OFFSET 0
214e86c7e3SAlexey Brodkin #define CGU_ARC_FMEAS_ARC_FCNT_OFFSET 15
224e86c7e3SAlexey Brodkin
234e86c7e3SAlexey Brodkin #define SDIO_BASE (void *)(ARC_PERIPHERAL_BASE + 0x10000)
244e86c7e3SAlexey Brodkin
mach_cpu_init(void)254e86c7e3SAlexey Brodkin int mach_cpu_init(void)
264e86c7e3SAlexey Brodkin {
274e86c7e3SAlexey Brodkin int rcnt, fcnt;
284e86c7e3SAlexey Brodkin u32 data;
294e86c7e3SAlexey Brodkin
304e86c7e3SAlexey Brodkin /* Start frequency measurement */
314e86c7e3SAlexey Brodkin writel(CGU_ARC_FMEAS_ARC_START, CGU_ARC_FMEAS_ARC);
324e86c7e3SAlexey Brodkin
334e86c7e3SAlexey Brodkin /* Poll DONE bit */
344e86c7e3SAlexey Brodkin do {
354e86c7e3SAlexey Brodkin data = readl(CGU_ARC_FMEAS_ARC);
364e86c7e3SAlexey Brodkin } while (!(data & CGU_ARC_FMEAS_ARC_DONE));
374e86c7e3SAlexey Brodkin
384e86c7e3SAlexey Brodkin /* Amount of reference 100 MHz clocks */
394e86c7e3SAlexey Brodkin rcnt = ((data >> CGU_ARC_FMEAS_ARC_RCNT_OFFSET) &
404e86c7e3SAlexey Brodkin CGU_ARC_FMEAS_ARC_CNT_MASK);
414e86c7e3SAlexey Brodkin
424e86c7e3SAlexey Brodkin /* Amount of CPU clocks */
434e86c7e3SAlexey Brodkin fcnt = ((data >> CGU_ARC_FMEAS_ARC_FCNT_OFFSET) &
444e86c7e3SAlexey Brodkin CGU_ARC_FMEAS_ARC_CNT_MASK);
454e86c7e3SAlexey Brodkin
464e86c7e3SAlexey Brodkin gd->cpu_clk = ((100 * fcnt) / rcnt) * 1000000;
474e86c7e3SAlexey Brodkin
484e86c7e3SAlexey Brodkin return 0;
494e86c7e3SAlexey Brodkin }
50adc9b09aSAlexey Brodkin
board_mmc_init(bd_t * bis)51adc9b09aSAlexey Brodkin int board_mmc_init(bd_t *bis)
52adc9b09aSAlexey Brodkin {
53adc9b09aSAlexey Brodkin struct dwmci_host *host = NULL;
54adc9b09aSAlexey Brodkin
55adc9b09aSAlexey Brodkin host = malloc(sizeof(struct dwmci_host));
56adc9b09aSAlexey Brodkin if (!host) {
57adc9b09aSAlexey Brodkin printf("dwmci_host malloc fail!\n");
58adc9b09aSAlexey Brodkin return 1;
59adc9b09aSAlexey Brodkin }
60adc9b09aSAlexey Brodkin
61adc9b09aSAlexey Brodkin memset(host, 0, sizeof(struct dwmci_host));
62adc9b09aSAlexey Brodkin host->name = "Synopsys Mobile storage";
634e86c7e3SAlexey Brodkin host->ioaddr = SDIO_BASE;
64adc9b09aSAlexey Brodkin host->buswidth = 4;
65adc9b09aSAlexey Brodkin host->dev_index = 0;
66adc9b09aSAlexey Brodkin host->bus_hz = 50000000;
67adc9b09aSAlexey Brodkin
68adc9b09aSAlexey Brodkin add_dwmci(host, host->bus_hz / 2, 400000);
69adc9b09aSAlexey Brodkin
70adc9b09aSAlexey Brodkin return 0;
71adc9b09aSAlexey Brodkin }
72adc9b09aSAlexey Brodkin
board_mmc_getcd(struct mmc * mmc)73adc9b09aSAlexey Brodkin int board_mmc_getcd(struct mmc *mmc)
74adc9b09aSAlexey Brodkin {
75adc9b09aSAlexey Brodkin struct dwmci_host *host = mmc->priv;
76adc9b09aSAlexey Brodkin
77adc9b09aSAlexey Brodkin return !(dwmci_readl(host, DWMCI_CDETECT) & 1);
78adc9b09aSAlexey Brodkin }
79adc9b09aSAlexey Brodkin
80adc9b09aSAlexey Brodkin #define CREG_BASE 0xF0001000
81fb9a46a2SAlexey Brodkin #define CREG_BOOT (void *)(CREG_BASE + 0x0FF0)
82fb9a46a2SAlexey Brodkin #define CREG_IP_SW_RESET (void *)(CREG_BASE + 0x0FF0)
83*6ef705b1SAlexey Brodkin #define CREG_IP_VERSION (void *)(CREG_BASE + 0x0FF8)
84adc9b09aSAlexey Brodkin
85fb9a46a2SAlexey Brodkin /* Bits in CREG_BOOT register */
86fb9a46a2SAlexey Brodkin #define CREG_BOOT_WP_BIT BIT(8)
87adc9b09aSAlexey Brodkin
reset_cpu(ulong addr)88adc9b09aSAlexey Brodkin void reset_cpu(ulong addr)
89adc9b09aSAlexey Brodkin {
90fb9a46a2SAlexey Brodkin writel(1, CREG_IP_SW_RESET);
91adc9b09aSAlexey Brodkin while (1)
92adc9b09aSAlexey Brodkin ; /* loop forever till reset */
93adc9b09aSAlexey Brodkin }
94adc9b09aSAlexey Brodkin
do_emsdp_rom(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])95adc9b09aSAlexey Brodkin static int do_emsdp_rom(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
96adc9b09aSAlexey Brodkin {
97fb9a46a2SAlexey Brodkin u32 creg_boot = readl(CREG_BOOT);
98adc9b09aSAlexey Brodkin
99adc9b09aSAlexey Brodkin if (!strcmp(argv[1], "unlock"))
100fb9a46a2SAlexey Brodkin creg_boot &= ~CREG_BOOT_WP_BIT;
101adc9b09aSAlexey Brodkin else if (!strcmp(argv[1], "lock"))
102fb9a46a2SAlexey Brodkin creg_boot |= CREG_BOOT_WP_BIT;
103adc9b09aSAlexey Brodkin else
104adc9b09aSAlexey Brodkin return CMD_RET_USAGE;
105adc9b09aSAlexey Brodkin
106fb9a46a2SAlexey Brodkin writel(creg_boot, CREG_BOOT);
107adc9b09aSAlexey Brodkin
108adc9b09aSAlexey Brodkin return CMD_RET_SUCCESS;
109adc9b09aSAlexey Brodkin }
110adc9b09aSAlexey Brodkin
111adc9b09aSAlexey Brodkin cmd_tbl_t cmd_emsdp[] = {
112adc9b09aSAlexey Brodkin U_BOOT_CMD_MKENT(rom, 2, 0, do_emsdp_rom, "", ""),
113adc9b09aSAlexey Brodkin };
114adc9b09aSAlexey Brodkin
do_emsdp(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])115adc9b09aSAlexey Brodkin static int do_emsdp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
116adc9b09aSAlexey Brodkin {
117adc9b09aSAlexey Brodkin cmd_tbl_t *c;
118adc9b09aSAlexey Brodkin
119adc9b09aSAlexey Brodkin c = find_cmd_tbl(argv[1], cmd_emsdp, ARRAY_SIZE(cmd_emsdp));
120adc9b09aSAlexey Brodkin
121adc9b09aSAlexey Brodkin /* Strip off leading 'emsdp' command */
122adc9b09aSAlexey Brodkin argc--;
123adc9b09aSAlexey Brodkin argv++;
124adc9b09aSAlexey Brodkin
125adc9b09aSAlexey Brodkin if (c == NULL || argc > c->maxargs)
126adc9b09aSAlexey Brodkin return CMD_RET_USAGE;
127adc9b09aSAlexey Brodkin
128adc9b09aSAlexey Brodkin return c->cmd(cmdtp, flag, argc, argv);
129adc9b09aSAlexey Brodkin }
130adc9b09aSAlexey Brodkin
131adc9b09aSAlexey Brodkin U_BOOT_CMD(
132adc9b09aSAlexey Brodkin emsdp, CONFIG_SYS_MAXARGS, 0, do_emsdp,
133adc9b09aSAlexey Brodkin "Synopsys EMSDP specific commands",
134adc9b09aSAlexey Brodkin "rom unlock - Unlock non-volatile memory for writing\n"
135adc9b09aSAlexey Brodkin "emsdp rom lock - Lock non-volatile memory to prevent writing\n"
136adc9b09aSAlexey Brodkin );
137*6ef705b1SAlexey Brodkin
checkboard(void)138*6ef705b1SAlexey Brodkin int checkboard(void)
139*6ef705b1SAlexey Brodkin {
140*6ef705b1SAlexey Brodkin int version = readl(CREG_IP_VERSION);
141*6ef705b1SAlexey Brodkin
142*6ef705b1SAlexey Brodkin printf("Board: ARC EM Software Development Platform v%d.%d\n",
143*6ef705b1SAlexey Brodkin (version >> 16) & 0xff, version & 0xff);
144*6ef705b1SAlexey Brodkin return 0;
145*6ef705b1SAlexey Brodkin };
146