xref: /openbmc/qemu/hw/usb/tusb6010.c (revision c122bca9)
114ec7b2cSPeter Maydell /*
214ec7b2cSPeter Maydell  * Texas Instruments TUSB6010 emulation.
314ec7b2cSPeter Maydell  * Based on reverse-engineering of a linux driver.
414ec7b2cSPeter Maydell  *
514ec7b2cSPeter Maydell  * Copyright (C) 2008 Nokia Corporation
614ec7b2cSPeter Maydell  * Written by Andrzej Zaborowski <andrew@openedhand.com>
714ec7b2cSPeter Maydell  *
814ec7b2cSPeter Maydell  * This program is free software; you can redistribute it and/or
914ec7b2cSPeter Maydell  * modify it under the terms of the GNU General Public License as
1014ec7b2cSPeter Maydell  * published by the Free Software Foundation; either version 2 or
1114ec7b2cSPeter Maydell  * (at your option) version 3 of the License.
1214ec7b2cSPeter Maydell  *
1314ec7b2cSPeter Maydell  * This program is distributed in the hope that it will be useful,
1414ec7b2cSPeter Maydell  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1514ec7b2cSPeter Maydell  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1614ec7b2cSPeter Maydell  * GNU General Public License for more details.
1714ec7b2cSPeter Maydell  *
1814ec7b2cSPeter Maydell  * You should have received a copy of the GNU General Public License along
1914ec7b2cSPeter Maydell  * with this program; if not, see <http://www.gnu.org/licenses/>.
2014ec7b2cSPeter Maydell  */
210b8fa32fSMarkus Armbruster 
2214ec7b2cSPeter Maydell #include "qemu/osdep.h"
230b8fa32fSMarkus Armbruster #include "qemu/module.h"
2414ec7b2cSPeter Maydell #include "qemu/timer.h"
2514ec7b2cSPeter Maydell #include "hw/usb.h"
262c89d911SPhilippe Mathieu-Daudé #include "hw/usb/hcd-musb.h"
2714ec7b2cSPeter Maydell #include "hw/arm/omap.h"
28650d103dSMarkus Armbruster #include "hw/hw.h"
2914ec7b2cSPeter Maydell #include "hw/irq.h"
3014ec7b2cSPeter Maydell #include "hw/sysbus.h"
31db1015e9SEduardo Habkost #include "qom/object.h"
3214ec7b2cSPeter Maydell 
3314ec7b2cSPeter Maydell #define TYPE_TUSB6010 "tusb6010"
34*8063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(TUSBState, TUSB6010)
3514ec7b2cSPeter Maydell 
36db1015e9SEduardo Habkost struct TUSBState {
3714ec7b2cSPeter Maydell     SysBusDevice parent_obj;
3814ec7b2cSPeter Maydell 
3914ec7b2cSPeter Maydell     MemoryRegion iomem[2];
4014ec7b2cSPeter Maydell     qemu_irq irq;
4114ec7b2cSPeter Maydell     MUSBState *musb;
4214ec7b2cSPeter Maydell     QEMUTimer *otg_timer;
4314ec7b2cSPeter Maydell     QEMUTimer *pwr_timer;
4414ec7b2cSPeter Maydell 
4514ec7b2cSPeter Maydell     int power;
4614ec7b2cSPeter Maydell     uint32_t scratch;
4714ec7b2cSPeter Maydell     uint16_t test_reset;
4814ec7b2cSPeter Maydell     uint32_t prcm_config;
4914ec7b2cSPeter Maydell     uint32_t prcm_mngmt;
5014ec7b2cSPeter Maydell     uint16_t otg_status;
5114ec7b2cSPeter Maydell     uint32_t dev_config;
5214ec7b2cSPeter Maydell     int host_mode;
5314ec7b2cSPeter Maydell     uint32_t intr;
5414ec7b2cSPeter Maydell     uint32_t intr_ok;
5514ec7b2cSPeter Maydell     uint32_t mask;
5614ec7b2cSPeter Maydell     uint32_t usbip_intr;
5714ec7b2cSPeter Maydell     uint32_t usbip_mask;
5814ec7b2cSPeter Maydell     uint32_t gpio_intr;
5914ec7b2cSPeter Maydell     uint32_t gpio_mask;
6014ec7b2cSPeter Maydell     uint32_t gpio_config;
6114ec7b2cSPeter Maydell     uint32_t dma_intr;
6214ec7b2cSPeter Maydell     uint32_t dma_mask;
6314ec7b2cSPeter Maydell     uint32_t dma_map;
6414ec7b2cSPeter Maydell     uint32_t dma_config;
6514ec7b2cSPeter Maydell     uint32_t ep0_config;
6614ec7b2cSPeter Maydell     uint32_t rx_config[15];
6714ec7b2cSPeter Maydell     uint32_t tx_config[15];
6814ec7b2cSPeter Maydell     uint32_t wkup_mask;
6914ec7b2cSPeter Maydell     uint32_t pullup[2];
7014ec7b2cSPeter Maydell     uint32_t control_config;
7114ec7b2cSPeter Maydell     uint32_t otg_timer_val;
72db1015e9SEduardo Habkost };
7314ec7b2cSPeter Maydell 
7414ec7b2cSPeter Maydell #define TUSB_DEVCLOCK			60000000	/* 60 MHz */
7514ec7b2cSPeter Maydell 
7614ec7b2cSPeter Maydell #define TUSB_VLYNQ_CTRL			0x004
7714ec7b2cSPeter Maydell 
7814ec7b2cSPeter Maydell /* Mentor Graphics OTG core registers.  */
7914ec7b2cSPeter Maydell #define TUSB_BASE_OFFSET		0x400
8014ec7b2cSPeter Maydell 
8114ec7b2cSPeter Maydell /* FIFO registers, 32-bit.  */
8214ec7b2cSPeter Maydell #define TUSB_FIFO_BASE			0x600
8314ec7b2cSPeter Maydell 
8414ec7b2cSPeter Maydell /* Device System & Control registers, 32-bit.  */
8514ec7b2cSPeter Maydell #define TUSB_SYS_REG_BASE		0x800
8614ec7b2cSPeter Maydell 
8714ec7b2cSPeter Maydell #define TUSB_DEV_CONF			(TUSB_SYS_REG_BASE + 0x000)
8814ec7b2cSPeter Maydell #define	TUSB_DEV_CONF_USB_HOST_MODE	(1 << 16)
8914ec7b2cSPeter Maydell #define	TUSB_DEV_CONF_PROD_TEST_MODE	(1 << 15)
9014ec7b2cSPeter Maydell #define	TUSB_DEV_CONF_SOFT_ID		(1 << 1)
9114ec7b2cSPeter Maydell #define	TUSB_DEV_CONF_ID_SEL		(1 << 0)
9214ec7b2cSPeter Maydell 
9314ec7b2cSPeter Maydell #define TUSB_PHY_OTG_CTRL_ENABLE	(TUSB_SYS_REG_BASE + 0x004)
9414ec7b2cSPeter Maydell #define TUSB_PHY_OTG_CTRL		(TUSB_SYS_REG_BASE + 0x008)
9514ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_WRPROTECT	(0xa5 << 24)
9614ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_O_ID_PULLUP	(1 << 23)
9714ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_O_VBUS_DET_EN	(1 << 19)
9814ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_O_SESS_END_EN	(1 << 18)
9914ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TESTM2	(1 << 17)
10014ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TESTM1	(1 << 16)
10114ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TESTM0	(1 << 15)
10214ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TX_DATA2	(1 << 14)
10314ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TX_GZ2	(1 << 13)
10414ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_TX_ENABLE2	(1 << 12)
10514ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_DM_PULLDOWN	(1 << 11)
10614ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_DP_PULLDOWN	(1 << 10)
10714ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_OSC_EN	(1 << 9)
10814ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_PHYREF_CLK(v)	(((v) & 3) << 7)
10914ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_PD		(1 << 6)
11014ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_PLL_ON	(1 << 5)
11114ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_EXT_RPU	(1 << 4)
11214ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_PWR_GOOD	(1 << 3)
11314ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_RESET		(1 << 2)
11414ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_SUSPENDM	(1 << 1)
11514ec7b2cSPeter Maydell #define	TUSB_PHY_OTG_CTRL_CLK_MODE	(1 << 0)
11614ec7b2cSPeter Maydell 
11714ec7b2cSPeter Maydell /* OTG status register */
11814ec7b2cSPeter Maydell #define TUSB_DEV_OTG_STAT		(TUSB_SYS_REG_BASE + 0x00c)
11914ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_PWR_CLK_GOOD	(1 << 8)
12014ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_SESS_END	(1 << 7)
12114ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_SESS_VALID	(1 << 6)
12214ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_VBUS_VALID	(1 << 5)
12314ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_VBUS_SENSE	(1 << 4)
12414ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_ID_STATUS	(1 << 3)
12514ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_HOST_DISCON	(1 << 2)
12614ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_LINE_STATE	(3 << 0)
12714ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_DP_ENABLE	(1 << 1)
12814ec7b2cSPeter Maydell #define	TUSB_DEV_OTG_STAT_DM_ENABLE	(1 << 0)
12914ec7b2cSPeter Maydell 
13014ec7b2cSPeter Maydell #define TUSB_DEV_OTG_TIMER		(TUSB_SYS_REG_BASE + 0x010)
13114ec7b2cSPeter Maydell #define TUSB_DEV_OTG_TIMER_ENABLE	(1 << 31)
13214ec7b2cSPeter Maydell #define TUSB_DEV_OTG_TIMER_VAL(v)	((v) & 0x07ffffff)
13314ec7b2cSPeter Maydell #define TUSB_PRCM_REV			(TUSB_SYS_REG_BASE + 0x014)
13414ec7b2cSPeter Maydell 
13514ec7b2cSPeter Maydell /* PRCM configuration register */
13614ec7b2cSPeter Maydell #define TUSB_PRCM_CONF			(TUSB_SYS_REG_BASE + 0x018)
13714ec7b2cSPeter Maydell #define	TUSB_PRCM_CONF_SFW_CPEN		(1 << 24)
13814ec7b2cSPeter Maydell #define	TUSB_PRCM_CONF_SYS_CLKSEL(v)	(((v) & 3) << 16)
13914ec7b2cSPeter Maydell 
14014ec7b2cSPeter Maydell /* PRCM management register */
14114ec7b2cSPeter Maydell #define TUSB_PRCM_MNGMT			(TUSB_SYS_REG_BASE + 0x01c)
14214ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_SRP_FIX_TMR(v)	(((v) & 0xf) << 25)
14314ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_SRP_FIX_EN	(1 << 24)
14414ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_VBUS_VAL_TMR(v)	(((v) & 0xf) << 20)
14514ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_VBUS_VAL_FLT_EN	(1 << 19)
14614ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_DFT_CLK_DIS	(1 << 18)
14714ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_VLYNQ_CLK_DIS	(1 << 17)
14814ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_OTG_SESS_END_EN	(1 << 10)
14914ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN	(1 << 9)
15014ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_OTG_ID_PULLUP	(1 << 8)
15114ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_15_SW_EN	(1 << 4)
15214ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_33_SW_EN	(1 << 3)
15314ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_5V_CPEN		(1 << 2)
15414ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_PM_IDLE		(1 << 1)
15514ec7b2cSPeter Maydell #define	TUSB_PRCM_MNGMT_DEV_IDLE	(1 << 0)
15614ec7b2cSPeter Maydell 
15714ec7b2cSPeter Maydell /* Wake-up source clear and mask registers */
15814ec7b2cSPeter Maydell #define TUSB_PRCM_WAKEUP_SOURCE		(TUSB_SYS_REG_BASE + 0x020)
15914ec7b2cSPeter Maydell #define TUSB_PRCM_WAKEUP_CLEAR		(TUSB_SYS_REG_BASE + 0x028)
16014ec7b2cSPeter Maydell #define TUSB_PRCM_WAKEUP_MASK		(TUSB_SYS_REG_BASE + 0x02c)
16114ec7b2cSPeter Maydell #define	TUSB_PRCM_WAKEUP_RESERVED_BITS	(0xffffe << 13)
16214ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_7		(1 << 12)
16314ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_6		(1 << 11)
16414ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_5		(1 << 10)
16514ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_4		(1 << 9)
16614ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_3		(1 << 8)
16714ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_2		(1 << 7)
16814ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_1		(1 << 6)
16914ec7b2cSPeter Maydell #define	TUSB_PRCM_WGPIO_0		(1 << 5)
17014ec7b2cSPeter Maydell #define	TUSB_PRCM_WHOSTDISCON		(1 << 4)	/* Host disconnect */
17114ec7b2cSPeter Maydell #define	TUSB_PRCM_WBUS			(1 << 3)	/* USB bus resume */
17214ec7b2cSPeter Maydell #define	TUSB_PRCM_WNORCS		(1 << 2)	/* NOR chip select */
17314ec7b2cSPeter Maydell #define	TUSB_PRCM_WVBUS			(1 << 1)	/* OTG PHY VBUS */
17414ec7b2cSPeter Maydell #define	TUSB_PRCM_WID			(1 << 0)	/* OTG PHY ID detect */
17514ec7b2cSPeter Maydell 
17614ec7b2cSPeter Maydell #define TUSB_PULLUP_1_CTRL		(TUSB_SYS_REG_BASE + 0x030)
17714ec7b2cSPeter Maydell #define TUSB_PULLUP_2_CTRL		(TUSB_SYS_REG_BASE + 0x034)
17814ec7b2cSPeter Maydell #define TUSB_INT_CTRL_REV		(TUSB_SYS_REG_BASE + 0x038)
17914ec7b2cSPeter Maydell #define TUSB_INT_CTRL_CONF		(TUSB_SYS_REG_BASE + 0x03c)
18014ec7b2cSPeter Maydell #define TUSB_USBIP_INT_SRC		(TUSB_SYS_REG_BASE + 0x040)
18114ec7b2cSPeter Maydell #define TUSB_USBIP_INT_SET		(TUSB_SYS_REG_BASE + 0x044)
18214ec7b2cSPeter Maydell #define TUSB_USBIP_INT_CLEAR		(TUSB_SYS_REG_BASE + 0x048)
18314ec7b2cSPeter Maydell #define TUSB_USBIP_INT_MASK		(TUSB_SYS_REG_BASE + 0x04c)
18414ec7b2cSPeter Maydell #define TUSB_DMA_INT_SRC		(TUSB_SYS_REG_BASE + 0x050)
18514ec7b2cSPeter Maydell #define TUSB_DMA_INT_SET		(TUSB_SYS_REG_BASE + 0x054)
18614ec7b2cSPeter Maydell #define TUSB_DMA_INT_CLEAR		(TUSB_SYS_REG_BASE + 0x058)
18714ec7b2cSPeter Maydell #define TUSB_DMA_INT_MASK		(TUSB_SYS_REG_BASE + 0x05c)
18814ec7b2cSPeter Maydell #define TUSB_GPIO_INT_SRC		(TUSB_SYS_REG_BASE + 0x060)
18914ec7b2cSPeter Maydell #define TUSB_GPIO_INT_SET		(TUSB_SYS_REG_BASE + 0x064)
19014ec7b2cSPeter Maydell #define TUSB_GPIO_INT_CLEAR		(TUSB_SYS_REG_BASE + 0x068)
19114ec7b2cSPeter Maydell #define TUSB_GPIO_INT_MASK		(TUSB_SYS_REG_BASE + 0x06c)
19214ec7b2cSPeter Maydell 
19314ec7b2cSPeter Maydell /* NOR flash interrupt source registers */
19414ec7b2cSPeter Maydell #define TUSB_INT_SRC			(TUSB_SYS_REG_BASE + 0x070)
19514ec7b2cSPeter Maydell #define TUSB_INT_SRC_SET		(TUSB_SYS_REG_BASE + 0x074)
19614ec7b2cSPeter Maydell #define TUSB_INT_SRC_CLEAR		(TUSB_SYS_REG_BASE + 0x078)
19714ec7b2cSPeter Maydell #define TUSB_INT_MASK			(TUSB_SYS_REG_BASE + 0x07c)
19814ec7b2cSPeter Maydell #define	TUSB_INT_SRC_TXRX_DMA_DONE	(1 << 24)
19914ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_CORE	(1 << 17)
20014ec7b2cSPeter Maydell #define	TUSB_INT_SRC_OTG_TIMEOUT	(1 << 16)
20114ec7b2cSPeter Maydell #define	TUSB_INT_SRC_VBUS_SENSE_CHNG	(1 << 15)
20214ec7b2cSPeter Maydell #define	TUSB_INT_SRC_ID_STATUS_CHNG	(1 << 14)
20314ec7b2cSPeter Maydell #define	TUSB_INT_SRC_DEV_WAKEUP		(1 << 13)
20414ec7b2cSPeter Maydell #define	TUSB_INT_SRC_DEV_READY		(1 << 12)
20514ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_TX		(1 << 9)
20614ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_RX		(1 << 8)
20714ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_VBUS_ERR	(1 << 7)
20814ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_VBUS_REQ	(1 << 6)
20914ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_DISCON	(1 << 5)
21014ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_CONN	(1 << 4)
21114ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_SOF		(1 << 3)
21214ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_RST_BABBLE	(1 << 2)
21314ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_RESUME	(1 << 1)
21414ec7b2cSPeter Maydell #define	TUSB_INT_SRC_USB_IP_SUSPEND	(1 << 0)
21514ec7b2cSPeter Maydell 
21614ec7b2cSPeter Maydell #define TUSB_GPIO_REV			(TUSB_SYS_REG_BASE + 0x080)
21714ec7b2cSPeter Maydell #define TUSB_GPIO_CONF			(TUSB_SYS_REG_BASE + 0x084)
21814ec7b2cSPeter Maydell #define TUSB_DMA_CTRL_REV		(TUSB_SYS_REG_BASE + 0x100)
21914ec7b2cSPeter Maydell #define TUSB_DMA_REQ_CONF		(TUSB_SYS_REG_BASE + 0x104)
22014ec7b2cSPeter Maydell #define TUSB_EP0_CONF			(TUSB_SYS_REG_BASE + 0x108)
22114ec7b2cSPeter Maydell #define TUSB_EP_IN_SIZE			(TUSB_SYS_REG_BASE + 0x10c)
22214ec7b2cSPeter Maydell #define TUSB_DMA_EP_MAP			(TUSB_SYS_REG_BASE + 0x148)
22314ec7b2cSPeter Maydell #define TUSB_EP_OUT_SIZE		(TUSB_SYS_REG_BASE + 0x14c)
22414ec7b2cSPeter Maydell #define TUSB_EP_MAX_PACKET_SIZE_OFFSET	(TUSB_SYS_REG_BASE + 0x188)
22514ec7b2cSPeter Maydell #define TUSB_SCRATCH_PAD		(TUSB_SYS_REG_BASE + 0x1c4)
22614ec7b2cSPeter Maydell #define TUSB_WAIT_COUNT			(TUSB_SYS_REG_BASE + 0x1c8)
22714ec7b2cSPeter Maydell #define TUSB_PROD_TEST_RESET		(TUSB_SYS_REG_BASE + 0x1d8)
22814ec7b2cSPeter Maydell 
22914ec7b2cSPeter Maydell #define TUSB_DIDR1_LO			(TUSB_SYS_REG_BASE + 0x1f8)
23014ec7b2cSPeter Maydell #define TUSB_DIDR1_HI			(TUSB_SYS_REG_BASE + 0x1fc)
23114ec7b2cSPeter Maydell 
23214ec7b2cSPeter Maydell /* Device System & Control register bitfields */
23314ec7b2cSPeter Maydell #define TUSB_INT_CTRL_CONF_INT_RLCYC(v)	(((v) & 0x7) << 18)
23414ec7b2cSPeter Maydell #define TUSB_INT_CTRL_CONF_INT_POLARITY	(1 << 17)
23514ec7b2cSPeter Maydell #define TUSB_INT_CTRL_CONF_INT_MODE	(1 << 16)
23614ec7b2cSPeter Maydell #define TUSB_GPIO_CONF_DMAREQ(v)	(((v) & 0x3f) << 24)
23714ec7b2cSPeter Maydell #define TUSB_DMA_REQ_CONF_BURST_SIZE(v)	(((v) & 3) << 26)
23814ec7b2cSPeter Maydell #define TUSB_DMA_REQ_CONF_DMA_RQ_EN(v)	(((v) & 0x3f) << 20)
23914ec7b2cSPeter Maydell #define TUSB_DMA_REQ_CONF_DMA_RQ_ASR(v)	(((v) & 0xf) << 16)
24014ec7b2cSPeter Maydell #define TUSB_EP0_CONFIG_SW_EN		(1 << 8)
24114ec7b2cSPeter Maydell #define TUSB_EP0_CONFIG_DIR_TX		(1 << 7)
24214ec7b2cSPeter Maydell #define TUSB_EP0_CONFIG_XFR_SIZE(v)	((v) & 0x7f)
24314ec7b2cSPeter Maydell #define TUSB_EP_CONFIG_SW_EN		(1 << 31)
24414ec7b2cSPeter Maydell #define TUSB_EP_CONFIG_XFR_SIZE(v)	((v) & 0x7fffffff)
24514ec7b2cSPeter Maydell #define TUSB_PROD_TEST_RESET_VAL	0xa596
24614ec7b2cSPeter Maydell 
tusb_intr_update(TUSBState * s)24714ec7b2cSPeter Maydell static void tusb_intr_update(TUSBState *s)
24814ec7b2cSPeter Maydell {
24914ec7b2cSPeter Maydell     if (s->control_config & TUSB_INT_CTRL_CONF_INT_POLARITY)
25014ec7b2cSPeter Maydell         qemu_set_irq(s->irq, s->intr & ~s->mask & s->intr_ok);
25114ec7b2cSPeter Maydell     else
25214ec7b2cSPeter Maydell         qemu_set_irq(s->irq, (!(s->intr & ~s->mask)) & s->intr_ok);
25314ec7b2cSPeter Maydell }
25414ec7b2cSPeter Maydell 
tusb_usbip_intr_update(TUSBState * s)25514ec7b2cSPeter Maydell static void tusb_usbip_intr_update(TUSBState *s)
25614ec7b2cSPeter Maydell {
25714ec7b2cSPeter Maydell     /* TX interrupt in the MUSB */
25814ec7b2cSPeter Maydell     if (s->usbip_intr & 0x0000ffff & ~s->usbip_mask)
25914ec7b2cSPeter Maydell         s->intr |= TUSB_INT_SRC_USB_IP_TX;
26014ec7b2cSPeter Maydell     else
26114ec7b2cSPeter Maydell         s->intr &= ~TUSB_INT_SRC_USB_IP_TX;
26214ec7b2cSPeter Maydell 
26314ec7b2cSPeter Maydell     /* RX interrupt in the MUSB */
26414ec7b2cSPeter Maydell     if (s->usbip_intr & 0xffff0000 & ~s->usbip_mask)
26514ec7b2cSPeter Maydell         s->intr |= TUSB_INT_SRC_USB_IP_RX;
26614ec7b2cSPeter Maydell     else
26714ec7b2cSPeter Maydell         s->intr &= ~TUSB_INT_SRC_USB_IP_RX;
26814ec7b2cSPeter Maydell 
26914ec7b2cSPeter Maydell     /* XXX: What about TUSB_INT_SRC_USB_IP_CORE?  */
27014ec7b2cSPeter Maydell 
27114ec7b2cSPeter Maydell     tusb_intr_update(s);
27214ec7b2cSPeter Maydell }
27314ec7b2cSPeter Maydell 
tusb_dma_intr_update(TUSBState * s)27414ec7b2cSPeter Maydell static void tusb_dma_intr_update(TUSBState *s)
27514ec7b2cSPeter Maydell {
27614ec7b2cSPeter Maydell     if (s->dma_intr & ~s->dma_mask)
27714ec7b2cSPeter Maydell         s->intr |= TUSB_INT_SRC_TXRX_DMA_DONE;
27814ec7b2cSPeter Maydell     else
27914ec7b2cSPeter Maydell         s->intr &= ~TUSB_INT_SRC_TXRX_DMA_DONE;
28014ec7b2cSPeter Maydell 
28114ec7b2cSPeter Maydell     tusb_intr_update(s);
28214ec7b2cSPeter Maydell }
28314ec7b2cSPeter Maydell 
tusb_gpio_intr_update(TUSBState * s)28414ec7b2cSPeter Maydell static void tusb_gpio_intr_update(TUSBState *s)
28514ec7b2cSPeter Maydell {
28614ec7b2cSPeter Maydell     /* TODO: How is this signalled?  */
28714ec7b2cSPeter Maydell }
28814ec7b2cSPeter Maydell 
tusb_async_readb(void * opaque,hwaddr addr)28914ec7b2cSPeter Maydell static uint32_t tusb_async_readb(void *opaque, hwaddr addr)
29014ec7b2cSPeter Maydell {
29114ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
29214ec7b2cSPeter Maydell 
29314ec7b2cSPeter Maydell     switch (addr & 0xfff) {
29414ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
29514ec7b2cSPeter Maydell         return musb_read[0](s->musb, addr & 0x1ff);
29614ec7b2cSPeter Maydell 
29714ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
29814ec7b2cSPeter Maydell         return musb_read[0](s->musb, 0x20 + ((addr >> 3) & 0x3c));
29914ec7b2cSPeter Maydell     }
30014ec7b2cSPeter Maydell 
30114ec7b2cSPeter Maydell     printf("%s: unknown register at %03x\n",
302a89f364aSAlistair Francis                     __func__, (int) (addr & 0xfff));
30314ec7b2cSPeter Maydell     return 0;
30414ec7b2cSPeter Maydell }
30514ec7b2cSPeter Maydell 
tusb_async_readh(void * opaque,hwaddr addr)30614ec7b2cSPeter Maydell static uint32_t tusb_async_readh(void *opaque, hwaddr addr)
30714ec7b2cSPeter Maydell {
30814ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
30914ec7b2cSPeter Maydell 
31014ec7b2cSPeter Maydell     switch (addr & 0xfff) {
31114ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
31214ec7b2cSPeter Maydell         return musb_read[1](s->musb, addr & 0x1ff);
31314ec7b2cSPeter Maydell 
31414ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
31514ec7b2cSPeter Maydell         return musb_read[1](s->musb, 0x20 + ((addr >> 3) & 0x3c));
31614ec7b2cSPeter Maydell     }
31714ec7b2cSPeter Maydell 
31814ec7b2cSPeter Maydell     printf("%s: unknown register at %03x\n",
319a89f364aSAlistair Francis                     __func__, (int) (addr & 0xfff));
32014ec7b2cSPeter Maydell     return 0;
32114ec7b2cSPeter Maydell }
32214ec7b2cSPeter Maydell 
tusb_async_readw(void * opaque,hwaddr addr)32314ec7b2cSPeter Maydell static uint32_t tusb_async_readw(void *opaque, hwaddr addr)
32414ec7b2cSPeter Maydell {
32514ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
32614ec7b2cSPeter Maydell     int offset = addr & 0xfff;
32714ec7b2cSPeter Maydell     int epnum;
32814ec7b2cSPeter Maydell     uint32_t ret;
32914ec7b2cSPeter Maydell 
33014ec7b2cSPeter Maydell     switch (offset) {
33114ec7b2cSPeter Maydell     case TUSB_DEV_CONF:
33214ec7b2cSPeter Maydell         return s->dev_config;
33314ec7b2cSPeter Maydell 
33414ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
33514ec7b2cSPeter Maydell         return musb_read[2](s->musb, offset & 0x1ff);
33614ec7b2cSPeter Maydell 
33714ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
33814ec7b2cSPeter Maydell         return musb_read[2](s->musb, 0x20 + ((addr >> 3) & 0x3c));
33914ec7b2cSPeter Maydell 
34014ec7b2cSPeter Maydell     case TUSB_PHY_OTG_CTRL_ENABLE:
34114ec7b2cSPeter Maydell     case TUSB_PHY_OTG_CTRL:
34214ec7b2cSPeter Maydell         return 0x00;	/* TODO */
34314ec7b2cSPeter Maydell 
34414ec7b2cSPeter Maydell     case TUSB_DEV_OTG_STAT:
34514ec7b2cSPeter Maydell         ret = s->otg_status;
34614ec7b2cSPeter Maydell #if 0
34714ec7b2cSPeter Maydell         if (!(s->prcm_mngmt & TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN))
34814ec7b2cSPeter Maydell             ret &= ~TUSB_DEV_OTG_STAT_VBUS_VALID;
34914ec7b2cSPeter Maydell #endif
35014ec7b2cSPeter Maydell         return ret;
35114ec7b2cSPeter Maydell     case TUSB_DEV_OTG_TIMER:
35214ec7b2cSPeter Maydell         return s->otg_timer_val;
35314ec7b2cSPeter Maydell 
35414ec7b2cSPeter Maydell     case TUSB_PRCM_REV:
35514ec7b2cSPeter Maydell         return 0x20;
35614ec7b2cSPeter Maydell     case TUSB_PRCM_CONF:
35714ec7b2cSPeter Maydell         return s->prcm_config;
35814ec7b2cSPeter Maydell     case TUSB_PRCM_MNGMT:
35914ec7b2cSPeter Maydell         return s->prcm_mngmt;
36014ec7b2cSPeter Maydell     case TUSB_PRCM_WAKEUP_SOURCE:
36114ec7b2cSPeter Maydell     case TUSB_PRCM_WAKEUP_CLEAR:	/* TODO: What does this one return?  */
36214ec7b2cSPeter Maydell         return 0x00000000;
36314ec7b2cSPeter Maydell     case TUSB_PRCM_WAKEUP_MASK:
36414ec7b2cSPeter Maydell         return s->wkup_mask;
36514ec7b2cSPeter Maydell 
36614ec7b2cSPeter Maydell     case TUSB_PULLUP_1_CTRL:
36714ec7b2cSPeter Maydell         return s->pullup[0];
36814ec7b2cSPeter Maydell     case TUSB_PULLUP_2_CTRL:
36914ec7b2cSPeter Maydell         return s->pullup[1];
37014ec7b2cSPeter Maydell 
37114ec7b2cSPeter Maydell     case TUSB_INT_CTRL_REV:
37214ec7b2cSPeter Maydell         return 0x20;
37314ec7b2cSPeter Maydell     case TUSB_INT_CTRL_CONF:
37414ec7b2cSPeter Maydell         return s->control_config;
37514ec7b2cSPeter Maydell 
37614ec7b2cSPeter Maydell     case TUSB_USBIP_INT_SRC:
37714ec7b2cSPeter Maydell     case TUSB_USBIP_INT_SET:	/* TODO: What do these two return?  */
37814ec7b2cSPeter Maydell     case TUSB_USBIP_INT_CLEAR:
37914ec7b2cSPeter Maydell         return s->usbip_intr;
38014ec7b2cSPeter Maydell     case TUSB_USBIP_INT_MASK:
38114ec7b2cSPeter Maydell         return s->usbip_mask;
38214ec7b2cSPeter Maydell 
38314ec7b2cSPeter Maydell     case TUSB_DMA_INT_SRC:
38414ec7b2cSPeter Maydell     case TUSB_DMA_INT_SET:	/* TODO: What do these two return?  */
38514ec7b2cSPeter Maydell     case TUSB_DMA_INT_CLEAR:
38614ec7b2cSPeter Maydell         return s->dma_intr;
38714ec7b2cSPeter Maydell     case TUSB_DMA_INT_MASK:
38814ec7b2cSPeter Maydell         return s->dma_mask;
38914ec7b2cSPeter Maydell 
39014ec7b2cSPeter Maydell     case TUSB_GPIO_INT_SRC:	/* TODO: What do these two return?  */
39114ec7b2cSPeter Maydell     case TUSB_GPIO_INT_SET:
39214ec7b2cSPeter Maydell     case TUSB_GPIO_INT_CLEAR:
39314ec7b2cSPeter Maydell         return s->gpio_intr;
39414ec7b2cSPeter Maydell     case TUSB_GPIO_INT_MASK:
39514ec7b2cSPeter Maydell         return s->gpio_mask;
39614ec7b2cSPeter Maydell 
39714ec7b2cSPeter Maydell     case TUSB_INT_SRC:
39814ec7b2cSPeter Maydell     case TUSB_INT_SRC_SET:	/* TODO: What do these two return?  */
39914ec7b2cSPeter Maydell     case TUSB_INT_SRC_CLEAR:
40014ec7b2cSPeter Maydell         return s->intr;
40114ec7b2cSPeter Maydell     case TUSB_INT_MASK:
40214ec7b2cSPeter Maydell         return s->mask;
40314ec7b2cSPeter Maydell 
40414ec7b2cSPeter Maydell     case TUSB_GPIO_REV:
40514ec7b2cSPeter Maydell         return 0x30;
40614ec7b2cSPeter Maydell     case TUSB_GPIO_CONF:
40714ec7b2cSPeter Maydell         return s->gpio_config;
40814ec7b2cSPeter Maydell 
40914ec7b2cSPeter Maydell     case TUSB_DMA_CTRL_REV:
41014ec7b2cSPeter Maydell         return 0x30;
41114ec7b2cSPeter Maydell     case TUSB_DMA_REQ_CONF:
41214ec7b2cSPeter Maydell         return s->dma_config;
41314ec7b2cSPeter Maydell     case TUSB_EP0_CONF:
41414ec7b2cSPeter Maydell         return s->ep0_config;
41514ec7b2cSPeter Maydell     case TUSB_EP_IN_SIZE ... (TUSB_EP_IN_SIZE + 0x3b):
41614ec7b2cSPeter Maydell         epnum = (offset - TUSB_EP_IN_SIZE) >> 2;
41714ec7b2cSPeter Maydell         return s->tx_config[epnum];
41814ec7b2cSPeter Maydell     case TUSB_DMA_EP_MAP:
41914ec7b2cSPeter Maydell         return s->dma_map;
42014ec7b2cSPeter Maydell     case TUSB_EP_OUT_SIZE ... (TUSB_EP_OUT_SIZE + 0x3b):
42114ec7b2cSPeter Maydell         epnum = (offset - TUSB_EP_OUT_SIZE) >> 2;
42214ec7b2cSPeter Maydell         return s->rx_config[epnum];
42314ec7b2cSPeter Maydell     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
42414ec7b2cSPeter Maydell             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
42514ec7b2cSPeter Maydell         return 0x00000000;	/* TODO */
42614ec7b2cSPeter Maydell     case TUSB_WAIT_COUNT:
42714ec7b2cSPeter Maydell         return 0x00;		/* TODO */
42814ec7b2cSPeter Maydell 
42914ec7b2cSPeter Maydell     case TUSB_SCRATCH_PAD:
43014ec7b2cSPeter Maydell         return s->scratch;
43114ec7b2cSPeter Maydell 
43214ec7b2cSPeter Maydell     case TUSB_PROD_TEST_RESET:
43314ec7b2cSPeter Maydell         return s->test_reset;
43414ec7b2cSPeter Maydell 
43514ec7b2cSPeter Maydell     /* DIE IDs */
43614ec7b2cSPeter Maydell     case TUSB_DIDR1_LO:
43714ec7b2cSPeter Maydell         return 0xa9453c59;
43814ec7b2cSPeter Maydell     case TUSB_DIDR1_HI:
43914ec7b2cSPeter Maydell         return 0x54059adf;
44014ec7b2cSPeter Maydell     }
44114ec7b2cSPeter Maydell 
442a89f364aSAlistair Francis     printf("%s: unknown register at %03x\n", __func__, offset);
44314ec7b2cSPeter Maydell     return 0;
44414ec7b2cSPeter Maydell }
44514ec7b2cSPeter Maydell 
tusb_async_writeb(void * opaque,hwaddr addr,uint32_t value)44614ec7b2cSPeter Maydell static void tusb_async_writeb(void *opaque, hwaddr addr,
44714ec7b2cSPeter Maydell                 uint32_t value)
44814ec7b2cSPeter Maydell {
44914ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
45014ec7b2cSPeter Maydell 
45114ec7b2cSPeter Maydell     switch (addr & 0xfff) {
45214ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
45314ec7b2cSPeter Maydell         musb_write[0](s->musb, addr & 0x1ff, value);
45414ec7b2cSPeter Maydell         break;
45514ec7b2cSPeter Maydell 
45614ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
45714ec7b2cSPeter Maydell         musb_write[0](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
45814ec7b2cSPeter Maydell         break;
45914ec7b2cSPeter Maydell 
46014ec7b2cSPeter Maydell     default:
46114ec7b2cSPeter Maydell         printf("%s: unknown register at %03x\n",
462a89f364aSAlistair Francis                         __func__, (int) (addr & 0xfff));
46314ec7b2cSPeter Maydell         return;
46414ec7b2cSPeter Maydell     }
46514ec7b2cSPeter Maydell }
46614ec7b2cSPeter Maydell 
tusb_async_writeh(void * opaque,hwaddr addr,uint32_t value)46714ec7b2cSPeter Maydell static void tusb_async_writeh(void *opaque, hwaddr addr,
46814ec7b2cSPeter Maydell                 uint32_t value)
46914ec7b2cSPeter Maydell {
47014ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
47114ec7b2cSPeter Maydell 
47214ec7b2cSPeter Maydell     switch (addr & 0xfff) {
47314ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
47414ec7b2cSPeter Maydell         musb_write[1](s->musb, addr & 0x1ff, value);
47514ec7b2cSPeter Maydell         break;
47614ec7b2cSPeter Maydell 
47714ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
47814ec7b2cSPeter Maydell         musb_write[1](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
47914ec7b2cSPeter Maydell         break;
48014ec7b2cSPeter Maydell 
48114ec7b2cSPeter Maydell     default:
48214ec7b2cSPeter Maydell         printf("%s: unknown register at %03x\n",
483a89f364aSAlistair Francis                         __func__, (int) (addr & 0xfff));
48414ec7b2cSPeter Maydell         return;
48514ec7b2cSPeter Maydell     }
48614ec7b2cSPeter Maydell }
48714ec7b2cSPeter Maydell 
tusb_async_writew(void * opaque,hwaddr addr,uint32_t value)48814ec7b2cSPeter Maydell static void tusb_async_writew(void *opaque, hwaddr addr,
48914ec7b2cSPeter Maydell                 uint32_t value)
49014ec7b2cSPeter Maydell {
49114ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
49214ec7b2cSPeter Maydell     int offset = addr & 0xfff;
49314ec7b2cSPeter Maydell     int epnum;
49414ec7b2cSPeter Maydell 
49514ec7b2cSPeter Maydell     switch (offset) {
49614ec7b2cSPeter Maydell     case TUSB_VLYNQ_CTRL:
49714ec7b2cSPeter Maydell         break;
49814ec7b2cSPeter Maydell 
49914ec7b2cSPeter Maydell     case TUSB_BASE_OFFSET ... (TUSB_BASE_OFFSET | 0x1ff):
50014ec7b2cSPeter Maydell         musb_write[2](s->musb, offset & 0x1ff, value);
50114ec7b2cSPeter Maydell         break;
50214ec7b2cSPeter Maydell 
50314ec7b2cSPeter Maydell     case TUSB_FIFO_BASE ... (TUSB_FIFO_BASE | 0x1ff):
50414ec7b2cSPeter Maydell         musb_write[2](s->musb, 0x20 + ((addr >> 3) & 0x3c), value);
50514ec7b2cSPeter Maydell         break;
50614ec7b2cSPeter Maydell 
50714ec7b2cSPeter Maydell     case TUSB_DEV_CONF:
50814ec7b2cSPeter Maydell         s->dev_config = value;
50914ec7b2cSPeter Maydell         s->host_mode = (value & TUSB_DEV_CONF_USB_HOST_MODE);
51014ec7b2cSPeter Maydell         if (value & TUSB_DEV_CONF_PROD_TEST_MODE)
511a89f364aSAlistair Francis             hw_error("%s: Product Test mode not allowed\n", __func__);
51214ec7b2cSPeter Maydell         break;
51314ec7b2cSPeter Maydell 
51414ec7b2cSPeter Maydell     case TUSB_PHY_OTG_CTRL_ENABLE:
51514ec7b2cSPeter Maydell     case TUSB_PHY_OTG_CTRL:
51614ec7b2cSPeter Maydell         return;		/* TODO */
51714ec7b2cSPeter Maydell     case TUSB_DEV_OTG_TIMER:
51814ec7b2cSPeter Maydell         s->otg_timer_val = value;
51914ec7b2cSPeter Maydell         if (value & TUSB_DEV_OTG_TIMER_ENABLE)
52014ec7b2cSPeter Maydell             timer_mod(s->otg_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
52114ec7b2cSPeter Maydell                             muldiv64(TUSB_DEV_OTG_TIMER_VAL(value),
52273bcb24dSRutuja Shah                                      NANOSECONDS_PER_SECOND, TUSB_DEVCLOCK));
52314ec7b2cSPeter Maydell         else
52414ec7b2cSPeter Maydell             timer_del(s->otg_timer);
52514ec7b2cSPeter Maydell         break;
52614ec7b2cSPeter Maydell 
52714ec7b2cSPeter Maydell     case TUSB_PRCM_CONF:
52814ec7b2cSPeter Maydell         s->prcm_config = value;
52914ec7b2cSPeter Maydell         break;
53014ec7b2cSPeter Maydell     case TUSB_PRCM_MNGMT:
53114ec7b2cSPeter Maydell         s->prcm_mngmt = value;
53214ec7b2cSPeter Maydell         break;
53314ec7b2cSPeter Maydell     case TUSB_PRCM_WAKEUP_CLEAR:
53414ec7b2cSPeter Maydell         break;
53514ec7b2cSPeter Maydell     case TUSB_PRCM_WAKEUP_MASK:
53614ec7b2cSPeter Maydell         s->wkup_mask = value;
53714ec7b2cSPeter Maydell         break;
53814ec7b2cSPeter Maydell 
53914ec7b2cSPeter Maydell     case TUSB_PULLUP_1_CTRL:
54014ec7b2cSPeter Maydell         s->pullup[0] = value;
54114ec7b2cSPeter Maydell         break;
54214ec7b2cSPeter Maydell     case TUSB_PULLUP_2_CTRL:
54314ec7b2cSPeter Maydell         s->pullup[1] = value;
54414ec7b2cSPeter Maydell         break;
54514ec7b2cSPeter Maydell     case TUSB_INT_CTRL_CONF:
54614ec7b2cSPeter Maydell         s->control_config = value;
54714ec7b2cSPeter Maydell         tusb_intr_update(s);
54814ec7b2cSPeter Maydell         break;
54914ec7b2cSPeter Maydell 
55014ec7b2cSPeter Maydell     case TUSB_USBIP_INT_SET:
55114ec7b2cSPeter Maydell         s->usbip_intr |= value;
55214ec7b2cSPeter Maydell         tusb_usbip_intr_update(s);
55314ec7b2cSPeter Maydell         break;
55414ec7b2cSPeter Maydell     case TUSB_USBIP_INT_CLEAR:
55514ec7b2cSPeter Maydell         s->usbip_intr &= ~value;
55614ec7b2cSPeter Maydell         tusb_usbip_intr_update(s);
55714ec7b2cSPeter Maydell         musb_core_intr_clear(s->musb, ~value);
55814ec7b2cSPeter Maydell         break;
55914ec7b2cSPeter Maydell     case TUSB_USBIP_INT_MASK:
56014ec7b2cSPeter Maydell         s->usbip_mask = value;
56114ec7b2cSPeter Maydell         tusb_usbip_intr_update(s);
56214ec7b2cSPeter Maydell         break;
56314ec7b2cSPeter Maydell 
56414ec7b2cSPeter Maydell     case TUSB_DMA_INT_SET:
56514ec7b2cSPeter Maydell         s->dma_intr |= value;
56614ec7b2cSPeter Maydell         tusb_dma_intr_update(s);
56714ec7b2cSPeter Maydell         break;
56814ec7b2cSPeter Maydell     case TUSB_DMA_INT_CLEAR:
56914ec7b2cSPeter Maydell         s->dma_intr &= ~value;
57014ec7b2cSPeter Maydell         tusb_dma_intr_update(s);
57114ec7b2cSPeter Maydell         break;
57214ec7b2cSPeter Maydell     case TUSB_DMA_INT_MASK:
57314ec7b2cSPeter Maydell         s->dma_mask = value;
57414ec7b2cSPeter Maydell         tusb_dma_intr_update(s);
57514ec7b2cSPeter Maydell         break;
57614ec7b2cSPeter Maydell 
57714ec7b2cSPeter Maydell     case TUSB_GPIO_INT_SET:
57814ec7b2cSPeter Maydell         s->gpio_intr |= value;
57914ec7b2cSPeter Maydell         tusb_gpio_intr_update(s);
58014ec7b2cSPeter Maydell         break;
58114ec7b2cSPeter Maydell     case TUSB_GPIO_INT_CLEAR:
58214ec7b2cSPeter Maydell         s->gpio_intr &= ~value;
58314ec7b2cSPeter Maydell         tusb_gpio_intr_update(s);
58414ec7b2cSPeter Maydell         break;
58514ec7b2cSPeter Maydell     case TUSB_GPIO_INT_MASK:
58614ec7b2cSPeter Maydell         s->gpio_mask = value;
58714ec7b2cSPeter Maydell         tusb_gpio_intr_update(s);
58814ec7b2cSPeter Maydell         break;
58914ec7b2cSPeter Maydell 
59014ec7b2cSPeter Maydell     case TUSB_INT_SRC_SET:
59114ec7b2cSPeter Maydell         s->intr |= value;
59214ec7b2cSPeter Maydell         tusb_intr_update(s);
59314ec7b2cSPeter Maydell         break;
59414ec7b2cSPeter Maydell     case TUSB_INT_SRC_CLEAR:
59514ec7b2cSPeter Maydell         s->intr &= ~value;
59614ec7b2cSPeter Maydell         tusb_intr_update(s);
59714ec7b2cSPeter Maydell         break;
59814ec7b2cSPeter Maydell     case TUSB_INT_MASK:
59914ec7b2cSPeter Maydell         s->mask = value;
60014ec7b2cSPeter Maydell         tusb_intr_update(s);
60114ec7b2cSPeter Maydell         break;
60214ec7b2cSPeter Maydell 
60314ec7b2cSPeter Maydell     case TUSB_GPIO_CONF:
60414ec7b2cSPeter Maydell         s->gpio_config = value;
60514ec7b2cSPeter Maydell         break;
60614ec7b2cSPeter Maydell     case TUSB_DMA_REQ_CONF:
60714ec7b2cSPeter Maydell         s->dma_config = value;
60814ec7b2cSPeter Maydell         break;
60914ec7b2cSPeter Maydell     case TUSB_EP0_CONF:
61014ec7b2cSPeter Maydell         s->ep0_config = value & 0x1ff;
61114ec7b2cSPeter Maydell         musb_set_size(s->musb, 0, TUSB_EP0_CONFIG_XFR_SIZE(value),
61214ec7b2cSPeter Maydell                         value & TUSB_EP0_CONFIG_DIR_TX);
61314ec7b2cSPeter Maydell         break;
61414ec7b2cSPeter Maydell     case TUSB_EP_IN_SIZE ... (TUSB_EP_IN_SIZE + 0x3b):
61514ec7b2cSPeter Maydell         epnum = (offset - TUSB_EP_IN_SIZE) >> 2;
61614ec7b2cSPeter Maydell         s->tx_config[epnum] = value;
61714ec7b2cSPeter Maydell         musb_set_size(s->musb, epnum + 1, TUSB_EP_CONFIG_XFR_SIZE(value), 1);
61814ec7b2cSPeter Maydell         break;
61914ec7b2cSPeter Maydell     case TUSB_DMA_EP_MAP:
62014ec7b2cSPeter Maydell         s->dma_map = value;
62114ec7b2cSPeter Maydell         break;
62214ec7b2cSPeter Maydell     case TUSB_EP_OUT_SIZE ... (TUSB_EP_OUT_SIZE + 0x3b):
62314ec7b2cSPeter Maydell         epnum = (offset - TUSB_EP_OUT_SIZE) >> 2;
62414ec7b2cSPeter Maydell         s->rx_config[epnum] = value;
62514ec7b2cSPeter Maydell         musb_set_size(s->musb, epnum + 1, TUSB_EP_CONFIG_XFR_SIZE(value), 0);
62614ec7b2cSPeter Maydell         break;
62714ec7b2cSPeter Maydell     case TUSB_EP_MAX_PACKET_SIZE_OFFSET ...
62814ec7b2cSPeter Maydell             (TUSB_EP_MAX_PACKET_SIZE_OFFSET + 0x3b):
62914ec7b2cSPeter Maydell         return;		/* TODO */
63014ec7b2cSPeter Maydell     case TUSB_WAIT_COUNT:
63114ec7b2cSPeter Maydell         return;		/* TODO */
63214ec7b2cSPeter Maydell 
63314ec7b2cSPeter Maydell     case TUSB_SCRATCH_PAD:
63414ec7b2cSPeter Maydell         s->scratch = value;
63514ec7b2cSPeter Maydell         break;
63614ec7b2cSPeter Maydell 
63714ec7b2cSPeter Maydell     case TUSB_PROD_TEST_RESET:
63814ec7b2cSPeter Maydell         s->test_reset = value;
63914ec7b2cSPeter Maydell         break;
64014ec7b2cSPeter Maydell 
64114ec7b2cSPeter Maydell     default:
642a89f364aSAlistair Francis         printf("%s: unknown register at %03x\n", __func__, offset);
64314ec7b2cSPeter Maydell         return;
64414ec7b2cSPeter Maydell     }
64514ec7b2cSPeter Maydell }
64614ec7b2cSPeter Maydell 
tusb_async_readfn(void * opaque,hwaddr addr,unsigned size)647a22cadbeSPeter Maydell static uint64_t tusb_async_readfn(void *opaque, hwaddr addr, unsigned size)
648a22cadbeSPeter Maydell {
649a22cadbeSPeter Maydell     switch (size) {
650a22cadbeSPeter Maydell     case 1:
651a22cadbeSPeter Maydell         return tusb_async_readb(opaque, addr);
652a22cadbeSPeter Maydell     case 2:
653a22cadbeSPeter Maydell         return tusb_async_readh(opaque, addr);
654a22cadbeSPeter Maydell     case 4:
655a22cadbeSPeter Maydell         return tusb_async_readw(opaque, addr);
656a22cadbeSPeter Maydell     default:
657a22cadbeSPeter Maydell         g_assert_not_reached();
658a22cadbeSPeter Maydell     }
659a22cadbeSPeter Maydell }
660a22cadbeSPeter Maydell 
tusb_async_writefn(void * opaque,hwaddr addr,uint64_t value,unsigned size)661a22cadbeSPeter Maydell static void tusb_async_writefn(void *opaque, hwaddr addr,
662a22cadbeSPeter Maydell                                uint64_t value, unsigned size)
663a22cadbeSPeter Maydell {
664a22cadbeSPeter Maydell     switch (size) {
665a22cadbeSPeter Maydell     case 1:
666a22cadbeSPeter Maydell         tusb_async_writeb(opaque, addr, value);
667a22cadbeSPeter Maydell         break;
668a22cadbeSPeter Maydell     case 2:
669a22cadbeSPeter Maydell         tusb_async_writeh(opaque, addr, value);
670a22cadbeSPeter Maydell         break;
671a22cadbeSPeter Maydell     case 4:
672a22cadbeSPeter Maydell         tusb_async_writew(opaque, addr, value);
673a22cadbeSPeter Maydell         break;
674a22cadbeSPeter Maydell     default:
675a22cadbeSPeter Maydell         g_assert_not_reached();
676a22cadbeSPeter Maydell     }
677a22cadbeSPeter Maydell }
678a22cadbeSPeter Maydell 
67914ec7b2cSPeter Maydell static const MemoryRegionOps tusb_async_ops = {
680a22cadbeSPeter Maydell     .read = tusb_async_readfn,
681a22cadbeSPeter Maydell     .write = tusb_async_writefn,
682a22cadbeSPeter Maydell     .valid.min_access_size = 1,
683a22cadbeSPeter Maydell     .valid.max_access_size = 4,
68414ec7b2cSPeter Maydell     .endianness = DEVICE_NATIVE_ENDIAN,
68514ec7b2cSPeter Maydell };
68614ec7b2cSPeter Maydell 
tusb_otg_tick(void * opaque)68714ec7b2cSPeter Maydell static void tusb_otg_tick(void *opaque)
68814ec7b2cSPeter Maydell {
68914ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
69014ec7b2cSPeter Maydell 
69114ec7b2cSPeter Maydell     s->otg_timer_val = 0;
69214ec7b2cSPeter Maydell     s->intr |= TUSB_INT_SRC_OTG_TIMEOUT;
69314ec7b2cSPeter Maydell     tusb_intr_update(s);
69414ec7b2cSPeter Maydell }
69514ec7b2cSPeter Maydell 
tusb_power_tick(void * opaque)69614ec7b2cSPeter Maydell static void tusb_power_tick(void *opaque)
69714ec7b2cSPeter Maydell {
69814ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
69914ec7b2cSPeter Maydell 
70014ec7b2cSPeter Maydell     if (s->power) {
70114ec7b2cSPeter Maydell         s->intr_ok = ~0;
70214ec7b2cSPeter Maydell         tusb_intr_update(s);
70314ec7b2cSPeter Maydell     }
70414ec7b2cSPeter Maydell }
70514ec7b2cSPeter Maydell 
tusb_musb_core_intr(void * opaque,int source,int level)70614ec7b2cSPeter Maydell static void tusb_musb_core_intr(void *opaque, int source, int level)
70714ec7b2cSPeter Maydell {
70814ec7b2cSPeter Maydell     TUSBState *s = (TUSBState *) opaque;
70914ec7b2cSPeter Maydell     uint16_t otg_status = s->otg_status;
71014ec7b2cSPeter Maydell 
71114ec7b2cSPeter Maydell     switch (source) {
71214ec7b2cSPeter Maydell     case musb_set_vbus:
71314ec7b2cSPeter Maydell         if (level)
71414ec7b2cSPeter Maydell             otg_status |= TUSB_DEV_OTG_STAT_VBUS_VALID;
71514ec7b2cSPeter Maydell         else
71614ec7b2cSPeter Maydell             otg_status &= ~TUSB_DEV_OTG_STAT_VBUS_VALID;
71714ec7b2cSPeter Maydell 
71814ec7b2cSPeter Maydell         /* XXX: only if TUSB_PHY_OTG_CTRL_OTG_VBUS_DET_EN set?  */
71914ec7b2cSPeter Maydell         /* XXX: only if TUSB_PRCM_MNGMT_OTG_VBUS_DET_EN set?  */
72014ec7b2cSPeter Maydell         if (s->otg_status != otg_status) {
72114ec7b2cSPeter Maydell             s->otg_status = otg_status;
72214ec7b2cSPeter Maydell             s->intr |= TUSB_INT_SRC_VBUS_SENSE_CHNG;
72314ec7b2cSPeter Maydell             tusb_intr_update(s);
72414ec7b2cSPeter Maydell         }
72514ec7b2cSPeter Maydell         break;
72614ec7b2cSPeter Maydell 
72714ec7b2cSPeter Maydell     case musb_set_session:
72814ec7b2cSPeter Maydell         /* XXX: only if TUSB_PHY_OTG_CTRL_OTG_SESS_END_EN set?  */
72914ec7b2cSPeter Maydell         /* XXX: only if TUSB_PRCM_MNGMT_OTG_SESS_END_EN set?  */
73014ec7b2cSPeter Maydell         if (level) {
73114ec7b2cSPeter Maydell             s->otg_status |= TUSB_DEV_OTG_STAT_SESS_VALID;
73214ec7b2cSPeter Maydell             s->otg_status &= ~TUSB_DEV_OTG_STAT_SESS_END;
73314ec7b2cSPeter Maydell         } else {
73414ec7b2cSPeter Maydell             s->otg_status &= ~TUSB_DEV_OTG_STAT_SESS_VALID;
73514ec7b2cSPeter Maydell             s->otg_status |= TUSB_DEV_OTG_STAT_SESS_END;
73614ec7b2cSPeter Maydell         }
73714ec7b2cSPeter Maydell 
73814ec7b2cSPeter Maydell         /* XXX: some IRQ or anything?  */
73914ec7b2cSPeter Maydell         break;
74014ec7b2cSPeter Maydell 
74114ec7b2cSPeter Maydell     case musb_irq_tx:
74214ec7b2cSPeter Maydell     case musb_irq_rx:
74314ec7b2cSPeter Maydell         s->usbip_intr = musb_core_intr_get(s->musb);
74414ec7b2cSPeter Maydell         /* Fall through.  */
74514ec7b2cSPeter Maydell     default:
74614ec7b2cSPeter Maydell         if (level)
74714ec7b2cSPeter Maydell             s->intr |= 1 << source;
74814ec7b2cSPeter Maydell         else
74914ec7b2cSPeter Maydell             s->intr &= ~(1 << source);
75014ec7b2cSPeter Maydell         tusb_intr_update(s);
75114ec7b2cSPeter Maydell         break;
75214ec7b2cSPeter Maydell     }
75314ec7b2cSPeter Maydell }
75414ec7b2cSPeter Maydell 
tusb6010_power(TUSBState * s,int on)75514ec7b2cSPeter Maydell static void tusb6010_power(TUSBState *s, int on)
75614ec7b2cSPeter Maydell {
75714ec7b2cSPeter Maydell     if (!on) {
75814ec7b2cSPeter Maydell         s->power = 0;
75914ec7b2cSPeter Maydell     } else if (!s->power && on) {
76014ec7b2cSPeter Maydell         s->power = 1;
76114ec7b2cSPeter Maydell         /* Pull the interrupt down after TUSB6010 comes up.  */
76214ec7b2cSPeter Maydell         s->intr_ok = 0;
76314ec7b2cSPeter Maydell         tusb_intr_update(s);
76473bcb24dSRutuja Shah         timer_mod(s->pwr_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
76573bcb24dSRutuja Shah                   NANOSECONDS_PER_SECOND / 2);
76614ec7b2cSPeter Maydell     }
76714ec7b2cSPeter Maydell }
76814ec7b2cSPeter Maydell 
tusb6010_irq(void * opaque,int source,int level)76914ec7b2cSPeter Maydell static void tusb6010_irq(void *opaque, int source, int level)
77014ec7b2cSPeter Maydell {
77114ec7b2cSPeter Maydell     if (source) {
77214ec7b2cSPeter Maydell         tusb_musb_core_intr(opaque, source - 1, level);
77314ec7b2cSPeter Maydell     } else {
77414ec7b2cSPeter Maydell         tusb6010_power(opaque, level);
77514ec7b2cSPeter Maydell     }
77614ec7b2cSPeter Maydell }
77714ec7b2cSPeter Maydell 
tusb6010_reset(DeviceState * dev)77814ec7b2cSPeter Maydell static void tusb6010_reset(DeviceState *dev)
77914ec7b2cSPeter Maydell {
780d4db9462SEduardo Habkost     TUSBState *s = TUSB6010(dev);
78114ec7b2cSPeter Maydell     int i;
78214ec7b2cSPeter Maydell 
78314ec7b2cSPeter Maydell     s->test_reset = TUSB_PROD_TEST_RESET_VAL;
78414ec7b2cSPeter Maydell     s->host_mode = 0;
78514ec7b2cSPeter Maydell     s->dev_config = 0;
78614ec7b2cSPeter Maydell     s->otg_status = 0;	/* !TUSB_DEV_OTG_STAT_ID_STATUS means host mode */
78714ec7b2cSPeter Maydell     s->power = 0;
78814ec7b2cSPeter Maydell     s->mask = 0xffffffff;
78914ec7b2cSPeter Maydell     s->intr = 0x00000000;
79014ec7b2cSPeter Maydell     s->otg_timer_val = 0;
79114ec7b2cSPeter Maydell     s->scratch = 0;
79214ec7b2cSPeter Maydell     s->prcm_config = 0;
79314ec7b2cSPeter Maydell     s->prcm_mngmt = 0;
79414ec7b2cSPeter Maydell     s->intr_ok = 0;
79514ec7b2cSPeter Maydell     s->usbip_intr = 0;
79614ec7b2cSPeter Maydell     s->usbip_mask = 0;
79714ec7b2cSPeter Maydell     s->gpio_intr = 0;
79814ec7b2cSPeter Maydell     s->gpio_mask = 0;
79914ec7b2cSPeter Maydell     s->gpio_config = 0;
80014ec7b2cSPeter Maydell     s->dma_intr = 0;
80114ec7b2cSPeter Maydell     s->dma_mask = 0;
80214ec7b2cSPeter Maydell     s->dma_map = 0;
80314ec7b2cSPeter Maydell     s->dma_config = 0;
80414ec7b2cSPeter Maydell     s->ep0_config = 0;
80514ec7b2cSPeter Maydell     s->wkup_mask = 0;
80614ec7b2cSPeter Maydell     s->pullup[0] = s->pullup[1] = 0;
80714ec7b2cSPeter Maydell     s->control_config = 0;
80814ec7b2cSPeter Maydell     for (i = 0; i < 15; i++) {
80914ec7b2cSPeter Maydell         s->rx_config[i] = s->tx_config[i] = 0;
81014ec7b2cSPeter Maydell     }
81114ec7b2cSPeter Maydell     musb_reset(s->musb);
81214ec7b2cSPeter Maydell }
81314ec7b2cSPeter Maydell 
tusb6010_realize(DeviceState * dev,Error ** errp)814f7c5f21eSMao Zhongyi static void tusb6010_realize(DeviceState *dev, Error **errp)
81514ec7b2cSPeter Maydell {
816d4db9462SEduardo Habkost     TUSBState *s = TUSB6010(dev);
817f7c5f21eSMao Zhongyi     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
81814ec7b2cSPeter Maydell 
81914ec7b2cSPeter Maydell     s->otg_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_otg_tick, s);
82014ec7b2cSPeter Maydell     s->pwr_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, tusb_power_tick, s);
82114ec7b2cSPeter Maydell     memory_region_init_io(&s->iomem[1], OBJECT(s), &tusb_async_ops, s,
82214ec7b2cSPeter Maydell                           "tusb-async", UINT32_MAX);
82314ec7b2cSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem[0]);
82414ec7b2cSPeter Maydell     sysbus_init_mmio(sbd, &s->iomem[1]);
82514ec7b2cSPeter Maydell     sysbus_init_irq(sbd, &s->irq);
82614ec7b2cSPeter Maydell     qdev_init_gpio_in(dev, tusb6010_irq, musb_irq_max + 1);
82714ec7b2cSPeter Maydell     s->musb = musb_init(dev, 1);
82814ec7b2cSPeter Maydell }
82914ec7b2cSPeter Maydell 
tusb6010_class_init(ObjectClass * klass,void * data)83014ec7b2cSPeter Maydell static void tusb6010_class_init(ObjectClass *klass, void *data)
83114ec7b2cSPeter Maydell {
83214ec7b2cSPeter Maydell     DeviceClass *dc = DEVICE_CLASS(klass);
83314ec7b2cSPeter Maydell 
834f7c5f21eSMao Zhongyi     dc->realize = tusb6010_realize;
83514ec7b2cSPeter Maydell     dc->reset = tusb6010_reset;
83614ec7b2cSPeter Maydell }
83714ec7b2cSPeter Maydell 
83814ec7b2cSPeter Maydell static const TypeInfo tusb6010_info = {
83914ec7b2cSPeter Maydell     .name          = TYPE_TUSB6010,
84014ec7b2cSPeter Maydell     .parent        = TYPE_SYS_BUS_DEVICE,
84114ec7b2cSPeter Maydell     .instance_size = sizeof(TUSBState),
84214ec7b2cSPeter Maydell     .class_init    = tusb6010_class_init,
84314ec7b2cSPeter Maydell };
84414ec7b2cSPeter Maydell 
tusb6010_register_types(void)84514ec7b2cSPeter Maydell static void tusb6010_register_types(void)
84614ec7b2cSPeter Maydell {
84714ec7b2cSPeter Maydell     type_register_static(&tusb6010_info);
84814ec7b2cSPeter Maydell }
84914ec7b2cSPeter Maydell 
85014ec7b2cSPeter Maydell type_init(tusb6010_register_types)
851