253 lines
7.1 KiB
C
Executable file
253 lines
7.1 KiB
C
Executable file
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2021 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef __PHY_EXYNOS_USBDRD_H__
|
|
#define __PHY_EXYNOS_USBDRD_H__
|
|
|
|
#include "phy-samsung-usb-cal.h"
|
|
#include "phy-exynos-usb3p1.h"
|
|
#include "phy-exynos-usbdp-gen2.h"
|
|
#include "phy-exynos-usbdp-gen2-v4.h"
|
|
|
|
#define EXYNOS_USBPHY_VER_02_0_0 0x0200 /* Lhotse - USBDP Combo PHY */
|
|
|
|
/* 9810 PMU register offset */
|
|
#define EXYNOS_USBDP_PHY_CONTROL (0x704)
|
|
#define EXYNOS_USB2_PHY_CONTROL (0x72C)
|
|
/* PMU register offset for USB */
|
|
#define EXYNOS_USBDEV_PHY_CONTROL (0x704)
|
|
#define EXYNOS_USBDRD_ENABLE BIT(0)
|
|
#define EXYNOS_USBHOST_ENABLE BIT(1)
|
|
|
|
/* Exynos USB PHY registers */
|
|
#define EXYNOS_FSEL_9MHZ6 0x0
|
|
#define EXYNOS_FSEL_10MHZ 0x1
|
|
#define EXYNOS_FSEL_12MHZ 0x2
|
|
#define EXYNOS_FSEL_19MHZ2 0x1
|
|
#define EXYNOS_FSEL_20MHZ 0x4
|
|
#define EXYNOS_FSEL_24MHZ 0x5
|
|
#define EXYNOS_FSEL_26MHZ 0x82
|
|
#define EXYNOS_FSEL_50MHZ 0x7
|
|
|
|
/* EXYNOS: USB DRD PHY registers */
|
|
#define EXYNOS_DRD_LINKSYSTEM 0x04
|
|
|
|
#define LINKSYSTEM_FLADJ_MASK (0x3f << 1)
|
|
#define LINKSYSTEM_FLADJ(_x) ((_x) << 1)
|
|
|
|
#define EXYNOS_DRD_PHYUTMI 0x08
|
|
|
|
#define EXYNOS_DRD_PHYPIPE 0x0c
|
|
|
|
#define PHYPIPE_PHY_CLOCK_SEL (0x1 << 4)
|
|
|
|
#define EXYNOS_DRD_PHYCLKRST 0x10
|
|
|
|
#define PHYCLKRST_SSC_REFCLKSEL_MASK (0xff << 23)
|
|
#define PHYCLKRST_SSC_REFCLKSEL(_x) ((_x) << 23)
|
|
|
|
#define PHYCLKRST_SSC_RANGE_MASK (0x03 << 21)
|
|
#define PHYCLKRST_SSC_RANGE(_x) ((_x) << 21)
|
|
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_MASK (0x7f << 11)
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF (0x19 << 11)
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF (0x32 << 11)
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF (0x68 << 11)
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF (0x7d << 11)
|
|
#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
|
|
|
|
#define PHYCLKRST_FSEL_UTMI_MASK (0x7 << 5)
|
|
#define PHYCLKRST_FSEL_PIPE_MASK (0x7 << 8)
|
|
#define PHYCLKRST_FSEL(_x) ((_x) << 5)
|
|
#define PHYCLKRST_FSEL_PAD_100MHZ (0x27 << 5)
|
|
#define PHYCLKRST_FSEL_PAD_24MHZ (0x2a << 5)
|
|
#define PHYCLKRST_FSEL_PAD_20MHZ (0x31 << 5)
|
|
#define PHYCLKRST_FSEL_PAD_19_2MHZ (0x38 << 5)
|
|
|
|
#define PHYCLKRST_REFCLKSEL_MASK (0x03 << 2)
|
|
#define PHYCLKRST_REFCLKSEL_PAD_REFCLK (0x2 << 2)
|
|
#define PHYCLKRST_REFCLKSEL_EXT_REFCLK (0x3 << 2)
|
|
|
|
#define EXYNOS_DRD_PHYREG0 0x14
|
|
#define EXYNOS_DRD_PHYREG1 0x18
|
|
|
|
#define EXYNOS_DRD_PHYPARAM0 0x1c
|
|
|
|
#define PHYPARAM0_REF_LOSLEVEL_MASK (0x1f << 26)
|
|
#define PHYPARAM0_REF_LOSLEVEL (0x9 << 26)
|
|
|
|
#define EXYNOS_DRD_PHYPARAM1 0x20
|
|
|
|
#define PHYPARAM1_PCS_TXDEEMPH_MASK (0x1f << 0)
|
|
#define PHYPARAM1_PCS_TXDEEMPH (0x1c)
|
|
|
|
#define EXYNOS_DRD_PHYTERM 0x24
|
|
|
|
#define EXYNOS_DRD_PHYTEST 0x28
|
|
|
|
#define EXYNOS_DRD_PHYADP 0x2c
|
|
|
|
#define EXYNOS_DRD_PHYUTMICLKSEL 0x30
|
|
|
|
#define PHYUTMICLKSEL_UTMI_CLKSEL BIT(2)
|
|
|
|
#define EXYNOS_DRD_PHYRESUME 0x34
|
|
#define EXYNOS_DRD_LINKPORT 0x44
|
|
|
|
#define KHZ 1000
|
|
#define MHZ (KHZ * KHZ)
|
|
|
|
#define EXYNOS_DRD_MAX_TUNEPARAM_NUM 32
|
|
#define EXYNOS_DRD_TUNEPARAM_LEN 30
|
|
|
|
enum exynos_usbdrd_phy_id {
|
|
EXYNOS_DRDPHY_UTMI,
|
|
EXYNOS_DRDPHY_PIPE3,
|
|
EXYNOS_DRDPHYS_NUM,
|
|
};
|
|
|
|
struct phy_usb_instance;
|
|
struct exynos_usbdrd_phy;
|
|
|
|
struct exynos_usbdrd_phy_config {
|
|
u32 id;
|
|
void (*phy_isol)(struct phy_usb_instance *inst, u32 on, unsigned int);
|
|
void (*phy_init)(struct exynos_usbdrd_phy *phy_drd);
|
|
void (*phy_exit)(struct exynos_usbdrd_phy *phy_drd);
|
|
void (*phy_tune)(struct exynos_usbdrd_phy *phy_drd, int);
|
|
int (*phy_vendor_set)(struct exynos_usbdrd_phy *phy_drd, int, int);
|
|
void (*phy_ilbk)(struct exynos_usbdrd_phy *phy_drd);
|
|
void (*phy_set)(struct exynos_usbdrd_phy *phy_drd, int, void *);
|
|
unsigned int (*set_refclk)(struct phy_usb_instance *inst);
|
|
};
|
|
|
|
struct exynos_usbdrd_phy_drvdata {
|
|
const struct exynos_usbdrd_phy_config *phy_cfg;
|
|
};
|
|
|
|
/**
|
|
* struct exynos_usbdrd_phy - driver data for USB DRD PHY
|
|
* @dev: pointer to device instance of this platform device
|
|
* @reg_phy: usb phy controller register memory base
|
|
* @clk: phy clock for register access
|
|
* @drv_data: pointer to SoC level driver data structure
|
|
* @phys[]: array for 'EXYNOS_DRDPHYS_NUM' number of PHY
|
|
* instances each with its 'phy' and 'phy_cfg'.
|
|
* @extrefclk: frequency select settings when using 'separate
|
|
* reference clocks' for SS and HS operations
|
|
* @ref_clk: reference clock to PHY block from which PHY's
|
|
* operational clocks are derived
|
|
* @usbphy_info; Phy main control info
|
|
* @usbphy_sub_info; USB3.0 phy control info
|
|
*/
|
|
struct exynos_usbdrd_phy {
|
|
struct device *dev;
|
|
void __iomem *reg_phy;
|
|
void __iomem *reg_phy2;
|
|
void __iomem *reg_phy3;
|
|
void __iomem *reg_link;
|
|
void __iomem *reg_eusb_ctrl;
|
|
void __iomem *reg_eusb_phy;
|
|
void __iomem *reg_dpphy_ctrl;
|
|
void __iomem *reg_dpphy_tca;
|
|
struct clk **clocks;
|
|
struct clk **phy_clocks;
|
|
const struct exynos_usbdrd_phy_drvdata *drv_data;
|
|
struct phy_usb_instance {
|
|
struct phy *phy;
|
|
u32 index;
|
|
struct regmap *reg_pmu;
|
|
u32 pmu_offset;
|
|
u32 pmu_offset_dp;
|
|
u32 pmu_mask;
|
|
u32 pmu_offset_tcxobuf;
|
|
u32 pmu_mask_tcxobuf;
|
|
const struct exynos_usbdrd_phy_config *phy_cfg;
|
|
} phys[EXYNOS_DRDPHYS_NUM];
|
|
u32 extrefclk;
|
|
bool use_phy_umux;
|
|
struct clk *ref_clk;
|
|
struct regulator *vbus;
|
|
struct regulator *vdd075_usb;
|
|
struct regulator *vdd12_usb;
|
|
struct regulator *vdd18_usb;
|
|
struct regulator *vdd33_usb;
|
|
struct exynos_usbphy_info usbphy_info;
|
|
struct exynos_usbphy_info usbphy_sub_info;
|
|
struct exynos_usbphy_info usbphy_blkcon_info;
|
|
struct exynos_usbphy_ss_tune ss_value[2];
|
|
struct exynos_usbphy_hs_tune hs_value[2];
|
|
int hs_tune_param_value[EXYNOS_DRD_MAX_TUNEPARAM_NUM][2];
|
|
int ss_tune_param_value[EXYNOS_DRD_MAX_TUNEPARAM_NUM][2];
|
|
|
|
u32 ip_type;
|
|
#if IS_ENABLED(CONFIG_EXYNOS_OTP)
|
|
#define OTP_SUPPORT_USBPHY_NUMBER 2
|
|
#define OTP_USB3PHY_INDEX 0
|
|
#define OTP_USB2PHY_INDEX 1
|
|
u8 otp_type[OTP_SUPPORT_USBPHY_NUMBER];
|
|
u8 otp_index[OTP_SUPPORT_USBPHY_NUMBER];
|
|
struct tune_bits *otp_data[OTP_SUPPORT_USBPHY_NUMBER];
|
|
#endif
|
|
int irq_wakeup;
|
|
int usb3_irq_wakeup;
|
|
int irq_conn;
|
|
int is_conn;
|
|
int is_irq_enabled;
|
|
int idle_ip_idx;
|
|
u32 phy_port;
|
|
u32 reverse_phy_port;
|
|
spinlock_t lock;
|
|
u32 use_default_tune_val;
|
|
int in_shutdown;
|
|
int is_ldo_on;
|
|
int phy_port_test_en;
|
|
#if defined(CONFIG_OTG_CDP_SUPPORT)
|
|
int cdp_check;
|
|
#endif
|
|
};
|
|
|
|
void __iomem *phy_exynos_usbdp_get_address(void);
|
|
|
|
enum samsung_cpu_type {
|
|
TYPE_S3C64XX,
|
|
TYPE_EXYNOS4210,
|
|
TYPE_EXYNOS5250,
|
|
TYPE_EXYNOS5430,
|
|
TYPE_EXYNOS7420,
|
|
TYPE_EXYNOS7580,
|
|
TYPE_EXYNOS8890,
|
|
TYPE_EXYNOS8895,
|
|
};
|
|
|
|
enum samsung_usb_ip_type {
|
|
TYPE_USB3DRD = 0,
|
|
TYPE_USB3HOST,
|
|
TYPE_USB2DRD,
|
|
TYPE_USB2HOST,
|
|
};
|
|
|
|
enum samsung_phy_set_option {
|
|
SET_DPPULLUP_ENABLE,
|
|
SET_DPPULLUP_DISABLE,
|
|
SET_DPDM_PULLDOWN,
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_PHY_EXYNOS_EUSB_REPEATER)
|
|
extern int tusb2e11_power_on(void);
|
|
extern int tusb2e11_power_off(void);
|
|
#endif
|
|
|
|
#endif /* __PHY_EXYNOS_USBDRD_H__ */
|