diff --git a/Documentation/devicetree/bindings/dma/phytium-ddma.yaml b/Documentation/devicetree/bindings/dma/phytium-ddma.yaml new file mode 100644 index 0000000000000000000000000000000000000000..098dbd867a1994c08c23e1ccf89e19ef01dc18d6 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/phytium-ddma.yaml @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +title: Phytium DDMA Controller bindings + +description: +The Phytium DDMA is a general-purpose direct memory access +controller capable of supporting 8 independent DMA channels. +Each channel can have up to 32 requests.DMA clients connected +to the Phytium DDMA controller must use the format described +in the dma.txt file, using a two-cell specifier for each +channel: + a phandle to the DMA controller plus the following two integer cells: + 1. The channel id + 2. The request line number + +maintainers: + - Huang Jie + +allOf: + - $ref: "dma-controller.yaml#" + +properties: + "#dma-cells": + const: 2 + + compatible: + const: phytium,ddma + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + dma-channels: + minItems: 1 + maxItems: 8 + description: it indicates that the number of channels are used + +required: + - compatible + - reg + - interrupts + - dma-channels + +unevaluatedProperties: false + +examples: + ddma0: ddma@28003000 { + compatible = "phytium,ddma"; + reg = <0x0 0x28003000 0x0 0x1000>; + interrupts = ; + #dma-cells = <2>; + dma-channels = <8>; + }; +... diff --git a/Documentation/devicetree/bindings/gpu/phytium,dc.yaml b/Documentation/devicetree/bindings/gpu/phytium,dc.yaml index 5cea3a283fa04e08d5e60e978ea824b0d2954787..e5336599307e5d58c4178bd67ca920d7218d74f5 100644 --- a/Documentation/devicetree/bindings/gpu/phytium,dc.yaml +++ b/Documentation/devicetree/bindings/gpu/phytium,dc.yaml @@ -1,53 +1,35 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/gpu/phytium,dc.yaml# +$id: http://devicetree.org/schemas/sound/phytium,dc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Phytium Display Engine +title: Phytium Display Controller maintainers: - - Chen Baozi + - Dai Jingtao properties: compatible: - const: phytium,dc + enum: + - phytium,dc reg: - minItems: 1 - maxItems: 2 - description: | - Physical base address of the registers and length of memory mapped region, - and optional physical base address and length of reserved system memory. + items: + - description: DC registers interrupts: maxItems: 1 - pipe_mask: - $ref: '/schemas/types.yaml#/definitions/uint32' - description: specify which pipe is enabled, each bit corresponds to a pipe. - - edp_mask: - $ref: '/schemas/types.yaml#/definitions/uint32' - description: specify which pipe is edp port, each bit corresponds to a pipe (0:dp, 1:edp). - - required: - compatible - reg - interrupts - - pipe_mask - - edp_mask examples: - | - /memreserve/ 0xf4000000 0x4000000; // (optional) - - dc0@32000000 { - compatible = "phytium,dc"; - reg = <0x0 0x32000000 0x0 0x8000>, - <0x0 0xf4000000 0x0 0x4000000>; // (optional) - interrupts = ; - pipe_mask = 0x3; - edp_mask = 0x0; + dc@32000000 { + compatible = "phytium,dc"; + reg = <0x0 0x32000000 0x0 0x8000>; + interrupts = ; }; diff --git a/Documentation/devicetree/bindings/net/cdns,macb.yaml b/Documentation/devicetree/bindings/net/cdns,macb.yaml index c09fcf5041c417978418ffbf5a07972afc833d82..1eaddca0219d366eeeadadd75b4d6d60f896c917 100644 --- a/Documentation/devicetree/bindings/net/cdns,macb.yaml +++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml @@ -63,6 +63,8 @@ properties: - cdns,emac # Generic - cdns,gem # Generic - cdns,macb # Generic + - cdns,phytium-gem-1.0 # GEM version 1.0 on Phytium SoCs + - cdns,phytium-gem-2.0 # GEM version 2.0 on Phytium SoCs reg: minItems: 1 diff --git a/MAINTAINERS b/MAINTAINERS index f04460ea14897fce61ce84423f577c6698cb3a3a..24b491bfa51e7204bbf975e2bd9244dc9a5cfe65 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2526,73 +2526,6 @@ S: Maintained W: http://www.digriz.org.uk/ts78xx/kernel F: arch/arm/mach-orion5x/ts78xx-* -ARM/PHYTIUM SOC SUPPORT -M: Chen Baozi -S: Maintained -W: https://www.phytium.com.cn -F: Documentation/devicetree/bindings/dma/phytium,ddma.yaml -F: Documentation/devicetree/bindings/gpio/phytium,pe220x-edac.yaml -F: Documentation/devicetree/bindings/gpio/phytium,gpio.yaml -F: Documentation/devicetree/bindings/gpio/phytium,sgpio.yaml -F: Documentation/devicetree/bindings/gpu/phytium,dc.yaml -F: Documentation/devicetree/bindings/hwlock/phytium,hwspinlock.yaml -F: Documentation/devicetree/bindings/hwmon/phytium,tacho.yaml -F: Documentation/devicetree/bindings/i2c/phytium,i2c.yaml -F: Documentation/devicetree/bindings/media/phytium,jpeg.yaml -F: Documentation/devicetree/bindings/iio/adc/phytium,adc.yaml -F: Documentation/devicetree/bindings/input/phytium,keypad.yaml -F: Documentation/devicetree/bindings/interrupt-controller/phytium,ixic.yaml -F: Documentation/devicetree/bindings/ipmi/phytium,bt-bmc.yaml -F: Documentation/devicetree/bindings/ipmi/phytium,kcs-bmc.yaml -F: Documentation/devicetree/bindings/mailbox/phytium,mbox.yaml -F: Documentation/devicetree/bindings/mmc/phytium,mci.yaml -F: Documentation/devicetree/bindings/mmc/phytium,sdci.yaml -F: Documentation/devicetree/bindings/mtd/phytium,nfc.yaml -F: Documentation/devicetree/bindings/net/can/phytium,can.yaml -F: Documentation/devicetree/bindings/pci/phytium,pd2008-pcie-ep.yaml -F: Documentation/devicetree/bindings/pwm/phytium,pwm.yaml -F: Documentation/devicetree/bindings/rng/phytium,rng.yaml -F: Documentation/devicetree/bindings/sound/phytium,hda.yaml -F: Documentation/devicetree/bindings/sound/phytium,i2s.yaml -F: Documentation/devicetree/bindings/spi/phytium,qspi-nor.yaml -F: Documentation/devicetree/bindings/spi/phytium,spi.yaml -F: Documentation/devicetree/bindings/usb/phytium,usb2.yaml -F: Documentation/devicetree/bindings/w1/phytium,w1.yaml -F: arch/arm64/boot/dts/phytium/* -F: drivers/char/hw_random/phytium-rng.c -F: drivers/char/ipmi/bt_bmc_phytium.c -F: drivers/char/ipmi/kcs_bmc_phytium.c -F: drivers/dma/phytium/phytium-ddmac.c -F: drivers/edac/phytium_pe220x_edac.c -F: drivers/gpio/gpio-phytium* -F: drivers/gpio/gpio-phytium-sgpio.c -F: drivers/gpu/drm/phytium/* -F: drivers/hwmon/tacho-phytium.c -F: drivers/hwspinlock/phytium_hwspinlock.c -F: drivers/i2c/busses/i2c-phytium-* -F: drivers/iio/adc/phytium-adc.c -F: drivers/input/keyboard/phytium-keypad.c -F: drivers/input/serio/phytium-ps2.c -F: drivers/irqchip/irq-phytium-ixic.c -F: drivers/mailbox/phytium_mailbox.c -F: drivers/media/platform/phytium-jpeg/phytium_jpeg* -F: drivers/mfd/phytium_px210_i2s_lsd.c -F: drivers/mfd/phytium_px210_i2s_mmd.c -F: drivers/mmc/host/phytium-mci* -F: drivers/mmc/host/phytium-sdci.* -F: drivers/mtd/nand/raw/phytium_nand* -F: drivers/net/can/phytium/* -F: drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c -F: drivers/pci/controller/pcie-phytium* -F: drivers/pwm/pwm-phytium.c -F: drivers/spi/spi-phytium* -F: drivers/spi/spi-phytium-qspi.c -F: drivers/tty/serial/phytium-uart.c -F: drivers/usb/phytium/* -F: drivers/w1/masters/phytium_w1.c -F: sound/pci/hda/hda_phytium.* -F: sound/soc/phytium/* - ARM/QUALCOMM CHROMEBOOK SUPPORT R: cros-qcom-dts-watchers@chromium.org F: arch/arm64/boot/dts/qcom/sc7180* @@ -17482,6 +17415,74 @@ F: include/sound/pxa2xx-lib.h F: sound/arm/pxa* F: sound/soc/pxa/ +ARM/PHYTIUM SOC SUPPORT +M: Wang Yinfeng +S: Maintained +W: https://www.phytium.com.cn +F: Documentation/devicetree/bindings/dma/phytium-ddma.yaml +F: Documentation/devicetree/bindings/edac/phytium-pe220x-edac.txt +F: Documentation/devicetree/bindings/gpio/phytium,gpio.yaml +F: Documentation/devicetree/bindings/gpio/phytium,sgpio.yaml +F: Documentation/devicetree/bindings/gpu/phytium,dc.yaml +F: drivers/hwmon/tacho-phytium.c +F: Documentation/devicetree/bindings/hwlock/phytium,hwspinlock.yaml +F: Documentation/devicetree/bindings/hwmon/phytium,tacho.yaml +F: Documentation/devicetree/bindings/i2c/phytium,i2c.yaml +F: Documentation/devicetree/bindings/media/phytium,jpeg.yaml +F: Documentation/devicetree/bindings/iio/adc/phytium,adc.yaml +F: Documentation/devicetree/bindings/input/phytium,keypad.yaml +F: Documentation/devicetree/bindings/interrupt-controller/phytium,ixic.yaml +F: Documentation/devicetree/bindings/ipmi/phytium,bt-bmc.yaml +F: Documentation/devicetree/bindings/ipmi/phytium,kcs-bmc.yaml +F: Documentation/devicetree/bindings/mailbox/phytium,mbox.yaml +F: Documentation/devicetree/bindings/mmc/phytium,mci.yaml +F: Documentation/devicetree/bindings/mmc/phytium,sdci.yaml +F: Documentation/devicetree/bindings/mtd/phytium,nfc.yaml +F: Documentation/devicetree/bindings/net/can/phytium,can.yaml +F: Documentation/devicetree/bindings/pci/phytium,pd2008-pcie-ep.yaml +F: Documentation/devicetree/bindings/pwm/phytium,pwm.yaml +F: Documentation/devicetree/bindings/rng/phytium,rng.yaml +F: Documentation/devicetree/bindings/sound/phytium,hda.yaml +F: Documentation/devicetree/bindings/sound/phytium,i2s.yaml +F: Documentation/devicetree/bindings/spi/phytium,qspi-nor.yaml +F: Documentation/devicetree/bindings/spi/phytium,spi.yaml +F: Documentation/devicetree/bindings/usb/phytium,usb2.yaml +F: Documentation/devicetree/bindings/w1/phytium,w1.yaml +F: arch/arm64/boot/dts/phytium/* +F: drivers/char/hw_random/phytium-rng.c +F: drivers/char/ipmi/bt_bmc_phytium.c +F: drivers/char/ipmi/kcs_bmc_phytium.c +F: drivers/dma/phytium/phytium-ddmac.c +F: drivers/edac/phytium_edac.c +F: drivers/gpio/gpio-phytium* +F: drivers/gpio/gpio-phytium-sgpio.c +F: drivers/gpu/drm/phytium/* +F: drivers/hwspinlock/phytium_hwspinlock.c +F: drivers/i2c/busses/i2c-phytium-* +F: drivers/iio/adc/phytium-adc.c +F: drivers/input/keyboard/phytium-keypad.c +F: drivers/input/serio/phytium-ps2.c +F: drivers/irqchip/irq-phytium-ixic.c +F: drivers/mailbox/phytium_mailbox.c +F: drivers/media/platform/phytium-jpeg/phytium_jpeg* +F: drivers/mfd/phytium_px210_i2s_lsd.c +F: drivers/mfd/phytium_px210_i2s_mmd.c +F: drivers/mmc/host/phytium-mci* +F: drivers/mmc/host/phytium-sdci.* +F: drivers/mtd/nand/raw/phytium_nand* +F: drivers/net/can/phytium/* +F: drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c +F: drivers/pci/controller/pcie-phytium* +F: drivers/pwm/pwm-phytium.c +F: drivers/spi/spi-phytium* +F: drivers/spi/spi-phytium-dma.c +F: drivers/spi/spi-phytium-qspi.c +F: drivers/tty/serial/phytium-uart.c +F: drivers/usb/phytium/* +F: drivers/w1/masters/phytium_w1.c +F: sound/pci/hda/hda_phytium.* +F: sound/soc/phytium/* + QAT DRIVER M: Giovanni Cabiddu L: qat-linux@intel.com diff --git a/arch/arm64/boot/dts/phytium/pe220x.dtsi b/arch/arm64/boot/dts/phytium/pe220x.dtsi index 5bc57fa6dc139a227f130c6292cbfa576ea8c746..ffa404152553ec195282b931058130b571a406c5 100644 --- a/arch/arm64/boot/dts/phytium/pe220x.dtsi +++ b/arch/arm64/boot/dts/phytium/pe220x.dtsi @@ -49,6 +49,10 @@ scmi_sensors0: protocol@15 { #thermal-sensor-cells = <1>; }; }; + optee { + compatible = "linaro,optee-tz"; + method = "smc"; + }; }; thermal_zones: thermal-zones { diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index a789119e6483b50000e6a3a6a1aeff5fb6eabe6d..0fd77961c63e8cf20f18b3f6fa166f09904f7938 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -55,6 +55,7 @@ CONFIG_ARCH_MXC=y CONFIG_ARCH_S32=y CONFIG_ARCH_MA35=y CONFIG_ARCH_NPCM=y +CONFIG_ARCH_PHYTIUM=y CONFIG_ARCH_QCOM=y CONFIG_ARCH_REALTEK=y CONFIG_ARCH_RENESAS=y diff --git a/arch/arm64/configs/phytium_defconfig b/arch/arm64/configs/phytium_defconfig index 270afd2b79114779b61300b002175656ac267cab..015369ac027259efee9d603dc770361d4c7780ce 100644 --- a/arch/arm64/configs/phytium_defconfig +++ b/arch/arm64/configs/phytium_defconfig @@ -1,4 +1,4 @@ -CONFIG_LOCALVERSION="-phytium-embedded" +CONFIG_LOCALVERSION="-phytium-embedded-v3.0" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y @@ -143,6 +143,7 @@ CONFIG_BT_HCIBTUSB=m CONFIG_BT_HCIBTUSB_MTK=y CONFIG_BT_HCIUART=m CONFIG_BT_HCIUART_LL=y +CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIUART_BCM=y CONFIG_BT_HCIUART_QCA=y CONFIG_BT_HCIUART_MRVL=y @@ -779,7 +780,7 @@ CONFIG_DMADEVICES=y CONFIG_BCM_SBA_RAID=m CONFIG_FSL_EDMA=y CONFIG_MV_XOR_V2=y -CONFIG_PHYTIUM_DDMA=m +CONFIG_PHYTIUM_DDMA=y CONFIG_PL330_DMA=y CONFIG_QCOM_HIDMA_MGMT=y CONFIG_QCOM_HIDMA=y diff --git a/arch/arm64/configs/phytium_optee.config b/arch/arm64/configs/phytium_optee.config new file mode 100644 index 0000000000000000000000000000000000000000..07554cf843d34ef484dd90155765a91519476980 --- /dev/null +++ b/arch/arm64/configs/phytium_optee.config @@ -0,0 +1,2 @@ +CONFIG_TEE=y +CONFIG_OPTEE=y diff --git a/drivers/char/ipmi/kcs_bmc_phytium.c b/drivers/char/ipmi/kcs_bmc_phytium.c index e26162e395aa855359683ac4599c3af145398c40..ddbe363bfa596b7a9d16c8abcc2d92d675ccc4f2 100644 --- a/drivers/char/ipmi/kcs_bmc_phytium.c +++ b/drivers/char/ipmi/kcs_bmc_phytium.c @@ -12,9 +12,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -82,13 +85,26 @@ #define LPC_ODR4 0x90 #define LPC_STR4 0x94 +#define OBE_POLL_PERIOD (HZ / 2) struct phytium_kcs_bmc { struct kcs_bmc_device kcs_bmc; struct regmap *map; + + struct { + spinlock_t lock; + bool remove; + struct timer_list timer; + } obe; +}; + +struct phytium_kcs_of_ops { + int (*get_channel)(struct platform_device *pdev); + int (*get_io_address)(struct platform_device *pdev, u32 addr); }; -static inline struct phytium_kcs_bmc *to_phytium_kcs_bmc(struct kcs_bmc_device *kcs_bmc) +static inline struct phytium_kcs_bmc *to_phytium_kcs_bmc + (struct kcs_bmc_device *kcs_bmc) { return container_of(kcs_bmc, struct phytium_kcs_bmc, kcs_bmc); } @@ -114,6 +130,14 @@ static void phytium_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) WARN(rc != 0, "regmap_write() failed: %d\n", rc); } +static void phytium_kcs_updateb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 mask, u8 val) +{ + struct phytium_kcs_bmc *priv = to_phytium_kcs_bmc(kcs_bmc); + int rc; + + rc = regmap_update_bits(priv->map, reg, mask, val); + WARN(rc != 0, "regmap_update_bits() failed: %d\n", rc); +} /* * Background: * we note D for Data, and C for Cmd/Status, default rules are @@ -127,11 +151,11 @@ static void phytium_kcs_outb(struct kcs_bmc_device *kcs_bmc, u32 reg, u8 data) * D / C : CA4h / CA5h * D / C : CB0h / CB1h -use */ -static void phytium_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) +static int phytium_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) { struct phytium_kcs_bmc *priv = to_phytium_kcs_bmc(kcs_bmc); - switch (kcs_bmc->channel) { + switch (priv->kcs_bmc.channel) { case 1: regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_LADR12AS, 0); regmap_write(priv->map, LPC_LADR12H, addr >> 8); @@ -154,6 +178,7 @@ static void phytium_kcs_set_address(struct kcs_bmc_device *kcs_bmc, u16 addr) default: break; } + return 0; } static void phytium_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enable) @@ -163,34 +188,24 @@ static void phytium_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enab switch (kcs_bmc->channel) { case 1: if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, LPC_HICR2_IBFIF1); regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC1E, LPC_HICR0_LPC1E); } else { regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC1E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF1, 0); } break; case 2: if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, LPC_HICR2_IBFIF2); regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC2E, LPC_HICR0_LPC2E); } else { regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC2E, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF2, 0); } break; case 3: if (enable) { - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, LPC_HICR2_IBFIF3); regmap_update_bits(priv->map, LPC_HICR0, LPC_HICR0_LPC3E, LPC_HICR0_LPC3E); regmap_update_bits(priv->map, LPC_HICR4, @@ -200,8 +215,6 @@ static void phytium_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enab LPC_HICR0_LPC3E, 0); regmap_update_bits(priv->map, LPC_HICR4, LPC_HICR4_KCSENBL, 0); - regmap_update_bits(priv->map, LPC_HICR2, - LPC_HICR2_IBFIF3, 0); } break; case 4: @@ -215,13 +228,78 @@ static void phytium_kcs_enable_channel(struct kcs_bmc_device *kcs_bmc, bool enab 0); break; default: - break; + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } +} + +static void phytium_kcs_check_obe(struct timer_list *timer) +{ + struct phytium_kcs_bmc *priv = container_of(timer, struct phytium_kcs_bmc, obe.timer); + unsigned long flags; + u8 str; + + spin_lock_irqsave(&priv->obe.lock, flags); + if (priv->obe.remove) { + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + + str = phytium_kcs_inb(&priv->kcs_bmc, priv->kcs_bmc.ioreg.str); + if (str & KCS_BMC_STR_OBF) { + mod_timer(timer, jiffies + OBE_POLL_PERIOD); + spin_unlock_irqrestore(&priv->obe.lock, flags); + return; + } + spin_unlock_irqrestore(&priv->obe.lock, flags); + + kcs_bmc_handle_event(&priv->kcs_bmc); +} + +static void phytium_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state) +{ + struct phytium_kcs_bmc *priv = to_phytium_kcs_bmc(kcs_bmc); + + if (mask & KCS_BMC_EVENT_TYPE_OBE) { + if (KCS_BMC_EVENT_TYPE_OBE & state) + mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD); + else + del_timer(&priv->obe.timer); + } + + if (mask & KCS_BMC_EVENT_TYPE_IBF) { + const bool enable = !!(state & KCS_BMC_EVENT_TYPE_IBF); + + switch (kcs_bmc->channel) { + case 1: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF1, + enable * LPC_HICR2_IBFIF1); + return; + case 2: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF2, + enable * LPC_HICR2_IBFIF2); + return; + case 3: + regmap_update_bits(priv->map, LPC_HICR2, LPC_HICR2_IBFIF3, + enable * LPC_HICR2_IBFIF3); + return; + case 4: + regmap_update_bits(priv->map, LPC_HICRB, LPC_HICRB_IBFIF4, + enable * LPC_HICRB_IBFIF4); + return; + default: + pr_warn("%s: Unsupported channel: %d", __func__, kcs_bmc->channel); + return; + } } } + static const struct kcs_bmc_device_ops phytium_kcs_ops = { + .irq_mask_update = phytium_kcs_irq_mask_update, .io_inputb = phytium_kcs_inb, .io_outputb = phytium_kcs_outb, + .io_updateb = phytium_kcs_updateb, }; static irqreturn_t phytium_kcs_irq(int irq, void *arg) @@ -231,7 +309,8 @@ static irqreturn_t phytium_kcs_irq(int irq, void *arg) return kcs_bmc_handle_event(kcs_bmc); } -static int phytium_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, struct platform_device *pdev) +static int phytium_kcs_config_irq(struct kcs_bmc_device *kcs_bmc, + struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq; @@ -249,6 +328,7 @@ static const struct kcs_ioreg phytium_kcs_bmc_ioregs[KCS_CHANNEL_MAX] = { { .idr = LPC_IDR2, .odr = LPC_ODR2, .str = LPC_STR2 }, { .idr = LPC_IDR3, .odr = LPC_ODR3, .str = LPC_STR3 }, { .idr = LPC_IDR4, .odr = LPC_ODR4, .str = LPC_STR4 }, + }; static int phytium_kcs_probe(struct platform_device *pdev) @@ -256,6 +336,7 @@ static int phytium_kcs_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct phytium_kcs_bmc *priv; struct kcs_bmc_device *kcs_bmc; + struct device_node *np; u32 chan, addr; int rc; @@ -264,45 +345,57 @@ static int phytium_kcs_probe(struct platform_device *pdev) dev_err(dev, "no valid 'kcs_chan' configured\n"); return -ENODEV; } - rc = of_property_read_u32(dev->of_node, "kcs_addr", &addr); if (rc) { dev_err(dev, "no valid 'kcs_addr' configured\n"); return -ENODEV; } + np = pdev->dev.of_node; + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; kcs_bmc = &priv->kcs_bmc; - kcs_bmc->dev = dev; + kcs_bmc->dev = &pdev->dev; kcs_bmc->channel = chan; kcs_bmc->ioreg = phytium_kcs_bmc_ioregs[chan - 1]; kcs_bmc->ops = &phytium_kcs_ops; - priv->map = syscon_node_to_regmap(dev->parent->of_node); + priv->map = syscon_node_to_regmap(pdev->dev.parent->of_node); if (IS_ERR(priv->map)) { - dev_err(dev, "Couldn't get regmap\n"); + dev_err(&pdev->dev, "Couldn't get regmap\n"); return -ENODEV; } - platform_set_drvdata(pdev, priv); + spin_lock_init(&priv->obe.lock); + priv->obe.remove = false; + timer_setup(&priv->obe.timer, phytium_kcs_check_obe, 0); + + rc = phytium_kcs_set_address(kcs_bmc, addr); + if (rc) + return rc; - phytium_kcs_set_address(kcs_bmc, addr); - phytium_kcs_enable_channel(kcs_bmc, true); rc = phytium_kcs_config_irq(kcs_bmc, pdev); if (rc) return rc; + platform_set_drvdata(pdev, priv); + + phytium_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + + phytium_kcs_enable_channel(kcs_bmc, true); + rc = kcs_bmc_add_device(&priv->kcs_bmc); if (rc) { - dev_err(dev, "Unable to register device\n"); + dev_warn(&pdev->dev, "Failed to register channel %d: %d\n", + kcs_bmc->channel, rc); return rc; } - pr_info("channel=%u addr=0x%x idr=0x%x odr=0x%x str=0x%x\n", - chan, addr, kcs_bmc->ioreg.idr, kcs_bmc->ioreg.odr, kcs_bmc->ioreg.str); + dev_info(&pdev->dev, "Initialised channel %d at 0x%x\n", + kcs_bmc->channel, addr); return 0; } @@ -313,12 +406,18 @@ static int phytium_kcs_remove(struct platform_device *pdev) struct kcs_bmc_device *kcs_bmc = &priv->kcs_bmc; kcs_bmc_remove_device(kcs_bmc); + phytium_kcs_enable_channel(kcs_bmc, false); + phytium_kcs_irq_mask_update(kcs_bmc, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0); + spin_lock_irq(&priv->obe.lock); + priv->obe.remove = true; + spin_unlock_irq(&priv->obe.lock); + del_timer_sync(&priv->obe.timer); return 0; } static const struct of_device_id phytium_kcs_bmc_match[] = { - { .compatible = "phytium,kcs-bmc" }, + { .compatible = "phytium,kcs-bmc", }, { } }; MODULE_DEVICE_TABLE(of, phytium_kcs_bmc_match); diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 603395018b0ed66046783accd4d250624445ee54..e60d7a8ab81acc7aaa306c87eae80d218d45ccfd 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -504,7 +504,7 @@ config PCH_DMA ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. config PHYTIUM_DDMA - tristate "Phytium PE220x DDMA support" + bool "Phytium PE220x DDMA support" depends on (ARCH_PHYTIUM || COMPILE_TEST) select DMA_ENGINE select DMA_VIRTUAL_CHANNELS diff --git a/drivers/dma/phytium/phytium-ddmac.c b/drivers/dma/phytium/phytium-ddmac.c index 015976378cedad9f6be8936c827d1f8e8bdf27eb..768236d9947ab6efdce0cf653d9d233283862abc 100644 --- a/drivers/dma/phytium/phytium-ddmac.c +++ b/drivers/dma/phytium/phytium-ddmac.c @@ -265,7 +265,7 @@ static void phytium_chan_start_xfer(struct phytium_ddma_chan *chan) chan->desc = to_ddma_desc(vdesc); chan->next_sg = 0; chan->current_sg = NULL; - dev_dbg(chan_to_dev(chan), "xfer start\n"); + dev_dbg(chan_to_dev(chan), "channel %d xfer start\n", chan->id); } if (chan->next_sg == chan->desc->num_sgs) @@ -322,7 +322,8 @@ static void phytium_chan_xfer_done(struct phytium_ddma_chan *chan) chan->busy = false; if (chan->next_sg == chan->desc->num_sgs) { - dev_dbg(chan_to_dev(chan), "xfer complete\n"); + dev_dbg(chan_to_dev(chan), + "channel %d xfer complete\n", chan->id); vchan_cookie_complete(&chan->desc->vdesc); chan->desc = NULL; chan->current_sg = NULL; @@ -938,7 +939,18 @@ static struct platform_driver phytium_driver = { }, }; -module_platform_driver(phytium_driver); +static __init int phytium_ddma_init(void) +{ + return platform_driver_register(&phytium_driver); +} + +static void __exit phytium_ddma_exit(void) +{ + platform_driver_unregister(&phytium_driver); +} + +subsys_initcall(phytium_ddma_init); +module_exit(phytium_ddma_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Phytium DDMA Controller platform driver"); diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 025b6ee672bb9249616bcb1e235b77efb94ea685..1cbc7b48a04fe3a07d15ea64494e041e5fd430ca 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -505,6 +505,13 @@ config EDAC_TI help Support for error detection and correction on the TI SoCs. +config EDAC_PHYTIUM + tristate "Phytium Pe220x SoC" + depends on (ARM64) + help + Support for error detection and correction on the + Phytium Pe220x family of SOCs. + config EDAC_QCOM tristate "QCOM EDAC Controller" depends on ARCH_QCOM && QCOM_LLCC @@ -561,11 +568,4 @@ config EDAC_NPCM error detection (in-line ECC in which a section 1/8th of the memory device used to store data is used for ECC storage). -config EDAC_PHYTIUM_PE220X - tristate "Phytium Pe220x SoC" - depends on ARCH_PHYTIUM - help - Support for error detection and correction on the - Phytium Pe220x family of SOCs. - endif # EDAC diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index b45c72a6a5bf475057bae2741dda63d6f005e9ed..f21c95254ab7432c12e1040415071659190c063f 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -80,10 +80,10 @@ obj-$(CONFIG_EDAC_ARMADA_XP) += armada_xp_edac.o obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o obj-$(CONFIG_EDAC_TI) += ti_edac.o +obj-$(CONFIG_EDAC_PHYTIUM) += phytium_edac.o obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o obj-$(CONFIG_EDAC_ASPEED) += aspeed_edac.o obj-$(CONFIG_EDAC_BLUEFIELD) += bluefield_edac.o obj-$(CONFIG_EDAC_DMC520) += dmc520_edac.o obj-$(CONFIG_EDAC_NPCM) += npcm_edac.o obj-$(CONFIG_EDAC_ZYNQMP) += zynqmp_edac.o -obj-$(CONFIG_EDAC_PHYTIUM_PE220X) += phytium_pe220x_edac.o diff --git a/drivers/edac/phytium_pe220x_edac.c b/drivers/edac/phytium_edac.c similarity index 81% rename from drivers/edac/phytium_pe220x_edac.c rename to drivers/edac/phytium_edac.c index 968b9cff18baf77d53ddc8dfabd37b8517ef12ce..af6a729816f4afb8212c85f7ee3db1ae0e78c18d 100644 --- a/drivers/edac/phytium_pe220x_edac.c +++ b/drivers/edac/phytium_edac.c @@ -2,7 +2,7 @@ /* * Phytium Pe220x EDAC (error detection and correction) * - * Copyright (c) 2023-2024 Phytium Technology Co., Ltd. + * Copyright (c) 2019-2023, Phytium Technology Co., Ltd. */ #include @@ -13,36 +13,35 @@ #include #include #include -#include #include "edac_module.h" -#define EDAC_MOD_STR "phytium_edac" +#define EDAC_MOD_STR "phytium_edac" /* register offset */ -#define ERR_STATUS(n) (0x10 + ((n)*64)) -#define ERR_CTLR(n) (0x08 + ((n)*64)) -#define ERR_MISC0(n) (0x20 + ((n)*64)) -#define ERR_INJECT 0x7C -#define ERR_DEVID 0xFC8 -#define ERR_GSR 0xE00 +#define ERR_STATUS(n) (0x10 + ((n) * 64)) +#define ERR_CTLR(n) (0x08 + ((n) * 64)) +#define ERR_MISC0(n) (0x20 + ((n) * 64)) +#define ERR_INJECT 0x7C +#define ERR_DEVID 0xFC8 +#define ERR_GSR 0xE00 -#define CTLR_ED BIT(0) -#define CTLR_UI BIT(2) -#define CTLR_CFI BIT(8) +#define CTLR_ED BIT(0) +#define CTLR_UI BIT(2) +#define CTLR_CFI BIT(8) -#define MISC0_CEC(x) ((u64)(x) << 32) +#define MISC0_CEC(x) ((u64)(x) << 32) -#define ERR_STATUS_CLEAR GENMASK(31, 0) +#define ERR_STATUS_CLEAR GENMASK(31, 0) -#define CORRECTED_ERROR 0 -#define UNCORRECTED_ERROR 1 +#define CORRECTED_ERROR 0 +#define UNCORRECTED_ERROR 1 -#define MAX_ERR_GROUP 3 +#define MAX_ERR_GROUP 3 struct phytium_edac { - struct device *dev; - void __iomem **ras_base; - struct dentry *dfs; + struct device *dev; + void __iomem **ras_base; + struct dentry *dfs; struct edac_device_ctl_info *edac_dev; }; @@ -132,7 +131,7 @@ static const struct ras_error_info *pe220x_ras_error[] = { }; static inline unsigned int get_error_num(const struct phytium_edac *edac, - int err_group) + int err_group) { unsigned int error_num = 0; @@ -157,8 +156,8 @@ static inline void phytium_ras_setup(const struct phytium_edac *edac) } static ssize_t phytium_edac_inject_ctrl_write(struct file *filp, - const char __user *buf, - size_t size, loff_t *ppos) + const char __user *buf, + size_t size, loff_t *ppos) { int ret = 0; int res = 0; @@ -206,13 +205,13 @@ static ssize_t phytium_edac_inject_ctrl_write(struct file *filp, goto out; } - dev_dbg(edac->dev, "inject group%d, error_id: %d\n", error_group, - error_id); + dev_dbg(edac->dev, "inject group%d, error_id: %d\n", + error_group, error_id); - if (pe220x_ras_error[error_group][error_id].error_type == - CORRECTED_ERROR) { + if (pe220x_ras_error[error_group][error_id].error_type + == CORRECTED_ERROR) { writeq(MISC0_CEC(0xFF), - edac->ras_base[error_group] + ERR_MISC0(error_id)); + edac->ras_base[error_group] + ERR_MISC0(error_id)); } writel(error_id, edac->ras_base[error_group] + ERR_INJECT); @@ -223,11 +222,10 @@ static ssize_t phytium_edac_inject_ctrl_write(struct file *filp, static const struct file_operations phytium_edac_debug_inject_fops[] = { { - .open = simple_open, - .write = phytium_edac_inject_ctrl_write, - .llseek = generic_file_llseek, - }, - {} + .open = simple_open, + .write = phytium_edac_inject_ctrl_write, + .llseek = generic_file_llseek, }, + { } }; static void phytium_edac_create_debugfs_nodes(struct phytium_edac *edac) @@ -247,8 +245,9 @@ static int phytium_edac_device_add(struct phytium_edac *edac) int res = 0; edac_dev = edac_device_alloc_ctl_info( - sizeof(struct edac_device_ctl_info), "ras", 1, "soc", 1, 0, - NULL, 0, edac_device_alloc_index()); + sizeof(struct edac_device_ctl_info), + "ras", 1, "soc", 1, 0, NULL, + 0, edac_device_alloc_index()); if (!edac_dev) res = -ENOMEM; @@ -285,7 +284,7 @@ static int phytium_edac_device_remove(struct phytium_edac *edac) } static int get_error_id(struct phytium_edac *edac, int *error_id, - int *error_group) + int *error_group) { unsigned int error_num = 0; u64 error_bit = 0; @@ -319,31 +318,32 @@ static int get_error_id(struct phytium_edac *edac, int *error_id, } static void phytium_edac_error_report(struct phytium_edac *edac, - const int error_id, const int error_group) + const int error_id, const int error_group) { - const struct ras_error_info *err_info = pe220x_ras_error[error_group]; + const struct ras_error_info *err_info = + pe220x_ras_error[error_group]; if (err_info[error_id].error_type == UNCORRECTED_ERROR) { edac_printk(KERN_CRIT, EDAC_MOD_STR, "uncorrected error: %s\n", - err_info[error_id].error_str); + err_info[error_id].error_str); edac_device_handle_ue(edac->edac_dev, 0, 0, - err_info[error_id].error_str); + err_info[error_id].error_str); /* Report the error via the trace interface */ if (IS_ENABLED(CONFIG_RAS)) - trace_non_standard_event( (guid_t *)&NULL_UUID_LE, - (guid_t *)&NULL_UUID_LE, EDAC_MOD_STR, - SEV_RECOVERABLE, err_info[error_id].error_str, - strlen(err_info[error_id].error_str)); + trace_non_standard_event(&NULL_GUID, &NULL_GUID, + EDAC_MOD_STR, SEV_RECOVERABLE, + err_info[error_id].error_str, + strlen(err_info[error_id].error_str)); } else { edac_printk(KERN_CRIT, EDAC_MOD_STR, "corrected error: %s\n", - err_info[error_id].error_str); + err_info[error_id].error_str); edac_device_handle_ce(edac->edac_dev, 0, 0, - err_info[error_id].error_str); + err_info[error_id].error_str); if (IS_ENABLED(CONFIG_RAS)) - trace_non_standard_event( (guid_t *)&NULL_UUID_LE, - (guid_t *)&NULL_UUID_LE, EDAC_MOD_STR, - SEV_CORRECTED, err_info[error_id].error_str, - strlen(err_info[error_id].error_str)); + trace_non_standard_event(&NULL_GUID, &NULL_GUID, + EDAC_MOD_STR, SEV_CORRECTED, + err_info[error_id].error_str, + strlen(err_info[error_id].error_str)); } } @@ -352,13 +352,12 @@ static void phytium_edac_error_report(struct phytium_edac *edac, * interrupt when next correct error event */ static void phytium_edac_clear_error_status(struct phytium_edac *edac, - const int error_id, - const int error_group) + const int error_id, const int error_group) { - writeq(MISC0_CEC(0XFE), - edac->ras_base[error_group] + ERR_MISC0(error_id)); - writeq(GENMASK(31, 0), - edac->ras_base[error_group] + ERR_STATUS(error_id)); + writeq(MISC0_CEC(0XFE), edac->ras_base[error_group] + + ERR_MISC0(error_id)); + writeq(GENMASK(31, 0), edac->ras_base[error_group] + + ERR_STATUS(error_id)); } static irqreturn_t phytium_edac_isr(int irq, void *dev_id) @@ -397,8 +396,8 @@ static int phytium_edac_probe(struct platform_device *pdev) edac->dev = &pdev->dev; platform_set_drvdata(pdev, edac); - edac->ras_base = devm_kcalloc(&pdev->dev, 3, sizeof(*edac->ras_base), - GFP_KERNEL); + edac->ras_base = devm_kcalloc(&pdev->dev, 3, + sizeof(*edac->ras_base), GFP_KERNEL); if (!edac->ras_base) { return -ENOMEM; goto out; @@ -438,10 +437,12 @@ static int phytium_edac_probe(struct platform_device *pdev) ret = -EINVAL; goto out; } - ret = devm_request_irq(&pdev->dev, irq, phytium_edac_isr, - IRQF_SHARED, EDAC_MOD_STR, edac); + ret = devm_request_irq(&pdev->dev, irq, + phytium_edac_isr, IRQF_SHARED, + EDAC_MOD_STR, edac); if (ret) { - dev_err(&pdev->dev, "could not request irq %d\n", irq); + dev_err(&pdev->dev, + "could not request irq %d\n", irq); goto out; } } @@ -469,7 +470,7 @@ static struct platform_driver phytium_edac_driver = { .probe = phytium_edac_probe, .remove = phytium_edac_remove, .driver = { - .name = "phytiumi-pe220x-edac", + .name = "phytium-edac", .of_match_table = phytium_edac_of_match, }, }; @@ -477,4 +478,4 @@ static struct platform_driver phytium_edac_driver = { module_platform_driver(phytium_edac_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Huang Jie "); +MODULE_AUTHOR("Huangjie "); diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 87383c05424bdfd05cfa035f77ab24257f9451e4..6a16007c60ba69fd8264b5c2de93b0bbce372de7 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -51,6 +51,8 @@ static DEFINE_SPINLOCK(protocol_lock); static LIST_HEAD(scmi_list); /* Protection for the entire list */ static DEFINE_MUTEX(scmi_list_mutex); +/* Protection for scmi xfer, prevent transmission timeout */ +static DEFINE_MUTEX(scmi_xfer_mutex); /* Track the unique id for the transfers for debug & profiling purpose */ static atomic_t transfer_last_id; @@ -1030,6 +1032,7 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, struct scmi_xfer *xfer, unsigned int timeout_ms) { int ret = 0; + struct scmi_info *info = handle_to_scmi_info(cinfo->handle); if (xfer->hdr.poll_completion) { /* @@ -1045,7 +1048,10 @@ static int scmi_wait_for_reply(struct device *dev, const struct scmi_desc *desc, spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop)); - if (ktime_after(ktime_get(), stop)) { + + /* Poll again, timeout maybe caused by preempted */ + if (ktime_after(ktime_get(), stop) && + !info->desc->ops->poll_done(cinfo, xfer)) { dev_err(dev, "timed out in resp(caller: %pS) - polling\n", (void *)_RET_IP_); @@ -1211,8 +1217,11 @@ static int do_xfer(const struct scmi_protocol_handle *ph, */ smp_mb(); + /* lock scmi xfer, too many scmi xfers may cause timeout */ + mutex_lock(&scmi_xfer_mutex); ret = info->desc->ops->send_message(cinfo, xfer); if (ret < 0) { + mutex_unlock(&scmi_xfer_mutex); dev_dbg(dev, "Failed to send message %d\n", ret); return ret; } @@ -1228,6 +1237,8 @@ static int do_xfer(const struct scmi_protocol_handle *ph, if (info->desc->ops->mark_txdone) info->desc->ops->mark_txdone(cinfo, ret, xfer); + mutex_unlock(&scmi_xfer_mutex); + trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id, xfer->hdr.protocol_id, xfer->hdr.seq, ret); diff --git a/drivers/gpio/gpio-phytium-platform.c b/drivers/gpio/gpio-phytium-platform.c index 26a6c75352dbb3ed67395228addff5981a098c2d..2f808b89e4ed57a670cc9e9ec6f75fb465193506 100644 --- a/drivers/gpio/gpio-phytium-platform.c +++ b/drivers/gpio/gpio-phytium-platform.c @@ -78,7 +78,9 @@ static int phytium_gpio_probe(struct platform_device *pdev) } if (fwnode_property_read_u32(fwnode, "ngpios", - &gpio->ngpio[idx])) { + &gpio->ngpio[idx]) + && fwnode_property_read_u32(fwnode, "nr-gpios", + &gpio->ngpio[idx])) { dev_info(dev, "failed to get number of gpios for Port%c\n", idx ? 'B' : 'A'); diff --git a/drivers/gpio/gpio-phytium-sgpio.c b/drivers/gpio/gpio-phytium-sgpio.c index 68254af26280b71fe569a71d5a0d31cb90c200c8..c661a86ae2ab319c572fd690ce579bd1bfe7e05b 100644 --- a/drivers/gpio/gpio-phytium-sgpio.c +++ b/drivers/gpio/gpio-phytium-sgpio.c @@ -17,6 +17,7 @@ #include #include #include +#include #define SGPIO_CTL0_REG 0x00 #define SGPIO_CTL0_REG_ENABLE BIT(0) @@ -42,6 +43,7 @@ #define SGPIO_RDATA_REG(x) (SGPIO_RDATA0_REG + (x) * 4) #define DEFAULT_L3_L0 0 +#define DEFAULT_CLK 50000000 #define GPIO_GROUP(x) ((x) >> 6) #define GPIO_OFFSET(x) ((x) & GENMASK(5, 0)) @@ -229,17 +231,26 @@ static int phytium_sgpio_probe(struct platform_device *pdev) return -EINVAL; } - gpio->pclk = devm_clk_get(dev, NULL); - if (IS_ERR(gpio->pclk)) { - dev_err(dev, "Could not get the APB clock property\n"); - return PTR_ERR(gpio->pclk); + if (has_acpi_companion(dev)) { + device_property_read_u32(dev, "pclk_freq", &pclk_freq); + if (!pclk_freq || (pclk_freq != 50000000)) { + dev_err(dev, "Could not get APB clock property from acpi, use default clk!\n"); + pclk_freq = DEFAULT_CLK; + } + + } else { + gpio->pclk = devm_clk_get(dev, NULL); + if (IS_ERR(gpio->pclk)) { + dev_err(dev, "Could not get the APB clock property\n"); + return PTR_ERR(gpio->pclk); + } + rc = clk_prepare_enable(gpio->pclk); + if (rc) { + dev_err(dev, "failed to enable pclk: %d\n", rc); + return rc; + } + pclk_freq = clk_get_rate(gpio->pclk); } - rc = clk_prepare_enable(gpio->pclk); - if (rc) { - dev_err(dev, "failed to enable pclk: %d\n", rc); - return rc; - } - pclk_freq = clk_get_rate(gpio->pclk); /* * From the datasheet: @@ -287,10 +298,17 @@ static const struct of_device_id phytium_sgpio_of_match[] = { }; MODULE_DEVICE_TABLE(of, phytium_sgpio_of_match); +static const struct acpi_device_id phytium_sgpio_acpi_match[] = { + { "PHYT0031", 0}, + {}, +}; +MODULE_DEVICE_TABLE(acpi, phytium_sgpio_acpi_match); + static struct platform_driver phytium_sgpio_driver = { .driver = { .name = KBUILD_MODNAME, .of_match_table = of_match_ptr(phytium_sgpio_of_match), + .acpi_match_table = ACPI_PTR(phytium_sgpio_acpi_match), }, .probe = phytium_sgpio_probe, }; diff --git a/drivers/gpu/drm/phytium/Kconfig b/drivers/gpu/drm/phytium/Kconfig index 46297c1baad71def1e51ba853198e6fbc0a3bd59..e1b91e6a2cababed4aa6775552038674e763e4ab 100644 --- a/drivers/gpu/drm/phytium/Kconfig +++ b/drivers/gpu/drm/phytium/Kconfig @@ -1,9 +1,11 @@ -# SPDX-License-Identifier: GPL-2.0-only - config DRM_PHYTIUM tristate "DRM Support for Phytium Graphics Card" depends on DRM + select FB_IOMEM_HELPERS select DRM_KMS_HELPER + select DRM_DISPLAY_HELPER + select DRM_DISPLAY_DP_HELPER + select DRM_DISPLAY_HDCP_HELPER help Choose this option if you have a phytium graphics card. This driver provides kernel mode setting and buffer management to userspace. diff --git a/drivers/gpu/drm/phytium/Makefile b/drivers/gpu/drm/phytium/Makefile index 1f68cdcd80dac4071c5d3f1578ea7e0d85fbccfd..2dc7ea1118cd4cbf141215a7f377e258ae2593ba 100644 --- a/drivers/gpu/drm/phytium/Makefile +++ b/drivers/gpu/drm/phytium/Makefile @@ -1,5 +1,3 @@ -# SPDX-License-Identifier: GPL-2.0-only - phytium-dc-drm-y := phytium_display_drv.o \ phytium_plane.o \ phytium_crtc.o \ diff --git a/drivers/gpu/drm/phytium/phytium_crtc.c b/drivers/gpu/drm/phytium/phytium_crtc.c index e41c09c0b9c80c96bd6df2f223655b38d0a19172..8adc1c6e10dc839a4fca999ea1b68492cd9a9295 100644 --- a/drivers/gpu/drm/phytium/phytium_crtc.c +++ b/drivers/gpu/drm/phytium/phytium_crtc.c @@ -29,8 +29,8 @@ #define MATH_Add(X, Y) ((float)((X) + (Y))) #define MATH_Multiply(X, Y) ((float)((X) * (Y))) #define MATH_Divide(X, Y) ((float)((X) / (Y))) -#define MATH_DivideFromUInteger(X, Y) (((float)(X) / (float)(Y))) -#define MATH_I2Float(X) ((float)(X)) +#define MATH_DivideFromUInteger(X, Y) ((float)(X) / (float)(Y)) +#define MATH_I2Float(X) ((float)(X)) struct filter_blit_array { uint8_t kernelSize; diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.c b/drivers/gpu/drm/phytium/phytium_display_drv.c index 4c2287b3373cb55625fff7c3cf732db7388a7f9a..f94e0cf4ebea8aa6ee23e17b145abbbd49319c6e 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.c +++ b/drivers/gpu/drm/phytium/phytium_display_drv.c @@ -249,12 +249,12 @@ static int phytium_display_load(struct drm_device *dev, unsigned long flags) goto failed_modeset_init; } - if (priv->support_memory_type & MEMORY_TYPE_VRAM) + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) priv->vram_hw_init(priv); phytium_irq_preinstall(dev); - ret = request_irq(priv->irq, phytium_display_irq_handler, - IRQF_SHARED, dev->driver->name, dev); + ret = request_irq(priv->irq, phytium_display_irq_handler, IRQF_SHARED, + dev->driver->name, dev); if (ret) { DRM_ERROR("install irq failed\n"); goto failed_irq_install; @@ -285,8 +285,25 @@ static void phytium_display_unload(struct drm_device *dev) drm_mode_config_cleanup(dev); } +/* phytium display specific ioctls + * The device specific ioctl range is 0x40 to 0x79. + */ +#define DRM_PHYTIUM_VRAM_TYPE_DEVICE 0x0 +#define DRM_IOCTL_PHYTIUM_VRAM_TYPE_DEVICE DRM_IO(DRM_COMMAND_BASE\ + + DRM_PHYTIUM_VRAM_TYPE_DEVICE) + +static int phytium_ioctl_check_vram_device(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct phytium_display_private *priv = dev->dev_private; + + return ((priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE) ? 1 : 0); +} + static const struct drm_ioctl_desc phytium_ioctls[] = { /* for test, none so far */ + DRM_IOCTL_DEF_DRV(PHYTIUM_VRAM_TYPE_DEVICE, phytium_ioctl_check_vram_device, + DRM_AUTH|DRM_UNLOCKED), }; static const struct file_operations phytium_drm_driver_fops = { @@ -378,7 +395,7 @@ static int phytium_display_pm_resume(struct drm_device *dev) phytium_crtc_resume(dev); phytium_gem_resume(dev); - if (priv->support_memory_type & MEMORY_TYPE_VRAM) + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) priv->vram_hw_init(priv); ret = drm_atomic_helper_resume(dev, dev->mode_config.suspend_state); diff --git a/drivers/gpu/drm/phytium/phytium_display_drv.h b/drivers/gpu/drm/phytium/phytium_display_drv.h index 5aac502420d1a33f4adcbb6a4674cf048545a197..d9d750eee3081afd4721803fe3a00ba500495082 100644 --- a/drivers/gpu/drm/phytium/phytium_display_drv.h +++ b/drivers/gpu/drm/phytium/phytium_display_drv.h @@ -49,9 +49,10 @@ enum phytium_mem_state_type { PHYTIUM_MEM_STATE_TYPE_COUNT, }; -#define MEMORY_TYPE_VRAM 0x1 +#define MEMORY_TYPE_VRAM_WC 0x1 #define MEMORY_TYPE_SYSTEM_CARVEOUT 0x2 #define MEMORY_TYPE_SYSTEM_UNIFIED 0x4 +#define MEMORY_TYPE_VRAM_DEVICE 0x8 #define IS_PLATFORM(priv, p) ((priv)->info.platform_mask & BIT(p)) diff --git a/drivers/gpu/drm/phytium/phytium_dp.c b/drivers/gpu/drm/phytium/phytium_dp.c index 40583f28d829e396566dcb67f95f906875defd86..567dfdc3d5eb6e08162bcfb85de9be3bef88af51 100644 --- a/drivers/gpu/drm/phytium/phytium_dp.c +++ b/drivers/gpu/drm/phytium/phytium_dp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -299,7 +300,7 @@ static int phytium_connector_add_common_modes(struct phytium_dp_device *phytium_ mode->hdisplay = common_mode[i].w; mode->vdisplay = common_mode[i].h; mode->type &= ~DRM_MODE_TYPE_PREFERRED; - strncpy(mode->name, common_mode[i].name, DRM_DISPLAY_MODE_LEN); + strscpy(mode->name, common_mode[i].name, DRM_DISPLAY_MODE_LEN); drm_mode_probed_add(&phytium_dp->connector, mode); ret++; } @@ -1105,7 +1106,6 @@ static int phytium_dp_dpcd_set_link(struct phytium_dp_device *phytium_dp, link_config[1] = lane_count; if (drm_dp_enhanced_frame_cap(phytium_dp->dpcd)) link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; - ret = drm_dp_dpcd_write(&phytium_dp->aux, DP_LINK_BW_SET, link_config, 2); if (ret < 0) { DRM_NOTE("write dpcd DP_LINK_BW_SET fail: ret:%d\n", ret); @@ -1729,6 +1729,7 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s enum drm_connector_status status = connector->status; bool video_enable = false; uint32_t index = 0; + struct edid *edid = NULL; if (phytium_dp->is_edp) status = connector_status_connected; @@ -1762,6 +1763,15 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s mdelay(2); phytium_dp_hw_enable_video(phytium_dp); } + + edid = drm_get_edid(connector, &phytium_dp->aux.ddc); + + if (edid && drm_edid_is_valid(edid)) + phytium_dp->has_audio = drm_detect_monitor_audio(edid); + else + phytium_dp->has_audio = false; + + kfree(edid); } out: diff --git a/drivers/gpu/drm/phytium/phytium_fbdev.c b/drivers/gpu/drm/phytium/phytium_fbdev.c index a3cbe234902ac904785ecb4ec55871f157d01f94..adce24d159b64276d23181b88236694d0b1863f1 100644 --- a/drivers/gpu/drm/phytium/phytium_fbdev.c +++ b/drivers/gpu/drm/phytium/phytium_fbdev.c @@ -16,6 +16,14 @@ #define PHYTIUM_MAX_CONNECTOR 1 #define helper_to_drm_private(x) container_of(x, struct phytium_display_private, fbdev_helper) +static void phytium_fbdev_destroy(struct fb_info *info) +{ + struct drm_fb_helper *helper = info->par; + struct phytium_display_private *priv = helper_to_drm_private(helper); + + phytium_gem_free_object(&priv->fbdev_phytium_gem->base); +} + static int phytium_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) { struct drm_fb_helper *helper = info->par; @@ -26,9 +34,10 @@ static int phytium_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) static const struct fb_ops phytium_fbdev_ops = { .owner = THIS_MODULE, - DRM_FB_HELPER_DEFAULT_OPS, .fb_mmap = phytium_fbdev_mmap, - __FB_DEFAULT_DMAMEM_OPS_DRAW, + .fb_destroy = phytium_fbdev_destroy, + DRM_FB_HELPER_DEFAULT_OPS, + FB_DEFAULT_IOMEM_OPS, }; static int diff --git a/drivers/gpu/drm/phytium/phytium_gem.c b/drivers/gpu/drm/phytium/phytium_gem.c index c4d2c844c14d6c8319c2d1285108ee28a73f6c37..7d962076f7d7f87282f3d4fd640220b310be4c31 100644 --- a/drivers/gpu/drm/phytium/phytium_gem.c +++ b/drivers/gpu/drm/phytium/phytium_gem.c @@ -87,7 +87,8 @@ phytium_gem_prime_get_sg_table(struct drm_gem_object *obj) return ERR_PTR(-ENOMEM); } - if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) || + if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) || + (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) || (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT)) { ret = sg_alloc_table(sgt, 1, GFP_KERNEL); if (ret) { @@ -172,12 +173,6 @@ void phytium_gem_prime_vunmap(struct drm_gem_object *obj, struct iosys_map *map) int phytium_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { - int ret = 0; - - ret = drm_gem_mmap_obj(obj, obj->size, vma); - if (ret < 0) - return ret; - return phytium_gem_mmap_obj(obj, vma); } @@ -282,7 +277,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev) int ret = 0; list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; phytium_gem_obj->vaddr_save = vmalloc(phytium_gem_obj->size); @@ -301,7 +297,8 @@ int phytium_gem_suspend(struct drm_device *drm_dev) return 0; malloc_failed: list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; if (phytium_gem_obj->vaddr_save) { @@ -318,7 +315,8 @@ void phytium_gem_resume(struct drm_device *drm_dev) struct phytium_gem_object *phytium_gem_obj = NULL; list_for_each_entry(phytium_gem_obj, &priv->gem_list_head, list) { - if (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM) + if ((phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_WC) && + (phytium_gem_obj->memory_type != MEMORY_TYPE_VRAM_DEVICE)) continue; memcpy(phytium_gem_obj->vaddr, phytium_gem_obj->vaddr_save, phytium_gem_obj->size); @@ -337,7 +335,8 @@ void phytium_gem_free_object(struct drm_gem_object *obj) DRM_DEBUG_KMS("free phytium_gem_obj iova:0x%pa size:0x%lx\n", &phytium_gem_obj->iova, phytium_gem_obj->size); if (phytium_gem_obj->vaddr) { - if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) { + if ((phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) || + (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE)) { phytium_memory_pool_free(priv, phytium_gem_obj->vaddr, size); priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] -= size; } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) { @@ -370,10 +369,14 @@ int phytium_gem_mmap_obj(struct drm_gem_object *obj, struct vm_area_struct *vma) vma->vm_pgoff = 0; vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); - if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM) { + if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_WC) { vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); ret = remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot); + } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_VRAM_DEVICE) { + vma->vm_page_prot = pgprot_device(vma->vm_page_prot); + ret = remap_pfn_range(vma, vma->vm_start, pfn, + vma->vm_end - vma->vm_start, vma->vm_page_prot); } else if (phytium_gem_obj->memory_type == MEMORY_TYPE_SYSTEM_CARVEOUT) { ret = remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot); @@ -392,10 +395,7 @@ int phytium_gem_mmap(struct file *filp, struct vm_area_struct *vma) int ret = 0; ret = drm_gem_mmap(filp, vma); - if (ret < 0) - return ret; - - return phytium_gem_mmap_obj(vma->vm_private_data, vma); + return ret; } static const struct vm_operations_struct phytium_vm_ops = { @@ -409,6 +409,7 @@ static const struct drm_gem_object_funcs phytium_drm_gem_object_funcs = { .vmap = phytium_gem_prime_vmap, .vunmap = phytium_gem_prime_vunmap, .vm_ops = &phytium_vm_ops, + .mmap = phytium_gem_prime_mmap, }; struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, unsigned long size) @@ -431,7 +432,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns goto failed_object_init; } - if (priv->support_memory_type & MEMORY_TYPE_VRAM) { + if (priv->support_memory_type & (MEMORY_TYPE_VRAM_WC | MEMORY_TYPE_VRAM_DEVICE)) { ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr, &phytium_gem_obj->phys_addr, size); if (ret) { @@ -439,7 +440,7 @@ struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, uns goto failed_dma_alloc; } phytium_gem_obj->iova = phytium_gem_obj->phys_addr; - phytium_gem_obj->memory_type = MEMORY_TYPE_VRAM; + phytium_gem_obj->memory_type = priv->support_memory_type; priv->mem_state[PHYTIUM_MEM_VRAM_ALLOC] += size; } else if (priv->support_memory_type & MEMORY_TYPE_SYSTEM_CARVEOUT) { ret = phytium_memory_pool_alloc(priv, &phytium_gem_obj->vaddr, diff --git a/drivers/gpu/drm/phytium/phytium_gem.h b/drivers/gpu/drm/phytium/phytium_gem.h index eb6f8987a2b855c99e90e6f7415a9ab03f3da26a..693d5408fee0dbf7db7b3fbde88c8fb03e43d650 100644 --- a/drivers/gpu/drm/phytium/phytium_gem.h +++ b/drivers/gpu/drm/phytium/phytium_gem.h @@ -37,7 +37,6 @@ int phytium_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, unsi struct phytium_gem_object *phytium_gem_create_object(struct drm_device *dev, unsigned long size); int phytium_gem_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -int phytium_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma); int phytium_gem_suspend(struct drm_device *drm_dev); void phytium_gem_resume(struct drm_device *drm_dev); #endif /* __PHYTIUM_GEM_H__ */ diff --git a/drivers/gpu/drm/phytium/phytium_pci.c b/drivers/gpu/drm/phytium/phytium_pci.c index 114c6306fd1d40e671808fc68eeb9b59afdc6b1e..e046c299da735486e01c5123fffa72891c7414b7 100644 --- a/drivers/gpu/drm/phytium/phytium_pci.c +++ b/drivers/gpu/drm/phytium/phytium_pci.c @@ -6,6 +6,7 @@ #include #include +#include #include #include "phytium_display_drv.h" #include "phytium_pci.h" @@ -27,6 +28,24 @@ void phytium_pci_vram_hw_init(struct phytium_display_private *priv) pci_priv->dc_hw_vram_init(priv, priv->pool_phys_addr, priv->pool_size); } +static bool phytium_pci_host_is_5c01(struct pci_bus *bus) +{ + struct pci_bus *child = bus; + struct pci_dev *root = NULL; + + while (child) { + if (child->parent->parent) + child = child->parent; + else + break; + } + + root = child->self; + if ((root->vendor == 0x1db7) && (root->device == 0x5c01)) + return true; + return false; +} + int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private *priv) { int ret = 0; @@ -34,8 +53,15 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private * priv->pool_phys_addr = pci_resource_start(pdev, 2); priv->pool_size = pci_resource_len(pdev, 2); if ((priv->pool_phys_addr != 0) && (priv->pool_size != 0)) { - priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr, - priv->pool_size); + if ((pdev->device == 0xdc3e) && phytium_pci_host_is_5c01(pdev->bus)) { + priv->pool_virt_addr = devm_ioremap(&pdev->dev, priv->pool_phys_addr, + priv->pool_size); + priv->support_memory_type = MEMORY_TYPE_VRAM_DEVICE; + } else { + priv->pool_virt_addr = devm_ioremap_wc(&pdev->dev, priv->pool_phys_addr, + priv->pool_size); + priv->support_memory_type = MEMORY_TYPE_VRAM_WC; + } if (priv->pool_virt_addr == NULL) { DRM_ERROR("pci vram ioremap fail, addr:0x%llx, size:0x%llx\n", priv->pool_phys_addr, priv->pool_size); @@ -47,7 +73,6 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private * goto failed_init_memory_pool; priv->mem_state[PHYTIUM_MEM_VRAM_TOTAL] = priv->pool_size; - priv->support_memory_type = MEMORY_TYPE_VRAM; priv->vram_hw_init = phytium_pci_vram_hw_init; } else { DRM_DEBUG_KMS("not support vram\n"); @@ -67,7 +92,8 @@ int phytium_pci_vram_init(struct pci_dev *pdev, struct phytium_display_private * void phytium_pci_vram_fini(struct pci_dev *pdev, struct phytium_display_private *priv) { - if (priv->support_memory_type == MEMORY_TYPE_VRAM) { + if ((priv->support_memory_type == MEMORY_TYPE_VRAM_WC) || + (priv->support_memory_type == MEMORY_TYPE_VRAM_DEVICE)) { phytium_memory_pool_fini(&pdev->dev, priv); devm_iounmap(&pdev->dev, priv->pool_virt_addr); } @@ -213,12 +239,30 @@ phytium_pci_private_fini(struct pci_dev *pdev, struct phytium_display_private *p devm_kfree(&pdev->dev, pci_priv); } +static int phytium_remove_conflicting_framebuffers(struct pci_dev *pdev) +{ + resource_size_t base, size; + + base = pci_resource_start(pdev, 2); + size = pci_resource_len(pdev, 2); + + return drm_aperture_remove_conflicting_framebuffers(base, size, + &phytium_display_drm_driver); + +} + static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct phytium_display_private *priv = NULL; struct drm_device *dev = NULL; int ret = 0; + ret = phytium_remove_conflicting_framebuffers(pdev); + if (ret) { + DRM_ERROR("failed to remove conflicting phytium framebuffers\n"); + return ret; + } + dev = drm_dev_alloc(&phytium_display_drm_driver, &pdev->dev); if (IS_ERR(dev)) { DRM_ERROR("failed to allocate drm_device\n"); diff --git a/drivers/gpu/drm/phytium/phytium_plane.c b/drivers/gpu/drm/phytium/phytium_plane.c index 315ad6b4b8137b1dad7b698f68867f342dc32684..bc28ad8d45c032dabf3ba2d811dbd0496db2e094 100644 --- a/drivers/gpu/drm/phytium/phytium_plane.c +++ b/drivers/gpu/drm/phytium/phytium_plane.c @@ -108,6 +108,35 @@ phytium_plane_atomic_destroy_state(struct drm_plane *plane, struct drm_plane_sta kfree(phytium_state); } +static bool phytium_plane_format_mod_supported(struct drm_plane *plane, + uint32_t format, uint64_t modifier) +{ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + if (modifier == DRM_FORMAT_MOD_PHYTIUM_TILE_MODE3_FBCDC) { + switch (format) { + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_RGBA8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + return true; + default: + return false; + } + } + + return false; +} + const struct drm_plane_funcs phytium_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, .disable_plane = drm_atomic_helper_disable_plane, @@ -117,6 +146,7 @@ const struct drm_plane_funcs phytium_plane_funcs = { .atomic_set_property = phytium_plane_atomic_set_property, .atomic_duplicate_state = phytium_plane_atomic_duplicate_state, .atomic_destroy_state = phytium_plane_atomic_destroy_state, + .format_mod_supported = phytium_plane_format_mod_supported, }; static int diff --git a/drivers/gpu/drm/phytium/phytium_reg.h b/drivers/gpu/drm/phytium/phytium_reg.h index 4dca6c02312792035be8bc57d1f68ebd0420011d..f5d4a6945c35b6313156955c56ef4367f86da5dc 100644 --- a/drivers/gpu/drm/phytium/phytium_reg.h +++ b/drivers/gpu/drm/phytium/phytium_reg.h @@ -268,7 +268,7 @@ #define PHYTIUM_DP_INTERRUPT_MASK 0x0144 #define HPD_IRQ_MASK (1<<1) #define HPD_EVENT_MASK (1<<0) - #define HPD_OTHER_MASK 0x3c + #define HPD_OTHER_MASK 0x7c #define PHYTIUM_DP_AUX_REPLY_DATA_COUNT 0x0148 #define PHYTIUM_DP_AUX_STATUS 0x014C #define REPLY_RECEIVED 0x1 diff --git a/drivers/hwmon/tacho-phytium.c b/drivers/hwmon/tacho-phytium.c index c89251f3595a3a3146832e735d6ef06ebd932d46..00a773014f9c205566d932981ce081e5ced8a37d 100644 --- a/drivers/hwmon/tacho-phytium.c +++ b/drivers/hwmon/tacho-phytium.c @@ -18,6 +18,7 @@ #include #include #include + #include #define TIMER_CTRL_REG 0x00 @@ -235,24 +236,41 @@ static const struct attribute_group *capture_groups[] = { static int phytium_tacho_get_work_mode(struct phytium_tacho *tacho) { - struct fwnode_handle *nc = dev_fwnode(tacho->dev); + struct device_node *nc = tacho->dev->of_node; + struct fwnode_handle *fwn = tacho->dev->fwnode; - if (fwnode_property_read_bool(nc, "tacho")) + if (of_property_read_bool(nc, "tacho")) + return tacho_mode; + else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( + fwn, "tacho")) return tacho_mode; - if (fwnode_property_read_bool(nc, "capture")) + if (of_property_read_bool(nc, "capture")) + return capture_mode; + else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( + fwn, "capture")) return capture_mode; return tacho_mode; } static int phytium_tacho_get_edge_mode(struct phytium_tacho *tacho) { - struct fwnode_handle *nc = dev_fwnode(tacho->dev); + struct device_node *nc = tacho->dev->of_node; + struct fwnode_handle *fwn = tacho->dev->fwnode; - if (fwnode_property_read_bool(nc, "up")) + if (of_property_read_bool(nc, "up")) return rising_edge; - if (fwnode_property_read_bool(nc, "down")) + else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( + fwn, "up")) + return rising_edge; + if (of_property_read_bool(nc, "down")) + return falling_edge; + else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( + fwn, "down")) return falling_edge; - if (fwnode_property_read_bool(nc, "double")) + if (of_property_read_bool(nc, "double")) + return double_edge; + else if (has_acpi_companion(tacho->dev) && fwnode_property_read_bool( + fwn, "double")) return double_edge; return rising_edge; } @@ -260,12 +278,16 @@ static int phytium_tacho_get_edge_mode(struct phytium_tacho *tacho) static int phytium_tacho_get_debounce(struct phytium_tacho *tacho) { u32 value; - struct fwnode_handle *nc = dev_fwnode(tacho->dev); + struct device_node *nc = tacho->dev->of_node; + struct fwnode_handle *fwn = tacho->dev->fwnode; - if (!fwnode_property_read_u32(nc, "debounce-level", &value)) + if (!of_property_read_u32(nc, "debounce-level", &value)) return value; - else - return 0; + if (has_acpi_companion(tacho->dev)) { + if (!fwnode_property_read_u32(fwn, "debounce-level", &value)) + return value; + } + return 0; } static void phytium_tacho_get_of_data(struct phytium_tacho *tacho) @@ -297,19 +319,24 @@ static int phytium_tacho_probe(struct platform_device *pdev) dev_err(&pdev->dev, "region map failed\n"); return PTR_ERR(tacho->base); } - if (dev->of_node) { + + if (!has_acpi_companion(tacho->dev)) { tacho->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tacho->clk)) return PTR_ERR(tacho->clk); ret = clk_prepare_enable(tacho->clk); if (ret) return ret; - tacho->freq = clk_get_rate(tacho->clk); - } else if (has_acpi_companion(dev)){ - if(fwnode_property_read_u32(dev_fwnode(dev),"clock-frequency", (u32 *)&(tacho->freq) ) <0) - tacho->freq = 50000000; - } + } else { + u32 fre; + + ret = clk_prepare_enable(tacho->clk); + if (ret) + return ret; + fwnode_property_read_u32(tacho->dev->fwnode, "clock-frequency", &fre); + tacho->freq = fre; + } tacho->irq = platform_get_irq(pdev, 0); if (tacho->irq < 0) { @@ -360,27 +387,25 @@ static int phytium_tacho_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(phytium_tacho_pm, phytium_tacho_suspend, phytium_tacho_resume); -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_tacho_acpi_ids[] = { - { "PHYT0033", 0 }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(acpi, phytium_tacho_acpi_ids); -#endif - static const struct of_device_id tacho_of_match[] = { { .compatible = "phytium,tacho", }, {}, }; MODULE_DEVICE_TABLE(of, tacho_of_match); +static const struct acpi_device_id tacho_acpi_match[] = { + { "PHYT0033", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, tacho_acpi_match); + static struct platform_driver phytium_tacho_driver = { .probe = phytium_tacho_probe, .driver = { .name = "phytium_tacho", .pm = &phytium_tacho_pm, .of_match_table = of_match_ptr(tacho_of_match), - .acpi_match_table = ACPI_PTR(phytium_tacho_acpi_ids), + .acpi_match_table = ACPI_PTR(tacho_acpi_match), }, }; diff --git a/drivers/hwspinlock/phytium_hwspinlock.c b/drivers/hwspinlock/phytium_hwspinlock.c index 7958531b0cb64d7779c7828e29d47b9d6c62d0de..579e6bacc352f9ac1daf22d468adb094352541c9 100644 --- a/drivers/hwspinlock/phytium_hwspinlock.c +++ b/drivers/hwspinlock/phytium_hwspinlock.c @@ -148,27 +148,27 @@ static int phytium_hwspinlock_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_hwspinlock_acpi_ids[] = { - { "PHYT0027", 0 }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(acpi, phytium_hwspinlock_acpi_ids); -#endif - static const struct of_device_id phytium_hwspinlock_of_match[] = { { .compatible = "phytium,hwspinlock", }, { /* end */ }, }; MODULE_DEVICE_TABLE(of, phytium_hwspinlock_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id phytium_hwspinlock_acpi_match[] = { + { "PHYT0053", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, phytium_hwspinlock_acpi_match); +#endif + static struct platform_driver phytium_hwspinlock_driver = { .probe = phytium_hwspinlock_probe, .remove = phytium_hwspinlock_remove, .driver = { .name = "phytium_hwspinlock", .of_match_table = of_match_ptr(phytium_hwspinlock_of_match), - .acpi_match_table = ACPI_PTR(phytium_hwspinlock_acpi_ids), + .acpi_match_table = ACPI_PTR(phytium_hwspinlock_acpi_match), }, }; diff --git a/drivers/i2c/busses/i2c-phytium-pci.c b/drivers/i2c/busses/i2c-phytium-pci.c index 0818b9db1031fa99f727010fc6bedb331fc4e973..c63abddd09b13f5220a4946c74d3de4943dfdb98 100644 --- a/drivers/i2c/busses/i2c-phytium-pci.c +++ b/drivers/i2c/busses/i2c-phytium-pci.c @@ -29,6 +29,10 @@ #define DRV_NAME "i2c-phytium-pci" +int i2c_msi_enable; +module_param(i2c_msi_enable, int, 0644); +MODULE_PARM_DESC(i2c_msi_enable, "Enable I2C msi interrupt (0-disabled; 1-enabled; default-0)"); + enum phytium_pci_ctl_id_t { octopus_i2c, }; @@ -162,6 +166,16 @@ static int i2c_phytium_pci_probe(struct pci_dev *pdev, goto out; } + if (i2c_msi_enable) { + pci_set_master(pdev); + + ret = pci_enable_msi(pdev); + if (ret) { + dev_dbg(&pdev->dev, "Error enabling MSI. ret = %d\n", ret); + goto out; + } + } + dev->controller = controller; dev->get_clk_rate_khz = i2c_phytium_get_clk_rate_khz; dev->base = pcim_iomap_table(pdev)[0]; diff --git a/drivers/input/keyboard/phytium-keypad.c b/drivers/input/keyboard/phytium-keypad.c index c65601bddc5f5ed9d019f4a6b097a8e513abf413..8237c0051e9e12680e471a0d04ff1a325afad4c0 100644 --- a/drivers/input/keyboard/phytium-keypad.c +++ b/drivers/input/keyboard/phytium-keypad.c @@ -394,14 +394,6 @@ static int phytium_keypad_open(struct input_dev *dev) return -EIO; } -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_keypad_acpi_ids[] = { - { "PHYT0028", 0 }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(acpi, phytium_keypad_acpi_ids); -#endif - #ifdef CONFIG_OF static const struct of_device_id phytium_keypad_of_match[] = { { .compatible = "phytium,keypad", }, @@ -410,6 +402,14 @@ static const struct of_device_id phytium_keypad_of_match[] = { MODULE_DEVICE_TABLE(of, phytium_keypad_of_match); #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id phytium_keypad_acpi_match[] = { + { "PHYT0028", 0}, + {} +}; +MODULE_DEVICE_TABLE(acpi, phytium_keypad_acpi_match); +#endif + static int phytium_keypad_probe(struct platform_device *pdev) { const struct matrix_keymap_data *keymap_data = dev_get_platdata(&pdev->dev); @@ -570,7 +570,7 @@ static struct platform_driver phytium_keypad_driver = { .name = "phytium-keypad", .pm = &phytium_keypad_pm_ops, .of_match_table = of_match_ptr(phytium_keypad_of_match), - .acpi_match_table = ACPI_PTR(phytium_keypad_acpi_ids), + .acpi_match_table = ACPI_PTR(phytium_keypad_acpi_match), }, .probe = phytium_keypad_probe, .remove = phytium_keypad_remove, diff --git a/drivers/media/platform/phytium/phytium_jpeg_core.c b/drivers/media/platform/phytium/phytium_jpeg_core.c index 874f6c5aa5d766337e903891d46502fa46cf366a..014af0162c49f7e413f4a2b4f62aae77a1994671 100644 --- a/drivers/media/platform/phytium/phytium_jpeg_core.c +++ b/drivers/media/platform/phytium/phytium_jpeg_core.c @@ -800,6 +800,7 @@ static void phytium_jpeg_resolution_work(struct work_struct *work) if (jpeg_dev->detected_timings.width != jpeg_dev->active_timings.width || jpeg_dev->detected_timings.height != jpeg_dev->active_timings.height || input_status != jpeg_dev->v4l2_input_status) { + static const struct v4l2_event event = { .type = V4L2_EVENT_SOURCE_CHANGE, .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, @@ -899,7 +900,6 @@ static void phytium_jpeg_irq_res_change(struct phytium_jpeg_dev *jpeg_dev, ulong delay) { dev_info(jpeg_dev->dev, "Source resolution is changed, resetting\n"); - set_bit(VIDEO_RES_CHANGE, &jpeg_dev->status); phytium_jpeg_off(jpeg_dev); @@ -1116,6 +1116,7 @@ static irqreturn_t phytium_jpeg_timer30_irq(int irq, void *arg) /* call SE to poweroff JPEG Engine */ arm_smccc_smc(0xc300fff4, 0x9, 0x2, 0x80000020, 0, 0, 0, 0, &res); + set_bit(VIDEO_RES_CHANGE, &jpeg_dev->status); /* set JPEG Engine's status is poweroff */ set_bit(VIDEO_POWEROFF, &jpeg_dev->status); dev_info(jpeg_dev->dev, "timer30 set jpeg status 0x%lx\n", jpeg_dev->status); diff --git a/drivers/mmc/host/phytium-mci.c b/drivers/mmc/host/phytium-mci.c index 5af8859ba6e19fec0e2666b87042f6518a471edb..4a938fea360ca68462c66bec220702aca532e26c 100644 --- a/drivers/mmc/host/phytium-mci.c +++ b/drivers/mmc/host/phytium-mci.c @@ -95,6 +95,7 @@ static void phytium_mci_update_external_clk(struct phytium_mci_host *host, u32 u writel(uhs_reg_value, host->base + MCI_UHS_REG_EXT); while (!(readl(host->base + MCI_CCLK_RDY) & 0x1)) cpu_relax(); + } static void phytium_mci_prepare_data(struct phytium_mci_host *host, @@ -134,7 +135,7 @@ static void phytium_mci_send_cmd(struct phytium_mci_host *host, u32 cmd, u32 arg rc = readl_relaxed_poll_timeout(host->base + MCI_STATUS, data, !(data & MCI_STATUS_CARD_BUSY), - 0, 100 * 1000); + 0, 5000 * 1000); if (rc == -ETIMEDOUT) pr_debug("%s %d, timeout mci_status: 0x%08x\n", __func__, __LINE__, data); @@ -143,7 +144,7 @@ static void phytium_mci_send_cmd(struct phytium_mci_host *host, u32 cmd, u32 arg rc = readl_relaxed_poll_timeout(host->base + MCI_CMD, data, !(data & MCI_CMD_START), - 0, 100 * 1000); + 0, 5000 * 1000); if (rc == -ETIMEDOUT) pr_debug("%s %d, timeout mci_cmd: 0x%08x\n", __func__, __LINE__, data); } @@ -679,6 +680,8 @@ phytium_mci_start_data(struct phytium_mci_host *host, struct mmc_request *mrq, phytium_mci_data_sg_write_2_fifo(host, data); spin_lock_irqsave(&host->lock, flags); + mod_timer(&host->timeout_timer, + jiffies + msecs_to_jiffies(MMC_REQ_TIMEOUT_MS)); sdr_set_bits(host->base + MCI_INT_MASK, cmd_ints_mask | data_ints_mask); if (host->is_use_dma && host->adtc_type == BLOCK_RW_ADTC) { sdr_set_bits(host->base + MCI_DMAC_INT_ENA, dmac_ints_mask); @@ -694,9 +697,6 @@ phytium_mci_start_data(struct phytium_mci_host *host, struct mmc_request *mrq, wmb(); /* drain writebuffer */ writel(rawcmd, host->base + MCI_CMD); spin_unlock_irqrestore(&host->lock, flags); - - mod_timer(&host->timeout_timer, - jiffies + msecs_to_jiffies(MMC_REQ_TIMEOUT_MS)); } static void phytium_mci_track_cmd_data(struct phytium_mci_host *host, @@ -756,6 +756,21 @@ static bool phytium_mci_cmd_done(struct phytium_mci_host *host, int events, rsp[1] = readl(host->base + MCI_RESP2); rsp[0] = readl(host->base + MCI_RESP3); } else { + /* + * Sometimes get ACMD41 cmd done irq but the respose index still the APP_CMD, + * so polling the mci status entill the respose index change. + */ + if (cmd->opcode == SD_APP_OP_COND) { + int polling_cnt = 20; + while (MMC_APP_CMD == MCI_STATUS_RESPOSE_INDEX(readl(host->base + MCI_STATUS))) { + udelay(100); + polling_cnt --; + if (polling_cnt == 0) { + dev_info(host->dev, "hw respose index not equal cmd opcode, respose value may error\n"); + break; + } + } + } rsp[0] = readl(host->base + MCI_RESP0); } @@ -803,13 +818,12 @@ static void phytium_mci_start_command(struct phytium_mci_host *host, } spin_lock_irqsave(&host->lock, flags); + mod_timer(&host->timeout_timer, + jiffies + msecs_to_jiffies(MMC_REQ_TIMEOUT_MS)); sdr_set_bits(host->base + MCI_INT_MASK, cmd_ints_mask); writel(cmd->arg, host->base + MCI_CMDARG); writel(rawcmd, host->base + MCI_CMD); spin_unlock_irqrestore(&host->lock, flags); - - mod_timer(&host->timeout_timer, - jiffies + msecs_to_jiffies(MMC_REQ_TIMEOUT_MS)); } static void @@ -1155,27 +1169,15 @@ static irqreturn_t phytium_mci_irq(int irq, void *dev_id) cmd = host->cmd; data = host->data; -#if 0 - if (((events & event_mask) & MCI_RAW_INTS_SDIO) && - ((events == 0x10001) || (events == 0x10000) || (events == 0x10040))) { - writel(events, host->base + MCI_RAW_INTS); + if ((events & event_mask) & MCI_RAW_INTS_SDIO) __phytium_mci_enable_sdio_irq(host, 0); - sdio_signal_irq(host->mmc); - spin_unlock_irqrestore(&host->lock, flags); - goto irq_out; - } -#endif - if ((events & event_mask) & MCI_RAW_INTS_SDIO) { - __phytium_mci_enable_sdio_irq(host, 0); - } writel((events & event_mask), host->base + MCI_RAW_INTS); writel(dmac_events, host->base + MCI_DMAC_STATUS); spin_unlock_irqrestore(&host->lock, flags); - if ((events & event_mask) & MCI_RAW_INTS_SDIO) { + if ((events & event_mask) & MCI_RAW_INTS_SDIO) sdio_signal_irq(host->mmc); - } if (((events & event_mask) == 0) && ((dmac_evt_mask & dmac_events) == 0)) goto irq_out; @@ -1209,12 +1211,12 @@ static irqreturn_t phytium_mci_irq(int irq, void *dev_id) goto irq_out; } - if ((events & MCI_MASKED_INTS_DTO) && (events & MCI_MASKED_INTS_CMD)) { + if (cmd && (events & MCI_MASKED_INTS_DTO) && (events & MCI_MASKED_INTS_CMD)) { phytium_mci_cmd_done(host, events, mrq, cmd); phytium_mci_data_xfer_done(host, (events & data_ints_mask) | (dmac_events & dmac_ints_mask), mrq, data); - } else if (events & MCI_MASKED_INTS_CMD || - ((events & MCI_INT_MASK_HTO) && (cmd->opcode == SD_SWITCH_VOLTAGE))) { + } else if (cmd && (events & MCI_MASKED_INTS_CMD || + ((events & MCI_INT_MASK_HTO) && (cmd->opcode == SD_SWITCH_VOLTAGE)))) { phytium_mci_cmd_done(host, events, mrq, cmd); } else if (events & MCI_MASKED_INTS_DTO) { phytium_mci_data_xfer_done(host, (events & data_ints_mask) | diff --git a/drivers/mmc/host/phytium-mci.h b/drivers/mmc/host/phytium-mci.h index fbe30a2df9286893a7cd0a9f424396f32f276905..90f51b9ee135d7911d5beb100da51a896765dd87 100644 --- a/drivers/mmc/host/phytium-mci.h +++ b/drivers/mmc/host/phytium-mci.h @@ -217,6 +217,9 @@ #define MCI_STATUS_CARD_STATUS (0x1 << 8) /* RO */ #define MCI_STATUS_CARD_BUSY (0x1 << 9) /* RO */ #define MCI_STATUS_DATA_BUSY (0x1 << 10) /* RO */ +#define MCI_STATUS_RESPOSE_INDEX_OFFSET (11) +#define MCI_STATUS_RESPOSE_INDEX_MASK (0x3f << MCI_STATUS_RESPOSE_INDEX_OFFSET) /* RO */ +#define MCI_STATUS_RESPOSE_INDEX(reg) (((reg) & MCI_STATUS_RESPOSE_INDEX_MASK) >> MCI_STATUS_RESPOSE_INDEX_OFFSET) #define MCI_STATUS_DMA_ACK (0x1 << 31) /* RO */ #define MCI_STATUS_DMA_REQ (0x1 << 32) /* RO */ diff --git a/drivers/mmc/host/phytium-sdci.c b/drivers/mmc/host/phytium-sdci.c index ba0296bddda3a0572d9f36353bea3c355b6f2670..44379f5589c682f2a2cc1860939f0e054b4cddec 100644 --- a/drivers/mmc/host/phytium-sdci.c +++ b/drivers/mmc/host/phytium-sdci.c @@ -1215,7 +1215,7 @@ static int phytium_sdci_probe(struct platform_device *pdev) return -ENODEV; } - acpi_dma_configure(dev, DEV_DMA_NOT_SUPPORTED); + acpi_dma_configure(dev, DEV_DMA_NON_COHERENT); host->clk_rate = 600000000; } else { diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 44bf7a98225b9ddab802fc5aa46c1ba56326cb32..bff334e15c9d5692fd995d6139447ba81e616af2 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -85,7 +85,7 @@ #define GEM_PBUFRXCUT 0x0044 /* RX Partial Store and Forward */ #define GEM_JML 0x0048 /* Jumbo Max Length */ #define GEM_HS_MAC_CONFIG 0x0050 /* GEM high speed config */ -#define GEM_AXI_PIPE 0x0054 /* AXI max pipeline register*/ +#define GEM_AXI_PIPE 0x0054 /* Axi max pipeline register*/ #define GEM_HRB 0x0080 /* Hash Bottom */ #define GEM_HRT 0x0084 /* Hash Top */ #define GEM_SA1B 0x0088 /* Specific1 Bottom */ @@ -222,30 +222,36 @@ #define GEM_IDR(hw_q) (0x0620 + ((hw_q) << 2)) #define GEM_IMR(hw_q) (0x0640 + ((hw_q) << 2)) #define GEM_TAIL(hw_q) (0x0e80 + ((hw_q) << 2)) /* Phytium: tail register */ -#define GEM_SRC_SEL_LN 0x1C04 -#define GEM_DIV_SEL0_LN 0x1C08 -#define GEM_DIV_SEL1_LN 0x1C0C + +#define GEM_SRC_SEL_LN 0x1C04 +#define GEM_DIV_SEL0_LN 0x1C08 +#define GEM_DIV_SEL1_LN 0x1C0C #define GEM_PMA_XCVR_POWER_STATE 0x1C10 -#define GEM_SPEED_MODE 0x1C14 -#define GEM_MII_SELECT 0x1C18 -#define GEM_SEL_MII_ON_RGMII 0x1C1C -#define GEM_TX_CLK_SEL0 0x1C20 -#define GEM_TX_CLK_SEL1 0x1C24 -#define GEM_TX_CLK_SEL2 0x1C28 -#define GEM_TX_CLK_SEL3 0x1C2C -#define GEM_RX_CLK_SEL0 0x1C30 -#define GEM_RX_CLK_SEL1 0x1C34 +#define GEM_SPEED_MODE 0x1C14 +#define GEM_MII_SELECT 0x1C18 +#define GEM_SEL_MII_ON_RGMII 0x1C1C +#define GEM_TX_CLK_SEL0 0x1C20 +#define GEM_TX_CLK_SEL1 0x1C24 +#define GEM_TX_CLK_SEL2 0x1C28 +#define GEM_TX_CLK_SEL3 0x1C2C +#define GEM_RX_CLK_SEL0 0x1C30 +#define GEM_RX_CLK_SEL1 0x1C34 #define GEM_CLK_250M_DIV10_DIV100_SEL 0x1C38 -#define GEM_TX_CLK_SEL5 0x1C3C -#define GEM_TX_CLK_SEL6 0x1C40 -#define GEM_RX_CLK_SEL4 0x1C44 -#define GEM_RX_CLK_SEL5 0x1C48 -#define GEM_TX_CLK_SEL3_0 0x1C70 -#define GEM_TX_CLK_SEL4_0 0x1C74 -#define GEM_RX_CLK_SEL3_0 0x1C78 -#define GEM_RX_CLK_SEL4_0 0x1C7C -#define GEM_RGMII_TX_CLK_SEL0 0x1C80 -#define GEM_RGMII_TX_CLK_SEL1 0x1C84 +#define GEM_TX_CLK_SEL5 0x1C3C +#define GEM_TX_CLK_SEL6 0x1C40 +#define GEM_RX_CLK_SEL4 0x1C44 +#define GEM_RX_CLK_SEL5 0x1C48 +#define GEM_TX_CLK_SEL3_0 0x1C70 +#define GEM_TX_CLK_SEL4_0 0x1C74 +#define GEM_RX_CLK_SEL3_0 0x1C78 +#define GEM_RX_CLK_SEL4_0 0x1C7C +#define GEM_RGMII_TX_CLK_SEL0 0x1C80 +#define GEM_RGMII_TX_CLK_SEL1 0x1C84 + +#define GEM_PHY_INT_ENABLE 0x1C88 +#define GEM_PHY_INT_CLEAR 0x1C8C +#define GEM_PHY_INT_STATE 0x1C90 +#define GEM_INTX_IRQ_MASK 0x1C7C /* Phytium: irq mask */ /* Bitfields in NCR */ #define MACB_LB_OFFSET 0 /* reserved */ @@ -762,8 +768,11 @@ #define MACB_CAPS_GEM_HAS_PTP 0x00000040 #define MACB_CAPS_BD_RD_PREFETCH 0x00000080 #define MACB_CAPS_NEEDS_RSTONUBR 0x00000100 +#define MACB_CAPS_SEL_CLK 0x00000800 #define MACB_CAPS_MIIONRGMII 0x00000200 #define MACB_CAPS_NEED_TSUCLK 0x00000400 +#define MACB_CAPS_SEL_CLK 0x00000800 +#define MACB_CAPS_TAILPTR 0x00001000 /* Phytium: tail register */ #define MACB_CAPS_PCS 0x01000000 #define MACB_CAPS_HIGH_SPEED 0x02000000 #define MACB_CAPS_CLK_HW_CHG 0x04000000 @@ -772,9 +781,8 @@ #define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000 #define MACB_CAPS_SG_DISABLED 0x40000000 #define MACB_CAPS_MACB_IS_GEM 0x80000000 -#define MACB_CAPS_SEL_CLK_HW 0x00001000 -#define MACB_CAPS_SEL_CLK_HW_2 0x00002000 -#define MACB_CAPS_TAILPTR 0x00004000 /* Phytium: tail register */ +#define MACB_CAPS_PCS 0x01000000 +#define MACB_CAPS_HIGH_SPEED 0x02000000 /* LSO settings */ #define MACB_LSO_UFO_ENABLE 0x01 @@ -817,6 +825,8 @@ #define gem_readl_n(port, reg, idx) (port)->macb_reg_readl((port), GEM_##reg + idx * 4) #define gem_writel_n(port, reg, idx, value) (port)->macb_reg_writel((port), GEM_##reg + idx * 4, (value)) +#define PTP_TS_BUFFER_SIZE 128 /* must be power of 2 */ + /* Conditional GEM/MACB macros. These perform the operation to the correct * register dependent on whether the device is a GEM or a MACB. For registers * and bitfields that are common across both devices, use macb_{read,write}l @@ -866,6 +876,11 @@ struct macb_dma_desc_ptp { u32 ts_1; u32 ts_2; }; + +struct gem_tx_ts { + struct sk_buff *skb; + struct macb_dma_desc_ptp desc_ptp; +}; #endif /* DMA descriptor bitfields */ @@ -1227,6 +1242,7 @@ struct macb_config { unsigned int max_tx_length; int jumbo_max_len; const struct macb_usrio_config *usrio; + void (*sel_clk_hw)(struct macb *bp, int speed); }; struct tsu_incr { @@ -1248,6 +1264,7 @@ struct macb_queue { unsigned int RBQP; unsigned int RBQPH; unsigned int TAILADDR; + /* Lock to protect tx_head and tx_tail */ spinlock_t tx_ptr_lock; unsigned int tx_head, tx_tail; @@ -1265,8 +1282,15 @@ struct macb_queue { struct macb_dma_desc *rx_ring; struct sk_buff **rx_skbuff; void *rx_buffers; + struct napi_struct napi; struct napi_struct napi_rx; struct queue_stats stats; + +#ifdef CONFIG_MACB_USE_HWSTAMP + struct work_struct tx_ts_task; + unsigned int tx_ts_head, tx_ts_tail; + struct gem_tx_ts tx_timestamps[PTP_TS_BUFFER_SIZE]; +#endif }; struct ethtool_rx_fs_item { @@ -1304,6 +1328,7 @@ struct macb { struct clk *rx_clk; struct clk *tsu_clk; struct net_device *dev; + struct ncsi_dev *ndev; union { struct macb_stats macb; struct gem_stats gem; @@ -1316,7 +1341,9 @@ struct macb { struct phylink_config phylink_config; struct phylink_pcs phylink_usx_pcs; struct phylink_pcs phylink_sgmii_pcs; - struct ncsi_dev *ndev; + int link; + int speed; + int duplex; int use_ncsi; u32 caps; @@ -1366,6 +1393,8 @@ struct macb { struct macb_pm_data pm_data; const struct macb_usrio_config *usrio; + + void (*sel_clk_hw)(struct macb *bp, int speed); }; #ifdef CONFIG_MACB_USE_HWSTAMP diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 4c7fbd437fa0ca8c14c776c193d815bbf667aed9..cb04fbf8a432757ae8574327a61091dfb7399802 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -6,7 +6,6 @@ */ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include #include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "macb.h" @@ -49,6 +50,9 @@ struct sifive_fu540_macb_mgmt { struct clk_hw hw; }; +#define MAX_RING_ADDR_ALLOC_TIMES 3 +#define RING_ADDR_INTERVAL 128 + #define MACB_RX_BUFFER_SIZE 128 #define RX_BUFFER_MULTIPLE 64 /* bytes */ @@ -89,12 +93,12 @@ struct sifive_fu540_macb_mgmt { #define MACB_WOL_HAS_MAGIC_PACKET (0x1 << 0) #define MACB_WOL_ENABLED (0x1 << 1) -#define HS_SPEED_100M 0 -#define HS_SPEED_1000M 1 -#define HS_SPEED_2500M 2 -#define HS_SPEED_5000M 3 -#define HS_SPEED_10000M 4 -#define MACB_SERDES_RATE_5G 0 +#define HS_SPEED_100M 0 +#define HS_SPEED_1000M 1 +#define HS_SPEED_2500M 2 +#define HS_SPEED_5000M 3 +#define HS_SPEED_10000M 4 +#define MACB_SERDES_RATE_5G 0 #define MACB_SERDES_RATE_10G 1 /* Graceful stop timeouts in us. We should allow up to @@ -105,6 +109,10 @@ struct sifive_fu540_macb_mgmt { #define MACB_MDIO_TIMEOUT 1000000 /* in usecs */ +static void macb_tx_unmap(struct macb *bp, + struct macb_tx_skb *tx_skb, + int budget); + /* DMA buffer descriptor might be different size * depends on hardware configuration: * @@ -569,162 +577,7 @@ static void macb_set_tx_clk(struct macb *bp, int speed) netdev_err(bp->dev, "adjusting tx_clk failed.\n"); } -static int phytium_gem_sel_clk(struct macb *bp, int spd) -{ - int speed = 0; - - if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || - bp->phy_interface == PHY_INTERFACE_MODE_10GBASER) { - gem_writel(bp, SRC_SEL_LN, 0x1); - if (spd == SPEED_5000) { - gem_writel(bp, DIV_SEL0_LN, 0x8); - gem_writel(bp, DIV_SEL1_LN, 0x2); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); - speed = HS_SPEED_5000M; - } else { - gem_writel(bp, DIV_SEL0_LN, 0x4); - gem_writel(bp, DIV_SEL1_LN, 0x1); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); - speed = HS_SPEED_10000M; - } - } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { - gem_writel(bp, SRC_SEL_LN, 0x1); - gem_writel(bp, DIV_SEL0_LN, 0x8); - gem_writel(bp, DIV_SEL1_LN, 0x2); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); - speed = HS_SPEED_5000M; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { - gem_writel(bp, SRC_SEL_LN, 0x1); - gem_writel(bp, DIV_SEL0_LN, 0x1); - gem_writel(bp, DIV_SEL1_LN, 0x2); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x1); - gem_writel(bp, TX_CLK_SEL2, 0x1); - gem_writel(bp, TX_CLK_SEL3, 0x1); - gem_writel(bp, RX_CLK_SEL0, 0x1); - gem_writel(bp, RX_CLK_SEL1, 0x0); - gem_writel(bp, TX_CLK_SEL3_0, 0x0); - gem_writel(bp, TX_CLK_SEL4_0, 0x0); - gem_writel(bp, RX_CLK_SEL3_0, 0x0); - gem_writel(bp, RX_CLK_SEL4_0, 0x0); - speed = HS_SPEED_2500M; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { - if (spd == SPEED_1000) { - gem_writel(bp, SRC_SEL_LN, 0x1); - gem_writel(bp, DIV_SEL0_LN, 0x4); - gem_writel(bp, DIV_SEL1_LN, 0x8); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x0); - gem_writel(bp, TX_CLK_SEL2, 0x0); - gem_writel(bp, TX_CLK_SEL3, 0x1); - gem_writel(bp, RX_CLK_SEL0, 0x1); - gem_writel(bp, RX_CLK_SEL1, 0x0); - gem_writel(bp, TX_CLK_SEL3_0, 0x0); - gem_writel(bp, TX_CLK_SEL4_0, 0x0); - gem_writel(bp, RX_CLK_SEL3_0, 0x0); - gem_writel(bp, RX_CLK_SEL4_0, 0x0); - speed = HS_SPEED_1000M; - } else if (spd == SPEED_100 || spd == SPEED_10) { - gem_writel(bp, SRC_SEL_LN, 0x1); - gem_writel(bp, DIV_SEL0_LN, 0x4); - gem_writel(bp, DIV_SEL1_LN, 0x8); - gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x0); - gem_writel(bp, TX_CLK_SEL2, 0x1); - gem_writel(bp, TX_CLK_SEL3, 0x1); - gem_writel(bp, RX_CLK_SEL0, 0x1); - gem_writel(bp, RX_CLK_SEL1, 0x0); - gem_writel(bp, TX_CLK_SEL3_0, 0x1); - gem_writel(bp, TX_CLK_SEL4_0, 0x0); - gem_writel(bp, RX_CLK_SEL3_0, 0x0); - gem_writel(bp, RX_CLK_SEL4_0, 0x1); - speed = HS_SPEED_100M; - } - } else if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII || - bp->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) { - if (spd == SPEED_1000) { - gem_writel(bp, MII_SELECT, 0x1); - gem_writel(bp, SEL_MII_ON_RGMII, 0x0); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x1); - gem_writel(bp, TX_CLK_SEL2, 0x0); - gem_writel(bp, TX_CLK_SEL3, 0x0); - gem_writel(bp, RX_CLK_SEL0, 0x0); - gem_writel(bp, RX_CLK_SEL1, 0x1); - gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); - gem_writel(bp, RX_CLK_SEL5, 0x1); - gem_writel(bp, RGMII_TX_CLK_SEL0, 0x1); - gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); - speed = HS_SPEED_1000M; - } else if (spd == SPEED_100) { - gem_writel(bp, MII_SELECT, 0x1); - gem_writel(bp, SEL_MII_ON_RGMII, 0x0); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x1); - gem_writel(bp, TX_CLK_SEL2, 0x0); - gem_writel(bp, TX_CLK_SEL3, 0x0); - gem_writel(bp, RX_CLK_SEL0, 0x0); - gem_writel(bp, RX_CLK_SEL1, 0x1); - gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); - gem_writel(bp, RX_CLK_SEL5, 0x1); - gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); - gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); - speed = HS_SPEED_100M; - } else { - gem_writel(bp, MII_SELECT, 0x1); - gem_writel(bp, SEL_MII_ON_RGMII, 0x0); - gem_writel(bp, TX_CLK_SEL0, 0x0); - gem_writel(bp, TX_CLK_SEL1, 0x1); - gem_writel(bp, TX_CLK_SEL2, 0x0); - gem_writel(bp, TX_CLK_SEL3, 0x0); - gem_writel(bp, RX_CLK_SEL0, 0x0); - gem_writel(bp, RX_CLK_SEL1, 0x1); - gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x1); - gem_writel(bp, RX_CLK_SEL5, 0x1); - gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); - gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); - speed = HS_SPEED_100M; - } - } else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) { - speed = HS_SPEED_100M; - gem_writel(bp, RX_CLK_SEL5, 0x1); - } - - gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, speed, - gem_readl(bp, HS_MAC_CONFIG))); - - return 0; -} - -static int phytium_gem_sel_clk_2(struct macb *bp, int spd) -{ - int speed = 0; - - if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || - bp->phy_interface == PHY_INTERFACE_MODE_10GBASER) { - speed = HS_SPEED_10000M; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { - speed = HS_SPEED_5000M; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { - speed = HS_SPEED_2500M; - } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { - if (spd == SPEED_1000) { - speed = HS_SPEED_1000M; - } else if (spd == SPEED_100 || spd == SPEED_10) { - speed = HS_SPEED_100M; - } - } - - gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, speed, - gem_readl(bp, HS_MAC_CONFIG))); - - return 0; -} - -static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, +static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, phy_interface_t interface, int speed, int duplex) { @@ -741,12 +594,13 @@ static void macb_usx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode, } config &= ~(GEM_BIT(TX_SCR_BYPASS) | GEM_BIT(RX_SCR_BYPASS)); - + /* reset */ config &= ~(GEM_BIT(SIGNAL_OK) | GEM_BIT(TX_EN)); config |= GEM_BIT(RX_SYNC_RESET); gem_writel(bp, USX_CONTROL, config); + /* enable rx and tx */ config &= ~(GEM_BIT(RX_SYNC_RESET)); config |= GEM_BIT(SIGNAL_OK) | GEM_BIT(TX_EN); @@ -761,8 +615,9 @@ static void macb_usx_pcs_get_state(struct phylink_pcs *pcs, if (state->interface == PHY_INTERFACE_MODE_5GBASER) state->speed = SPEED_5000; - else - state->speed = SPEED_10000; + else if (state->interface == PHY_INTERFACE_MODE_10GBASER || + state->interface == PHY_INTERFACE_MODE_USXGMII) + state->speed = bp->speed; state->duplex = 1; state->an_complete = 1; @@ -866,8 +721,8 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode, * Must be written after PCSSEL is set in NCFGR, * otherwise writes will not take effect. */ - if (macb_is_gem(bp) && state->interface == (PHY_INTERFACE_MODE_SGMII || - PHY_INTERFACE_MODE_2500BASEX)) { + if (macb_is_gem(bp) && (state->interface == PHY_INTERFACE_MODE_SGMII || + PHY_INTERFACE_MODE_2500BASEX)) { u32 pcsctrl, old_pcsctrl; old_pcsctrl = gem_readl(bp, PCSCNTRL); @@ -887,9 +742,14 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, { struct net_device *ndev = to_net_dev(config->dev); struct macb *bp = netdev_priv(ndev); + struct macb_tx_skb *tx_skb; struct macb_queue *queue; unsigned int q; u32 ctrl; + int i; + + if (bp->use_ncsi) + ncsi_stop_dev(bp->ndev); if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) @@ -897,12 +757,195 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode, bp->rx_intr_mask | MACB_TX_INT_FLAGS | MACB_BIT(HRESP)); /* Disable Rx and Tx */ - ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | MACB_BIT(TE)) & ~(MACB_BIT(2PT5G)); + ctrl = macb_readl(bp, NCR) & ~(MACB_BIT(RE) | + MACB_BIT(TE)) & ~(MACB_BIT(2PT5G)); macb_writel(bp, NCR, ctrl); + /* Tx clean */ + for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { + for (i = 0; i < bp->tx_ring_size; i++) { + tx_skb = macb_tx_skb(queue, i); + /* free unsent skb buffers */ + if (tx_skb) + macb_tx_unmap(bp, tx_skb, 0); + } + } + netif_tx_stop_all_queues(ndev); } +static void phytium_gem1p0_sel_clk(struct macb *bp, int speed) +{ + if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER || + bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + if (speed == SPEED_5000) { + gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); /*0x1c10*/ + } else { + gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x1); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ + } + } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x8); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x0); /*0x1c10*/ + } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x1); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x2); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/ + gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/ + gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/ + gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ + gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ + } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (speed == SPEED_1000) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x0); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/ + gem_writel(bp, TX_CLK_SEL3_0, 0x0); /*0x1c70*/ + gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/ + gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ + gem_writel(bp, RX_CLK_SEL4_0, 0x0); /*0x1c7c*/ + } else if (speed == SPEED_100 || speed == SPEED_10) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL0_LN, 0x4); /*0x1c08*/ + gem_writel(bp, DIV_SEL1_LN, 0x8); /*0x1c0c*/ + gem_writel(bp, PMA_XCVR_POWER_STATE, 0x1); /*0x1c10*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x0); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x1); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x1); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x1); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x0); /*0x1c34*/ + gem_writel(bp, TX_CLK_SEL3_0, 0x1); /*0x1c70*/ + gem_writel(bp, TX_CLK_SEL4_0, 0x0); /*0x1c74*/ + gem_writel(bp, RX_CLK_SEL3_0, 0x0); /*0x1c78*/ + gem_writel(bp, RX_CLK_SEL4_0, 0x1); /*0x1c7c*/ + } + } else if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII || + bp->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) { + if (speed == SPEED_1000) { + gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/ + gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/ + gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); /*0x1c38*/ + gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/ + gem_writel(bp, RGMII_TX_CLK_SEL0, 0x1); /*0x1c80*/ + gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/ + } else if (speed == SPEED_100) { + gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/ + gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/ + gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x0); /*0x1c38*/ + gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/ + gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); /*0x1c80*/ + gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/ + } else { + gem_writel(bp, MII_SELECT, 0x1); /*0x1c18*/ + gem_writel(bp, SEL_MII_ON_RGMII, 0x0); /*0x1c1c*/ + gem_writel(bp, TX_CLK_SEL0, 0x0); /*0x1c20*/ + gem_writel(bp, TX_CLK_SEL1, 0x1); /*0x1c24*/ + gem_writel(bp, TX_CLK_SEL2, 0x0); /*0x1c28*/ + gem_writel(bp, TX_CLK_SEL3, 0x0); /*0x1c2c*/ + gem_writel(bp, RX_CLK_SEL0, 0x0); /*0x1c30*/ + gem_writel(bp, RX_CLK_SEL1, 0x1); /*0x1c34*/ + gem_writel(bp, CLK_250M_DIV10_DIV100_SEL, 0x1); /*0x1c38*/ + gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/ + gem_writel(bp, RGMII_TX_CLK_SEL0, 0x0); /*0x1c80*/ + gem_writel(bp, RGMII_TX_CLK_SEL1, 0x0); /*0x1c84*/ + } + } else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII) { + gem_writel(bp, RX_CLK_SEL5, 0x1); /*0x1c48*/ + } + + if (speed == SPEED_100) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_100M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_1000) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_1000M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_2500) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_2500M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_5000) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_10000) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_10000M, + gem_readl(bp, HS_MAC_CONFIG))); +} + +static void phytium_gem2p0_sel_clk(struct macb *bp, int speed) +{ + if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (speed == SPEED_100 || speed == SPEED_10) { + gem_writel(bp, SRC_SEL_LN, 0x1); /*0x1c04*/ + gem_writel(bp, DIV_SEL1_LN, 0x1); /*0x1c0c*/ + } + } + + if (speed == SPEED_100 || speed == SPEED_10) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_100M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_1000) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_1000M, + gem_readl(bp, HS_MAC_CONFIG))); + else if (speed == SPEED_2500) + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_2500M, + gem_readl(bp, HS_MAC_CONFIG))); +} + +static void phytium_gmac_sel_clk(struct macb *bp, int spd) +{ + int speed = 0; + + if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_10GBASER) { + speed = HS_SPEED_10000M; + } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + speed = HS_SPEED_5000M; + } else if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + speed = HS_SPEED_2500M; + } else if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { + if (spd == SPEED_1000) { + speed = HS_SPEED_1000M; + } else if (spd == SPEED_100 || spd == SPEED_10) { + speed = HS_SPEED_100M; + } + } + + gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, speed, + gem_readl(bp, HS_MAC_CONFIG))); +} + static void macb_mac_link_up(struct phylink_config *config, struct phy_device *phy, unsigned int mode, phy_interface_t interface, @@ -915,14 +958,12 @@ static void macb_mac_link_up(struct phylink_config *config, unsigned long flags; unsigned int q; u32 ctrl; + int err; spin_lock_irqsave(&bp->lock, flags); - if (bp->caps & MACB_CAPS_SEL_CLK_HW) - phytium_gem_sel_clk(bp, speed); - - if (bp->caps & MACB_CAPS_SEL_CLK_HW_2) - phytium_gem_sel_clk_2(bp, speed); + if (bp->caps & MACB_CAPS_SEL_CLK) + bp->sel_clk_hw(bp, speed); ctrl = macb_or_gem_readl(bp, NCFGR); @@ -946,6 +987,8 @@ static void macb_mac_link_up(struct phylink_config *config, if (rx_pause) ctrl |= MACB_BIT(PAE); + macb_set_tx_clk(bp, speed); + /* Initialize rings & buffers as clearing MACB_BIT(TE) in link down * cleared the pipeline and control registers. */ @@ -959,8 +1002,13 @@ static void macb_mac_link_up(struct phylink_config *config, macb_or_gem_writel(bp, NCFGR, ctrl); - if (speed == SPEED_2500) - macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(2PT5G)); + if (speed == SPEED_2500) { + u32 network_ctrl; + + network_ctrl = macb_readl(bp, NCR); + network_ctrl |= MACB_BIT(2PT5G); + macb_writel(bp, NCR, network_ctrl); + } if (bp->phy_interface == PHY_INTERFACE_MODE_10GBASER || bp->phy_interface == PHY_INTERFACE_MODE_USXGMII) { @@ -973,8 +1021,9 @@ static void macb_mac_link_up(struct phylink_config *config, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_10000M, gem_readl(bp, HS_MAC_CONFIG))); } else if (bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) - gem_writel(bp, HS_MAC_CONFIG, GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M, - gem_readl(bp, HS_MAC_CONFIG))); + gem_writel(bp, HS_MAC_CONFIG, + GEM_BFINS(HS_MAC_SPEED, HS_SPEED_5000M, + gem_readl(bp, HS_MAC_CONFIG))); spin_unlock_irqrestore(&bp->lock, flags); @@ -988,6 +1037,15 @@ static void macb_mac_link_up(struct phylink_config *config, macb_writel(bp, NCR, ctrl | MACB_BIT(RE) | MACB_BIT(TE)); + if (bp->use_ncsi) { + /* Start the NCSI device */ + err = ncsi_start_dev(bp->ndev); + if (err) { + netdev_err(bp->dev, "Ncsi start dev failed (error %d)\n", err); + return; + } + } + netif_tx_wake_all_queues(ndev); } @@ -999,10 +1057,10 @@ static struct phylink_pcs *macb_mac_select_pcs(struct phylink_config *config, if (interface == PHY_INTERFACE_MODE_10GBASER || interface == PHY_INTERFACE_MODE_5GBASER || - interface == PHY_INTERFACE_MODE_USXGMII) { + interface == PHY_INTERFACE_MODE_USXGMII) { return &bp->phylink_usx_pcs; } else if (interface == PHY_INTERFACE_MODE_SGMII || - interface == PHY_INTERFACE_MODE_2500BASEX) { + interface == PHY_INTERFACE_MODE_2500BASEX) { return &bp->phylink_sgmii_pcs; } else { return NULL; @@ -1550,6 +1608,7 @@ static void gem_rx_refill(struct macb_queue *queue) /* Make hw descriptor updates visible to CPU */ rmb(); + queue->rx_prepared_head++; desc = macb_rx_desc(queue, entry); if (!queue->rx_skbuff[entry]) { @@ -1588,7 +1647,6 @@ static void gem_rx_refill(struct macb_queue *queue) dma_wmb(); desc->addr &= ~MACB_BIT(RX_USED); } - queue->rx_prepared_head++; } /* Make descriptor updates visible to hardware */ @@ -2125,11 +2183,10 @@ static irqreturn_t gem_wol_interrupt(int irq, void *dev_id) static irqreturn_t macb_interrupt(int irq, void *dev_id) { - struct macb_queue *qq, *queue = dev_id; + struct macb_queue *queue = dev_id; struct macb *bp = queue->bp; struct net_device *dev = bp->dev; u32 status, ctrl; - unsigned int q; status = queue_readl(queue, ISR); @@ -2176,13 +2233,11 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) MACB_BIT(TXUBR)); if (status & MACB_BIT(TXUBR)) { - for (q = 0, qq = bp->queues; q < bp->num_queues; q++, qq++) { - qq->txubr_pending = true; - wmb(); // ensure softirq can see update - if (napi_schedule_prep(&qq->napi_tx)) - __napi_schedule(&qq->napi_tx); - } - } else if (napi_schedule_prep(&queue->napi_tx)) { + queue->txubr_pending = true; + wmb(); // ensure softirq can see update + } + + if (napi_schedule_prep(&queue->napi_tx)) { netdev_vdbg(bp->dev, "scheduling TX softirq\n"); __napi_schedule(&queue->napi_tx); } @@ -2632,6 +2687,7 @@ static netdev_tx_t macb_start_xmit(struct sk_buff *skb, struct net_device *dev) if (bp->caps & MACB_CAPS_TAILPTR) queue_writel(queue, TAILADDR, BIT(31) | macb_tx_ring_wrap(bp, queue->tx_head)); + spin_lock_irq(&bp->lock); macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); spin_unlock_irq(&bp->lock); @@ -2712,27 +2768,48 @@ static void macb_free_rx_buffers(struct macb *bp) static void macb_free_consistent(struct macb *bp) { + struct macb_dma_desc *tx_ring_base = NULL; + struct macb_dma_desc *rx_ring_base = NULL; + dma_addr_t tx_ring_base_addr; + dma_addr_t rx_ring_base_addr; struct macb_queue *queue; unsigned int q; int size; bp->macbgem_ops.mog_free_rx_buffers(bp); + queue = bp->queues; + if (queue->tx_ring) { + tx_ring_base = queue->tx_ring; + tx_ring_base_addr = queue->tx_ring_dma; + } + if (queue->rx_ring) { + rx_ring_base = queue->rx_ring; + rx_ring_base_addr = queue->rx_ring_dma; + } + for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { kfree(queue->tx_skb); queue->tx_skb = NULL; - if (queue->tx_ring) { - size = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch; - dma_free_coherent(&bp->pdev->dev, size, - queue->tx_ring, queue->tx_ring_dma); + if (queue->tx_ring) queue->tx_ring = NULL; - } - if (queue->rx_ring) { - size = RX_RING_BYTES(bp) + bp->rx_bd_rd_prefetch; - dma_free_coherent(&bp->pdev->dev, size, - queue->rx_ring, queue->rx_ring_dma); + if (queue->rx_ring) queue->rx_ring = NULL; - } + } + + if (tx_ring_base) { + size = bp->num_queues * (TX_RING_BYTES(bp) + + bp->tx_bd_rd_prefetch + + RING_ADDR_INTERVAL); + dma_free_coherent(&bp->pdev->dev, size, tx_ring_base, + tx_ring_base_addr); + } + if (rx_ring_base) { + size = bp->num_queues * (RX_RING_BYTES(bp) + + bp->rx_bd_rd_prefetch + + RING_ADDR_INTERVAL); + dma_free_coherent(&bp->pdev->dev, size, rx_ring_base, + rx_ring_base_addr); } } @@ -2772,17 +2849,87 @@ static int macb_alloc_rx_buffers(struct macb *bp) return 0; } +static int macb_queue_phyaddr_check(struct macb *bp, dma_addr_t ring_base_addr, + int offset) +{ + u32 bus_addr_high; + int i; + + bus_addr_high = upper_32_bits(ring_base_addr); + for (i = 1; i < bp->num_queues; i++) { + ring_base_addr += offset; + if (bus_addr_high != upper_32_bits(ring_base_addr)) + return -1; + } + + return 0; +} + static int macb_alloc_consistent(struct macb *bp) { + struct macb_dma_desc *tx_ring_base, *rx_ring_base; + dma_addr_t tx_ring_base_addr, rx_ring_base_addr; struct macb_queue *queue; + int tx_offset, rx_offset; + int tx_size, rx_size; unsigned int q; + int ret, i; int size; + tx_offset = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch + + RING_ADDR_INTERVAL; + tx_size = bp->num_queues * tx_offset; + for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { + if (i == MAX_RING_ADDR_ALLOC_TIMES) + return -ENOMEM; + + tx_ring_base = dma_alloc_coherent(&bp->pdev->dev, tx_size, + &tx_ring_base_addr, + GFP_KERNEL); + if (!tx_ring_base) + continue; + + ret = macb_queue_phyaddr_check(bp, tx_ring_base_addr, + tx_offset); + if (ret) { + dma_free_coherent(&bp->pdev->dev, tx_size, tx_ring_base, + tx_ring_base_addr); + continue; + } else { + break; + } + } + + rx_offset = RX_RING_BYTES(bp) + bp->rx_bd_rd_prefetch + + RING_ADDR_INTERVAL; + rx_size = bp->num_queues * rx_offset; + for (i = 0; i < MAX_RING_ADDR_ALLOC_TIMES + 1; i++) { + if (i == MAX_RING_ADDR_ALLOC_TIMES) { + dma_free_coherent(&bp->pdev->dev, tx_size, tx_ring_base, + tx_ring_base_addr); + return -ENOMEM; + } + + rx_ring_base = dma_alloc_coherent(&bp->pdev->dev, rx_size, + &rx_ring_base_addr, + GFP_KERNEL); + if (!rx_ring_base) + continue; + + ret = macb_queue_phyaddr_check(bp, rx_ring_base_addr, + rx_offset); + if (ret) { + dma_free_coherent(&bp->pdev->dev, rx_size, rx_ring_base, + rx_ring_base_addr); + continue; + } else { + break; + } + } + for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) { - size = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch; - queue->tx_ring = dma_alloc_coherent(&bp->pdev->dev, size, - &queue->tx_ring_dma, - GFP_KERNEL); + queue->tx_ring = (void *)tx_ring_base + q * tx_offset; + queue->tx_ring_dma = tx_ring_base_addr + q * tx_offset; if (!queue->tx_ring) goto out_err; netdev_dbg(bp->dev, @@ -2791,13 +2938,12 @@ static int macb_alloc_consistent(struct macb *bp) queue->tx_ring); size = bp->tx_ring_size * sizeof(struct macb_tx_skb); - queue->tx_skb = kmalloc(size, GFP_KERNEL); + queue->tx_skb = kzalloc(size, GFP_KERNEL); if (!queue->tx_skb) goto out_err; - size = RX_RING_BYTES(bp) + bp->rx_bd_rd_prefetch; - queue->rx_ring = dma_alloc_coherent(&bp->pdev->dev, size, - &queue->rx_ring_dma, GFP_KERNEL); + queue->rx_ring = (void *)rx_ring_base + q * rx_offset; + queue->rx_ring_dma = rx_ring_base_addr + q * rx_offset; if (!queue->rx_ring) goto out_err; netdev_dbg(bp->dev, @@ -2834,6 +2980,15 @@ static void gem_init_rings(struct macb *bp) if (bp->caps & MACB_CAPS_TAILPTR) queue_writel(queue, TAILADDR, BIT(31) | queue->tx_head); + for (i = 0; i < bp->rx_ring_size; i++) { + desc = macb_rx_desc(queue, i); + desc->ctrl = 0; + /* make sure ctrl is cleared first, + * and bit RX_USED is set to avoid a race. + */ + dma_wmb(); + desc->addr |= MACB_BIT(RX_USED); + } queue->rx_tail = 0; queue->rx_prepared_head = 0; @@ -3010,6 +3165,46 @@ static void macb_configure_dma(struct macb *bp) } } +static int phytium_mac_config(struct macb *bp) +{ + u32 old_ctrl, ctrl; + u32 old_ncr, ncr; + + netdev_dbg(bp->dev, "phytium mac config"); + + ncr = macb_readl(bp, NCR); + old_ncr = ncr; + ctrl = macb_or_gem_readl(bp, NCFGR); + old_ctrl = ctrl; + + ncr &= ~(GEM_BIT(ENABLE_HS_MAC) | MACB_BIT(2PT5G)); + ctrl &= ~(GEM_BIT(SGMIIEN) | GEM_BIT(PCSSEL) | + MACB_BIT(SPD) | MACB_BIT(FD)); + if (macb_is_gem(bp)) + ctrl &= ~GEM_BIT(GBE); + + if (bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + ctrl |= GEM_BIT(PCSSEL) | GEM_BIT(SGMIIEN); + ncr |= MACB_BIT(2PT5G); + } else if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_5GBASER) { + ctrl |= GEM_BIT(PCSSEL); + ncr |= GEM_BIT(ENABLE_HS_MAC); + } + + if (bp->duplex) + ctrl |= MACB_BIT(FD); + + /* Apply the new configuration, if any */ + if (old_ctrl ^ ctrl) + macb_or_gem_writel(bp, NCFGR, ctrl); + + if (old_ncr ^ ncr) + macb_or_gem_writel(bp, NCR, ncr); + + return 0; +} + static void macb_init_hw(struct macb *bp) { u32 config; @@ -3039,14 +3234,26 @@ static void macb_init_hw(struct macb *bp) bp->rx_frm_len_mask = MACB_RX_JFRMLEN_MASK; gem_writel(bp, AXI_PIPE, 0x1010); + + if (bp->phy_interface == PHY_INTERFACE_MODE_USXGMII || + bp->phy_interface == PHY_INTERFACE_MODE_5GBASER || + bp->phy_interface == PHY_INTERFACE_MODE_2500BASEX) { + /* phytium need hwclock */ + if (bp->caps & MACB_CAPS_SEL_CLK) + bp->sel_clk_hw(bp, bp->speed); + phytium_mac_config(bp); + if (bp->link) + macb_usx_pcs_link_up(&bp->phylink_usx_pcs, 0, + bp->phy_interface, bp->speed, bp->duplex); + } else { + bp->speed = SPEED_10; + bp->duplex = DUPLEX_HALF; + } + if (bp->caps & MACB_CAPS_TAILPTR) gem_writel(bp, TAIL_ENABLE, 0x80000001); macb_configure_dma(bp); - - /* Enable RX partial store and forward and set watermark */ - if (bp->rx_watermark) - gem_writel(bp, PBUFRXCUT, (bp->rx_watermark | GEM_BIT(ENCUTTHRU))); } /* The hash address register is 64 bits long and takes up two @@ -3200,26 +3407,16 @@ static int macb_open(struct net_device *dev) napi_enable(&queue->napi_tx); } + macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(MPE)); macb_init_hw(bp); - if (bp->use_ncsi) { - /* If using NC-SI, set our carrier on and start the stack */ - netif_carrier_on(dev); - - /* Start the NCSI device */ - err = ncsi_start_dev(bp->ndev); - if (err) { - netdev_err(dev, "NCSI start dev failed (error %d)\n", err); - } - } else { - err = phy_power_on(bp->sgmii_phy); - if (err) - goto reset_hw; + err = phy_power_on(bp->sgmii_phy); + if (err) + goto reset_hw; - err = macb_phylink_connect(bp); - if (err) - goto phy_off; - } + err = macb_phylink_connect(bp); + if (err) + goto phy_off; netif_tx_start_all_queues(dev); @@ -3262,9 +3459,6 @@ static int macb_close(struct net_device *dev) phy_power_off(bp->sgmii_phy); - if (bp->use_ncsi) - ncsi_stop_dev(bp->ndev); - spin_lock_irqsave(&bp->lock, flags); macb_reset_hw(bp); netif_carrier_off(dev); @@ -4313,6 +4507,97 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk, return err; } +static int phytium_clk_init(struct platform_device *pdev, struct clk **pclk, + struct clk **hclk, struct clk **tx_clk, + struct clk **rx_clk, struct clk **tsu_clk) +{ + struct macb_platform_data *pdata; + struct device_node *np = pdev->dev.of_node; + int err; + + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + *pclk = pdata->pclk; + *hclk = pdata->hclk; + } else { + if (has_acpi_companion(&pdev->dev)) { + *pclk = NULL; + *hclk = NULL; + } else if (np) { + *pclk = devm_clk_get(&pdev->dev, "pclk"); + *hclk = devm_clk_get(&pdev->dev, "hclk"); + } + } + + if (IS_ERR(*pclk)) + return dev_err_probe(&pdev->dev, + IS_ERR(*pclk) ? PTR_ERR(*pclk) : -ENODEV, + "failed to get pclk\n"); + + if (IS_ERR(*hclk)) + return dev_err_probe(&pdev->dev, + IS_ERR(*hclk) ? PTR_ERR(*hclk) : -ENODEV, + "failed to get hclk\n"); + + *tx_clk = devm_clk_get_optional(&pdev->dev, "tx_clk"); + if (IS_ERR(*tx_clk)) + return PTR_ERR(*tx_clk); + + *rx_clk = devm_clk_get_optional(&pdev->dev, "rx_clk"); + if (IS_ERR(*rx_clk)) + return PTR_ERR(*rx_clk); + + *tsu_clk = devm_clk_get_optional(&pdev->dev, "tsu_clk"); + if (IS_ERR(*tsu_clk)) + return PTR_ERR(*tsu_clk); + + err = clk_prepare_enable(*pclk); + if (err) { + dev_err(&pdev->dev, "failed to enable pclk (%d)\n", err); + return err; + } + + err = clk_prepare_enable(*hclk); + if (err) { + dev_err(&pdev->dev, "failed to enable hclk (%d)\n", err); + goto err_disable_pclk; + } + + err = clk_prepare_enable(*tx_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable tx_clk (%d)\n", err); + goto err_disable_hclk; + } + + err = clk_prepare_enable(*rx_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable rx_clk (%d)\n", err); + goto err_disable_txclk; + } + + err = clk_prepare_enable(*tsu_clk); + if (err) { + dev_err(&pdev->dev, "failed to enable tsu_clk (%d)\n", err); + goto err_disable_rxclk; + } + + return 0; + +err_disable_rxclk: + clk_disable_unprepare(*rx_clk); + +err_disable_txclk: + clk_disable_unprepare(*tx_clk); + +err_disable_hclk: + clk_disable_unprepare(*hclk); + +err_disable_pclk: + clk_disable_unprepare(*pclk); + + return err; +} + static int macb_init(struct platform_device *pdev) { struct net_device *dev = platform_get_drvdata(pdev); @@ -4367,8 +4652,10 @@ static int macb_init(struct platform_device *pdev) } #endif } + if (bp->caps & MACB_CAPS_TAILPTR) queue->TAILADDR = GEM_TAIL(hw_q); + /* get irq: here we use the linux queue index, not the hardware * queue index. the queue irq definitions in the device tree * must remove the optional gaps that could exist in the @@ -4392,12 +4679,14 @@ static int macb_init(struct platform_device *pdev) /* setup appropriated routines according to adapter type */ if (macb_is_gem(bp)) { + bp->max_tx_length = GEM_MAX_TX_LEN; bp->macbgem_ops.mog_alloc_rx_buffers = gem_alloc_rx_buffers; bp->macbgem_ops.mog_free_rx_buffers = gem_free_rx_buffers; bp->macbgem_ops.mog_init_rings = gem_init_rings; bp->macbgem_ops.mog_rx = gem_rx; dev->ethtool_ops = &gem_ethtool_ops; } else { + bp->max_tx_length = MACB_MAX_TX_LEN; bp->macbgem_ops.mog_alloc_rx_buffers = macb_alloc_rx_buffers; bp->macbgem_ops.mog_free_rx_buffers = macb_free_rx_buffers; bp->macbgem_ops.mog_init_rings = macb_init_rings; @@ -4417,12 +4706,6 @@ static int macb_init(struct platform_device *pdev) /* Checksum offload is only available on gem with packet buffer */ if (macb_is_gem(bp) && !(bp->caps & MACB_CAPS_FIFO_MODE)) dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_RXCSUM; - - if (bp->use_ncsi) { - dev->hw_features &= ~(NETIF_F_HW_CSUM | NETIF_F_RXCSUM); - dev->hw_features |= NETIF_F_HW_VLAN_CTAG_FILTER; - } - if (bp->caps & MACB_CAPS_SG_DISABLED) dev->hw_features &= ~NETIF_F_SG; dev->features = dev->hw_features; @@ -5023,57 +5306,6 @@ static int init_reset_optional(struct platform_device *pdev) return ret; } -#define PHYTIUM_PCLK_RATE 250000000 -#define PHYTIUM_HCLK_RATE 48000000 - -static int phytium_clk_init(struct platform_device *pdev, struct clk **pclk, - struct clk **hclk, struct clk **tx_clk, - struct clk **rx_clk, struct clk **tsu_clk) -{ - struct macb_platform_data plat_data; - int err = 0; - - if (has_acpi_companion(&pdev->dev)) { - char clk_name[20]; - /* set up macb platform data */ - memset(&plat_data, 0, sizeof(plat_data)); - - /* initialize clocks */ - snprintf(clk_name, 20, "%s-pclk", pdev->name); - plat_data.pclk = clk_register_fixed_rate(&pdev->dev, clk_name, NULL, 0, - PHYTIUM_PCLK_RATE); - if (IS_ERR(plat_data.pclk)) { - err = PTR_ERR(plat_data.pclk); - goto err_pclk_register; - } - - snprintf(clk_name, 20, "%s-hclk", pdev->name); - plat_data.hclk = clk_register_fixed_rate(&pdev->dev, clk_name, NULL, 0, - PHYTIUM_HCLK_RATE); - if (IS_ERR(plat_data.hclk)) { - err = PTR_ERR(plat_data.hclk); - goto err_hclk_register; - } - - err = platform_device_add_data(pdev, &plat_data, sizeof(plat_data)); - if (err) - goto err_plat_dev_register; - } - - err = macb_clk_init(pdev, pclk, hclk, tx_clk, rx_clk, tsu_clk); - - return 0; - -err_plat_dev_register: - clk_unregister(plat_data.hclk); - -err_hclk_register: - clk_unregister(plat_data.pclk); - -err_pclk_register: - return err; -} - static const struct macb_usrio_config sama7g5_usrio = { .mii = 0, .rmii = 1, @@ -5224,25 +5456,46 @@ static const struct macb_config versal_config = { .usrio = &macb_default_usrio, }; -static const struct macb_config phytium_config = { - .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | - MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH | - MACB_CAPS_SEL_CLK_HW, +static const struct macb_config phytium_gem1p0_config = { + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | + MACB_CAPS_JUMBO | + MACB_CAPS_GEM_HAS_PTP | + MACB_CAPS_BD_RD_PREFETCH | + MACB_CAPS_SEL_CLK, .dma_burst_length = 16, .clk_init = phytium_clk_init, .init = macb_init, .jumbo_max_len = 16360, + .sel_clk_hw = phytium_gem1p0_sel_clk, + .usrio = &macb_default_usrio, +}; + +static const struct macb_config phytium_gem2p0_config = { + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | + MACB_CAPS_JUMBO | + MACB_CAPS_GEM_HAS_PTP | + MACB_CAPS_BD_RD_PREFETCH | + MACB_CAPS_SEL_CLK, + .dma_burst_length = 16, + .clk_init = phytium_clk_init, + .init = macb_init, + .jumbo_max_len = 10240, + .sel_clk_hw = phytium_gem2p0_sel_clk, .usrio = &macb_default_usrio, }; static const struct macb_config phytium_gmac_config = { - .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO | - MACB_CAPS_GEM_HAS_PTP | MACB_CAPS_BD_RD_PREFETCH | - MACB_CAPS_SEL_CLK_HW_2 | MACB_CAPS_TAILPTR, + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | + MACB_CAPS_JUMBO | + MACB_CAPS_GEM_HAS_PTP | + MACB_CAPS_BD_RD_PREFETCH | + MACB_CAPS_SEL_CLK | + MACB_CAPS_TAILPTR, .dma_burst_length = 16, .clk_init = phytium_clk_init, .init = macb_init, .jumbo_max_len = 10240, + .sel_clk_hw = phytium_gmac_sel_clk, .usrio = &macb_default_usrio, }; @@ -5269,7 +5522,9 @@ static const struct of_device_id macb_dt_ids[] = { { .compatible = "xlnx,zynqmp-gem", .data = &zynqmp_config}, { .compatible = "xlnx,zynq-gem", .data = &zynq_config }, { .compatible = "xlnx,versal-gem", .data = &versal_config}, - { .compatible = "cdns,phytium-gem", .data = &phytium_config }, + { .compatible = "cdns,phytium-gem", .data = &phytium_gem1p0_config }, /* old version */ + { .compatible = "cdns,phytium-gem-1.0", .data = &phytium_gem1p0_config }, + { .compatible = "cdns,phytium-gem-2.0", .data = &phytium_gem2p0_config }, { .compatible = "phytium,gmac-1.0", .data = &phytium_gmac_config }, { /* sentinel */ } }; @@ -5278,7 +5533,7 @@ MODULE_DEVICE_TABLE(of, macb_dt_ids); #ifdef CONFIG_ACPI static const struct acpi_device_id macb_acpi_ids[] = { - { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_config }, + { .id = "PHYT0036", .driver_data = (kernel_ulong_t)&phytium_gem1p0_config }, { .id = "PHYT0046", .driver_data = (kernel_ulong_t)&phytium_gmac_config }, { } }; @@ -5299,17 +5554,6 @@ static const struct macb_config default_gem_config = { .jumbo_max_len = 10240, }; -static void macb_destroy_mdio(struct net_device *dev) -{ - struct macb *bp = netdev_priv(dev); - - if (!bp->mii_bus) - return; - - mdiobus_unregister(bp->mii_bus); - mdiobus_free(bp->mii_bus); -} - static void gem_ncsi_handler(struct ncsi_dev *nd) { if (unlikely(nd->state != ncsi_dev_state_functional)) @@ -5319,22 +5563,19 @@ static void gem_ncsi_handler(struct ncsi_dev *nd) nd->link_up ? "up" : "down"); } -static int macb_get_phy_mode(struct platform_device *pdev, phy_interface_t *interface) +static int macb_get_phy_mode(struct platform_device *pdev) { const char *pm; int err, i; err = device_property_read_string(&pdev->dev, "phy-mode", &pm); - if (err < 0) - err = device_property_read_string(&pdev->dev, "phy-connection-type", &pm); if (err < 0) return err; - for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) - if (!strcasecmp(pm, phy_modes(i))) { - *interface = i; - return 0; - } + for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) { + if (!strcasecmp(pm, phy_modes(i))) + return i; + } return -ENODEV; } @@ -5351,7 +5592,6 @@ static int macb_probe(struct platform_device *pdev) struct clk *tsu_clk = NULL; unsigned int queue_mask, num_queues; bool native_io; - phy_interface_t interface; struct net_device *dev; struct resource *regs; u32 wtrmrk_rst_val; @@ -5429,6 +5669,9 @@ static int macb_probe(struct platform_device *pdev) if (macb_config) bp->jumbo_max_len = macb_config->jumbo_max_len; + if (macb_config) + bp->sel_clk_hw = macb_config->sel_clk_hw; + if (!hw_is_gem(bp->regs, bp->native_io)) bp->max_tx_length = MACB_MAX_TX_LEN; else if (macb_config->max_tx_length) @@ -5510,37 +5753,33 @@ static int macb_probe(struct platform_device *pdev) else if (err) macb_get_hwaddr(bp); - err = macb_get_phy_mode(pdev, &interface); - if (err) - /* not found in DT, MII by default */ + err = macb_get_phy_mode(pdev); + if (err < 0) bp->phy_interface = PHY_INTERFACE_MODE_MII; else - bp->phy_interface = interface; + bp->phy_interface = err; + /* IP specific init */ err = init(pdev); if (err) goto err_out_free_netdev; + err = macb_mii_init(bp); + if (err) + goto err_out_phy_exit; + if (device_property_read_bool(&pdev->dev, "use-ncsi")) { if (!IS_ENABLED(CONFIG_NET_NCSI)) { dev_err(&pdev->dev, "NCSI stack not enabled\n"); - err = -EINVAL; goto err_out_free_netdev; } - dev_notice(&pdev->dev, "Using NCSI interface\n"); bp->use_ncsi = 1; bp->ndev = ncsi_register_dev(dev, gem_ncsi_handler); - if (!bp->ndev) { - err = -EINVAL; + if (!bp->ndev) goto err_out_free_netdev; - } } else { - err = macb_mii_init(bp); - if (err) - goto err_out_phy_exit; - bp->use_ncsi = 0; } @@ -5564,9 +5803,8 @@ static int macb_probe(struct platform_device *pdev) return 0; err_out_unregister_mdio: - if (bp->ndev) - ncsi_unregister_dev(bp->ndev); - macb_destroy_mdio(dev); + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); err_out_phy_exit: phy_exit(bp->sgmii_phy); @@ -5593,9 +5831,8 @@ static int macb_remove(struct platform_device *pdev) if (dev) { bp = netdev_priv(dev); phy_exit(bp->sgmii_phy); - macb_destroy_mdio(dev); - if (bp->ndev) - ncsi_unregister_dev(bp->ndev); + mdiobus_unregister(bp->mii_bus); + mdiobus_free(bp->mii_bus); unregister_netdev(dev); tasklet_kill(&bp->hresp_err_tasklet); @@ -5777,6 +6014,8 @@ static int __maybe_unused macb_resume(struct device *dev) macb_set_rx_mode(netdev); macb_restore_features(bp); rtnl_lock(); + if (!device_may_wakeup(&bp->dev->dev)) + phy_init(bp->sgmii_phy); phylink_start(bp->phylink); rtnl_unlock(); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c index a930cea6280b60a5555b44da53604b771c2e12bd..6e8e44730bec60141940f5e0762149c3333ce7d1 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-phytium.c @@ -37,8 +37,7 @@ static int phytium_get_mac_mode(struct fwnode_handle *fwnode) static int phytium_dwmac_acpi_phy(struct plat_stmmacenet_data *plat, struct fwnode_handle *np, struct device *dev) { - plat->mdio_bus_data = - devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); + plat->mdio_bus_data = devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); if (!plat->mdio_bus_data) return -ENOMEM; @@ -60,8 +59,7 @@ static int phytium_dwmac_probe(struct platform_device *pdev) if (!plat) return -ENOMEM; - plat->dma_cfg = - devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); + plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL); if (!plat->dma_cfg) return -ENOMEM; @@ -113,12 +111,10 @@ static int phytium_dwmac_probe(struct platform_device *pdev) &plat->unicast_filter_entries)) plat->unicast_filter_entries = 1; - if (fwnode_property_read_u32(fwnode, "tx-fifo-depth", - &plat->tx_fifo_size)) + if (fwnode_property_read_u32(fwnode, "tx-fifo-depth", &plat->tx_fifo_size)) plat->tx_fifo_size = 0x1000; - if (fwnode_property_read_u32(fwnode, "rx-fifo-depth", - &plat->rx_fifo_size)) + if (fwnode_property_read_u32(fwnode, "rx-fifo-depth", &plat->rx_fifo_size)) plat->rx_fifo_size = 0x1000; if (phytium_dwmac_acpi_phy(plat, fwnode, &pdev->dev)) @@ -133,11 +129,9 @@ static int phytium_dwmac_probe(struct platform_device *pdev) clk_freq = 125000000; /* Set system clock */ - snprintf(clk_name, sizeof(clk_name), "%s-%d", "stmmaceth", - plat->bus_id); + snprintf(clk_name, sizeof(clk_name), "%s-%d", "stmmaceth", plat->bus_id); - plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev, clk_name, NULL, - 0, clk_freq); + plat->stmmac_clk = clk_register_fixed_rate(&pdev->dev, clk_name, NULL, 0, clk_freq); if (IS_ERR(plat->stmmac_clk)) { dev_warn(&pdev->dev, "Fail to register stmmac-clk\n"); plat->stmmac_clk = NULL; @@ -158,13 +152,10 @@ static int phytium_dwmac_probe(struct platform_device *pdev) fwnode_property_read_u32(fwnode, "snps,txpbl", &plat->dma_cfg->txpbl); fwnode_property_read_u32(fwnode, "snps,rxpbl", &plat->dma_cfg->rxpbl); - plat->dma_cfg->pblx8 = - !fwnode_property_read_bool(fwnode, "snps,no-pbl-x8"); + plat->dma_cfg->pblx8 = !fwnode_property_read_bool(fwnode, "snps,no-pbl-x8"); plat->dma_cfg->aal = fwnode_property_read_bool(fwnode, "snps,aal"); - plat->dma_cfg->fixed_burst = - fwnode_property_read_bool(fwnode, "snps,fixed-burst"); - plat->dma_cfg->mixed_burst = - fwnode_property_read_bool(fwnode, "snps,mixed-burst"); + plat->dma_cfg->fixed_burst = fwnode_property_read_bool(fwnode, "snps,fixed-burst"); + plat->dma_cfg->mixed_burst = fwnode_property_read_bool(fwnode, "snps,mixed-burst"); plat->axi->axi_lpi_en = false; plat->axi->axi_xit_frm = false; @@ -182,10 +173,10 @@ static int phytium_dwmac_probe(struct platform_device *pdev) stmmac_res.wol_irq = stmmac_res.irq; stmmac_res.lpi_irq = -1; - return stmmac_dvr_probe(&pdev->dev, plat, &stmmac_res); + return stmmac_dvr_probe(&pdev->dev, plat, &stmmac_res); } -void phytium_dwmac_remove(struct platform_device *pdev) +int phytium_dwmac_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *priv = netdev_priv(ndev); @@ -193,12 +184,14 @@ void phytium_dwmac_remove(struct platform_device *pdev) stmmac_pltfr_remove(pdev); clk_unregister_fixed_rate(plat->stmmac_clk); + + return 0; } #ifdef CONFIG_OF static const struct of_device_id phytium_dwmac_of_match[] = { { .compatible = "phytium,gmac" }, - {} + { } }; MODULE_DEVICE_TABLE(of, phytium_dwmac_of_match); #endif @@ -213,9 +206,10 @@ MODULE_DEVICE_TABLE(acpi, phytium_dwmac_acpi_ids); static struct platform_driver phytium_dwmac_driver = { .probe = phytium_dwmac_probe, - .remove_new = phytium_dwmac_remove, + .remove = phytium_dwmac_remove, .driver = { .name = "phytium-dwmac", + .pm = &stmmac_pltfr_pm_ops, .of_match_table = of_match_ptr(phytium_dwmac_of_match), .acpi_match_table = ACPI_PTR(phytium_dwmac_acpi_ids), }, diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index b5f012619e42da6a05329d3af1a55a56ae01e49b..fead848224bbf5048bff3ca7e3ce59454203a58f 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -3739,6 +3739,11 @@ static int __init phylink_init(void) return 0; } +static void __exit phylink_exit(void) +{ +} + module_init(phylink_init); +module_exit(phylink_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index 298663b03580853ce4d3fc171eadc332944d7cbb..0c1c1ff31085cf44a723ae8ec9de5de1a85d2d31 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -309,6 +309,13 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq; ret = rtw_pwr_seq_parser(rtwdev, pwr_seq); + if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { + if (chip->id == RTW_CHIP_TYPE_8822C || + chip->id == RTW_CHIP_TYPE_8822B || + chip->id == RTW_CHIP_TYPE_8821C) + rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0)); + } + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) rtw_write32(rtwdev, REG_SDIO_HIMR, imr); diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index a99b53d4426763dd719beeef43235fd6dd072184..d8d68f16014e34384ec6b27a630d0aa6451df309 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -280,9 +280,9 @@ static void rtw_ops_configure_filter(struct ieee80211_hw *hw, if (changed_flags & FIF_ALLMULTI) { if (*new_flags & FIF_ALLMULTI) - rtwdev->hal.rcr |= BIT_AM | BIT_AB; + rtwdev->hal.rcr |= BIT_AM; else - rtwdev->hal.rcr &= ~(BIT_AM | BIT_AB); + rtwdev->hal.rcr &= ~(BIT_AM); } if (changed_flags & FIF_FCSFAIL) { if (*new_flags & FIF_FCSFAIL) diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index 4a33d2e47f33ff59751fe4ff95de3e1179dd8300..63673005c2fb19290e7b4e912c5635ef0298ddda 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -2027,8 +2027,6 @@ static int rtw_chip_board_info_setup(struct rtw_dev *rtwdev) rtw_phy_setup_phy_cond(rtwdev, hal->pkg_type); rtw_phy_init_tx_power(rtwdev); - if (rfe_def->agc_btg_tbl) - rtw_load_table(rtwdev, rfe_def->agc_btg_tbl); rtw_load_table(rtwdev, rfe_def->phy_pg_tbl); rtw_load_table(rtwdev, rfe_def->txpwr_lmt_tbl); rtw_phy_tx_power_by_rate_config(hal); diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 128e75a81bf3cc98f12d6af61610fd78b2815a4e..37ef80c9091dba8e28421f427e626c88e47eb47b 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -1761,12 +1761,15 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev) void rtw_phy_load_tables(struct rtw_dev *rtwdev) { + const struct rtw_rfe_def *rfe_def = rtw_get_rfe_def(rtwdev); const struct rtw_chip_info *chip = rtwdev->chip; u8 rf_path; rtw_load_table(rtwdev, chip->mac_tbl); rtw_load_table(rtwdev, chip->bb_tbl); rtw_load_table(rtwdev, chip->agc_tbl); + if (rfe_def->agc_btg_tbl) + rtw_load_table(rtwdev, rfe_def->agc_btg_tbl); rtw_load_rfk_table(rtwdev); for (rf_path = 0; rf_path < rtwdev->hal.rf_path_num; rf_path++) { diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821c.c b/drivers/net/wireless/realtek/rtw88/rtw8821c.c index adf224618a2a6f3cae2d8dffc8bce5c7a98b407d..5f3a3a88c3d0d4c426191a17a1bf5b6269d4e44e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821c.c @@ -706,9 +706,9 @@ static void rtw8821c_false_alarm_statistics(struct rtw_dev *rtwdev) dm_info->cck_fa_cnt = cck_fa_cnt; dm_info->ofdm_fa_cnt = ofdm_fa_cnt; + dm_info->total_fa_cnt = ofdm_fa_cnt; if (cck_enable) dm_info->total_fa_cnt += cck_fa_cnt; - dm_info->total_fa_cnt = ofdm_fa_cnt; crc32_cnt = rtw_read32(rtwdev, REG_CRC_CCK); dm_info->cck_ok_cnt = FIELD_GET(GENMASK(15, 0), crc32_cnt); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c index 7a5cbdc31ef7937f0204f7bf081b6e87577b90de..e2c7d9f876836a32d335d751cb3303ffd5fa204f 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8821cu.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8821cu.c @@ -9,24 +9,36 @@ #include "usb.h" static const struct usb_device_id rtw_8821cu_id_table[] = { - { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8731, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb820, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ - { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xb82b, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc80c, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc820, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc821, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82a, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82b, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8821CU */ - { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc811, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */ - { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8811, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* 8811CU */ - { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x2006, 0xff, 0xff, 0xff), - .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* TOTOLINK A650UA v3 */ + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xc82c, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x331d, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* D-Link */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xc811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ + { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xd811, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&(rtw8821c_hw_spec) }, /* Edimax */ {}, }; MODULE_DEVICE_TABLE(usb, rtw_8821cu_id_table); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 2c1fb2dabd40a40d45311dded79b2f2ed10a54b2..0cae5746f540fa8a4ff68e2e125c3c46d391daf5 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -500,19 +500,40 @@ static u32 rtw_sdio_get_tx_addr(struct rtw_dev *rtwdev, size_t size, static int rtw_sdio_read_port(struct rtw_dev *rtwdev, u8 *buf, size_t count) { struct rtw_sdio *rtwsdio = (struct rtw_sdio *)rtwdev->priv; + struct mmc_host *host = rtwsdio->sdio_func->card->host; bool bus_claim = rtw_sdio_bus_claim_needed(rtwsdio); u32 rxaddr = rtwsdio->rx_addr++; - int ret; + int ret = 0, err; + size_t bytes; if (bus_claim) sdio_claim_host(rtwsdio->sdio_func); - ret = sdio_memcpy_fromio(rtwsdio->sdio_func, buf, - RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), count); - if (ret) - rtw_warn(rtwdev, - "Failed to read %zu byte(s) from SDIO port 0x%08x", - count, rxaddr); + while (count > 0) { + bytes = min_t(size_t, host->max_req_size, count); + + err = sdio_memcpy_fromio(rtwsdio->sdio_func, buf, + RTW_SDIO_ADDR_RX_RX0FF_GEN(rxaddr), + bytes); + if (err) { + rtw_warn(rtwdev, + "Failed to read %zu byte(s) from SDIO port 0x%08x: %d", + bytes, rxaddr, err); + + /* Signal to the caller that reading did not work and + * that the data in the buffer is short/corrupted. + */ + ret = err; + + /* Don't stop here - instead drain the remaining data + * from the card's buffer, else the card will return + * corrupt data for the next rtw_sdio_read_port() call. + */ + } + + count -= bytes; + buf += bytes; + } if (bus_claim) sdio_release_host(rtwsdio->sdio_func); diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index e6ab1ac6d70934d9afb8e9a018054b6c0233239a..a0188511099a1bdfa28bc8882141fb7390f1c851 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -33,6 +33,36 @@ static void rtw_usb_fill_tx_checksum(struct rtw_usb *rtwusb, rtw_tx_fill_txdesc_checksum(rtwdev, &pkt_info, skb->data); } +static void rtw_usb_reg_sec(struct rtw_dev *rtwdev, u32 addr, __le32 *data) +{ + struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); + struct usb_device *udev = rtwusb->udev; + bool reg_on_section = false; + u16 t_reg = 0x4e0; + u8 t_len = 1; + int status; + + /* There are three sections: + * 1. on (0x00~0xFF; 0x1000~0x10FF): this section is always powered on + * 2. off (< 0xFE00, excluding "on" section): this section could be + * powered off + * 3. local (>= 0xFE00): usb specific registers section + */ + if (addr <= 0xff || (addr >= 0x1000 && addr <= 0x10ff)) + reg_on_section = true; + + if (!reg_on_section) + return; + + status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + RTW_USB_CMD_REQ, RTW_USB_CMD_WRITE, + t_reg, 0, data, t_len, 500); + + if (status != t_len && status != -ENODEV) + rtw_err(rtwdev, "%s: reg 0x%x, usb write %u fail, status: %d\n", + __func__, t_reg, t_len, status); +} + static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len) { struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev); @@ -58,6 +88,11 @@ static u32 rtw_usb_read(struct rtw_dev *rtwdev, u32 addr, u16 len) rtw_err(rtwdev, "read register 0x%x failed with %d\n", addr, ret); + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C || + rtwdev->chip->id == RTW_CHIP_TYPE_8822B || + rtwdev->chip->id == RTW_CHIP_TYPE_8821C) + rtw_usb_reg_sec(rtwdev, addr, data); + return le32_to_cpu(*data); } @@ -102,6 +137,11 @@ static void rtw_usb_write(struct rtw_dev *rtwdev, u32 addr, u32 val, int len) if (ret < 0 && ret != -ENODEV && count++ < 4) rtw_err(rtwdev, "write register 0x%x failed with %d\n", addr, ret); + + if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C || + rtwdev->chip->id == RTW_CHIP_TYPE_8822B || + rtwdev->chip->id == RTW_CHIP_TYPE_8821C) + rtw_usb_reg_sec(rtwdev, addr, data); } static void rtw_usb_write8(struct rtw_dev *rtwdev, u32 addr, u8 val) diff --git a/drivers/pwm/pwm-phytium.c b/drivers/pwm/pwm-phytium.c index 9997ce38ffb3a7fc92e73b053e2451772915614b..98ae864a82cd60588c8964e3e27f2a76ad08b1f7 100644 --- a/drivers/pwm/pwm-phytium.c +++ b/drivers/pwm/pwm-phytium.c @@ -98,7 +98,6 @@ struct phytium_pwm_chip { struct phytium_pwm_param parameter[MAX_PARAMETER]; unsigned int num_parameters; - unsigned long clk_rate; struct clk *base_clk; }; @@ -185,7 +184,10 @@ static void pwm_phytium_set_periodns(struct pwm_chip *chip, unsigned int periodn int div = our_chip->state.div; u64 cycles; - cycles = our_chip->clk_rate; + if (has_acpi_companion(chip->dev)) + device_property_read_u64(chip->dev, "clock-frequency", &cycles); + else + cycles = clk_get_rate(our_chip->base_clk); cycles *= (periodns / (div + 1)); do_div(cycles, NSEC_PER_SEC); @@ -203,7 +205,10 @@ static void pwm_phytium_set_duty(struct pwm_chip *chip, unsigned int duty, int n int div = our_chip->state.div; u64 cycles; - cycles = our_chip->clk_rate; + if (has_acpi_companion(chip->dev)) + device_property_read_u64(chip->dev, "clock-frequency", &cycles); + else + cycles = clk_get_rate(our_chip->base_clk); cycles *= (duty / (div + 1)); do_div(cycles, NSEC_PER_SEC); @@ -221,7 +226,10 @@ static int pwm_phytium_set_dbcly(struct pwm_chip *chip, unsigned int updbcly, un u64 dbcly, cycles, upcycles, dwcycles; reg = readl(our_chip->base + REG_TPERIOD); - cycles = our_chip->clk_rate; + if (has_acpi_companion(chip->dev)) + device_property_read_u64(chip->dev, "clock-frequency", &cycles); + else + cycles = clk_get_rate(our_chip->base_clk); dbcly &= 0x0; if (updbcly) { upcycles = cycles * updbcly; @@ -399,21 +407,32 @@ static int phytium_pwm_set_parameter(struct phytium_pwm_chip *priv) } static int pwm_phytium_probe_parameter(struct phytium_pwm_chip *priv, - struct fwnode_handle *np) + struct device_node *np) { int nb, ret, array_size; unsigned int i; - array_size = fwnode_property_read_u32_array(np, "phytium,db", NULL, 0); - nb = array_size / (sizeof(struct phytium_pwm_param) / sizeof(u32)); - if (nb <= 0 || nb > MAX_PARAMETER) - return -EINVAL; + if (has_acpi_companion(priv->chip.dev)) { + priv->num_parameters = 1; + array_size = sizeof(struct phytium_pwm_param) / sizeof(u32); + ret = fwnode_property_read_u32_array(dev_fwnode(priv->chip.dev), + "phytium,db", (u32 *)priv->parameter, + array_size); + if (ret < 0) + return ret; + } else { + nb = of_property_count_elems_of_size(np, "phytium,db", + sizeof(struct phytium_pwm_param)); + if (nb <= 0 || nb > MAX_PARAMETER) + return -EINVAL; - priv->num_parameters = nb; - ret = fwnode_property_read_u32_array(np, "phytium,db", - (u32 *)priv->parameter, array_size); - if (ret) - return ret; + priv->num_parameters = nb; + array_size = nb * sizeof(struct phytium_pwm_param) / sizeof(u32); + ret = of_property_read_u32_array(np, "phytium,db", + (u32 *)priv->parameter, array_size); + if (ret) + return ret; + } for (i = 0; i < priv->num_parameters; i++) { if (priv->parameter[i].cntmod > 1 || @@ -428,7 +447,7 @@ static int pwm_phytium_probe_parameter(struct phytium_pwm_chip *priv, static int pwm_phytium_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct fwnode_handle *np = dev_fwnode(dev); + struct device_node *np = dev->of_node; struct phytium_pwm_chip *chip; struct resource *res; int ret; @@ -444,10 +463,11 @@ static int pwm_phytium_probe(struct platform_device *pdev) chip->chip.npwm = PWM_NUM; chip->inverter_mask = BIT(PWM_NUM) - 1; - if (dev->of_node) { + if (pdev->dev.of_node) { chip->chip.of_xlate = of_pwm_xlate_with_flags; chip->chip.of_pwm_n_cells = 3; } + ret = pwm_phytium_probe_parameter(chip, np); if (ret) { dev_err(dev, "failed to set parameter\n"); @@ -458,27 +478,27 @@ static int pwm_phytium_probe(struct platform_device *pdev) chip->base1 = devm_ioremap_resource(&pdev->dev, res); chip->base = (chip->base1 + 0x400); - if (IS_ERR(chip->base)) { - dev_err(dev, "failed to get base_addr\n"); - return PTR_ERR(chip->base); - } - if (dev->of_node) { - chip->base_clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(chip->base_clk)) { - dev_err(dev, "failed to get clk\n"); - return PTR_ERR(chip->base_clk); - } + if (!has_acpi_companion(&pdev->dev)) { + if (IS_ERR(chip->base)) { + dev_err(dev, "failed to get base_addr\n"); + return PTR_ERR(chip->base); + } - ret = clk_prepare_enable(chip->base_clk); - if (ret < 0) { - dev_err(dev, "failed to enable clk\n"); - return ret; - } - chip->clk_rate = clk_get_rate(chip->base_clk); - } else if (has_acpi_companion(dev)){ - if(fwnode_property_read_u32(dev_fwnode(dev),"clock-frequency", (u32 *)&(chip->clk_rate) ) <0) - chip->clk_rate = 50000000; + if (pdev->dev.of_node) { + chip->base_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(chip->base_clk)) { + dev_err(dev, "failed to get clk\n"); + return PTR_ERR(chip->base_clk); + } + + ret = clk_prepare_enable(chip->base_clk); + if (ret < 0) { + dev_err(dev, "failed to enable clk\n"); + return ret; + } + } } + platform_set_drvdata(pdev, chip); ret = pwmchip_add(&chip->chip); @@ -537,26 +557,28 @@ static int pwm_phytium_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(phytium_pwm_dev_pm_ops, pwm_phytium_suspend, pwm_phytium_resume); -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_pwm_acpi_ids[] = { - { "PHYT0029", 0 }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(acpi, phytium_pwm_acpi_ids); -#endif - static const struct of_device_id phytium_pwm_matches[] = { { .compatible = "phytium,pwm" }, {}, }; MODULE_DEVICE_TABLE(of, phytium_pwm_matches); +#ifdef CONFIG_ACPI +static const struct acpi_device_id phytium_pwm_acpi_matches[] = { + { "PHYT0029", 0 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, phytium_pwm_acpi_matches); +#endif + static struct platform_driver pwm_phytium_driver = { .driver = { .name = "phytium-pwm", .pm = &phytium_pwm_dev_pm_ops, .of_match_table = phytium_pwm_matches, - .acpi_match_table = ACPI_PTR(phytium_pwm_acpi_ids), +#ifdef CONFIG_ACPI + .acpi_match_table = phytium_pwm_acpi_matches, +#endif }, .probe = pwm_phytium_probe, .remove = pwm_phytium_remove, diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3c431de8636571d7dbaed6b36550df19e1a61255..cfaf68b2d39d98a1f006aeaf6b0dc1cf3a05fb56 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -101,10 +101,11 @@ obj-$(CONFIG_SPI_OMAP24XX) += spi-omap2-mcspi.o obj-$(CONFIG_SPI_TI_QSPI) += spi-ti-qspi.o obj-$(CONFIG_SPI_ORION) += spi-orion.o obj-$(CONFIG_SPI_PCI1XXXX) += spi-pci1xxxx.o -obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium.o spi-phytium-dma.o +obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium.o obj-$(CONFIG_SPI_PHYTIUM_PLAT) += spi-phytium-plat.o obj-$(CONFIG_SPI_PHYTIUM_PCI) += spi-phytium-pci.o obj-$(CONFIG_SPI_PHYTIUM_QSPI) += spi-phytium-qspi.o +obj-$(CONFIG_SPI_PHYTIUM) += spi-phytium-dma.o obj-$(CONFIG_SPI_PIC32) += spi-pic32.o obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o obj-$(CONFIG_SPI_PL022) += spi-pl022.o diff --git a/drivers/spi/spi-phytium-dma.c b/drivers/spi/spi-phytium-dma.c index 0a18c8b7140fc385fbaca6086a25e04bb22c441e..25693b633953099d75b3c3a262d7debc237edb07 100644 --- a/drivers/spi/spi-phytium-dma.c +++ b/drivers/spi/spi-phytium-dma.c @@ -46,13 +46,24 @@ static void phytium_spi_dma_maxburst_init(struct phytium_spi *fts) else max_burst = TX_BURST_LEVEL; + /* + * Having a Rx DMA channel serviced with higher priority than a Tx DMA + * channel might not be enough to provide a well balanced DMA-based + * SPI transfer interface. There might still be moments when the Tx DMA + * channel is occasionally handled faster than the Rx DMA channel. + * That in its turn will eventually cause the SPI Rx FIFO overflow if + * SPI bus speed is high enough to fill the SPI Rx FIFO in before it's + * cleared by the Rx DMA channel. In order to fix the problem the Tx + * DMA activity is intentionally slowed down by limiting the SPI Tx + * FIFO depth with a value twice bigger than the Tx burst length. + */ fts->txburst = min(max_burst, def_burst); /* set dmatdlr to 0 + 1 */ phytium_writel(fts, DMATDLR, 0); } static int phytium_spi_dma_init(struct device *dev, - struct phytium_spi *fts) + struct phytium_spi *fts) { fts->rxchan = dma_request_chan(dev, "rx"); if (IS_ERR_OR_NULL(fts->rxchan)) @@ -89,8 +100,8 @@ static void phytium_spi_dma_exit(struct phytium_spi *fts) } } -static irqreturn_t -phytium_spi_dma_transfer_handler(struct phytium_spi *fts) +static irqreturn_t phytium_spi_dma_transfer_handler +(struct phytium_spi *fts) { phytium_spi_check_status(fts, false); @@ -100,7 +111,7 @@ phytium_spi_dma_transfer_handler(struct phytium_spi *fts) } static bool phytium_spi_can_dma(struct spi_controller *master, - struct spi_device *spi, struct spi_transfer *xfer) + struct spi_device *spi, struct spi_transfer *xfer) { struct phytium_spi *fts = spi_controller_get_devdata(master); @@ -118,7 +129,7 @@ static enum dma_slave_buswidth phytium_spi_dma_convert_width(u8 n_bytes) } static int phytium_spi_dma_wait(struct phytium_spi *fts, unsigned int len, - u32 speed) + u32 speed) { unsigned long long ms; @@ -150,7 +161,6 @@ static void spi_transfer_delay_ns(u32 ns) { if (!ns) return; - if (ns <= 1000) { ndelay(ns); } else { @@ -164,7 +174,7 @@ static void spi_transfer_delay_ns(u32 ns) } static int phytium_spi_dma_wait_tx_done(struct phytium_spi *fts, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { int retry = SPI_WAIT_RETRIES; u32 ns = 0; @@ -185,6 +195,11 @@ static int phytium_spi_dma_wait_tx_done(struct phytium_spi *fts, return 0; } +/* + * fts->dma_chan_busy is set before the dma transfer starts, + * callback for tx + * channel will clear a corresponding bit. + */ static void phytium_spi_dma_tx_done(void *arg) { struct phytium_spi *fts = arg; @@ -212,7 +227,7 @@ static int phytium_spi_dma_config_tx(struct phytium_spi *fts) } static int phytium_spi_dma_submit_tx(struct phytium_spi *fts, - struct scatterlist *sgl, unsigned int nents) + struct scatterlist *sgl, unsigned int nents) { struct dma_async_tx_descriptor *txdesc; dma_cookie_t cookie; @@ -250,6 +265,15 @@ static int phytium_spi_dma_wait_rx_done(struct phytium_spi *fts) unsigned long ns = 0; u32 nents = 0; + /* + * It's unlikely that DMA engine is still doing the data fetching, but + * if it's let's give it some reasonable time. The timeout calculation + * is based on the synchronous APB/SSI reference clock rate, on a + * number of data entries left in the Rx FIFO, times a number of clock + * periods normally needed for a single APB read/write transaction + * without PREADY signal utilized (which is true for the phytium APB SSI + * controller). + */ nents = phytium_readl(fts, RXFLR); ns = 4U * NSEC_PER_SEC / fts->max_freq * nents; @@ -264,6 +288,11 @@ static int phytium_spi_dma_wait_rx_done(struct phytium_spi *fts) return 0; } +/* + * fts->dma_chan_busy is set before the dma transfer starts, + * callback for rx + * channel will clear a corresponding bit. + */ static void phytium_spi_dma_rx_done(void *arg) { struct phytium_spi *fts = arg; @@ -291,7 +320,7 @@ static int phytium_spi_dma_config_rx(struct phytium_spi *fts) } static int phytium_spi_dma_submit_rx(struct phytium_spi *fts, - struct scatterlist *sgl, unsigned int nents) + struct scatterlist *sgl, unsigned int nents) { struct dma_async_tx_descriptor *rxdesc; dma_cookie_t cookie; @@ -319,7 +348,7 @@ static int phytium_spi_dma_submit_rx(struct phytium_spi *fts, } static int phytium_spi_dma_setup(struct phytium_spi *fts, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { u16 imr, dma_ctrl; int ret; @@ -359,7 +388,7 @@ static int phytium_spi_dma_setup(struct phytium_spi *fts, } static int phytium_spi_dma_transfer_all(struct phytium_spi *fts, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { int ret; @@ -391,7 +420,7 @@ static int phytium_spi_dma_transfer_all(struct phytium_spi *fts, } static int phytium_spi_dma_transfer_one(struct phytium_spi *fts, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { struct scatterlist *tx_sg = NULL, *rx_sg = NULL, tx_tmp, rx_tmp; unsigned int tx_len = 0, rx_len = 0; @@ -441,6 +470,12 @@ static int phytium_spi_dma_transfer_one(struct phytium_spi *fts, dma_async_issue_pending(fts->txchan); + /* + * Here we only need to wait for the DMA transfer to be + * finished since SPI controller is kept enabled during the + * procedure this loop implements and there is no risk to lose + * data left in the Tx/Rx FIFOs. + */ ret = phytium_spi_dma_wait(fts, len, xfer->speed_hz); if (ret) break; @@ -459,7 +494,7 @@ static int phytium_spi_dma_transfer_one(struct phytium_spi *fts, } static int phytium_spi_dma_transfer(struct phytium_spi *fts, - struct spi_transfer *xfer) + struct spi_transfer *xfer) { unsigned int nents; int ret; diff --git a/drivers/spi/spi-phytium-pci.c b/drivers/spi/spi-phytium-pci.c index 54032b429b955acf994fbddbdc1c3459b28a0ef9..6ef8acfe5c85643c8a0281e63f12985fad049e36 100644 --- a/drivers/spi/spi-phytium-pci.c +++ b/drivers/spi/spi-phytium-pci.c @@ -88,14 +88,16 @@ static void phytium_spi_pci_remove(struct pci_dev *pdev) #ifdef CONFIG_PM_SLEEP static int spi_suspend(struct device *dev) { - struct phytium_spi *fts = dev_get_drvdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct phytium_spi *fts = spi_master_get_devdata(master); return phytium_spi_suspend_host(fts); } static int spi_resume(struct device *dev) { - struct phytium_spi *fts = dev_get_drvdata(dev); + struct spi_master *master = dev_get_drvdata(dev); + struct phytium_spi *fts = spi_master_get_devdata(master); return phytium_spi_resume_host(fts); } diff --git a/drivers/spi/spi-phytium-plat.c b/drivers/spi/spi-phytium-plat.c index 8b8570c7e19a06bb20d57992453cb818470fbce4..9b82c5c016092c4bb80cde8cd15685db91a11c9b 100644 --- a/drivers/spi/spi-phytium-plat.c +++ b/drivers/spi/spi-phytium-plat.c @@ -88,16 +88,16 @@ static int phytium_spi_probe(struct platform_device *pdev) device_property_read_u32(&pdev->dev, "reg-io-width", &fts->reg_io_width); num_cs = 4; - device_property_read_u32(&pdev->dev, "num-cs", &num_cs); - fts->num_cs = num_cs; device_property_read_u32(&pdev->dev, "global-cs", &global_cs); fts->global_cs = global_cs; - if ((device_property_read_string_array(&pdev->dev, "dma-names", NULL, 0) > 0) && - device_property_present(&pdev->dev, "dmas")) { + /* check is use dma transfer */ + if ((device_property_read_string_array(&pdev->dev, "dma-names", + NULL, 0) > 0) && + device_property_present(&pdev->dev, "dmas")) { fts->dma_en = true; phytium_spi_dmaops_set(fts); } diff --git a/drivers/spi/spi-phytium-qspi.c b/drivers/spi/spi-phytium-qspi.c index fef637a140fc222ab577a2429093aee8488f86dd..c68a790ed45336da9078d3549faef419059bcaa4 100644 --- a/drivers/spi/spi-phytium-qspi.c +++ b/drivers/spi/spi-phytium-qspi.c @@ -2,14 +2,13 @@ /* * Phytium Quad SPI controller driver. * - * Copyright (c) 2022-2024 Phytium Technology Co., Ltd. + * Copyright (c) 2022-2023, Phytium Technology Co., Ltd. */ #include #include #include #include -#include #include #include #include @@ -290,8 +289,6 @@ static void phytium_qspi_clear_wr(struct phytium_qspi *qspi, struct phytium_qspi_flash *flash) { u32 cmd = 0; - u32 state = 0; - int ret = 0; cmd |= 0x05 << QSPI_CMD_PORT_CMD_SHIFT; cmd |= BIT(QSPI_CMD_PORT_TRANSFER_SHIFT); @@ -300,13 +297,8 @@ static void phytium_qspi_clear_wr(struct phytium_qspi *qspi, writel_relaxed(cmd, qspi->io_base + QSPI_CMD_PORT_REG); readl_relaxed(qspi->io_base + QSPI_LD_PORT_REG); - ret = readl_poll_timeout(qspi->io_base + QSPI_LD_PORT_REG, - state, !(state & 0x01), 10, 100000); - if (ret) - dev_err(qspi->dev, "wait device timeout\n"); - /* clear wr_cfg */ - writel_relaxed(0x0, qspi->io_base + QSPI_WR_CFG_REG); + writel_relaxed(0, qspi->io_base + QSPI_WR_CFG_REG); } static int phytium_qspi_write_port(struct phytium_qspi *qspi, diff --git a/drivers/spi/spi-phytium.c b/drivers/spi/spi-phytium.c index 78180523c0248bd98155cf96f0a9d24ef1c2b258..131baeacdcd14e079584a881de22ab13cbd3a7af 100644 --- a/drivers/spi/spi-phytium.c +++ b/drivers/spi/spi-phytium.c @@ -119,7 +119,6 @@ static void phytium_reader(struct phytium_spi *fts) fts->rx += fts->n_bytes; } } - int phytium_spi_check_status(struct phytium_spi *fts, bool raw) { u32 irq_status; @@ -151,7 +150,6 @@ int phytium_spi_check_status(struct phytium_spi *fts, bool raw) if (fts->master->cur_msg) fts->master->cur_msg->status = ret; } - return ret; } EXPORT_SYMBOL_GPL(phytium_spi_check_status); @@ -243,7 +241,9 @@ static int phytium_spi_transfer_one(struct spi_master *master, if (transfer->speed_hz != fts->current_freq) { if (transfer->speed_hz != chip->speed_hz) { - clk_div = (fts->max_freq / transfer->speed_hz + 1) & 0xfffe; + clk_div = (fts->max_freq / transfer->speed_hz + 1) & + 0xfffe; + chip->speed_hz = transfer->speed_hz; chip->clk_div = clk_div; } @@ -275,19 +275,21 @@ static int phytium_spi_transfer_one(struct spi_master *master, cr0 |= (chip->tmode << TMOD_OFFSET); } - phytium_writel(fts, CTRL0, cr0); + phytium_writel(fts, CTRLR0, cr0); + /* check if current transfer is a DMA transcation */ if (master->can_dma && master->can_dma(master, spi, transfer)) fts->dma_mapped = master->cur_msg_mapped; spi_mask_intr(fts, 0xff); + /* DMA setup */ if (fts->dma_mapped) { ret = fts->dma_ops->dma_setup(fts, transfer); if (ret) return ret; } - + /* interrupt transfer mode setup */ if (!chip->poll_mode && !fts->dma_mapped) { txlevel = min_t(u16, fts->fifo_len / 2, fts->len / fts->n_bytes); phytium_writel(fts, TXFLTR, txlevel); @@ -354,7 +356,7 @@ static int phytium_spi_setup(struct spi_device *spi) cr0 = (spi->bits_per_word - 1) | (chip->type << FRF_OFFSET) | (spi->mode << MODE_OFFSET) | (chip->tmode << TMOD_OFFSET); - phytium_writel(fts, CTRL0, cr0); + phytium_writel(fts, CTRLR0, cr0); spi_enable_chip(fts, 1); @@ -403,6 +405,8 @@ int phytium_spi_add_host(struct device *dev, struct phytium_spi *fts) fts->dma_addr = (dma_addr_t)(fts->paddr + DR); snprintf(fts->name, sizeof(fts->name), "phytium_spi%d", fts->bus_num); + spi_hw_init(dev, fts); + ret = request_irq(fts->irq, phytium_spi_irq, IRQF_SHARED, fts->name, master); if (ret < 0) { dev_err(dev, "can not get IRQ\n"); @@ -424,8 +428,6 @@ int phytium_spi_add_host(struct device *dev, struct phytium_spi *fts) master->dev.fwnode = dev->fwnode; master->flags = SPI_CONTROLLER_GPIO_SS; - spi_hw_init(dev, fts); - if (fts->dma_ops && fts->dma_ops->dma_init) { ret = fts->dma_ops->dma_init(dev, fts); if (ret) { @@ -460,7 +462,6 @@ void phytium_spi_remove_host(struct phytium_spi *fts) { if (fts->dma_ops && fts->dma_ops->dma_exit) fts->dma_ops->dma_exit(fts); - spi_shutdown_chip(fts); spi_unregister_controller(fts->master); diff --git a/drivers/spi/spi-phytium.h b/drivers/spi/spi-phytium.h index f1f234b5952091addf6660fbfae75f718f4c6c38..781a4fae52dbdb3b58f610df0dab8ed2b6c98a3e 100644 --- a/drivers/spi/spi-phytium.h +++ b/drivers/spi/spi-phytium.h @@ -11,7 +11,7 @@ #include #include -#define CTRL0 0x00 +#define CTRLR0 0x00 #define SSIENR 0x08 #define SER 0x10 #define BAUDR 0x14 @@ -42,7 +42,6 @@ #define INT_TXOI (1 << 1) #define INT_RXUI (1 << 2) #define INT_RXOI (1 << 3) - /* Bit fields in SR, 7 bits */ #define SR_MASK 0x7f /* cover 7 bits */ #define SR_BUSY (1 << 0) @@ -52,15 +51,11 @@ #define SR_RF_FULL (1 << 4) #define SR_TX_ERR (1 << 5) #define SR_DCOL (1 << 6) - /* Bit fields in DMACR */ #define SPI_DMA_RDMAE (1 << 0) #define SPI_DMA_TDMAE (1 << 1) - #define SPI_WAIT_RETRIES 5 - struct phytium_spi; - struct phytium_spi_dma_ops { int (*dma_init)(struct device *dev, struct phytium_spi *fts); void (*dma_exit)(struct phytium_spi *fts); @@ -95,9 +90,8 @@ struct phytium_spi { void *rx_end; u8 n_bytes; int dma_mapped; - struct clk *clk; irqreturn_t (*transfer_handler)(struct phytium_spi *fts); - + /* DMA info */ u32 current_freq; /* frequency in hz */ struct dma_chan *txchan; u32 txburst; @@ -105,7 +99,7 @@ struct phytium_spi { u32 rxburst; u32 dma_sg_burst; unsigned long dma_chan_busy; - dma_addr_t dma_addr; + dma_addr_t dma_addr; /* phy address of the Data register */ const struct phytium_spi_dma_ops *dma_ops; struct completion dma_completion; }; @@ -114,22 +108,18 @@ static inline u32 phytium_readl(struct phytium_spi *fts, u32 offset) { return __raw_readl(fts->regs + offset); } - static inline u16 phytium_readw(struct phytium_spi *fts, u32 offset) { return __raw_readw(fts->regs + offset); } - static inline void phytium_writel(struct phytium_spi *fts, u32 offset, u32 val) { __raw_writel(val, fts->regs + offset); } - static inline void phytium_writew(struct phytium_spi *fts, u32 offset, u16 val) { __raw_writew(val, fts->regs + offset); } - static inline u32 phytium_read_io_reg(struct phytium_spi *fts, u32 offset) { switch (fts->reg_io_width) { @@ -140,8 +130,8 @@ static inline u32 phytium_read_io_reg(struct phytium_spi *fts, u32 offset) return phytium_readl(fts, offset); } } - -static inline void phytium_write_io_reg(struct phytium_spi *fts, u32 offset, u32 val) +static inline void phytium_write_io_reg(struct phytium_spi *fts, + u32 offset, u32 val) { switch (fts->reg_io_width) { case 2: @@ -153,17 +143,14 @@ static inline void phytium_write_io_reg(struct phytium_spi *fts, u32 offset, u32 break; } } - static inline void spi_enable_chip(struct phytium_spi *fts, int enable) { phytium_writel(fts, SSIENR, (enable ? 1 : 0)); } - static inline void spi_set_clk(struct phytium_spi *fts, u16 div) { phytium_writel(fts, BAUDR, div); } - static inline void spi_mask_intr(struct phytium_spi *fts, u32 mask) { u32 new_mask; @@ -171,7 +158,6 @@ static inline void spi_mask_intr(struct phytium_spi *fts, u32 mask) new_mask = phytium_readl(fts, IMR) & ~mask; phytium_writel(fts, IMR, new_mask); } - static inline void spi_umask_intr(struct phytium_spi *fts, u32 mask) { u32 new_mask; @@ -179,17 +165,15 @@ static inline void spi_umask_intr(struct phytium_spi *fts, u32 mask) new_mask = phytium_readl(fts, IMR) | mask; phytium_writel(fts, IMR, new_mask); } - static inline void spi_global_cs(struct phytium_spi *fts) { u32 global_cs_en, mask, setmask; mask = GENMASK(fts->num_cs-1, 0) << fts->num_cs; setmask = ~GENMASK(fts->num_cs-1, 0); - global_cs_en = (phytium_readl(fts, GCSR) | mask) & setmask; + global_cs_en = (phytium_readl(fts, GCSR) | mask) & setmask; phytium_writel(fts, GCSR, global_cs_en); } - static inline void spi_reset_chip(struct phytium_spi *fts) { spi_enable_chip(fts, 0); @@ -198,19 +182,16 @@ static inline void spi_reset_chip(struct phytium_spi *fts) spi_mask_intr(fts, 0xff); spi_enable_chip(fts, 1); } - static inline void spi_shutdown_chip(struct phytium_spi *fts) { spi_enable_chip(fts, 0); spi_set_clk(fts, 0); fts->current_freq = 0; } - extern int phytium_spi_add_host(struct device *dev, struct phytium_spi *fts); extern void phytium_spi_remove_host(struct phytium_spi *fts); extern int phytium_spi_suspend_host(struct phytium_spi *fts); extern int phytium_spi_resume_host(struct phytium_spi *fts); extern void phytium_spi_dmaops_set(struct phytium_spi *fts); extern int phytium_spi_check_status(struct phytium_spi *fts, bool raw); - #endif /* PHYTIUM_SPI_HEADER_H */ diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index d1c1a0de5fb3cc62fcc6e4c1071281bd45459ced..e2b16275df1d9772a4b12ccdfb9f81241afcd0cc 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1428,7 +1428,7 @@ static void optee_smccc_hvc(unsigned long a0, unsigned long a1, #if defined(CONFIG_OPTEE_DEFAULT_METHOD_HVC) #define DEFAULT_CONDUIT_METHOD optee_smccc_hvc #elif defined(CONFIG_OPTEE_DEFAULT_METHOD_SMC) -#define DEFAULT_CONDUIT_METHOD optee_smccc_hvc +#define DEFAULT_CONDUIT_METHOD optee_smccc_smc #else #define DEFAULT_CONDUIT_METHOD ERR_PTR(-ENXIO) #endif diff --git a/drivers/usb/phytium/Kconfig b/drivers/usb/phytium/Kconfig index 7f28d666737259f5568526e9d92032e4d38b7382..797d7b4ee1034da3e3d2a88f631de11cc1a9690e 100644 --- a/drivers/usb/phytium/Kconfig +++ b/drivers/usb/phytium/Kconfig @@ -7,3 +7,14 @@ config USB_PHYTIUM If you choose to build this driver is a dynamically linked modules, the module will be called phytium-usb.ko + +config USB_PHYTIUM_PCI + tristate "PHYTIUM PCI USB Support" + default n + depends on USB + depends on USB_GADGET + help + Say Y or M here if your system has a OTG USB Controller based on PHYTIUM SOC. + + If you choose to build this driver is a dynamically linked modules, the module will + be called phytium-usb-pci.ko diff --git a/drivers/usb/phytium/Makefile b/drivers/usb/phytium/Makefile index 05d422d4a59bc5dddc5f5483e9eeaf792330ede5..e176c334cba560bf54bbbc92a89ea17faeace449 100644 --- a/drivers/usb/phytium/Makefile +++ b/drivers/usb/phytium/Makefile @@ -1,5 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_USB_PHYTIUM) += phytium-usb.o +obj-$(CONFIG_USB_PHYTIUM_PCI) += phytium-usb-pci.o phytium-usb-y := core.o dma.o platform.o host.o gadget.o +phytium-usb-pci-y := core.o dma.o pci.o host.o gadget.o diff --git a/drivers/usb/phytium/host.c b/drivers/usb/phytium/host.c index d58db7afa3936874f2767bcaa260b9bb04b97cf6..8d58eaa99dd56bfa755a1174f435c89ad54a146d 100644 --- a/drivers/usb/phytium/host.c +++ b/drivers/usb/phytium/host.c @@ -23,6 +23,75 @@ #define HOST_EP_NUM 16 +static void dump_ep_remap_pool(struct HOST_CTRL *priv, bool dirIn) +{ + int index, dir = 0; + + if (!dirIn) + dir = 1; + + pr_info("%s dir endpoint remap table\n", dir ? "OUT" : "IN"); + + for (index = 1; index <= MAX_INSTANCE_EP_NUM; index++) + pr_info("ep_remap_pool[%d][%d]->%d\n", dir, index, + priv->ep_remap_pool[dir][index]); +} + +static int get_epnum_from_pool(struct HOST_CTRL *priv, int real_epNum, bool dirIn) +{ + int index, dir = 0; + int ret = 0; + + if (!priv || real_epNum == 0) + return 0; + + if (!dirIn) + dir = 1; + + for (index = 1; index <= MAX_INSTANCE_EP_NUM; index++) { + if (priv->ep_remap_pool[dir][index] == real_epNum) { + ret = index; + goto out; + } + } + + for (index = 1; index <= MAX_INSTANCE_EP_NUM; index++) { + if (!priv->ep_remap_pool[dir][index]) { + priv->ep_remap_pool[dir][index] = real_epNum; + ret = index; + goto out; + } + } + + if (index > MAX_INSTANCE_EP_NUM) + return index; + +out: + return ret; +} + +static int release_epnum_from_pool(struct HOST_CTRL *priv, int real_epNum, bool dirIn) +{ + int index = 0; + int dir = 0; + + if (!priv || real_epNum == 0) + return 0; + + if (!dirIn) + dir = 1; + + for (index = 1; index <= MAX_INSTANCE_EP_NUM; index++) { + if (priv->ep_remap_pool[dir][index] == real_epNum) { + priv->ep_remap_pool[dir][index] = 0; + + return 0; + } + } + + return 0; +} + static inline struct HOST_REQ *getUsbRequestEntry(struct list_head *list) { return (struct HOST_REQ *)((uintptr_t)list - (uintptr_t)&(((struct HOST_REQ *)0)->list)); @@ -220,6 +289,8 @@ static inline void connectHostDetect(struct HOST_CTRL *priv, uint8_t otgState) if (!priv) return; + + memset(priv->ep_remap_pool, 0, sizeof(priv->ep_remap_pool)); pr_debug("otgState:0x%x pirv->otgState:0x%x\n", otgState, priv->otgState); if (priv->custom_regs) { phytium_write32(&priv->custom_regs->wakeup, 0); @@ -571,7 +642,7 @@ static void hostEpProgram(struct HOST_CTRL *priv, struct HostEp *hwEp, phytium_write8(&priv->regs->ep[hwEp->hwEpNum - 1].txcon, regCon); if (usbEpPriv->type != USB_ENDPOINT_XFER_ISOC) { retval = priv->hostCallbacks.getEpToggle(priv, - usbReq->usbDev, usbEpPriv->epNum, 0); + usbReq->usbDev, usbHEp->device_epNum, 0); if (retval) { phytium_write8(&priv->regs->endprst, hwEp->hwEpNum | ENDPRST_IO_TX); @@ -592,7 +663,7 @@ static void hostEpProgram(struct HOST_CTRL *priv, struct HostEp *hwEp, usbEpPriv->maxPacketSize); phytium_write8(&priv->regs->epExt[hwEp->hwEpNum - 1].txctrl, - usbEpPriv->epNum); + usbHEp->device_epNum); phytium_write8(&priv->regs->fnaddr, usbEpPriv->faddress); @@ -629,7 +700,7 @@ static void hostEpProgram(struct HOST_CTRL *priv, struct HostEp *hwEp, if (usbEpPriv->type != USB_ENDPOINT_XFER_ISOC) { if (priv->hostCallbacks.getEpToggle) { retval = priv->hostCallbacks.getEpToggle(priv, - usbReq->usbDev, usbEpPriv->epNum, 1); + usbReq->usbDev, usbHEp->device_epNum, 1); if (retval) { phytium_write8(&priv->regs->endprst, hwEp->hwEpNum); phytium_write8(&priv->regs->endprst, hwEp->hwEpNum | @@ -646,7 +717,7 @@ static void hostEpProgram(struct HOST_CTRL *priv, struct HostEp *hwEp, usbEpPriv->maxPacketSize); phytium_write8(&priv->regs->epExt[hwEp->hwEpNum - 1].rxctrl, - usbEpPriv->epNum); + usbHEp->device_epNum); phytium_write8(&priv->regs->fnaddr, usbEpPriv->faddress); @@ -837,7 +908,7 @@ static void scheduleNextTransfer(struct HOST_CTRL *priv, endprst = (phytium_read8(&priv->regs->endprst) & ENDPRST_TOGSETQ) ? 1 : 0; if (priv->hostCallbacks.setEpToggle) priv->hostCallbacks.setEpToggle(priv, usbReq->usbDev, - usbHEpPriv->epNum, usbHEpPriv->isIn, endprst); + usbEp->device_epNum, usbHEpPriv->isIn, endprst); } else { if (waitForBusyBit(priv, hwEp) > 0) { usbReq->status = HOST_ESHUTDOWN; @@ -849,7 +920,7 @@ static void scheduleNextTransfer(struct HOST_CTRL *priv, endprst = (phytium_read8(&priv->regs->endprst) & ENDPRST_TOGSETQ) ? 1 : 0; if (priv->hostCallbacks.setEpToggle) priv->hostCallbacks.setEpToggle(priv, usbReq->usbDev, - usbHEpPriv->epNum, usbHEpPriv->isIn, endprst); + usbEp->device_epNum, usbHEpPriv->isIn, endprst); } break; } @@ -995,7 +1066,7 @@ static int32_t hostEp0Irq(struct HOST_CTRL *priv, uint8_t isIn) scheduleNextTransfer(priv, usbReq, hwEp); } - return 0; + return ret; } static void updateTimeIntTransfer(struct list_head *head, struct HOST_EP_PRIV *lastFinished) @@ -1169,9 +1240,8 @@ static void host_endpoint_update(struct phytium_cusb *config, if (!config || !udev || !ep) return; - epnum = usb_endpoint_num(&ep->desc); - if (epnum > MAX_INSTANCE_EP_NUM) - epnum = MAX_INSTANCE_EP_NUM; + epnum = get_epnum_from_pool(config->host_priv, usb_endpoint_num(&ep->desc), + usb_endpoint_dir_in(&ep->desc)); if (usb_endpoint_dir_out(&ep->desc)) { if (udev->out_ep[epnum] == NULL) { @@ -1243,9 +1313,13 @@ static int hc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) req->isoFramesDesc = NULL; req->isoFramesNumber = urb->number_of_packets; - req->epNum = usb_endpoint_num(host_ep_desc); - if (req->epNum > MAX_INSTANCE_EP_NUM) + req->epNum = get_epnum_from_pool(config->host_priv, usb_endpoint_num(host_ep_desc), + usb_endpoint_dir_in(host_ep_desc)); + if (req->epNum > MAX_INSTANCE_EP_NUM) { + pr_err("Not enough endpoint resource for remap\n"); + dump_ep_remap_pool(priv, usb_endpoint_dir_in(host_ep_desc)); req->epNum = MAX_INSTANCE_EP_NUM; + } if (usb_endpoint_dir_in(host_ep_desc)) { if (!usbDev->in_ep[req->epNum]) @@ -1280,6 +1354,7 @@ static int hc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) req->status = EINPROGRESS; req->usbDev = &usbDev->udev; req->usbEp = req->epIsIn ? usbDev->in_ep[req->epNum] : usbDev->out_ep[req->epNum]; + req->usbEp->device_epNum = usb_endpoint_num(host_ep_desc); if (!req->epNum) usbDev->ep0_hep.desc.wMaxPacketSize = urb->dev->ep0.desc.wMaxPacketSize; @@ -1321,6 +1396,10 @@ static int hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto err_giveback; ret = config->host_obj->host_reqDequeue(priv, urb->hcpriv, status); + + release_epnum_from_pool(config->host_priv, usb_pipeendpoint(urb->pipe), + usb_pipein(urb->pipe)); + kfree(urb->hcpriv); urb->hcpriv = NULL; done: @@ -1338,10 +1417,18 @@ static int hc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) static void hc_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *ld_ep) { struct HOST_USB_DEVICE *usbDev; - int ep_num = usb_endpoint_num(&ld_ep->desc); + int ep_num; + struct phytium_cusb *config; + struct HOST_CTRL *priv; + + config = *(struct phytium_cusb **)hcd->hcd_priv; + if (!config) + return; + + ep_num = get_epnum_from_pool(config->host_priv, usb_endpoint_num(&ld_ep->desc), + usb_endpoint_dir_in(&ld_ep->desc)); - if (ep_num > MAX_INSTANCE_EP_NUM) - ep_num = MAX_INSTANCE_EP_NUM; + priv = config->host_priv; usbDev = (struct HOST_USB_DEVICE *)ld_ep->hcpriv; if (!usbDev) @@ -1349,18 +1436,20 @@ static void hc_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *l if (ld_ep->desc.bEndpointAddress) { if (usb_endpoint_dir_in(&ld_ep->desc)) { - if (!usbDev->in_ep[ep_num]) { + if (usbDev->in_ep[ep_num]) { usbDev->in_ep[ep_num]->userExt = NULL; INIT_LIST_HEAD(&usbDev->in_ep[ep_num]->reqList); kfree(usbDev->in_ep[ep_num]); usbDev->in_ep[ep_num] = NULL; + priv->ep_remap_pool[0][ep_num] = 0; } } else { - if (!usbDev->out_ep[ep_num]) { + if (usbDev->out_ep[ep_num]) { usbDev->out_ep[ep_num]->userExt = NULL; INIT_LIST_HEAD(&usbDev->out_ep[ep_num]->reqList); kfree(usbDev->out_ep[ep_num]); usbDev->out_ep[ep_num] = NULL; + priv->ep_remap_pool[1][ep_num] = 0; } } } @@ -1699,6 +1788,7 @@ static uint32_t initEndpoints(struct HOST_CTRL *priv) priv->hwEpOutCount = 0; phytium_write8(&priv->regs->ep0fifoctrl, FIFOCTRL_FIFOAUTO | 0); phytium_write8(&priv->regs->ep0fifoctrl, FIFOCTRL_FIFOAUTO | FIFOCTRL_IO_TX | 0); + memset(priv->ep_remap_pool, 0, sizeof(priv->ep_remap_pool)); for (epNum = 0; epNum < HOST_EP_NUM; epNum++) { priv->in[epNum].isInEp = 1; @@ -1949,7 +2039,8 @@ int32_t hostEpDisable(struct HOST_CTRL *priv, struct HOST_EP *ep) return 0; } -unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, int speed) +unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, + int speed) { unsigned int interval = 0; @@ -1961,9 +2052,9 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, int spee interval = fls(desc.bInterval) - 1; interval = clamp_val(interval, 0, 15); interval = 1 << interval; - if (interval != desc.bInterval) + if ((1 << interval) != desc.bInterval) pr_debug("rounding to %d microframes, desc %d microframes\n", - interval, desc.bInterval); + 1 << interval, desc.bInterval); break; } @@ -1971,16 +2062,17 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, int spee interval = clamp_val(desc.bInterval, 1, 16) - 1; interval = 1 << interval; if (interval != desc.bInterval - 1) - pr_debug("rounding to %d %sframes\n", interval, - speed == USB_SPEED_FULL ? "" : "micro"); + pr_debug("rounding to %d %sframes\n", 1 << interval, + speed == USB_SPEED_FULL ? "" : "micro"); } break; case USB_SPEED_FULL: if (usb_endpoint_xfer_isoc(&desc)) { - interval = clamp_val(desc.bInterval, 1, 16); - if (interval != desc.bInterval) + interval = clamp_val(desc.bInterval, 1, 16) - 1; + if (interval != desc.bInterval - 1) pr_debug("rounding to %d %sframes\n", 1 << interval, - speed == USB_SPEED_FULL ? "" : "micro"); + speed == USB_SPEED_FULL ? "" : "micro"); + interval += 3; break; } fallthrough; @@ -1990,7 +2082,7 @@ unsigned int get_endpoint_interval(struct usb_endpoint_descriptor desc, int spee interval = clamp_val(interval, 3, 10); if ((1 << interval) != desc.bInterval * 8) pr_debug("rounding to %d microframes, desc %d microframes\n", - 1 << interval, desc.bInterval); + 1 << interval, desc.bInterval); } } diff --git a/drivers/usb/phytium/host_api.h b/drivers/usb/phytium/host_api.h index 3d45258278c475fdd4ef15810499e41c73d27948..b99d2b4980fbe09ab31f8591b0cd528f6516d6f5 100644 --- a/drivers/usb/phytium/host_api.h +++ b/drivers/usb/phytium/host_api.h @@ -10,6 +10,7 @@ #define MAX_SUPPORTED_DEVICES 16 #define USB_PORT_STAT_RESUME (1 << 31) #define MAX_INSTANCE_EP_NUM 6 +#define ENDPOINT_DIR 2 enum HOST_OtgState { HOST_OTG_STATE_A_IDLE, @@ -63,6 +64,7 @@ struct HOST_EP { struct list_head reqList; void *userExt; uint8_t *hcPriv; + uint8_t device_epNum; }; struct HOST_USB_DEVICE { @@ -241,6 +243,7 @@ struct HOST_CTRL { struct HOST_USB_DEVICE *host_devices_table[MAX_SUPPORTED_DEVICES]; struct CUSTOM_REGS *custom_regs; struct VHUB_REGS *vhub_regs; + int ep_remap_pool[ENDPOINT_DIR][MAX_INSTANCE_EP_NUM + 1]; }; struct HOST_OBJ *HOST_GetInstance(void); diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c index 84dca3695f862dc2a2c26717c8cbb27cad7db80e..c444082e0477860bd5a74bf0d38a8634309d36f7 100644 --- a/drivers/watchdog/dw_wdt.c +++ b/drivers/watchdog/dw_wdt.c @@ -12,6 +12,7 @@ * heartbeat requests after the watchdog device has been closed. */ +#include #include #include #include @@ -83,7 +84,7 @@ struct dw_wdt { void __iomem *regs; struct clk *clk; struct clk *pclk; - unsigned long rate; + u64 rate; enum dw_wdt_rmod rmod; struct dw_wdt_timeout timeouts[DW_WDT_NUM_TOPS]; struct watchdog_device wdd; @@ -560,33 +561,45 @@ static int dw_wdt_drv_probe(struct platform_device *pdev) if (IS_ERR(dw_wdt->regs)) return PTR_ERR(dw_wdt->regs); - /* - * Try to request the watchdog dedicated timer clock source. It must - * be supplied if asynchronous mode is enabled. Otherwise fallback - * to the common timer/bus clocks configuration, in which the very - * first found clock supply both timer and APB signals. - */ - dw_wdt->clk = devm_clk_get_enabled(dev, "tclk"); - if (IS_ERR(dw_wdt->clk)) { - dw_wdt->clk = devm_clk_get_enabled(dev, NULL); - if (IS_ERR(dw_wdt->clk)) - return PTR_ERR(dw_wdt->clk); - } + if (dev->of_node) { + /* + * Try to request the watchdog dedicated timer clock source. It must + * be supplied if asynchronous mode is enabled. Otherwise fallback + * to the common timer/bus clocks configuration, in which the very + * first found clock supply both timer and APB signals. + */ + dw_wdt->clk = devm_clk_get_enabled(dev, "tclk"); + if (IS_ERR(dw_wdt->clk)) { + dw_wdt->clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(dw_wdt->clk)) + return PTR_ERR(dw_wdt->clk); + } - dw_wdt->rate = clk_get_rate(dw_wdt->clk); - if (dw_wdt->rate == 0) - return -EINVAL; + dw_wdt->rate = clk_get_rate(dw_wdt->clk); + if (dw_wdt->rate == 0) + return -EINVAL; - /* - * Request APB clock if device is configured with async clocks mode. - * In this case both tclk and pclk clocks are supposed to be specified. - * Alas we can't know for sure whether async mode was really activated, - * so the pclk phandle reference is left optional. If it couldn't be - * found we consider the device configured in synchronous clocks mode. - */ - dw_wdt->pclk = devm_clk_get_optional_enabled(dev, "pclk"); - if (IS_ERR(dw_wdt->pclk)) - return PTR_ERR(dw_wdt->pclk); + /* + * Request APB clock if device is configured with async clocks mode. + * In this case both tclk and pclk clocks are supposed to be specified. + * Alas we can't know for sure whether async mode was really activated, + * so the pclk phandle reference is left optional. If it couldn't be + * found we consider the device configured in synchronous clocks mode. + */ + dw_wdt->pclk = devm_clk_get_optional_enabled(dev, "pclk"); + if (IS_ERR(dw_wdt->pclk)) + return PTR_ERR(dw_wdt->pclk); + } else if (has_acpi_companion(&pdev->dev)) { + /* + * When Driver probe with ACPI device, clock devices + * are not available, so watchdog rate get from + * clock-frequency property given in _DSD object. + */ + device_property_read_u64(dev, "clock-frequency", + &dw_wdt->rate); + if (dw_wdt->rate == 0) + return -EINVAL; + } dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL); if (IS_ERR(dw_wdt->rst)) @@ -674,6 +687,12 @@ static void dw_wdt_drv_remove(struct platform_device *pdev) reset_control_assert(dw_wdt->rst); } +static const struct acpi_device_id dw_wdt_acpi_match[] = { + { "PHYT0014", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, dw_wdt_acpi_match); + #ifdef CONFIG_OF static const struct of_device_id dw_wdt_of_match[] = { { .compatible = "snps,dw-wdt", }, @@ -688,6 +707,7 @@ static struct platform_driver dw_wdt_driver = { .driver = { .name = "dw_wdt", .of_match_table = of_match_ptr(dw_wdt_of_match), + .acpi_match_table = ACPI_PTR(dw_wdt_acpi_match), .pm = pm_sleep_ptr(&dw_wdt_pm_ops), }, }; diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 74edbce2320bae543c522b97301ec9719725cfa1..6f334bb43fa045f7f35716479e74a7e7b26f3e7c 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -662,6 +662,13 @@ static int lzo_compress_threadfn(void *data) d->ret = lzo1x_1_compress(d->unc, d->unc_len, d->cmp + LZO_HEADER, &d->cmp_len, d->wrk); +#ifdef CONFIG_ARM64 + /* + * Ensure that compressed data is indeed written to memory + * before atomic_set on weakly-ordered architectures. + */ + smp_wmb(); +#endif atomic_set(&d->stop, 1); wake_up(&d->done); } @@ -811,6 +818,10 @@ static int save_image_lzo(struct swap_map_handle *handle, for (run_threads = thr, thr = 0; thr < run_threads; thr++) { wait_event(data[thr].done, atomic_read(&data[thr].stop)); +#ifdef CONFIG_ARM64 + /* Force data access later than written */ + smp_rmb(); +#endif atomic_set(&data[thr].stop, 0); ret = data[thr].ret; diff --git a/sound/pci/hda/hda_phytium.c b/sound/pci/hda/hda_phytium.c index b5ed0650e2dde215121f4d51ad28ef72839ca946..86cd17120b0d529ebb9e30b7873ccc7589248008 100644 --- a/sound/pci/hda/hda_phytium.c +++ b/sound/pci/hda/hda_phytium.c @@ -253,37 +253,6 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev) return 1; /* OK, it's fine */ } -static int hda_ft_dma_configure(struct device *dev) -{ - const struct of_device_id *match_of; - const struct acpi_device_id *match_acpi; - - if (dev->of_node) { - match_of = of_match_device(dev->driver->of_match_table, dev); - if (!match_of) { - dev_err(dev, "Error DT match data is missing\n"); - return -ENODEV; - } - set_dma_ops(dev, NULL); - /* - * Because there is no way to transfer to non-coherent dma in - * of_dma_configure if 'dma-coherent' is described in DT, - * use acpi_dma_configure to alloc dma_ops correctly. - */ - acpi_dma_configure(dev, DEV_DMA_NON_COHERENT); - } else if (has_acpi_companion(dev)) { - match_acpi = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!match_acpi) { - dev_err(dev, "Error ACPI match data is missing\n"); - return -ENODEV; - } - set_dma_ops(dev, NULL); - acpi_dma_configure(dev, DEV_DMA_NON_COHERENT); - } - - return 0; -} - /* The work for pending PCM period updates. */ static void azx_irq_pending_work(struct work_struct *work) { @@ -655,7 +624,7 @@ static int azx_free(struct azx *chip) } if (bus->irq >= 0) { - free_irq(bus->irq, (void*)chip); + free_irq(bus->irq, (void *)chip); bus->irq = -1; } @@ -840,6 +809,7 @@ static int azx_first_init(struct azx *chip) unsigned int dma_bits = 64; struct resource *res; + const struct acpi_device_id *match; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hda->regs = devm_ioremap_resource(hddev, res); @@ -876,9 +846,15 @@ static int azx_first_init(struct azx *chip) chip->align_buffer_size = 1; } - err = hda_ft_dma_configure(hddev); - if (err < 0) - return err; + if (has_acpi_companion(hddev)) { + match = acpi_match_device(hddev->driver->acpi_match_table, hddev); + if (!match) { + dev_err(hddev, "Error ACPI match data is missing\n"); + return -ENODEV; + } + set_dma_ops(hddev, NULL); + acpi_dma_configure(hddev, DEV_DMA_NON_COHERENT); + } /* allow 64bit DMA address if supported by H/W */ if (!(gcap & AZX_GCAP_64OK)) @@ -925,8 +901,8 @@ static int azx_first_init(struct azx *chip) if (azx_acquire_irq(chip, 0) < 0) return -EBUSY; - strcpy(card->driver, "ft-hda"); - strcpy(card->shortname, "ft-hda"); + strscpy(card->driver, "ft-hda", sizeof(card->driver)); + strscpy(card->shortname, "ft-hda", sizeof(card->shortname)); snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", card->shortname, bus->addr, bus->irq); diff --git a/sound/soc/codecs/es8336.c b/sound/soc/codecs/es8336.c index dfdb5bf70253f214fd5a6e7f7296fa330e5f11ea..2d666ab2831c1a9f06251374f04ebbacc202dfd1 100644 --- a/sound/soc/codecs/es8336.c +++ b/sound/soc/codecs/es8336.c @@ -30,6 +30,7 @@ #include #include #include "es8336.h" +#define ES8336_MUTE (1 << 5) static struct snd_soc_component *es8336_component; @@ -71,7 +72,7 @@ struct es8336_priv { struct gpio_desc *hp_det_gpio; bool muted; bool hp_inserted; - + bool spk_active_level; u8 mic_src; int pwr_count; }; @@ -90,7 +91,9 @@ static int es8336_reset(struct snd_soc_component *component) static void es8336_enable_spk(struct es8336_priv *es8336, bool enable) { - gpiod_set_value(es8336->spk_ctl_gpio, enable); + bool level; + level = enable ? es8336->spk_active_level : !es8336->spk_active_level; + gpiod_set_value(es8336->spk_ctl_gpio, level); } static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9600, 50, 1); @@ -666,17 +669,18 @@ static int es8336_mute(struct snd_soc_dai *dai, int mute, int direction) struct es8336_priv *es8336 = snd_soc_component_get_drvdata(component); es8336->muted = mute; - if (mute) { + if (!es8336->hp_inserted) + es8336_enable_spk(es8336, true); + else es8336_enable_spk(es8336, false); - msleep(100); - snd_soc_component_write(component, ES8336_DAC_SET1_REG30, 0x20); - } else if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_PLAYBACK)) { - snd_soc_component_write(component, ES8336_DAC_SET1_REG30, 0x00); - msleep(130); - if (!es8336->hp_inserted) - es8336_enable_spk(es8336, true); - } - return 0; + if (direction) + return snd_soc_component_update_bits(dai->component, ES8336_ADC_MUTE_REG26, + ES8336_MUTE, + mute ? ES8336_MUTE : 0); + else + return snd_soc_component_update_bits(dai->component, ES8336_DAC_SET1_REG30, + ES8336_MUTE, + mute ? ES8336_MUTE : 0); } static int es8336_set_bias_level(struct snd_soc_component *component, @@ -949,6 +953,7 @@ static int es8336_i2c_probe(struct i2c_client *i2c) struct es8336_priv *es8336; int ret = -1; int hp_irq; + int active_level = 0; es8336 = devm_kzalloc(&i2c->dev, sizeof(*es8336), GFP_KERNEL); if (!es8336) @@ -970,6 +975,7 @@ static int es8336_i2c_probe(struct i2c_client *i2c) es8336->spk_ctl_gpio = devm_gpiod_get_index_optional(&i2c->dev, "sel", 0, GPIOD_OUT_HIGH); + device_property_read_u32(&i2c->dev, "spk-active-level", &active_level); ret = of_property_read_u8(i2c->dev.of_node, "mic-src", &es8336->mic_src); if (ret != 0) { dev_dbg(&i2c->dev, "mic1-src return %d", ret); @@ -979,8 +985,10 @@ static int es8336_i2c_probe(struct i2c_client *i2c) if (IS_ERR_OR_NULL(es8336->spk_ctl_gpio)) dev_info(&i2c->dev, "Can not get spk_ctl_gpio\n"); - else + else { + es8336->spk_active_level = active_level; es8336_enable_spk(es8336, false); + } es8336->hp_det_gpio = devm_gpiod_get_index_optional(&i2c->dev, "det", 0, GPIOD_IN); @@ -1005,7 +1013,7 @@ static int es8336_i2c_probe(struct i2c_client *i2c) msecs_to_jiffies(es8336->debounce_time)); } - ret = snd_soc_register_component(&i2c->dev, + ret = devm_snd_soc_register_component(&i2c->dev, &soc_component_dev_es8336, &es8336_dai, 1); @@ -1014,7 +1022,7 @@ static int es8336_i2c_probe(struct i2c_client *i2c) static void es8336_i2c_remove(struct i2c_client *client) { - kfree(i2c_get_clientdata(client)); + } static void es8336_i2c_shutdown(struct i2c_client *client) diff --git a/sound/soc/codecs/es8388.c b/sound/soc/codecs/es8388.c index dd04993abe777f5609c8b943fc8cca64b9c0b8ec..11959e97e61bcf1c1465080c893618c99a6ceb5b 100644 --- a/sound/soc/codecs/es8388.c +++ b/sound/soc/codecs/es8388.c @@ -421,9 +421,14 @@ static const struct snd_soc_dapm_route es8388_dapm_routes[] = { static int es8388_mute(struct snd_soc_dai *dai, int mute, int direction) { - return snd_soc_component_update_bits(dai->component, ES8388_DACCONTROL3, - ES8388_DACCONTROL3_DACMUTE, - mute ? ES8388_DACCONTROL3_DACMUTE : 0); + if (direction) + return snd_soc_component_update_bits(dai->component, ES8388_ADCCONTROL7, + ES8388_ADCCONTROL7_ADC_MUTE, + mute ? ES8388_ADCCONTROL7_ADC_MUTE : 0); + else + return snd_soc_component_update_bits(dai->component, ES8388_DACCONTROL3, + ES8388_DACCONTROL3_DACMUTE, + mute ? ES8388_DACCONTROL3_DACMUTE : 0); } static int es8388_startup(struct snd_pcm_substream *substream, diff --git a/sound/soc/phytium/Kconfig b/sound/soc/phytium/Kconfig index c0621dce1228b2a87f26e56f92d763a76271c917..b4fd9ae0b654bd337194dd15e02663060dfdf6a6 100644 --- a/sound/soc/phytium/Kconfig +++ b/sound/soc/phytium/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 config SND_SOC_PHYTIUM_I2S - bool "Phytium I2S Device Driver" + tristate "Phytium I2S Device Driver" depends on ARCH_PHYTIUM help Say Y or M if you want to add support for I2S driver for diff --git a/sound/soc/phytium/local.h b/sound/soc/phytium/local.h index 3967fe6a97a53587f8f2d675df48bba88aebd6d4..8cc80d1d1040e1f0e5ea6179e63a115c5d048f46 100644 --- a/sound/soc/phytium/local.h +++ b/sound/soc/phytium/local.h @@ -306,7 +306,7 @@ struct i2s_phytium { u32 xfer_resolution; u32 ccr; u32 clk_base; - + u32 cfg; struct i2s_clk_config_data config; /*azx_dev*/ diff --git a/sound/soc/phytium/phytium_i2s.c b/sound/soc/phytium/phytium_i2s.c index bee85fc00749dc072f0c7ba50a1cc96fe4f6505a..9119cdae1c24909a20eade6d96a737c0e0c62598 100644 --- a/sound/soc/phytium/phytium_i2s.c +++ b/sound/soc/phytium/phytium_i2s.c @@ -270,6 +270,7 @@ static int phytium_i2s_hw_params(struct snd_pcm_substream *substream, i2s_write_reg(dev->regs, CLK_CFG0, cfg); i2s_write_reg(dev->regs, CLK_CFG1, 0xf); } + dev->cfg = cfg; return 0; } @@ -367,7 +368,8 @@ static int phytium_i2s_resume(struct snd_soc_component *component) if (snd_soc_dai_stream_active(dai, SNDRV_PCM_STREAM_CAPTURE)) phytium_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE); } - + i2s_write_reg(dev->regs, CLK_CFG0, dev->cfg); + i2s_write_reg(dev->regs, CLK_CFG1, 0xf); return 0; } #else @@ -546,6 +548,25 @@ static int phytium_pcm_hw_params(struct snd_soc_component *component, azx_dev->core.period_bytes = 0; azx_dev->core.format_val = 0; + switch (params_format(hw_params)) { + case SNDRV_PCM_FORMAT_S16_LE: + azx_dev->core.format_val = 2; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + azx_dev->core.format_val = 0; + break; + + case SNDRV_PCM_FORMAT_S32_LE: + azx_dev->core.format_val = 0; + break; + + default: + dev_err(dev->dev, "phytium-i2s: unsupported PCM fmt"); + return -EINVAL; + } + + ret = chip->ops->substream_alloc_pages(chip, substream, params_buffer_bytes(hw_params)); @@ -681,11 +702,9 @@ int snd_i2s_stream_set_params(struct i2s_stream *azx_dev, period_bytes = snd_pcm_lib_period_bytes(substream); if (bufsize != azx_dev->bufsize || period_bytes != azx_dev->period_bytes || - format_val != azx_dev->format_val || runtime->no_period_wakeup != azx_dev->no_period_wakeup) { azx_dev->bufsize = bufsize; azx_dev->period_bytes = period_bytes; - azx_dev->format_val = format_val; azx_dev->no_period_wakeup = runtime->no_period_wakeup; err = snd_i2s_stream_setup_periods(azx_dev); if (err < 0) @@ -704,31 +723,31 @@ int snd_i2s_stream_setup(struct i2s_stream *azx_dev, int pcie, u32 paddr) else runtime = NULL; - i2s_write_reg(azx_dev->sd_addr, DMA_CHAL_CONFG0, 0x8180); + i2s_write_reg(azx_dev->sd_addr, DMA_CHAL_CONFG0, 0x8081); i2s_write_reg(azx_dev->sd_addr, DMA_MASK_INT, 0x80000003); if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) { - i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(0), (u32)azx_dev->bdl.addr); - i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(0), upper_32_bits(azx_dev->bdl.addr)); - if (pcie) - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(0), 0x1c8); - else - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(0), paddr + 0x1c8); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CBL(0), azx_dev->bufsize); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_LVI(0), azx_dev->frags - 1); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DSIZE(0), 0x2);//0x2 - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DLENTH(0), 0x0);//0x0 - } else { i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(1), (u32)azx_dev->bdl.addr); i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(1), upper_32_bits(azx_dev->bdl.addr)); if (pcie) - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(1), 0x1c0); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(1), 0x1c8); else - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(1), paddr + 0x1c0); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(1), paddr + 0x1c8); i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CBL(1), azx_dev->bufsize); i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_LVI(1), azx_dev->frags - 1); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DSIZE(1), 0x8);//0x8 - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DLENTH(1), 0x0); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DSIZE(1), azx_dev->format_val);//0x2 + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DLENTH(1), 0x0);//0x0 + } else { + i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(0), (u32)azx_dev->bdl.addr); + i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(0), upper_32_bits(azx_dev->bdl.addr)); + if (pcie) + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(0), 0x1c0); + else + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DEV_ADDR(0), paddr + 0x1c0); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CBL(0), azx_dev->bufsize); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_LVI(0), azx_dev->frags - 1); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DSIZE(0), azx_dev->format_val << 2);//0x8 + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_DLENTH(0), 0x0); } if (runtime && runtime->period_size > 64) @@ -784,9 +803,9 @@ static int phytium_pcm_prepare(struct snd_soc_component *component, void snd_i2s_stream_clear(struct i2s_stream *azx_dev) { if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0x0); - else i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(1), 0x0); + else + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0x0); azx_dev->running = false; } @@ -799,9 +818,9 @@ void snd_i2s_stream_stop(struct i2s_stream *azx_dev) void snd_i2s_stream_start(struct i2s_stream *azx_dev, bool fresh_start) { if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0x1); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(1), 0x1); else - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(1), 0x5); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0x5); azx_dev->running = true; } @@ -870,19 +889,6 @@ void snd_i2s_stream_cleanup(struct i2s_stream *azx_dev) if (azx_dev->sd_addr) { if (azx_dev->direction == SNDRV_PCM_STREAM_PLAYBACK) { - mask = i2s_read_reg(azx_dev->sd_addr, DMA_MASK_INT); - mask &= ~BIT(0); - i2s_write_reg(azx_dev->sd_addr, DMA_MASK_INT, mask); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0); - while (cnt--) { - if (i2s_read_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0)) == 0) - break; - } - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 2); - i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0); - i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(0), 0); - i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(0), 0); - } else { mask = i2s_read_reg(azx_dev->sd_addr, DMA_MASK_INT); mask &= ~BIT(1); i2s_write_reg(azx_dev->sd_addr, DMA_MASK_INT, mask); @@ -895,6 +901,21 @@ void snd_i2s_stream_cleanup(struct i2s_stream *azx_dev) i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(1), 0); i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(1), 0); i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(1), 0); + i2s_write_reg(azx_dev->sd_addr, DMA_STS, azx_dev->sd_int_sta_mask); + } else { + mask = i2s_read_reg(azx_dev->sd_addr, DMA_MASK_INT); + mask &= ~BIT(0); + i2s_write_reg(azx_dev->sd_addr, DMA_MASK_INT, mask); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0); + while (cnt--) { + if (i2s_read_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0)) == 0) + break; + } + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 2); + i2s_write_reg(azx_dev->sd_addr, DMA_CHALX_CTL(0), 0); + i2s_write_reg(azx_dev->sd_addr, DMA_BDLPL(0), 0); + i2s_write_reg(azx_dev->sd_addr, DMA_BDLPU(0), 0); + i2s_write_reg(azx_dev->sd_addr, DMA_STS, azx_dev->sd_int_sta_mask); } } } @@ -924,9 +945,12 @@ static snd_pcm_uframes_t phytium_pcm_pointer(struct snd_soc_component *component { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct i2s_phytium *dev = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0)); - int stream = substream->stream; + u32 pos = 0; - u32 pos = i2s_read_reg(dev->regs_db, DMA_LPIB(stream)); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + pos = i2s_read_reg(dev->regs_db, DMA_LPIB(1)); + else + pos = i2s_read_reg(dev->regs_db, DMA_LPIB(0)); return bytes_to_frames(substream->runtime, pos); } @@ -1088,9 +1112,9 @@ void snd_i2s_stream_init(struct i2sc_bus *bus, struct i2s_stream *stream, stream->sd_addr = bus->remap_addr; if (idx == 0) - stream->sd_int_sta_mask = 1 << idx; - else stream->sd_int_sta_mask = 1 << 8; + else + stream->sd_int_sta_mask = 1; stream->index = idx; stream->direction = direction; @@ -1376,27 +1400,29 @@ static int phytium_i2s_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_ACPI -static const struct acpi_device_id phytium_i2s_acpi_ids[] = { - { "PHYT0016", 0 }, - { /* sentinel */ }, -}; -MODULE_DEVICE_TABLE(acpi, phytium_i2s_acpi_ids); -#endif - static const struct of_device_id phytium_i2s_of_match[] = { { .compatible = "phytium,i2s", }, {}, }; MODULE_DEVICE_TABLE(of, phytium_i2s_of_match); +#ifdef CONFIG_ACPI +static const struct acpi_device_id phytium_i2s_acpi_match[] = { + { "PHYT0016", 0 }, + { } +}; +MODULE_DEVICE_TABLE(acpi, phytium_i2s_acpi_match); +#else +#define phytium_i2s_acpi_match NULL +#endif + static struct platform_driver phytium_i2s_driver = { .probe = phytium_i2s_probe, .remove = phytium_i2s_remove, .driver = { .name = "phytium-i2s", .of_match_table = of_match_ptr(phytium_i2s_of_match), - .acpi_match_table = ACPI_PTR(phytium_i2s_acpi_ids), + .acpi_match_table = phytium_i2s_acpi_match, }, }; diff --git a/sound/soc/phytium/pmdk_dp.c b/sound/soc/phytium/pmdk_dp.c index aedbf2696e38b2f77d87b2655536703b712921fa..85ff8e5667a8d5b9667687ec4b802dacbec28cd5 100644 --- a/sound/soc/phytium/pmdk_dp.c +++ b/sound/soc/phytium/pmdk_dp.c @@ -31,27 +31,6 @@ static const struct snd_soc_dapm_route pmdk_dp_audio_map[] = { {"DP", NULL, "TX"}, }; -static struct snd_soc_jack_pin dp0_pins[] = { - { - .pin = "HDMI/DP,pcm=0", - .mask = SND_JACK_LINEOUT, - }, -}; - -static struct snd_soc_jack_pin dp1_pins[] = { - { - .pin = "HDMI/DP,pcm=1", - .mask = SND_JACK_LINEOUT, - }, -}; - -static struct snd_soc_jack_pin dp2_pins[] = { - { - .pin = "HDMI/DP,pcm=2", - .mask = SND_JACK_LINEOUT, - }, -}; - #define SMDK_DAI_FMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \ SND_SOC_DAIFMT_CBS_CFS) @@ -62,10 +41,8 @@ static int pmdk_dp0_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; int ret; - ret = snd_soc_card_jack_new_pins(card, "HDMI/DP,pcm=0", - SND_JACK_LINEOUT, - &priv->jack0, dp0_pins, - ARRAY_SIZE(dp0_pins)); + ret = snd_soc_card_jack_new(card, "HDMI/DP,pcm=0", SND_JACK_LINEOUT, + &priv->jack0); if (ret) { dev_err(card->dev, "Jack creation failed %d\n", ret); @@ -83,10 +60,8 @@ static int pmdk_dp1_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; int ret; - ret = snd_soc_card_jack_new_pins(card, "HDMI/DP,pcm=1", - SND_JACK_LINEOUT, - &priv->jack1, dp1_pins, - ARRAY_SIZE(dp1_pins)); + ret = snd_soc_card_jack_new(card, "HDMI/DP,pcm=1", SND_JACK_LINEOUT, + &priv->jack1); if (ret) { dev_err(card->dev, "Jack creation failed %d\n", ret); @@ -103,10 +78,9 @@ static int pmdk_dp2_init(struct snd_soc_pcm_runtime *runtime) struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; int ret; - ret = snd_soc_card_jack_new_pins(card, "HDMI/DP,pcm=2", - SND_JACK_LINEOUT, - &priv->jack2, dp2_pins, - ARRAY_SIZE(dp2_pins)); + ret = snd_soc_card_jack_new(card, "HDMI/DP,pcm=2", SND_JACK_LINEOUT, + &priv->jack2); + if (ret) { dev_err(card->dev, "Jack creation failed %d\n", ret); return ret;