aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-11-10 07:57:34 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-11-10 07:57:34 -0500
commitd5335b3dfc614fbb4ce2b352177f38521ec3ecdd (patch)
tree4bc6a8a5b291dd2bd81ef04a0be8e71e9efc0465
parentaa4330e15c26c5ef8dd184f515c0655db8c6df3a (diff)
parent247c554a14aa16ca08f4ed4d9eb39a2389f69d1d (diff)
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: "I2C has one bugfix (qcom-geni driver), one arch enablement (i2c-omap driver, no code change), and a new driver (nvidia-gpu) this time" * 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: usb: typec: ucsi: add support for Cypress CCGx i2c: nvidia-gpu: make pm_ops static i2c: add i2c bus driver for NVIDIA GPU i2c: qcom-geni: Fix runtime PM mismatch with child devices MAINTAINERS: Add entry for i2c-omap driver i2c: omap: Enable for ARCH_K3 dt-bindings: i2c: omap: Add new compatible for AM654 SoCs
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-omap.txt8
-rw-r--r--Documentation/i2c/busses/i2c-nvidia-gpu18
-rw-r--r--MAINTAINERS15
-rw-r--r--drivers/i2c/busses/Kconfig11
-rw-r--r--drivers/i2c/busses/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-nvidia-gpu.c368
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c15
-rw-r--r--drivers/usb/typec/ucsi/Kconfig10
-rw-r--r--drivers/usb/typec/ucsi/Makefile2
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c307
10 files changed, 745 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/i2c/i2c-omap.txt b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
index 7e49839d4124..4b90ba9f31b7 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-omap.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-omap.txt
@@ -1,8 +1,12 @@
1I2C for OMAP platforms 1I2C for OMAP platforms
2 2
3Required properties : 3Required properties :
4- compatible : Must be "ti,omap2420-i2c", "ti,omap2430-i2c", "ti,omap3-i2c" 4- compatible : Must be
5 or "ti,omap4-i2c" 5 "ti,omap2420-i2c" for OMAP2420 SoCs
6 "ti,omap2430-i2c" for OMAP2430 SoCs
7 "ti,omap3-i2c" for OMAP3 SoCs
8 "ti,omap4-i2c" for OMAP4+ SoCs
9 "ti,am654-i2c", "ti,omap4-i2c" for AM654 SoCs
6- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based) 10- ti,hwmods : Must be "i2c<n>", n being the instance number (1-based)
7- #address-cells = <1>; 11- #address-cells = <1>;
8- #size-cells = <0>; 12- #size-cells = <0>;
diff --git a/Documentation/i2c/busses/i2c-nvidia-gpu b/Documentation/i2c/busses/i2c-nvidia-gpu
new file mode 100644
index 000000000000..31884d2b2eb5
--- /dev/null
+++ b/Documentation/i2c/busses/i2c-nvidia-gpu
@@ -0,0 +1,18 @@
1Kernel driver i2c-nvidia-gpu
2
3Datasheet: not publicly available.
4
5Authors:
6 Ajay Gupta <ajayg@nvidia.com>
7
8Description
9-----------
10
11i2c-nvidia-gpu is a driver for I2C controller included in NVIDIA Turing
12and later GPUs and it is used to communicate with Type-C controller on GPUs.
13
14If your 'lspci -v' listing shows something like the following,
15
1601:00.3 Serial bus controller [0c80]: NVIDIA Corporation Device 1ad9 (rev a1)
17
18then this driver should support the I2C controller of your GPU.
diff --git a/MAINTAINERS b/MAINTAINERS
index 95e56fd128a5..0abecc528dac 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6861,6 +6861,13 @@ L: linux-acpi@vger.kernel.org
6861S: Maintained 6861S: Maintained
6862F: drivers/i2c/i2c-core-acpi.c 6862F: drivers/i2c/i2c-core-acpi.c
6863 6863
6864I2C CONTROLLER DRIVER FOR NVIDIA GPU
6865M: Ajay Gupta <ajayg@nvidia.com>
6866L: linux-i2c@vger.kernel.org
6867S: Maintained
6868F: Documentation/i2c/busses/i2c-nvidia-gpu
6869F: drivers/i2c/busses/i2c-nvidia-gpu.c
6870
6864I2C MUXES 6871I2C MUXES
6865M: Peter Rosin <peda@axentia.se> 6872M: Peter Rosin <peda@axentia.se>
6866L: linux-i2c@vger.kernel.org 6873L: linux-i2c@vger.kernel.org
@@ -10784,6 +10791,14 @@ L: linux-omap@vger.kernel.org
10784S: Maintained 10791S: Maintained
10785F: arch/arm/mach-omap2/omap_hwmod.* 10792F: arch/arm/mach-omap2/omap_hwmod.*
10786 10793
10794OMAP I2C DRIVER
10795M: Vignesh R <vigneshr@ti.com>
10796L: linux-omap@vger.kernel.org
10797L: linux-i2c@vger.kernel.org
10798S: Maintained
10799F: Documentation/devicetree/bindings/i2c/i2c-omap.txt
10800F: drivers/i2c/busses/i2c-omap.c
10801
10787OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS) 10802OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
10788M: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 10803M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
10789L: linux-media@vger.kernel.org 10804L: linux-media@vger.kernel.org
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 56ccb1ea7da5..f2c681971201 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -224,6 +224,15 @@ config I2C_NFORCE2_S4985
224 This driver can also be built as a module. If so, the module 224 This driver can also be built as a module. If so, the module
225 will be called i2c-nforce2-s4985. 225 will be called i2c-nforce2-s4985.
226 226
227config I2C_NVIDIA_GPU
228 tristate "NVIDIA GPU I2C controller"
229 depends on PCI
230 help
231 If you say yes to this option, support will be included for the
232 NVIDIA GPU I2C controller which is used to communicate with the GPU's
233 Type-C controller. This driver can also be built as a module called
234 i2c-nvidia-gpu.
235
227config I2C_SIS5595 236config I2C_SIS5595
228 tristate "SiS 5595" 237 tristate "SiS 5595"
229 depends on PCI 238 depends on PCI
@@ -752,7 +761,7 @@ config I2C_OCORES
752 761
753config I2C_OMAP 762config I2C_OMAP
754 tristate "OMAP I2C adapter" 763 tristate "OMAP I2C adapter"
755 depends on ARCH_OMAP 764 depends on ARCH_OMAP || ARCH_K3
756 default y if MACH_OMAP_H3 || MACH_OMAP_OSK 765 default y if MACH_OMAP_H3 || MACH_OMAP_OSK
757 help 766 help
758 If you say yes to this option, support will be included for the 767 If you say yes to this option, support will be included for the
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 18b26af82b1c..5f0cb6915969 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_I2C_ISCH) += i2c-isch.o
19obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o 19obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o
20obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o 20obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o
21obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o 21obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o
22obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o
22obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o 23obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
23obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o 24obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
24obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o 25obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c
new file mode 100644
index 000000000000..8822357bca0c
--- /dev/null
+++ b/drivers/i2c/busses/i2c-nvidia-gpu.c
@@ -0,0 +1,368 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Nvidia GPU I2C controller Driver
4 *
5 * Copyright (C) 2018 NVIDIA Corporation. All rights reserved.
6 * Author: Ajay Gupta <ajayg@nvidia.com>
7 */
8#include <linux/delay.h>
9#include <linux/i2c.h>
10#include <linux/interrupt.h>
11#include <linux/module.h>
12#include <linux/pci.h>
13#include <linux/platform_device.h>
14#include <linux/pm.h>
15#include <linux/pm_runtime.h>
16
17#include <asm/unaligned.h>
18
19/* I2C definitions */
20#define I2C_MST_CNTL 0x00
21#define I2C_MST_CNTL_GEN_START BIT(0)
22#define I2C_MST_CNTL_GEN_STOP BIT(1)
23#define I2C_MST_CNTL_CMD_READ (1 << 2)
24#define I2C_MST_CNTL_CMD_WRITE (2 << 2)
25#define I2C_MST_CNTL_BURST_SIZE_SHIFT 6
26#define I2C_MST_CNTL_GEN_NACK BIT(28)
27#define I2C_MST_CNTL_STATUS GENMASK(30, 29)
28#define I2C_MST_CNTL_STATUS_OKAY (0 << 29)
29#define I2C_MST_CNTL_STATUS_NO_ACK (1 << 29)
30#define I2C_MST_CNTL_STATUS_TIMEOUT (2 << 29)
31#define I2C_MST_CNTL_STATUS_BUS_BUSY (3 << 29)
32#define I2C_MST_CNTL_CYCLE_TRIGGER BIT(31)
33
34#define I2C_MST_ADDR 0x04
35
36#define I2C_MST_I2C0_TIMING 0x08
37#define I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ 0x10e
38#define I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT 16
39#define I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX 255
40#define I2C_MST_I2C0_TIMING_TIMEOUT_CHECK BIT(24)
41
42#define I2C_MST_DATA 0x0c
43
44#define I2C_MST_HYBRID_PADCTL 0x20
45#define I2C_MST_HYBRID_PADCTL_MODE_I2C BIT(0)
46#define I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV BIT(14)
47#define I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV BIT(15)
48
49struct gpu_i2c_dev {
50 struct device *dev;
51 void __iomem *regs;
52 struct i2c_adapter adapter;
53 struct i2c_board_info *gpu_ccgx_ucsi;
54};
55
56static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd)
57{
58 u32 val;
59
60 /* enable I2C */
61 val = readl(i2cd->regs + I2C_MST_HYBRID_PADCTL);
62 val |= I2C_MST_HYBRID_PADCTL_MODE_I2C |
63 I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV |
64 I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV;
65 writel(val, i2cd->regs + I2C_MST_HYBRID_PADCTL);
66
67 /* enable 100KHZ mode */
68 val = I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ;
69 val |= (I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX
70 << I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT);
71 val |= I2C_MST_I2C0_TIMING_TIMEOUT_CHECK;
72 writel(val, i2cd->regs + I2C_MST_I2C0_TIMING);
73}
74
75static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd)
76{
77 unsigned long target = jiffies + msecs_to_jiffies(1000);
78 u32 val;
79
80 do {
81 val = readl(i2cd->regs + I2C_MST_CNTL);
82 if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER))
83 break;
84 if ((val & I2C_MST_CNTL_STATUS) !=
85 I2C_MST_CNTL_STATUS_BUS_BUSY)
86 break;
87 usleep_range(500, 600);
88 } while (time_is_after_jiffies(target));
89
90 if (time_is_before_jiffies(target)) {
91 dev_err(i2cd->dev, "i2c timeout error %x\n", val);
92 return -ETIME;
93 }
94
95 val = readl(i2cd->regs + I2C_MST_CNTL);
96 switch (val & I2C_MST_CNTL_STATUS) {
97 case I2C_MST_CNTL_STATUS_OKAY:
98 return 0;
99 case I2C_MST_CNTL_STATUS_NO_ACK:
100 return -EIO;
101 case I2C_MST_CNTL_STATUS_TIMEOUT:
102 return -ETIME;
103 default:
104 return 0;
105 }
106}
107
108static int gpu_i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len)
109{
110 int status;
111 u32 val;
112
113 val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_CMD_READ |
114 (len << I2C_MST_CNTL_BURST_SIZE_SHIFT) |
115 I2C_MST_CNTL_CYCLE_TRIGGER | I2C_MST_CNTL_GEN_NACK;
116 writel(val, i2cd->regs + I2C_MST_CNTL);
117
118 status = gpu_i2c_check_status(i2cd);
119 if (status < 0)
120 return status;
121
122 val = readl(i2cd->regs + I2C_MST_DATA);
123 switch (len) {
124 case 1:
125 data[0] = val;
126 break;
127 case 2:
128 put_unaligned_be16(val, data);
129 break;
130 case 3:
131 put_unaligned_be16(val >> 8, data);
132 data[2] = val;
133 break;
134 case 4:
135 put_unaligned_be32(val, data);
136 break;
137 default:
138 break;
139 }
140 return status;
141}
142
143static int gpu_i2c_start(struct gpu_i2c_dev *i2cd)
144{
145 writel(I2C_MST_CNTL_GEN_START, i2cd->regs + I2C_MST_CNTL);
146 return gpu_i2c_check_status(i2cd);
147}
148
149static int gpu_i2c_stop(struct gpu_i2c_dev *i2cd)
150{
151 writel(I2C_MST_CNTL_GEN_STOP, i2cd->regs + I2C_MST_CNTL);
152 return gpu_i2c_check_status(i2cd);
153}
154
155static int gpu_i2c_write(struct gpu_i2c_dev *i2cd, u8 data)
156{
157 u32 val;
158
159 writel(data, i2cd->regs + I2C_MST_DATA);
160
161 val = I2C_MST_CNTL_CMD_WRITE | (1 << I2C_MST_CNTL_BURST_SIZE_SHIFT);
162 writel(val, i2cd->regs + I2C_MST_CNTL);
163
164 return gpu_i2c_check_status(i2cd);
165}
166
167static int gpu_i2c_master_xfer(struct i2c_adapter *adap,
168 struct i2c_msg *msgs, int num)
169{
170 struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap);
171 int status, status2;
172 int i, j;
173
174 /*
175 * The controller supports maximum 4 byte read due to known
176 * limitation of sending STOP after every read.
177 */
178 for (i = 0; i < num; i++) {
179 if (msgs[i].flags & I2C_M_RD) {
180 /* program client address before starting read */
181 writel(msgs[i].addr, i2cd->regs + I2C_MST_ADDR);
182 /* gpu_i2c_read has implicit start */
183 status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len);
184 if (status < 0)
185 goto stop;
186 } else {
187 u8 addr = i2c_8bit_addr_from_msg(msgs + i);
188
189 status = gpu_i2c_start(i2cd);
190 if (status < 0) {
191 if (i == 0)
192 return status;
193 goto stop;
194 }
195
196 status = gpu_i2c_write(i2cd, addr);
197 if (status < 0)
198 goto stop;
199
200 for (j = 0; j < msgs[i].len; j++) {
201 status = gpu_i2c_write(i2cd, msgs[i].buf[j]);
202 if (status < 0)
203 goto stop;
204 }
205 }
206 }
207 status = gpu_i2c_stop(i2cd);
208 if (status < 0)
209 return status;
210
211 return i;
212stop:
213 status2 = gpu_i2c_stop(i2cd);
214 if (status2 < 0)
215 dev_err(i2cd->dev, "i2c stop failed %d\n", status2);
216 return status;
217}
218
219static const struct i2c_adapter_quirks gpu_i2c_quirks = {
220 .max_read_len = 4,
221 .flags = I2C_AQ_COMB_WRITE_THEN_READ,
222};
223
224static u32 gpu_i2c_functionality(struct i2c_adapter *adap)
225{
226 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
227}
228
229static const struct i2c_algorithm gpu_i2c_algorithm = {
230 .master_xfer = gpu_i2c_master_xfer,
231 .functionality = gpu_i2c_functionality,
232};
233
234/*
235 * This driver is for Nvidia GPU cards with USB Type-C interface.
236 * We want to identify the cards using vendor ID and class code only
237 * to avoid dependency of adding product id for any new card which
238 * requires this driver.
239 * Currently there is no class code defined for UCSI device over PCI
240 * so using UNKNOWN class for now and it will be updated when UCSI
241 * over PCI gets a class code.
242 * There is no other NVIDIA cards with UNKNOWN class code. Even if the
243 * driver gets loaded for an undesired card then eventually i2c_read()
244 * (initiated from UCSI i2c_client) will timeout or UCSI commands will
245 * timeout.
246 */
247#define PCI_CLASS_SERIAL_UNKNOWN 0x0c80
248static const struct pci_device_id gpu_i2c_ids[] = {
249 { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
250 PCI_CLASS_SERIAL_UNKNOWN << 8, 0xffffff00},
251 { }
252};
253MODULE_DEVICE_TABLE(pci, gpu_i2c_ids);
254
255static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq)
256{
257 struct i2c_client *ccgx_client;
258
259 i2cd->gpu_ccgx_ucsi = devm_kzalloc(i2cd->dev,
260 sizeof(*i2cd->gpu_ccgx_ucsi),
261 GFP_KERNEL);
262 if (!i2cd->gpu_ccgx_ucsi)
263 return -ENOMEM;
264
265 strlcpy(i2cd->gpu_ccgx_ucsi->type, "ccgx-ucsi",
266 sizeof(i2cd->gpu_ccgx_ucsi->type));
267 i2cd->gpu_ccgx_ucsi->addr = 0x8;
268 i2cd->gpu_ccgx_ucsi->irq = irq;
269 ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi);
270 if (!ccgx_client)
271 return -ENODEV;
272
273 return 0;
274}
275
276static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id)
277{
278 struct gpu_i2c_dev *i2cd;
279 int status;
280
281 i2cd = devm_kzalloc(&pdev->dev, sizeof(*i2cd), GFP_KERNEL);
282 if (!i2cd)
283 return -ENOMEM;
284
285 i2cd->dev = &pdev->dev;
286 dev_set_drvdata(&pdev->dev, i2cd);
287
288 status = pcim_enable_device(pdev);
289 if (status < 0) {
290 dev_err(&pdev->dev, "pcim_enable_device failed %d\n", status);
291 return status;
292 }
293
294 pci_set_master(pdev);
295
296 i2cd->regs = pcim_iomap(pdev, 0, 0);
297 if (!i2cd->regs) {
298 dev_err(&pdev->dev, "pcim_iomap failed\n");
299 return -ENOMEM;
300 }
301
302 status = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
303 if (status < 0) {
304 dev_err(&pdev->dev, "pci_alloc_irq_vectors err %d\n", status);
305 return status;
306 }
307
308 gpu_enable_i2c_bus(i2cd);
309
310 i2c_set_adapdata(&i2cd->adapter, i2cd);
311 i2cd->adapter.owner = THIS_MODULE;
312 strlcpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter",
313 sizeof(i2cd->adapter.name));
314 i2cd->adapter.algo = &gpu_i2c_algorithm;
315 i2cd->adapter.quirks = &gpu_i2c_quirks;
316 i2cd->adapter.dev.parent = &pdev->dev;
317 status = i2c_add_adapter(&i2cd->adapter);
318 if (status < 0)
319 goto free_irq_vectors;
320
321 status = gpu_populate_client(i2cd, pdev->irq);
322 if (status < 0) {
323 dev_err(&pdev->dev, "gpu_populate_client failed %d\n", status);
324 goto del_adapter;
325 }
326
327 return 0;
328
329del_adapter:
330 i2c_del_adapter(&i2cd->adapter);
331free_irq_vectors:
332 pci_free_irq_vectors(pdev);
333 return status;
334}
335
336static void gpu_i2c_remove(struct pci_dev *pdev)
337{
338 struct gpu_i2c_dev *i2cd = dev_get_drvdata(&pdev->dev);
339
340 i2c_del_adapter(&i2cd->adapter);
341 pci_free_irq_vectors(pdev);
342}
343
344static int gpu_i2c_resume(struct device *dev)
345{
346 struct gpu_i2c_dev *i2cd = dev_get_drvdata(dev);
347
348 gpu_enable_i2c_bus(i2cd);
349 return 0;
350}
351
352static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, NULL, gpu_i2c_resume, NULL);
353
354static struct pci_driver gpu_i2c_driver = {
355 .name = "nvidia-gpu",
356 .id_table = gpu_i2c_ids,
357 .probe = gpu_i2c_probe,
358 .remove = gpu_i2c_remove,
359 .driver = {
360 .pm = &gpu_i2c_driver_pm,
361 },
362};
363
364module_pci_driver(gpu_i2c_driver);
365
366MODULE_AUTHOR("Ajay Gupta <ajayg@nvidia.com>");
367MODULE_DESCRIPTION("Nvidia GPU I2C controller Driver");
368MODULE_LICENSE("GPL v2");
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 527f55c8c4c7..db075bc0d952 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -571,18 +571,19 @@ static int geni_i2c_probe(struct platform_device *pdev)
571 571
572 dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth); 572 dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
573 573
574 ret = i2c_add_adapter(&gi2c->adap);
575 if (ret) {
576 dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret);
577 return ret;
578 }
579
580 gi2c->suspended = 1; 574 gi2c->suspended = 1;
581 pm_runtime_set_suspended(gi2c->se.dev); 575 pm_runtime_set_suspended(gi2c->se.dev);
582 pm_runtime_set_autosuspend_delay(gi2c->se.dev, I2C_AUTO_SUSPEND_DELAY); 576 pm_runtime_set_autosuspend_delay(gi2c->se.dev, I2C_AUTO_SUSPEND_DELAY);
583 pm_runtime_use_autosuspend(gi2c->se.dev); 577 pm_runtime_use_autosuspend(gi2c->se.dev);
584 pm_runtime_enable(gi2c->se.dev); 578 pm_runtime_enable(gi2c->se.dev);
585 579
580 ret = i2c_add_adapter(&gi2c->adap);
581 if (ret) {
582 dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret);
583 pm_runtime_disable(gi2c->se.dev);
584 return ret;
585 }
586
586 return 0; 587 return 0;
587} 588}
588 589
@@ -590,8 +591,8 @@ static int geni_i2c_remove(struct platform_device *pdev)
590{ 591{
591 struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); 592 struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
592 593
593 pm_runtime_disable(gi2c->se.dev);
594 i2c_del_adapter(&gi2c->adap); 594 i2c_del_adapter(&gi2c->adap);
595 pm_runtime_disable(gi2c->se.dev);
595 return 0; 596 return 0;
596} 597}
597 598
diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig
index e36d6c73c4a4..78118883f96c 100644
--- a/drivers/usb/typec/ucsi/Kconfig
+++ b/drivers/usb/typec/ucsi/Kconfig
@@ -23,6 +23,16 @@ config TYPEC_UCSI
23 23
24if TYPEC_UCSI 24if TYPEC_UCSI
25 25
26config UCSI_CCG
27 tristate "UCSI Interface Driver for Cypress CCGx"
28 depends on I2C
29 help
30 This driver enables UCSI support on platforms that expose a
31 Cypress CCGx Type-C controller over I2C interface.
32
33 To compile the driver as a module, choose M here: the module will be
34 called ucsi_ccg.
35
26config UCSI_ACPI 36config UCSI_ACPI
27 tristate "UCSI ACPI Interface Driver" 37 tristate "UCSI ACPI Interface Driver"
28 depends on ACPI 38 depends on ACPI
diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile
index 7afbea512207..2f4900b26210 100644
--- a/drivers/usb/typec/ucsi/Makefile
+++ b/drivers/usb/typec/ucsi/Makefile
@@ -8,3 +8,5 @@ typec_ucsi-y := ucsi.o
8typec_ucsi-$(CONFIG_TRACING) += trace.o 8typec_ucsi-$(CONFIG_TRACING) += trace.o
9 9
10obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o 10obj-$(CONFIG_UCSI_ACPI) += ucsi_acpi.o
11
12obj-$(CONFIG_UCSI_CCG) += ucsi_ccg.o
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
new file mode 100644
index 000000000000..de8a43bdff68
--- /dev/null
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -0,0 +1,307 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * UCSI driver for Cypress CCGx Type-C controller
4 *
5 * Copyright (C) 2017-2018 NVIDIA Corporation. All rights reserved.
6 * Author: Ajay Gupta <ajayg@nvidia.com>
7 *
8 * Some code borrowed from drivers/usb/typec/ucsi/ucsi_acpi.c
9 */
10#include <linux/acpi.h>
11#include <linux/delay.h>
12#include <linux/i2c.h>
13#include <linux/module.h>
14#include <linux/pci.h>
15#include <linux/platform_device.h>
16
17#include <asm/unaligned.h>
18#include "ucsi.h"
19
20struct ucsi_ccg {
21 struct device *dev;
22 struct ucsi *ucsi;
23 struct ucsi_ppm ppm;
24 struct i2c_client *client;
25};
26
27#define CCGX_RAB_INTR_REG 0x06
28#define CCGX_RAB_UCSI_CONTROL 0x39
29#define CCGX_RAB_UCSI_CONTROL_START BIT(0)
30#define CCGX_RAB_UCSI_CONTROL_STOP BIT(1)
31#define CCGX_RAB_UCSI_DATA_BLOCK(offset) (0xf000 | ((offset) & 0xff))
32
33static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
34{
35 struct i2c_client *client = uc->client;
36 const struct i2c_adapter_quirks *quirks = client->adapter->quirks;
37 unsigned char buf[2];
38 struct i2c_msg msgs[] = {
39 {
40 .addr = client->addr,
41 .flags = 0x0,
42 .len = sizeof(buf),
43 .buf = buf,
44 },
45 {
46 .addr = client->addr,
47 .flags = I2C_M_RD,
48 .buf = data,
49 },
50 };
51 u32 rlen, rem_len = len, max_read_len = len;
52 int status;
53
54 /* check any max_read_len limitation on i2c adapter */
55 if (quirks && quirks->max_read_len)
56 max_read_len = quirks->max_read_len;
57
58 while (rem_len > 0) {
59 msgs[1].buf = &data[len - rem_len];
60 rlen = min_t(u16, rem_len, max_read_len);
61 msgs[1].len = rlen;
62 put_unaligned_le16(rab, buf);
63 status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
64 if (status < 0) {
65 dev_err(uc->dev, "i2c_transfer failed %d\n", status);
66 return status;
67 }
68 rab += rlen;
69 rem_len -= rlen;
70 }
71
72 return 0;
73}
74
75static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
76{
77 struct i2c_client *client = uc->client;
78 unsigned char *buf;
79 struct i2c_msg msgs[] = {
80 {
81 .addr = client->addr,
82 .flags = 0x0,
83 }
84 };
85 int status;
86
87 buf = kzalloc(len + sizeof(rab), GFP_KERNEL);
88 if (!buf)
89 return -ENOMEM;
90
91 put_unaligned_le16(rab, buf);
92 memcpy(buf + sizeof(rab), data, len);
93
94 msgs[0].len = len + sizeof(rab);
95 msgs[0].buf = buf;
96
97 status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
98 if (status < 0) {
99 dev_err(uc->dev, "i2c_transfer failed %d\n", status);
100 kfree(buf);
101 return status;
102 }
103
104 kfree(buf);
105 return 0;
106}
107
108static int ucsi_ccg_init(struct ucsi_ccg *uc)
109{
110 unsigned int count = 10;
111 u8 data;
112 int status;
113
114 data = CCGX_RAB_UCSI_CONTROL_STOP;
115 status = ccg_write(uc, CCGX_RAB_UCSI_CONTROL, &data, sizeof(data));
116 if (status < 0)
117 return status;
118
119 data = CCGX_RAB_UCSI_CONTROL_START;
120 status = ccg_write(uc, CCGX_RAB_UCSI_CONTROL, &data, sizeof(data));
121 if (status < 0)
122 return status;
123
124 /*
125 * Flush CCGx RESPONSE queue by acking interrupts. Above ucsi control
126 * register write will push response which must be cleared.
127 */
128 do {
129 status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
130 if (status < 0)
131 return status;
132
133 if (!data)
134 return 0;
135
136 status = ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
137 if (status < 0)
138 return status;
139
140 usleep_range(10000, 11000);
141 } while (--count);
142
143 return -ETIMEDOUT;
144}
145
146static int ucsi_ccg_send_data(struct ucsi_ccg *uc)
147{
148 u8 *ppm = (u8 *)uc->ppm.data;
149 int status;
150 u16 rab;
151
152 rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out));
153 status = ccg_write(uc, rab, ppm +
154 offsetof(struct ucsi_data, message_out),
155 sizeof(uc->ppm.data->message_out));
156 if (status < 0)
157 return status;
158
159 rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl));
160 return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl),
161 sizeof(uc->ppm.data->ctrl));
162}
163
164static int ucsi_ccg_recv_data(struct ucsi_ccg *uc)
165{
166 u8 *ppm = (u8 *)uc->ppm.data;
167 int status;
168 u16 rab;
169
170 rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci));
171 status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci),
172 sizeof(uc->ppm.data->cci));
173 if (status < 0)
174 return status;
175
176 rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in));
177 return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in),
178 sizeof(uc->ppm.data->message_in));
179}
180
181static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc)
182{
183 int status;
184 unsigned char data;
185
186 status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
187 if (status < 0)
188 return status;
189
190 return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
191}
192
193static int ucsi_ccg_sync(struct ucsi_ppm *ppm)
194{
195 struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
196 int status;
197
198 status = ucsi_ccg_recv_data(uc);
199 if (status < 0)
200 return status;
201
202 /* ack interrupt to allow next command to run */
203 return ucsi_ccg_ack_interrupt(uc);
204}
205
206static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
207{
208 struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
209
210 ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
211 return ucsi_ccg_send_data(uc);
212}
213
214static irqreturn_t ccg_irq_handler(int irq, void *data)
215{
216 struct ucsi_ccg *uc = data;
217
218 ucsi_notify(uc->ucsi);
219
220 return IRQ_HANDLED;
221}
222
223static int ucsi_ccg_probe(struct i2c_client *client,
224 const struct i2c_device_id *id)
225{
226 struct device *dev = &client->dev;
227 struct ucsi_ccg *uc;
228 int status;
229 u16 rab;
230
231 uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
232 if (!uc)
233 return -ENOMEM;
234
235 uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL);
236 if (!uc->ppm.data)
237 return -ENOMEM;
238
239 uc->ppm.cmd = ucsi_ccg_cmd;
240 uc->ppm.sync = ucsi_ccg_sync;
241 uc->dev = dev;
242 uc->client = client;
243
244 /* reset ccg device and initialize ucsi */
245 status = ucsi_ccg_init(uc);
246 if (status < 0) {
247 dev_err(uc->dev, "ucsi_ccg_init failed - %d\n", status);
248 return status;
249 }
250
251 status = devm_request_threaded_irq(dev, client->irq, NULL,
252 ccg_irq_handler,
253 IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
254 dev_name(dev), uc);
255 if (status < 0) {
256 dev_err(uc->dev, "request_threaded_irq failed - %d\n", status);
257 return status;
258 }
259
260 uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
261 if (IS_ERR(uc->ucsi)) {
262 dev_err(uc->dev, "ucsi_register_ppm failed\n");
263 return PTR_ERR(uc->ucsi);
264 }
265
266 rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version));
267 status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) +
268 offsetof(struct ucsi_data, version),
269 sizeof(uc->ppm.data->version));
270 if (status < 0) {
271 ucsi_unregister_ppm(uc->ucsi);
272 return status;
273 }
274
275 i2c_set_clientdata(client, uc);
276 return 0;
277}
278
279static int ucsi_ccg_remove(struct i2c_client *client)
280{
281 struct ucsi_ccg *uc = i2c_get_clientdata(client);
282
283 ucsi_unregister_ppm(uc->ucsi);
284
285 return 0;
286}
287
288static const struct i2c_device_id ucsi_ccg_device_id[] = {
289 {"ccgx-ucsi", 0},
290 {}
291};
292MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id);
293
294static struct i2c_driver ucsi_ccg_driver = {
295 .driver = {
296 .name = "ucsi_ccg",
297 },
298 .probe = ucsi_ccg_probe,
299 .remove = ucsi_ccg_remove,
300 .id_table = ucsi_ccg_device_id,
301};
302
303module_i2c_driver(ucsi_ccg_driver);
304
305MODULE_AUTHOR("Ajay Gupta <ajayg@nvidia.com>");
306MODULE_DESCRIPTION("UCSI driver for Cypress CCGx Type-C controller");
307MODULE_LICENSE("GPL v2");