Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BAM DMUX driver as network interface to the modem #103

Merged
merged 7 commits into from Sep 28, 2020
8 changes: 8 additions & 0 deletions arch/arm64/boot/dts/qcom/msm8916-modem.dtsi
Expand Up @@ -7,6 +7,14 @@
status = "okay";
};

&bam_dmux {
status = "okay";
};

&bam_dmux_dma {
status = "okay";
};

&lpass {
status = "disabled";
};
Expand Down
30 changes: 30 additions & 0 deletions arch/arm64/boot/dts/qcom/msm8916.dtsi
Expand Up @@ -225,6 +225,22 @@
};
};

bam_dmux: ethernet-bam-dmux {
compatible = "qcom,bam-dmux";

interrupt-parent = <&hexagon_smsm>;
interrupts = <1 IRQ_TYPE_EDGE_BOTH>, <11 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "pc", "pc-ack";

qcom,smem-states = <&apps_smsm 1>, <&apps_smsm 11>;
qcom,smem-state-names = "pc", "pc-ack";

dmas = <&bam_dmux_dma 4>, <&bam_dmux_dma 5>;
dma-names = "tx", "rx";

status = "disabled";
};

firmware {
scm: scm {
compatible = "qcom,scm-msm8916", "qcom,scm";
Expand Down Expand Up @@ -1281,6 +1297,20 @@
#interrupt-cells = <4>;
};

bam_dmux_dma: dma@4044000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x04044000 0x19000>;
interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <1>;
qcom,ee = <0>;

num-channels = <6>;
qcom,num-ees = <1>;
qcom,remote-power-collapse;

status = "disabled";
};

mpss: remoteproc@4080000 {
compatible = "qcom,msm8916-mss-pil", "qcom,q6v5-pil";
reg = <0x04080000 0x100>,
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/configs/msm8916_defconfig
Expand Up @@ -141,6 +141,7 @@ CONFIG_MACVTAP=m
CONFIG_VXLAN=m
CONFIG_TUN=m
CONFIG_VETH=m
CONFIG_QCOM_BAM_DMUX=m
CONFIG_RMNET=m
CONFIG_WCN36XX=m
CONFIG_INPUT_EVDEV=y
Expand Down
82 changes: 52 additions & 30 deletions drivers/dma/qcom/bam_dma.c
Expand Up @@ -389,6 +389,8 @@ struct bam_device {
/* execution environment ID, from DT */
u32 ee;
bool controlled_remotely;
bool remote_power_collapse;
u32 active_channels;

const struct reg_offset_data *layout;

Expand Down Expand Up @@ -490,6 +492,8 @@ static void bam_chan_init_hw(struct bam_chan *bchan,
bchan->tail = 0;
}

static void bam_reset(struct bam_device *bdev);

/**
* bam_alloc_chan - Allocate channel resources for DMA channel.
* @chan: specified channel
Expand All @@ -513,6 +517,9 @@ static int bam_alloc_chan(struct dma_chan *chan)
return -ENOMEM;
}

if (bdev->active_channels++ == 0 && bdev->remote_power_collapse)
bam_reset(bdev);

return 0;
}

Expand Down Expand Up @@ -566,6 +573,13 @@ static void bam_free_chan(struct dma_chan *chan)
/* disable irq */
writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN));

if (--bdev->active_channels == 0 && bdev->remote_power_collapse) {
/* s/w reset bam */
val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
val |= BAM_SW_RST;
writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
}

err:
pm_runtime_mark_last_busy(bdev->dev);
pm_runtime_put_autosuspend(bdev->dev);
Expand Down Expand Up @@ -1144,34 +1158,10 @@ static struct dma_chan *bam_dma_xlate(struct of_phandle_args *dma_spec,
return dma_get_slave_channel(&(bdev->channels[request].vc.chan));
}

/**
* bam_init
* @bdev: bam device
*
* Initialization helper for global bam registers
*/
static int bam_init(struct bam_device *bdev)
static void bam_reset(struct bam_device *bdev)
{
u32 val;

/* read revision and configuration information */
if (!bdev->num_ees) {
val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION));
bdev->num_ees = (val >> NUM_EES_SHIFT) & NUM_EES_MASK;
}

/* check that configured EE is within range */
if (bdev->ee >= bdev->num_ees)
return -EINVAL;

