2 * Driver for the NXP ISP1760 chip
4 * Copyright 2014 Laurent Pinchart
5 * Copyright 2007 Sebastian Siewior
8 * Sebastian Siewior <bigeasy@linutronix.de>
9 * Laurent Pinchart <laurent.pinchart@ideasonboard.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
16 #include <linux/delay.h>
17 #include <linux/gpio/consumer.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/slab.h>
22 #include <linux/usb.h>
24 #include "isp1760-core.h"
25 #include "isp1760-hcd.h"
26 #include "isp1760-regs.h"
27 #include "isp1760-udc.h"
29 static void isp1760_init_core(struct isp1760_device
*isp
)
34 /* Low-level chip reset */
36 gpiod_set_value_cansleep(isp
->rst_gpio
, 1);
38 gpiod_set_value_cansleep(isp
->rst_gpio
, 0);
42 * Reset the host controller, including the CPU interface
45 isp1760_write32(isp
->regs
, HC_RESET_REG
, SW_RESET_RESET_ALL
);
48 /* Setup HW Mode Control: This assumes a level active-low interrupt */
49 hwmode
= HW_DATA_BUS_32BIT
;
51 if (isp
->devflags
& ISP1760_FLAG_BUS_WIDTH_16
)
52 hwmode
&= ~HW_DATA_BUS_32BIT
;
53 if (isp
->devflags
& ISP1760_FLAG_ANALOG_OC
)
54 hwmode
|= HW_ANA_DIGI_OC
;
55 if (isp
->devflags
& ISP1760_FLAG_DACK_POL_HIGH
)
56 hwmode
|= HW_DACK_POL_HIGH
;
57 if (isp
->devflags
& ISP1760_FLAG_DREQ_POL_HIGH
)
58 hwmode
|= HW_DREQ_POL_HIGH
;
59 if (isp
->devflags
& ISP1760_FLAG_INTR_POL_HIGH
)
60 hwmode
|= HW_INTR_HIGH_ACT
;
61 if (isp
->devflags
& ISP1760_FLAG_INTR_EDGE_TRIG
)
62 hwmode
|= HW_INTR_EDGE_TRIG
;
65 * The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
66 * IRQ line for both the host and device controllers. Hardcode IRQ
67 * sharing for now and disable the DC interrupts globally to avoid
68 * spurious interrupts during HCD registration.
70 if (isp
->devflags
& ISP1760_FLAG_ISP1761
) {
71 isp1760_write32(isp
->regs
, DC_MODE
, 0);
72 hwmode
|= HW_COMN_IRQ
;
76 * We have to set this first in case we're in 16-bit mode.
77 * Write it twice to ensure correct upper bits if switching
80 isp1760_write32(isp
->regs
, HC_HW_MODE_CTRL
, hwmode
);
81 isp1760_write32(isp
->regs
, HC_HW_MODE_CTRL
, hwmode
);
84 * PORT 1 Control register of the ISP1760 is the OTG control register
87 * TODO: Really support OTG. For now we configure port 1 in device mode
88 * when OTG is requested.
90 if ((isp
->devflags
& ISP1760_FLAG_ISP1761
) &&
91 (isp
->devflags
& ISP1760_FLAG_OTG_EN
))
92 otgctrl
= ((HW_DM_PULLDOWN
| HW_DP_PULLDOWN
) << 16)
95 otgctrl
= (HW_SW_SEL_HC_DC
<< 16)
96 | (HW_VBUS_DRV
| HW_SEL_CP_EXT
);
98 isp1760_write32(isp
->regs
, HC_PORT1_CTRL
, otgctrl
);
100 dev_info(isp
->dev
, "bus width: %u, oc: %s\n",
101 isp
->devflags
& ISP1760_FLAG_BUS_WIDTH_16
? 16 : 32,
102 isp
->devflags
& ISP1760_FLAG_ANALOG_OC
? "analog" : "digital");
105 void isp1760_set_pullup(struct isp1760_device
*isp
, bool enable
)
107 isp1760_write32(isp
->regs
, HW_OTG_CTRL_SET
,
108 enable
? HW_DP_PULLUP
: HW_DP_PULLUP
<< 16);
111 int isp1760_register(struct resource
*mem
, int irq
, unsigned long irqflags
,
112 struct device
*dev
, unsigned int devflags
)
114 struct isp1760_device
*isp
;
120 /* prevent usb-core allocating DMA pages */
121 dev
->dma_mask
= NULL
;
123 isp
= devm_kzalloc(dev
, sizeof(*isp
), GFP_KERNEL
);
128 isp
->devflags
= devflags
;
130 isp
->rst_gpio
= devm_gpiod_get_optional(dev
, NULL
, GPIOD_OUT_HIGH
);
131 if (IS_ERR(isp
->rst_gpio
))
132 return PTR_ERR(isp
->rst_gpio
);
134 isp
->regs
= devm_ioremap_resource(dev
, mem
);
135 if (IS_ERR(isp
->regs
))
136 return PTR_ERR(isp
->regs
);
138 isp1760_init_core(isp
);
140 ret
= isp1760_hcd_register(&isp
->hcd
, isp
->regs
, mem
, irq
,
141 irqflags
| IRQF_SHARED
, dev
);
145 if (devflags
& ISP1760_FLAG_ISP1761
) {
146 ret
= isp1760_udc_register(isp
, irq
, irqflags
| IRQF_SHARED
|
149 isp1760_hcd_unregister(&isp
->hcd
);
154 dev_set_drvdata(dev
, isp
);
159 void isp1760_unregister(struct device
*dev
)
161 struct isp1760_device
*isp
= dev_get_drvdata(dev
);
163 if (isp
->devflags
& ISP1760_FLAG_ISP1761
)
164 isp1760_udc_unregister(isp
);
166 isp1760_hcd_unregister(&isp
->hcd
);
169 MODULE_DESCRIPTION("Driver for the ISP1760 USB-controller from NXP");
170 MODULE_AUTHOR("Sebastian Siewior <bigeasy@linuxtronix.de>");
171 MODULE_LICENSE("GPL v2");