linux/drivers/usb/dwc3/dwc3-octeon.c

// SPDX-License-Identifier: GPL-2.0
/*
 * DWC3 glue for Cavium Octeon III SOCs.
 *
 * Copyright (C) 2010-2017 Cavium Networks
 * Copyright (C) 2023 RACOM s.r.o.
 */

#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>

/*
 * USB Control Register
 */
#define USBDRD_UCTL_CTL
/* BIST fast-clear mode select. A BIST run with this bit set
 * clears all entries in USBH RAMs to 0x0.
 */
#define USBDRD_UCTL_CTL_CLEAR_BIST
/* 1 = Start BIST and cleared by hardware */
#define USBDRD_UCTL_CTL_START_BIST
/* Reference clock select for SuperSpeed and HighSpeed PLLs:
 *	0x0 = Both PLLs use DLMC_REF_CLK0 for reference clock
 *	0x1 = Both PLLs use DLMC_REF_CLK1 for reference clock
 *	0x2 = SuperSpeed PLL uses DLMC_REF_CLK0 for reference clock &
 *	      HighSpeed PLL uses PLL_REF_CLK for reference clck
 *	0x3 = SuperSpeed PLL uses DLMC_REF_CLK1 for reference clock &
 *	      HighSpeed PLL uses PLL_REF_CLK for reference clck
 */
#define USBDRD_UCTL_CTL_REF_CLK_SEL
/* 1 = Spread-spectrum clock enable, 0 = SS clock disable */
#define USBDRD_UCTL_CTL_SSC_EN
/* Spread-spectrum clock modulation range:
 *	0x0 = -4980 ppm downspread
 *	0x1 = -4492 ppm downspread
 *	0x2 = -4003 ppm downspread
 *	0x3 - 0x7 = Reserved
 */
#define USBDRD_UCTL_CTL_SSC_RANGE
/* Enable non-standard oscillator frequencies:
 *	[55:53] = modules -1
 *	[52:47] = 2's complement push amount, 0 = Feature disabled
 */
#define USBDRD_UCTL_CTL_SSC_REF_CLK_SEL
/* Reference clock multiplier for non-standard frequencies:
 *	0x19 = 100MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1
 *	0x28 = 125MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1
 *	0x32 =  50MHz on DLMC_REF_CLK* if REF_CLK_SEL = 0x0 or 0x1
 *	Other Values = Reserved
 */
#define USBDRD_UCTL_CTL_MPLL_MULTIPLIER
/* Enable reference clock to prescaler for SuperSpeed functionality.
 * Should always be set to "1"
 */
#define USBDRD_UCTL_CTL_REF_SSP_EN
/* Divide the reference clock by 2 before entering the
 * REF_CLK_FSEL divider:
 *	If REF_CLK_SEL = 0x0 or 0x1, then only 0x0 is legal
 *	If REF_CLK_SEL = 0x2 or 0x3, then:
 *		0x1 = DLMC_REF_CLK* is 125MHz
 *		0x0 = DLMC_REF_CLK* is another supported frequency
 */
#define USBDRD_UCTL_CTL_REF_CLK_DIV2
/* Select reference clock freqnuency for both PLL blocks:
 *	0x27 = REF_CLK_SEL is 0x0 or 0x1
 *	0x07 = REF_CLK_SEL is 0x2 or 0x3
 */
#define USBDRD_UCTL_CTL_REF_CLK_FSEL
/* Controller clock enable. */
#define USBDRD_UCTL_CTL_H_CLK_EN
/* Select bypass input to controller clock divider:
 *	0x0 = Use divided coprocessor clock from H_CLKDIV
 *	0x1 = Use clock from GPIO pins
 */
#define USBDRD_UCTL_CTL_H_CLK_BYP_SEL
/* Reset controller clock divider. */
#define USBDRD_UCTL_CTL_H_CLKDIV_RST
/* Clock divider select:
 *	0x0 = divide by 1
 *	0x1 = divide by 2
 *	0x2 = divide by 4
 *	0x3 = divide by 6
 *	0x4 = divide by 8
 *	0x5 = divide by 16
 *	0x6 = divide by 24
 *	0x7 = divide by 32
 */
#define USBDRD_UCTL_CTL_H_CLKDIV_SEL
/* USB3 port permanently attached: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_USB3_PORT_PERM_ATTACH
/* USB2 port permanently attached: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_USB2_PORT_PERM_ATTACH
/* Disable SuperSpeed PHY: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_USB3_PORT_DISABLE
/* Disable HighSpeed PHY: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_USB2_PORT_DISABLE
/* Enable PHY SuperSpeed block power: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_SS_POWER_EN
/* Enable PHY HighSpeed block power: 0x0 = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_HS_POWER_EN
/* Enable USB UCTL interface clock: 0xx = No, 0x1 = Yes */
#define USBDRD_UCTL_CTL_CSCLK_EN
/* Controller mode: 0x0 = Host, 0x1 = Device */
#define USBDRD_UCTL_CTL_DRD_MODE
/* PHY reset */
#define USBDRD_UCTL_CTL_UPHY_RST
/* Software reset UAHC */
#define USBDRD_UCTL_CTL_UAHC_RST
/* Software resets UCTL */
#define USBDRD_UCTL_CTL_UCTL_RST

#define USBDRD_UCTL_BIST_STATUS
#define USBDRD_UCTL_SPARE0
#define USBDRD_UCTL_INTSTAT
#define USBDRD_UCTL_PORT_CFG_HS(port)
#define USBDRD_UCTL_PORT_CFG_SS(port)
#define USBDRD_UCTL_PORT_CR_DBG_CFG(port)
#define USBDRD_UCTL_PORT_CR_DBG_STATUS(port)

