/*
* Rockchip USB2.0 PHY with Innosilicon IP block driver
*
* Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/extcon.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/gpio/consumer.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <linux/usb/of.h>
#include <linux/usb/otg.h>
#define BIT_WRITEABLE_SHIFT 16
#define SCHEDULE_DELAY (60 * HZ)
#define OTG_SCHEDULE_DELAY (2 * HZ)
enum rockchip_usb2phy_port_id {
USB2PHY_PORT_OTG,
USB2PHY_PORT_HOST,
USB2PHY_NUM_PORTS,
};
enum rockchip_usb2phy_host_state {
PHY_STATE_HS_ONLINE = 0,
PHY_STATE_DISCONNECT = 1,
PHY_STATE_CONNECT = 2,
PHY_STATE_FS_LS_ONLINE = 4,
};
/**
* Different states involved in USB charger detection.
* USB_CHG_STATE_UNDEFINED USB charger is not connected or detection
* process is not yet started.
* USB_CHG_STATE_WAIT_FOR_DCD Waiting for Data pins contact.
* USB_CHG_STATE_DCD_DONE Data pin contact is detected.
* USB_CHG_STATE_PRIMARY_DONE Primary detection is completed (Detects
* between SDP and DCP/CDP).
* USB_CHG_STATE_SECONDARY_DONE Secondary detection is completed (Detects
* between DCP and CDP).
* USB_CHG_STATE_DETECTED USB charger type is determined.
*/
enum usb_chg_state {
USB_CHG_STATE_UNDEFINED = 0,
USB_CHG_STATE_WAIT_FOR_DCD,
USB_CHG_STATE_DCD_DONE,
USB_CHG_STATE_PRIMARY_DONE,
USB_CHG_STATE_SECONDARY_DONE,
USB_CHG_STATE_DETECTED,
};
static const unsigned int rockchip_usb2phy_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
EXTCON_CHG_USB_SDP,
EXTCON_CHG_USB_CDP,
EXTCON_CHG_USB_DCP,
EXTCON_CHG_USB_SLOW,
EXTCON_NONE,
};
struct usb2phy_reg {
unsigned int offset;
unsigned int bitend;
unsigned int bitstart;
unsigned int disable;
unsigned int enable;
};
/**
* struct rockchip_chg_det_reg: usb charger detect registers
* @cp_det: charging port detected successfully.
* @dcp_det: dedicated charging port detected successfully.
* @dp_det: assert data pin connect successfully.
* @idm_sink_en: open dm sink curren.
* @idp_sink_en: open dp sink current.
* @idp_src_en: open dm source current.
* @rdm_pdwn_en: open dm pull down resistor.
* @vdm_src_en: open dm voltage source.
* @vdp_src_en: open dp voltage source.
* @opmode: utmi operational mode.
*/
struct rockchip_chg_det_reg {
struct usb2phy_reg cp_det;
struct usb2phy_reg dcp_det;
struct usb2phy_reg dp_det;
struct usb2phy_reg idm_sink_en;
struct usb2phy_reg idp_sink_en;
struct usb2phy_reg idp_src_en;
struct usb2phy_reg rdm_pdwn_en;
struct usb2phy_reg vdm_src_en;
struct usb2phy_reg vdp_src_en;
struct usb2phy_reg opmode;
};
/**
* struct rockchip_usb2phy_port_cfg: usb-phy port configuration.
* @phy_sus: phy suspend register.
* @bvalid_det_en: vbus valid rise detection enable register.
* @bvalid_det_st: vbus valid rise detection status register.
* @bvalid_det_clr: vbus valid rise detection clear register.
* @ls_det_en: linestate detection enable register.
* @ls_det_st: linestate detection state register.
* @ls_det_clr: linestate detection clear register.
* @utmi_avalid: utmi vbus avalid status register.
* @utmi_bvalid: utmi vbus bvalid status register.
* @utmi_ls: utmi linestate state register.
* @utmi_hstdet: utmi host disconnect register.
*/
struct rockchip_usb2phy_port_cfg {
struct usb2phy_reg phy_sus;
struct usb2phy_reg bvalid_det_en;
struct usb2phy_reg bvalid_det_st;
struct usb2phy_reg bvalid_det_clr;
struct usb2phy_reg ls_det_en;
struct usb2phy_reg ls_det_st;
struct usb2phy_reg ls_det_clr;
struct