1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2018
4  * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
5  *
6  * base on the MPC83xx serdes initialization, which is
7  *
8  * Copyright 2007,2011 Freescale Semiconductor, Inc.
9  * Copyright (C) 2008 MontaVista Software, Inc.
10  */
11 
12 #include <common.h>
13 #include <dm.h>
14 #include <log.h>
15 #include <mapmem.h>
16 #include <misc.h>
17 #include <linux/delay.h>
18 
19 #include "mpc83xx_serdes.h"
20 
21 /**
22  * struct mpc83xx_serdes_priv - Private structure for MPC83xx serdes
23  * @regs:  The device's register map
24  * @rfcks: Variable to keep the serdes reference clock selection set during
25  *	   initialization in (is or'd to every value written to SRDSCR4)
26  */
27 struct mpc83xx_serdes_priv {
28 	struct mpc83xx_serdes_regs *regs;
29 	u32 rfcks;
30 };
31 
32 /**
33  * setup_sata() - Configure the SerDes device to SATA mode
34  * @dev: The device to configure
35  */
setup_sata(struct udevice * dev)36 static void setup_sata(struct udevice *dev)
37 {
38 	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
39 
40 	/* Set and clear reset bits */
41 	setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
42 	udelay(1000);
43 	clrbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_SATA_RESET);
44 
45 	/* Configure SRDSCR0 */
46 	clrsetbits_be32(&priv->regs->srdscr0,
47 			SRDSCR0_TXEQA_MASK | SRDSCR0_TXEQE_MASK,
48 			SRDSCR0_TXEQA_SATA | SRDSCR0_TXEQE_SATA);
49 
50 	/* Configure SRDSCR1 */
51 	clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
52 
53 	/* Configure SRDSCR2 */
54 	clrsetbits_be32(&priv->regs->srdscr2,
55 			SRDSCR2_SEIC_MASK,
56 			SRDSCR2_SEIC_SATA);
57 
58 	/* Configure SRDSCR3 */
59 	out_be32(&priv->regs->srdscr3,
60 		 SRDSCR3_KFR_SATA | SRDSCR3_KPH_SATA |
61 		 SRDSCR3_SDFM_SATA_PEX | SRDSCR3_SDTXL_SATA);
62 
63 	/* Configure SRDSCR4 */
64 	out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SATA);
65 }
66 
67 /**
68  * setup_pex() - Configure the SerDes device to PCI Express mode
69  * @dev:  The device to configure
70  * @type: The PCI Express type to configure for (x1 or x2)
71  */
setup_pex(struct udevice * dev,enum pex_type type)72 static void setup_pex(struct udevice *dev, enum pex_type type)
73 {
74 	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
75 
76 	/* Configure SRDSCR1 */
77 	setbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
78 
79 	/* Configure SRDSCR2 */
80 	clrsetbits_be32(&priv->regs->srdscr2,
81 			SRDSCR2_SEIC_MASK,
82 			SRDSCR2_SEIC_PEX);
83 
84 	/* Configure SRDSCR3 */
85 	out_be32(&priv->regs->srdscr3, SRDSCR3_SDFM_SATA_PEX);
86 
87 	/* Configure SRDSCR4 */
88 	if (type == PEX_X2)
89 		out_be32(&priv->regs->srdscr4,
90 			 priv->rfcks | SRDSCR4_PROT_PEX | SRDSCR4_PLANE_X2);
91 	else
92 		out_be32(&priv->regs->srdscr4,
93 			 priv->rfcks | SRDSCR4_PROT_PEX);
94 }
95 
96 /**
97  * setup_sgmii() - Configure the SerDes device to SGMII mode
98  * @dev: The device to configure
99  */
setup_sgmii(struct udevice * dev)100 static void setup_sgmii(struct udevice *dev)
101 {
102 	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
103 
104 	/* Configure SRDSCR1 */
105 	clrbits_be32(&priv->regs->srdscr1, SRDSCR1_PLLBW);
106 
107 	/* Configure SRDSCR2 */
108 	clrsetbits_be32(&priv->regs->srdscr2,
109 			SRDSCR2_SEIC_MASK,
110 			SRDSCR2_SEIC_SGMII);
111 
112 	/* Configure SRDSCR3 */
113 	out_be32(&priv->regs->srdscr3, 0);
114 
115 	/* Configure SRDSCR4 */
116 	out_be32(&priv->regs->srdscr4, priv->rfcks | SRDSCR4_PROT_SGMII);
117 }
118 
mpc83xx_serdes_probe(struct udevice * dev)119 static int mpc83xx_serdes_probe(struct udevice *dev)
120 {
121 	struct mpc83xx_serdes_priv *priv = dev_get_priv(dev);
122 	bool vdd;
123 	const char *proto;
124 
125 	priv->regs = map_sysmem(dev_read_addr(dev),
126 				sizeof(struct mpc83xx_serdes_regs));
127 
128 	switch (dev_read_u32_default(dev, "serdes-clk", -1)) {
129 	case 100:
130 		priv->rfcks = SRDSCR4_RFCKS_100;
131 		break;
132 	case 125:
133 		priv->rfcks = SRDSCR4_RFCKS_125;
134 		break;
135 	case 150:
136 		priv->rfcks = SRDSCR4_RFCKS_150;
137 		break;
138 	default:
139 		debug("%s: Could not read serdes clock value\n", dev->name);
140 		return -EINVAL;
141 	}
142 
143 	vdd = dev_read_bool(dev, "vdd");
144 
145 	/* 1.0V corevdd */
146 	if (vdd) {
147 		/* DPPE/DPPA = 0 */
148 		clrbits_be32(&priv->regs->srdscr0, SRDSCR0_DPP_1V2);
149 
150 		/* VDD = 0 */
151 		clrbits_be32(&priv->regs->srdscr0, SRDSCR2_VDD_1V2);
152 	}
153 
154 	proto = dev_read_string(dev, "proto");
155 
156 	/* protocol specific configuration */
157 	if (!strcmp(proto, "sata")) {
158 		setup_sata(dev);
159 	} else if (!strcmp(proto, "pex")) {
160 		setup_pex(dev, PEX_X1);
161 	} else if (!strcmp(proto, "pex-x2")) {
162 		setup_pex(dev, PEX_X2);
163 	} else if (!strcmp(proto, "sgmii")) {
164 		setup_sgmii(dev);
165 	} else {
166 		debug("%s: Invalid protocol value %s\n", dev->name, proto);
167 		return -EINVAL;
168 	}
169 
170 	/* Do a software reset */
171 	setbits_be32(&priv->regs->srdsrstctl, SRDSRSTCTL_RST);
172 
173 	return 0;
174 }
175 
176 static const struct udevice_id mpc83xx_serdes_ids[] = {
177 	{ .compatible = "fsl,mpc83xx-serdes" },
178 	{ }
179 };
180 
181 U_BOOT_DRIVER(mpc83xx_serdes) = {
182 	.name           = "mpc83xx_serdes",
183 	.id             = UCLASS_MISC,
184 	.of_match       = mpc83xx_serdes_ids,
185 	.probe          = mpc83xx_serdes_probe,
186 	.priv_auto	= sizeof(struct mpc83xx_serdes_priv),
187 };
188