1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/err.h> 8 #include <linux/interrupt.h> 9 #include <linux/io.h> 10 #include <linux/iopoll.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/slab.h> 16 #include <linux/sysfs.h> 17 #include <linux/usb/role.h> 18 #include <linux/firmware/qcom/qcom_scm.h> 19 20 #define EUD_REG_INT1_EN_MASK 0x0024 21 #define EUD_REG_INT_STATUS_1 0x0044 22 #define EUD_REG_CTL_OUT_1 0x0074 23 #define EUD_REG_VBUS_INT_CLR 0x0080 24 #define EUD_REG_CSR_EUD_EN 0x1014 25 #define EUD_REG_SW_ATTACH_DET 0x1018 26 #define EUD_REG_EUD_EN2 0x0000 27 28 #define EUD_ENABLE BIT(0) 29 #define EUD_INT_PET_EUD BIT(0) 30 #define EUD_INT_VBUS BIT(2) 31 #define EUD_INT_SAFE_MODE BIT(4) 32 #define EUD_INT_ALL (EUD_INT_VBUS | EUD_INT_SAFE_MODE) 33 34 struct eud_chip { 35 struct device *dev; 36 struct usb_role_switch *role_sw; 37 void __iomem *base; 38 phys_addr_t mode_mgr; 39 unsigned int int_status; 40 int irq; 41 bool enabled; 42 bool usb_attached; 43 }; 44 45 static int enable_eud(struct eud_chip *priv) 46 { 47 int ret; 48 49 ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 1); 50 if (ret) 51 return ret; 52 53 writel(EUD_ENABLE, priv->base + EUD_REG_CSR_EUD_EN); 54 writel(EUD_INT_VBUS | EUD_INT_SAFE_MODE, 55 priv->base + EUD_REG_INT1_EN_MASK); 56 57 return usb_role_switch_set_role(priv->role_sw, USB_ROLE_DEVICE); 58 } 59 60 static int disable_eud(struct eud_chip *priv) 61 { 62 int ret; 63 64 ret = qcom_scm_io_writel(priv->mode_mgr + EUD_REG_EUD_EN2, 0); 65 if (ret) 66 return ret; 67 68 writel(0, priv->base + EUD_REG_CSR_EUD_EN); 69 return 0; 70 } 71 72 static ssize_t enable_show(struct device *dev, 73 struct device_attribute *attr, char *buf) 74 { 75 struct eud_chip *chip = dev_get_drvdata(dev); 76 77 return sysfs_emit(buf, "%d\n", chip->enabled); 78 } 79 80 static ssize_t enable_store(struct device *dev, 81 struct device_attribute *attr, 82 const char *buf, size_t count) 83 { 84 struct eud_chip *chip = dev_get_drvdata(dev); 85 bool enable; 86 int ret; 87 88 if (kstrtobool(buf, &enable)) 89 return -EINVAL; 90 91 if (enable) { 92 ret = enable_eud(chip); 93 if (!ret) 94 chip->enabled = enable; 95 else 96 disable_eud(chip); 97 98 } else { 99 ret = disable_eud(chip); 100 } 101 102 return ret < 0 ? ret : count; 103 } 104 105 static DEVICE_ATTR_RW(enable); 106 107 static struct attribute *eud_attrs[] = { 108 &dev_attr_enable.attr, 109 NULL, 110 }; 111 ATTRIBUTE_GROUPS(eud); 112 113 static void usb_attach_detach(struct eud_chip *chip) 114 { 115 u32 reg; 116 117 /* read ctl_out_1[4] to find USB attach or detach event */ 118 reg = readl(chip->base + EUD_REG_CTL_OUT_1); 119 chip->usb_attached = reg & EUD_INT_SAFE_MODE; 120 } 121 122 static void pet_eud(struct eud_chip *chip) 123 { 124 u32 reg; 125 int ret; 126 127 /* When the EUD_INT_PET_EUD in SW_ATTACH_DET is set, the cable has been 128 * disconnected and we need to detach the pet to check if EUD is in safe 129 * mode before attaching again. 130 */ 131 reg = readl(chip->base + EUD_REG_SW_ATTACH_DET); 132 if (reg & EUD_INT_PET_EUD) { 133 /* Detach & Attach pet for EUD */ 134 writel(0, chip->base + EUD_REG_SW_ATTACH_DET); 135 /* Delay to make sure detach pet is done before attach pet */ 136 ret = readl_poll_timeout(chip->base + EUD_REG_SW_ATTACH_DET, 137 reg, (reg == 0), 1, 100); 138 if (ret) { 139 dev_err(chip->dev, "Detach pet failed\n"); 140 return; 141 } 142 } 143 /* Attach pet for EUD */ 144 writel(EUD_INT_PET_EUD, chip->base + EUD_REG_SW_ATTACH_DET); 145 } 146 147 static irqreturn_t handle_eud_irq(int irq, void *data) 148 { 149 struct eud_chip *chip = data; 150 u32 reg; 151 152 reg = readl(chip->base + EUD_REG_INT_STATUS_1); 153 switch (reg & EUD_INT_ALL) { 154 case EUD_INT_VBUS: 155 usb_attach_detach(chip); 156 return IRQ_WAKE_THREAD; 157 case EUD_INT_SAFE_MODE: 158 pet_eud(chip); 159 return IRQ_HANDLED; 160 default: 161 return IRQ_NONE; 162 } 163 } 164 165 static irqreturn_t handle_eud_irq_thread(int irq, void *data) 166 { 167 struct eud_chip *chip = data; 168 int ret; 169 170 if (chip->usb_attached) 171 ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_DEVICE); 172 else 173 ret = usb_role_switch_set_role(chip->role_sw, USB_ROLE_HOST); 174 if (ret) 175 dev_err(chip->dev, "failed to set role switch\n"); 176 177 /* set and clear vbus_int_clr[0] to clear interrupt */ 178 writel(BIT(0), chip->base + EUD_REG_VBUS_INT_CLR); 179 writel(0, chip->base + EUD_REG_VBUS_INT_CLR); 180 181 return IRQ_HANDLED; 182 } 183 184 static void eud_role_switch_release(void *data) 185 { 186 struct eud_chip *chip = data; 187 188 usb_role_switch_put(chip->role_sw); 189 } 190 191 static int eud_probe(struct platform_device *pdev) 192 { 193 struct eud_chip *chip; 194 struct resource *res; 195 int ret; 196 197 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 198 if (!chip) 199 return -ENOMEM; 200 201 chip->dev = &pdev->dev; 202 203 chip->role_sw = usb_role_switch_get(&pdev->dev); 204 if (IS_ERR(chip->role_sw)) 205 return dev_err_probe(chip->dev, PTR_ERR(chip->role_sw), 206 "failed to get role switch\n"); 207 208 ret = devm_add_action_or_reset(chip->dev, eud_role_switch_release, chip); 209 if (ret) 210 return ret; 211 212 chip->base = devm_platform_ioremap_resource(pdev, 0); 213 if (IS_ERR(chip->base)) 214 return PTR_ERR(chip->base); 215 216 res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 217 if (!res) 218 return -ENODEV; 219 chip->mode_mgr = res->start; 220 221 chip->irq = platform_get_irq(pdev, 0); 222 if (chip->irq < 0) 223 return chip->irq; 224 225 ret = devm_request_threaded_irq(&pdev->dev, chip->irq, handle_eud_irq, 226 handle_eud_irq_thread, IRQF_ONESHOT, NULL, chip); 227 if (ret) 228 return dev_err_probe(chip->dev, ret, "failed to allocate irq\n"); 229 230 enable_irq_wake(chip->irq); 231 232 platform_set_drvdata(pdev, chip); 233 234 return 0; 235 } 236 237 static void eud_remove(struct platform_device *pdev) 238 { 239 struct eud_chip *chip = platform_get_drvdata(pdev); 240 241 if (chip->enabled) 242 disable_eud(chip); 243 244 device_init_wakeup(&pdev->dev, false); 245 disable_irq_wake(chip->irq); 246 } 247 248 static const struct of_device_id eud_dt_match[] = { 249 { .compatible = "qcom,eud" }, 250 { } 251 }; 252 MODULE_DEVICE_TABLE(of, eud_dt_match); 253 254 static struct platform_driver eud_driver = { 255 .probe = eud_probe, 256 .remove = eud_remove, 257 .driver = { 258 .name = "qcom_eud", 259 .dev_groups = eud_groups, 260 .of_match_table = eud_dt_match, 261 }, 262 }; 263 module_platform_driver(eud_driver); 264 265 MODULE_DESCRIPTION("QTI EUD driver"); 266 MODULE_LICENSE("GPL v2"); 267