if (!bdev->num_channels) {
val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
bdev->num_channels = val & BAM_NUM_PIPES_MASK;
}

if (bdev->controlled_remotely)
return 0;

/* s/w reset bam */
/* after reset all pipes are disabled and idle */
val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
Expand Down Expand Up @@ -1200,7 +1190,37 @@ static int bam_init(struct bam_device *bdev)

/* unmask global bam interrupt */
writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
}

/**
* bam_init
* @bdev: bam device
*
* Initialization helper for global bam registers
*/
static int bam_init(struct bam_device *bdev)
{
u32 val;

/* read revision and configuration information */
if (!bdev->num_ees) {
val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION));
bdev->num_ees = (val >> NUM_EES_SHIFT) & NUM_EES_MASK;
}

/* check that configured EE is within range */
if (bdev->ee >= bdev->num_ees)
return -EINVAL;

if (!bdev->num_channels) {
val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
bdev->num_channels = val & BAM_NUM_PIPES_MASK;
}

if (bdev->controlled_remotely || bdev->remote_power_collapse)
return 0;

bam_reset(bdev);
return 0;
}

Expand Down Expand Up @@ -1262,8 +1282,10 @@ static int bam_dma_probe(struct platform_device *pdev)

bdev->controlled_remotely = of_property_read_bool(pdev->dev.of_node,
"qcom,controlled-remotely");
bdev->remote_power_collapse = of_property_read_bool(pdev->dev.of_node,
"qcom,remote-power-collapse");

if (bdev->controlled_remotely) {
if (bdev->controlled_remotely || bdev->remote_power_collapse) {
ret = of_property_read_u32(pdev->dev.of_node, "num-channels",
&bdev->num_channels);
if (ret)
Expand All @@ -1277,7 +1299,7 @@ static int bam_dma_probe(struct platform_device *pdev)

bdev->bamclk = devm_clk_get(bdev->dev, "bam_clk");
if (IS_ERR(bdev->bamclk)) {
if (!bdev->controlled_remotely)
if (!bdev->controlled_remotely && !bdev->remote_power_collapse)
return PTR_ERR(bdev->bamclk);

bdev->bamclk = NULL;
Expand Down Expand Up @@ -1356,7 +1378,7 @@ static int bam_dma_probe(struct platform_device *pdev)
if (ret)
goto err_unregister_dma;

if (bdev->controlled_remotely) {
if (bdev->controlled_remotely || bdev->remote_power_collapse) {
pm_runtime_disable(&pdev->dev);
return 0;
}
Expand Down Expand Up @@ -1444,7 +1466,7 @@ static int __maybe_unused bam_dma_suspend(struct device *dev)
{
struct bam_device *bdev = dev_get_drvdata(dev);

if (!bdev->controlled_remotely)
if (!bdev->controlled_remotely && !bdev->remote_power_collapse)
pm_runtime_force_suspend(dev);

clk_unprepare(bdev->bamclk);
Expand All @@ -1461,7 +1483,7 @@ static int __maybe_unused bam_dma_resume(struct device *dev)
if (ret)
return ret;

if (!bdev->controlled_remotely)
if (!bdev->controlled_remotely && !bdev->remote_power_collapse)
pm_runtime_force_resume(dev);

return 0;
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/qualcomm/Kconfig
Expand Up @@ -47,6 +47,10 @@ config QCA7000_UART
To compile this driver as a module, choose M here. The module
will be called qcauart.

config QCOM_BAM_DMUX
tristate "Qualcomm BAM DMUX Ethernet/IP support"
select QCOM_SMEM_STATE

config QCOM_EMAC
tristate "Qualcomm Technologies, Inc. EMAC Gigabit Ethernet support"
depends on HAS_DMA && HAS_IOMEM
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/qualcomm/Makefile
Expand Up @@ -8,6 +8,7 @@ obj-$(CONFIG_QCA7000_SPI) += qcaspi.o
qcaspi-objs := qca_7k.o qca_debug.o qca_spi.o
obj-$(CONFIG_QCA7000_UART) += qcauart.o
qcauart-objs := qca_uart.o
obj-$(CONFIG_QCOM_BAM_DMUX) += bam-dmux.o

obj-y += emac/

Expand Down