Skip to content
Permalink
Browse files
MSC313: Add support for weird register placing MSC313: Add back in su…
…pport for fusbh200
  • Loading branch information
fifteenhex committed Jul 19, 2021
1 parent 0bf5e94 commit bcbee03b0eb2ac09fb2f2c431c8214db56afffcb
Show file tree
Hide file tree
Showing 4 changed files with 237 additions and 24 deletions.
@@ -46,6 +46,19 @@
reg = <0xa0000000 0x20000>;
};

&utmi0 {
reg = <0x1f004400 0x80>;
};

&usbc0 {
reg = <0x1f004800 0x20>;
};

&uhc0 {
reg = <0x1f004a00 0x200>;
interrupts-extended = <&intc_irq 14 IRQ_TYPE_LEVEL_HIGH>;
};

&gpio_pm {
interrupt-names = "pm_spi_do", "pm_sd_sdz";
interrupts-extended = <&gpio_pm 0 29 IRQ_TYPE_LEVEL_HIGH>;
@@ -714,6 +714,66 @@
};
};

usbphy0: usbphy@0 {
#phy-cells = <1>;
compatible = "mstar,msc313-usb-phy";
clocks = <&xtal_div2>;
mstar,utmi = <&utmi0>;
mstar,usbc = <&usbc0>;
interrupts-extended = <&intc_irq GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
/*pinctrl-names = "default";
pinctrl-0 = <&usb_pins>;*/
status = "disabled";
};

utmi0: utmi@1f284200 {
compatible = "syscon";
reg = <0x1f284200 0x80>;
};

usbc0: usbc@1f284600 {
compatible = "syscon";
reg = <0x1f284600 0x20>;
};

uhc0: uhc@1f284800 {
compatible = "mstar,msc313-ehci";
reg = <0x1f284800 0x200>;
interrupts-extended = <&intc_irq GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usbphy0 0>;
phy-names = "usb";
mstar,usbc = <&usbc0>;
status = "disabled";
};

utmi1: utmi@1f285200 {
compatible = "syscon";
reg = <0x1f285200 0x80>;
};

usbc1: usbc@1f286200 {
compatible = "syscon";
reg = <0x1f286200 0x20>;
};

usbphy1: usbphy@1 {
#phy-cells = <1>;
compatible = "mstar,msc313-usb-phy";
clocks = <&xtal_div2>;
mstar,utmi = <&utmi1>;
mstar,usbc = <&usbc1>;
};

uhc1: uhc@1f286400 {
compatible = "mstar,msc313-ehci";
reg = <0x1f286400 0x200>;
interrupts-extended = <&intc_irq GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
phys = <&usbphy1 0>;
phy-names = "usb";
mstar,usbc = <&usbc1>;
status = "disabled";
};

imi: sram@a0000000 {
compatible = "mmio-sram";
reg = <0xa0000000 0x10000>;
@@ -35,6 +35,10 @@
#include <linux/iopoll.h>
#include <linux/clk.h>

#include <linux/regmap.h>
#include <linux/usb/mstar_usbc.h>
#include <linux/mfd/syscon.h>

#include <asm/byteorder.h>
#include <asm/irq.h>
#include <asm/unaligned.h>
@@ -735,6 +739,13 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf)
next += temp;
#endif

if(fotg210->fusbh200){
temp = scnprintf(next, size, "bmcsr %04x\n",
fotg210_readl(fotg210, &fotg210->regs->bmcsr));
size -= temp;
next += temp;
}

done:
spin_unlock_irqrestore(&fotg210->lock, flags);

@@ -1528,8 +1539,14 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
fotg210_writel(fotg210, temp | PORT_CSC, status_reg);
break;
case USB_PORT_FEAT_C_OVER_CURRENT:
fotg210_writel(fotg210, temp | OTGISR_OVC,
&fotg210->regs->otgisr);
if(fotg210->fusbh200){
fotg210_writel(fotg210, temp | BMISR_OVC,
&fotg210->regs->bmisr);
}
else {
fotg210_writel(fotg210, temp | OTGISR_OVC,
&fotg210->regs->otgisr);
}
break;
case USB_PORT_FEAT_C_RESET:
/* GetPortStatus clears reset */
@@ -1561,9 +1578,16 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;

temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
if(fotg210->fusbh200){
temp1 = fotg210_readl(fotg210, &fotg210->regs->bmisr);
if (temp1 & BMISR_OVC)
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
}
else {
temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
}

/* whoever resumes must GetPortStatus to complete it!! */
if (temp & PORT_RESUME) {
@@ -1673,9 +1697,17 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
set_bit(wIndex, &fotg210->port_c_suspend);
}

temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_OVERCURRENT;
if(fotg210->fusbh200){
temp1 = fotg210_readl(fotg210, &fotg210->regs->bmisr);
if (temp1 & BMISR_OVC)
status |= USB_PORT_STAT_OVERCURRENT;
}
else {
temp1 = fotg210_readl(fotg210, &fotg210->regs->otgisr);
if (temp1 & OTGISR_OVC)
status |= USB_PORT_STAT_OVERCURRENT;
}

if (temp & PORT_RESET)
status |= USB_PORT_STAT_RESET;
if (test_bit(wIndex, &fotg210->port_c_suspend))
@@ -1684,6 +1716,7 @@ static int fotg210_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
if (status & ~0xffff) /* only if wPortChange is interesting */
dbg_port(fotg210, "GetStatus", wIndex + 1, temp);
put_unaligned_le32(status, buf);

