xref: /openbmc/u-boot/board/synopsys/emsdp/emsdp.c (revision e54457f7495e6fe527d1bad0d8cc7b717558a759)
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