xref: /freebsd/sys/arm/mv/armada38x/armada38x.c (revision fdafd315)
1f8742b0dSZbigniew Bodek /*-
2f8742b0dSZbigniew Bodek  * Copyright (c) 2015 Semihalf.
3f8742b0dSZbigniew Bodek  * Copyright (c) 2015 Stormshield.
4f8742b0dSZbigniew Bodek  * All rights reserved.
5f8742b0dSZbigniew Bodek  *
6f8742b0dSZbigniew Bodek  * Redistribution and use in source and binary forms, with or without
7f8742b0dSZbigniew Bodek  * modification, are permitted provided that the following conditions
8f8742b0dSZbigniew Bodek  * are met:
9f8742b0dSZbigniew Bodek  * 1. Redistributions of source code must retain the above copyright
10f8742b0dSZbigniew Bodek  *    notice, this list of conditions and the following disclaimer.
11f8742b0dSZbigniew Bodek  * 2. Redistributions in binary form must reproduce the above copyright
12f8742b0dSZbigniew Bodek  *    notice, this list of conditions and the following disclaimer in the
13f8742b0dSZbigniew Bodek  *    documentation and/or other materials provided with the distribution.
14f8742b0dSZbigniew Bodek  *
15f8742b0dSZbigniew Bodek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16f8742b0dSZbigniew Bodek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17f8742b0dSZbigniew Bodek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18f8742b0dSZbigniew Bodek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19f8742b0dSZbigniew Bodek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20f8742b0dSZbigniew Bodek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21f8742b0dSZbigniew Bodek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22f8742b0dSZbigniew Bodek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23f8742b0dSZbigniew Bodek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24f8742b0dSZbigniew Bodek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25f8742b0dSZbigniew Bodek  * SUCH DAMAGE.
26f8742b0dSZbigniew Bodek  */
27f8742b0dSZbigniew Bodek 
28f8742b0dSZbigniew Bodek #include <sys/param.h>
2911a6a330SZbigniew Bodek #include <sys/sysctl.h>
30f8742b0dSZbigniew Bodek #include <sys/systm.h>
31f8742b0dSZbigniew Bodek #include <sys/bus.h>
32f8742b0dSZbigniew Bodek 
335b683b6fSZbigniew Bodek #include <machine/fdt.h>
345b683b6fSZbigniew Bodek 
35f8742b0dSZbigniew Bodek #include <arm/mv/mvwin.h>
36f8742b0dSZbigniew Bodek #include <arm/mv/mvreg.h>
37f8742b0dSZbigniew Bodek #include <arm/mv/mvvar.h>
38f8742b0dSZbigniew Bodek 
3946c9254bSZbigniew Bodek int armada38x_open_bootrom_win(void);
40223e0cfdSZbigniew Bodek int armada38x_scu_enable(void);
4146c9254bSZbigniew Bodek int armada38x_win_set_iosync_barrier(void);
422fcf4145SZbigniew Bodek int armada38x_mbus_optimization(void);
430a57279bSMarcin Wojtas static uint64_t get_sar_value_armada38x(void);
445b683b6fSZbigniew Bodek 
4511a6a330SZbigniew Bodek static int hw_clockrate;
4611a6a330SZbigniew Bodek SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD,
4711a6a330SZbigniew Bodek     &hw_clockrate, 0, "CPU instruction clock rate");
4811a6a330SZbigniew Bodek 
490a57279bSMarcin Wojtas static uint64_t
get_sar_value_armada38x(void)500a57279bSMarcin Wojtas get_sar_value_armada38x(void)
510a57279bSMarcin Wojtas {
520a57279bSMarcin Wojtas 	uint32_t sar_low, sar_high;
530a57279bSMarcin Wojtas 
540a57279bSMarcin Wojtas 	sar_high = 0;
550a57279bSMarcin Wojtas 	sar_low = bus_space_read_4(fdtbus_bs_tag, MV_MISC_BASE,
560a57279bSMarcin Wojtas 	    SAMPLE_AT_RESET_ARMADA38X);
570a57279bSMarcin Wojtas 	return (((uint64_t)sar_high << 32) | sar_low);
580a57279bSMarcin Wojtas }
590a57279bSMarcin Wojtas 
60f8742b0dSZbigniew Bodek uint32_t
get_tclk_armada38x(void)61526de79bSMarcin Wojtas get_tclk_armada38x(void)
62f8742b0dSZbigniew Bodek {
63f8742b0dSZbigniew Bodek 	uint32_t sar;
64f8742b0dSZbigniew Bodek 
65f8742b0dSZbigniew Bodek 	/*
66f8742b0dSZbigniew Bodek 	 * On Armada38x TCLK can be configured to 250 MHz or 200 MHz.
67f8742b0dSZbigniew Bodek 	 * Current setting is read from Sample At Reset register.
68f8742b0dSZbigniew Bodek 	 */
690a57279bSMarcin Wojtas 	sar = (uint32_t)get_sar_value_armada38x();
700a57279bSMarcin Wojtas 	sar = (sar & TCLK_MASK_ARMADA38X) >> TCLK_SHIFT_ARMADA38X;
71f8742b0dSZbigniew Bodek 	if (sar == 0)
72f8742b0dSZbigniew Bodek 		return (TCLK_250MHZ);
73f8742b0dSZbigniew Bodek 	else
74f8742b0dSZbigniew Bodek 		return (TCLK_200MHZ);
75f8742b0dSZbigniew Bodek }
765b683b6fSZbigniew Bodek 
7711a6a330SZbigniew Bodek uint32_t
get_cpu_freq_armada38x(void)78526de79bSMarcin Wojtas get_cpu_freq_armada38x(void)
7911a6a330SZbigniew Bodek {
8011a6a330SZbigniew Bodek 	uint32_t sar;
8111a6a330SZbigniew Bodek 
8211a6a330SZbigniew Bodek 	static const uint32_t cpu_frequencies[] = {
8311a6a330SZbigniew Bodek 		0, 0, 0, 0,
8411a6a330SZbigniew Bodek 		1066, 0, 0, 0,
8511a6a330SZbigniew Bodek 		1332, 0, 0, 0,
8611a6a330SZbigniew Bodek 		1600, 0, 0, 0,
8711a6a330SZbigniew Bodek 		1866, 0, 0, 2000
8811a6a330SZbigniew Bodek 	};
8911a6a330SZbigniew Bodek 
900a57279bSMarcin Wojtas 	sar = (uint32_t)get_sar_value_armada38x();
9111a6a330SZbigniew Bodek 	sar = (sar & A38X_CPU_DDR_CLK_MASK) >> A38X_CPU_DDR_CLK_SHIFT;
9211a6a330SZbigniew Bodek 	if (sar >= nitems(cpu_frequencies))
9311a6a330SZbigniew Bodek 		return (0);
9411a6a330SZbigniew Bodek 
9511a6a330SZbigniew Bodek 	hw_clockrate = cpu_frequencies[sar];
9611a6a330SZbigniew Bodek 
9711a6a330SZbigniew Bodek 	return (hw_clockrate * 1000 * 1000);
9811a6a330SZbigniew Bodek }
9911a6a330SZbigniew Bodek 
1005b683b6fSZbigniew Bodek int
armada38x_win_set_iosync_barrier(void)1015b683b6fSZbigniew Bodek armada38x_win_set_iosync_barrier(void)
1025b683b6fSZbigniew Bodek {
1035b683b6fSZbigniew Bodek 	bus_space_handle_t vaddr_iowind;
1045b683b6fSZbigniew Bodek 	int rv;
1055b683b6fSZbigniew Bodek 
1065b683b6fSZbigniew Bodek 	rv = bus_space_map(fdtbus_bs_tag, (bus_addr_t)MV_MBUS_BRIDGE_BASE,
1075b683b6fSZbigniew Bodek 	    MV_CPU_SUBSYS_REGS_LEN, 0, &vaddr_iowind);
1085b683b6fSZbigniew Bodek 	if (rv != 0)
1095b683b6fSZbigniew Bodek 		return (rv);
1105b683b6fSZbigniew Bodek 
1115b683b6fSZbigniew Bodek 	/* Set Sync Barrier flags for all Mbus internal units */
1125b683b6fSZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, MV_SYNC_BARRIER_CTRL,
1135b683b6fSZbigniew Bodek 	    MV_SYNC_BARRIER_CTRL_ALL);
1145b683b6fSZbigniew Bodek 
1155b683b6fSZbigniew Bodek 	bus_space_barrier(fdtbus_bs_tag, vaddr_iowind, 0,
1165b683b6fSZbigniew Bodek 	    MV_CPU_SUBSYS_REGS_LEN, BUS_SPACE_BARRIER_WRITE);
1175b683b6fSZbigniew Bodek 	bus_space_unmap(fdtbus_bs_tag, vaddr_iowind, MV_CPU_SUBSYS_REGS_LEN);
1185b683b6fSZbigniew Bodek 
1195b683b6fSZbigniew Bodek 	return (rv);
1205b683b6fSZbigniew Bodek }
121223e0cfdSZbigniew Bodek 
122223e0cfdSZbigniew Bodek int
armada38x_open_bootrom_win(void)12346c9254bSZbigniew Bodek armada38x_open_bootrom_win(void)
12446c9254bSZbigniew Bodek {
12546c9254bSZbigniew Bodek 	bus_space_handle_t vaddr_iowind;
12646c9254bSZbigniew Bodek 	uint32_t val;
12746c9254bSZbigniew Bodek 	int rv;
12846c9254bSZbigniew Bodek 
12946c9254bSZbigniew Bodek 	rv = bus_space_map(fdtbus_bs_tag, (bus_addr_t)MV_MBUS_BRIDGE_BASE,
13046c9254bSZbigniew Bodek 	    MV_CPU_SUBSYS_REGS_LEN, 0, &vaddr_iowind);
13146c9254bSZbigniew Bodek 	if (rv != 0)
13246c9254bSZbigniew Bodek 		return (rv);
13346c9254bSZbigniew Bodek 
13446c9254bSZbigniew Bodek 	val = (MV_BOOTROM_WIN_SIZE & IO_WIN_SIZE_MASK) << IO_WIN_SIZE_SHIFT;
13546c9254bSZbigniew Bodek 	val |= (MBUS_BOOTROM_ATTR & IO_WIN_ATTR_MASK) << IO_WIN_ATTR_SHIFT;
13646c9254bSZbigniew Bodek 	val |= (MBUS_BOOTROM_TGT_ID & IO_WIN_TGT_MASK) << IO_WIN_TGT_SHIFT;
13746c9254bSZbigniew Bodek 	/* Enable window and Sync Barrier */
13846c9254bSZbigniew Bodek 	val |= (0x1 & IO_WIN_SYNC_MASK) << IO_WIN_SYNC_SHIFT;
13946c9254bSZbigniew Bodek 	val |= (0x1 & IO_WIN_ENA_MASK) << IO_WIN_ENA_SHIFT;
14046c9254bSZbigniew Bodek 
14146c9254bSZbigniew Bodek 	/* Configure IO Window Control Register */
14246c9254bSZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, IO_WIN_9_CTRL_OFFSET,
14346c9254bSZbigniew Bodek 	    val);
14446c9254bSZbigniew Bodek 	/* Configure IO Window Base Register */
14546c9254bSZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, IO_WIN_9_BASE_OFFSET,
14646c9254bSZbigniew Bodek 	    MV_BOOTROM_MEM_ADDR);
14746c9254bSZbigniew Bodek 
14846c9254bSZbigniew Bodek 	bus_space_barrier(fdtbus_bs_tag, vaddr_iowind, 0, MV_CPU_SUBSYS_REGS_LEN,
14946c9254bSZbigniew Bodek 	    BUS_SPACE_BARRIER_WRITE);
15046c9254bSZbigniew Bodek 	bus_space_unmap(fdtbus_bs_tag, vaddr_iowind, MV_CPU_SUBSYS_REGS_LEN);
15146c9254bSZbigniew Bodek 
15246c9254bSZbigniew Bodek 	return (rv);
15346c9254bSZbigniew Bodek }
15446c9254bSZbigniew Bodek 
15546c9254bSZbigniew Bodek int
armada38x_mbus_optimization(void)1562fcf4145SZbigniew Bodek armada38x_mbus_optimization(void)
1572fcf4145SZbigniew Bodek {
1582fcf4145SZbigniew Bodek 	bus_space_handle_t vaddr_iowind;
1592fcf4145SZbigniew Bodek 	int rv;
1602fcf4145SZbigniew Bodek 
1612fcf4145SZbigniew Bodek 	rv = bus_space_map(fdtbus_bs_tag, (bus_addr_t)MV_MBUS_CTRL_BASE,
1622fcf4145SZbigniew Bodek 	    MV_MBUS_CTRL_REGS_LEN, 0, &vaddr_iowind);
1632fcf4145SZbigniew Bodek 	if (rv != 0)
1642fcf4145SZbigniew Bodek 		return (rv);
1652fcf4145SZbigniew Bodek 
1662fcf4145SZbigniew Bodek 	/*
1672fcf4145SZbigniew Bodek 	 * MBUS Units Priority Control Register - Prioritize XOR,
1682fcf4145SZbigniew Bodek 	 * PCIe and GbEs (ID=4,6,3,7,8) DRAM access
1692fcf4145SZbigniew Bodek 	 * GbE is High and others are Medium.
1702fcf4145SZbigniew Bodek 	 */
1712fcf4145SZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, 0, 0x19180);
1722fcf4145SZbigniew Bodek 
1732fcf4145SZbigniew Bodek 	/*
1742fcf4145SZbigniew Bodek 	 * Fabric Units Priority Control Register -
1752fcf4145SZbigniew Bodek 	 * Prioritize CPUs requests.
1762fcf4145SZbigniew Bodek 	 */
1772fcf4145SZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, 0x4, 0x3000A);
1782fcf4145SZbigniew Bodek 
1792fcf4145SZbigniew Bodek 	/*
1802fcf4145SZbigniew Bodek 	 * MBUS Units Prefetch Control Register -
1812fcf4145SZbigniew Bodek 	 * Pre-fetch enable for all IO masters.
1822fcf4145SZbigniew Bodek 	 */
1832fcf4145SZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, 0x8, 0xFFFF);
1842fcf4145SZbigniew Bodek 
1852fcf4145SZbigniew Bodek 	/*
1862fcf4145SZbigniew Bodek 	 * Fabric Units Prefetch Control Register -
1872fcf4145SZbigniew Bodek 	 * Enable the CPUs Instruction and Data prefetch.
1882fcf4145SZbigniew Bodek 	 */
1892fcf4145SZbigniew Bodek 	bus_space_write_4(fdtbus_bs_tag, vaddr_iowind, 0xc, 0x303);
1902fcf4145SZbigniew Bodek 
1912fcf4145SZbigniew Bodek 	bus_space_barrier(fdtbus_bs_tag, vaddr_iowind, 0, MV_MBUS_CTRL_REGS_LEN,
1922fcf4145SZbigniew Bodek 	    BUS_SPACE_BARRIER_WRITE);
1932fcf4145SZbigniew Bodek 
1942fcf4145SZbigniew Bodek 	bus_space_unmap(fdtbus_bs_tag, vaddr_iowind, MV_MBUS_CTRL_REGS_LEN);
1952fcf4145SZbigniew Bodek 
1962fcf4145SZbigniew Bodek 	return (rv);
1972fcf4145SZbigniew Bodek }
1982fcf4145SZbigniew Bodek 
1992fcf4145SZbigniew Bodek int
armada38x_scu_enable(void)200223e0cfdSZbigniew Bodek armada38x_scu_enable(void)
201223e0cfdSZbigniew Bodek {
202223e0cfdSZbigniew Bodek 	bus_space_handle_t vaddr_scu;
203223e0cfdSZbigniew Bodek 	int rv;
204223e0cfdSZbigniew Bodek 	uint32_t val;
205223e0cfdSZbigniew Bodek 
206223e0cfdSZbigniew Bodek 	rv = bus_space_map(fdtbus_bs_tag, (bus_addr_t)MV_SCU_BASE,
207223e0cfdSZbigniew Bodek 	    MV_SCU_REGS_LEN, 0, &vaddr_scu);
208223e0cfdSZbigniew Bodek 	if (rv != 0)
209223e0cfdSZbigniew Bodek 		return (rv);
210223e0cfdSZbigniew Bodek 
211223e0cfdSZbigniew Bodek 	/* Enable SCU */
212223e0cfdSZbigniew Bodek 	val = bus_space_read_4(fdtbus_bs_tag, vaddr_scu, MV_SCU_REG_CTRL);
213bb98396bSZbigniew Bodek 	if (!(val & MV_SCU_ENABLE)) {
214bb98396bSZbigniew Bodek 		/* Enable SCU Speculative linefills to L2 */
215bb98396bSZbigniew Bodek 		val |= MV_SCU_SL_L2_ENABLE;
216bb98396bSZbigniew Bodek 
217223e0cfdSZbigniew Bodek 		bus_space_write_4(fdtbus_bs_tag, vaddr_scu, 0,
218223e0cfdSZbigniew Bodek 		    val | MV_SCU_ENABLE);
219bb98396bSZbigniew Bodek 	}
220223e0cfdSZbigniew Bodek 
221223e0cfdSZbigniew Bodek 	bus_space_unmap(fdtbus_bs_tag, vaddr_scu, MV_SCU_REGS_LEN);
222223e0cfdSZbigniew Bodek 	return (0);
223223e0cfdSZbigniew Bodek }
224