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-exynos4x12-usb2.c (10581B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
      4 *
      5 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
      6 * Author: Kamil Debski <k.debski@samsung.com>
      7 */
      8
      9#include <linux/delay.h>
     10#include <linux/io.h>
     11#include <linux/phy/phy.h>
     12#include <linux/regmap.h>
     13#include "phy-samsung-usb2.h"
     14
     15/* Exynos USB PHY registers */
     16
     17/* PHY power control */
     18#define EXYNOS_4x12_UPHYPWR			0x0
     19
     20#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND	BIT(0)
     21#define EXYNOS_4x12_UPHYPWR_PHY0_PWR		BIT(3)
     22#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR	BIT(4)
     23#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP		BIT(5)
     24#define EXYNOS_4x12_UPHYPWR_PHY0 ( \
     25	EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
     26	EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
     27	EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
     28	EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
     29
     30#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND	BIT(6)
     31#define EXYNOS_4x12_UPHYPWR_PHY1_PWR		BIT(7)
     32#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP		BIT(8)
     33#define EXYNOS_4x12_UPHYPWR_PHY1 ( \
     34	EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
     35	EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
     36	EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
     37
     38#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND	BIT(9)
     39#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR		BIT(10)
     40#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP		BIT(11)
     41#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
     42	EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
     43	EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
     44	EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
     45
     46#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND	BIT(12)
     47#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR		BIT(13)
     48#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP		BIT(14)
     49#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
     50	EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
     51	EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
     52	EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
     53
     54/* PHY clock control */
     55#define EXYNOS_4x12_UPHYCLK			0x4
     56
     57#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK	(0x7 << 0)
     58#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET	0
     59#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6	(0x0 << 0)
     60#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ	(0x1 << 0)
     61#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ	(0x2 << 0)
     62#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2	(0x3 << 0)
     63#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ	(0x4 << 0)
     64#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ	(0x5 << 0)
     65#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ	(0x7 << 0)
     66
     67#define EXYNOS_3250_UPHYCLK_REFCLKSEL		(0x2 << 8)
     68
     69#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP	BIT(3)
     70#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON	BIT(4)
     71#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON	BIT(7)
     72
     73#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK	(0x7f << 10)
     74#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET  10
     75#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ	(0x24 << 10)
     76#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ	(0x1c << 10)
     77#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ	(0x1a << 10)
     78#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2	(0x15 << 10)
     79#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ	(0x14 << 10)
     80
     81/* PHY reset control */
     82#define EXYNOS_4x12_UPHYRST			0x8
     83
     84#define EXYNOS_4x12_URSTCON_PHY0		BIT(0)
     85#define EXYNOS_4x12_URSTCON_OTG_HLINK		BIT(1)
     86#define EXYNOS_4x12_URSTCON_OTG_PHYLINK		BIT(2)
     87#define EXYNOS_4x12_URSTCON_HOST_PHY		BIT(3)
     88/* The following bit defines are presented in the
     89 * order taken from the Exynos4412 reference manual.
     90 *
     91 * During experiments with the hardware and debugging
     92 * it was determined that the hardware behaves contrary
     93 * to the manual.
     94 *
     95 * The following bit values were chaned accordingly to the
     96 * results of real hardware experiments.
     97 */
     98#define EXYNOS_4x12_URSTCON_PHY1		BIT(4)
     99#define EXYNOS_4x12_URSTCON_HSIC0		BIT(6)
    100#define EXYNOS_4x12_URSTCON_HSIC1		BIT(5)
    101#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL	BIT(7)
    102#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(10)
    103#define EXYNOS_4x12_URSTCON_HOST_LINK_P1	BIT(9)
    104#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(8)
    105
    106/* Isolation, configured in the power management unit */
    107#define EXYNOS_4x12_USB_ISOL_OFFSET		0x704
    108#define EXYNOS_4x12_USB_ISOL_OTG		BIT(0)
    109#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET	0x708
    110#define EXYNOS_4x12_USB_ISOL_HSIC0		BIT(0)
    111#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET	0x70c
    112#define EXYNOS_4x12_USB_ISOL_HSIC1		BIT(0)
    113
    114/* Mode switching SUB Device <-> Host */
    115#define EXYNOS_4x12_MODE_SWITCH_OFFSET		0x21c
    116#define EXYNOS_4x12_MODE_SWITCH_MASK		1
    117#define EXYNOS_4x12_MODE_SWITCH_DEVICE		0
    118#define EXYNOS_4x12_MODE_SWITCH_HOST		1
    119
    120enum exynos4x12_phy_id {
    121	EXYNOS4x12_DEVICE,
    122	EXYNOS4x12_HOST,
    123	EXYNOS4x12_HSIC0,
    124	EXYNOS4x12_HSIC1,
    125	EXYNOS4x12_NUM_PHYS,
    126};
    127
    128/*
    129 * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
    130 * can be written to the phy register.
    131 */
    132static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
    133{
    134	/* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
    135
    136	switch (rate) {
    137	case 9600 * KHZ:
    138		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
    139		break;
    140	case 10 * MHZ:
    141		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
    142		break;
    143	case 12 * MHZ:
    144		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
    145		break;
    146	case 19200 * KHZ:
    147		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
    148		break;
    149	case 20 * MHZ:
    150		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
    151		break;
    152	case 24 * MHZ:
    153		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
    154		break;
    155	case 50 * MHZ:
    156		*reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
    157		break;
    158	default:
    159		return -EINVAL;
    160	}
    161
    162	return 0;
    163}
    164
    165static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
    166{
    167	struct samsung_usb2_phy_driver *drv = inst->drv;
    168	u32 offset;
    169	u32 mask;
    170
    171	switch (inst->cfg->id) {
    172	case EXYNOS4x12_DEVICE:
    173	case EXYNOS4x12_HOST:
    174		offset = EXYNOS_4x12_USB_ISOL_OFFSET;
    175		mask = EXYNOS_4x12_USB_ISOL_OTG;
    176		break;
    177	case EXYNOS4x12_HSIC0:
    178		offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
    179		mask = EXYNOS_4x12_USB_ISOL_HSIC0;
    180		break;
    181	case EXYNOS4x12_HSIC1:
    182		offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
    183		mask = EXYNOS_4x12_USB_ISOL_HSIC1;
    184		break;
    185	default:
    186		return;
    187	}
    188
    189	regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
    190}
    191
    192static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
    193{
    194	struct samsung_usb2_phy_driver *drv = inst->drv;
    195	u32 clk;
    196
    197	clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
    198	clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
    199
    200	if (drv->cfg->has_refclk_sel)
    201		clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
    202
    203	clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
    204	clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
    205	writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
    206}
    207
    208static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
    209{
    210	struct samsung_usb2_phy_driver *drv = inst->drv;
    211	u32 rstbits = 0;
    212	u32 phypwr = 0;
    213	u32 rst;
    214	u32 pwr;
    215
    216	switch (inst->cfg->id) {
    217	case EXYNOS4x12_DEVICE:
    218		phypwr =	EXYNOS_4x12_UPHYPWR_PHY0;
    219		rstbits =	EXYNOS_4x12_URSTCON_PHY0;
    220		break;
    221	case EXYNOS4x12_HOST:
    222		phypwr =	EXYNOS_4x12_UPHYPWR_PHY1;
    223		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY |
    224				EXYNOS_4x12_URSTCON_PHY1 |
    225				EXYNOS_4x12_URSTCON_HOST_LINK_P0;
    226		break;
    227	case EXYNOS4x12_HSIC0:
    228		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC0;
    229		rstbits =	EXYNOS_4x12_URSTCON_HSIC0 |
    230				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
    231		break;
    232	case EXYNOS4x12_HSIC1:
    233		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC1;
    234		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
    235				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
    236		break;
    237	}
    238
    239	if (on) {
    240		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
    241		pwr &= ~phypwr;
    242		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
    243
    244		rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
    245		rst |= rstbits;
    246		writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
    247		udelay(10);
    248		rst &= ~rstbits;
    249		writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
    250		/* The following delay is necessary for the reset sequence to be
    251		 * completed */
    252		udelay(80);
    253	} else {
    254		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
    255		pwr |= phypwr;
    256		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
    257	}
    258}
    259
    260static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
    261{
    262	if (inst->int_cnt++ > 0)
    263		return;
    264
    265	exynos4x12_setup_clk(inst);
    266	exynos4x12_isol(inst, 0);
    267	exynos4x12_phy_pwr(inst, 1);
    268}
    269
    270static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
    271{
    272	struct samsung_usb2_phy_driver *drv = inst->drv;
    273
    274	if (inst->ext_cnt++ > 0)
    275		return 0;
    276
    277	if (inst->cfg->id == EXYNOS4x12_HOST) {
    278		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
    279						EXYNOS_4x12_MODE_SWITCH_MASK,
    280						EXYNOS_4x12_MODE_SWITCH_HOST);
    281		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
    282	}
    283
    284	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
    285		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
    286						EXYNOS_4x12_MODE_SWITCH_MASK,
    287						EXYNOS_4x12_MODE_SWITCH_DEVICE);
    288
    289	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
    290		inst->cfg->id == EXYNOS4x12_HSIC1) {
    291		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
    292		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
    293	}
    294
    295	exynos4x12_power_on_int(inst);
    296
    297	return 0;
    298}
    299
    300static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
    301{
    302	if (inst->int_cnt-- > 1)
    303		return;
    304
    305	exynos4x12_isol(inst, 1);
    306	exynos4x12_phy_pwr(inst, 0);
    307}
    308
    309static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
    310{
    311	struct samsung_usb2_phy_driver *drv = inst->drv;
    312
    313	if (inst->ext_cnt-- > 1)
    314		return 0;
    315
    316	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
    317		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
    318						EXYNOS_4x12_MODE_SWITCH_MASK,
    319						EXYNOS_4x12_MODE_SWITCH_HOST);
    320
    321	if (inst->cfg->id == EXYNOS4x12_HOST)
    322		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
    323
    324	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
    325		inst->cfg->id == EXYNOS4x12_HSIC1) {
    326		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
    327		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
    328	}
    329
    330	exynos4x12_power_off_int(inst);
    331
    332	return 0;
    333}
    334
    335
    336static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
    337	{
    338		.label		= "device",
    339		.id		= EXYNOS4x12_DEVICE,
    340		.power_on	= exynos4x12_power_on,
    341		.power_off	= exynos4x12_power_off,
    342	},
    343	{
    344		.label		= "host",
    345		.id		= EXYNOS4x12_HOST,
    346		.power_on	= exynos4x12_power_on,
    347		.power_off	= exynos4x12_power_off,
    348	},
    349	{
    350		.label		= "hsic0",
    351		.id		= EXYNOS4x12_HSIC0,
    352		.power_on	= exynos4x12_power_on,
    353		.power_off	= exynos4x12_power_off,
    354	},
    355	{
    356		.label		= "hsic1",
    357		.id		= EXYNOS4x12_HSIC1,
    358		.power_on	= exynos4x12_power_on,
    359		.power_off	= exynos4x12_power_off,
    360	},
    361};
    362
    363const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
    364	.has_refclk_sel		= 1,
    365	.num_phys		= 1,
    366	.phys			= exynos4x12_phys,
    367	.rate_to_clk		= exynos4x12_rate_to_clk,
    368};
    369
    370const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
    371	.has_mode_switch	= 1,
    372	.num_phys		= EXYNOS4x12_NUM_PHYS,
    373	.phys			= exynos4x12_phys,
    374	.rate_to_clk		= exynos4x12_rate_to_clk,
    375};