^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) }