xref: /openbmc/u-boot/arch/arm/mach-zynq/slcr.c (revision 23ff8633)
1 /*
2  * Copyright (c) 2013 Xilinx Inc.
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <asm/io.h>
9 #include <malloc.h>
10 #include <asm/arch/hardware.h>
11 #include <asm/arch/sys_proto.h>
12 #include <asm/arch/clk.h>
13 
14 #define SLCR_LOCK_MAGIC		0x767B
15 #define SLCR_UNLOCK_MAGIC	0xDF0D
16 
17 #define SLCR_USB_L1_SEL			0x04
18 
19 #define SLCR_IDCODE_MASK	0x1F000
20 #define SLCR_IDCODE_SHIFT	12
21 
22 /*
23  * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
24  *
25  * @peri_name: Name of the peripheral for checking MIO status
26  * @get_pins: Pointer to array of get pin for this peripheral
27  * @num_pins: Number of pins for this peripheral
28  * @mask: Mask value
29  * @check_val: Required check value to get the status of  periph
30  */
31 struct zynq_slcr_mio_get_status {
32 	const char *peri_name;
33 	const int *get_pins;
34 	int num_pins;
35 	u32 mask;
36 	u32 check_val;
37 };
38 
39 static const int usb0_pins[] = {
40 	28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
41 };
42 
43 static const int usb1_pins[] = {
44 	40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
45 };
46 
47 static const struct zynq_slcr_mio_get_status mio_periphs[] = {
48 	{
49 		"usb0",
50 		usb0_pins,
51 		ARRAY_SIZE(usb0_pins),
52 		SLCR_USB_L1_SEL,
53 		SLCR_USB_L1_SEL,
54 	},
55 	{
56 		"usb1",
57 		usb1_pins,
58 		ARRAY_SIZE(usb1_pins),
59 		SLCR_USB_L1_SEL,
60 		SLCR_USB_L1_SEL,
61 	},
62 };
63 
64 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
65 
66 void zynq_slcr_lock(void)
67 {
68 	if (!slcr_lock) {
69 		writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock);
70 		slcr_lock = 1;
71 	}
72 }
73 
74 void zynq_slcr_unlock(void)
75 {
76 	if (slcr_lock) {
77 		writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock);
78 		slcr_lock = 0;
79 	}
80 }
81 
82 /* Reset the entire system */
83 void zynq_slcr_cpu_reset(void)
84 {
85 	/*
86 	 * Unlock the SLCR then reset the system.
87 	 * Note that this seems to require raw i/o
88 	 * functions or there's a lockup?
89 	 */
90 	zynq_slcr_unlock();
91 
92 	/*
93 	 * Clear 0x0F000000 bits of reboot status register to workaround
94 	 * the FSBL not loading the bitstream after soft-reboot
95 	 * This is a temporary solution until we know more.
96 	 */
97 	clrbits_le32(&slcr_base->reboot_status, 0xF000000);
98 
99 	writel(1, &slcr_base->pss_rst_ctrl);
100 }
101 
102 /* Setup clk for network */
103 void zynq_slcr_gem_clk_setup(u32 gem_id, unsigned long clk_rate)
104 {
105 	int ret;
106 
107 	zynq_slcr_unlock();
108 
109 	if (gem_id > 1) {
110 		printf("Non existing GEM id %d\n", gem_id);
111 		goto out;
112 	}
113 
114 	ret = zynq_clk_set_rate(gem0_clk + gem_id, clk_rate);
115 	if (ret)
116 		goto out;
117 
118 	if (gem_id) {
119 		/* Configure GEM_RCLK_CTRL */
120 		writel(1, &slcr_base->gem1_rclk_ctrl);
121 	} else {
122 		/* Configure GEM_RCLK_CTRL */
123 		writel(1, &slcr_base->gem0_rclk_ctrl);
124 	}
125 	udelay(100000);
126 out:
127 	zynq_slcr_lock();
128 }
129 
130 void zynq_slcr_devcfg_disable(void)
131 {
132 	u32 reg_val;
133 
134 	zynq_slcr_unlock();
135 
136 	/* Disable AXI interface by asserting FPGA resets */
137 	writel(0xF, &slcr_base->fpga_rst_ctrl);
138 
139 	/* Disable Level shifters before setting PS-PL */
140 	reg_val = readl(&slcr_base->lvl_shftr_en);
141 	reg_val &= ~0xF;
142 	writel(reg_val, &slcr_base->lvl_shftr_en);
143 
144 	/* Set Level Shifters DT618760 */
145 	writel(0xA, &slcr_base->lvl_shftr_en);
146 
147 	zynq_slcr_lock();
148 }
149 
150 void zynq_slcr_devcfg_enable(void)
151 {
152 	zynq_slcr_unlock();
153 
154 	/* Set Level Shifters DT618760 */
155 	writel(0xF, &slcr_base->lvl_shftr_en);
156 
157 	/* Enable AXI interface by de-asserting FPGA resets */
158 	writel(0x0, &slcr_base->fpga_rst_ctrl);
159 
160 	zynq_slcr_lock();
161 }
162 
163 u32 zynq_slcr_get_boot_mode(void)
164 {
165 	/* Get the bootmode register value */
166 	return readl(&slcr_base->boot_mode);
167 }
168 
169 u32 zynq_slcr_get_idcode(void)
170 {
171 	return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >>
172 							SLCR_IDCODE_SHIFT;
173 }
174 
175 /*
176  * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
177  *
178  * @periph: Name of the peripheral
179  *
180  * Returns count to indicate the number of pins configured for the
181  * given @periph.
182  */
183 int zynq_slcr_get_mio_pin_status(const char *periph)
184 {
185 	const struct zynq_slcr_mio_get_status *mio_ptr;
186 	int val, i, j;
187 	int mio = 0;
188 
189 	for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
190 		if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
191 			mio_ptr = &mio_periphs[i];
192 			for (j = 0; j < mio_ptr->num_pins; j++) {
193 				val = readl(&slcr_base->mio_pin
194 						[mio_ptr->get_pins[j]]);
195 				if ((val & mio_ptr->mask) == mio_ptr->check_val)
196 					mio++;
197 			}
198 			break;
199 		}
200 	}
201 
202 	return mio;
203 }
204