diff --git a/arch/loongarch/boot/dts/loongson/loongson2k300.dtsi b/arch/loongarch/boot/dts/loongson/loongson2k300.dtsi index e2442719c..1b45d1812 100644 --- a/arch/loongarch/boot/dts/loongson/loongson2k300.dtsi +++ b/arch/loongarch/boot/dts/loongson/loongson2k300.dtsi @@ -707,6 +707,7 @@ cap-mmc-highspeed; no-sd; no-sdio; + non-removable; }; sdio1: sdio@0x16148000 { diff --git a/arch/loongarch/boot/dts/loongson/ls2k300_gongkong_gbkpgk0.dts b/arch/loongarch/boot/dts/loongson/ls2k300_gongkong_gbkpgk0.dts index 4c5bc528f..378291812 100644 --- a/arch/loongarch/boot/dts/loongson/ls2k300_gongkong_gbkpgk0.dts +++ b/arch/loongarch/boot/dts/loongson/ls2k300_gongkong_gbkpgk0.dts @@ -1,5 +1,6 @@ #include "ls2k300_g2k03z2_core.dtsi" #include +#include "loongson_panel_param.dtsi" / { model = "LS2K300-GONGKONG-GBKPGK0"; @@ -48,7 +49,7 @@ /* lcd power on control gpio */ // enable-gpios = <&pioA 3 GPIO_ACTIVE_HIGH>; // power-supply = <&vdd_lcd>; -#if 1 // 4.3' LCD +#if 0 // 4.3' LCD width-mm = <223>; height-mm = <125>; label = "ATK-MD0430R-800x480"; @@ -173,7 +174,7 @@ }; &i2c2 { - i2c-speed = <400000>; + //i2c-speed = <400000>; codec: es8388@11{ compatible = "everest,es8388"; @@ -217,6 +218,11 @@ interrupt-controller; #interrupt-cells = <2>; }; + + rtc_ds1307@68 { + compatible = "dallas,ds1307"; + reg = <0x68>; + }; }; &i2c3 { @@ -237,9 +243,9 @@ gpio-controller; #gpio-cells = <2>; // 2K300 GPIO 支持中断控制 - // GPIO 中断号为 vhwirq-base + pinnum (194 = 128 + 66) + // GPIO 中断号为 vhwirq-base + pinnum (195 = 128 + 67) interrupt-parent = <&gpio>; - interrupts = <194 IRQ_TYPE_EDGE_FALLING>; + interrupts = <195 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; }; @@ -250,9 +256,9 @@ gpio-controller; #gpio-cells = <2>; // 2K300 GPIO 支持中断控制 - // GPIO 中断号为 vhwirq-base + pinnum (195 = 128 + 67) + // GPIO 中断号为 vhwirq-base + pinnum (194 = 128 + 66) interrupt-parent = <&gpio>; - interrupts = <195 IRQ_TYPE_EDGE_FALLING>; + interrupts = <194 IRQ_TYPE_EDGE_FALLING>; interrupt-controller; #interrupt-cells = <2>; }; @@ -301,10 +307,12 @@ &can2 { status = "ok"; + ls,canfd-stb-gpio = <&gpio 60 GPIO_ACTIVE_HIGH>; }; &can3 { status = "ok"; + ls,canfd-stb-gpio = <&gpio 60 GPIO_ACTIVE_HIGH>; }; &adc { diff --git a/arch/loongarch/configs/loongson_2k1000_defconfig b/arch/loongarch/configs/loongson_2k1000_defconfig index 6b68c6521..b6387fdd9 100644 --- a/arch/loongarch/configs/loongson_2k1000_defconfig +++ b/arch/loongarch/configs/loongson_2k1000_defconfig @@ -459,9 +459,18 @@ CONFIG_SND_HDA_CODEC_SIGMATEL=y CONFIG_SND_HDA_CODEC_HDMI=y CONFIG_SND_HDA_CODEC_CONEXANT=y CONFIG_SND_USB_AUDIO=y +CONFIG_SND_USB_UA101=y +CONFIG_SND_USB_CAIAQ=y +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=y +CONFIG_SND_USB_HIFACE=y +CONFIG_SND_BCD2000=y +CONFIG_SND_USB_POD=y +CONFIG_SND_USB_PODHD=y +CONFIG_SND_USB_TONEPORT=y +CONFIG_SND_USB_VARIAX=y CONFIG_SND_SOC=y CONFIG_SND_SOC_LOONGSON=y -CONFIG_SND_SOC_LOONGSON_CJC8988=y CONFIG_SND_LS=y CONFIG_SND_LS_PCM=y CONFIG_HIDRAW=y diff --git a/arch/loongarch/configs/loongson_2k300_defconfig b/arch/loongarch/configs/loongson_2k300_defconfig index 9cecae541..f7b76177f 100644 --- a/arch/loongarch/configs/loongson_2k300_defconfig +++ b/arch/loongarch/configs/loongson_2k300_defconfig @@ -563,6 +563,7 @@ CONFIG_LEDS_GPIO=y CONFIG_LEDS_PWM=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_DS1307=y CONFIG_RTC_DRV_RX8025T=y CONFIG_RTC_DRV_SD3078=y CONFIG_RTC_DRV_LS2X=y diff --git a/drivers/mmc/host/ls2kmci.c b/drivers/mmc/host/ls2kmci.c index 3937233f1..42e62686b 100644 --- a/drivers/mmc/host/ls2kmci.c +++ b/drivers/mmc/host/ls2kmci.c @@ -1101,6 +1101,10 @@ probe_free_host: static void ls2k_mci_shutdown(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); + struct ls2k_mci_host *host = mmc_priv(mmc); + + if (mmc->caps & MMC_CAP_NONREMOVABLE) + return; mmc_remove_host(mmc); } @@ -1110,6 +1114,9 @@ static int ls2k_mci_remove(struct platform_device *pdev) struct mmc_host *mmc = platform_get_drvdata(pdev); struct ls2k_mci_host *host = mmc_priv(mmc); + if (mmc->caps & MMC_CAP_NONREMOVABLE) + return 0; + ls2k_mci_shutdown(pdev); diff --git a/drivers/net/can/ls_canfd/lscanfd_dma.o_shipped b/drivers/net/can/ls_canfd/lscanfd_dma.o_shipped index b08a62d85..f17237627 100644 Binary files a/drivers/net/can/ls_canfd/lscanfd_dma.o_shipped and b/drivers/net/can/ls_canfd/lscanfd_dma.o_shipped differ diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index b0af13074..ec9162df9 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1879,6 +1879,25 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) return up->dma->rx_dma(up); } +static int serial8250_handle_irq_rx_status_error_ignore(unsigned char status) +{ + unsigned char temp; + int i = 0; + + // 0x18 打断中断 有帧错误表示位 接收FIFO为空 + unsigned char error_value_set[] = {(UART_LSR_BI | UART_LSR_FE), UART_LSR_BI}; + unsigned char error_mask_set[] = {(UART_LSR_BI | UART_LSR_FE | UART_LSR_DR), (UART_LSR_BI | UART_LSR_DR)}; + + for (i = 0; i < sizeof(error_value_set); ++i) { + temp = status; + temp &= error_mask_set[i]; + if (temp == error_value_set[i]) { + return 0; + } + } + return -1; +} + /* * This handles the interrupt from one port. */ @@ -1910,8 +1929,10 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) skip_rx = true; if (status & (UART_LSR_DR | UART_LSR_BI) && !skip_rx) { - if (!up->dma || handle_rx_dma(up, iir)) - status = serial8250_rx_chars(up, status); + if (serial8250_handle_irq_rx_status_error_ignore(status)) { + if (!up->dma || handle_rx_dma(up, iir)) + status = serial8250_rx_chars(up, status); + } } serial8250_modem_status(up); if ((!up->dma || up->dma->tx_err) && (status & UART_LSR_THRE) && diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index 26f9fb9f6..7c8c24808 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -225,7 +225,7 @@ static bool usb_generic_driver_match(struct usb_device *udev) int usb_generic_driver_probe(struct usb_device *udev) { - int err, c; + int err, c, try; /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. @@ -235,7 +235,13 @@ int usb_generic_driver_probe(struct usb_device *udev) else { c = usb_choose_configuration(udev); if (c >= 0) { - err = usb_set_configuration(udev, c); + for (try = 0; try < 5; try++) { + err = usb_set_configuration(udev, c); + if (!err) + break; + dev_warn(&udev->dev, "try to set config #%d again\n", c); + udelay(100); + } if (err && err != -ENODEV) { dev_err(&udev->dev, "can't set config #%d, error %d\n", c, err); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 17202b2ee..94b5ef758 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2874,7 +2874,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm) { - int i, status; + int i, status, rst_try; u16 portchange, portstatus; struct usb_port *port_dev = hub->ports[port1 - 1]; int reset_recovery_time; @@ -2903,6 +2903,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, /* Reset the port */ for (i = 0; i < PORT_RESET_TRIES; i++) { +try_rst_again: status = set_port_feature(hub->hdev, port1, (warm ? USB_PORT_FEAT_BH_PORT_RESET : USB_PORT_FEAT_RESET)); @@ -2915,10 +2916,16 @@ static int hub_port_reset(struct usb_hub *hub, int port1, } else { status = hub_port_wait_reset(hub, port1, udev, delay, warm); - if (status && status != -ENOTCONN && status != -ENODEV) + if (status && status != -ENOTCONN && status != -ENODEV) { + if (rst_try < 5) { + rst_try++; + udelay(10); + goto try_rst_again; + } dev_dbg(hub->intfdev, "port_wait_reset: err = %d\n", status); + } } /* Check for disconnect or reset */ diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index e9ac215b9..1b749a535 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -3682,6 +3682,7 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq, hprt0 &= ~HPRT0_RST; dwc2_writel(hsotg, hprt0, HPRT0); hsotg->lx_state = DWC2_L0; /* Now back to On state */ + msleep(50); break; case USB_PORT_FEAT_INDICATOR: diff --git a/sound/soc/loongson/ls-i2s.c b/sound/soc/loongson/ls-i2s.c index 35897055c..118905f00 100644 --- a/sound/soc/loongson/ls-i2s.c +++ b/sound/soc/loongson/ls-i2s.c @@ -24,6 +24,7 @@ #include #include "ls-i2s.h" +#include "ls-pcm.h" #define PCM_STEREO_OUT_NAME "I2S PCM Stereo out" #define PCM_STEREO_IN_NAME "I2S PCM Stereo in" @@ -136,16 +137,45 @@ static int ls_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) static int ls_i2s_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { + struct ls_runtime_data *prtd = substream->runtime->private_data; + uint32_t data; int ret = 0; switch (cmd) { case SNDRV_PCM_TRIGGER_START: - break; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + data = readl((void*)prtd->i2s_ctl_base); + data &= ~(0x1 << 12); + writel(data, (void*)prtd->i2s_ctl_base); + data = readl((void*)prtd->i2s_ctl_base); + if (ls_i2s_is_slave_mode()) + data |= 0x4010 | (1 << 7) | (1 << 12); + else + data |= 0xc010 | (1 << 7) | (1 << 12); + writel(data, (void*)prtd->i2s_ctl_base); + } else { + data = readl((void*)prtd->i2s_ctl_base); + if (ls_i2s_is_slave_mode()) + data |= 0x4010 | (1 << 11) | (1 << 13); + else + data |= 0xc010 | (1 << 11) | (1 << 13); + writel(data, (void*)prtd->i2s_ctl_base); + } + break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + data = readl((void*)prtd->i2s_ctl_base); + data &= ~((1 << 7) | (1 << 12)); + writel(data, (void*)prtd->i2s_ctl_base); + } else { + data = readl((void*)prtd->i2s_ctl_base); + data &= ~((1 << 13) | (1 << 11)); + writel(data, (void*)prtd->i2s_ctl_base); + } break; default: ret = -EINVAL; diff --git a/sound/soc/loongson/ls-pcm-generic.c b/sound/soc/loongson/ls-pcm-generic.c index a961d9407..ecf2bbdaa 100644 --- a/sound/soc/loongson/ls-pcm-generic.c +++ b/sound/soc/loongson/ls-pcm-generic.c @@ -128,37 +128,17 @@ static int ls_pcm_trigger(struct snd_soc_component *component, case SNDRV_PCM_TRIGGER_START: dma_async_issue_pending(chan); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - data = readl((void*)prtd->i2s_ctl_base); - data &= ~(0x1 << 12); - writel(data, (void*)prtd->i2s_ctl_base); - data = readl((void*)prtd->i2s_ctl_base); - if (ls_i2s_is_slave_mode()) - data |= 0x4010 | (1 << 7) | (1 << 12); - else - data |= 0xc010 | (1 << 7) | (1 << 12); - writel(data, (void*)prtd->i2s_ctl_base); - } else { - data = readl((void*)prtd->i2s_ctl_base); - if (ls_i2s_is_slave_mode()) - data |= 0x4010 | (1 << 11) | (1 << 13); - else - data |= 0xc010 | (1 << 11) | (1 << 13); - writel(data, (void*)prtd->i2s_ctl_base); - } break; case SNDRV_PCM_TRIGGER_STOP: dmaengine_terminate_all(chan); break; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - dmaengine_terminate_all(chan); + dmaengine_pause(chan); break; case SNDRV_PCM_TRIGGER_RESUME: - break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - dma_async_issue_pending(chan); - udelay(1000); + dmaengine_resume(chan); break; default: ret = -EINVAL;