usb: isp1760: add support for isp1763

isp1763 have some differences from the isp1760, 8 bit address for
registers and 16 bit for values, no bulk access to memory addresses,
16 PTD's instead of 32.

Following the regmap work done before add the registers, memory access
and add the functions to support differences in setup sequences.

Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
Link: https://lore.kernel.org/r/20210513084717.2487366-8-rui.silva@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Rui Miguel Silva 2021-05-13 09:47:15 +01:00 committed by Greg Kroah-Hartman
parent 3eb96e04be
commit 60d789f3bf
9 changed files with 853 additions and 208 deletions

View File

@ -1,11 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
config USB_ISP1760
tristate "NXP ISP 1760/1761 support"
tristate "NXP ISP 1760/1761/1763 support"
depends on USB || USB_GADGET
select REGMAP_MMIO
help
Say Y or M here if your system as an ISP1760 USB host controller
Say Y or M here if your system as an ISP1760/1763 USB host controller
or an ISP1761 USB dual-role controller.
This driver does not support isochronous transfers or OTG.

View File

@ -2,12 +2,14 @@
/*
* Driver for the NXP ISP1760 chip
*
* Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Laurent Pinchart
* Copyright 2007 Sebastian Siewior
*
* Contacts:
* Sebastian Siewior <bigeasy@linutronix.de>
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Rui Miguel Silva <rui.silva@linaro.org>
*/
#include <linux/delay.h>
@ -24,7 +26,7 @@
#include "isp1760-regs.h"
#include "isp1760-udc.h"
static void isp1760_init_core(struct isp1760_device *isp)
static int isp1760_init_core(struct isp1760_device *isp)
{
struct isp1760_hcd *hcd = &isp->hcd;
struct isp1760_udc *udc = &isp->udc;
@ -44,8 +46,15 @@ static void isp1760_init_core(struct isp1760_device *isp)
msleep(100);
/* Setup HW Mode Control: This assumes a level active-low interrupt */
if ((isp->devflags & ISP1760_FLAG_ANALOG_OC) && hcd->is_isp1763) {
dev_err(isp->dev, "isp1763 analog overcurrent not available\n");
return -EINVAL;
}
if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16)
isp1760_field_clear(hcd->fields, HW_DATA_BUS_WIDTH);
if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_8)
isp1760_field_set(hcd->fields, HW_DATA_BUS_WIDTH);
if (isp->devflags & ISP1760_FLAG_ANALOG_OC)
isp1760_field_set(hcd->fields, HW_ANA_DIGI_OC);
if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH)
@ -85,9 +94,14 @@ static void isp1760_init_core(struct isp1760_device *isp)
isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
}
dev_info(isp->dev, "bus width: %u, oc: %s\n",
dev_info(isp->dev, "%s bus width: %u, oc: %s\n",
hcd->is_isp1763 ? "isp1763" : "isp1760",
isp->devflags & ISP1760_FLAG_BUS_WIDTH_8 ? 8 :
isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
hcd->is_isp1763 ? "not available" :
isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital");
return 0;
}
void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
@ -101,6 +115,8 @@ void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
}
/*
* ISP1760/61:
*
* 60kb divided in:
* - 32 blocks @ 256 bytes
* - 20 blocks @ 1024 bytes
@ -114,15 +130,36 @@ static const struct isp1760_memory_layout isp176x_memory_conf = {
.blocks[2] = 4,
.blocks_size[2] = 8192,
.ptd_num = 32,
.slot_num = 32,
.payload_blocks = 32 + 20 + 4,
.payload_area_size = 0xf000,
};
/*
* ISP1763:
*
* 20kb divided in:
* - 8 blocks @ 256 bytes
* - 2 blocks @ 1024 bytes
* - 4 blocks @ 4096 bytes
*/
static const struct isp1760_memory_layout isp1763_memory_conf = {
.blocks[0] = 8,
.blocks_size[0] = 256,
.blocks[1] = 2,
.blocks_size[1] = 1024,
.blocks[2] = 4,
.blocks_size[2] = 4096,
.slot_num = 16,
.payload_blocks = 8 + 2 + 4,
.payload_area_size = 0x5000,
};
static const struct regmap_range isp176x_hc_volatile_ranges[] = {
regmap_reg_range(ISP176x_HC_USBCMD, ISP176x_HC_ATL_PTD_LASTPTD),
regmap_reg_range(ISP176x_HC_BUFFER_STATUS, ISP176x_HC_MEMORY),
regmap_reg_range(ISP176x_HC_INTERRUPT, ISP176x_HC_ATL_IRQ_MASK_AND),
regmap_reg_range(ISP176x_HC_INTERRUPT, ISP176x_HC_OTG_CTRL_CLEAR),
};
static const struct regmap_access_table isp176x_hc_volatile_table = {
@ -130,13 +167,13 @@ static const struct regmap_access_table isp176x_hc_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(isp176x_hc_volatile_ranges),
};
static struct regmap_config isp1760_hc_regmap_conf = {
static const struct regmap_config isp1760_hc_regmap_conf = {
.name = "isp1760-hc",
.reg_bits = 16,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
.max_register = ISP176x_HC_MEMORY,
.max_register = ISP176x_HC_OTG_CTRL_CLEAR,
.volatile_table = &isp176x_hc_volatile_table,
};
@ -151,6 +188,15 @@ static const struct reg_field isp1760_hc_reg_fields[] = {
[STS_PCD] = REG_FIELD(ISP176x_HC_USBSTS, 2, 2),
[HC_FRINDEX] = REG_FIELD(ISP176x_HC_FRINDEX, 0, 13),
[FLAG_CF] = REG_FIELD(ISP176x_HC_CONFIGFLAG, 0, 0),
[HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_DONEMAP, 0, 31),
[HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_SKIPMAP, 0, 31),
[HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ISO_PTD_LASTPTD, 0, 31),
[HC_INT_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_INT_PTD_DONEMAP, 0, 31),
[HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_INT_PTD_SKIPMAP, 0, 31),
[HC_INT_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_INT_PTD_LASTPTD, 0, 31),
[HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_DONEMAP, 0, 31),
[HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_SKIPMAP, 0, 31),
[HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ATL_PTD_LASTPTD, 0, 31),
[PORT_OWNER] = REG_FIELD(ISP176x_HC_PORTSC1, 13, 13),
[PORT_POWER] = REG_FIELD(ISP176x_HC_PORTSC1, 12, 12),
[PORT_LSTATUS] = REG_FIELD(ISP176x_HC_PORTSC1, 10, 11),
@ -169,18 +215,135 @@ static const struct reg_field isp1760_hc_reg_fields[] = {
[HW_INTR_HIGH_ACT] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 2, 2),
[HW_INTR_EDGE_TRIG] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 1, 1),
[HW_GLOBAL_INTR_EN] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 0, 0),
[HC_CHIP_REV] = REG_FIELD(ISP176x_HC_CHIP_ID, 16, 31),
[HC_CHIP_ID_HIGH] = REG_FIELD(ISP176x_HC_CHIP_ID, 8, 15),
[HC_CHIP_ID_LOW] = REG_FIELD(ISP176x_HC_CHIP_ID, 0, 7),
[HC_SCRATCH] = REG_FIELD(ISP176x_HC_SCRATCH, 0, 31),
[SW_RESET_RESET_ALL] = REG_FIELD(ISP176x_HC_RESET, 0, 0),
[ISO_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 2, 2),
[INT_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 1, 1),
[ATL_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 0, 0),
[MEM_BANK_SEL] = REG_FIELD(ISP176x_HC_MEMORY, 16, 17),
[MEM_START_ADDR] = REG_FIELD(ISP176x_HC_MEMORY, 0, 15),
[HC_INT_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 8),
[HC_INTERRUPT] = REG_FIELD(ISP176x_HC_INTERRUPT, 0, 9),
[HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 8, 8),
[HC_INT_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 7),
[HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_OR, 0, 31),
[HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_OR, 0, 31),
[HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_OR, 0, 31),
[HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_AND, 0, 31),
[HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_AND, 0, 31),
[HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_AND, 0, 31),
[HW_OTG_DISABLE] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 10, 10),
[HW_SW_SEL_HC_DC] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 7, 7),
[HW_VBUS_DRV] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 4, 4),
[HW_SEL_CP_EXT] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 3, 3),
[HW_DM_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 2, 2),
[HW_DP_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 1, 1),
[HW_DP_PULLUP] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 0, 0),
[HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 10, 10),
[HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 7, 7),
[HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 4, 4),
[HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 3, 3),
[HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 2, 2),
[HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 1, 1),
[HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 0, 0),
};
static const struct reg_field isp1763_hc_reg_fields[] = {
[CMD_LRESET] = REG_FIELD(ISP1763_HC_USBCMD, 7, 7),
[CMD_RESET] = REG_FIELD(ISP1763_HC_USBCMD, 1, 1),
[CMD_RUN] = REG_FIELD(ISP1763_HC_USBCMD, 0, 0),
[STS_PCD] = REG_FIELD(ISP1763_HC_USBSTS, 2, 2),
[HC_FRINDEX] = REG_FIELD(ISP1763_HC_FRINDEX, 0, 13),
[FLAG_CF] = REG_FIELD(ISP1763_HC_CONFIGFLAG, 0, 0),
[HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_DONEMAP, 0, 15),
[HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_SKIPMAP, 0, 15),
[HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ISO_PTD_LASTPTD, 0, 15),
[HC_INT_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_INT_PTD_DONEMAP, 0, 15),
[HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_INT_PTD_SKIPMAP, 0, 15),
[HC_INT_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_INT_PTD_LASTPTD, 0, 15),
[HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_DONEMAP, 0, 15),
[HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_SKIPMAP, 0, 15),
[HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ATL_PTD_LASTPTD, 0, 15),
[PORT_OWNER] = REG_FIELD(ISP1763_HC_PORTSC1, 13, 13),
[PORT_POWER] = REG_FIELD(ISP1763_HC_PORTSC1, 12, 12),
[PORT_LSTATUS] = REG_FIELD(ISP1763_HC_PORTSC1, 10, 11),
[PORT_RESET] = REG_FIELD(ISP1763_HC_PORTSC1, 8, 8),
[PORT_SUSPEND] = REG_FIELD(ISP1763_HC_PORTSC1, 7, 7),
[PORT_RESUME] = REG_FIELD(ISP1763_HC_PORTSC1, 6, 6),
[PORT_PE] = REG_FIELD(ISP1763_HC_PORTSC1, 2, 2),
[PORT_CSC] = REG_FIELD(ISP1763_HC_PORTSC1, 1, 1),
[PORT_CONNECT] = REG_FIELD(ISP1763_HC_PORTSC1, 0, 0),
[HW_DATA_BUS_WIDTH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 4, 4),
[HW_DACK_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 6, 6),
[HW_DREQ_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 5, 5),
[HW_INTF_LOCK] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 3, 3),
[HW_INTR_HIGH_ACT] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 2, 2),
[HW_INTR_EDGE_TRIG] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 1, 1),
[HW_GLOBAL_INTR_EN] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 0, 0),
[SW_RESET_RESET_ATX] = REG_FIELD(ISP1763_HC_RESET, 3, 3),
[SW_RESET_RESET_ALL] = REG_FIELD(ISP1763_HC_RESET, 0, 0),
[HC_CHIP_ID_HIGH] = REG_FIELD(ISP1763_HC_CHIP_ID, 0, 15),
[HC_CHIP_ID_LOW] = REG_FIELD(ISP1763_HC_CHIP_REV, 8, 15),
[HC_CHIP_REV] = REG_FIELD(ISP1763_HC_CHIP_REV, 0, 7),
[HC_SCRATCH] = REG_FIELD(ISP1763_HC_SCRATCH, 0, 15),
[ISO_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 2, 2),
[INT_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 1, 1),
[ATL_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 0, 0),
[MEM_START_ADDR] = REG_FIELD(ISP1763_HC_MEMORY, 0, 15),
[HC_DATA] = REG_FIELD(ISP1763_HC_DATA, 0, 15),
[HC_INTERRUPT] = REG_FIELD(ISP1763_HC_INTERRUPT, 0, 10),
[HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 8, 8),
[HC_INT_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 7, 7),
[HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_OR, 0, 15),
[HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_OR, 0, 15),
[HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_OR, 0, 15),
[HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_AND, 0, 15),
[HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_AND, 0, 15),
[HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_AND, 0, 15),
[HW_HC_2_DIS] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 15, 15),
[HW_OTG_DISABLE] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 10, 10),
[HW_SW_SEL_HC_DC] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 7, 7),
[HW_VBUS_DRV] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 4, 4),
[HW_SEL_CP_EXT] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 3, 3),
[HW_DM_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 2, 2),
[HW_DP_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 1, 1),
[HW_DP_PULLUP] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 0, 0),
[HW_HC_2_DIS_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 15, 15),
[HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 10, 10),
[HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 7, 7),
[HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 4, 4),
[HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 3, 3),
[HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 2, 2),
[HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 1, 1),
[HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 0, 0),
};
static const struct regmap_range isp1763_hc_volatile_ranges[] = {
regmap_reg_range(ISP1763_HC_USBCMD, ISP1763_HC_ATL_PTD_LASTPTD),
regmap_reg_range(ISP1763_HC_BUFFER_STATUS, ISP1763_HC_DATA),
regmap_reg_range(ISP1763_HC_INTERRUPT, ISP1763_HC_OTG_CTRL_CLEAR),
};
static const struct regmap_access_table isp1763_hc_volatile_table = {
.yes_ranges = isp1763_hc_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(isp1763_hc_volatile_ranges),
};
static const struct regmap_config isp1763_hc_regmap_conf = {
.name = "isp1763-hc",
.reg_bits = 8,
.reg_stride = 2,
.val_bits = 16,
.fast_io = true,
.max_register = ISP1763_HC_OTG_CTRL_CLEAR,
.volatile_table = &isp1763_hc_volatile_table,
};
static const struct regmap_range isp176x_dc_volatile_ranges[] = {
regmap_reg_range(ISP176x_DC_EPMAXPKTSZ, ISP176x_DC_EPTYPE),
regmap_reg_range(ISP176x_DC_BUFLEN, ISP176x_DC_EPINDEX),
regmap_reg_range(ISP1761_DC_OTG_CTRL_SET, ISP1761_DC_OTG_CTRL_CLEAR),
};
static const struct regmap_access_table isp176x_dc_volatile_table = {
@ -188,13 +351,13 @@ static const struct regmap_access_table isp176x_dc_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(isp176x_dc_volatile_ranges),
};
static struct regmap_config isp1761_dc_regmap_conf = {
static const struct regmap_config isp1761_dc_regmap_conf = {
.name = "isp1761-dc",
.reg_bits = 16,
.reg_stride = 4,
.val_bits = 32,
.fast_io = true,
.max_register = ISP1761_DC_OTG_CTRL_CLEAR,
.max_register = ISP176x_DC_TESTMODE,
.volatile_table = &isp176x_dc_volatile_table,
};
@ -236,31 +399,84 @@ static const struct reg_field isp1761_dc_reg_fields[] = {
[DC_ENDPTYP] = REG_FIELD(ISP176x_DC_EPTYPE, 0, 1),
[DC_UFRAMENUM] = REG_FIELD(ISP176x_DC_FRAMENUM, 11, 13),
[DC_FRAMENUM] = REG_FIELD(ISP176x_DC_FRAMENUM, 0, 10),
[HW_OTG_DISABLE] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 10, 10),
[HW_SW_SEL_HC_DC] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 7, 7),
[HW_VBUS_DRV] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 4, 4),
[HW_SEL_CP_EXT] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 3, 3),
[HW_DM_PULLDOWN] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 2, 2),
[HW_DP_PULLDOWN] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 1, 1),
[HW_DP_PULLUP] = REG_FIELD(ISP1761_DC_OTG_CTRL_SET, 0, 0),
[HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 10, 10),
[HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 7, 7),
[HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 4, 4),
[HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 3, 3),
[HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 2, 2),
[HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 1, 1),
[HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP1761_DC_OTG_CTRL_CLEAR, 0, 0),
[DC_CHIP_ID_HIGH] = REG_FIELD(ISP176x_DC_CHIPID, 16, 31),
[DC_CHIP_ID_LOW] = REG_FIELD(ISP176x_DC_CHIPID, 0, 15),
[DC_SCRATCH] = REG_FIELD(ISP176x_DC_SCRATCH, 0, 15),
};
static const struct regmap_range isp1763_dc_volatile_ranges[] = {
regmap_reg_range(ISP1763_DC_EPMAXPKTSZ, ISP1763_DC_EPTYPE),
regmap_reg_range(ISP1763_DC_BUFLEN, ISP1763_DC_EPINDEX),
};
static const struct regmap_access_table isp1763_dc_volatile_table = {
.yes_ranges = isp1763_dc_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(isp1763_dc_volatile_ranges),
};
static const struct reg_field isp1763_dc_reg_fields[] = {
[DC_DEVEN] = REG_FIELD(ISP1763_DC_ADDRESS, 7, 7),
[DC_DEVADDR] = REG_FIELD(ISP1763_DC_ADDRESS, 0, 6),
[DC_VBUSSTAT] = REG_FIELD(ISP1763_DC_MODE, 8, 8),
[DC_SFRESET] = REG_FIELD(ISP1763_DC_MODE, 4, 4),
[DC_GLINTENA] = REG_FIELD(ISP1763_DC_MODE, 3, 3),
[DC_CDBGMOD_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 6, 6),
[DC_DDBGMODIN_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 4, 4),
[DC_DDBGMODOUT_ACK] = REG_FIELD(ISP1763_DC_INTCONF, 2, 2),
[DC_INTPOL] = REG_FIELD(ISP1763_DC_INTCONF, 0, 0),
[DC_IEPRXTX_7] = REG_FIELD(ISP1763_DC_INTENABLE, 25, 25),
[DC_IEPRXTX_6] = REG_FIELD(ISP1763_DC_INTENABLE, 23, 23),
[DC_IEPRXTX_5] = REG_FIELD(ISP1763_DC_INTENABLE, 21, 21),
[DC_IEPRXTX_4] = REG_FIELD(ISP1763_DC_INTENABLE, 19, 19),
[DC_IEPRXTX_3] = REG_FIELD(ISP1763_DC_INTENABLE, 17, 17),
[DC_IEPRXTX_2] = REG_FIELD(ISP1763_DC_INTENABLE, 15, 15),
[DC_IEPRXTX_1] = REG_FIELD(ISP1763_DC_INTENABLE, 13, 13),
[DC_IEPRXTX_0] = REG_FIELD(ISP1763_DC_INTENABLE, 11, 11),
[DC_IEP0SETUP] = REG_FIELD(ISP1763_DC_INTENABLE, 8, 8),
[DC_IEVBUS] = REG_FIELD(ISP1763_DC_INTENABLE, 7, 7),
[DC_IEHS_STA] = REG_FIELD(ISP1763_DC_INTENABLE, 5, 5),
[DC_IERESM] = REG_FIELD(ISP1763_DC_INTENABLE, 4, 4),
[DC_IESUSP] = REG_FIELD(ISP1763_DC_INTENABLE, 3, 3),
[DC_IEBRST] = REG_FIELD(ISP1763_DC_INTENABLE, 0, 0),
[DC_EP0SETUP] = REG_FIELD(ISP1763_DC_EPINDEX, 5, 5),
[DC_ENDPIDX] = REG_FIELD(ISP1763_DC_EPINDEX, 1, 4),
[DC_EPDIR] = REG_FIELD(ISP1763_DC_EPINDEX, 0, 0),
[DC_CLBUF] = REG_FIELD(ISP1763_DC_CTRLFUNC, 4, 4),
[DC_VENDP] = REG_FIELD(ISP1763_DC_CTRLFUNC, 3, 3),
[DC_DSEN] = REG_FIELD(ISP1763_DC_CTRLFUNC, 2, 2),
[DC_STATUS] = REG_FIELD(ISP1763_DC_CTRLFUNC, 1, 1),
[DC_STALL] = REG_FIELD(ISP1763_DC_CTRLFUNC, 0, 0),
[DC_BUFLEN] = REG_FIELD(ISP1763_DC_BUFLEN, 0, 15),
[DC_FFOSZ] = REG_FIELD(ISP1763_DC_EPMAXPKTSZ, 0, 10),
[DC_EPENABLE] = REG_FIELD(ISP1763_DC_EPTYPE, 3, 3),
[DC_ENDPTYP] = REG_FIELD(ISP1763_DC_EPTYPE, 0, 1),
[DC_UFRAMENUM] = REG_FIELD(ISP1763_DC_FRAMENUM, 11, 13),
[DC_FRAMENUM] = REG_FIELD(ISP1763_DC_FRAMENUM, 0, 10),
[DC_CHIP_ID_HIGH] = REG_FIELD(ISP1763_DC_CHIPID_HIGH, 0, 15),
[DC_CHIP_ID_LOW] = REG_FIELD(ISP1763_DC_CHIPID_LOW, 0, 15),
[DC_SCRATCH] = REG_FIELD(ISP1763_DC_SCRATCH, 0, 15),
};
static const struct regmap_config isp1763_dc_regmap_conf = {
.name = "isp1763-dc",
.reg_bits = 8,
.reg_stride = 2,
.val_bits = 16,
.fast_io = true,
.max_register = ISP1763_DC_TESTMODE,
.volatile_table = &isp1763_dc_volatile_table,
};
int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
struct device *dev, unsigned int devflags)
{
bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761);
const struct regmap_config *hc_regmap;
const struct reg_field *hc_reg_fields;
struct isp1760_device *isp;
struct isp1760_hcd *hcd;
struct isp1760_udc *udc;
bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761);
struct regmap_field *f;
void __iomem *base;
int ret;
int i;
@ -281,9 +497,19 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
hcd = &isp->hcd;
udc = &isp->udc;
if (devflags & ISP1760_FLAG_BUS_WIDTH_16) {
isp1760_hc_regmap_conf.val_bits = 16;
isp1761_dc_regmap_conf.val_bits = 16;
hcd->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763);
if (!hcd->is_isp1763 && (devflags & ISP1760_FLAG_BUS_WIDTH_8)) {
dev_err(dev, "isp1760/61 do not support data width 8\n");
return -EINVAL;
}
if (hcd->is_isp1763) {
hc_regmap = &isp1763_hc_regmap_conf;
hc_reg_fields = &isp1763_hc_reg_fields[0];
} else {
hc_regmap = &isp1760_hc_regmap_conf;
hc_reg_fields = &isp1760_hc_reg_fields[0];
}
isp->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH);
@ -294,20 +520,20 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
if (IS_ERR(hcd->base))
return PTR_ERR(hcd->base);
hcd->regs = devm_regmap_init_mmio(dev, base, &isp1760_hc_regmap_conf);
hcd->regs = devm_regmap_init_mmio(dev, hcd->base, hc_regmap);
if (IS_ERR(hcd->regs))
return PTR_ERR(hcd->regs);
for (i = 0; i < HC_FIELD_MAX; i++) {
f = devm_regmap_field_alloc(dev, hcd->regs,
isp1760_hc_reg_fields[i]);
f = devm_regmap_field_alloc(dev, hcd->regs, hc_reg_fields[i]);
if (IS_ERR(f))
return PTR_ERR(f);
hcd->fields[i] = f;
}
udc->regs = devm_regmap_init_mmio(dev, base, &isp1761_dc_regmap_conf);
udc->regs = devm_regmap_init_mmio(dev, hcd->base,
&isp1761_dc_regmap_conf);
if (IS_ERR(udc->regs))
return PTR_ERR(udc->regs);
@ -320,9 +546,14 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
udc->fields[i] = f;
}
hcd->memory_layout = &isp176x_memory_conf;
if (hcd->is_isp1763)
hcd->memory_layout = &isp1763_memory_conf;
else
hcd->memory_layout = &isp176x_memory_conf;
isp1760_init_core(isp);
ret = isp1760_init_core(isp);
if (ret < 0)
return ret;
if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) && !usb_disabled()) {
ret = isp1760_hcd_register(hcd, mem, irq,

View File

@ -2,12 +2,14 @@
/*
* Driver for the NXP ISP1760 chip
*
* Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Laurent Pinchart
* Copyright 2007 Sebastian Siewior
*
* Contacts:
* Sebastian Siewior <bigeasy@linutronix.de>
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Rui Miguel Silva <rui.silva@linaro.org>
*/
#ifndef _ISP1760_CORE_H_
@ -35,6 +37,8 @@ struct gpio_desc;
#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */
#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */
#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */
#define ISP1760_FLAG_ISP1763 0x00000200 /* Chip is ISP1763 */
#define ISP1760_FLAG_BUS_WIDTH_8 0x00000400 /* 8-bit data bus width */
struct isp1760_device {
struct device *dev;

File diff suppressed because it is too large Load Diff

View File

@ -19,13 +19,14 @@ struct isp1760_slotinfo {
};
/* chip memory management */
#define ISP176x_BLOCK_MAX (32 + 20 + 4)
#define ISP176x_BLOCK_NUM 3
struct isp1760_memory_layout {
unsigned int blocks[ISP176x_BLOCK_NUM];
unsigned int blocks_size[ISP176x_BLOCK_NUM];
unsigned int ptd_num;
unsigned int slot_num;
unsigned int payload_blocks;
unsigned int payload_area_size;
};
@ -51,6 +52,7 @@ struct isp1760_hcd {
struct regmap *regs;
struct regmap_field *fields[HC_FIELD_MAX];
bool is_isp1763;
const struct isp1760_memory_layout *memory_layout;
spinlock_t lock;
@ -58,7 +60,7 @@ struct isp1760_hcd {
int atl_done_map;
struct isp1760_slotinfo *int_slots;
int int_done_map;
struct isp1760_memory_chunk *memory_pool;
struct isp1760_memory_chunk memory_pool[ISP176x_BLOCK_MAX];
struct list_head qh_list[QH_END];
/* periodic schedule support */

View File

@ -7,6 +7,7 @@
* - PDEV (generic platform device centralized driver model)
*
* (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
*
*/
@ -209,10 +210,18 @@ static int isp1760_plat_probe(struct platform_device *pdev)
if (of_device_is_compatible(dp, "nxp,usb-isp1761"))
devflags |= ISP1760_FLAG_ISP1761;
/* Some systems wire up only 16 of the 32 data lines */
if (of_device_is_compatible(dp, "nxp,usb-isp1763"))
devflags |= ISP1760_FLAG_ISP1763;
/*
* Some systems wire up only 8 of 16 data lines or
* 16 of the 32 data lines
*/
of_property_read_u32(dp, "bus-width", &bus_width);
if (bus_width == 16)
devflags |= ISP1760_FLAG_BUS_WIDTH_16;
else if (bus_width == 8)
devflags |= ISP1760_FLAG_BUS_WIDTH_8;
if (usb_get_dr_mode(&pdev->dev) == USB_DR_MODE_PERIPHERAL)
devflags |= ISP1760_FLAG_PERIPHERAL_EN;
@ -250,6 +259,7 @@ static int isp1760_plat_remove(struct platform_device *pdev)
static const struct of_device_id isp1760_of_match[] = {
{ .compatible = "nxp,usb-isp1760", },
{ .compatible = "nxp,usb-isp1761", },
{ .compatible = "nxp,usb-isp1763", },
{ },
};
MODULE_DEVICE_TABLE(of, isp1760_of_match);

View File

@ -2,12 +2,14 @@
/*
* Driver for the NXP ISP1760 chip
*
* Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Laurent Pinchart
* Copyright 2007 Sebastian Siewior
*
* Contacts:
* Sebastian Siewior <bigeasy@linutronix.de>
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Rui Miguel Silva <rui.silva@linaro.org>
*/
#ifndef _ISP176x_REGS_H_
@ -17,8 +19,8 @@
* Host Controller
*/
/* ISP1760/31 */
/* EHCI capability registers */
#define ISP176x_HC_CAPLENGTH 0x000
#define ISP176x_HC_VERSION 0x002
#define ISP176x_HC_HCSPARAMS 0x004
#define ISP176x_HC_HCCPARAMS 0x008
@ -59,7 +61,13 @@
#define ISP176x_HC_INT_IRQ_MASK_AND 0x328
#define ISP176x_HC_ATL_IRQ_MASK_AND 0x32c
#define ISP176x_HC_OTG_CTRL_SET 0x374
#define ISP176x_HC_OTG_CTRL_CLEAR 0x376
enum isp176x_host_controller_fields {
/* HC_PORTSC1 */
PORT_OWNER, PORT_POWER, PORT_LSTATUS, PORT_RESET, PORT_SUSPEND,
PORT_RESUME, PORT_PE, PORT_CSC, PORT_CONNECT,
/* HC_HCSPARAMS */
HCS_PPC, HCS_N_PORTS,
/* HC_HCCPARAMS */
@ -72,25 +80,86 @@ enum isp176x_host_controller_fields {
HC_FRINDEX,
/* HC_CONFIGFLAG */
FLAG_CF,
/* HC_PORTSC1 */
PORT_OWNER, PORT_POWER, PORT_LSTATUS, PORT_RESET, PORT_SUSPEND,
PORT_RESUME, PORT_PE, PORT_CSC, PORT_CONNECT,
/* ISO/INT/ATL PTD */
HC_ISO_PTD_DONEMAP, HC_ISO_PTD_SKIPMAP, HC_ISO_PTD_LASTPTD,
HC_INT_PTD_DONEMAP, HC_INT_PTD_SKIPMAP, HC_INT_PTD_LASTPTD,
HC_ATL_PTD_DONEMAP, HC_ATL_PTD_SKIPMAP, HC_ATL_PTD_LASTPTD,
/* HC_HW_MODE_CTRL */
ALL_ATX_RESET, HW_ANA_DIGI_OC, HW_DEV_DMA, HW_COMN_IRQ, HW_COMN_DMA,
HW_DATA_BUS_WIDTH, HW_DACK_POL_HIGH, HW_DREQ_POL_HIGH, HW_INTR_HIGH_ACT,
HW_INTR_EDGE_TRIG, HW_GLOBAL_INTR_EN,
HW_INTF_LOCK, HW_INTR_EDGE_TRIG, HW_GLOBAL_INTR_EN,
/* HC_CHIP_ID */
HC_CHIP_ID_HIGH, HC_CHIP_ID_LOW, HC_CHIP_REV,
/* HC_SCRATCH */
HC_SCRATCH,
/* HC_RESET */
SW_RESET_RESET_HC, SW_RESET_RESET_ALL,
SW_RESET_RESET_ATX, SW_RESET_RESET_HC, SW_RESET_RESET_ALL,
/* HC_BUFFER_STATUS */
INT_BUF_FILL, ATL_BUF_FILL,
ISO_BUF_FILL, INT_BUF_FILL, ATL_BUF_FILL,
/* HC_MEMORY */
MEM_BANK_SEL, MEM_START_ADDR,
/* HC_DATA */
HC_DATA,
/* HC_INTERRUPT */
HC_INTERRUPT,
/* HC_INTERRUPT_ENABLE */
HC_INT_ENABLE,
HC_INT_IRQ_ENABLE, HC_ATL_IRQ_ENABLE,
/* INTERRUPT MASKS */
HC_ISO_IRQ_MASK_OR, HC_INT_IRQ_MASK_OR, HC_ATL_IRQ_MASK_OR,
HC_ISO_IRQ_MASK_AND, HC_INT_IRQ_MASK_AND, HC_ATL_IRQ_MASK_AND,
/* HW_OTG_CTRL_SET */
HW_OTG_DISABLE, HW_SW_SEL_HC_DC, HW_VBUS_DRV, HW_SEL_CP_EXT,
HW_DM_PULLDOWN, HW_DP_PULLDOWN, HW_DP_PULLUP, HW_HC_2_DIS,
/* HW_OTG_CTRL_CLR */
HW_OTG_DISABLE_CLEAR, HW_SW_SEL_HC_DC_CLEAR, HW_VBUS_DRV_CLEAR,
HW_SEL_CP_EXT_CLEAR, HW_DM_PULLDOWN_CLEAR, HW_DP_PULLDOWN_CLEAR,
HW_DP_PULLUP_CLEAR, HW_HC_2_DIS_CLEAR,
/* Last element */
HC_FIELD_MAX,
};
/* ISP1763 */
/* EHCI operational registers */
#define ISP1763_HC_USBCMD 0x8c
#define ISP1763_HC_USBSTS 0x90
#define ISP1763_HC_FRINDEX 0x98
#define ISP1763_HC_CONFIGFLAG 0x9c
#define ISP1763_HC_PORTSC1 0xa0
#define ISP1763_HC_ISO_PTD_DONEMAP 0xa4
#define ISP1763_HC_ISO_PTD_SKIPMAP 0xa6
#define ISP1763_HC_ISO_PTD_LASTPTD 0xa8
#define ISP1763_HC_INT_PTD_DONEMAP 0xaa
#define ISP1763_HC_INT_PTD_SKIPMAP 0xac
#define ISP1763_HC_INT_PTD_LASTPTD 0xae
#define ISP1763_HC_ATL_PTD_DONEMAP 0xb0
#define ISP1763_HC_ATL_PTD_SKIPMAP 0xb2
#define ISP1763_HC_ATL_PTD_LASTPTD 0xb4
/* Configuration Register */
#define ISP1763_HC_HW_MODE_CTRL 0xb6
#define ISP1763_HC_CHIP_REV 0x70
#define ISP1763_HC_CHIP_ID 0x72
#define ISP1763_HC_SCRATCH 0x78
#define ISP1763_HC_RESET 0xb8
#define ISP1763_HC_BUFFER_STATUS 0xba
#define ISP1763_HC_MEMORY 0xc4
#define ISP1763_HC_DATA 0xc6
/* Interrupt Register */
#define ISP1763_HC_INTERRUPT 0xd4
#define ISP1763_HC_INTERRUPT_ENABLE 0xd6
#define ISP1763_HC_ISO_IRQ_MASK_OR 0xd8
#define ISP1763_HC_INT_IRQ_MASK_OR 0xda
#define ISP1763_HC_ATL_IRQ_MASK_OR 0xdc
#define ISP1763_HC_ISO_IRQ_MASK_AND 0xde
#define ISP1763_HC_INT_IRQ_MASK_AND 0xe0
#define ISP1763_HC_ATL_IRQ_MASK_AND 0xe2
#define ISP1763_HC_OTG_CTRL_SET 0xe4
#define ISP1763_HC_OTG_CTRL_CLEAR 0xe6
/* -----------------------------------------------------------------------------
* Peripheral Controller
*/
@ -132,9 +201,6 @@ enum isp176x_host_controller_fields {
#define ISP176x_DC_CTRLFUNC 0x0228
#define ISP176x_DC_EPINDEX 0x022c
#define ISP1761_DC_OTG_CTRL_SET 0x374
#define ISP1761_DC_OTG_CTRL_CLEAR 0x376
/* DMA Registers */
#define ISP176x_DC_DMACMD 0x0230
#define ISP176x_DC_DMATXCOUNT 0x0234
@ -177,13 +243,6 @@ enum isp176x_device_controller_fields {
DC_EPENABLE, DC_ENDPTYP,
/* DC_FRAMENUM */
DC_FRAMENUM, DC_UFRAMENUM,
/* HW_OTG_CTRL_SET */
HW_OTG_DISABLE, HW_SW_SEL_HC_DC, HW_VBUS_DRV, HW_SEL_CP_EXT,
HW_DM_PULLDOWN, HW_DP_PULLDOWN, HW_DP_PULLUP,
/* HW_OTG_CTRL_CLR */
HW_OTG_DISABLE_CLEAR, HW_SW_SEL_HC_DC_CLEAR, HW_VBUS_DRV_CLEAR,
HW_SEL_CP_EXT_CLEAR, HW_DM_PULLDOWN_CLEAR, HW_DP_PULLDOWN_CLEAR,
HW_DP_PULLUP_CLEAR,
/* Last element */
DC_FIELD_MAX,
};

View File

@ -2,10 +2,12 @@
/*
* Driver for the NXP ISP1761 device controller
*
* Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Ideas on Board Oy
*
* Contacts:
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Rui Miguel Silva <rui.silva@linaro.org>
*/
#include <linux/interrupt.h>

View File

@ -2,10 +2,12 @@
/*
* Driver for the NXP ISP1761 device controller
*
* Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Ideas on Board Oy
*
* Contacts:
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
* Rui Miguel Silva <rui.silva@linaro.org>
*/
#ifndef _ISP1760_UDC_H_