1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#include <platsupport/clock.h>
13#include <usb/usb_host.h>
14#include "../usb_otg.h"
15#include "../../ehci/ehci.h"
16#include "../../services.h"
17#include <stdio.h>
18#include <stddef.h>
19
20#define USB_PHY1_PADDR     0x20C9000
21#define USB_PHY2_PADDR     0x20CA000
22#define USB_PADDR          0x2184000
23
24#define USB_HOST1_IRQ       72
25#define USB_HOST2_IRQ       73
26#define USB_HOST3_IRQ       74
27#define USB_OTG_IRQ         75
28
29#define USB_PHY1_SIZE      0x0001000
30#define USB_PHY2_SIZE      0x0001000
31#define USB_SIZE           0x0001000
32
33#define IMX6_PORTSC_PTS_MASK  ((3UL << 30) | (1UL << 25))
34#define IMX6_PORTSC_PTS_UTMI  ((0UL << 30) | (0UL << 25))
35#define IMX6_PORTSC_PTS_ULPI  ((2UL << 30) | (0UL << 25))
36#define IMX6_PORTSC_PTS_ICUSB ((3UL << 30) | (0UL << 25))
37#define IMX6_PORTSC_PTS_HSIC  ((4UL << 30) | (1UL << 25))
38#define IMX6_PORTSC_STS       (1UL << 29)
39#define IMX6_PORTSC_PTW       (1UL << 28)
40
41struct usb_sct {
42    uint32_t val;
43    uint32_t set;
44    uint32_t clr;
45    uint32_t tog;
46};
47
48
49//USB_PHY1_PADDR
50//USB_PHY2_PADDR
51struct usb_phy_regs {
52    struct usb_sct pwd;     /* 0x00 */
53    struct usb_sct tx;      /* 0x10 */
54    struct usb_sct rx;      /* 0x20 */
55#define PHYCTRL_SFTRST               BIT(31)
56#define PHYCTRL_CLKGATE              BIT(30)
57#define PHYCTRL_UTMI_SUSPENDM        BIT(29)
58#define PHYCTRL_HOST_FORCE_LS_SE0    BIT(28)
59#define PHYCTRL_OTG_ID_VALUE         BIT(27)
60#define PHYCTRL_FSDLL_RST_EN         BIT(24)
61#define PHYCTRL_ENVBUSCHG_WKUP       BIT(23)
62#define PHYCTRL_ENIDCHG_WKUP         BIT(22)
63#define PHYCTRL_ENDPDMCHG_WKUP       BIT(21)
64#define PHYCTRL_ENAUTOCLR_PHY_PWD    BIT(20)
65#define PHYCTRL_ENAUTOCLR_CLKGATE    BIT(19)
66#define PHYCTRL_WAKEUP_IRQ           BIT(17)
67#define PHYCTRL_ENIRQWAKEUP          BIT(16)
68#define PHYCTRL_ENUTMIL3             BIT(15)
69#define PHYCTRL_ENUTMIL2             BIT(14)
70#define PHYCTRL_DATA_ON_LRADC        BIT(13)
71#define PHYCTRL_DEVPLUGIN_IRQ        BIT(12)
72#define PHYCTRL_ENIRQDEVPLUGIN       BIT(11)
73#define PHYCTRL_RESUME_IRQ           BIT(10)
74#define PHYCTRL_ENIRQRESUMEDETECT    BIT( 9)
75#define PHYCTRL_RESUMEIRQSTICKY      BIT( 8)
76#define PHYCTRL_ENOTGIDDETECT        BIT( 7)
77#define PHYCTRL_OTG_ID_CHG_IRQ       BIT( 6)
78#define PHYCTRL_DEVPLUGIN_POLARITY   BIT( 5)
79#define PHYCTRL_ENDEVPLUGINDETECT    BIT( 4)
80#define PHYCTRL_HOSTDISCONDETECT_IRQ BIT( 3)
81#define PHYCTRL_ENIRQHOSTDISCON      BIT( 2)
82#define PHYCTRL_ENHOSTDISCONDETECT   BIT( 1)
83#define PHYCTRL_ENOTG_ID_CHG_IRQ     BIT( 0)
84    struct usb_sct ctrl;    /* 0x30 */
85    uint32_t status;        /* 0x40 */
86    uint32_t res0[3];
87    struct usb_sct debug;   /* 0x50 */
88    uint32_t debug0_status; /* 0x60 */
89    uint32_t res1[3];
90    struct usb_sct debug1;  /* 0x70 */
91    uint32_t version;       /* 0x80 */
92};
93
94
95
96
97struct usb_otg_regs {
98    uint32_t id;                    /* +0x000 */
99    uint32_t hwgeneral;             /* +0x004 */
100    uint32_t hwhost;                /* +0x008 */
101    uint32_t otg_hwdevice;          /* +0x00C */
102    uint32_t hwtxbuf;               /* +0x010 */
103    uint32_t hwrxbuf;               /* +0x014 */
104    uint32_t res02[26];
105    uint32_t gptimer0ld;            /* +0x080 */
106    uint32_t gptimer0ctrl;          /* +0x084 */
107    uint32_t gptimer1ld;            /* +0x088 */
108    uint32_t gptimer1ctrl;          /* +0x08C */
109    uint32_t sbuscfg;               /* +0x090 */
110    uint32_t res03[27];
111
112    /* capability registers */
113    uint8_t  caplength;             /* +0x100 */
114    uint8_t  res05[1];
115    uint16_t hciversion;            /* +0x102 */
116    uint32_t hcsparams;             /* +0x104 */
117    uint32_t hccparams;             /* +0x108 */
118    uint32_t res06[5];
119    uint32_t otg_dciversion;        /* +0x120 */
120    uint32_t otg_dccparams;         /* +0x124 */
121    uint32_t res08[6];
122
123    /* operational registers */
124    uint32_t usbcmd;                /* +0x140 */
125    uint32_t usbsts;                /* +0x144 */
126    uint32_t usbintr;               /* +0x148 */
127    uint32_t frindex;               /* +0x14C */
128    uint32_t res09[1];
129    uint32_t otg_deviceaddr;        /* +0x154 */
130    uint32_t otg_endptlistaddr;     /* +0x158 */
131    uint32_t res10[1];
132    uint32_t burstsize;             /* +0x160 */
133    uint32_t txfilltuning;          /* +0x164 */
134    uint32_t res11[4];
135    uint32_t otg_endptnak;          /* +0x178 */
136    uint32_t otg_endptnaken;        /* +0x17C */
137    uint32_t configflag;            /* +0x180 */
138    uint32_t portsc1;               /* +0x184 */
139
140    uint32_t res13[7];
141    uint32_t otg_otgsc;             /* +0x1A4 */
142#define USBMODE_HOST (0x3 << 0)
143#define USBMODE_DEV  (0x2 << 0)
144#define USBMODE_IDLE (0x0 << 0)
145    uint32_t usbmode;               /* +0x1A8 */
146    uint32_t otg_endptsetupstat;    /* +0x1AC */
147    uint32_t otg_endptprime;        /* +0x1B0 */
148    uint32_t otg_endptflush;        /* +0x1B4 */
149    uint32_t otg_endptstat;         /* +0x1B8 */
150    uint32_t otg_endptcomplete;     /* +0x1BC */
151    uint32_t otg_endptctrl0;        /* +0x1C0 */
152    uint32_t otg_endptctrl1;        /* +0x1C4 */
153    uint32_t otg_endptctrl2;        /* +0x1C8 */
154    uint32_t otg_endptctrl3;        /* +0x1CC */
155    uint32_t otg_endptctrl4;        /* +0x1D0 */
156    uint32_t otg_endptctrl5;        /* +0x1D4 */
157    uint32_t otg_endptctrl6;        /* +0x1D8 */
158    uint32_t otg_endptctrl7;        /* +0x1DC */
159    uint32_t res16[8];
160};
161
162struct usb_host_regs {
163    uint32_t id;                    /* +0x000 */
164    uint32_t hwgeneral;             /* +0x004 */
165    uint32_t hwhost;                /* +0x008 */
166    uint32_t res01[1];
167    uint32_t hwtxbuf;               /* +0x010 */
168    uint32_t hwrxbuf;               /* +0x014 */
169    uint32_t res02[26];
170    uint32_t gptimer0ld;            /* +0x080 */
171    uint32_t gptimer0ctrl;          /* +0x084 */
172    uint32_t gptimer1ld;            /* +0x088 */
173    uint32_t gptimer1ctrl;          /* +0x08C */
174    uint32_t sbuscfg;               /* +0x090 */
175    uint32_t res03[27];
176
177    /* capability registers */
178    uint8_t  caplength;             /* +0x100 */
179    uint8_t  res05[1];
180    uint16_t hciversion;            /* +0x102 */
181    uint32_t hcsparams;             /* +0x104 */
182    uint32_t hccparams;             /* +0x108 */
183    uint32_t res06[5];
184    uint32_t res07[2];
185    uint32_t res08[6];
186
187    /* operational registers */
188    uint32_t usbcmd;                /* +0x140 */
189    uint32_t usbsts;                /* +0x144 */
190    uint32_t usbintr;               /* +0x148 */
191    uint32_t frindex;               /* +0x14C */
192    uint32_t res09[1];
193    uint32_t host_periodiclistbase; /* +0x154 */
194    uint32_t host_asynclistaddr;    /* +0x158 */
195    uint32_t res10[1];
196    uint32_t burstsize;             /* +0x160 */
197    uint32_t txfilltuning;          /* +0x164 */
198    uint32_t res11[4];
199    uint32_t res12[2];
200    uint32_t configflag;            /* +0x180 */
201    uint32_t portsc1;               /* +0x184 */
202
203    uint32_t res13[7];
204    uint32_t res14[1];
205
206    uint32_t usbmode;               /* +0x1A8 */
207    uint32_t res15[13];
208    uint32_t res16[8];
209};
210
211struct usb_regs {
212    /* Core */
213    struct usb_otg_regs  otg;       /* +0x000 */
214    struct usb_host_regs host1;     /* +0x200 */
215    struct usb_host_regs host2;     /* +0x400 */
216    struct usb_host_regs host3;     /* +0x600 */
217    /* Non-core */
218#define USBCTRL_WIR           BIT(31)
219#define USBCTRL_WKUP_VBUS_EN  BIT(17)
220#define USBCTRL_WKUP_ID_EN    BIT(16)
221#define USBCTRL_WKUP_SW       BIT(15)
222#define USBCTRL_WKUP_SW_EN    BIT(14)
223#define USBCTRL_UTMI_ON_CLOCK BIT(13)
224#define USBCTRL_SUSPENDM      BIT(12)
225#define USBCTRL_RESET         BIT(11)
226#define USBCTRL_WIE           BIT(10)
227#define USBCTRL_PWR_POL       BIT( 9)
228#define USBCTRL_OVER_CUR_POL  BIT( 8)
229#define USBCTRL_OVER_CUR_DIS  BIT( 7)
230    uint32_t otg_ctrl;              /* +0x800 */
231    uint32_t host1_ctrl;            /* +0x804 */
232    uint32_t host2_ctrl;            /* +0x808 */
233    uint32_t host3_ctrl;            /* +0x80C */
234    uint32_t host2_hsic_ctrl;       /* +0x810 */
235    uint32_t host3_hsic_ctrl;       /* +0x814 */
236    uint32_t otg_phy_ctrl_0;        /* +0x818 */
237    uint32_t host1_phy_ctrl_0;      /* +0x81C */
238};
239
240
241static volatile struct usb_phy_regs *_usb_phy1_regs = NULL;
242static volatile struct usb_phy_regs *_usb_phy2_regs = NULL;
243static volatile struct usb_regs     *_usb_regs      = NULL;
244
245static const int _usb_irqs[] = {
246    [USB_OTG0]  = USB_OTG_IRQ,
247    [USB_HOST1] = USB_HOST1_IRQ,
248    [USB_HOST2] = USB_HOST2_IRQ,
249    [USB_HOST3] = USB_HOST3_IRQ
250};
251
252static void
253phy_enable(int devid, ps_io_ops_t* o)
254{
255    volatile struct usb_phy_regs* phy_regs;
256    clk_t* clk;
257
258    clock_sys_init(o, &o->clock_sys);
259    switch (devid) {
260    case 0:
261        clk = clk_get_clock(&o->clock_sys, CLK_USB1);
262        if (_usb_phy1_regs == NULL) {
263            _usb_phy1_regs = GET_RESOURCE(o, USB_PHY1);
264        }
265        phy_regs = _usb_phy1_regs;
266        if (!clk || !phy_regs) {
267            ZF_LOGF("Clock error\n");
268        }
269        break;
270    case 1:
271        clk = clk_get_clock(&o->clock_sys, CLK_USB2);
272        if (_usb_phy2_regs == NULL) {
273            _usb_phy2_regs = GET_RESOURCE(o, USB_PHY2);
274        }
275        phy_regs = _usb_phy2_regs;
276        if (!clk || !phy_regs) {
277            ZF_LOGF("Clock error\n");
278        }
279        break;
280    default:
281        phy_regs = NULL;
282        clk = NULL;
283        break;
284    }
285
286
287    if (phy_regs) {
288        if (clk == NULL) {
289            ZF_LOGD("Failed to initialise USB PHY clock\n");
290        }
291        /* Enable clocks */
292        phy_regs->ctrl.clr = PHYCTRL_CLKGATE;
293        /* Reset PHY */
294        phy_regs->ctrl.set = PHYCTRL_SFTRST;
295        dsb();
296        ps_udelay(10);
297        phy_regs->ctrl.clr = PHYCTRL_SFTRST;
298        dsb();
299        ps_udelay(10);
300        /* Enable PHY and FS/LS */
301        phy_regs->pwd.val = 0;
302        phy_regs->ctrl.set = PHYCTRL_ENUTMIL3 | PHYCTRL_ENUTMIL2;
303        dsb();
304        ps_mdelay(10);
305    }
306}
307
308static int
309imx6_usb_generic_init(int id, ps_io_ops_t* ioops)
310{
311    struct usb_host_regs * hc_regs = NULL;
312    volatile uint32_t* hc_ctrl;
313
314    if (id < 0 || id > USB_NHOSTS) {
315        ZF_LOGF("Invalid host id\n");
316    }
317    /* Check device mappings */
318    if (_usb_regs == NULL) {
319        _usb_regs = GET_RESOURCE(ioops, USB);
320    }
321    if (_usb_regs == NULL) {
322        return -1;
323    }
324    hc_regs = (struct usb_host_regs*)_usb_regs + id;
325    hc_ctrl = &_usb_regs->otg_ctrl + id;
326
327    /* Reset the EHCI controller */
328    hc_regs->usbcmd |= EHCICMD_HCRESET;
329    /* Disable over-current */
330    *hc_ctrl |= USBCTRL_OVER_CUR_POL;
331    *hc_ctrl |= USBCTRL_OVER_CUR_DIS;
332    /* Enable the PHY */
333    phy_enable(id, ioops);
334    return 0;
335}
336
337
338int
339usb_host_init(enum usb_host_id id, ps_io_ops_t* ioops, ps_mutex_ops_t *sync,
340               usb_host_t* hdev)
341{
342    struct usb_host_regs * hc_regs = NULL;
343    int err;
344    if (id < 0 || id > USB_NHOSTS) {
345        return -1;
346    }
347
348    if (!ioops || !hdev) {
349        ZF_LOGF("Invalid arguments\n");
350    }
351
352    hdev->id = id;
353    hdev->dman = &ioops->dma_manager;
354    hdev->sync = sync;
355
356    err = imx6_usb_generic_init(hdev->id, ioops);
357    if (err) {
358        return -1;
359    }
360    /* Pass control to EHCI initialisation */
361    hc_regs = (struct usb_host_regs*)_usb_regs + hdev->id;
362    hc_regs->usbmode = USBMODE_HOST;
363    err = ehci_host_init(hdev, (uintptr_t)&hc_regs->caplength, NULL);
364    /* Configure ports */
365    hc_regs->portsc1 = IMX6_PORTSC_PTS_UTMI | IMX6_PORTSC_PTW;
366    return err;
367}
368
369const int*
370usb_host_irqs(usb_host_t* host, int* nirqs)
371{
372    if (host->id < 0 || host->id > USB_NHOSTS) {
373        return NULL;
374    }
375
376    if (nirqs) {
377        *nirqs = 1;
378    }
379    host->irqs = &_usb_irqs[host->id];
380
381    return host->irqs;
382}
383
384int
385usb_plat_otg_init(usb_otg_t odev, ps_io_ops_t* ioops)
386{
387    struct usb_otg_regs* otg_regs;
388    int err;
389
390    if (!odev->dman || !odev->id) {
391        ZF_LOGF("Invalid arguments\n");
392    }
393    err = imx6_usb_generic_init(odev->id, ioops);
394    if (err) {
395        return -1;
396    }
397    otg_regs = (struct usb_otg_regs*)_usb_regs + odev->id;
398    otg_regs->usbmode = USBMODE_DEV;
399    err = ehci_otg_init(odev, (uintptr_t)&otg_regs->caplength);
400    if (otg_regs->usbmode != USBMODE_DEV) {
401        ZF_LOGF("Set the hardware to device mode\n");
402    }
403
404    return err;
405}
406
407
408