1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
4  *
5  * based on original code from:
6  * (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
7  */
8 
9 #include <dm.h>
10 #include <dm/device-internal.h>
11 #include <dm/device_compat.h>
12 #include <dm/devres.h>
13 #include <dm/lists.h>
14 #include <linux/bug.h>
15 #include <linux/io.h>
16 #include <linux/kernel.h>
17 #include <linux/usb/otg.h>
18 #include <log.h>
19 #include <usb.h>
20 
21 #include "isp1760-core.h"
22 #include "isp1760-regs.h"
23 #include "isp1760-uboot.h"
24 
isp1760_of_to_plat(struct udevice * dev)25 static int isp1760_of_to_plat(struct udevice *dev)
26 {
27 	struct isp1760_device *isp = dev_get_plat(dev);
28 	unsigned int devflags = 0;
29 	u32 bus_width = 0;
30 	ofnode dp;
31 
32 	if (!dev_has_ofnode(dev)) {
33 		/* select isp1763 as the default device */
34 		devflags = ISP1760_FLAG_ISP1763 | ISP1760_FLAG_BUS_WIDTH_16;
35 		pr_err("isp1760: no platform data\n");
36 		goto isp_setup;
37 	}
38 
39 	dp = dev_ofnode(dev);
40 
41 	if (ofnode_device_is_compatible(dp, "nxp,usb-isp1761"))
42 		devflags |= ISP1760_FLAG_ISP1761;
43 
44 	if (ofnode_device_is_compatible(dp, "nxp,usb-isp1763"))
45 		devflags |= ISP1760_FLAG_ISP1763;
46 
47 	/*
48 	 * Some systems wire up only 8 of 16 data lines or
49 	 * 16 of the 32 data lines
50 	 */
51 	bus_width = ofnode_read_u32_default(dp, "bus-width", 16);
52 	if (bus_width == 16)
53 		devflags |= ISP1760_FLAG_BUS_WIDTH_16;
54 	else if (bus_width == 8)
55 		devflags |= ISP1760_FLAG_BUS_WIDTH_8;
56 
57 	if (usb_get_dr_mode(dev_ofnode(dev)) == USB_DR_MODE_PERIPHERAL)
58 		devflags |= ISP1760_FLAG_PERIPHERAL_EN;
59 
60 	if (ofnode_read_bool(dp, "analog-oc"))
61 		devflags |= ISP1760_FLAG_ANALOG_OC;
62 
63 	if (ofnode_read_bool(dp, "dack-polarity"))
64 		devflags |= ISP1760_FLAG_DACK_POL_HIGH;
65 
66 	if (ofnode_read_bool(dp, "dreq-polarity"))
67 		devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
68 
69 isp_setup:
70 	isp->devflags = devflags;
71 	isp->dev = dev;
72 
73 	return 0;
74 }
75 
isp1760_plat_probe(struct udevice * dev)76 static int isp1760_plat_probe(struct udevice *dev)
77 {
78 	struct isp1760_device *isp = dev_get_plat(dev);
79 	struct resource mem_res;
80 	struct resource irq_res;
81 	int ret;
82 
83 	dev_read_resource(dev, 0, &mem_res);
84 	dev_read_resource(dev, 1, &irq_res);
85 
86 	isp1760_init_kmem_once();
87 
88 	ret = isp1760_register(isp, &mem_res, irq_res.start, irq_res.flags);
89 	if (ret < 0) {
90 		isp1760_deinit_kmem_cache();
91 		return ret;
92 	}
93 
94 	return 0;
95 }
96 
isp1760_plat_remove(struct udevice * dev)97 static int isp1760_plat_remove(struct udevice *dev)
98 {
99 	struct isp1760_device *isp = dev_get_plat(dev);
100 
101 	isp1760_deinit_kmem_cache();
102 	isp1760_unregister(isp);
103 
104 	return 0;
105 }
106 
107 static const struct udevice_id isp1760_ids[] = {
108 	{ .compatible = "nxp,usb-isp1760", },
109 	{ .compatible = "nxp,usb-isp1761", },
110 	{ .compatible = "nxp,usb-isp1763", },
111 	{ },
112 };
113 
114 U_BOOT_DRIVER(isp1760) = {
115 	.name		= "isp1760",
116 	.id		= UCLASS_USB,
117 	.of_match	= isp1760_ids,
118 	.of_to_plat	= isp1760_of_to_plat,
119 	.ops		= &isp1760_usb_ops,
120 	.probe		= isp1760_plat_probe,
121 	.remove		= isp1760_plat_remove,
122 	.plat_auto	= sizeof(struct isp1760_device),
123 	.priv_auto	= sizeof(struct isp1760_host_data),
124 };
125