1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2016 Rockchip Electronics Co., Ltd 4 */ 5 6 #include <common.h> 7 #include <asm/io.h> 8 #include <linux/libfdt.h> 9 10 #include "../gadget/dwc2_udc_otg_priv.h" 11 12 DECLARE_GLOBAL_DATA_PTR; 13 14 #define BIT_WRITEABLE_SHIFT 16 15 16 struct usb2phy_reg { 17 unsigned int offset; 18 unsigned int bitend; 19 unsigned int bitstart; 20 unsigned int disable; 21 unsigned int enable; 22 }; 23 24 /** 25 * struct rockchip_usb2_phy_cfg: usb-phy port configuration 26 * @port_reset: usb otg per-port reset register 27 * @soft_con: software control usb otg register 28 * @suspend: phy suspend register 29 */ 30 struct rockchip_usb2_phy_cfg { 31 struct usb2phy_reg port_reset; 32 struct usb2phy_reg soft_con; 33 struct usb2phy_reg suspend; 34 }; 35 36 struct rockchip_usb2_phy_dt_id { 37 char compatible[128]; 38 const void *data; 39 }; 40 41 static const struct rockchip_usb2_phy_cfg rk3288_pdata = { 42 .port_reset = {0x00, 12, 12, 0, 1}, 43 .soft_con = {0x08, 2, 2, 0, 1}, 44 .suspend = {0x0c, 5, 0, 0x01, 0x2A}, 45 }; 46 47 static struct rockchip_usb2_phy_dt_id rockchip_usb2_phy_dt_ids[] = { 48 { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata }, 49 {} 50 }; 51 52 static void property_enable(struct dwc2_plat_otg_data *pdata, 53 const struct usb2phy_reg *reg, bool en) 54 { 55 unsigned int val, mask, tmp; 56 57 tmp = en ? reg->enable : reg->disable; 58 mask = GENMASK(reg->bitend, reg->bitstart); 59 val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT); 60 61 writel(val, pdata->regs_phy + reg->offset); 62 } 63 64 65 void otg_phy_init(struct dwc2_udc *dev) 66 { 67 struct dwc2_plat_otg_data *pdata = dev->pdata; 68 struct rockchip_usb2_phy_cfg *phy_cfg = NULL; 69 struct rockchip_usb2_phy_dt_id *of_id; 70 int i; 71 72 for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) { 73 of_id = &rockchip_usb2_phy_dt_ids[i]; 74 if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node, 75 of_id->compatible) == 0) { 76 phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data; 77 break; 78 } 79 } 80 if (!phy_cfg) { 81 debug("Can't find device platform data\n"); 82 83 hang(); 84 return; 85 } 86 pdata->priv = phy_cfg; 87 /* disable software control */ 88 property_enable(pdata, &phy_cfg->soft_con, false); 89 90 /* reset otg port */ 91 property_enable(pdata, &phy_cfg->port_reset, true); 92 mdelay(1); 93 property_enable(pdata, &phy_cfg->port_reset, false); 94 udelay(1); 95 } 96 97 void otg_phy_off(struct dwc2_udc *dev) 98 { 99 struct dwc2_plat_otg_data *pdata = dev->pdata; 100 struct rockchip_usb2_phy_cfg *phy_cfg = pdata->priv; 101 102 /* enable software control */ 103 property_enable(pdata, &phy_cfg->soft_con, true); 104 /* enter suspend */ 105 property_enable(pdata, &phy_cfg->suspend, true); 106 } 107