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