break;
case SetHubFeature:
switch (wValue) {
@@ -3063,6 +3096,10 @@ static int submit_async(struct fotg210_hcd *fotg210, struct urb *urb,
*/
if (likely(qh->qh_state == QH_STATE_IDLE))
qh_link_async(fotg210, qh);

if(fotg210->mstar)
mb();

done:
spin_unlock_irqrestore(&fotg210->lock, flags);
if (unlikely(qh == NULL))
@@ -3092,6 +3129,9 @@ static void single_unlink_async(struct fotg210_hcd *fotg210,
prev->qh_next = qh->qh_next;
if (fotg210->qh_scan_next == qh)
fotg210->qh_scan_next = qh->qh_next.qh;

if(fotg210->mstar)
mb();
}

static void start_iaa_cycle(struct fotg210_hcd *fotg210, bool nested)
@@ -3863,6 +3903,9 @@ static int intr_submit(struct fotg210_hcd *fotg210, struct urb *urb,
/* ... update usbfs periodic stats */
fotg210_to_hcd(fotg210)->self.bandwidth_int_reqs++;

if(fotg210->mstar)
mb();

done:
if (unlikely(status))
usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
@@ -4602,7 +4645,8 @@ static inline int scan_frame_queue(struct fotg210_hcd *fotg210, unsigned frame,
* frame is current.
*/
if (frame == now_frame && live) {
rmb();
if(fotg210->mstar)
mb();
for (uf = 0; uf < 8; uf++) {
if (q.itd->hw_transaction[uf] &
ITD_ACTIVE(fotg210))
@@ -4828,6 +4872,9 @@ static void fotg210_shutdown(struct usb_hcd *hcd)
*/
static void fotg210_work(struct fotg210_hcd *fotg210)
{
if(fotg210->mstar)
mb();

/* another CPU may drop fotg210->lock during a schedule scan while
* it reports urb completions. this flag guards against bogus
* attempts at re-entrant schedule scanning.
@@ -5120,8 +5167,9 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
struct fotg210_hcd *fotg210 = hcd_to_fotg210(hcd);
u32 status, masked_status, pcd_status = 0, cmd;
int bh;
unsigned long flags;

spin_lock(&fotg210->lock);
spin_lock_irqsave(&fotg210->lock, flags);

status = fotg210_readl(fotg210, &fotg210->regs->status);

@@ -5140,7 +5188,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)
/* Shared IRQ? */
if (!masked_status ||
unlikely(fotg210->rh_state == FOTG210_RH_HALTED)) {
spin_unlock(&fotg210->lock);
spin_unlock_irqrestore(&fotg210->lock, flags);
return IRQ_NONE;
}

@@ -5245,7 +5293,7 @@ static irqreturn_t fotg210_irq(struct usb_hcd *hcd)

if (bh)
fotg210_work(fotg210);
spin_unlock(&fotg210->lock);
spin_unlock_irqrestore(&fotg210->lock, flags);
if (pcd_status)
usb_hcd_poll_rh_status(hcd);
return IRQ_HANDLED;
@@ -5547,13 +5595,24 @@ static void fotg210_init(struct fotg210_hcd *fotg210)
{
u32 value;

iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
&fotg210->regs->gmir);
if(fotg210->fusbh200){
printk("need fusbh200 code here %d\n", __LINE__);
regmap_update_bits(fotg210->usbc, MSTAR_USBC_REG_RSTCTRL,
MSTAR_RSTCTRL_REG_SUSPEND | MSTAR_RSTCTRL_UHC_XIU,
MSTAR_RSTCTRL_REG_SUSPEND | MSTAR_RSTCTRL_UHC_XIU);
value = fotg210_readl(fotg210, &fotg210->regs->bmcsr);
fotg210_writel(fotg210, (value & ~BMCSR_VBUS_OFF) | BMCSR_INT_POLARITY,
&fotg210->regs->bmcsr);
}
else {
iowrite32(GMIR_MDEV_INT | GMIR_MOTG_INT | GMIR_INT_POLARITY,
&fotg210->regs->gmir);

value = ioread32(&fotg210->regs->otgcsr);
value &= ~OTGCSR_A_BUS_DROP;
value |= OTGCSR_A_BUS_REQ;
iowrite32(value, &fotg210->regs->otgcsr);
value = ioread32(&fotg210->regs->otgcsr);
value &= ~OTGCSR_A_BUS_DROP;
value |= OTGCSR_A_BUS_REQ;
iowrite32(value, &fotg210->regs->otgcsr);
}
}

/*
@@ -5627,6 +5686,15 @@ static int fotg210_hcd_probe(struct platform_device *pdev)
goto failed_dis_clk;
}

if (dev->of_node && of_device_is_compatible(dev->of_node,
"mstar,msc313-ehci")){
fotg210->mstar = 1;
fotg210->fusbh200 = 1;
fotg210->usbc = syscon_regmap_lookup_by_phandle(dev->of_node, "mstar,usbc");
if (IS_ERR(fotg210->usbc))
goto failed_dis_clk;
}

retval = fotg210_setup(hcd);
if (retval)
goto failed_dis_clk;
@@ -5679,6 +5747,7 @@ static int fotg210_hcd_remove(struct platform_device *pdev)
#ifdef CONFIG_OF
static const struct of_device_id fotg210_of_match[] = {
{ .compatible = "faraday,fotg210" },
{ .compatible = "mstar,msc313-ehci" },
{},
};
MODULE_DEVICE_TABLE(of, fotg210_of_match);

0 comments on commit bcbee03

Please sign in to comment.