/*
 * UCTL Configuration Register
 */
#define USBDRD_UCTL_HOST_CFG
/* Indicates minimum value of all received BELT values */
#define USBDRD_UCTL_HOST_CFG_HOST_CURRENT_BELT
/* HS jitter adjustment */
#define USBDRD_UCTL_HOST_CFG_FLA
/* Bus-master enable: 0x0 = Disabled (stall DMAs), 0x1 = enabled */
#define USBDRD_UCTL_HOST_CFG_BME
/* Overcurrent protection enable: 0x0 = unavailable, 0x1 = available */
#define USBDRD_UCTL_HOST_OCI_EN
/* Overcurrent sene selection:
 *	0x0 = Overcurrent indication from off-chip is active-low
 *	0x1 = Overcurrent indication from off-chip is active-high
 */
#define USBDRD_UCTL_HOST_OCI_ACTIVE_HIGH_EN
/* Port power control enable: 0x0 = unavailable, 0x1 = available */
#define USBDRD_UCTL_HOST_PPC_EN
/* Port power control sense selection:
 *	0x0 = Port power to off-chip is active-low
 *	0x1 = Port power to off-chip is active-high
 */
#define USBDRD_UCTL_HOST_PPC_ACTIVE_HIGH_EN

/*
 * UCTL Shim Features Register
 */
#define USBDRD_UCTL_SHIM_CFG
/* Out-of-bound UAHC register access: 0 = read, 1 = write */
#define USBDRD_UCTL_SHIM_CFG_XS_NCB_OOB_WRN
/* SRCID error log for out-of-bound UAHC register access:
 *	[59:58] = chipID
 *	[57] = Request source: 0 = core, 1 = NCB-device
 *	[56:51] = Core/NCB-device number, [56] always 0 for NCB devices
 *	[50:48] = SubID
 */
#define USBDRD_UCTL_SHIM_CFG_XS_NCB_OOB_OSRC
/* Error log for bad UAHC DMA access: 0 = Read log, 1 = Write log */
#define USBDRD_UCTL_SHIM_CFG_XM_BAD_DMA_WRN
/* Encoded error type for bad UAHC DMA */
#define USBDRD_UCTL_SHIM_CFG_XM_BAD_DMA_TYPE
/* Select the IOI read command used by DMA accesses */
#define USBDRD_UCTL_SHIM_CFG_DMA_READ_CMD
/* Select endian format for DMA accesses to the L2C:
 *	0x0 = Little endian
 *	0x1 = Big endian
 *	0x2 = Reserved
 *	0x3 = Reserved
 */
#define USBDRD_UCTL_SHIM_CFG_DMA_ENDIAN_MODE
/* Select endian format for IOI CSR access to UAHC:
 *	0x0 = Little endian
 *	0x1 = Big endian
 *	0x2 = Reserved
 *	0x3 = Reserved
 */
#define USBDRD_UCTL_SHIM_CFG_CSR_ENDIAN_MODE

#define USBDRD_UCTL_ECC
#define USBDRD_UCTL_SPARE1

struct dwc3_octeon {};

#define DWC3_GPIO_POWER_NONE

#ifdef CONFIG_CAVIUM_OCTEON_SOC
#include <asm/octeon/octeon.h>
static inline uint64_t dwc3_octeon_readq(void __iomem *addr)
{
	return cvmx_readq_csr(addr);
}

static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val)
{
	cvmx_writeq_csr(base, val);
}

static void dwc3_octeon_config_gpio(int index, int gpio)
{
	union cvmx_gpio_bit_cfgx gpio_bit;

	if ((OCTEON_IS_MODEL(OCTEON_CN73XX) ||
	    OCTEON_IS_MODEL(OCTEON_CNF75XX))
	    && gpio <= 31) {
		gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio));
		gpio_bit.s.tx_oe = 1;
		gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x15);
		cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64);
	} else if (gpio <= 15) {
		gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_BIT_CFGX(gpio));
		gpio_bit.s.tx_oe = 1;
		gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19);
		cvmx_write_csr(CVMX_GPIO_BIT_CFGX(gpio), gpio_bit.u64);
	} else {
		gpio_bit.u64 = cvmx_read_csr(CVMX_GPIO_XBIT_CFGX(gpio));
		gpio_bit.s.tx_oe = 1;
		gpio_bit.s.output_sel = (index == 0 ? 0x14 : 0x19);
		cvmx_write_csr(CVMX_GPIO_XBIT_CFGX(gpio), gpio_bit.u64);
	}
}
#else
static inline uint64_t dwc3_octeon_readq(void __iomem *addr)
{}

static inline void dwc3_octeon_writeq(void __iomem *base, uint64_t val) {}

static inline void dwc3_octeon_config_gpio(int index, int gpio) {}

static uint64_t octeon_get_io_clock_rate(void)
{}
#endif

static int dwc3_octeon_get_divider(void)
{}

static int dwc3_octeon_setup(struct dwc3_octeon *octeon,
			     int ref_clk_sel, int ref_clk_fsel, int mpll_mul,
			     int power_gpio, int power_active_low)
{}

static void dwc3_octeon_set_endian_mode(struct dwc3_octeon *octeon)
{}

static void dwc3_octeon_phy_reset(struct dwc3_octeon *octeon)
{}

static int dwc3_octeon_probe(struct platform_device *pdev)
{}

static void dwc3_octeon_remove(struct platform_device *pdev)
{}

static const struct of_device_id dwc3_octeon_of_match[] =;
MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);

static struct platform_driver dwc3_octeon_driver =;
module_platform_driver();

MODULE_ALIAS();
MODULE_AUTHOR();
MODULE_LICENSE();
MODULE_DESCRIPTION();