Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-1.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Renesas USB driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Copyright (C) 2011 Renesas Solutions Corp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2019 Renesas Electronics Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include "mod.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *		autonomy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * these functions are used if platform doesn't have external phy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *  -> there is no "notify_hotplug" callback from platform
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *  -> call "notify_hotplug" by itself
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *  -> use own interrupt to connect/disconnect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *  -> it mean module clock is always ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *             ~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	return  VBSTS & usbhs_read(priv, INTSTS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 				    struct usbhs_irq_state *irq_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	usbhsc_schedule_notify_hotplug(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	info->irq_vbus = usbhsm_autonomy_irq_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	info->get_vbus = usbhsm_autonomy_get_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	usbhs_irq_callback_update(priv, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	info->get_vbus = priv->pfunc->get_vbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  *		host / gadget functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * renesas_usbhs host/gadget can register itself by below functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * these functions are called when probe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	info->mod[id]	= mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	mod->priv	= priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	struct usbhs_mod *ret = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	case USBHS_HOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	case USBHS_GADGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		ret = info->mod[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) int usbhs_mod_is_host(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	if (!mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	return info->mod[USBHS_HOST] == mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	return info->curt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int usbhs_mod_change(struct usbhs_priv *priv, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	struct usbhs_mod *mod = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	/* id < 0 mean no current */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	switch (id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	case USBHS_HOST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	case USBHS_GADGET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		mod = info->mod[id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	info->curt = mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static irqreturn_t usbhs_interrupt(int irq, void *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) int usbhs_mod_probe(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	struct device *dev = usbhs_priv_to_dev(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	 * install host/gadget driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	ret = usbhs_mod_host_probe(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	ret = usbhs_mod_gadget_probe(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		goto mod_init_host_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	/* irq settings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 			  priv->irqflags, dev_name(dev), priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		dev_err(dev, "irq request err\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		goto mod_init_gadget_err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) mod_init_gadget_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	usbhs_mod_gadget_remove(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mod_init_host_err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	usbhs_mod_host_remove(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void usbhs_mod_remove(struct usbhs_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	usbhs_mod_host_remove(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	usbhs_mod_gadget_remove(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)  *		status functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	return (int)irq_state->intsts0 & DVSQ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	 * return value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	 * IDLE_SETUP_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	 * READ_DATA_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	 * READ_STATUS_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	 * WRITE_DATA_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	 * WRITE_STATUS_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	 * NODATA_STATUS_STAGE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	 * SEQUENCE_ERROR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	return (int)irq_state->intsts0 & CTSQ_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 				     struct usbhs_irq_state *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	u16 intenb0, intenb1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	/********************  spin lock ********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	usbhs_lock(priv, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	state->intsts0 = usbhs_read(priv, INTSTS0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	intenb0 = usbhs_read(priv, INTENB0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	if (usbhs_mod_is_host(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 		state->intsts1 = usbhs_read(priv, INTSTS1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		intenb1 = usbhs_read(priv, INTENB1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		state->intsts1 = intenb1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	/* mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		state->brdysts = usbhs_read(priv, BRDYSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		state->nrdysts = usbhs_read(priv, NRDYSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		state->bempsts = usbhs_read(priv, BEMPSTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		state->bempsts &= mod->irq_bempsts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		state->brdysts &= mod->irq_brdysts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	usbhs_unlock(priv, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	/********************  spin unlock ******************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	 * Check whether the irq enable registers and the irq status are set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	 * when IRQF_SHARED is set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if (priv->irqflags & IRQF_SHARED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		if (!(intenb0 & state->intsts0) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		    !(intenb1 & state->intsts1) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		    !(state->bempsts) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		    !(state->brdysts))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 			return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  *		interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) #define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) static irqreturn_t usbhs_interrupt(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	struct usbhs_priv *priv = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	struct usbhs_irq_state irq_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 	 * clear interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	 * The hardware is _very_ picky to clear interrupt bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	 * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	 * see
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	 *	"Operation"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	 *	 - "Control Transfer (DCP)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	 *	   - Function :: VALID bit should 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 	if (usbhs_mod_is_host(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	 * The driver should not clear the xxxSTS after the line of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	 * "call irq callback functions" because each "if" statement is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	 * possible to call the callback function for avoiding any side effects.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (irq_state.intsts0 & BRDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (irq_state.intsts0 & BEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	 * call irq callback functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	 * see also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 	 *	usbhs_irq_setting_update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	/* INTSTS0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	if (irq_state.intsts0 & VBINT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 		usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	if (irq_state.intsts0 & DVST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 		usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	if (irq_state.intsts0 & CTRT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 		usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	if (irq_state.intsts0 & BEMP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		usbhs_mod_call(priv, irq_empty, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	if (irq_state.intsts0 & BRDY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 		usbhs_mod_call(priv, irq_ready, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	if (usbhs_mod_is_host(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		/* INTSTS1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 		if (irq_state.intsts1 & ATTCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 			usbhs_mod_call(priv, irq_attch, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		if (irq_state.intsts1 & DTCH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 			usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		if (irq_state.intsts1 & SIGN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			usbhs_mod_call(priv, irq_sign, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		if (irq_state.intsts1 & SACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 			usbhs_mod_call(priv, irq_sack, priv, &irq_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	u16 intenb0 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	u16 intenb1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	 * BEMPENB/BRDYENB are picky.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	 * below method is required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	 *  - clear  INTSTS0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	 *  - update BEMPENB/BRDYENB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	 *  - update INTSTS0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	usbhs_write(priv, INTENB0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	if (usbhs_mod_is_host(priv))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		usbhs_write(priv, INTENB1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	usbhs_write(priv, BEMPENB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	usbhs_write(priv, BRDYENB, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	 * see also
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 	 *	usbhs_interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	if (info->irq_vbus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 		intenb0 |= VBSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	if (mod) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		 * INTSTS0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		if (mod->irq_ctrl_stage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			intenb0 |= CTRE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		if (mod->irq_dev_state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 			intenb0 |= DVSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		if (mod->irq_empty && mod->irq_bempsts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			usbhs_write(priv, BEMPENB, mod->irq_bempsts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 			intenb0 |= BEMPE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		if (mod->irq_ready && mod->irq_brdysts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 			usbhs_write(priv, BRDYENB, mod->irq_brdysts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 			intenb0 |= BRDYE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 		if (usbhs_mod_is_host(priv)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			 * INTSTS1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 			if (mod->irq_attch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 				intenb1 |= ATTCHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			if (mod->irq_dtch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 				intenb1 |= DTCHE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 			if (mod->irq_sign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 				intenb1 |= SIGNE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 			if (mod->irq_sack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 				intenb1 |= SACKE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 	if (intenb0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		usbhs_write(priv, INTENB0, intenb0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	if (usbhs_mod_is_host(priv) && intenb1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) 		usbhs_write(priv, INTENB1, intenb1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }