uboot/drivers/usb/isp1760/isp1760-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Driver for the NXP ISP1760 chip
   4 *
   5 * Copyright 2022 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
   6 *
   7 * This is based on linux kernel driver, original developed:
   8 * Copyright 2014 Laurent Pinchart
   9 * Copyright 2007 Sebastian Siewior
  10 *
  11 */
  12
  13#include <dm.h>
  14#include <dm/device-internal.h>
  15#include <dm/device_compat.h>
  16#include <dm/devres.h>
  17#include <linux/compat.h>
  18#include <linux/delay.h>
  19#include <linux/io.h>
  20#include <linux/kernel.h>
  21#include <regmap.h>
  22#include <usb.h>
  23
  24#include "isp1760-core.h"
  25#include "isp1760-hcd.h"
  26#include "isp1760-regs.h"
  27
  28#define msleep(a) udelay((a) * 1000)
  29
  30static int isp1760_init_core(struct isp1760_device *isp)
  31{
  32        struct isp1760_hcd *hcd = &isp->hcd;
  33
  34        /*
  35         * Reset the host controller, including the CPU interface
  36         * configuration.
  37         */
  38        isp1760_field_set(hcd->fields, SW_RESET_RESET_ALL);
  39        msleep(100);
  40
  41        /* Setup HW Mode Control: This assumes a level active-low interrupt */
  42        if ((isp->devflags & ISP1760_FLAG_ANALOG_OC) && hcd->is_isp1763)
  43                return -EINVAL;
  44
  45        if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16)
  46                isp1760_field_clear(hcd->fields, HW_DATA_BUS_WIDTH);
  47        if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_8)
  48                isp1760_field_set(hcd->fields, HW_DATA_BUS_WIDTH);
  49        if (isp->devflags & ISP1760_FLAG_ANALOG_OC)
  50                isp1760_field_set(hcd->fields, HW_ANA_DIGI_OC);
  51        if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH)
  52                isp1760_field_set(hcd->fields, HW_DACK_POL_HIGH);
  53        if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
  54                isp1760_field_set(hcd->fields, HW_DREQ_POL_HIGH);
  55        if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH)
  56                isp1760_field_set(hcd->fields, HW_INTR_HIGH_ACT);
  57        if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
  58                isp1760_field_set(hcd->fields, HW_INTR_EDGE_TRIG);
  59
  60        /*
  61         * The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
  62         * IRQ line for both the host and device controllers. Hardcode IRQ
  63         * sharing for now and disable the DC interrupts globally to avoid
  64         * spurious interrupts during HCD registration.
  65         */
  66        if (isp->devflags & ISP1760_FLAG_ISP1761) {
  67                isp1760_reg_write(hcd->regs, ISP176x_DC_MODE, 0);
  68                isp1760_field_set(hcd->fields, HW_COMN_IRQ);
  69        }
  70
  71        /*
  72         * PORT 1 Control register of the ISP1760 is the OTG control register
  73         * on ISP1761.
  74         *
  75         * TODO: Really support OTG. For now we configure port 1 in device mode
  76         */
  77        if (((isp->devflags & ISP1760_FLAG_ISP1761) ||
  78             (isp->devflags & ISP1760_FLAG_ISP1763)) &&
  79            (isp->devflags & ISP1760_FLAG_PERIPHERAL_EN)) {
  80                isp1760_field_set(hcd->fields, HW_DM_PULLDOWN);
  81                isp1760_field_set(hcd->fields, HW_DP_PULLDOWN);
  82                isp1760_field_set(hcd->fields, HW_OTG_DISABLE);
  83        } else {
  84                isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC);
  85                isp1760_field_set(hcd->fields, HW_VBUS_DRV);
  86                isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
  87        }
  88
  89        printf("%s bus width: %u, oc: %s\n",
  90               hcd->is_isp1763 ? "isp1763" : "isp1760",
  91               isp->devflags & ISP1760_FLAG_BUS_WIDTH_8 ? 8 :
  92               isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
  93               hcd->is_isp1763 ? "not available" :
  94               isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital");
  95
  96        return 0;
  97}
  98
  99void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
 100{
 101        struct isp1760_hcd *hcd = &isp->hcd;
 102
 103        if (enable)
 104                isp1760_field_set(hcd->fields, HW_DP_PULLUP);
 105        else
 106                isp1760_field_set(hcd->fields, HW_DP_PULLUP_CLEAR);
 107}
 108
 109/*
 110 * ISP1760/61:
 111 *
 112 * 60kb divided in:
 113 * - 32 blocks @ 256  bytes
 114 * - 20 blocks @ 1024 bytes
 115 * -  4 blocks @ 8192 bytes
 116 */
 117static const struct isp1760_memory_layout isp176x_memory_conf = {
 118        .blocks[0]              = 32,
 119        .blocks_size[0]         = 256,
 120        .blocks[1]              = 20,
 121        .blocks_size[1]         = 1024,
 122        .blocks[2]              = 4,
 123        .blocks_size[2]         = 8192,
 124
 125        .slot_num               = 32,
 126        .payload_blocks         = 32 + 20 + 4,
 127        .payload_area_size      = 0xf000,
 128};
 129
 130/*
 131 * ISP1763:
 132 *
 133 * 20kb divided in:
 134 * - 8 blocks @ 256  bytes
 135 * - 2 blocks @ 1024 bytes
 136 * - 4 blocks @ 4096 bytes
 137 */
 138static const struct isp1760_memory_layout isp1763_memory_conf = {
 139        .blocks[0]              = 8,
 140        .blocks_size[0]         = 256,
 141        .blocks[1]              = 2,
 142        .blocks_size[1]         = 1024,
 143        .blocks[2]              = 4,
 144        .blocks_size[2]         = 4096,
 145
 146        .slot_num               = 16,
 147        .payload_blocks         = 8 + 2 + 4,
 148        .payload_area_size      = 0x5000,
 149};
 150
 151static const struct regmap_config isp1760_hc_regmap_conf = {
 152        .width = REGMAP_SIZE_16,
 153};
 154
 155static const struct reg_field isp1760_hc_reg_fields[] = {
 156        [HCS_PPC]               = REG_FIELD(ISP176x_HC_HCSPARAMS, 4, 4),
 157        [HCS_N_PORTS]           = REG_FIELD(ISP176x_HC_HCSPARAMS, 0, 3),
 158        [HCC_ISOC_CACHE]        = REG_FIELD(ISP176x_HC_HCCPARAMS, 7, 7),
 159        [HCC_ISOC_THRES]        = REG_FIELD(ISP176x_HC_HCCPARAMS, 4, 6),
 160        [CMD_LRESET]            = REG_FIELD(ISP176x_HC_USBCMD, 7, 7),
 161        [CMD_RESET]             = REG_FIELD(ISP176x_HC_USBCMD, 1, 1),
 162        [CMD_RUN]               = REG_FIELD(ISP176x_HC_USBCMD, 0, 0),
 163        [STS_PCD]               = REG_FIELD(ISP176x_HC_USBSTS, 2, 2),
 164        [HC_FRINDEX]            = REG_FIELD(ISP176x_HC_FRINDEX, 0, 13),
 165        [FLAG_CF]               = REG_FIELD(ISP176x_HC_CONFIGFLAG, 0, 0),
 166        [HC_ISO_PTD_DONEMAP]    = REG_FIELD(ISP176x_HC_ISO_PTD_DONEMAP, 0, 31),
 167        [HC_ISO_PTD_SKIPMAP]    = REG_FIELD(ISP176x_HC_ISO_PTD_SKIPMAP, 0, 31),
 168        [HC_ISO_PTD_LASTPTD]    = REG_FIELD(ISP176x_HC_ISO_PTD_LASTPTD, 0, 31),
 169        [HC_INT_PTD_DONEMAP]    = REG_FIELD(ISP176x_HC_INT_PTD_DONEMAP, 0, 31),
 170        [HC_INT_PTD_SKIPMAP]    = REG_FIELD(ISP176x_HC_INT_PTD_SKIPMAP, 0, 31),
 171        [HC_INT_PTD_LASTPTD]    = REG_FIELD(ISP176x_HC_INT_PTD_LASTPTD, 0, 31),
 172        [HC_ATL_PTD_DONEMAP]    = REG_FIELD(ISP176x_HC_ATL_PTD_DONEMAP, 0, 31),
 173        [HC_ATL_PTD_SKIPMAP]    = REG_FIELD(ISP176x_HC_ATL_PTD_SKIPMAP, 0, 31),
 174        [HC_ATL_PTD_LASTPTD]    = REG_FIELD(ISP176x_HC_ATL_PTD_LASTPTD, 0, 31),
 175        [PORT_OWNER]            = REG_FIELD(ISP176x_HC_PORTSC1, 13, 13),
 176        [PORT_POWER]            = REG_FIELD(ISP176x_HC_PORTSC1, 12, 12),
 177        [PORT_LSTATUS]          = REG_FIELD(ISP176x_HC_PORTSC1, 10, 11),
 178        [PORT_RESET]            = REG_FIELD(ISP176x_HC_PORTSC1, 8, 8),
 179        [PORT_SUSPEND]          = REG_FIELD(ISP176x_HC_PORTSC1, 7, 7),
 180        [PORT_RESUME]           = REG_FIELD(ISP176x_HC_PORTSC1, 6, 6),
 181        [PORT_PE]               = REG_FIELD(ISP176x_HC_PORTSC1, 2, 2),
 182        [PORT_CSC]              = REG_FIELD(ISP176x_HC_PORTSC1, 1, 1),
 183        [PORT_CONNECT]          = REG_FIELD(ISP176x_HC_PORTSC1, 0, 0),
 184        [ALL_ATX_RESET]         = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 31, 31),
 185        [HW_ANA_DIGI_OC]        = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 15, 15),
 186        [HW_COMN_IRQ]           = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 10, 10),
 187        [HW_DATA_BUS_WIDTH]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 8, 8),
 188        [HW_DACK_POL_HIGH]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 6, 6),
 189        [HW_DREQ_POL_HIGH]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 5, 5),
 190        [HW_INTR_HIGH_ACT]      = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 2, 2),
 191        [HW_INTR_EDGE_TRIG]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 1, 1),
 192        [HW_GLOBAL_INTR_EN]     = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 0, 0),
 193        [HC_CHIP_REV]           = REG_FIELD(ISP176x_HC_CHIP_ID, 16, 31),
 194        [HC_CHIP_ID_HIGH]       = REG_FIELD(ISP176x_HC_CHIP_ID, 8, 15),
 195        [HC_CHIP_ID_LOW]        = REG_FIELD(ISP176x_HC_CHIP_ID, 0, 7),
 196        [HC_SCRATCH]            = REG_FIELD(ISP176x_HC_SCRATCH, 0, 31),
 197        [SW_RESET_RESET_ALL]    = REG_FIELD(ISP176x_HC_RESET, 0, 0),
 198        [ISO_BUF_FILL]          = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 2, 2),
 199        [INT_BUF_FILL]          = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 1, 1),
 200        [ATL_BUF_FILL]          = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 0, 0),
 201        [MEM_BANK_SEL]          = REG_FIELD(ISP176x_HC_MEMORY, 16, 17),
 202        [MEM_START_ADDR]        = REG_FIELD(ISP176x_HC_MEMORY, 0, 15),
 203        [HC_INTERRUPT]          = REG_FIELD(ISP176x_HC_INTERRUPT, 0, 9),
 204        [HC_ATL_IRQ_ENABLE]     = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 8, 8),
 205        [HC_INT_IRQ_ENABLE]     = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 7),
 206        [HC_ISO_IRQ_MASK_OR]    = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_OR, 0, 31),
 207        [HC_INT_IRQ_MASK_OR]    = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_OR, 0, 31),
 208        [HC_ATL_IRQ_MASK_OR]    = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_OR, 0, 31),
 209        [HC_ISO_IRQ_MASK_AND]   = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_AND, 0, 31),
 210        [HC_INT_IRQ_MASK_AND]   = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_AND, 0, 31),
 211        [HC_ATL_IRQ_MASK_AND]   = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_AND, 0, 31),
 212        [HW_OTG_DISABLE]        = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 10, 10),
 213        [HW_SW_SEL_HC_DC]       = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 7, 7),
 214        [HW_VBUS_DRV]           = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 4, 4),
 215        [HW_SEL_CP_EXT]         = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 3, 3),
 216        [HW_DM_PULLDOWN]        = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 2, 2),
 217        [HW_DP_PULLDOWN]        = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 1, 1),
 218        [HW_DP_PULLUP]          = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 0, 0),
 219        [HW_OTG_DISABLE_CLEAR]  = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 10, 10),
 220        [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 7, 7),
 221        [HW_VBUS_DRV_CLEAR]     = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 4, 4),
 222        [HW_SEL_CP_EXT_CLEAR]   = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 3, 3),
 223        [HW_DM_PULLDOWN_CLEAR]  = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 2, 2),
 224        [HW_DP_PULLDOWN_CLEAR]  = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 1, 1),
 225        [HW_DP_PULLUP_CLEAR]    = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 0, 0),
 226        /* Make sure the array is sized properly during compilation */
 227        [HC_FIELD_MAX]          = {},
 228};
 229
 230static const struct regmap_config isp1763_hc_regmap_conf = {
 231        .width = REGMAP_SIZE_16,
 232};
 233
 234static const struct reg_field isp1763_hc_reg_fields[] = {
 235        [CMD_LRESET]            = REG_FIELD(ISP1763_HC_USBCMD, 7, 7),
 236        [CMD_RESET]             = REG_FIELD(ISP1763_HC_USBCMD, 1, 1),
 237        [CMD_RUN]               = REG_FIELD(ISP1763_HC_USBCMD, 0, 0),
 238        [STS_PCD]               = REG_FIELD(ISP1763_HC_USBSTS, 2, 2),
 239        [HC_FRINDEX]            = REG_FIELD(ISP1763_HC_FRINDEX, 0, 13),
 240        [FLAG_CF]               = REG_FIELD(ISP1763_HC_CONFIGFLAG, 0, 0),
 241        [HC_ISO_PTD_DONEMAP]    = REG_FIELD(ISP1763_HC_ISO_PTD_DONEMAP, 0, 15),
 242        [HC_ISO_PTD_SKIPMAP]    = REG_FIELD(ISP1763_HC_ISO_PTD_SKIPMAP, 0, 15),
 243        [HC_ISO_PTD_LASTPTD]    = REG_FIELD(ISP1763_HC_ISO_PTD_LASTPTD, 0, 15),
 244        [HC_INT_PTD_DONEMAP]    = REG_FIELD(ISP1763_HC_INT_PTD_DONEMAP, 0, 15),
 245        [HC_INT_PTD_SKIPMAP]    = REG_FIELD(ISP1763_HC_INT_PTD_SKIPMAP, 0, 15),
 246        [HC_INT_PTD_LASTPTD]    = REG_FIELD(ISP1763_HC_INT_PTD_LASTPTD, 0, 15),
 247        [HC_ATL_PTD_DONEMAP]    = REG_FIELD(ISP1763_HC_ATL_PTD_DONEMAP, 0, 15),
 248        [HC_ATL_PTD_SKIPMAP]    = REG_FIELD(ISP1763_HC_ATL_PTD_SKIPMAP, 0, 15),
 249        [HC_ATL_PTD_LASTPTD]    = REG_FIELD(ISP1763_HC_ATL_PTD_LASTPTD, 0, 15),
 250        [PORT_OWNER]            = REG_FIELD(ISP1763_HC_PORTSC1, 13, 13),
 251        [PORT_POWER]            = REG_FIELD(ISP1763_HC_PORTSC1, 12, 12),
 252        [PORT_LSTATUS]          = REG_FIELD(ISP1763_HC_PORTSC1, 10, 11),
 253        [PORT_RESET]            = REG_FIELD(ISP1763_HC_PORTSC1, 8, 8),
 254        [PORT_SUSPEND]          = REG_FIELD(ISP1763_HC_PORTSC1, 7, 7),
 255        [PORT_RESUME]           = REG_FIELD(ISP1763_HC_PORTSC1, 6, 6),
 256        [PORT_PE]               = REG_FIELD(ISP1763_HC_PORTSC1, 2, 2),
 257        [PORT_CSC]              = REG_FIELD(ISP1763_HC_PORTSC1, 1, 1),
 258        [PORT_CONNECT]          = REG_FIELD(ISP1763_HC_PORTSC1, 0, 0),
 259        [HW_DATA_BUS_WIDTH]     = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 4, 4),
 260        [HW_DACK_POL_HIGH]      = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 6, 6),
 261        [HW_DREQ_POL_HIGH]      = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 5, 5),
 262        [HW_INTF_LOCK]          = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 3, 3),
 263        [HW_INTR_HIGH_ACT]      = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 2, 2),
 264        [HW_INTR_EDGE_TRIG]     = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 1, 1),
 265        [HW_GLOBAL_INTR_EN]     = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 0, 0),
 266        [SW_RESET_RESET_ATX]    = REG_FIELD(ISP1763_HC_RESET, 3, 3),
 267        [SW_RESET_RESET_ALL]    = REG_FIELD(ISP1763_HC_RESET, 0, 0),
 268        [HC_CHIP_ID_HIGH]       = REG_FIELD(ISP1763_HC_CHIP_ID, 0, 15),
 269        [HC_CHIP_ID_LOW]        = REG_FIELD(ISP1763_HC_CHIP_REV, 8, 15),
 270        [HC_CHIP_REV]           = REG_FIELD(ISP1763_HC_CHIP_REV, 0, 7),
 271        [HC_SCRATCH]            = REG_FIELD(ISP1763_HC_SCRATCH, 0, 15),
 272        [ISO_BUF_FILL]          = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 2, 2),
 273        [INT_BUF_FILL]          = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 1, 1),
 274        [ATL_BUF_FILL]          = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 0, 0),
 275        [MEM_START_ADDR]        = REG_FIELD(ISP1763_HC_MEMORY, 0, 15),
 276        [HC_DATA]               = REG_FIELD(ISP1763_HC_DATA, 0, 15),
 277        [HC_INTERRUPT]          = REG_FIELD(ISP1763_HC_INTERRUPT, 0, 10),
 278        [HC_ATL_IRQ_ENABLE]     = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 8, 8),
 279        [HC_INT_IRQ_ENABLE]     = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 7, 7),
 280        [HC_ISO_IRQ_MASK_OR]    = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_OR, 0, 15),
 281        [HC_INT_IRQ_MASK_OR]    = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_OR, 0, 15),
 282        [HC_ATL_IRQ_MASK_OR]    = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_OR, 0, 15),
 283        [HC_ISO_IRQ_MASK_AND]   = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_AND, 0, 15),
 284        [HC_INT_IRQ_MASK_AND]   = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_AND, 0, 15),
 285        [HC_ATL_IRQ_MASK_AND]   = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_AND, 0, 15),
 286        [HW_HC_2_DIS]           = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 15, 15),
 287        [HW_OTG_DISABLE]        = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 10, 10),
 288        [HW_SW_SEL_HC_DC]       = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 7, 7),
 289        [HW_VBUS_DRV]           = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 4, 4),
 290        [HW_SEL_CP_EXT]         = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 3, 3),
 291        [HW_DM_PULLDOWN]        = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 2, 2),
 292        [HW_DP_PULLDOWN]        = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 1, 1),
 293        [HW_DP_PULLUP]          = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 0, 0),
 294        [HW_HC_2_DIS_CLEAR]     = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 15, 15),
 295        [HW_OTG_DISABLE_CLEAR]  = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 10, 10),
 296        [HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 7, 7),
 297        [HW_VBUS_DRV_CLEAR]     = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 4, 4),
 298        [HW_SEL_CP_EXT_CLEAR]   = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 3, 3),
 299        [HW_DM_PULLDOWN_CLEAR]  = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 2, 2),
 300        [HW_DP_PULLDOWN_CLEAR]  = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 1, 1),
 301        [HW_DP_PULLUP_CLEAR]    = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 0, 0),
 302        /* Make sure the array is sized properly during compilation */
 303        [HC_FIELD_MAX]          = {},
 304};
 305
 306int isp1760_register(struct isp1760_device *isp, struct resource *mem, int irq,
 307                     unsigned long irqflags)
 308{
 309        const struct regmap_config *hc_regmap;
 310        const struct reg_field *hc_reg_fields;
 311        struct isp1760_hcd *hcd;
 312        struct regmap_field *f;
 313        unsigned int devflags;
 314        struct udevice *dev;
 315        int ret;
 316        int i;
 317
 318        hcd = &isp->hcd;
 319        devflags = isp->devflags;
 320        dev = isp->dev;
 321
 322        hcd->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763);
 323
 324        if (!hcd->is_isp1763 && (devflags & ISP1760_FLAG_BUS_WIDTH_8)) {
 325                dev_err(dev, "isp1760/61 do not support data width 8\n");
 326                return -EINVAL;
 327        }
 328
 329        if (hcd->is_isp1763) {
 330                hc_regmap = &isp1763_hc_regmap_conf;
 331                hc_reg_fields = &isp1763_hc_reg_fields[0];
 332        } else {
 333                hc_regmap = &isp1760_hc_regmap_conf;
 334                hc_reg_fields = &isp1760_hc_reg_fields[0];
 335        }
 336
 337        hcd->base = devm_ioremap(dev, mem->start, resource_size(mem));
 338        if (IS_ERR(hcd->base))
 339                return PTR_ERR(hcd->base);
 340
 341        hcd->regs = devm_regmap_init(dev, NULL, NULL, hc_regmap);
 342        if (IS_ERR(hcd->regs))
 343                return PTR_ERR(hcd->regs);
 344
 345        for (i = 0; i < HC_FIELD_MAX; i++) {
 346                f = devm_regmap_field_alloc(dev, hcd->regs, hc_reg_fields[i]);
 347                if (IS_ERR(f))
 348                        return PTR_ERR(f);
 349
 350                hcd->fields[i] = f;
 351        }
 352
 353        if (hcd->is_isp1763)
 354                hcd->memory_layout = &isp1763_memory_conf;
 355        else
 356                hcd->memory_layout = &isp176x_memory_conf;
 357
 358        ret = isp1760_init_core(isp);
 359        if (ret < 0)
 360                return ret;
 361
 362        hcd->dev = dev;
 363
 364        ret = isp1760_hcd_register(hcd, mem, irq, irqflags, dev);
 365        if (ret < 0)
 366                return ret;
 367
 368        ret = isp1760_hcd_lowlevel_init(hcd);
 369        if (ret < 0)
 370                return ret;
 371
 372        dev_set_drvdata(dev, isp);
 373
 374        return 0;
 375}
 376
 377void isp1760_unregister(struct isp1760_device *isp)
 378{
 379        isp1760_hcd_unregister(&isp->hcd);
 380}
 381