18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2003-2014 Broadcom Corporation
38c2ecf20Sopenharmony_ci * All Rights Reserved
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two
68c2ecf20Sopenharmony_ci * licenses.  You may choose to be licensed under the terms of the GNU
78c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file
88c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the Broadcom
98c2ecf20Sopenharmony_ci * license below:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
128c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
138c2ecf20Sopenharmony_ci * are met:
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
168c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
178c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
188c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in
198c2ecf20Sopenharmony_ci *    the documentation and/or other materials provided with the
208c2ecf20Sopenharmony_ci *    distribution.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
238c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
268c2ecf20Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
298c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
308c2ecf20Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
318c2ecf20Sopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
328c2ecf20Sopenharmony_ci * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
368c2ecf20Sopenharmony_ci#include <linux/kernel.h>
378c2ecf20Sopenharmony_ci#include <linux/delay.h>
388c2ecf20Sopenharmony_ci#include <linux/init.h>
398c2ecf20Sopenharmony_ci#include <linux/pci.h>
408c2ecf20Sopenharmony_ci#include <linux/irq.h>
418c2ecf20Sopenharmony_ci#include <linux/bitops.h>
428c2ecf20Sopenharmony_ci#include <linux/pci_ids.h>
438c2ecf20Sopenharmony_ci#include <linux/nodemask.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <asm/cpu.h>
468c2ecf20Sopenharmony_ci#include <asm/mipsregs.h>
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#include <asm/netlogic/common.h>
498c2ecf20Sopenharmony_ci#include <asm/netlogic/haldefs.h>
508c2ecf20Sopenharmony_ci#include <asm/netlogic/mips-extns.h>
518c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/xlp.h>
528c2ecf20Sopenharmony_ci#include <asm/netlogic/xlp-hal/iomap.h>
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define SATA_CTL		0x0
558c2ecf20Sopenharmony_ci#define SATA_STATUS		0x1 /* Status Reg */
568c2ecf20Sopenharmony_ci#define SATA_INT		0x2 /* Interrupt Reg */
578c2ecf20Sopenharmony_ci#define SATA_INT_MASK		0x3 /* Interrupt Mask Reg */
588c2ecf20Sopenharmony_ci#define SATA_BIU_TIMEOUT	0x4
598c2ecf20Sopenharmony_ci#define AXIWRSPERRLOG		0x5
608c2ecf20Sopenharmony_ci#define AXIRDSPERRLOG		0x6
618c2ecf20Sopenharmony_ci#define BiuTimeoutLow		0x7
628c2ecf20Sopenharmony_ci#define BiuTimeoutHi		0x8
638c2ecf20Sopenharmony_ci#define BiuSlvErLow		0x9
648c2ecf20Sopenharmony_ci#define BiuSlvErHi		0xa
658c2ecf20Sopenharmony_ci#define IO_CONFIG_SWAP_DIS	0xb
668c2ecf20Sopenharmony_ci#define CR_REG_TIMER		0xc
678c2ecf20Sopenharmony_ci#define CORE_ID			0xd
688c2ecf20Sopenharmony_ci#define AXI_SLAVE_OPT1		0xe
698c2ecf20Sopenharmony_ci#define PHY_MEM_ACCESS		0xf
708c2ecf20Sopenharmony_ci#define PHY0_CNTRL		0x10
718c2ecf20Sopenharmony_ci#define PHY0_STAT		0x11
728c2ecf20Sopenharmony_ci#define PHY0_RX_ALIGN		0x12
738c2ecf20Sopenharmony_ci#define PHY0_RX_EQ_LO		0x13
748c2ecf20Sopenharmony_ci#define PHY0_RX_EQ_HI		0x14
758c2ecf20Sopenharmony_ci#define PHY0_BIST_LOOP		0x15
768c2ecf20Sopenharmony_ci#define PHY1_CNTRL		0x16
778c2ecf20Sopenharmony_ci#define PHY1_STAT		0x17
788c2ecf20Sopenharmony_ci#define PHY1_RX_ALIGN		0x18
798c2ecf20Sopenharmony_ci#define PHY1_RX_EQ_LO		0x19
808c2ecf20Sopenharmony_ci#define PHY1_RX_EQ_HI		0x1a
818c2ecf20Sopenharmony_ci#define PHY1_BIST_LOOP		0x1b
828c2ecf20Sopenharmony_ci#define RdExBase		0x1c
838c2ecf20Sopenharmony_ci#define RdExLimit		0x1d
848c2ecf20Sopenharmony_ci#define CacheAllocBase		0x1e
858c2ecf20Sopenharmony_ci#define CacheAllocLimit		0x1f
868c2ecf20Sopenharmony_ci#define BiuSlaveCmdGstNum	0x20
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/*SATA_CTL Bits */
898c2ecf20Sopenharmony_ci#define SATA_RST_N		BIT(0)  /* Active low reset sata_core phy */
908c2ecf20Sopenharmony_ci#define SataCtlReserve0		BIT(1)
918c2ecf20Sopenharmony_ci#define M_CSYSREQ		BIT(2)  /* AXI master low power, not used */
928c2ecf20Sopenharmony_ci#define S_CSYSREQ		BIT(3)  /* AXI slave low power, not used */
938c2ecf20Sopenharmony_ci#define P0_CP_DET		BIT(8)  /* Reserved, bring in from pad */
948c2ecf20Sopenharmony_ci#define P0_MP_SW		BIT(9)  /* Mech Switch */
958c2ecf20Sopenharmony_ci#define P0_DISABLE		BIT(10) /* disable p0 */
968c2ecf20Sopenharmony_ci#define P0_ACT_LED_EN		BIT(11) /* Active LED enable */
978c2ecf20Sopenharmony_ci#define P0_IRST_HARD_SYNTH	BIT(12) /* PHY hard synth reset */
988c2ecf20Sopenharmony_ci#define P0_IRST_HARD_TXRX	BIT(13) /* PHY lane hard reset */
998c2ecf20Sopenharmony_ci#define P0_IRST_POR		BIT(14) /* PHY power on reset*/
1008c2ecf20Sopenharmony_ci#define P0_IPDTXL		BIT(15) /* PHY Tx lane dis/power down */
1018c2ecf20Sopenharmony_ci#define P0_IPDRXL		BIT(16) /* PHY Rx lane dis/power down */
1028c2ecf20Sopenharmony_ci#define P0_IPDIPDMSYNTH		BIT(17) /* PHY synthesizer dis/porwer down */
1038c2ecf20Sopenharmony_ci#define P0_CP_POD_EN		BIT(18) /* CP_POD enable */
1048c2ecf20Sopenharmony_ci#define P0_AT_BYPASS		BIT(19) /* P0 address translation by pass */
1058c2ecf20Sopenharmony_ci#define P1_CP_DET		BIT(20) /* Reserved,Cold Detect */
1068c2ecf20Sopenharmony_ci#define P1_MP_SW		BIT(21) /* Mech Switch */
1078c2ecf20Sopenharmony_ci#define P1_DISABLE		BIT(22) /* disable p1 */
1088c2ecf20Sopenharmony_ci#define P1_ACT_LED_EN		BIT(23) /* Active LED enable */
1098c2ecf20Sopenharmony_ci#define P1_IRST_HARD_SYNTH	BIT(24) /* PHY hard synth reset */
1108c2ecf20Sopenharmony_ci#define P1_IRST_HARD_TXRX	BIT(25) /* PHY lane hard reset */
1118c2ecf20Sopenharmony_ci#define P1_IRST_POR		BIT(26) /* PHY power on reset*/
1128c2ecf20Sopenharmony_ci#define P1_IPDTXL		BIT(27) /* PHY Tx lane dis/porwer down */
1138c2ecf20Sopenharmony_ci#define P1_IPDRXL		BIT(28) /* PHY Rx lane dis/porwer down */
1148c2ecf20Sopenharmony_ci#define P1_IPDIPDMSYNTH		BIT(29) /* PHY synthesizer dis/porwer down */
1158c2ecf20Sopenharmony_ci#define P1_CP_POD_EN		BIT(30)
1168c2ecf20Sopenharmony_ci#define P1_AT_BYPASS		BIT(31) /* P1 address translation by pass */
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/* Status register */
1198c2ecf20Sopenharmony_ci#define M_CACTIVE		BIT(0)  /* m_cactive, not used */
1208c2ecf20Sopenharmony_ci#define S_CACTIVE		BIT(1)  /* s_cactive, not used */
1218c2ecf20Sopenharmony_ci#define P0_PHY_READY		BIT(8)  /* phy is ready */
1228c2ecf20Sopenharmony_ci#define P0_CP_POD		BIT(9)  /* Cold PowerOn */
1238c2ecf20Sopenharmony_ci#define P0_SLUMBER		BIT(10) /* power mode slumber */
1248c2ecf20Sopenharmony_ci#define P0_PATIAL		BIT(11) /* power mode patial */
1258c2ecf20Sopenharmony_ci#define P0_PHY_SIG_DET		BIT(12) /* phy dignal detect */
1268c2ecf20Sopenharmony_ci#define P0_PHY_CALI		BIT(13) /* phy calibration done */
1278c2ecf20Sopenharmony_ci#define P1_PHY_READY		BIT(16) /* phy is ready */
1288c2ecf20Sopenharmony_ci#define P1_CP_POD		BIT(17) /* Cold PowerOn */
1298c2ecf20Sopenharmony_ci#define P1_SLUMBER		BIT(18) /* power mode slumber */
1308c2ecf20Sopenharmony_ci#define P1_PATIAL		BIT(19) /* power mode patial */
1318c2ecf20Sopenharmony_ci#define P1_PHY_SIG_DET		BIT(20) /* phy dignal detect */
1328c2ecf20Sopenharmony_ci#define P1_PHY_CALI		BIT(21) /* phy calibration done */
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/* SATA CR_REG_TIMER bits */
1358c2ecf20Sopenharmony_ci#define CR_TIME_SCALE		(0x1000 << 0)
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci/* SATA PHY specific registers start and end address */
1388c2ecf20Sopenharmony_ci#define RXCDRCALFOSC0		0x0065
1398c2ecf20Sopenharmony_ci#define CALDUTY			0x006e
1408c2ecf20Sopenharmony_ci#define RXDPIF			0x8065
1418c2ecf20Sopenharmony_ci#define PPMDRIFTMAX_HI		0x80A4
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci#define nlm_read_sata_reg(b, r)		nlm_read_reg(b, r)
1448c2ecf20Sopenharmony_ci#define nlm_write_sata_reg(b, r, v)	nlm_write_reg(b, r, v)
1458c2ecf20Sopenharmony_ci#define nlm_get_sata_pcibase(node)	\
1468c2ecf20Sopenharmony_ci		nlm_pcicfg_base(XLP9XX_IO_SATA_OFFSET(node))
1478c2ecf20Sopenharmony_ci#define nlm_get_sata_regbase(node)	\
1488c2ecf20Sopenharmony_ci		(nlm_get_sata_pcibase(node) + 0x100)
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci/* SATA PHY config for register block 1 0x0065 .. 0x006e */
1518c2ecf20Sopenharmony_cistatic const u8 sata_phy_config1[]  = {
1528c2ecf20Sopenharmony_ci	0xC9, 0xC9, 0x07, 0x07, 0x18, 0x18, 0x01, 0x01, 0x22, 0x00
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/* SATA PHY config for register block 2 0x8065 .. 0x80A4 */
1568c2ecf20Sopenharmony_cistatic const u8 sata_phy_config2[]  = {
1578c2ecf20Sopenharmony_ci	0xAA, 0x00, 0x4C, 0xC9, 0xC9, 0x07, 0x07, 0x18,
1588c2ecf20Sopenharmony_ci	0x18, 0x05, 0x0C, 0x10, 0x00, 0x10, 0x00, 0xFF,
1598c2ecf20Sopenharmony_ci	0xCF, 0xF7, 0xE1, 0xF5, 0xFD, 0xFD, 0xFF, 0xFF,
1608c2ecf20Sopenharmony_ci	0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5, 0xFD, 0xFD,
1618c2ecf20Sopenharmony_ci	0xF5, 0xF5, 0xFF, 0xFF, 0xE3, 0xE7, 0xDB, 0xF5,
1628c2ecf20Sopenharmony_ci	0xFD, 0xFD, 0xF5, 0xF5, 0xFF, 0xFF, 0xFF, 0xF5,
1638c2ecf20Sopenharmony_ci	0x3F, 0x00, 0x32, 0x00, 0x03, 0x01, 0x05, 0x05,
1648c2ecf20Sopenharmony_ci	0x04, 0x00, 0x00, 0x08, 0x04, 0x00, 0x00, 0x04,
1658c2ecf20Sopenharmony_ci};
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciconst int sata_phy_debug = 0;	/* set to verify PHY writes */
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic void sata_clear_glue_reg(u64 regbase, u32 off, u32 bit)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	u32 reg_val;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	reg_val = nlm_read_sata_reg(regbase, off);
1748c2ecf20Sopenharmony_ci	nlm_write_sata_reg(regbase, off, (reg_val & ~bit));
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic void sata_set_glue_reg(u64 regbase, u32 off, u32 bit)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	u32 reg_val;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	reg_val = nlm_read_sata_reg(regbase, off);
1828c2ecf20Sopenharmony_ci	nlm_write_sata_reg(regbase, off, (reg_val | bit));
1838c2ecf20Sopenharmony_ci}
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_cistatic void write_phy_reg(u64 regbase, u32 addr, u32 physel, u8 data)
1868c2ecf20Sopenharmony_ci{
1878c2ecf20Sopenharmony_ci	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
1888c2ecf20Sopenharmony_ci		(1u << 31) | (physel << 24) | (data << 16) | addr);
1898c2ecf20Sopenharmony_ci	udelay(850);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic u8 read_phy_reg(u64 regbase, u32 addr, u32 physel)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	u32 val;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	nlm_write_sata_reg(regbase, PHY_MEM_ACCESS,
1978c2ecf20Sopenharmony_ci		(0 << 31) | (physel << 24) | (0 << 16) | addr);
1988c2ecf20Sopenharmony_ci	udelay(850);
1998c2ecf20Sopenharmony_ci	val = nlm_read_sata_reg(regbase, PHY_MEM_ACCESS);
2008c2ecf20Sopenharmony_ci	return (val >> 16) & 0xff;
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void config_sata_phy(u64 regbase)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	u32 port, i, reg;
2068c2ecf20Sopenharmony_ci	u8 val;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	for (port = 0; port < 2; port++) {
2098c2ecf20Sopenharmony_ci		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
2108c2ecf20Sopenharmony_ci			write_phy_reg(regbase, reg, port, sata_phy_config1[i]);
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
2138c2ecf20Sopenharmony_ci			write_phy_reg(regbase, reg, port, sata_phy_config2[i]);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci		/* Fix for PHY link up failures at lower temperatures */
2168c2ecf20Sopenharmony_ci		write_phy_reg(regbase, 0x800F, port, 0x1f);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci		val = read_phy_reg(regbase, 0x0029, port);
2198c2ecf20Sopenharmony_ci		write_phy_reg(regbase, 0x0029, port, val | (0x7 << 1));
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		val = read_phy_reg(regbase, 0x0056, port);
2228c2ecf20Sopenharmony_ci		write_phy_reg(regbase, 0x0056, port, val & ~(1 << 3));
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		val = read_phy_reg(regbase, 0x0018, port);
2258c2ecf20Sopenharmony_ci		write_phy_reg(regbase, 0x0018, port, val & ~(0x7 << 0));
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic void check_phy_register(u64 regbase, u32 addr, u32 physel, u8 xdata)
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	u8 data;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	data = read_phy_reg(regbase, addr, physel);
2348c2ecf20Sopenharmony_ci	pr_info("PHY read addr = 0x%x physel = %d data = 0x%x %s\n",
2358c2ecf20Sopenharmony_ci		addr, physel, data, data == xdata ? "TRUE" : "FALSE");
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic void verify_sata_phy_config(u64 regbase)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	u32 port, i, reg;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	for (port = 0; port < 2; port++) {
2438c2ecf20Sopenharmony_ci		for (i = 0, reg = RXCDRCALFOSC0; reg <= CALDUTY; reg++, i++)
2448c2ecf20Sopenharmony_ci			check_phy_register(regbase, reg, port,
2458c2ecf20Sopenharmony_ci						sata_phy_config1[i]);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci		for (i = 0, reg = RXDPIF; reg <= PPMDRIFTMAX_HI; reg++, i++)
2488c2ecf20Sopenharmony_ci			check_phy_register(regbase, reg, port,
2498c2ecf20Sopenharmony_ci						sata_phy_config2[i]);
2508c2ecf20Sopenharmony_ci	}
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic void nlm_sata_firmware_init(int node)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	u32 reg_val;
2568c2ecf20Sopenharmony_ci	u64 regbase;
2578c2ecf20Sopenharmony_ci	int n;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	pr_info("Initializing XLP9XX On-chip AHCI...\n");
2608c2ecf20Sopenharmony_ci	regbase = nlm_get_sata_regbase(node);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	/* Reset port0 */
2638c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
2648c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
2658c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
2668c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
2678c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
2688c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/* port1 */
2718c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
2728c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
2738c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
2748c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
2758c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
2768c2ecf20Sopenharmony_ci	sata_clear_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
2778c2ecf20Sopenharmony_ci	udelay(300);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	/* Set PHY */
2808c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDTXL);
2818c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDRXL);
2828c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IPDIPDMSYNTH);
2838c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDTXL);
2848c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDRXL);
2858c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IPDIPDMSYNTH);
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	udelay(1000);
2888c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_POR);
2898c2ecf20Sopenharmony_ci	udelay(1000);
2908c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_POR);
2918c2ecf20Sopenharmony_ci	udelay(1000);
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	/* setup PHY */
2948c2ecf20Sopenharmony_ci	config_sata_phy(regbase);
2958c2ecf20Sopenharmony_ci	if (sata_phy_debug)
2968c2ecf20Sopenharmony_ci		verify_sata_phy_config(regbase);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	udelay(1000);
2998c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_TXRX);
3008c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P0_IRST_HARD_SYNTH);
3018c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_TXRX);
3028c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, P1_IRST_HARD_SYNTH);
3038c2ecf20Sopenharmony_ci	udelay(300);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	/* Override reset in serial PHY mode */
3068c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, CR_REG_TIMER, CR_TIME_SCALE);
3078c2ecf20Sopenharmony_ci	/* Set reset SATA */
3088c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, SATA_RST_N);
3098c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, M_CSYSREQ);
3108c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_CTL, S_CSYSREQ);
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	pr_debug("Waiting for PHYs to come up.\n");
3138c2ecf20Sopenharmony_ci	n = 10000;
3148c2ecf20Sopenharmony_ci	do {
3158c2ecf20Sopenharmony_ci		reg_val = nlm_read_sata_reg(regbase, SATA_STATUS);
3168c2ecf20Sopenharmony_ci		if ((reg_val & P1_PHY_READY) && (reg_val & P0_PHY_READY))
3178c2ecf20Sopenharmony_ci			break;
3188c2ecf20Sopenharmony_ci		udelay(10);
3198c2ecf20Sopenharmony_ci	} while (--n > 0);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	if (reg_val  & P0_PHY_READY)
3228c2ecf20Sopenharmony_ci		pr_info("PHY0 is up.\n");
3238c2ecf20Sopenharmony_ci	else
3248c2ecf20Sopenharmony_ci		pr_info("PHY0 is down.\n");
3258c2ecf20Sopenharmony_ci	if (reg_val  & P1_PHY_READY)
3268c2ecf20Sopenharmony_ci		pr_info("PHY1 is up.\n");
3278c2ecf20Sopenharmony_ci	else
3288c2ecf20Sopenharmony_ci		pr_info("PHY1 is down.\n");
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	pr_info("XLP AHCI Init Done.\n");
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic int __init nlm_ahci_init(void)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	int node;
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	if (!cpu_is_xlp9xx())
3388c2ecf20Sopenharmony_ci		return 0;
3398c2ecf20Sopenharmony_ci	for (node = 0; node < NLM_NR_NODES; node++)
3408c2ecf20Sopenharmony_ci		if (nlm_node_present(node))
3418c2ecf20Sopenharmony_ci			nlm_sata_firmware_init(node);
3428c2ecf20Sopenharmony_ci	return 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void nlm_sata_intr_ack(struct irq_data *data)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	u64 regbase;
3488c2ecf20Sopenharmony_ci	u32 val;
3498c2ecf20Sopenharmony_ci	int node;
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	node = data->irq / NLM_IRQS_PER_NODE;
3528c2ecf20Sopenharmony_ci	regbase = nlm_get_sata_regbase(node);
3538c2ecf20Sopenharmony_ci	val = nlm_read_sata_reg(regbase, SATA_INT);
3548c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_INT, val);
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_cistatic void nlm_sata_fixup_bar(struct pci_dev *dev)
3588c2ecf20Sopenharmony_ci{
3598c2ecf20Sopenharmony_ci	dev->resource[5] = dev->resource[0];
3608c2ecf20Sopenharmony_ci	memset(&dev->resource[0], 0, sizeof(dev->resource[0]));
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic void nlm_sata_fixup_final(struct pci_dev *dev)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	u32 val;
3668c2ecf20Sopenharmony_ci	u64 regbase;
3678c2ecf20Sopenharmony_ci	int node;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	/* Find end bridge function to find node */
3708c2ecf20Sopenharmony_ci	node = xlp_socdev_to_node(dev);
3718c2ecf20Sopenharmony_ci	regbase = nlm_get_sata_regbase(node);
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	/* clear pending interrupts and then enable them */
3748c2ecf20Sopenharmony_ci	val = nlm_read_sata_reg(regbase, SATA_INT);
3758c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_INT, val);
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/* Enable only the core interrupt */
3788c2ecf20Sopenharmony_ci	sata_set_glue_reg(regbase, SATA_INT_MASK, 0x1);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	dev->irq = nlm_irq_to_xirq(node, PIC_SATA_IRQ);
3818c2ecf20Sopenharmony_ci	nlm_set_pic_extra_ack(node, PIC_SATA_IRQ, nlm_sata_intr_ack);
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ciarch_initcall(nlm_ahci_init);
3858c2ecf20Sopenharmony_ci
3868c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
3878c2ecf20Sopenharmony_ci		nlm_sata_fixup_bar);
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_XLP9XX_SATA,
3908c2ecf20Sopenharmony_ci		nlm_sata_fixup_final);
391