mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 00:49:43 +00:00
usb: add isp1760 family driver
ISP1760/61/63 are a family of usb controllers, here the main goal is to support the ISP1763 hcd part found in the MPS3 FPGA board form Arm. This is based on the kernel driver and ported to u-boot. Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
This commit is contained in:
parent
b2d2b78722
commit
88861a2c2c
13 changed files with 3575 additions and 0 deletions
1
Makefile
1
Makefile
|
@ -847,6 +847,7 @@ libs-y += drivers/usb/host/
|
|||
libs-y += drivers/usb/mtu3/
|
||||
libs-y += drivers/usb/musb/
|
||||
libs-y += drivers/usb/musb-new/
|
||||
libs-y += drivers/usb/isp1760/
|
||||
libs-y += drivers/usb/phy/
|
||||
libs-y += drivers/usb/ulpi/
|
||||
ifdef CONFIG_POST
|
||||
|
|
|
@ -68,6 +68,8 @@ config SPL_DM_USB_GADGET
|
|||
|
||||
source "drivers/usb/host/Kconfig"
|
||||
|
||||
source "drivers/usb/isp1760/Kconfig"
|
||||
|
||||
source "drivers/usb/cdns3/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc3/Kconfig"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
|
||||
obj-$(CONFIG_$(SPL_)DM_USB) += common.o
|
||||
obj-$(CONFIG_USB_ISP1760) += usb_urb.o
|
||||
obj-$(CONFIG_USB_MUSB_HOST) += usb_urb.o
|
||||
obj-$(CONFIG_USB_MUSB_GADGET) += usb_urb.o
|
||||
obj-$(CONFIG_USB_R8A66597_HCD) += usb_urb.o
|
||||
|
|
12
drivers/usb/isp1760/Kconfig
Normal file
12
drivers/usb/isp1760/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
config USB_ISP1760
|
||||
tristate "NXP ISP 1760/1761/1763 support"
|
||||
select DM_USB
|
||||
select USB_HOST
|
||||
help
|
||||
Say Y or M here if your system as an ISP1760/1761/1763 USB host
|
||||
controller.
|
||||
|
||||
This USB controller is usually attached to a non-DMA-Master
|
||||
capable bus.
|
6
drivers/usb/isp1760/Makefile
Normal file
6
drivers/usb/isp1760/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
isp1760-y := isp1760-core.o isp1760-if.o isp1760-uboot.o isp1760-hcd.o
|
||||
|
||||
#isp1760-hcd.o
|
||||
|
||||
obj-$(CONFIG_USB_ISP1760) += isp1760.o
|
380
drivers/usb/isp1760/isp1760-core.c
Normal file
380
drivers/usb/isp1760/isp1760-core.c
Normal file
|
@ -0,0 +1,380 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2022 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
* This is based on linux kernel driver, original developed:
|
||||
* Copyright 2014 Laurent Pinchart
|
||||
* Copyright 2007 Sebastian Siewior
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <regmap.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-hcd.h"
|
||||
#include "isp1760-regs.h"
|
||||
|
||||
#define msleep(a) udelay((a) * 1000)
|
||||
|
||||
static int isp1760_init_core(struct isp1760_device *isp)
|
||||
{
|
||||
struct isp1760_hcd *hcd = &isp->hcd;
|
||||
|
||||
/*
|
||||
* Reset the host controller, including the CPU interface
|
||||
* configuration.
|
||||
*/
|
||||
isp1760_field_set(hcd->fields, SW_RESET_RESET_ALL);
|
||||
msleep(100);
|
||||
|
||||
/* Setup HW Mode Control: This assumes a level active-low interrupt */
|
||||
if ((isp->devflags & ISP1760_FLAG_ANALOG_OC) && hcd->is_isp1763)
|
||||
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)
|
||||
isp1760_field_set(hcd->fields, HW_DACK_POL_HIGH);
|
||||
if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
|
||||
isp1760_field_set(hcd->fields, HW_DREQ_POL_HIGH);
|
||||
if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH)
|
||||
isp1760_field_set(hcd->fields, HW_INTR_HIGH_ACT);
|
||||
if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
|
||||
isp1760_field_set(hcd->fields, HW_INTR_EDGE_TRIG);
|
||||
|
||||
/*
|
||||
* The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
|
||||
* IRQ line for both the host and device controllers. Hardcode IRQ
|
||||
* sharing for now and disable the DC interrupts globally to avoid
|
||||
* spurious interrupts during HCD registration.
|
||||
*/
|
||||
if (isp->devflags & ISP1760_FLAG_ISP1761) {
|
||||
isp1760_reg_write(hcd->regs, ISP176x_DC_MODE, 0);
|
||||
isp1760_field_set(hcd->fields, HW_COMN_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
* PORT 1 Control register of the ISP1760 is the OTG control register
|
||||
* on ISP1761.
|
||||
*
|
||||
* TODO: Really support OTG. For now we configure port 1 in device mode
|
||||
*/
|
||||
if (((isp->devflags & ISP1760_FLAG_ISP1761) ||
|
||||
(isp->devflags & ISP1760_FLAG_ISP1763)) &&
|
||||
(isp->devflags & ISP1760_FLAG_PERIPHERAL_EN)) {
|
||||
isp1760_field_set(hcd->fields, HW_DM_PULLDOWN);
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLDOWN);
|
||||
isp1760_field_set(hcd->fields, HW_OTG_DISABLE);
|
||||
} else {
|
||||
isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC);
|
||||
isp1760_field_set(hcd->fields, HW_VBUS_DRV);
|
||||
isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
|
||||
}
|
||||
|
||||
printf("%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)
|
||||
{
|
||||
struct isp1760_hcd *hcd = &isp->hcd;
|
||||
|
||||
if (enable)
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLUP);
|
||||
else
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLUP_CLEAR);
|
||||
}
|
||||
|
||||
/*
|
||||
* ISP1760/61:
|
||||
*
|
||||
* 60kb divided in:
|
||||
* - 32 blocks @ 256 bytes
|
||||
* - 20 blocks @ 1024 bytes
|
||||
* - 4 blocks @ 8192 bytes
|
||||
*/
|
||||
static const struct isp1760_memory_layout isp176x_memory_conf = {
|
||||
.blocks[0] = 32,
|
||||
.blocks_size[0] = 256,
|
||||
.blocks[1] = 20,
|
||||
.blocks_size[1] = 1024,
|
||||
.blocks[2] = 4,
|
||||
.blocks_size[2] = 8192,
|
||||
|
||||
.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_config isp1760_hc_regmap_conf = {
|
||||
.width = REGMAP_SIZE_16,
|
||||
};
|
||||
|
||||
static const struct reg_field isp1760_hc_reg_fields[] = {
|
||||
[HCS_PPC] = REG_FIELD(ISP176x_HC_HCSPARAMS, 4, 4),
|
||||
[HCS_N_PORTS] = REG_FIELD(ISP176x_HC_HCSPARAMS, 0, 3),
|
||||
[HCC_ISOC_CACHE] = REG_FIELD(ISP176x_HC_HCCPARAMS, 7, 7),
|
||||
[HCC_ISOC_THRES] = REG_FIELD(ISP176x_HC_HCCPARAMS, 4, 6),
|
||||
[CMD_LRESET] = REG_FIELD(ISP176x_HC_USBCMD, 7, 7),
|
||||
[CMD_RESET] = REG_FIELD(ISP176x_HC_USBCMD, 1, 1),
|
||||
[CMD_RUN] = REG_FIELD(ISP176x_HC_USBCMD, 0, 0),
|
||||
[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),
|
||||
[PORT_RESET] = REG_FIELD(ISP176x_HC_PORTSC1, 8, 8),
|
||||
[PORT_SUSPEND] = REG_FIELD(ISP176x_HC_PORTSC1, 7, 7),
|
||||
[PORT_RESUME] = REG_FIELD(ISP176x_HC_PORTSC1, 6, 6),
|
||||
[PORT_PE] = REG_FIELD(ISP176x_HC_PORTSC1, 2, 2),
|
||||
[PORT_CSC] = REG_FIELD(ISP176x_HC_PORTSC1, 1, 1),
|
||||
[PORT_CONNECT] = REG_FIELD(ISP176x_HC_PORTSC1, 0, 0),
|
||||
[ALL_ATX_RESET] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 31, 31),
|
||||
[HW_ANA_DIGI_OC] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 15, 15),
|
||||
[HW_COMN_IRQ] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 10, 10),
|
||||
[HW_DATA_BUS_WIDTH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 8, 8),
|
||||
[HW_DACK_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 6, 6),
|
||||
[HW_DREQ_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 5, 5),
|
||||
[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_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),
|
||||
/* Make sure the array is sized properly during compilation */
|
||||
[HC_FIELD_MAX] = {},
|
||||
};
|
||||
|
||||
static const struct regmap_config isp1763_hc_regmap_conf = {
|
||||
.width = REGMAP_SIZE_16,
|
||||
};
|
||||
|
||||
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),
|
||||
/* Make sure the array is sized properly during compilation */
|
||||
[HC_FIELD_MAX] = {},
|
||||
};
|
||||
|
||||
int isp1760_register(struct isp1760_device *isp, struct resource *mem, int irq,
|
||||
unsigned long irqflags)
|
||||
{
|
||||
const struct regmap_config *hc_regmap;
|
||||
const struct reg_field *hc_reg_fields;
|
||||
struct isp1760_hcd *hcd;
|
||||
struct regmap_field *f;
|
||||
unsigned int devflags;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
hcd = &isp->hcd;
|
||||
devflags = isp->devflags;
|
||||
dev = isp->dev;
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
hcd->base = devm_ioremap(dev, mem->start, resource_size(mem));
|
||||
if (IS_ERR(hcd->base))
|
||||
return PTR_ERR(hcd->base);
|
||||
|
||||
hcd->regs = devm_regmap_init(dev, NULL, NULL, 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, hc_reg_fields[i]);
|
||||
if (IS_ERR(f))
|
||||
return PTR_ERR(f);
|
||||
|
||||
hcd->fields[i] = f;
|
||||
}
|
||||
|
||||
if (hcd->is_isp1763)
|
||||
hcd->memory_layout = &isp1763_memory_conf;
|
||||
else
|
||||
hcd->memory_layout = &isp176x_memory_conf;
|
||||
|
||||
ret = isp1760_init_core(isp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hcd->dev = dev;
|
||||
|
||||
ret = isp1760_hcd_register(hcd, mem, irq, irqflags, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = isp1760_hcd_lowlevel_init(hcd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_set_drvdata(dev, isp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isp1760_unregister(struct isp1760_device *isp)
|
||||
{
|
||||
isp1760_hcd_unregister(&isp->hcd);
|
||||
}
|
96
drivers/usb/isp1760/isp1760-core.h
Normal file
96
drivers/usb/isp1760/isp1760-core.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* 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_
|
||||
#define _ISP1760_CORE_H_
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <regmap.h>
|
||||
|
||||
#include "isp1760-hcd.h"
|
||||
|
||||
struct device;
|
||||
struct gpio_desc;
|
||||
|
||||
/*
|
||||
* Device flags that can vary from board to board. All of these
|
||||
* indicate the most "atypical" case, so that a devflags of 0 is
|
||||
* a sane default configuration.
|
||||
*/
|
||||
#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */
|
||||
#define ISP1760_FLAG_PERIPHERAL_EN 0x00000004 /* Port 1 supports Peripheral mode*/
|
||||
#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */
|
||||
#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */
|
||||
#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */
|
||||
#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 udevice *dev;
|
||||
|
||||
unsigned int devflags;
|
||||
struct gpio_desc *rst_gpio;
|
||||
|
||||
struct isp1760_hcd hcd;
|
||||
};
|
||||
|
||||
int isp1760_register(struct isp1760_device *isp, struct resource *mem, int irq,
|
||||
unsigned long irqflags);
|
||||
void isp1760_unregister(struct isp1760_device *isp);
|
||||
|
||||
void isp1760_set_pullup(struct isp1760_device *isp, bool enable);
|
||||
|
||||
static inline u32 isp1760_field_read(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_field_read(fields[field], &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void isp1760_field_write(struct regmap_field **fields, u32 field,
|
||||
u32 val)
|
||||
{
|
||||
regmap_field_write(fields[field], val);
|
||||
}
|
||||
|
||||
static inline void isp1760_field_set(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
isp1760_field_write(fields, field, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static inline void isp1760_field_clear(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
isp1760_field_write(fields, field, 0);
|
||||
}
|
||||
|
||||
static inline u32 isp1760_reg_read(struct regmap *regs, u32 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(regs, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void isp1760_reg_write(struct regmap *regs, u32 reg, u32 val)
|
||||
{
|
||||
regmap_write(regs, reg, val);
|
||||
}
|
||||
#endif
|
2477
drivers/usb/isp1760/isp1760-hcd.c
Normal file
2477
drivers/usb/isp1760/isp1760-hcd.c
Normal file
File diff suppressed because it is too large
Load diff
81
drivers/usb/isp1760/isp1760-hcd.h
Normal file
81
drivers/usb/isp1760/isp1760-hcd.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ISP1760_HCD_H_
|
||||
#define _ISP1760_HCD_H_
|
||||
|
||||
#include <regmap.h>
|
||||
|
||||
#include "isp1760-regs.h"
|
||||
|
||||
struct isp1760_qh;
|
||||
struct isp1760_qtd;
|
||||
struct resource;
|
||||
struct usb_hcd;
|
||||
|
||||
struct isp1760_slotinfo {
|
||||
struct isp1760_qh *qh;
|
||||
struct isp1760_qtd *qtd;
|
||||
unsigned long timestamp;
|
||||
};
|
||||
|
||||
/* 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 slot_num;
|
||||
unsigned int payload_blocks;
|
||||
unsigned int payload_area_size;
|
||||
};
|
||||
|
||||
struct isp1760_memory_chunk {
|
||||
unsigned int start;
|
||||
unsigned int size;
|
||||
unsigned int free;
|
||||
};
|
||||
|
||||
enum isp1760_queue_head_types {
|
||||
QH_CONTROL,
|
||||
QH_BULK,
|
||||
QH_INTERRUPT,
|
||||
QH_END
|
||||
};
|
||||
|
||||
struct isp1760_hcd {
|
||||
struct usb_hcd *hcd;
|
||||
struct udevice *dev;
|
||||
|
||||
void __iomem *base;
|
||||
|
||||
struct regmap *regs;
|
||||
struct regmap_field *fields[HC_FIELD_MAX];
|
||||
|
||||
bool is_isp1763;
|
||||
const struct isp1760_memory_layout *memory_layout;
|
||||
|
||||
struct isp1760_slotinfo *atl_slots;
|
||||
int atl_done_map;
|
||||
struct isp1760_slotinfo *int_slots;
|
||||
int int_done_map;
|
||||
struct isp1760_memory_chunk memory_pool[ISP176x_BLOCK_MAX];
|
||||
struct list_head qh_list[QH_END];
|
||||
|
||||
/* periodic schedule support */
|
||||
#define DEFAULT_I_TDPS 1024
|
||||
unsigned int periodic_size;
|
||||
unsigned int i_thresh;
|
||||
unsigned long reset_done;
|
||||
unsigned long next_statechange;
|
||||
};
|
||||
|
||||
int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem,
|
||||
int irq, unsigned long irqflags, struct udevice *dev);
|
||||
void isp1760_hcd_unregister(struct isp1760_hcd *priv);
|
||||
int isp1760_hcd_lowlevel_init(struct isp1760_hcd *priv);
|
||||
|
||||
int isp1760_init_kmem_once(void);
|
||||
void isp1760_deinit_kmem_cache(void);
|
||||
|
||||
#endif /* _ISP1760_HCD_H_ */
|
125
drivers/usb/isp1760/isp1760-if.c
Normal file
125
drivers/usb/isp1760/isp1760-if.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
* based on original code from:
|
||||
* (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-regs.h"
|
||||
#include "isp1760-uboot.h"
|
||||
|
||||
static int isp1760_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
unsigned int devflags = 0;
|
||||
u32 bus_width = 0;
|
||||
ofnode dp;
|
||||
|
||||
if (!dev_has_ofnode(dev)) {
|
||||
/* select isp1763 as the default device */
|
||||
devflags = ISP1760_FLAG_ISP1763 | ISP1760_FLAG_BUS_WIDTH_16;
|
||||
pr_err("isp1760: no platform data\n");
|
||||
goto isp_setup;
|
||||
}
|
||||
|
||||
dp = dev_ofnode(dev);
|
||||
|
||||
if (ofnode_device_is_compatible(dp, "nxp,usb-isp1761"))
|
||||
devflags |= ISP1760_FLAG_ISP1761;
|
||||
|
||||
if (ofnode_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
|
||||
*/
|
||||
bus_width = ofnode_read_u32_default(dp, "bus-width", 16);
|
||||
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(dev_ofnode(dev)) == USB_DR_MODE_PERIPHERAL)
|
||||
devflags |= ISP1760_FLAG_PERIPHERAL_EN;
|
||||
|
||||
if (ofnode_read_bool(dp, "analog-oc"))
|
||||
devflags |= ISP1760_FLAG_ANALOG_OC;
|
||||
|
||||
if (ofnode_read_bool(dp, "dack-polarity"))
|
||||
devflags |= ISP1760_FLAG_DACK_POL_HIGH;
|
||||
|
||||
if (ofnode_read_bool(dp, "dreq-polarity"))
|
||||
devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
|
||||
|
||||
isp_setup:
|
||||
isp->devflags = devflags;
|
||||
isp->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp1760_plat_probe(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
struct resource mem_res;
|
||||
struct resource irq_res;
|
||||
int ret;
|
||||
|
||||
dev_read_resource(dev, 0, &mem_res);
|
||||
dev_read_resource(dev, 1, &irq_res);
|
||||
|
||||
isp1760_init_kmem_once();
|
||||
|
||||
ret = isp1760_register(isp, &mem_res, irq_res.start, irq_res.flags);
|
||||
if (ret < 0) {
|
||||
isp1760_deinit_kmem_cache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp1760_plat_remove(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
|
||||
isp1760_deinit_kmem_cache();
|
||||
isp1760_unregister(isp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id isp1760_ids[] = {
|
||||
{ .compatible = "nxp,usb-isp1760", },
|
||||
{ .compatible = "nxp,usb-isp1761", },
|
||||
{ .compatible = "nxp,usb-isp1763", },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(isp1760) = {
|
||||
.name = "isp1760",
|
||||
.id = UCLASS_USB,
|
||||
.of_match = isp1760_ids,
|
||||
.of_to_plat = isp1760_of_to_plat,
|
||||
.ops = &isp1760_usb_ops,
|
||||
.probe = isp1760_plat_probe,
|
||||
.remove = isp1760_plat_remove,
|
||||
.plat_auto = sizeof(struct isp1760_device),
|
||||
.priv_auto = sizeof(struct isp1760_host_data),
|
||||
};
|
292
drivers/usb/isp1760/isp1760-regs.h
Normal file
292
drivers/usb/isp1760/isp1760-regs.h
Normal file
|
@ -0,0 +1,292 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* 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_
|
||||
#define _ISP176x_REGS_H_
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Host Controller
|
||||
*/
|
||||
|
||||
/* ISP1760/31 */
|
||||
/* EHCI capability registers */
|
||||
#define ISP176x_HC_VERSION 0x002
|
||||
#define ISP176x_HC_HCSPARAMS 0x004
|
||||
#define ISP176x_HC_HCCPARAMS 0x008
|
||||
|
||||
/* EHCI operational registers */
|
||||
#define ISP176x_HC_USBCMD 0x020
|
||||
#define ISP176x_HC_USBSTS 0x024
|
||||
#define ISP176x_HC_FRINDEX 0x02c
|
||||
|
||||
#define ISP176x_HC_CONFIGFLAG 0x060
|
||||
#define ISP176x_HC_PORTSC1 0x064
|
||||
|
||||
#define ISP176x_HC_ISO_PTD_DONEMAP 0x130
|
||||
#define ISP176x_HC_ISO_PTD_SKIPMAP 0x134
|
||||
#define ISP176x_HC_ISO_PTD_LASTPTD 0x138
|
||||
#define ISP176x_HC_INT_PTD_DONEMAP 0x140
|
||||
#define ISP176x_HC_INT_PTD_SKIPMAP 0x144
|
||||
#define ISP176x_HC_INT_PTD_LASTPTD 0x148
|
||||
#define ISP176x_HC_ATL_PTD_DONEMAP 0x150
|
||||
#define ISP176x_HC_ATL_PTD_SKIPMAP 0x154
|
||||
#define ISP176x_HC_ATL_PTD_LASTPTD 0x158
|
||||
|
||||
/* Configuration Register */
|
||||
#define ISP176x_HC_HW_MODE_CTRL 0x300
|
||||
#define ISP176x_HC_CHIP_ID 0x304
|
||||
#define ISP176x_HC_SCRATCH 0x308
|
||||
#define ISP176x_HC_RESET 0x30c
|
||||
#define ISP176x_HC_BUFFER_STATUS 0x334
|
||||
#define ISP176x_HC_MEMORY 0x33c
|
||||
|
||||
/* Interrupt Register */
|
||||
#define ISP176x_HC_INTERRUPT 0x310
|
||||
#define ISP176x_HC_INTERRUPT_ENABLE 0x314
|
||||
#define ISP176x_HC_ISO_IRQ_MASK_OR 0x318
|
||||
#define ISP176x_HC_INT_IRQ_MASK_OR 0x31c
|
||||
#define ISP176x_HC_ATL_IRQ_MASK_OR 0x320
|
||||
#define ISP176x_HC_ISO_IRQ_MASK_AND 0x324
|
||||
#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 */
|
||||
HCC_ISOC_CACHE, HCC_ISOC_THRES,
|
||||
/* HC_USBCMD */
|
||||
CMD_LRESET, CMD_RESET, CMD_RUN,
|
||||
/* HC_USBSTS */
|
||||
STS_PCD,
|
||||
/* HC_FRINDEX */
|
||||
HC_FRINDEX,
|
||||
/* HC_CONFIGFLAG */
|
||||
FLAG_CF,
|
||||
/* 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_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_ATX, SW_RESET_RESET_HC, SW_RESET_RESET_ALL,
|
||||
/* HC_BUFFER_STATUS */
|
||||
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_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
|
||||
*/
|
||||
|
||||
#define DC_IEPTX(n) (1 << (11 + 2 * (n)))
|
||||
#define DC_IEPRX(n) (1 << (10 + 2 * (n)))
|
||||
#define DC_IEPRXTX(n) (3 << (10 + 2 * (n)))
|
||||
|
||||
#define ISP176x_DC_CDBGMOD_ACK BIT(6)
|
||||
#define ISP176x_DC_DDBGMODIN_ACK BIT(4)
|
||||
#define ISP176x_DC_DDBGMODOUT_ACK BIT(2)
|
||||
|
||||
#define ISP176x_DC_IEP0SETUP BIT(8)
|
||||
#define ISP176x_DC_IEVBUS BIT(7)
|
||||
#define ISP176x_DC_IEHS_STA BIT(5)
|
||||
#define ISP176x_DC_IERESM BIT(4)
|
||||
#define ISP176x_DC_IESUSP BIT(3)
|
||||
#define ISP176x_DC_IEBRST BIT(0)
|
||||
|
||||
#define ISP176x_DC_ENDPTYP_ISOC 0x01
|
||||
#define ISP176x_DC_ENDPTYP_BULK 0x02
|
||||
#define ISP176x_DC_ENDPTYP_INTERRUPT 0x03
|
||||
|
||||
/* Initialization Registers */
|
||||
#define ISP176x_DC_ADDRESS 0x0200
|
||||
#define ISP176x_DC_MODE 0x020c
|
||||
#define ISP176x_DC_INTCONF 0x0210
|
||||
#define ISP176x_DC_DEBUG 0x0212
|
||||
#define ISP176x_DC_INTENABLE 0x0214
|
||||
|
||||
/* Data Flow Registers */
|
||||
#define ISP176x_DC_EPMAXPKTSZ 0x0204
|
||||
#define ISP176x_DC_EPTYPE 0x0208
|
||||
|
||||
#define ISP176x_DC_BUFLEN 0x021c
|
||||
#define ISP176x_DC_BUFSTAT 0x021e
|
||||
#define ISP176x_DC_DATAPORT 0x0220
|
||||
|
||||
#define ISP176x_DC_CTRLFUNC 0x0228
|
||||
#define ISP176x_DC_EPINDEX 0x022c
|
||||
|
||||
/* DMA Registers */
|
||||
#define ISP176x_DC_DMACMD 0x0230
|
||||
#define ISP176x_DC_DMATXCOUNT 0x0234
|
||||
#define ISP176x_DC_DMACONF 0x0238
|
||||
#define ISP176x_DC_DMAHW 0x023c
|
||||
#define ISP176x_DC_DMAINTREASON 0x0250
|
||||
#define ISP176x_DC_DMAINTEN 0x0254
|
||||
#define ISP176x_DC_DMAEP 0x0258
|
||||
#define ISP176x_DC_DMABURSTCOUNT 0x0264
|
||||
|
||||
/* General Registers */
|
||||
#define ISP176x_DC_INTERRUPT 0x0218
|
||||
#define ISP176x_DC_CHIPID 0x0270
|
||||
#define ISP176x_DC_FRAMENUM 0x0274
|
||||
#define ISP176x_DC_SCRATCH 0x0278
|
||||
#define ISP176x_DC_UNLOCKDEV 0x027c
|
||||
#define ISP176x_DC_INTPULSEWIDTH 0x0280
|
||||
#define ISP176x_DC_TESTMODE 0x0284
|
||||
|
||||
enum isp176x_device_controller_fields {
|
||||
/* DC_ADDRESS */
|
||||
DC_DEVEN, DC_DEVADDR,
|
||||
/* DC_MODE */
|
||||
DC_VBUSSTAT, DC_SFRESET, DC_GLINTENA,
|
||||
/* DC_INTCONF */
|
||||
DC_CDBGMOD_ACK, DC_DDBGMODIN_ACK, DC_DDBGMODOUT_ACK, DC_INTPOL,
|
||||
/* DC_INTENABLE */
|
||||
DC_IEPRXTX_7, DC_IEPRXTX_6, DC_IEPRXTX_5, DC_IEPRXTX_4, DC_IEPRXTX_3,
|
||||
DC_IEPRXTX_2, DC_IEPRXTX_1, DC_IEPRXTX_0,
|
||||
DC_IEP0SETUP, DC_IEVBUS, DC_IEHS_STA, DC_IERESM, DC_IESUSP, DC_IEBRST,
|
||||
/* DC_EPINDEX */
|
||||
DC_EP0SETUP, DC_ENDPIDX, DC_EPDIR,
|
||||
/* DC_CTRLFUNC */
|
||||
DC_CLBUF, DC_VENDP, DC_DSEN, DC_STATUS, DC_STALL,
|
||||
/* DC_BUFLEN */
|
||||
DC_BUFLEN,
|
||||
/* DC_EPMAXPKTSZ */
|
||||
DC_FFOSZ,
|
||||
/* DC_EPTYPE */
|
||||
DC_EPENABLE, DC_ENDPTYP,
|
||||
/* DC_FRAMENUM */
|
||||
DC_FRAMENUM, DC_UFRAMENUM,
|
||||
/* DC_CHIP_ID */
|
||||
DC_CHIP_ID_HIGH, DC_CHIP_ID_LOW,
|
||||
/* DC_SCRATCH */
|
||||
DC_SCRATCH,
|
||||
/* Last element */
|
||||
DC_FIELD_MAX,
|
||||
};
|
||||
|
||||
/* ISP1763 */
|
||||
/* Initialization Registers */
|
||||
#define ISP1763_DC_ADDRESS 0x00
|
||||
#define ISP1763_DC_MODE 0x0c
|
||||
#define ISP1763_DC_INTCONF 0x10
|
||||
#define ISP1763_DC_INTENABLE 0x14
|
||||
|
||||
/* Data Flow Registers */
|
||||
#define ISP1763_DC_EPMAXPKTSZ 0x04
|
||||
#define ISP1763_DC_EPTYPE 0x08
|
||||
|
||||
#define ISP1763_DC_BUFLEN 0x1c
|
||||
#define ISP1763_DC_BUFSTAT 0x1e
|
||||
#define ISP1763_DC_DATAPORT 0x20
|
||||
|
||||
#define ISP1763_DC_CTRLFUNC 0x28
|
||||
#define ISP1763_DC_EPINDEX 0x2c
|
||||
|
||||
/* DMA Registers */
|
||||
#define ISP1763_DC_DMACMD 0x30
|
||||
#define ISP1763_DC_DMATXCOUNT 0x34
|
||||
#define ISP1763_DC_DMACONF 0x38
|
||||
#define ISP1763_DC_DMAHW 0x3c
|
||||
#define ISP1763_DC_DMAINTREASON 0x50
|
||||
#define ISP1763_DC_DMAINTEN 0x54
|
||||
#define ISP1763_DC_DMAEP 0x58
|
||||
#define ISP1763_DC_DMABURSTCOUNT 0x64
|
||||
|
||||
/* General Registers */
|
||||
#define ISP1763_DC_INTERRUPT 0x18
|
||||
#define ISP1763_DC_CHIPID_LOW 0x70
|
||||
#define ISP1763_DC_CHIPID_HIGH 0x72
|
||||
#define ISP1763_DC_FRAMENUM 0x74
|
||||
#define ISP1763_DC_SCRATCH 0x78
|
||||
#define ISP1763_DC_UNLOCKDEV 0x7c
|
||||
#define ISP1763_DC_INTPULSEWIDTH 0x80
|
||||
#define ISP1763_DC_TESTMODE 0x84
|
||||
|
||||
#endif
|
75
drivers/usb/isp1760/isp1760-uboot.c
Normal file
75
drivers/usb/isp1760/isp1760-uboot.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-hcd.h"
|
||||
#include "isp1760-regs.h"
|
||||
#include "isp1760-uboot.h"
|
||||
|
||||
static int isp1760_msg_submit_control(struct udevice *dev,
|
||||
struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer,
|
||||
int length, struct devrequest *setup)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_control(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length, setup, 0,
|
||||
host->host_speed);
|
||||
}
|
||||
|
||||
static int isp1760_msg_submit_bulk(struct udevice *dev, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_bulk(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length);
|
||||
}
|
||||
|
||||
static int isp1760_msg_submit_irq(struct udevice *dev, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length,
|
||||
int interval, bool nonblock)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_irq(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length, interval);
|
||||
}
|
||||
|
||||
static int isp1760_get_max_xfer_size(struct udevice *dev, size_t *size)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
struct isp1760_hcd *priv = host->hcd.hcd_priv;
|
||||
const struct isp1760_memory_layout *mem = priv->memory_layout;
|
||||
|
||||
*size = mem->blocks_size[ISP176x_BLOCK_NUM - 1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dm_usb_ops isp1760_usb_ops = {
|
||||
.control = isp1760_msg_submit_control,
|
||||
.bulk = isp1760_msg_submit_bulk,
|
||||
.interrupt = isp1760_msg_submit_irq,
|
||||
.get_max_xfer_size = isp1760_get_max_xfer_size,
|
||||
};
|
27
drivers/usb/isp1760/isp1760-uboot.h
Normal file
27
drivers/usb/isp1760/isp1760-uboot.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ISP1760_UBOOT_H__
|
||||
#define __ISP1760_UBOOT_H__
|
||||
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
|
||||
struct isp1760_host_data {
|
||||
struct isp1760_hcd *priv;
|
||||
struct usb_hcd hcd;
|
||||
enum usb_device_speed host_speed;
|
||||
struct usb_host_endpoint hep;
|
||||
struct urb urb;
|
||||
};
|
||||
|
||||
extern struct dm_usb_ops isp1760_usb_ops;
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue