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
enable_eud(struct eud_chip * priv)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
disable_eud(struct eud_chip * priv)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
enable_show(struct device * dev,struct device_attribute * attr,char * buf)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
enable_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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
usb_attach_detach(struct eud_chip * chip)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
pet_eud(struct eud_chip * chip)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
handle_eud_irq(int irq,void * data)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
handle_eud_irq_thread(int irq,void * data)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
eud_role_switch_release(void * data)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
eud_probe(struct platform_device * pdev)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
eud_remove(struct platform_device * pdev)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