cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

phy-am654-serdes.c (23000B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * PCIe SERDES driver for AM654x SoC
      4 *
      5 * Copyright (C) 2018 - 2019 Texas Instruments Incorporated - http://www.ti.com/
      6 * Author: Kishon Vijay Abraham I <kishon@ti.com>
      7 */
      8
      9#include <dt-bindings/phy/phy.h>
     10#include <linux/clk.h>
     11#include <linux/clk-provider.h>
     12#include <linux/delay.h>
     13#include <linux/module.h>
     14#include <linux/mfd/syscon.h>
     15#include <linux/mux/consumer.h>
     16#include <linux/of_address.h>
     17#include <linux/phy/phy.h>
     18#include <linux/platform_device.h>
     19#include <linux/pm_runtime.h>
     20#include <linux/regmap.h>
     21
     22#define CMU_R004		0x4
     23#define CMU_R060		0x60
     24#define CMU_R07C		0x7c
     25#define CMU_R088		0x88
     26#define CMU_R0D0		0xd0
     27#define CMU_R0E8		0xe8
     28
     29#define LANE_R048		0x248
     30#define LANE_R058		0x258
     31#define LANE_R06c		0x26c
     32#define LANE_R070		0x270
     33#define LANE_R070		0x270
     34#define LANE_R19C		0x39c
     35
     36#define COMLANE_R004		0xa04
     37#define COMLANE_R138		0xb38
     38#define VERSION_VAL		0x70
     39
     40#define COMLANE_R190		0xb90
     41#define COMLANE_R194		0xb94
     42
     43#define COMRXEQ_R004		0x1404
     44#define COMRXEQ_R008		0x1408
     45#define COMRXEQ_R00C		0x140c
     46#define COMRXEQ_R014		0x1414
     47#define COMRXEQ_R018		0x1418
     48#define COMRXEQ_R01C		0x141c
     49#define COMRXEQ_R04C		0x144c
     50#define COMRXEQ_R088		0x1488
     51#define COMRXEQ_R094		0x1494
     52#define COMRXEQ_R098		0x1498
     53
     54#define SERDES_CTRL		0x1fd0
     55
     56#define WIZ_LANEXCTL_STS	0x1fe0
     57#define TX0_DISABLE_STATE	0x4
     58#define TX0_SLEEP_STATE		0x5
     59#define TX0_SNOOZE_STATE	0x6
     60#define TX0_ENABLE_STATE	0x7
     61
     62#define RX0_DISABLE_STATE	0x4
     63#define RX0_SLEEP_STATE		0x5
     64#define RX0_SNOOZE_STATE	0x6
     65#define RX0_ENABLE_STATE	0x7
     66
     67#define WIZ_PLL_CTRL		0x1ff4
     68#define PLL_DISABLE_STATE	0x4
     69#define PLL_SLEEP_STATE		0x5
     70#define PLL_SNOOZE_STATE	0x6
     71#define PLL_ENABLE_STATE	0x7
     72
     73#define PLL_LOCK_TIME		100000	/* in microseconds */
     74#define SLEEP_TIME		100	/* in microseconds */
     75
     76#define LANE_USB3		0x0
     77#define LANE_PCIE0_LANE0	0x1
     78
     79#define LANE_PCIE1_LANE0	0x0
     80#define LANE_PCIE0_LANE1	0x1
     81
     82#define SERDES_NUM_CLOCKS	3
     83
     84#define AM654_SERDES_CTRL_CLKSEL_MASK	GENMASK(7, 4)
     85#define AM654_SERDES_CTRL_CLKSEL_SHIFT	4
     86
     87struct serdes_am654_clk_mux {
     88	struct clk_hw	hw;
     89	struct regmap	*regmap;
     90	unsigned int	reg;
     91	int		clk_id;
     92	struct clk_init_data clk_data;
     93};
     94
     95#define to_serdes_am654_clk_mux(_hw)	\
     96		container_of(_hw, struct serdes_am654_clk_mux, hw)
     97
     98static const struct regmap_config serdes_am654_regmap_config = {
     99	.reg_bits = 32,
    100	.val_bits = 32,
    101	.reg_stride = 4,
    102	.fast_io = true,
    103	.max_register = 0x1ffc,
    104};
    105
    106enum serdes_am654_fields {
    107	/* CMU PLL Control */
    108	CMU_PLL_CTRL,
    109
    110	LANE_PLL_CTRL_RXEQ_RXIDLE,
    111
    112	/* CMU VCO bias current and VREG setting */
    113	AHB_PMA_CM_VCO_VBIAS_VREG,
    114	AHB_PMA_CM_VCO_BIAS_VREG,
    115
    116	AHB_PMA_CM_SR,
    117	AHB_SSC_GEN_Z_O_20_13,
    118
    119	/* AHB PMA Lane Configuration */
    120	AHB_PMA_LN_AGC_THSEL_VREGH,
    121
    122	/* AGC and Signal detect threshold for Gen3 */
    123	AHB_PMA_LN_GEN3_AGC_SD_THSEL,
    124
    125	AHB_PMA_LN_RX_SELR_GEN3,
    126	AHB_PMA_LN_TX_DRV,
    127
    128	/* CMU Master Reset */
    129	CMU_MASTER_CDN,
    130
    131	/* P2S ring buffer initial startup pointer difference */
    132	P2S_RBUF_PTR_DIFF,
    133
    134	CONFIG_VERSION,
    135
    136	/* Lane 1 Master Reset */
    137	L1_MASTER_CDN,
    138
    139	/* CMU OK Status */
    140	CMU_OK_I_0,
    141
    142	/* Mid-speed initial calibration control */
    143	COMRXEQ_MS_INIT_CTRL_7_0,
    144
    145	/* High-speed initial calibration control */
    146	COMRXEQ_HS_INIT_CAL_7_0,
    147
    148	/* Mid-speed recalibration control */
    149	COMRXEQ_MS_RECAL_CTRL_7_0,
    150
    151	/* High-speed recalibration control */
    152	COMRXEQ_HS_RECAL_CTRL_7_0,
    153
    154	/* ATT configuration */
    155	COMRXEQ_CSR_ATT_CONFIG,
    156
    157	/* Edge based boost adaptation window length */
    158	COMRXEQ_CSR_EBSTADAPT_WIN_LEN,
    159
    160	/* COMRXEQ control 3 & 4 */
    161	COMRXEQ_CTRL_3_4,
    162
    163	/* COMRXEQ control 14, 15 and 16*/
    164	COMRXEQ_CTRL_14_15_16,
    165
    166	/* Threshold for errors in pattern data  */
    167	COMRXEQ_CSR_DLEV_ERR_THRESH,
    168
    169	/* COMRXEQ control 25 */
    170	COMRXEQ_CTRL_25,
    171
    172	/* Mid-speed rate change calibration control */
    173	CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O,
    174
    175	/* High-speed rate change calibration control */
    176	COMRXEQ_HS_RCHANGE_CTRL_7_0,
    177
    178	/* Serdes reset */
    179	POR_EN,
    180
    181	/* Tx Enable Value */
    182	TX0_ENABLE,
    183
    184	/* Rx Enable Value */
    185	RX0_ENABLE,
    186
    187	/* PLL Enable Value */
    188	PLL_ENABLE,
    189
    190	/* PLL ready for use */
    191	PLL_OK,
    192
    193	/* sentinel */
    194	MAX_FIELDS
    195
    196};
    197
    198static const struct reg_field serdes_am654_reg_fields[] = {
    199	[CMU_PLL_CTRL]			= REG_FIELD(CMU_R004, 8, 15),
    200	[AHB_PMA_CM_VCO_VBIAS_VREG]	= REG_FIELD(CMU_R060, 8, 15),
    201	[CMU_MASTER_CDN]		= REG_FIELD(CMU_R07C, 24, 31),
    202	[AHB_PMA_CM_VCO_BIAS_VREG]	= REG_FIELD(CMU_R088, 24, 31),
    203	[AHB_PMA_CM_SR]			= REG_FIELD(CMU_R0D0, 24, 31),
    204	[AHB_SSC_GEN_Z_O_20_13]		= REG_FIELD(CMU_R0E8, 8, 15),
    205	[LANE_PLL_CTRL_RXEQ_RXIDLE]	= REG_FIELD(LANE_R048, 8, 15),
    206	[AHB_PMA_LN_AGC_THSEL_VREGH]	= REG_FIELD(LANE_R058, 16, 23),
    207	[AHB_PMA_LN_GEN3_AGC_SD_THSEL]	= REG_FIELD(LANE_R06c, 0, 7),
    208	[AHB_PMA_LN_RX_SELR_GEN3]	= REG_FIELD(LANE_R070, 16, 23),
    209	[AHB_PMA_LN_TX_DRV]		= REG_FIELD(LANE_R19C, 16, 23),
    210	[P2S_RBUF_PTR_DIFF]		= REG_FIELD(COMLANE_R004, 0, 7),
    211	[CONFIG_VERSION]		= REG_FIELD(COMLANE_R138, 16, 23),
    212	[L1_MASTER_CDN]			= REG_FIELD(COMLANE_R190, 8, 15),
    213	[CMU_OK_I_0]			= REG_FIELD(COMLANE_R194, 19, 19),
    214	[COMRXEQ_MS_INIT_CTRL_7_0]	= REG_FIELD(COMRXEQ_R004, 24, 31),
    215	[COMRXEQ_HS_INIT_CAL_7_0]	= REG_FIELD(COMRXEQ_R008, 0, 7),
    216	[COMRXEQ_MS_RECAL_CTRL_7_0]	= REG_FIELD(COMRXEQ_R00C, 8, 15),
    217	[COMRXEQ_HS_RECAL_CTRL_7_0]	= REG_FIELD(COMRXEQ_R00C, 16, 23),
    218	[COMRXEQ_CSR_ATT_CONFIG]	= REG_FIELD(COMRXEQ_R014, 16, 23),
    219	[COMRXEQ_CSR_EBSTADAPT_WIN_LEN]	= REG_FIELD(COMRXEQ_R018, 16, 23),
    220	[COMRXEQ_CTRL_3_4]		= REG_FIELD(COMRXEQ_R01C, 8, 15),
    221	[COMRXEQ_CTRL_14_15_16]		= REG_FIELD(COMRXEQ_R04C, 0, 7),
    222	[COMRXEQ_CSR_DLEV_ERR_THRESH]	= REG_FIELD(COMRXEQ_R088, 16, 23),
    223	[COMRXEQ_CTRL_25]		= REG_FIELD(COMRXEQ_R094, 24, 31),
    224	[CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O] = REG_FIELD(COMRXEQ_R098, 8, 15),
    225	[COMRXEQ_HS_RCHANGE_CTRL_7_0]	= REG_FIELD(COMRXEQ_R098, 16, 23),
    226	[POR_EN]			= REG_FIELD(SERDES_CTRL, 29, 29),
    227	[TX0_ENABLE]			= REG_FIELD(WIZ_LANEXCTL_STS, 29, 31),
    228	[RX0_ENABLE]			= REG_FIELD(WIZ_LANEXCTL_STS, 13, 15),
    229	[PLL_ENABLE]			= REG_FIELD(WIZ_PLL_CTRL, 29, 31),
    230	[PLL_OK]			= REG_FIELD(WIZ_PLL_CTRL, 28, 28),
    231};
    232
    233struct serdes_am654 {
    234	struct regmap		*regmap;
    235	struct regmap_field	*fields[MAX_FIELDS];
    236
    237	struct device		*dev;
    238	struct mux_control	*control;
    239	bool			busy;
    240	u32			type;
    241	struct device_node	*of_node;
    242	struct clk_onecell_data	clk_data;
    243	struct clk		*clks[SERDES_NUM_CLOCKS];
    244};
    245
    246static int serdes_am654_enable_pll(struct serdes_am654 *phy)
    247{
    248	int ret;
    249	u32 val;
    250
    251	ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_ENABLE_STATE);
    252	if (ret)
    253		return ret;
    254
    255	return regmap_field_read_poll_timeout(phy->fields[PLL_OK], val, val,
    256					      1000, PLL_LOCK_TIME);
    257}
    258
    259static void serdes_am654_disable_pll(struct serdes_am654 *phy)
    260{
    261	struct device *dev = phy->dev;
    262	int ret;
    263
    264	ret = regmap_field_write(phy->fields[PLL_ENABLE], PLL_DISABLE_STATE);
    265	if (ret)
    266		dev_err(dev, "Failed to disable PLL\n");
    267}
    268
    269static int serdes_am654_enable_txrx(struct serdes_am654 *phy)
    270{
    271	int ret = 0;
    272
    273	/* Enable TX */
    274	ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_ENABLE_STATE);
    275
    276	/* Enable RX */
    277	ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_ENABLE_STATE);
    278
    279	if (ret)
    280		return -EIO;
    281
    282	return 0;
    283}
    284
    285static int serdes_am654_disable_txrx(struct serdes_am654 *phy)
    286{
    287	int ret = 0;
    288
    289	/* Disable TX */
    290	ret |= regmap_field_write(phy->fields[TX0_ENABLE], TX0_DISABLE_STATE);
    291
    292	/* Disable RX */
    293	ret |= regmap_field_write(phy->fields[RX0_ENABLE], RX0_DISABLE_STATE);
    294
    295	if (ret)
    296		return -EIO;
    297
    298	return 0;
    299}
    300
    301static int serdes_am654_power_on(struct phy *x)
    302{
    303	struct serdes_am654 *phy = phy_get_drvdata(x);
    304	struct device *dev = phy->dev;
    305	int ret;
    306	u32 val;
    307
    308	ret = serdes_am654_enable_pll(phy);
    309	if (ret) {
    310		dev_err(dev, "Failed to enable PLL\n");
    311		return ret;
    312	}
    313
    314	ret = serdes_am654_enable_txrx(phy);
    315	if (ret) {
    316		dev_err(dev, "Failed to enable TX RX\n");
    317		return ret;
    318	}
    319
    320	return regmap_field_read_poll_timeout(phy->fields[CMU_OK_I_0], val,
    321					      val, SLEEP_TIME, PLL_LOCK_TIME);
    322}
    323
    324static int serdes_am654_power_off(struct phy *x)
    325{
    326	struct serdes_am654 *phy = phy_get_drvdata(x);
    327
    328	serdes_am654_disable_txrx(phy);
    329	serdes_am654_disable_pll(phy);
    330
    331	return 0;
    332}
    333
    334#define SERDES_AM654_CFG(offset, a, b, val) \
    335	regmap_update_bits(phy->regmap, (offset),\
    336			   GENMASK((a), (b)), (val) << (b))
    337
    338static int serdes_am654_usb3_init(struct serdes_am654 *phy)
    339{
    340	SERDES_AM654_CFG(0x0000, 31, 24, 0x17);
    341	SERDES_AM654_CFG(0x0004, 15, 8, 0x02);
    342	SERDES_AM654_CFG(0x0004, 7, 0, 0x0e);
    343	SERDES_AM654_CFG(0x0008, 23, 16, 0x2e);
    344	SERDES_AM654_CFG(0x0008, 31, 24, 0x2e);
    345	SERDES_AM654_CFG(0x0060, 7, 0, 0x4b);
    346	SERDES_AM654_CFG(0x0060, 15, 8, 0x98);
    347	SERDES_AM654_CFG(0x0060, 23, 16, 0x60);
    348	SERDES_AM654_CFG(0x00d0, 31, 24, 0x45);
    349	SERDES_AM654_CFG(0x00e8, 15, 8, 0x0e);
    350	SERDES_AM654_CFG(0x0220, 7, 0, 0x34);
    351	SERDES_AM654_CFG(0x0220, 15, 8, 0x34);
    352	SERDES_AM654_CFG(0x0220, 31, 24, 0x37);
    353	SERDES_AM654_CFG(0x0224, 7, 0, 0x37);
    354	SERDES_AM654_CFG(0x0224, 15, 8, 0x37);
    355	SERDES_AM654_CFG(0x0228, 23, 16, 0x37);
    356	SERDES_AM654_CFG(0x0228, 31, 24, 0x37);
    357	SERDES_AM654_CFG(0x022c, 7, 0, 0x37);
    358	SERDES_AM654_CFG(0x022c, 15, 8, 0x37);
    359	SERDES_AM654_CFG(0x0230, 15, 8, 0x2a);
    360	SERDES_AM654_CFG(0x0230, 23, 16, 0x2a);
    361	SERDES_AM654_CFG(0x0240, 23, 16, 0x10);
    362	SERDES_AM654_CFG(0x0240, 31, 24, 0x34);
    363	SERDES_AM654_CFG(0x0244, 7, 0, 0x40);
    364	SERDES_AM654_CFG(0x0244, 23, 16, 0x34);
    365	SERDES_AM654_CFG(0x0248, 15, 8, 0x0d);
    366	SERDES_AM654_CFG(0x0258, 15, 8, 0x16);
    367	SERDES_AM654_CFG(0x0258, 23, 16, 0x84);
    368	SERDES_AM654_CFG(0x0258, 31, 24, 0xf2);
    369	SERDES_AM654_CFG(0x025c, 7, 0, 0x21);
    370	SERDES_AM654_CFG(0x0260, 7, 0, 0x27);
    371	SERDES_AM654_CFG(0x0260, 15, 8, 0x04);
    372	SERDES_AM654_CFG(0x0268, 15, 8, 0x04);
    373	SERDES_AM654_CFG(0x0288, 15, 8, 0x2c);
    374	SERDES_AM654_CFG(0x0330, 31, 24, 0xa0);
    375	SERDES_AM654_CFG(0x0338, 23, 16, 0x03);
    376	SERDES_AM654_CFG(0x0338, 31, 24, 0x00);
    377	SERDES_AM654_CFG(0x033c, 7, 0, 0x00);
    378	SERDES_AM654_CFG(0x0344, 31, 24, 0x18);
    379	SERDES_AM654_CFG(0x034c, 7, 0, 0x18);
    380	SERDES_AM654_CFG(0x039c, 23, 16, 0x3b);
    381	SERDES_AM654_CFG(0x0a04, 7, 0, 0x03);
    382	SERDES_AM654_CFG(0x0a14, 31, 24, 0x3c);
    383	SERDES_AM654_CFG(0x0a18, 15, 8, 0x3c);
    384	SERDES_AM654_CFG(0x0a38, 7, 0, 0x3e);
    385	SERDES_AM654_CFG(0x0a38, 15, 8, 0x3e);
    386	SERDES_AM654_CFG(0x0ae0, 7, 0, 0x07);
    387	SERDES_AM654_CFG(0x0b6c, 23, 16, 0xcd);
    388	SERDES_AM654_CFG(0x0b6c, 31, 24, 0x04);
    389	SERDES_AM654_CFG(0x0b98, 23, 16, 0x03);
    390	SERDES_AM654_CFG(0x1400, 7, 0, 0x3f);
    391	SERDES_AM654_CFG(0x1404, 23, 16, 0x6f);
    392	SERDES_AM654_CFG(0x1404, 31, 24, 0x6f);
    393	SERDES_AM654_CFG(0x140c, 7, 0, 0x6f);
    394	SERDES_AM654_CFG(0x140c, 15, 8, 0x6f);
    395	SERDES_AM654_CFG(0x1410, 15, 8, 0x27);
    396	SERDES_AM654_CFG(0x1414, 7, 0, 0x0c);
    397	SERDES_AM654_CFG(0x1414, 23, 16, 0x07);
    398	SERDES_AM654_CFG(0x1418, 23, 16, 0x40);
    399	SERDES_AM654_CFG(0x141c, 7, 0, 0x00);
    400	SERDES_AM654_CFG(0x141c, 15, 8, 0x1f);
    401	SERDES_AM654_CFG(0x1428, 31, 24, 0x08);
    402	SERDES_AM654_CFG(0x1434, 31, 24, 0x00);
    403	SERDES_AM654_CFG(0x1444, 7, 0, 0x94);
    404	SERDES_AM654_CFG(0x1460, 31, 24, 0x7f);
    405	SERDES_AM654_CFG(0x1464, 7, 0, 0x43);
    406	SERDES_AM654_CFG(0x1464, 23, 16, 0x6f);
    407	SERDES_AM654_CFG(0x1464, 31, 24, 0x43);
    408	SERDES_AM654_CFG(0x1484, 23, 16, 0x8f);
    409	SERDES_AM654_CFG(0x1498, 7, 0, 0x4f);
    410	SERDES_AM654_CFG(0x1498, 23, 16, 0x4f);
    411	SERDES_AM654_CFG(0x007c, 31, 24, 0x0d);
    412	SERDES_AM654_CFG(0x0b90, 15, 8, 0x0f);
    413
    414	return 0;
    415}
    416
    417static int serdes_am654_pcie_init(struct serdes_am654 *phy)
    418{
    419	int ret = 0;
    420
    421	ret |= regmap_field_write(phy->fields[CMU_PLL_CTRL], 0x2);
    422	ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_VBIAS_VREG], 0x98);
    423	ret |= regmap_field_write(phy->fields[AHB_PMA_CM_VCO_BIAS_VREG], 0x98);
    424	ret |= regmap_field_write(phy->fields[AHB_PMA_CM_SR], 0x45);
    425	ret |= regmap_field_write(phy->fields[AHB_SSC_GEN_Z_O_20_13], 0xe);
    426	ret |= regmap_field_write(phy->fields[LANE_PLL_CTRL_RXEQ_RXIDLE], 0x5);
    427	ret |= regmap_field_write(phy->fields[AHB_PMA_LN_AGC_THSEL_VREGH], 0x83);
    428	ret |= regmap_field_write(phy->fields[AHB_PMA_LN_GEN3_AGC_SD_THSEL], 0x83);
    429	ret |= regmap_field_write(phy->fields[AHB_PMA_LN_RX_SELR_GEN3],	0x81);
    430	ret |= regmap_field_write(phy->fields[AHB_PMA_LN_TX_DRV], 0x3b);
    431	ret |= regmap_field_write(phy->fields[P2S_RBUF_PTR_DIFF], 0x3);
    432	ret |= regmap_field_write(phy->fields[CONFIG_VERSION], VERSION_VAL);
    433	ret |= regmap_field_write(phy->fields[COMRXEQ_MS_INIT_CTRL_7_0], 0xf);
    434	ret |= regmap_field_write(phy->fields[COMRXEQ_HS_INIT_CAL_7_0], 0x4f);
    435	ret |= regmap_field_write(phy->fields[COMRXEQ_MS_RECAL_CTRL_7_0], 0xf);
    436	ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RECAL_CTRL_7_0], 0x4f);
    437	ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_ATT_CONFIG], 0x7);
    438	ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_EBSTADAPT_WIN_LEN], 0x7f);
    439	ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_3_4], 0xf);
    440	ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_14_15_16], 0x9a);
    441	ret |= regmap_field_write(phy->fields[COMRXEQ_CSR_DLEV_ERR_THRESH], 0x32);
    442	ret |= regmap_field_write(phy->fields[COMRXEQ_CTRL_25], 0x80);
    443	ret |= regmap_field_write(phy->fields[CSR_RXEQ_RATE_CHANGE_CAL_RUN_RATE2_O], 0xf);
    444	ret |= regmap_field_write(phy->fields[COMRXEQ_HS_RCHANGE_CTRL_7_0], 0x4f);
    445	ret |= regmap_field_write(phy->fields[CMU_MASTER_CDN], 0x1);
    446	ret |= regmap_field_write(phy->fields[L1_MASTER_CDN], 0x2);
    447
    448	if (ret)
    449		return -EIO;
    450
    451	return 0;
    452}
    453
    454static int serdes_am654_init(struct phy *x)
    455{
    456	struct serdes_am654 *phy = phy_get_drvdata(x);
    457
    458	switch (phy->type) {
    459	case PHY_TYPE_PCIE:
    460		return serdes_am654_pcie_init(phy);
    461	case PHY_TYPE_USB3:
    462		return serdes_am654_usb3_init(phy);
    463	default:
    464		return -EINVAL;
    465	}
    466}
    467
    468static int serdes_am654_reset(struct phy *x)
    469{
    470	struct serdes_am654 *phy = phy_get_drvdata(x);
    471	int ret = 0;
    472
    473	serdes_am654_disable_pll(phy);
    474	serdes_am654_disable_txrx(phy);
    475
    476	ret |= regmap_field_write(phy->fields[POR_EN], 0x1);
    477
    478	mdelay(1);
    479
    480	ret |= regmap_field_write(phy->fields[POR_EN], 0x0);
    481
    482	if (ret)
    483		return -EIO;
    484
    485	return 0;
    486}
    487
    488static void serdes_am654_release(struct phy *x)
    489{
    490	struct serdes_am654 *phy = phy_get_drvdata(x);
    491
    492	phy->type = PHY_NONE;
    493	phy->busy = false;
    494	mux_control_deselect(phy->control);
    495}
    496
    497static struct phy *serdes_am654_xlate(struct device *dev,
    498				      struct of_phandle_args *args)
    499{
    500	struct serdes_am654 *am654_phy;
    501	struct phy *phy;
    502	int ret;
    503
    504	phy = of_phy_simple_xlate(dev, args);
    505	if (IS_ERR(phy))
    506		return phy;
    507
    508	am654_phy = phy_get_drvdata(phy);
    509	if (am654_phy->busy)
    510		return ERR_PTR(-EBUSY);
    511
    512	ret = mux_control_select(am654_phy->control, args->args[1]);
    513	if (ret) {
    514		dev_err(dev, "Failed to select SERDES Lane Function\n");
    515		return ERR_PTR(ret);
    516	}
    517
    518	am654_phy->busy = true;
    519	am654_phy->type = args->args[0];
    520
    521	return phy;
    522}
    523
    524static const struct phy_ops ops = {
    525	.reset		= serdes_am654_reset,
    526	.init		= serdes_am654_init,
    527	.power_on	= serdes_am654_power_on,
    528	.power_off	= serdes_am654_power_off,
    529	.release	= serdes_am654_release,
    530	.owner		= THIS_MODULE,
    531};
    532
    533#define SERDES_NUM_MUX_COMBINATIONS 16
    534
    535#define LICLK 0
    536#define EXT_REFCLK 1
    537#define RICLK 2
    538
    539static const int
    540serdes_am654_mux_table[SERDES_NUM_MUX_COMBINATIONS][SERDES_NUM_CLOCKS] = {
    541	/*
    542	 * Each combination maps to one of
    543	 * "Figure 12-1986. SerDes Reference Clock Distribution"
    544	 * in TRM.
    545	 */
    546	 /* Parent of CMU refclk, Left output, Right output
    547	  * either of EXT_REFCLK, LICLK, RICLK
    548	  */
    549	{ EXT_REFCLK, EXT_REFCLK, EXT_REFCLK },	/* 0000 */
    550	{ RICLK, EXT_REFCLK, EXT_REFCLK },	/* 0001 */
    551	{ EXT_REFCLK, RICLK, LICLK },		/* 0010 */
    552	{ RICLK, RICLK, EXT_REFCLK },		/* 0011 */
    553	{ LICLK, EXT_REFCLK, EXT_REFCLK },	/* 0100 */
    554	{ EXT_REFCLK, EXT_REFCLK, EXT_REFCLK },	/* 0101 */
    555	{ LICLK, RICLK, LICLK },		/* 0110 */
    556	{ EXT_REFCLK, RICLK, LICLK },		/* 0111 */
    557	{ EXT_REFCLK, EXT_REFCLK, LICLK },	/* 1000 */
    558	{ RICLK, EXT_REFCLK, LICLK },		/* 1001 */
    559	{ EXT_REFCLK, RICLK, EXT_REFCLK },	/* 1010 */
    560	{ RICLK, RICLK, EXT_REFCLK },		/* 1011 */
    561	{ LICLK, EXT_REFCLK, LICLK },		/* 1100 */
    562	{ EXT_REFCLK, EXT_REFCLK, LICLK },	/* 1101 */
    563	{ LICLK, RICLK, EXT_REFCLK },		/* 1110 */
    564	{ EXT_REFCLK, RICLK, EXT_REFCLK },	/* 1111 */
    565};
    566
    567static u8 serdes_am654_clk_mux_get_parent(struct clk_hw *hw)
    568{
    569	struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw);
    570	struct regmap *regmap = mux->regmap;
    571	unsigned int reg = mux->reg;
    572	unsigned int val;
    573
    574	regmap_read(regmap, reg, &val);
    575	val &= AM654_SERDES_CTRL_CLKSEL_MASK;
    576	val >>= AM654_SERDES_CTRL_CLKSEL_SHIFT;
    577
    578	return serdes_am654_mux_table[val][mux->clk_id];
    579}
    580
    581static int serdes_am654_clk_mux_set_parent(struct clk_hw *hw, u8 index)
    582{
    583	struct serdes_am654_clk_mux *mux = to_serdes_am654_clk_mux(hw);
    584	struct regmap *regmap = mux->regmap;
    585	const char *name = clk_hw_get_name(hw);
    586	unsigned int reg = mux->reg;
    587	int clk_id = mux->clk_id;
    588	int parents[SERDES_NUM_CLOCKS];
    589	const int *p;
    590	u32 val;
    591	int found, i;
    592	int ret;
    593
    594	/* get existing setting */
    595	regmap_read(regmap, reg, &val);
    596	val &= AM654_SERDES_CTRL_CLKSEL_MASK;
    597	val >>= AM654_SERDES_CTRL_CLKSEL_SHIFT;
    598
    599	for (i = 0; i < SERDES_NUM_CLOCKS; i++)
    600		parents[i] = serdes_am654_mux_table[val][i];
    601
    602	/* change parent of this clock. others left intact */
    603	parents[clk_id] = index;
    604
    605	/* Find the match */
    606	for (val = 0; val < SERDES_NUM_MUX_COMBINATIONS; val++) {
    607		p = serdes_am654_mux_table[val];
    608		found = 1;
    609		for (i = 0; i < SERDES_NUM_CLOCKS; i++) {
    610			if (parents[i] != p[i]) {
    611				found = 0;
    612				break;
    613			}
    614		}
    615
    616		if (found)
    617			break;
    618	}
    619
    620	if (!found) {
    621		/*
    622		 * This can never happen, unless we missed
    623		 * a valid combination in serdes_am654_mux_table.
    624		 */
    625		WARN(1, "Failed to find the parent of %s clock\n", name);
    626		return -EINVAL;
    627	}
    628
    629	val <<= AM654_SERDES_CTRL_CLKSEL_SHIFT;
    630	ret = regmap_update_bits(regmap, reg, AM654_SERDES_CTRL_CLKSEL_MASK,
    631				 val);
    632
    633	return ret;
    634}
    635
    636static const struct clk_ops serdes_am654_clk_mux_ops = {
    637	.set_parent = serdes_am654_clk_mux_set_parent,
    638	.get_parent = serdes_am654_clk_mux_get_parent,
    639};
    640
    641static int serdes_am654_clk_register(struct serdes_am654 *am654_phy,
    642				     const char *clock_name, int clock_num)
    643{
    644	struct device_node *node = am654_phy->of_node;
    645	struct device *dev = am654_phy->dev;
    646	struct serdes_am654_clk_mux *mux;
    647	struct device_node *regmap_node;
    648	const char **parent_names;
    649	struct clk_init_data *init;
    650	unsigned int num_parents;
    651	struct regmap *regmap;
    652	const __be32 *addr;
    653	unsigned int reg;
    654	struct clk *clk;
    655	int ret = 0;
    656
    657	mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
    658	if (!mux)
    659		return -ENOMEM;
    660
    661	init = &mux->clk_data;
    662
    663	regmap_node = of_parse_phandle(node, "ti,serdes-clk", 0);
    664	if (!regmap_node) {
    665		dev_err(dev, "Fail to get serdes-clk node\n");
    666		ret = -ENODEV;
    667		goto out_put_node;
    668	}
    669
    670	regmap = syscon_node_to_regmap(regmap_node->parent);
    671	if (IS_ERR(regmap)) {
    672		dev_err(dev, "Fail to get Syscon regmap\n");
    673		ret = PTR_ERR(regmap);
    674		goto out_put_node;
    675	}
    676
    677	num_parents = of_clk_get_parent_count(node);
    678	if (num_parents < 2) {
    679		dev_err(dev, "SERDES clock must have parents\n");
    680		ret = -EINVAL;
    681		goto out_put_node;
    682	}
    683
    684	parent_names = devm_kzalloc(dev, (sizeof(char *) * num_parents),
    685				    GFP_KERNEL);
    686	if (!parent_names) {
    687		ret = -ENOMEM;
    688		goto out_put_node;
    689	}
    690
    691	of_clk_parent_fill(node, parent_names, num_parents);
    692
    693	addr = of_get_address(regmap_node, 0, NULL, NULL);
    694	if (!addr) {
    695		ret = -EINVAL;
    696		goto out_put_node;
    697	}
    698
    699	reg = be32_to_cpu(*addr);
    700
    701	init->ops = &serdes_am654_clk_mux_ops;
    702	init->flags = CLK_SET_RATE_NO_REPARENT;
    703	init->parent_names = parent_names;
    704	init->num_parents = num_parents;
    705	init->name = clock_name;
    706
    707	mux->regmap = regmap;
    708	mux->reg = reg;
    709	mux->clk_id = clock_num;
    710	mux->hw.init = init;
    711
    712	clk = devm_clk_register(dev, &mux->hw);
    713	if (IS_ERR(clk)) {
    714		ret = PTR_ERR(clk);
    715		goto out_put_node;
    716	}
    717
    718	am654_phy->clks[clock_num] = clk;
    719
    720out_put_node:
    721	of_node_put(regmap_node);
    722	return ret;
    723}
    724
    725static const struct of_device_id serdes_am654_id_table[] = {
    726	{
    727		.compatible = "ti,phy-am654-serdes",
    728	},
    729	{}
    730};
    731MODULE_DEVICE_TABLE(of, serdes_am654_id_table);
    732
    733static int serdes_am654_regfield_init(struct serdes_am654 *am654_phy)
    734{
    735	struct regmap *regmap = am654_phy->regmap;
    736	struct device *dev = am654_phy->dev;
    737	int i;
    738
    739	for (i = 0; i < MAX_FIELDS; i++) {
    740		am654_phy->fields[i] = devm_regmap_field_alloc(dev,
    741							       regmap,
    742							       serdes_am654_reg_fields[i]);
    743		if (IS_ERR(am654_phy->fields[i])) {
    744			dev_err(dev, "Unable to allocate regmap field %d\n", i);
    745			return PTR_ERR(am654_phy->fields[i]);
    746		}
    747	}
    748
    749	return 0;
    750}
    751
    752static int serdes_am654_probe(struct platform_device *pdev)
    753{
    754	struct phy_provider *phy_provider;
    755	struct device *dev = &pdev->dev;
    756	struct device_node *node = dev->of_node;
    757	struct clk_onecell_data *clk_data;
    758	struct serdes_am654 *am654_phy;
    759	struct mux_control *control;
    760	const char *clock_name;
    761	struct regmap *regmap;
    762	void __iomem *base;
    763	struct phy *phy;
    764	int ret;
    765	int i;
    766
    767	am654_phy = devm_kzalloc(dev, sizeof(*am654_phy), GFP_KERNEL);
    768	if (!am654_phy)
    769		return -ENOMEM;
    770
    771	base = devm_platform_ioremap_resource(pdev, 0);
    772	if (IS_ERR(base))
    773		return PTR_ERR(base);
    774
    775	regmap = devm_regmap_init_mmio(dev, base, &serdes_am654_regmap_config);
    776	if (IS_ERR(regmap)) {
    777		dev_err(dev, "Failed to initialize regmap\n");
    778		return PTR_ERR(regmap);
    779	}
    780
    781	control = devm_mux_control_get(dev, NULL);
    782	if (IS_ERR(control))
    783		return PTR_ERR(control);
    784
    785	am654_phy->dev = dev;
    786	am654_phy->of_node = node;
    787	am654_phy->regmap = regmap;
    788	am654_phy->control = control;
    789	am654_phy->type = PHY_NONE;
    790
    791	ret = serdes_am654_regfield_init(am654_phy);
    792	if (ret) {
    793		dev_err(dev, "Failed to initialize regfields\n");
    794		return ret;
    795	}
    796
    797	platform_set_drvdata(pdev, am654_phy);
    798
    799	for (i = 0; i < SERDES_NUM_CLOCKS; i++) {
    800		ret = of_property_read_string_index(node, "clock-output-names",
    801						    i, &clock_name);
    802		if (ret) {
    803			dev_err(dev, "Failed to get clock name\n");
    804			return ret;
    805		}
    806
    807		ret = serdes_am654_clk_register(am654_phy, clock_name, i);
    808		if (ret) {
    809			dev_err(dev, "Failed to initialize clock %s\n",
    810				clock_name);
    811			return ret;
    812		}
    813	}
    814
    815	clk_data = &am654_phy->clk_data;
    816	clk_data->clks = am654_phy->clks;
    817	clk_data->clk_num = SERDES_NUM_CLOCKS;
    818	ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
    819	if (ret)
    820		return ret;
    821
    822	pm_runtime_enable(dev);
    823
    824	phy = devm_phy_create(dev, NULL, &ops);
    825	if (IS_ERR(phy)) {
    826		ret = PTR_ERR(phy);
    827		goto clk_err;
    828	}
    829
    830	phy_set_drvdata(phy, am654_phy);
    831	phy_provider = devm_of_phy_provider_register(dev, serdes_am654_xlate);
    832	if (IS_ERR(phy_provider)) {
    833		ret = PTR_ERR(phy_provider);
    834		goto clk_err;
    835	}
    836
    837	return 0;
    838
    839clk_err:
    840	of_clk_del_provider(node);
    841	pm_runtime_disable(dev);
    842	return ret;
    843}
    844
    845static int serdes_am654_remove(struct platform_device *pdev)
    846{
    847	struct serdes_am654 *am654_phy = platform_get_drvdata(pdev);
    848	struct device_node *node = am654_phy->of_node;
    849
    850	pm_runtime_disable(&pdev->dev);
    851	of_clk_del_provider(node);
    852
    853	return 0;
    854}
    855
    856static struct platform_driver serdes_am654_driver = {
    857	.probe		= serdes_am654_probe,
    858	.remove		= serdes_am654_remove,
    859	.driver		= {
    860		.name	= "phy-am654",
    861		.of_match_table = serdes_am654_id_table,
    862	},
    863};
    864module_platform_driver(serdes_am654_driver);
    865
    866MODULE_AUTHOR("Texas Instruments Inc.");
    867MODULE_DESCRIPTION("TI AM654x SERDES driver");
    868MODULE_LICENSE("GPL v2");