2017-11-03 11:28:30 +01:00
// SPDX-License-Identifier: GPL-2.0
2016-01-07 18:18:13 +09:00
/*
* Renesas USB driver R - Car Gen . 3 initialization and power control
*
2019-06-25 14:38:55 +09:00
* Copyright ( C ) 2016 - 2019 Renesas Electronics Corporation
2016-01-07 18:18:13 +09:00
*/
2016-10-20 13:19:19 +09:00
# include <linux/delay.h>
2016-01-07 18:18:13 +09:00
# include <linux/io.h>
# include "common.h"
# include "rcar3.h"
# define LPSTS 0x102
2017-10-03 20:09:14 +09:00
# define UGCTRL 0x180 /* 32-bit register */
2016-01-07 18:18:13 +09:00
# define UGCTRL2 0x184 /* 32-bit register */
2017-10-03 20:09:14 +09:00
# define UGSTS 0x188 /* 32-bit register */
2016-01-07 18:18:13 +09:00
/* Low Power Status register (LPSTS) */
# define LPSTS_SUSPM 0x4000
2017-10-03 20:09:14 +09:00
/* R-Car D3 only: USB General control register (UGCTRL) */
# define UGCTRL_PLLRESET 0x00000001
# define UGCTRL_CONNECT 0x00000004
2017-08-02 13:21:45 +09:00
/*
* USB General control register 2 ( UGCTRL2 )
* Remarks : bit [ 31 : 11 ] and bit [ 9 : 6 ] should be 0
*/
2016-01-07 18:18:13 +09:00
# define UGCTRL2_RESERVED_3 0x00000001 /* bit[3:0] should be B'0001 */
2017-10-03 20:09:14 +09:00
# define UGCTRL2_USB0SEL_HSUSB 0x00000020
2016-01-07 18:18:13 +09:00
# define UGCTRL2_USB0SEL_OTG 0x00000030
2017-08-02 13:21:45 +09:00
# define UGCTRL2_VBUSSEL 0x00000400
2016-01-07 18:18:13 +09:00
2017-10-03 20:09:14 +09:00
/* R-Car D3 only: USB General status register (UGSTS) */
# define UGSTS_LOCK 0x00000100
2016-06-21 18:52:54 +01:00
static void usbhs_write32 ( struct usbhs_priv * priv , u32 reg , u32 data )
2016-01-07 18:18:13 +09:00
{
iowrite32 ( data , priv - > base + reg ) ;
}
2017-10-03 20:09:14 +09:00
static u32 usbhs_read32 ( struct usbhs_priv * priv , u32 reg )
{
return ioread32 ( priv - > base + reg ) ;
}
2017-12-13 15:46:57 +09:00
static void usbhs_rcar3_set_ugctrl2 ( struct usbhs_priv * priv , u32 val )
{
usbhs_write32 ( priv , UGCTRL2 , val | UGCTRL2_RESERVED_3 ) ;
}
2016-01-07 18:18:13 +09:00
static int usbhs_rcar3_power_ctrl ( struct platform_device * pdev ,
void __iomem * base , int enable )
{
struct usbhs_priv * priv = usbhs_pdev_to_priv ( pdev ) ;
2017-12-13 15:46:57 +09:00
usbhs_rcar3_set_ugctrl2 ( priv , UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL ) ;
2016-01-07 18:18:13 +09:00
2016-10-20 13:19:19 +09:00
if ( enable ) {
2016-01-07 18:18:13 +09:00
usbhs_bset ( priv , LPSTS , LPSTS_SUSPM , LPSTS_SUSPM ) ;
2016-10-20 13:19:19 +09:00
/* The controller on R-Car Gen3 needs to wait up to 45 usec */
2019-01-17 16:24:15 +09:00
usleep_range ( 45 , 90 ) ;
2016-10-20 13:19:19 +09:00
} else {
2016-01-07 18:18:13 +09:00
usbhs_bset ( priv , LPSTS , LPSTS_SUSPM , 0 ) ;
2016-10-20 13:19:19 +09:00
}
2016-01-07 18:18:13 +09:00
return 0 ;
}
2017-10-03 20:09:14 +09:00
/* R-Car D3 needs to release UGCTRL.PLLRESET */
static int usbhs_rcar3_power_and_pll_ctrl ( struct platform_device * pdev ,
void __iomem * base , int enable )
{
struct usbhs_priv * priv = usbhs_pdev_to_priv ( pdev ) ;
u32 val ;
int timeout = 1000 ;
if ( enable ) {
usbhs_write32 ( priv , UGCTRL , 0 ) ; /* release PLLRESET */
2018-09-21 21:26:30 +09:00
usbhs_rcar3_set_ugctrl2 ( priv ,
UGCTRL2_USB0SEL_OTG | UGCTRL2_VBUSSEL ) ;
2017-10-03 20:09:14 +09:00
usbhs_bset ( priv , LPSTS , LPSTS_SUSPM , LPSTS_SUSPM ) ;
do {
val = usbhs_read32 ( priv , UGSTS ) ;
udelay ( 1 ) ;
} while ( ! ( val & UGSTS_LOCK ) & & timeout - - ) ;
usbhs_write32 ( priv , UGCTRL , UGCTRL_CONNECT ) ;
} else {
usbhs_write32 ( priv , UGCTRL , 0 ) ;
usbhs_bset ( priv , LPSTS , LPSTS_SUSPM , 0 ) ;
usbhs_write32 ( priv , UGCTRL , UGCTRL_PLLRESET ) ;
}
return 0 ;
}
2019-06-25 14:38:56 +09:00
const struct renesas_usbhs_platform_info usbhs_rcar_gen3_plat_info = {
. platform_callback = {
. power_ctrl = usbhs_rcar3_power_ctrl ,
. get_id = usbhs_get_id_as_gadget ,
} ,
. driver_param = {
. has_usb_dmac = 1 ,
. multi_clks = 1 ,
. has_new_pipe_configs = 1 ,
} ,
2016-01-07 18:18:13 +09:00
} ;
2017-10-03 20:09:14 +09:00
2019-06-25 14:38:56 +09:00
const struct renesas_usbhs_platform_info usbhs_rcar_gen3_with_pll_plat_info = {
. platform_callback = {
. power_ctrl = usbhs_rcar3_power_and_pll_ctrl ,
. get_id = usbhs_get_id_as_gadget ,
} ,
. driver_param = {
. has_usb_dmac = 1 ,
. multi_clks = 1 ,
. has_new_pipe_configs = 1 ,
} ,
2017-10-03 20:09:14 +09:00
} ;