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